ARTS  2.0.49
interpolation_poly.cc
Go to the documentation of this file.
1 /* Copyright (C) 2008 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 "interpolation_poly.h"
41 #include "interpolation.h"
42 #include "logic.h"
43 #include "arts_omp.h"
44 
46 
63 {
64  return a>b ? a:b;
65 }
66 
68 
85 {
86  return a<b ? a:b;
87 }
88 
89 // File-global constants:
90 
92 
104 
106 
125  ConstVectorView old_grid,
126  ConstVectorView new_grid,
127  const Index order,
128  const Numeric& extpolfac)
129 {
130  // Number of points used in the interpolation (order + 1):
131  Index m=order+1;
132 
133  const Index n_old = old_grid.nelem();
134  const Index n_new = new_grid.nelem();
135 
136  // Since we need m interpolation points, the old grid must have a
137  // least m elements.
138  assert(n_old>=m);
139 
140  // Consistently with gridpos, the array size of gp has to be set
141  // outside. Here, we only assert that it is correct:
142  assert( is_size(gp,n_new) );
143 
144  // First call the traditional gridpos to find the grid positions:
145  ArrayOfGridPos gp_trad(n_new);
146  gridpos( gp_trad, old_grid, new_grid, extpolfac );
147 
148  for (Index s=0; s<n_new; ++s)
149  {
150 
151  // Here we calculate the index of the first of the range of
152  // points used for interpolation. For linear interpolation this
153  // is identical to j. The idea for this expression is from
154  // Numerical Receipes (Chapter 3, section "after the hunt"), but
155  // there is is for 1-based arrays.
156  Index k = IMIN(IMAX(gp_trad[s].idx-(m-1)/2, 0),
157  n_old-m);
158 
159  // cout << "m: "<< m << ", k: " << k << endl;
160 
161 
162  // Make gp[s].idx and gp[s].w the right size:
163  gp[s].idx.resize(m);
164  gp[s].w.resize(m);
165 
166  // Calculate w for each interpolation point. In the linear case
167  // these are just the fractional distances to each interpolation
168  // point. The w here correspond exactly to the terms in front of
169  // the yi in Numerical Recipes, 2nd edition, section 3.1,
170  // eq. 3.1.1.
171  for (Index i=0; i<m; ++i)
172  {
173  gp[s].idx[i] = k+i;
174 
175  // Numerical Recipes, 2nd edition, section 3.1, eq. 3.1.1.
176 
177  // Numerator:
178  Numeric num = 1;
179  for (Index j=0; j<m; ++j)
180  if (j!=i)
181  num *= new_grid[s] - old_grid[k+j];
182 
183  // Denominator:
184  Numeric denom = 1;
185  for (Index j=0; j<m; ++j)
186  if (j!=i)
187  denom *= old_grid[k+i] - old_grid[k+j];
188 
189  gp[s].w[i] = num / denom;
190  }
191 
192  // Debugging: Test if sum of all w is 1, as it should be:
193 // Numeric testsum = 0;
194 // for (Index i=0; i<m; ++i) testsum += gp[s].w[i];
195 // cout << "Testsum = " << testsum << endl;
196 
197  }
198 }
199 
200 
202 
225  ConstVectorView old_grid,
226  const Numeric& new_grid,
227  const Index order,
228  const Numeric& extpolfac )
229 {
230  ArrayOfGridPosPoly agp(1);
231  gridpos_poly( agp, old_grid, new_grid, order, extpolfac );
232  gp = agp[0];
233 }
234 
235 
236 
237 
238 
239 
240 // FIXME: Below here is copied code from interpolation.cc that must be adapted.
241 
243 
257 //#define LOOPW(x) for ( const Numeric* x=&t##x.fd[1]; x>=&t##x.fd[0]; --x )
258 //#define LOOPW(x) for ( Index x=0; x<t##x.w.nelem(); ++x )
259 #define LOOPW(x) for ( ConstIterator1D x=t##x.w.begin(); x!=t##x.w.end(); ++x )
260 
262 
267 #define LOOPIDX(x) for (ArrayOfIndex::const_iterator x=t##x.idx.begin(); x!=t##x.idx.end(); ++x)
268 
269 
271 
279 ostream& operator<<(ostream& os, const GridPosPoly& gp)
280 {
281  os << "idx: " << gp.idx << "\n";
282  os << "w: " << gp.w << "\n";
283 
284 // cout << "Test iterator:\n";
285 // for (ArrayOfIndex::const_iterator x=gp.idx.begin(); x!=gp.idx.end(); ++x)
286 // cout << *x << ":";
287 // cout << "\n";
288 
289  return os;
290 }
291 
292 
293 
294 
295 
296 
298 // Red Interpolation
300 
302 
316  const GridPosPoly& tc )
317 {
318  assert(is_size(itw,tc.w.nelem()));
319 
320  // Interpolation weights are stored in this order (l=lower
321  // u=upper, c=column):
322  // 1. l-c
323  // 2. u-c
324 
325  Index iti = 0;
326 
327  LOOPW(c)
328  {
329  itw[iti] = *c;
330  ++iti;
331  }
332 }
333 
335 
350  const GridPosPoly& tr,
351  const GridPosPoly& tc )
352 {
353  assert(is_size(itw,
354  tr.w.nelem()*
355  tc.w.nelem()));
356  Index iti = 0;
357 
358  LOOPW(r)
359  LOOPW(c)
360  {
361  itw[iti] = (*r) * (*c);
362  ++iti;
363  }
364 }
365 
367 
383  const GridPosPoly& tp,
384  const GridPosPoly& tr,
385  const GridPosPoly& tc )
386 {
387  assert(is_size(itw,
388  tp.w.nelem()*
389  tr.w.nelem()*
390  tc.w.nelem()));
391 
392  Index iti = 0;
393 
394  LOOPW(p)
395  LOOPW(r)
396  LOOPW(c)
397  {
398  itw[iti] = (*p) * (*r) * (*c);
399  ++iti;
400  }
401 }
402 
404 
421  const GridPosPoly& tb,
422  const GridPosPoly& tp,
423  const GridPosPoly& tr,
424  const GridPosPoly& tc )
425 {
426  assert(is_size(itw,
427  tb.w.nelem()*
428  tp.w.nelem()*
429  tr.w.nelem()*
430  tc.w.nelem()));
431 
432  Index iti = 0;
433 
434  LOOPW(b)
435  LOOPW(p)
436  LOOPW(r)
437  LOOPW(c)
438  {
439  itw[iti] = (*b) * (*p) * (*r) * (*c);
440  ++iti;
441  }
442 }
443 
445 
463  const GridPosPoly& ts,
464  const GridPosPoly& tb,
465  const GridPosPoly& tp,
466  const GridPosPoly& tr,
467  const GridPosPoly& tc )
468 {
469  assert(is_size(itw,
470  ts.w.nelem()*
471  tb.w.nelem()*
472  tp.w.nelem()*
473  tr.w.nelem()*
474  tc.w.nelem()));
475 
476  Index iti = 0;
477 
478  LOOPW(s)
479  LOOPW(b)
480  LOOPW(p)
481  LOOPW(r)
482  LOOPW(c)
483  {
484  itw[iti] = (*s) * (*b) * (*p) * (*r) * (*c);
485  ++iti;
486  }
487 }
488 
490 
509  const GridPosPoly& tv,
510  const GridPosPoly& ts,
511  const GridPosPoly& tb,
512  const GridPosPoly& tp,
513  const GridPosPoly& tr,
514  const GridPosPoly& tc )
515 {
516  assert(is_size(itw,
517  tv.w.nelem()*
518  ts.w.nelem()*
519  tb.w.nelem()*
520  tp.w.nelem()*
521  tr.w.nelem()*
522  tc.w.nelem()));
523 
524  Index iti = 0;
525 
526  LOOPW(v)
527  LOOPW(s)
528  LOOPW(b)
529  LOOPW(p)
530  LOOPW(r)
531  LOOPW(c)
532  {
533  itw[iti] = (*v) * (*s) * (*b) * (*p) * (*r) * (*c);
534  ++iti;
535  }
536 }
537 
539 
555  ConstVectorView a,
556  const GridPosPoly& tc )
557 {
558  assert(is_size(itw,tc.w.nelem()));
559 
560  // Check that interpolation weights are valid. The sum of all
561  // weights (last dimension) must always be approximately one.
562  assert( is_same_within_epsilon( itw.sum(),
563  1,
564  sum_check_epsilon ) );
565 
566  // To store interpolated value:
567  Numeric tia = 0;
568 
569  Index iti = 0;
570  LOOPIDX(c)
571  {
572  tia += a[*c] * itw[iti];
573  ++iti;
574  }
575 
576  return tia;
577 }
578 
580 
597  ConstMatrixView a,
598  const GridPosPoly& tr,
599  const GridPosPoly& tc )
600 {
601  assert(is_size(itw,
602  tr.w.nelem()*
603  tc.w.nelem()));
604 
605  // Check that interpolation weights are valid. The sum of all
606  // weights (last dimension) must always be approximately one.
607  assert( is_same_within_epsilon( itw.sum(),
608  1,
609  sum_check_epsilon ) );
610 
611  // To store interpolated value:
612  Numeric tia = 0;
613 
614  Index iti = 0;
615  LOOPIDX(r)
616  LOOPIDX(c)
617  {
618  tia += a(*r,
619  *c) * itw[iti];
620  ++iti;
621  }
622 
623  return tia;
624 }
625 
627 
645  ConstTensor3View a,
646  const GridPosPoly& tp,
647  const GridPosPoly& tr,
648  const GridPosPoly& tc )
649 {
650  assert(is_size(itw,
651  tp.w.nelem()*
652  tr.w.nelem()*
653  tc.w.nelem()));
654 
655  // Check that interpolation weights are valid. The sum of all
656  // weights (last dimension) must always be approximately one.
657  assert( is_same_within_epsilon( itw.sum(),
658  1,
659  sum_check_epsilon ) );
660 
661  // To store interpolated value:
662  Numeric tia = 0;
663 
664  Index iti = 0;
665  LOOPIDX(p)
666  LOOPIDX(r)
667  LOOPIDX(c)
668  {
669  tia += a(*p,
670  *r,
671  *c) * itw[iti];
672  ++iti;
673  }
674 
675  return tia;
676 }
677 
679 
698  ConstTensor4View a,
699  const GridPosPoly& tb,
700  const GridPosPoly& tp,
701  const GridPosPoly& tr,
702  const GridPosPoly& tc )
703 {
704  assert(is_size(itw,
705  tb.w.nelem()*
706  tp.w.nelem()*
707  tr.w.nelem()*
708  tc.w.nelem()));
709 
710  // Check that interpolation weights are valid. The sum of all
711  // weights (last dimension) must always be approximately one.
712  assert( is_same_within_epsilon( itw.sum(),
713  1,
714  sum_check_epsilon ) );
715 
716  // To store interpolated value:
717  Numeric tia = 0;
718 
719  Index iti = 0;
720  LOOPIDX(b)
721  LOOPIDX(p)
722  LOOPIDX(r)
723  LOOPIDX(c)
724  {
725  tia += a(*b,
726  *p,
727  *r,
728  *c) * itw[iti];
729  ++iti;
730  }
731 
732  return tia;
733 }
734 
736 
756  ConstTensor5View a,
757  const GridPosPoly& ts,
758  const GridPosPoly& tb,
759  const GridPosPoly& tp,
760  const GridPosPoly& tr,
761  const GridPosPoly& tc )
762 {
763  assert(is_size(itw,
764  ts.w.nelem()*
765  tb.w.nelem()*
766  tp.w.nelem()*
767  tr.w.nelem()*
768  tc.w.nelem()));
769 
770  // Check that interpolation weights are valid. The sum of all
771  // weights (last dimension) must always be approximately one.
772  assert( is_same_within_epsilon( itw.sum(),
773  1,
774  sum_check_epsilon ) );
775 
776  // To store interpolated value:
777  Numeric tia = 0;
778 
779  Index iti = 0;
780  LOOPIDX(s)
781  LOOPIDX(b)
782  LOOPIDX(p)
783  LOOPIDX(r)
784  LOOPIDX(c)
785  {
786  tia += a(*s,
787  *b,
788  *p,
789  *r,
790  *c) * itw[iti];
791  ++iti;
792  }
793 
794  return tia;
795 }
796 
798 
819  ConstTensor6View a,
820  const GridPosPoly& tv,
821  const GridPosPoly& ts,
822  const GridPosPoly& tb,
823  const GridPosPoly& tp,
824  const GridPosPoly& tr,
825  const GridPosPoly& tc )
826 {
827  assert(is_size(itw,
828  tv.w.nelem()*
829  ts.w.nelem()*
830  tb.w.nelem()*
831  tp.w.nelem()*
832  tr.w.nelem()*
833  tc.w.nelem()));
834 
835  // Check that interpolation weights are valid. The sum of all
836  // weights (last dimension) must always be approximately one.
837  assert( is_same_within_epsilon( itw.sum(),
838  1,
839  sum_check_epsilon ) );
840 
841  // To store interpolated value:
842  Numeric tia = 0;
843 
844  Index iti = 0;
845  LOOPIDX(v)
846  LOOPIDX(s)
847  LOOPIDX(b)
848  LOOPIDX(p)
849  LOOPIDX(r)
850  LOOPIDX(c)
851  {
852  tia += a(*v,
853  *s,
854  *b,
855  *p,
856  *r,
857  *c) * itw[iti];
858  ++iti;
859  }
860 
861  return tia;
862 }
863 
864 
865 
867 // Blue interpolation
869 
871 
887  const ArrayOfGridPosPoly& cgp )
888 {
889  Index n = cgp.nelem();
890  assert(is_size(itw,n,
891  cgp[0].w.nelem()));
892 
893 
894  // We have to loop all the points in the sequence:
895  for ( Index i=0; i<n; ++i )
896  {
897  // Current grid positions:
898  const GridPosPoly& tc = cgp[i];
899 
900  // Interpolation weights are stored in this order (l=lower
901  // u=upper, c=column):
902  // 1. l-c
903  // 2. u-c
904 
905  Index iti = 0;
906 
907  // We could use a straight-forward for loop here:
908  //
909  // for ( Index c=1; c>=0; --c )
910  // {
911  // ti[iti] = tc.fd[c];
912  // ++iti;
913  // }
914  //
915  // However, it is slightly faster to use pointers (I tried it,
916  // the speed gain is about 20%). So we should write something
917  // like:
918  //
919  // for ( const Numeric* c=&tc.fd[1]; c>=&tc.fd[0]; --c )
920  // {
921  // ti[iti] = *c;
922  // ++iti;
923  // }
924  //
925  // For higher dimensions we have to nest these loops. To avoid
926  // typos and safe typing, I use the LOOPW macro, which expands
927  // to the for loop above. Note: NO SEMICOLON AFTER THE LOOPW
928  // COMMAND!
929 
930  LOOPW(c)
931  {
932  itw(i,iti) = *c;
933  ++iti;
934  }
935  }
936 }
937 
939 
961  const ArrayOfGridPosPoly& rgp,
962  const ArrayOfGridPosPoly& cgp )
963 {
964  Index n = cgp.nelem();
965  assert(is_size(rgp,n)); // rgp must have same size as cgp.
966  assert(is_size(itw,n,
967  rgp[0].w.nelem()*
968  cgp[0].w.nelem()));
969 
970 
971  // We have to loop all the points in the sequence:
972  for ( Index i=0; i<n; ++i )
973  {
974  // Current grid positions:
975  const GridPosPoly& tr = rgp[i];
976  const GridPosPoly& tc = cgp[i];
977 
978  // Interpolation weights are stored in this order (l=lower
979  // u=upper, r=row, c=column):
980  // 1. l-r l-c
981  // 2. l-r u-c
982  // 3. u-r l-c
983  // 4. u-r u-c
984 
985  Index iti = 0;
986 
987  LOOPW(r)
988  LOOPW(c)
989  {
990  itw(i,iti) = (*r) * (*c);
991  ++iti;
992  }
993  }
994 }
995 
997 
1020  const ArrayOfGridPosPoly& pgp,
1021  const ArrayOfGridPosPoly& rgp,
1022  const ArrayOfGridPosPoly& cgp )
1023 {
1024  Index n = cgp.nelem();
1025  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1026  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1027  assert(is_size(itw,n,
1028  pgp[0].w.nelem()*
1029  rgp[0].w.nelem()*
1030  cgp[0].w.nelem()));
1031 
1032 
1033  // We have to loop all the points in the sequence:
1034  for ( Index i=0; i<n; ++i )
1035  {
1036  // Current grid positions:
1037  const GridPosPoly& tp = pgp[i];
1038  const GridPosPoly& tr = rgp[i];
1039  const GridPosPoly& tc = cgp[i];
1040 
1041  Index iti = 0;
1042  LOOPW(p)
1043  LOOPW(r)
1044  LOOPW(c)
1045  {
1046  itw(i,iti) = (*p) * (*r) * (*c);
1047  ++iti;
1048  }
1049  }
1050 }
1051 
1053 
1077  const ArrayOfGridPosPoly& bgp,
1078  const ArrayOfGridPosPoly& pgp,
1079  const ArrayOfGridPosPoly& rgp,
1080  const ArrayOfGridPosPoly& cgp )
1081 {
1082  Index n = cgp.nelem();
1083  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1084  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1085  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1086  assert(is_size(itw,n,
1087  bgp[0].w.nelem()*
1088  pgp[0].w.nelem()*
1089  rgp[0].w.nelem()*
1090  cgp[0].w.nelem()));
1091 
1092 
1093  // We have to loop all the points in the sequence:
1094  for ( Index i=0; i<n; ++i )
1095  {
1096  // Current grid positions:
1097  const GridPosPoly& tb = bgp[i];
1098  const GridPosPoly& tp = pgp[i];
1099  const GridPosPoly& tr = rgp[i];
1100  const GridPosPoly& tc = cgp[i];
1101 
1102  Index iti = 0;
1103  LOOPW(b)
1104  LOOPW(p)
1105  LOOPW(r)
1106  LOOPW(c)
1107  {
1108  itw(i,iti) = (*b) * (*p) * (*r) * (*c);
1109  ++iti;
1110  }
1111  }
1112 }
1113 
1115 
1140  const ArrayOfGridPosPoly& sgp,
1141  const ArrayOfGridPosPoly& bgp,
1142  const ArrayOfGridPosPoly& pgp,
1143  const ArrayOfGridPosPoly& rgp,
1144  const ArrayOfGridPosPoly& cgp )
1145 {
1146  Index n = cgp.nelem();
1147  assert(is_size(sgp,n)); // sgp must have same size as cgp.
1148  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1149  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1150  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1151  assert(is_size(itw,n,
1152  sgp[0].w.nelem()*
1153  bgp[0].w.nelem()*
1154  pgp[0].w.nelem()*
1155  rgp[0].w.nelem()*
1156  cgp[0].w.nelem()));
1157 
1158 
1159  // We have to loop all the points in the sequence:
1160  for ( Index i=0; i<n; ++i )
1161  {
1162  // Current grid positions:
1163  const GridPosPoly& ts = sgp[i];
1164  const GridPosPoly& tb = bgp[i];
1165  const GridPosPoly& tp = pgp[i];
1166  const GridPosPoly& tr = rgp[i];
1167  const GridPosPoly& tc = cgp[i];
1168 
1169  Index iti = 0;
1170  LOOPW(s)
1171  LOOPW(b)
1172  LOOPW(p)
1173  LOOPW(r)
1174  LOOPW(c)
1175  {
1176  itw(i,iti) = (*s) * (*b) * (*p) * (*r) * (*c);
1177  ++iti;
1178  }
1179  }
1180 }
1181 
1183 
1209  const ArrayOfGridPosPoly& vgp,
1210  const ArrayOfGridPosPoly& sgp,
1211  const ArrayOfGridPosPoly& bgp,
1212  const ArrayOfGridPosPoly& pgp,
1213  const ArrayOfGridPosPoly& rgp,
1214  const ArrayOfGridPosPoly& cgp )
1215 {
1216  Index n = cgp.nelem();
1217  assert(is_size(vgp,n)); // vgp must have same size as cgp.
1218  assert(is_size(sgp,n)); // sgp must have same size as cgp.
1219  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1220  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1221  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1222  assert(is_size(itw,n,
1223  vgp[0].w.nelem()*
1224  sgp[0].w.nelem()*
1225  bgp[0].w.nelem()*
1226  pgp[0].w.nelem()*
1227  rgp[0].w.nelem()*
1228  cgp[0].w.nelem()));
1229 
1230 
1231  // We have to loop all the points in the sequence:
1232  for ( Index i=0; i<n; ++i )
1233  {
1234  // Current grid positions:
1235  const GridPosPoly& tv = vgp[i];
1236  const GridPosPoly& ts = sgp[i];
1237  const GridPosPoly& tb = bgp[i];
1238  const GridPosPoly& tp = pgp[i];
1239  const GridPosPoly& tr = rgp[i];
1240  const GridPosPoly& tc = cgp[i];
1241 
1242  Index iti = 0;
1243  LOOPW(v)
1244  LOOPW(s)
1245  LOOPW(b)
1246  LOOPW(p)
1247  LOOPW(r)
1248  LOOPW(c)
1249  {
1250  itw(i,iti) = (*v) * (*s) * (*b) * (*p) * (*r) * (*c);
1251  ++iti;
1252  }
1253  }
1254 }
1255 
1257 
1274  ConstMatrixView itw,
1275  ConstVectorView a,
1276  const ArrayOfGridPosPoly& cgp)
1277 {
1278  Index n = cgp.nelem();
1279  assert(is_size(ia,n)); // ia must have same size as cgp.
1280  assert(is_size(itw,n,
1281  cgp[0].w.nelem()));
1282 
1283  // Check that interpolation weights are valid. The sum of all
1284  // weights (last dimension) must always be approximately one. We
1285  // only check the first element.
1286  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1287  1,
1288  sum_check_epsilon ) );
1289 
1290  // We have to loop all the points in the sequence:
1291  for ( Index i=0; i<n; ++i )
1292  {
1293  // Current grid positions:
1294  const GridPosPoly& tc = cgp[i];
1295 
1296  // Get handle to current element of output vector and initialize
1297  // it to zero:
1298  Numeric& tia = ia[i];
1299  tia = 0;
1300 
1301  Index iti = 0;
1302  LOOPIDX(c)
1303  {
1304  tia += a[*c] * itw(i,iti);
1305  ++iti;
1306  }
1307  }
1308 }
1309 
1311 
1333  ConstMatrixView itw,
1334  ConstMatrixView a,
1335  const ArrayOfGridPosPoly& rgp,
1336  const ArrayOfGridPosPoly& cgp)
1337 {
1338  Index n = cgp.nelem();
1339  assert(is_size(ia,n)); // ia must have same size as cgp.
1340  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1341  assert(is_size(itw,n,
1342  rgp[0].w.nelem()*
1343  cgp[0].w.nelem()));
1344 
1345  // Check that interpolation weights are valid. The sum of all
1346  // weights (last dimension) must always be approximately one. We
1347  // only check the first element.
1348  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1349  1,
1350  sum_check_epsilon ) );
1351 
1352  // We have to loop all the points in the sequence:
1353  for ( Index i=0; i<n; ++i )
1354  {
1355  // Current grid positions:
1356  const GridPosPoly& tr = rgp[i];
1357  const GridPosPoly& tc = cgp[i];
1358 
1359  // Get handle to current element of output vector and initialize
1360  // it to zero:
1361  Numeric& tia = ia[i];
1362  tia = 0;
1363 
1364  Index iti = 0;
1365  LOOPIDX(r)
1366  LOOPIDX(c)
1367  {
1368  tia += a(*r,
1369  *c) * itw(i,iti);
1370  ++iti;
1371  }
1372  }
1373 }
1374 
1376 
1399  ConstMatrixView itw,
1400  ConstTensor3View a,
1401  const ArrayOfGridPosPoly& pgp,
1402  const ArrayOfGridPosPoly& rgp,
1403  const ArrayOfGridPosPoly& cgp)
1404 {
1405  Index n = cgp.nelem();
1406  assert(is_size(ia,n)); // ia must have same size as cgp.
1407  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1408  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1409  assert(is_size(itw,n,
1410  pgp[0].w.nelem()*
1411  rgp[0].w.nelem()*
1412  cgp[0].w.nelem()));
1413 
1414  // Check that interpolation weights are valid. The sum of all
1415  // weights (last dimension) must always be approximately one. We
1416  // only check the first element.
1417  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1418  1,
1419  sum_check_epsilon ) );
1420 
1421  // We have to loop all the points in the sequence:
1422  for ( Index i=0; i<n; ++i )
1423  {
1424  // Current grid positions:
1425  const GridPosPoly& tp = pgp[i];
1426  const GridPosPoly& tr = rgp[i];
1427  const GridPosPoly& tc = cgp[i];
1428 
1429  // Get handle to current element of output vector and initialize
1430  // it to zero:
1431  Numeric& tia = ia[i];
1432  tia = 0;
1433 
1434  Index iti = 0;
1435  LOOPIDX(p)
1436  LOOPIDX(r)
1437  LOOPIDX(c)
1438  {
1439  tia += a(*p,
1440  *r,
1441  *c) * itw(i,iti);
1442  ++iti;
1443  }
1444  }
1445 }
1446 
1448 
1472  ConstMatrixView itw,
1473  ConstTensor4View a,
1474  const ArrayOfGridPosPoly& bgp,
1475  const ArrayOfGridPosPoly& pgp,
1476  const ArrayOfGridPosPoly& rgp,
1477  const ArrayOfGridPosPoly& cgp)
1478 {
1479  Index n = cgp.nelem();
1480  assert(is_size(ia,n)); // ia must have same size as cgp.
1481  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1482  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1483  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1484  assert(is_size(itw,n,
1485  bgp[0].w.nelem()*
1486  pgp[0].w.nelem()*
1487  rgp[0].w.nelem()*
1488  cgp[0].w.nelem()));
1489 
1490  // Check that interpolation weights are valid. The sum of all
1491  // weights (last dimension) must always be approximately one. We
1492  // only check the first element.
1493  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1494  1,
1495  sum_check_epsilon ) );
1496 
1497  // We have to loop all the points in the sequence:
1498  for ( Index i=0; i<n; ++i )
1499  {
1500  // Current grid positions:
1501  const GridPosPoly& tb = bgp[i];
1502  const GridPosPoly& tp = pgp[i];
1503  const GridPosPoly& tr = rgp[i];
1504  const GridPosPoly& tc = cgp[i];
1505 
1506  // Get handle to current element of output vector and initialize
1507  // it to zero:
1508  Numeric& tia = ia[i];
1509  tia = 0;
1510 
1511  Index iti = 0;
1512  LOOPIDX(b)
1513  LOOPIDX(p)
1514  LOOPIDX(r)
1515  LOOPIDX(c)
1516  {
1517  tia += a(*b,
1518  *p,
1519  *r,
1520  *c) * itw(i,iti);
1521  ++iti;
1522  }
1523  }
1524 }
1525 
1527 
1552  ConstMatrixView itw,
1553  ConstTensor5View a,
1554  const ArrayOfGridPosPoly& sgp,
1555  const ArrayOfGridPosPoly& bgp,
1556  const ArrayOfGridPosPoly& pgp,
1557  const ArrayOfGridPosPoly& rgp,
1558  const ArrayOfGridPosPoly& cgp)
1559 {
1560  Index n = cgp.nelem();
1561  assert(is_size(ia,n)); // ia must have same size as cgp.
1562  assert(is_size(sgp,n)); // sgp must have same size as cgp.
1563  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1564  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1565  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1566  assert(is_size(itw,n,
1567  sgp[0].w.nelem()*
1568  bgp[0].w.nelem()*
1569  pgp[0].w.nelem()*
1570  rgp[0].w.nelem()*
1571  cgp[0].w.nelem()));
1572 
1573  // Check that interpolation weights are valid. The sum of all
1574  // weights (last dimension) must always be approximately one. We
1575  // only check the first element.
1576  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1577  1,
1578  sum_check_epsilon ) );
1579 
1580  // We have to loop all the points in the sequence:
1581  for ( Index i=0; i<n; ++i )
1582  {
1583  // Current grid positions:
1584  const GridPosPoly& ts = sgp[i];
1585  const GridPosPoly& tb = bgp[i];
1586  const GridPosPoly& tp = pgp[i];
1587  const GridPosPoly& tr = rgp[i];
1588  const GridPosPoly& tc = cgp[i];
1589 
1590  // Get handle to current element of output vector and initialize
1591  // it to zero:
1592  Numeric& tia = ia[i];
1593  tia = 0;
1594 
1595  Index iti = 0;
1596  LOOPIDX(s)
1597  LOOPIDX(b)
1598  LOOPIDX(p)
1599  LOOPIDX(r)
1600  LOOPIDX(c)
1601  {
1602  tia += a(*s,
1603  *b,
1604  *p,
1605  *r,
1606  *c) * itw(i,iti);
1607  ++iti;
1608  }
1609  }
1610 }
1611 
1613 
1639  ConstMatrixView itw,
1640  ConstTensor6View a,
1641  const ArrayOfGridPosPoly& vgp,
1642  const ArrayOfGridPosPoly& sgp,
1643  const ArrayOfGridPosPoly& bgp,
1644  const ArrayOfGridPosPoly& pgp,
1645  const ArrayOfGridPosPoly& rgp,
1646  const ArrayOfGridPosPoly& cgp)
1647 {
1648  Index n = cgp.nelem();
1649  assert(is_size(ia,n)); // ia must have same size as cgp.
1650  assert(is_size(vgp,n)); // vgp must have same size as cgp.
1651  assert(is_size(sgp,n)); // sgp must have same size as cgp.
1652  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1653  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1654  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1655  assert(is_size(itw,n,
1656  vgp[0].w.nelem()*
1657  sgp[0].w.nelem()*
1658  bgp[0].w.nelem()*
1659  pgp[0].w.nelem()*
1660  rgp[0].w.nelem()*
1661  cgp[0].w.nelem()));
1662 
1663  // Check that interpolation weights are valid. The sum of all
1664  // weights (last dimension) must always be approximately one. We
1665  // only check the first element.
1666  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1667  1,
1668  sum_check_epsilon ) );
1669 
1670  // We have to loop all the points in the sequence:
1671  for ( Index i=0; i<n; ++i )
1672  {
1673  // Current grid positions:
1674  const GridPosPoly& tv = vgp[i];
1675  const GridPosPoly& ts = sgp[i];
1676  const GridPosPoly& tb = bgp[i];
1677  const GridPosPoly& tp = pgp[i];
1678  const GridPosPoly& tr = rgp[i];
1679  const GridPosPoly& tc = cgp[i];
1680 
1681  // Get handle to current element of output vector and initialize
1682  // it to zero:
1683  Numeric& tia = ia[i];
1684  tia = 0;
1685 
1686  Index iti = 0;
1687  LOOPIDX(v)
1688  LOOPIDX(s)
1689  LOOPIDX(b)
1690  LOOPIDX(p)
1691  LOOPIDX(r)
1692  LOOPIDX(c)
1693  {
1694  tia += a(*v,
1695  *s,
1696  *b,
1697  *p,
1698  *r,
1699  *c) * itw(i,iti);
1700  ++iti;
1701  }
1702  }
1703 }
1704 
1706 // Green interpolation
1708 
1710 
1732  const ArrayOfGridPosPoly& rgp,
1733  const ArrayOfGridPosPoly& cgp )
1734 {
1735  Index nr = rgp.nelem();
1736  Index nc = cgp.nelem();
1737  assert(is_size(itw,nr,nc,
1738  rgp[0].w.nelem()*
1739  cgp[0].w.nelem()));
1740 
1741 
1742  // We have to loop all the points in the new grid:
1743  for ( Index ir=0; ir<nr; ++ir )
1744  {
1745  // Current grid position:
1746  const GridPosPoly& tr = rgp[ir];
1747 
1748  for ( Index ic=0; ic<nc; ++ic )
1749  {
1750  // Current grid position:
1751  const GridPosPoly& tc = cgp[ic];
1752 
1753  // Interpolation weights are stored in this order (l=lower
1754  // u=upper, r=row, c=column):
1755  // 1. l-r l-c
1756  // 2. l-r u-c
1757  // 3. u-r l-c
1758  // 4. u-r u-c
1759 
1760  Index iti = 0;
1761 
1762  LOOPW(r)
1763  LOOPW(c)
1764  {
1765  itw(ir,ic,iti) = (*r) * (*c);
1766  ++iti;
1767  }
1768  }
1769  }
1770 }
1771 
1773 
1796  const ArrayOfGridPosPoly& pgp,
1797  const ArrayOfGridPosPoly& rgp,
1798  const ArrayOfGridPosPoly& cgp )
1799 {
1800  Index np = pgp.nelem();
1801  Index nr = rgp.nelem();
1802  Index nc = cgp.nelem();
1803 
1804  assert(is_size(itw,np,nr,nc,
1805  pgp[0].w.nelem()*
1806  rgp[0].w.nelem()*
1807  cgp[0].w.nelem()));
1808 
1809  // We have to loop all the points in the new grid:
1810  for ( Index ip=0; ip<np; ++ip )
1811  {
1812  const GridPosPoly& tp = pgp[ip];
1813  for ( Index ir=0; ir<nr; ++ir )
1814  {
1815  const GridPosPoly& tr = rgp[ir];
1816  for ( Index ic=0; ic<nc; ++ic )
1817  {
1818  const GridPosPoly& tc = cgp[ic];
1819 
1820  Index iti = 0;
1821 
1822  LOOPW(p)
1823  LOOPW(r)
1824  LOOPW(c)
1825  {
1826  itw(ip,ir,ic,iti) =
1827  (*p) * (*r) * (*c);
1828  ++iti;
1829  }
1830  }
1831  }
1832  }
1833 }
1834 
1836 
1860  const ArrayOfGridPosPoly& bgp,
1861  const ArrayOfGridPosPoly& pgp,
1862  const ArrayOfGridPosPoly& rgp,
1863  const ArrayOfGridPosPoly& cgp )
1864 {
1865  Index nb = bgp.nelem();
1866  Index np = pgp.nelem();
1867  Index nr = rgp.nelem();
1868  Index nc = cgp.nelem();
1869 
1870  assert(is_size(itw,nb,np,nr,nc,
1871  bgp[0].w.nelem()*
1872  pgp[0].w.nelem()*
1873  rgp[0].w.nelem()*
1874  cgp[0].w.nelem()));
1875 
1876  // We have to loop all the points in the new grid:
1877  for ( Index ib=0; ib<nb; ++ib )
1878  {
1879  const GridPosPoly& tb = bgp[ib];
1880  for ( Index ip=0; ip<np; ++ip )
1881  {
1882  const GridPosPoly& tp = pgp[ip];
1883  for ( Index ir=0; ir<nr; ++ir )
1884  {
1885  const GridPosPoly& tr = rgp[ir];
1886  for ( Index ic=0; ic<nc; ++ic )
1887  {
1888  const GridPosPoly& tc = cgp[ic];
1889 
1890  Index iti = 0;
1891 
1892  LOOPW(b)
1893  LOOPW(p)
1894  LOOPW(r)
1895  LOOPW(c)
1896  {
1897  itw(ib,ip,ir,ic,iti) =
1898  (*b) * (*p) * (*r) * (*c);
1899  ++iti;
1900  }
1901  }
1902  }
1903  }
1904  }
1905 }
1906 
1908 
1933  const ArrayOfGridPosPoly& sgp,
1934  const ArrayOfGridPosPoly& bgp,
1935  const ArrayOfGridPosPoly& pgp,
1936  const ArrayOfGridPosPoly& rgp,
1937  const ArrayOfGridPosPoly& cgp )
1938 {
1939  Index ns = sgp.nelem();
1940  Index nb = bgp.nelem();
1941  Index np = pgp.nelem();
1942  Index nr = rgp.nelem();
1943  Index nc = cgp.nelem();
1944 
1945  assert(is_size(itw,ns,nb,np,nr,nc,
1946  sgp[0].w.nelem()*
1947  bgp[0].w.nelem()*
1948  pgp[0].w.nelem()*
1949  rgp[0].w.nelem()*
1950  cgp[0].w.nelem()));
1951 
1952  // We have to loop all the points in the new grid:
1953  for ( Index is=0; is<ns; ++is )
1954  {
1955  const GridPosPoly& ts = sgp[is];
1956  for ( Index ib=0; ib<nb; ++ib )
1957  {
1958  const GridPosPoly& tb = bgp[ib];
1959  for ( Index ip=0; ip<np; ++ip )
1960  {
1961  const GridPosPoly& tp = pgp[ip];
1962  for ( Index ir=0; ir<nr; ++ir )
1963  {
1964  const GridPosPoly& tr = rgp[ir];
1965  for ( Index ic=0; ic<nc; ++ic )
1966  {
1967  const GridPosPoly& tc = cgp[ic];
1968 
1969  Index iti = 0;
1970 
1971  LOOPW(s)
1972  LOOPW(b)
1973  LOOPW(p)
1974  LOOPW(r)
1975  LOOPW(c)
1976  {
1977  itw(is,ib,ip,ir,ic,iti) =
1978  (*s) * (*b) * (*p) * (*r) * (*c);
1979  ++iti;
1980  }
1981  }
1982  }
1983  }
1984  }
1985  }
1986 }
1987 
1989 
2015  const ArrayOfGridPosPoly& vgp,
2016  const ArrayOfGridPosPoly& sgp,
2017  const ArrayOfGridPosPoly& bgp,
2018  const ArrayOfGridPosPoly& pgp,
2019  const ArrayOfGridPosPoly& rgp,
2020  const ArrayOfGridPosPoly& cgp )
2021 {
2022  Index nv = vgp.nelem();
2023  Index ns = sgp.nelem();
2024  Index nb = bgp.nelem();
2025  Index np = pgp.nelem();
2026  Index nr = rgp.nelem();
2027  Index nc = cgp.nelem();
2028 
2029  assert(is_size(itw,nv,ns,nb,np,nr,nc,
2030  vgp[0].w.nelem()*
2031  sgp[0].w.nelem()*
2032  bgp[0].w.nelem()*
2033  pgp[0].w.nelem()*
2034  rgp[0].w.nelem()*
2035  cgp[0].w.nelem()));
2036 
2037  // We have to loop all the points in the new grid:
2038  for ( Index iv=0; iv<nv; ++iv )
2039  {
2040  const GridPosPoly& tv = vgp[iv];
2041  for ( Index is=0; is<ns; ++is )
2042  {
2043  const GridPosPoly& ts = sgp[is];
2044  for ( Index ib=0; ib<nb; ++ib )
2045  {
2046  const GridPosPoly& tb = bgp[ib];
2047  for ( Index ip=0; ip<np; ++ip )
2048  {
2049  const GridPosPoly& tp = pgp[ip];
2050  for ( Index ir=0; ir<nr; ++ir )
2051  {
2052  const GridPosPoly& tr = rgp[ir];
2053  for ( Index ic=0; ic<nc; ++ic )
2054  {
2055  const GridPosPoly& tc = cgp[ic];
2056 
2057  Index iti = 0;
2058 
2059  LOOPW(v)
2060  LOOPW(s)
2061  LOOPW(b)
2062  LOOPW(p)
2063  LOOPW(r)
2064  LOOPW(c)
2065  {
2066  itw(iv,is,ib,ip,ir,ic,iti) =
2067  (*v) * (*s) * (*b) * (*p) * (*r) * (*c);
2068  ++iti;
2069  }
2070  }
2071  }
2072  }
2073  }
2074  }
2075  }
2076 }
2077 
2079 
2101  ConstTensor3View itw,
2102  ConstMatrixView a,
2103  const ArrayOfGridPosPoly& rgp,
2104  const ArrayOfGridPosPoly& cgp)
2105 {
2106  Index nr = rgp.nelem();
2107  Index nc = cgp.nelem();
2108  assert(is_size(ia,nr,nc));
2109  assert(is_size(itw,nr,nc,
2110  rgp[0].w.nelem()*
2111  cgp[0].w.nelem()));
2112 
2113  // Check that interpolation weights are valid. The sum of all
2114  // weights (last dimension) must always be approximately one. We
2115  // only check the first element.
2116  assert( is_same_within_epsilon( itw(0,0,Range(joker)).sum(),
2117  1,
2118  sum_check_epsilon ) );
2119 
2120  // We have to loop all the points in the new grid:
2121  for ( Index ir=0; ir<nr; ++ir )
2122  {
2123  // Current grid position:
2124  const GridPosPoly& tr = rgp[ir];
2125 
2126  for ( Index ic=0; ic<nc; ++ic )
2127  {
2128  // Current grid position:
2129  const GridPosPoly& tc = cgp[ic];
2130 
2131  // Get handle to current element of output tensor and initialize
2132  // it to zero:
2133  Numeric& tia = ia(ir,ic);
2134  tia = 0;
2135 
2136  Index iti = 0;
2137  LOOPIDX(r)
2138  LOOPIDX(c)
2139  {
2140  tia += a(*r,
2141  *c) * itw(ir,ic,iti);
2142  ++iti;
2143  }
2144  }
2145  }
2146 }
2147 
2149 
2172  ConstTensor4View itw,
2173  ConstTensor3View a,
2174  const ArrayOfGridPosPoly& pgp,
2175  const ArrayOfGridPosPoly& rgp,
2176  const ArrayOfGridPosPoly& cgp)
2177 {
2178  Index np = pgp.nelem();
2179  Index nr = rgp.nelem();
2180  Index nc = cgp.nelem();
2181  assert(is_size(ia,
2182  np,nr,nc));
2183  assert(is_size(itw,
2184  np,nr,nc,
2185  pgp[0].w.nelem()*
2186  rgp[0].w.nelem()*
2187  cgp[0].w.nelem()));
2188 
2189  // Check that interpolation weights are valid. The sum of all
2190  // weights (last dimension) must always be approximately one. We
2191  // only check the first element.
2192  assert( is_same_within_epsilon( itw(0,0,0,Range(joker)).sum(),
2193  1,
2194  sum_check_epsilon ) );
2195 
2196  // We have to loop all the points in the new grid:
2197  for ( Index ip=0; ip<np; ++ip )
2198  {
2199  const GridPosPoly& tp = pgp[ip];
2200  for ( Index ir=0; ir<nr; ++ir )
2201  {
2202  const GridPosPoly& tr = rgp[ir];
2203  for ( Index ic=0; ic<nc; ++ic )
2204  {
2205  // Current grid position:
2206  const GridPosPoly& tc = cgp[ic];
2207 
2208  // Get handle to current element of output tensor and
2209  // initialize it to zero:
2210  Numeric& tia = ia(ip,ir,ic);
2211  tia = 0;
2212 
2213  Index iti = 0;
2214  LOOPIDX(p)
2215  LOOPIDX(r)
2216  LOOPIDX(c)
2217  {
2218  tia += a(*p,
2219  *r,
2220  *c) * itw(ip,ir,ic,
2221  iti);
2222  ++iti;
2223  }
2224  }
2225  }
2226  }
2227 }
2228 
2230 
2254  ConstTensor5View itw,
2255  ConstTensor4View a,
2256  const ArrayOfGridPosPoly& bgp,
2257  const ArrayOfGridPosPoly& pgp,
2258  const ArrayOfGridPosPoly& rgp,
2259  const ArrayOfGridPosPoly& cgp)
2260 {
2261  Index nb = bgp.nelem();
2262  Index np = pgp.nelem();
2263  Index nr = rgp.nelem();
2264  Index nc = cgp.nelem();
2265  assert(is_size(ia,
2266  nb,np,nr,nc));
2267  assert(is_size(itw,
2268  nb,np,nr,nc,
2269  bgp[0].w.nelem()*
2270  pgp[0].w.nelem()*
2271  rgp[0].w.nelem()*
2272  cgp[0].w.nelem()));
2273 
2274  // Check that interpolation weights are valid. The sum of all
2275  // weights (last dimension) must always be approximately one. We
2276  // only check the first element.
2277  assert( is_same_within_epsilon( itw(0,0,0,0,Range(joker)).sum(),
2278  1,
2279  sum_check_epsilon ) );
2280 
2281  // We have to loop all the points in the new grid:
2282  for ( Index ib=0; ib<nb; ++ib )
2283  {
2284  const GridPosPoly& tb = bgp[ib];
2285  for ( Index ip=0; ip<np; ++ip )
2286  {
2287  const GridPosPoly& tp = pgp[ip];
2288  for ( Index ir=0; ir<nr; ++ir )
2289  {
2290  const GridPosPoly& tr = rgp[ir];
2291  for ( Index ic=0; ic<nc; ++ic )
2292  {
2293  // Current grid position:
2294  const GridPosPoly& tc = cgp[ic];
2295 
2296  // Get handle to current element of output tensor and
2297  // initialize it to zero:
2298  Numeric& tia = ia(ib,ip,ir,ic);
2299  tia = 0;
2300 
2301  Index iti = 0;
2302  LOOPIDX(b)
2303  LOOPIDX(p)
2304  LOOPIDX(r)
2305  LOOPIDX(c)
2306  {
2307  tia += a(*b,
2308  *p,
2309  *r,
2310  *c) * itw(ib,ip,ir,ic,
2311  iti);
2312  ++iti;
2313  }
2314  }
2315  }
2316  }
2317  }
2318 }
2319 
2321 
2346  ConstTensor6View itw,
2347  ConstTensor5View a,
2348  const ArrayOfGridPosPoly& sgp,
2349  const ArrayOfGridPosPoly& bgp,
2350  const ArrayOfGridPosPoly& pgp,
2351  const ArrayOfGridPosPoly& rgp,
2352  const ArrayOfGridPosPoly& cgp)
2353 {
2354  Index ns = sgp.nelem();
2355  Index nb = bgp.nelem();
2356  Index np = pgp.nelem();
2357  Index nr = rgp.nelem();
2358  Index nc = cgp.nelem();
2359  assert(is_size(ia,
2360  ns,nb,np,nr,nc));
2361  assert(is_size(itw,
2362  ns,nb,np,nr,nc,
2363  sgp[0].w.nelem()*
2364  bgp[0].w.nelem()*
2365  pgp[0].w.nelem()*
2366  rgp[0].w.nelem()*
2367  cgp[0].w.nelem()));
2368 
2369  // Check that interpolation weights are valid. The sum of all
2370  // weights (last dimension) must always be approximately one. We
2371  // only check the first element.
2372  assert( is_same_within_epsilon( itw(0,0,0,0,0,Range(joker)).sum(),
2373  1,
2374  sum_check_epsilon ) );
2375 
2376  // We have to loop all the points in the new grid:
2377  for ( Index is=0; is<ns; ++is )
2378  {
2379  const GridPosPoly& ts = sgp[is];
2380  for ( Index ib=0; ib<nb; ++ib )
2381  {
2382  const GridPosPoly& tb = bgp[ib];
2383  for ( Index ip=0; ip<np; ++ip )
2384  {
2385  const GridPosPoly& tp = pgp[ip];
2386  for ( Index ir=0; ir<nr; ++ir )
2387  {
2388  const GridPosPoly& tr = rgp[ir];
2389  for ( Index ic=0; ic<nc; ++ic )
2390  {
2391  // Current grid position:
2392  const GridPosPoly& tc = cgp[ic];
2393 
2394  // Get handle to current element of output tensor and
2395  // initialize it to zero:
2396  Numeric& tia = ia(is,ib,ip,ir,ic);
2397  tia = 0;
2398 
2399  Index iti = 0;
2400  LOOPIDX(s)
2401  LOOPIDX(b)
2402  LOOPIDX(p)
2403  LOOPIDX(r)
2404  LOOPIDX(c)
2405  {
2406  tia += a(*s,
2407  *b,
2408  *p,
2409  *r,
2410  *c) * itw(is,ib,ip,ir,ic,
2411  iti);
2412  ++iti;
2413  }
2414  }
2415  }
2416  }
2417  }
2418  }
2419 }
2420 
2422 
2448  ConstTensor7View itw,
2449  ConstTensor6View a,
2450  const ArrayOfGridPosPoly& vgp,
2451  const ArrayOfGridPosPoly& sgp,
2452  const ArrayOfGridPosPoly& bgp,
2453  const ArrayOfGridPosPoly& pgp,
2454  const ArrayOfGridPosPoly& rgp,
2455  const ArrayOfGridPosPoly& cgp)
2456 {
2457  Index nv = vgp.nelem();
2458  Index ns = sgp.nelem();
2459  Index nb = bgp.nelem();
2460  Index np = pgp.nelem();
2461  Index nr = rgp.nelem();
2462  Index nc = cgp.nelem();
2463  assert(is_size(ia,
2464  nv,ns,nb,np,nr,nc));
2465  assert(is_size(itw,
2466  nv,ns,nb,np,nr,nc,
2467  vgp[0].w.nelem()*
2468  sgp[0].w.nelem()*
2469  bgp[0].w.nelem()*
2470  pgp[0].w.nelem()*
2471  rgp[0].w.nelem()*
2472  cgp[0].w.nelem()));
2473 
2474  // Check that interpolation weights are valid. The sum of all
2475  // weights (last dimension) must always be approximately one. We
2476  // only check the first element.
2477  assert( is_same_within_epsilon( itw(0,0,0,0,0,0,Range(joker)).sum(),
2478  1,
2479  sum_check_epsilon ) );
2480 
2481  // We have to loop all the points in the new grid:
2482  for ( Index iv=0; iv<nv; ++iv )
2483  {
2484  const GridPosPoly& tv = vgp[iv];
2485  for ( Index is=0; is<ns; ++is )
2486  {
2487  const GridPosPoly& ts = sgp[is];
2488  for ( Index ib=0; ib<nb; ++ib )
2489  {
2490  const GridPosPoly& tb = bgp[ib];
2491  for ( Index ip=0; ip<np; ++ip )
2492  {
2493  const GridPosPoly& tp = pgp[ip];
2494  for ( Index ir=0; ir<nr; ++ir )
2495  {
2496  const GridPosPoly& tr = rgp[ir];
2497  for ( Index ic=0; ic<nc; ++ic )
2498  {
2499  // Current grid position:
2500  const GridPosPoly& tc = cgp[ic];
2501 
2502  // Get handle to current element of output tensor and
2503  // initialize it to zero:
2504  Numeric& tia = ia(iv,is,ib,ip,ir,ic);
2505  tia = 0;
2506 
2507  Index iti = 0;
2508  LOOPIDX(v)
2509  LOOPIDX(s)
2510  LOOPIDX(b)
2511  LOOPIDX(p)
2512  LOOPIDX(r)
2513  LOOPIDX(c)
2514  {
2515  tia += a(*v,
2516  *s,
2517  *b,
2518  *p,
2519  *r,
2520  *c) * itw(iv,is,ib,ip,ir,ic,
2521  iti);
2522  ++iti;
2523  }
2524  }
2525  }
2526  }
2527  }
2528  }
2529  }
2530 }
2531 
2532 
Tensor7View
The Tensor7View class.
Definition: matpackVII.h:779
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:421
sum_check_epsilon
const Numeric sum_check_epsilon
The maximum difference from 1 that we allow for a sum check.
Definition: interpolation_poly.cc:103
IMIN
Index IMIN(Index a, Index b)
Return the minimum of two integer numbers.
Definition: interpolation_poly.cc:84
MatrixView
The MatrixView class.
Definition: matpackI.h:668
operator<<
ostream & operator<<(ostream &os, const GridPosPoly &gp)
Output operator for GridPosPoly.
Definition: interpolation_poly.cc:279
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:169
joker
const Joker joker
interpolation.h
Header file for interpolation.cc.
interpweights
void interpweights(VectorView itw, const GridPosPoly &tc)
Red 1D interpolation weights.
Definition: interpolation_poly.cc:315
is_size
bool is_size(ConstVectorView x, const Index &n)
Verifies that the size of x is l.
Definition: logic.cc:90
LOOPW
#define LOOPW(x)
Macro for interpolation weight loops.
Definition: interpolation_poly.cc:259
ConstTensor4View
A constant view of a Tensor4.
Definition: matpackIV.h:149
Tensor3View
The Tensor3View class.
Definition: matpackIII.h:234
Array
This can be used to make arrays out of anything.
Definition: array.h:103
GridPosPoly
Structure to store a grid position for higher order interpolation.
Definition: interpolation_poly.h:64
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:175
VectorView
The VectorView class.
Definition: matpackI.h:373
IMAX
Index IMAX(Index a, Index b)
Return the maximum of two integer numbers.
Definition: interpolation_poly.cc:62
ns
#define ns
Definition: continua.cc:14564
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:181
ConstTensor6View
A constant view of a Tensor6.
Definition: matpackVI.h:167
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
Tensor5View
The Tensor5View class.
Definition: matpackV.h:278
LOOPIDX
#define LOOPIDX(x)
Macro for interpolation index loops.
Definition: interpolation_poly.cc:267
interpolation_poly.h
Header file for interpolation_poly.cc.
ConstMatrixView
A constant view of a Matrix.
Definition: matpackI.h:591
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:147
Tensor4View
The Tensor4View class.
Definition: matpackIV.h:245
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:554
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
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:124
arts_omp.h
Header file for helper functions for OpenMP.
ConstVectorView
A constant view of a Vector.
Definition: matpackI.h:300
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:172
ConstTensor5View
A constant view of a Tensor5.
Definition: matpackV.h:160
Tensor6View
The Tensor6View class.
Definition: matpackVI.h:450