ARTS 2.5.11 (git: 6827797f)
special_interp.cc
Go to the documentation of this file.
1
45#include <cmath>
46#include <iostream>
47#include <stdexcept>
48#include "auto_md.h"
49#include "check_input.h"
50#include "math_funcs.h"
51#include "messages.h"
52#include "special_interp.h"
53
54/*===========================================================================
55 === Point interpolation functions for atmospheric grids and fields
56 ===========================================================================*/
57
58void interp_atmfield_gp2itw(Matrix& itw,
59 const Index& atmosphere_dim,
60 const ArrayOfGridPos& gp_p,
61 const ArrayOfGridPos& gp_lat,
62 const ArrayOfGridPos& gp_lon) {
63 const Index n = gp_p.nelem();
64
65 if (atmosphere_dim == 1) {
66 itw.resize(n, 2);
67 interpweights(itw, gp_p);
68 }
69
70 else if (atmosphere_dim == 2) {
71 ARTS_ASSERT(gp_lat.nelem() == n);
72 itw.resize(n, 4);
73 interpweights(itw, gp_p, gp_lat);
74 }
75
76 else if (atmosphere_dim == 3) {
77 ARTS_ASSERT(gp_lat.nelem() == n);
78 ARTS_ASSERT(gp_lon.nelem() == n);
79 itw.resize(n, 8);
80 interpweights(itw, gp_p, gp_lat, gp_lon);
81 }
82}
83
84void interp_atmfield_by_itw(VectorView x,
85 const Index& atmosphere_dim,
86 ConstTensor3View x_field,
87 const ArrayOfGridPos& gp_p,
88 const ArrayOfGridPos& gp_lat,
89 const ArrayOfGridPos& gp_lon,
90 ConstMatrixView itw) {
91 ARTS_ASSERT(x.nelem() == gp_p.nelem());
92
93 if (atmosphere_dim == 1) {
94 ARTS_ASSERT(itw.ncols() == 2);
95 interp(x, itw, x_field(Range(joker), 0, 0), gp_p);
96 }
97
98 else if (atmosphere_dim == 2) {
99 ARTS_ASSERT(itw.ncols() == 4);
100 interp(x, itw, x_field(Range(joker), Range(joker), 0), gp_p, gp_lat);
101 }
102
103 else if (atmosphere_dim == 3) {
104 ARTS_ASSERT(itw.ncols() == 8);
105 interp(x, itw, x_field, gp_p, gp_lat, gp_lon);
106 }
107}
108
109void interp_atmfield_by_gp(VectorView x,
110 const Index& atmosphere_dim,
111 ConstTensor3View x_field,
112 const ArrayOfGridPos& gp_p,
113 const ArrayOfGridPos& gp_lat,
114 const ArrayOfGridPos& gp_lon) {
115 Matrix itw;
116
117 interp_atmfield_gp2itw(itw, atmosphere_dim, gp_p, gp_lat, gp_lon);
118
119 interp_atmfield_by_itw(x, atmosphere_dim, x_field, gp_p, gp_lat, gp_lon, itw);
120}
121
122Numeric interp_atmfield_by_gp(const Index& atmosphere_dim,
123 ConstTensor3View x_field,
124 const GridPos& gp_p,
125 const GridPos& gp_lat,
126 const GridPos& gp_lon) {
127 ArrayOfGridPos agp_p(1), agp_lat(0), agp_lon(0);
128
129 gridpos_copy(agp_p[0], gp_p);
130
131 if (atmosphere_dim > 1) {
132 agp_lat.resize(1);
133 gridpos_copy(agp_lat[0], gp_lat);
134 }
135
136 if (atmosphere_dim > 2) {
137 agp_lon.resize(1);
138 gridpos_copy(agp_lon[0], gp_lon);
139 }
140
141 Vector x(1);
142
143 interp_atmfield_by_gp(x, atmosphere_dim, x_field, agp_p, agp_lat, agp_lon);
144
145 return x[0];
146}
147
148void interp_cloudfield_gp2itw(VectorView itw,
149 GridPos& gp_p_out,
150 GridPos& gp_lat_out,
151 GridPos& gp_lon_out,
152 const GridPos& gp_p_in,
153 const GridPos& gp_lat_in,
154 const GridPos& gp_lon_in,
155 const Index& atmosphere_dim,
156 const ArrayOfIndex& cloudbox_limits) {
157 // Shift grid positions to cloud box grids
158 if (atmosphere_dim == 1) {
159 gridpos_copy(gp_p_out, gp_p_in);
160 gp_p_out.idx -= cloudbox_limits[0];
161 gridpos_upperend_check(gp_p_out, cloudbox_limits[1] - cloudbox_limits[0]);
162 ARTS_ASSERT(itw.nelem() == 2);
163 interpweights(itw, gp_p_out);
164 } else if (atmosphere_dim == 2) {
165 gridpos_copy(gp_p_out, gp_p_in);
166 gridpos_copy(gp_lat_out, gp_lat_in);
167 gp_p_out.idx -= cloudbox_limits[0];
168 gp_lat_out.idx -= cloudbox_limits[2];
169 gridpos_upperend_check(gp_p_out, cloudbox_limits[1] - cloudbox_limits[0]);
170 gridpos_upperend_check(gp_lat_out, cloudbox_limits[3] - cloudbox_limits[2]);
171 ARTS_ASSERT(itw.nelem() == 4);
172 interpweights(itw, gp_p_out, gp_lat_out);
173 } else {
174 gridpos_copy(gp_p_out, gp_p_in);
175 gridpos_copy(gp_lat_out, gp_lat_in);
176 gridpos_copy(gp_lon_out, gp_lon_in);
177 gp_p_out.idx -= cloudbox_limits[0];
178 gp_lat_out.idx -= cloudbox_limits[2];
179 gp_lon_out.idx -= cloudbox_limits[4];
180 gridpos_upperend_check(gp_p_out, cloudbox_limits[1] - cloudbox_limits[0]);
181 gridpos_upperend_check(gp_lat_out, cloudbox_limits[3] - cloudbox_limits[2]);
182 gridpos_upperend_check(gp_lon_out, cloudbox_limits[5] - cloudbox_limits[4]);
183 ARTS_ASSERT(itw.nelem() == 8);
184 interpweights(itw, gp_p_out, gp_lat_out, gp_lon_out);
185 }
186}
187
208 const Index& atmosphere_dim,
209 const ArrayOfGridPos& gp_lat,
210 const ArrayOfGridPos& gp_lon) {
211 if (atmosphere_dim == 1) {
212 itw.resize(1, 1);
213 itw = 1;
214 }
215
216 else if (atmosphere_dim == 2) {
217 const Index n = gp_lat.nelem();
218 itw.resize(n, 2);
219 interpweights(itw, gp_lat);
220 }
221
222 else if (atmosphere_dim == 3) {
223 const Index n = gp_lat.nelem();
224 ARTS_ASSERT(n == gp_lon.nelem());
225 itw.resize(n, 4);
226 interpweights(itw, gp_lat, gp_lon);
227 }
228}
229
230void interp_atmsurface_by_itw(VectorView x,
231 const Index& atmosphere_dim,
232 ConstMatrixView x_surface,
233 const ArrayOfGridPos& gp_lat,
234 const ArrayOfGridPos& gp_lon,
235 ConstMatrixView itw) {
236 if (atmosphere_dim == 1) {
237 ARTS_ASSERT(itw.ncols() == 1);
238 x = x_surface(0, 0);
239 }
240
241 else if (atmosphere_dim == 2) {
242 ARTS_ASSERT(x.nelem() == gp_lat.nelem());
243 ARTS_ASSERT(itw.ncols() == 2);
244 interp(x, itw, x_surface(Range(joker), 0), gp_lat);
245 }
246
247 else if (atmosphere_dim == 3) {
248 ARTS_ASSERT(x.nelem() == gp_lat.nelem());
249 ARTS_ASSERT(itw.ncols() == 4);
250 interp(x, itw, x_surface, gp_lat, gp_lon);
251 }
252}
253
254void interp_atmsurface_by_gp(VectorView x,
255 const Index& atmosphere_dim,
256 ConstMatrixView x_surface,
257 const ArrayOfGridPos& gp_lat,
258 const ArrayOfGridPos& gp_lon) {
259 Matrix itw;
260
261 interp_atmsurface_gp2itw(itw, atmosphere_dim, gp_lat, gp_lon);
262
263 interp_atmsurface_by_itw(x, atmosphere_dim, x_surface, gp_lat, gp_lon, itw);
264}
265
266Numeric interp_atmsurface_by_gp(const Index& atmosphere_dim,
267 ConstMatrixView x_surface,
268 const GridPos& gp_lat,
269 const GridPos& gp_lon) {
270 ArrayOfGridPos agp_lat(0), agp_lon(0);
271
272 if (atmosphere_dim > 1) {
273 agp_lat.resize(1);
274 gridpos_copy(agp_lat[0], gp_lat);
275 }
276
277 if (atmosphere_dim > 2) {
278 agp_lon.resize(1);
279 gridpos_copy(agp_lon[0], gp_lon);
280 }
281
282 Vector x(1);
283
284 interp_atmsurface_by_gp(x, atmosphere_dim, x_surface, agp_lat, agp_lon);
285
286 return x[0];
287}
288
289/*===========================================================================
290 === Regridding
291 ===========================================================================*/
292
293void regrid_atmfield_by_gp(Tensor3& field_new,
294 const Index& atmosphere_dim,
295 ConstTensor3View field_old,
296 const ArrayOfGridPos& gp_p,
297 const ArrayOfGridPos& gp_lat,
298 const ArrayOfGridPos& gp_lon) {
299 const Index n1 = gp_p.nelem();
300
301 if (atmosphere_dim == 1) {
302 field_new.resize(n1, 1, 1);
303 Matrix itw(n1, 2);
304 interpweights(itw, gp_p);
305 interp(field_new(joker, 0, 0), itw, field_old(joker, 0, 0), gp_p);
306 } else if (atmosphere_dim == 2) {
307 const Index n2 = gp_lat.nelem();
308 field_new.resize(n1, n2, 1);
309 Tensor3 itw(n1, n2, 4);
310 interpweights(itw, gp_p, gp_lat);
311 interp(field_new(joker, joker, 0),
312 itw,
313 field_old(joker, joker, 0),
314 gp_p,
315 gp_lat);
316 } else if (atmosphere_dim == 3) {
317 const Index n2 = gp_lat.nelem();
318 const Index n3 = gp_lon.nelem();
319 field_new.resize(n1, n2, n3);
320 Tensor4 itw(n1, n2, n3, 8);
321 interpweights(itw, gp_p, gp_lat, gp_lon);
322 interp(field_new, itw, field_old, gp_p, gp_lat, gp_lon);
323 }
324}
325
326void regrid_atmsurf_by_gp(Matrix& field_new,
327 const Index& atmosphere_dim,
328 ConstMatrixView field_old,
329 const ArrayOfGridPos& gp_lat,
330 const ArrayOfGridPos& gp_lon) {
331 if (atmosphere_dim == 1) {
332 field_new = field_old;
333 } else if (atmosphere_dim == 2) {
334 const Index n1 = gp_lat.nelem();
335 field_new.resize(n1, 1);
336 Matrix itw(n1, 2);
337 interpweights(itw, gp_lat);
338 interp(field_new(joker, 0), itw, field_old(joker, 0), gp_lat);
339 } else if (atmosphere_dim == 3) {
340 const Index n1 = gp_lat.nelem();
341 const Index n2 = gp_lon.nelem();
342 field_new.resize(n1, n2);
343 Tensor3 itw(n1, n2, 4);
344 interpweights(itw, gp_lat, gp_lon);
345 interp(field_new, itw, field_old, gp_lat, gp_lon);
346 }
347}
348
350 ArrayOfGridPos& gp_lat,
351 ArrayOfGridPos& gp_lon,
352 const RetrievalQuantity& rq,
353 const Index& atmosphere_dim,
354 const Vector& p_grid,
355 const Vector& lat_grid,
356 const Vector& lon_grid) {
357 gp_p.resize(rq.Grids()[0].nelem());
358 p2gridpos(gp_p, p_grid, rq.Grids()[0], 0);
359 //
360 if (atmosphere_dim >= 2) {
361 gp_lat.resize(rq.Grids()[1].nelem());
362 gridpos(gp_lat, lat_grid, rq.Grids()[1], 0);
363 } else {
364 gp_lat.resize(0);
365 }
366 //
367 if (atmosphere_dim >= 3) {
368 gp_lon.resize(rq.Grids()[2].nelem());
369 gridpos(gp_lon, lon_grid, rq.Grids()[2], 0);
370 } else {
371 gp_lon.resize(0);
372 }
373}
374
376 ArrayOfGridPos& gp_lon,
377 const RetrievalQuantity& rq,
378 const Index& atmosphere_dim,
379 const Vector& lat_grid,
380 const Vector& lon_grid) {
381 if (atmosphere_dim >= 2) {
382 gp_lat.resize(rq.Grids()[0].nelem());
383 gridpos(gp_lat, lat_grid, rq.Grids()[0], 0);
384 } else {
385 gp_lat.resize(0);
386 }
387 //
388 if (atmosphere_dim >= 3) {
389 gp_lon.resize(rq.Grids()[1].nelem());
390 gridpos(gp_lon, lon_grid, rq.Grids()[1], 0);
391 } else {
392 gp_lon.resize(0);
393 }
394}
395
397 ArrayOfGridPos& gp_lat,
398 ArrayOfGridPos& gp_lon,
399 Index& n_p,
400 Index& n_lat,
401 Index& n_lon,
402 const ArrayOfVector& ret_grids,
403 const Index& atmosphere_dim,
404 const Vector& p_grid,
405 const Vector& lat_grid,
406 const Vector& lon_grid) {
407 // We want here an extrapolation to infinity ->
408 // extremly high extrapolation factor
409 const Numeric inf_proxy = 1.0e99;
410
411 gp_p.resize(p_grid.nelem());
412 n_p = ret_grids[0].nelem();
413 if (n_p > 1) {
414 p2gridpos(gp_p, ret_grids[0], p_grid, inf_proxy);
416 } else {
417 gp4length1grid(gp_p);
418 }
419
420 if (atmosphere_dim >= 2) {
421 gp_lat.resize(lat_grid.nelem());
422 n_lat = ret_grids[1].nelem();
423 if (n_lat > 1) {
424 gridpos(gp_lat, ret_grids[1], lat_grid, inf_proxy);
426 } else {
427 gp4length1grid(gp_lat);
428 }
429 } else {
430 gp_lat.resize(0);
431 n_lat = 1;
432 }
433 //
434 if (atmosphere_dim >= 3) {
435 gp_lon.resize(lon_grid.nelem());
436 n_lon = ret_grids[2].nelem();
437 if (n_lon > 1) {
438 gridpos(gp_lon, ret_grids[2], lon_grid, inf_proxy);
440 } else {
441 gp4length1grid(gp_lon);
442 }
443 } else {
444 gp_lon.resize(0);
445 n_lon = 1;
446 }
447}
448
450 ArrayOfGridPos& gp_lon,
451 Index& n_lat,
452 Index& n_lon,
453 const ArrayOfVector& ret_grids,
454 const Index& atmosphere_dim,
455 const Vector& lat_grid,
456 const Vector& lon_grid) {
457 // We want here an extrapolation to infinity ->
458 // extremly high extrapolation factor
459 const Numeric inf_proxy = 1.0e99;
460
461 if (atmosphere_dim >= 2) {
462 gp_lat.resize(lat_grid.nelem());
463 n_lat = ret_grids[0].nelem();
464 if (n_lat > 1) {
465 gridpos(gp_lat, ret_grids[0], lat_grid, inf_proxy);
467 } else {
468 gp4length1grid(gp_lat);
469 }
470 } else {
471 gp_lat.resize(0);
472 n_lat = 1;
473 }
474 //
475 if (atmosphere_dim >= 3) {
476 gp_lon.resize(lon_grid.nelem());
477 n_lon = ret_grids[1].nelem();
478 if (n_lon > 1) {
479 gridpos(gp_lon, ret_grids[1], lon_grid, inf_proxy);
481 } else {
482 gp4length1grid(gp_lon);
483 }
484 } else {
485 gp_lon.resize(0);
486 n_lon = 1;
487 }
488}
489
490void regrid_atmfield_by_gp_oem(Tensor3& field_new,
491 const Index& atmosphere_dim,
492 ConstTensor3View field_old,
493 const ArrayOfGridPos& gp_p,
494 const ArrayOfGridPos& gp_lat,
495 const ArrayOfGridPos& gp_lon) {
496 const Index n1 = gp_p.nelem();
497
498 const bool np_is1 = field_old.npages() == 1 ? true : false;
499 const bool nlat_is1 =
500 atmosphere_dim > 1 && field_old.nrows() == 1 ? true : false;
501 const bool nlon_is1 =
502 atmosphere_dim > 2 && field_old.ncols() == 1 ? true : false;
503
504 // If no length 1, we can use standard function
505 if (!np_is1 && !nlat_is1 && !nlon_is1) {
507 field_new, atmosphere_dim, field_old, gp_p, gp_lat, gp_lon);
508 } else {
509 //--- 1D (1 possibilities left) -------------------------------------------
510 if (atmosphere_dim == 1) { // 1: No interpolation at all
511 field_new.resize(n1, 1, 1);
512 field_new(joker, 0, 0) = field_old(0, 0, 0);
513 }
514
515 //--- 2D (3 possibilities left) -------------------------------------------
516 else if (atmosphere_dim == 2) {
517 const Index n2 = gp_lat.nelem();
518 field_new.resize(n1, n2, 1);
519 //
520 if (np_is1 && nlat_is1) // 1: No interpolation at all
521 {
522 // Here we need no interpolation at all
523 field_new(joker, joker, 0) = field_old(0, 0, 0);
524 } else if (np_is1) // 2: Latitude interpolation
525 {
526 Matrix itw(n2, 2);
527 interpweights(itw, gp_lat);
528 Vector tmp(n2);
529 interp(tmp, itw, field_old(0, joker, 0), gp_lat);
530 for (Index p = 0; p < n1; p++) {
531 ARTS_ASSERT(gp_p[p].fd[0] < 1e-6);
532 field_new(p, joker, 0) = tmp;
533 }
534 } else // 3: Pressure interpolation
535 {
536 Matrix itw(n1, 2);
537 interpweights(itw, gp_p);
538 Vector tmp(n1);
539 interp(tmp, itw, field_old(joker, 0, 0), gp_p);
540 for (Index lat = 0; lat < n2; lat++) {
541 ARTS_ASSERT(gp_lat[lat].fd[0] < 1e-6);
542 field_new(joker, lat, 0) = tmp;
543 }
544 }
545 }
546
547 //--- 3D (7 possibilities left) -------------------------------------------
548 else if (atmosphere_dim == 3) {
549 const Index n2 = gp_lat.nelem();
550 const Index n3 = gp_lon.nelem();
551 field_new.resize(n1, n2, n3);
552 //
553 if (np_is1 && nlat_is1 && nlon_is1) // 1: No interpolation at all
554 {
555 field_new(joker, joker, joker) = field_old(0, 0, 0);
556 }
557
558 else if (np_is1) // No pressure interpolation --------------
559 {
560 if (nlat_is1) // 2: Just longitude interpolation
561 {
562 Matrix itw(n3, 2);
563 interpweights(itw, gp_lon);
564 Vector tmp(n3);
565 interp(tmp, itw, field_old(0, 0, joker), gp_lon);
566 for (Index p = 0; p < n1; p++) {
567 ARTS_ASSERT(gp_p[p].fd[0] < 1e-6);
568 for (Index lat = 0; lat < n2; lat++) {
569 ARTS_ASSERT(gp_lat[lat].fd[0] < 1e-6);
570 field_new(p, lat, joker) = tmp;
571 }
572 }
573 } else if (nlon_is1) // 3: Just latitude interpolation
574 {
575 Matrix itw(n2, 2);
576 interpweights(itw, gp_lat);
577 Vector tmp(n2);
578 interp(tmp, itw, field_old(0, joker, 0), gp_lat);
579 for (Index p = 0; p < n1; p++) {
580 ARTS_ASSERT(gp_p[p].fd[0] < 1e-6);
581 for (Index lon = 0; lon < n3; lon++) {
582 ARTS_ASSERT(gp_lon[lon].fd[0] < 1e-6);
583 field_new(p, joker, lon) = tmp;
584 }
585 }
586 } else // 4: Both lat and lon interpolation
587 {
588 Tensor3 itw(n2, n3, 4);
589 interpweights(itw, gp_lat, gp_lon);
590 Matrix tmp(n2, n3);
591 interp(tmp, itw, field_old(0, joker, joker), gp_lat, gp_lon);
592 for (Index p = 0; p < n1; p++) {
593 ARTS_ASSERT(gp_p[p].fd[0] < 1e-6);
594 field_new(p, joker, joker) = tmp;
595 }
596 }
597 }
598
599 else // Pressure interpolation --------------
600 {
601 if (nlat_is1 && nlon_is1) // 5: Just pressure interpolatiom
602 {
603 Matrix itw(n1, 2);
604 interpweights(itw, gp_p);
605 Vector tmp(n1);
606 interp(tmp, itw, field_old(joker, 0, 0), gp_p);
607 for (Index lat = 0; lat < n2; lat++) {
608 ARTS_ASSERT(gp_lat[lat].fd[0] < 1e-6);
609 for (Index lon = 0; lon < n3; lon++) {
610 ARTS_ASSERT(gp_lon[lon].fd[0] < 1e-6);
611 field_new(joker, lat, lon) = tmp;
612 }
613 }
614 } else if (nlat_is1) // 6: Both p and lon interpolation
615 {
616 Tensor3 itw(n1, n3, 4);
617 interpweights(itw, gp_p, gp_lon);
618 Matrix tmp(n1, n3);
619 interp(tmp, itw, field_old(joker, 0, joker), gp_p, gp_lon);
620 for (Index lat = 0; lat < n2; lat++) {
621 ARTS_ASSERT(gp_lat[lat].fd[0] < 1e-6);
622 field_new(joker, lat, joker) = tmp;
623 }
624 } else // 7: Both p and lat interpolation
625 {
626 Tensor3 itw(n1, n2, 4);
627 interpweights(itw, gp_p, gp_lat);
628 Matrix tmp(n1, n2);
629 interp(tmp, itw, field_old(joker, joker, 0), gp_p, gp_lat);
630 for (Index lon = 0; lon < n3; lon++) {
631 ARTS_ASSERT(gp_lon[lon].fd[0] < 1e-6);
632 field_new(joker, joker, lon) = tmp;
633 }
634 }
635 }
636 }
637 }
638}
639
640/* So far just a temporary test */
641void regrid_atmsurf_by_gp_oem(Matrix& field_new,
642 const Index& atmosphere_dim,
643 ConstMatrixView field_old,
644 const ArrayOfGridPos& gp_lat,
645 const ArrayOfGridPos& gp_lon) {
646 // As 1D is so simple, let's do it here and not go to standard function
647 if (atmosphere_dim == 1) {
648 field_new = field_old;
649 } else {
650 const bool nlat_is1 = field_old.nrows() == 1 ? true : false;
651 const bool nlon_is1 =
652 atmosphere_dim > 2 && field_old.ncols() == 1 ? true : false;
653
654 // If no length 1, we can use standard function
655 if (!nlat_is1 && !nlon_is1) {
657 field_new, atmosphere_dim, field_old, gp_lat, gp_lon);
658 } else {
659 if (atmosphere_dim == 2) { // 1: No interpolation at all
660 const Index n1 = gp_lat.nelem();
661 field_new.resize(n1, 1);
662 field_new(joker, 0) = field_old(0, 0);
663 } else {
664 const Index n1 = gp_lat.nelem();
665 const Index n2 = gp_lon.nelem();
666 field_new.resize(n1, n2);
667 //
668 if (nlat_is1 && nlon_is1) // 1: No interpolation at all
669 {
670 field_new(joker, joker) = field_old(0, 0);
671 } else if (nlon_is1) // 2: Just latitude interpolation
672 {
673 Matrix itw(n1, 2);
674 interpweights(itw, gp_lat);
675 Vector tmp(n1);
676 interp(tmp, itw, field_old(joker, 0), gp_lat);
677 for (Index lon = 0; lon < n2; lon++) {
678 ARTS_ASSERT(gp_lon[lon].fd[0] < 1e-6);
679 field_new(joker, lon) = tmp;
680 }
681 } else // 2: Just longitude interpolation
682 {
683 Matrix itw(n2, 2);
684 interpweights(itw, gp_lon);
685 Vector tmp(n2);
686 interp(tmp, itw, field_old(0, joker), gp_lon);
687 for (Index lat = 0; lat < n1; lat++) {
688 ARTS_ASSERT(gp_lat[lat].fd[0] < 1e-6);
689 field_new(lat, joker) = tmp;
690 }
691 }
692 }
693 }
694 }
695}
696
697/*===========================================================================
698 === Conversion altitudes / pressure
699 ===========================================================================*/
700
701void itw2p(VectorView p_values,
702 ConstVectorView p_grid,
703 const ArrayOfGridPos& gp,
704 ConstMatrixView itw) {
705 ARTS_ASSERT(itw.ncols() == 2);
706 ARTS_ASSERT(p_values.nelem() == itw.nrows());
707
708 // Local variable to store log of the pressure grid:
709 Vector logpgrid(p_grid.nelem());
710
711 transform(logpgrid, log, p_grid);
712
713 interp(p_values, itw, logpgrid, gp);
714
715 transform(p_values, exp, p_values);
716}
717
743 ConstVectorView old_pgrid,
744 ConstVectorView new_pgrid,
745 const Numeric& extpolfac) {
746 // Local variable to store log of the pressure grids
747 Vector logold(old_pgrid.nelem());
748 Vector lognew(new_pgrid.nelem());
749
750 transform(logold, log, old_pgrid);
751 transform(lognew, log, new_pgrid);
752
753 gridpos(gp, logold, lognew, extpolfac);
754}
755
757 GridPos& gp_lat,
758 GridPos& gp_lon,
759 const Index& atmosphere_dim,
760 ConstVectorView p_grid,
761 ConstVectorView lat_grid,
762 ConstVectorView lon_grid,
763 ConstTensor3View z_field,
764 ConstVectorView rte_pos) {
765 chk_rte_pos(atmosphere_dim, rte_pos);
766
767 if (atmosphere_dim == 1) {
769 "Altitude interpolation", z_field(joker, 0, 0), rte_pos[0]);
770 gridpos(gp_p, z_field(joker, 0, 0), rte_pos[0]);
771 } else {
772 // Determine z at lat/lon (z_grid) by blue interpolation
773 const Index np = p_grid.nelem();
774 Vector z_grid(np);
775 ArrayOfGridPos agp_z, agp_lat(np);
776 //
777 gridpos_1to1(agp_z, p_grid);
778 //
779 chk_interpolation_grids("Latitude interpolation", lat_grid, rte_pos[1]);
780 gridpos(gp_lat, lat_grid, rte_pos[1]);
781
782 if (atmosphere_dim == 2) {
783 for (Index i = 0; i < np; i++) {
784 agp_lat[i] = gp_lat;
785 }
786 Matrix itw(np, 4);
787 interpweights(itw, agp_z, agp_lat);
788 interp(z_grid, itw, z_field(joker, joker, 0), agp_z, agp_lat);
789 } else {
790 chk_interpolation_grids("Longitude interpolation", lon_grid, rte_pos[2]);
791 gridpos(gp_lon, lon_grid, rte_pos[2]);
792 ArrayOfGridPos agp_lon(np);
793 for (Index i = 0; i < np; i++) {
794 agp_lat[i] = gp_lat;
795 agp_lon[i] = gp_lon;
796 }
797 Matrix itw(np, 8);
798 interpweights(itw, agp_z, agp_lat, agp_lon);
799 interp(z_grid, itw, z_field, agp_z, agp_lat, agp_lon);
800 }
801
802 // And use z_grid to get gp_p (gp_al and gp_lon determined above)
803 chk_interpolation_grids("Altitude interpolation", z_grid, rte_pos[0]);
804 gridpos(gp_p, z_grid, rte_pos[0]);
805 }
806}
807
809 GridPos& gp_lon,
810 const Index& atmosphere_dim,
811 ConstVectorView lat_grid,
812 ConstVectorView lon_grid,
813 ConstVectorView rte_pos) {
814 chk_rte_pos(atmosphere_dim, rte_pos);
815
816 if (atmosphere_dim == 1) {
817 } else {
818 chk_interpolation_grids("Latitude interpolation", lat_grid, rte_pos[1]);
819 gridpos(gp_lat, lat_grid, rte_pos[1]);
820
821 if (atmosphere_dim == 3) {
822 chk_interpolation_grids("Longitude interpolation", lon_grid, rte_pos[2]);
823 gridpos(gp_lon, lon_grid, rte_pos[2]);
824 }
825 }
826}
827
828void z_at_lat_2d(VectorView z,
829 ConstVectorView p_grid,
830// FIXME only used in assertion
831#ifndef NDEBUG
832 ConstVectorView lat_grid,
833#else
834 ConstVectorView,
835#endif
836 ConstMatrixView z_field,
837 const GridPos& gp_lat) {
838 const Index np = p_grid.nelem();
839
840 ARTS_ASSERT(z.nelem() == np);
841 ARTS_ASSERT(z_field.nrows() == np);
842 ARTS_ASSERT(z_field.ncols() == lat_grid.nelem());
843
844 Matrix z_matrix(np, 1);
845 ArrayOfGridPos gp_z(np), agp_lat(1);
846 Tensor3 itw(np, 1, 4);
847
848 gridpos_copy(agp_lat[0], gp_lat);
849 gridpos(gp_z, p_grid, p_grid);
850 interpweights(itw, gp_z, agp_lat);
851 interp(z_matrix, itw, z_field, gp_z, agp_lat);
852
853 z = z_matrix(Range(joker), 0);
854}
855
856void z_at_latlon(VectorView z,
857 ConstVectorView p_grid,
858//FIXME only used in assertion
859#ifndef NDEBUG
860 ConstVectorView lat_grid,
861 ConstVectorView lon_grid,
862#else
863 ConstVectorView,
864 ConstVectorView,
865#endif
866 ConstTensor3View z_field,
867 const GridPos& gp_lat,
868 const GridPos& gp_lon) {
869 const Index np = p_grid.nelem();
870
871 ARTS_ASSERT(z.nelem() == np);
872 ARTS_ASSERT(z_field.npages() == np);
873 ARTS_ASSERT(z_field.nrows() == lat_grid.nelem());
874 ARTS_ASSERT(z_field.ncols() == lon_grid.nelem());
875
876 Tensor3 z_tensor(np, 1, 1);
877 ArrayOfGridPos agp_z(np), agp_lat(1), agp_lon(1);
878 Tensor4 itw(np, 1, 1, 8);
879
880 gridpos_copy(agp_lat[0], gp_lat);
881 gridpos_copy(agp_lon[0], gp_lon);
882 gridpos(agp_z, p_grid, p_grid);
883 interpweights(itw, agp_z, agp_lat, agp_lon);
884
885 interp(z_tensor, itw, z_field, agp_z, agp_lat, agp_lon);
886
887 z = z_tensor(Range(joker), 0, 0);
888}
889
890/*===========================================================================
891 === Interpolation of GriddedFields
892 ===========================================================================*/
893
894void complex_n_interp(MatrixView n_real,
895 MatrixView n_imag,
896 const GriddedField3& complex_n,
897 const String& varname,
898 ConstVectorView f_grid,
899 ConstVectorView t_grid) {
900 // Set expected order of grids
901 Index gfield_fID = 0;
902 Index gfield_tID = 1;
903 Index gfield_compID = 2;
904
905 // Check of complex_n
906 //
907 complex_n.checksize_strict();
908 //
909 chk_griddedfield_gridname(complex_n, gfield_fID, "Frequency");
910 chk_griddedfield_gridname(complex_n, gfield_tID, "Temperature");
911 chk_griddedfield_gridname(complex_n, gfield_compID, "Complex");
912 //
913 if (complex_n.data.ncols() != 2) {
914 ostringstream os;
915 os << "The data in *" << varname
916 << "* must have exactly two pages. One page "
917 << "each\nfor the real and imaginary part of the complex refractive index.";
918 }
919
920 // Frequency and temperature grid sizes
921 const Index nf_in = complex_n.data.npages();
922 const Index nt_in = complex_n.data.nrows();
923 const Index nf_out = f_grid.nelem();
924 const Index nt_out = t_grid.nelem();
925
926 //Assert size of output variables
927 ARTS_ASSERT(n_real.nrows() == nf_out && n_real.ncols() == nt_out);
928 ARTS_ASSERT(n_imag.nrows() == nf_out && n_imag.ncols() == nt_out);
929
930 const Vector& f_grid_in = complex_n.get_numeric_grid(gfield_fID);
931 const Vector& t_grid_in = complex_n.get_numeric_grid(gfield_tID);
932
933 // Expand/interpolate in frequency dimension
934 //
935 Matrix nrf(nf_out, nt_in), nif(nf_out, nt_in);
936 //
937 if (nf_in == 1) {
938 for (Index i = 0; i < nf_out; i++) {
939 nrf(i, joker) = complex_n.data(0, joker, 0);
940 nif(i, joker) = complex_n.data(0, joker, 1);
941 }
942 } else {
943 chk_interpolation_grids("Frequency interpolation", f_grid_in, f_grid);
944 //
945 ArrayOfGridPos gp(nf_out);
946 Matrix itw(nf_out, 2);
947 gridpos(gp, f_grid_in, f_grid);
948 interpweights(itw, gp);
949 for (Index i = 0; i < nt_in; i++) {
950 interp(nrf(joker, i), itw, complex_n.data(joker, i, 0), gp);
951 interp(nif(joker, i), itw, complex_n.data(joker, i, 1), gp);
952 }
953 }
954
955 // Expand/interpolate in temperature dimension
956 //
957 if (nt_in == 1) {
958 for (Index i = 0; i < nt_out; i++) {
959 n_real(joker, i) = nrf(joker, 0);
960 n_imag(joker, i) = nif(joker, 0);
961 }
962 } else {
963 chk_interpolation_grids("Temperature interpolation", t_grid_in, t_grid);
964 //
965 ArrayOfGridPos gp(nt_out);
966 Matrix itw(nt_out, 2);
967 gridpos(gp, t_grid_in, t_grid);
968 interpweights(itw, gp);
969 for (Index i = 0; i < nf_out; i++) {
970 interp(n_real(i, joker), itw, nrf(i, joker), gp);
971 interp(n_imag(i, joker), itw, nif(i, joker), gp);
972 }
973 }
974}
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:887
void chk_rte_pos(const Index &atmosphere_dim, ConstVectorView rte_pos, const bool &is_rte_pos2)
chk_rte_pos
void chk_griddedfield_gridname(const GriddedField &gf, const Index gridindex, const String &gridname)
Check name of grid in GriddedField.
Index nelem() const ARTS_NOEXCEPT
Definition: array.h:75
void checksize_strict() const final
Strict consistency check.
const Vector & get_numeric_grid(Index i) const
Get a numeric grid.
Deals with internal derivatives, Jacobian definition, and OEM calculations.
Definition: jacobian.h:310
const ArrayOfVector & Grids() const
Returns the grids of the retrieval.
Definition: jacobian.h:393
#define ARTS_ASSERT(condition,...)
Definition: debug.h:84
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
void gridpos_upperend_check(GridPos &gp, const Index &ie)
gridpos_upperend_check
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
void gp4length1grid(ArrayOfGridPos &gp)
Grid position matching a grid of length 1.
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPos &tc)
Red 1D Interpolate.
void gridpos_copy(GridPos &gp_new, const GridPos &gp_old)
gridpos_copy
void gridpos_1to1(ArrayOfGridPos &gp, ConstVectorView grid)
gridpos_1to1
void jacobian_type_extrapol(ArrayOfGridPos &gp)
Adopts grid positions to extrapolation used for jacobians.
Definition: jacobian.cc:819
Declarations having to do with the four output streams.
void complex_n_interp(MatrixView n_real, MatrixView n_imag, const GriddedField3 &complex_n, const String &varname, ConstVectorView f_grid, ConstVectorView t_grid)
General function for interpolating data of complex n type.
void regrid_atmfield_by_gp(Tensor3 &field_new, const Index &atmosphere_dim, ConstTensor3View field_old, const ArrayOfGridPos &gp_p, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Regrids an atmospheric field, for precalculated grid positions.
void interp_atmsurface_gp2itw(Matrix &itw, const Index &atmosphere_dim, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Converts atmospheric grid positions to weights for interpolation of a surface-type variable.
void regrid_atmfield_by_gp_oem(Tensor3 &field_new, const Index &atmosphere_dim, ConstTensor3View field_old, const ArrayOfGridPos &gp_p, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Regridding of atmospheric field OEM-type.
void get_gp_atmsurf_to_rq(ArrayOfGridPos &gp_lat, ArrayOfGridPos &gp_lon, const RetrievalQuantity &rq, const Index &atmosphere_dim, const Vector &lat_grid, const Vector &lon_grid)
Determines grid positions for regridding of atmospheric surfaces to retrieval grids.
void regrid_atmsurf_by_gp(Matrix &field_new, const Index &atmosphere_dim, ConstMatrixView field_old, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Regrids an atmospheric surface, for precalculated grid positions.
void interp_atmfield_gp2itw(Matrix &itw, const Index &atmosphere_dim, const ArrayOfGridPos &gp_p, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Converts atmospheric grid positions to weights for interpolation of an atmospheric field.
void itw2p(VectorView p_values, ConstVectorView p_grid, const ArrayOfGridPos &gp, ConstMatrixView itw)
Converts interpolation weights to pressures.
void z_at_latlon(VectorView z, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid, ConstTensor3View z_field, const GridPos &gp_lat, const GridPos &gp_lon)
Returns the geomtrical altitudes of p_grid for one latitude and one longitude.
void p2gridpos(ArrayOfGridPos &gp, ConstVectorView old_pgrid, ConstVectorView new_pgrid, const Numeric &extpolfac)
Calculates grid positions for pressure values.
void interp_cloudfield_gp2itw(VectorView itw, GridPos &gp_p_out, GridPos &gp_lat_out, GridPos &gp_lon_out, const GridPos &gp_p_in, const GridPos &gp_lat_in, const GridPos &gp_lon_in, const Index &atmosphere_dim, const ArrayOfIndex &cloudbox_limits)
Converts atmospheric a grid position to weights for interpolation of a field defined ONLY inside the ...
void get_gp_rq_to_atmgrids(ArrayOfGridPos &gp_p, ArrayOfGridPos &gp_lat, ArrayOfGridPos &gp_lon, Index &n_p, Index &n_lat, Index &n_lon, const ArrayOfVector &ret_grids, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid)
Determines grid positions for regridding of atmospheric fields to retrieval grids.
void regrid_atmsurf_by_gp_oem(Matrix &field_new, const Index &atmosphere_dim, ConstMatrixView field_old, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Regridding of surface field OEM-type.
void get_gp_atmgrids_to_rq(ArrayOfGridPos &gp_p, ArrayOfGridPos &gp_lat, ArrayOfGridPos &gp_lon, const RetrievalQuantity &rq, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid)
Determines grid positions for regridding of atmospheric fields to retrieval grids.
void interp_atmfield_by_gp(VectorView x, const Index &atmosphere_dim, ConstTensor3View x_field, const ArrayOfGridPos &gp_p, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Interpolates an atmospheric field given the grid positions.
void rte_pos2gridpos(GridPos &gp_p, GridPos &gp_lat, GridPos &gp_lon, const Index &atmosphere_dim, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid, ConstTensor3View z_field, ConstVectorView rte_pos)
Converts a geographical position (rte_pos) to grid positions for p, lat and lon.
void interp_atmfield_by_itw(VectorView x, const Index &atmosphere_dim, ConstTensor3View x_field, const ArrayOfGridPos &gp_p, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon, ConstMatrixView itw)
Interpolates an atmospheric field with pre-calculated weights by interp_atmfield_gp2itw.
void z_at_lat_2d(VectorView z, ConstVectorView p_grid, ConstVectorView lat_grid, ConstMatrixView z_field, const GridPos &gp_lat)
Returns the geomtrical altitudes of p_grid for one latitude.
void interp_atmsurface_by_gp(VectorView x, const Index &atmosphere_dim, ConstMatrixView x_surface, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Interpolates a surface-type variable given the grid positions.
void interp_atmsurface_by_itw(VectorView x, const Index &atmosphere_dim, ConstMatrixView x_surface, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon, ConstMatrixView itw)
Interpolates a surface-type variable with pre-calculated weights by interp_atmsurface_gp2itw.
Header file for special_interp.cc.
Structure to store a grid position.
Definition: interpolation.h:56
Index idx
Definition: interpolation.h:57