73 const double RTOL = 1e-2;
96 const double ANGTOL = 1e-7;
134 assert(
abs(za) <= 180 );
166 assert(
abs(a_za) <= 180 );
167 assert( r >= ppc -
RTOL );
171 double za =
RAD2DEG * asin( ppc / r );
205 assert(
abs(za) <= 180 );
233 assert(
abs(za0) <= 180 );
234 assert(
abs(za) <= 180 );
235 assert( ( za0 >= 0 && za >= 0 ) || ( za0 < 0 && za < 0 ) );
237 return lat0 + za0 - za;
261 assert( r >= ppc -
RTOL );
264 {
return sqrt( r*r - ppc*ppc ); }
292 return sqrt( l*l + ppc*ppc );
317 assert(
abs(za0) <= 180 );
318 assert( ( za0 >= 0 && lat >= lat0 ) || ( za0 <= 0 && lat <= lat0 ) );
321 const double za = za0 + lat0 -lat;
371 n =
Index( ceil(
abs( l2 - l1 ) / lmax ) );
381 lstep = ( l2 - l1 ) / (
double)n;
392 for(
Index i=1; i<n; i++ )
407 for(
Index i=1; i<=n; i++ )
411 lstep =
abs( lstep );
449 const double dlat =
abs( lat2 - lat1 );
454 sqrt( r1*r1 + r2*r2 - 2 * r1 * r2 * cos(
DEG2RAD * dlat ) ) );
499 assert(
abs( lat ) <= 90 );
500 assert(
abs( lon ) <= 360 );
502 const double latrad =
DEG2RAD * lat;
503 const double lonrad =
DEG2RAD * lon;
505 x = r * cos( latrad );
506 z = x * sin( lonrad );
507 x = x * cos( lonrad );
508 y = r * sin( latrad );
535 r = sqrt( x*x + y*y + z*z );
585 const double s =
sign( lat );
599 const double latrad =
DEG2RAD * lat;
600 const double lonrad =
DEG2RAD * lon;
601 const double zarad =
DEG2RAD * za;
602 const double aarad =
DEG2RAD * aa;
606 const double coslat = cos( latrad );
607 const double sinlat = sin( latrad );
608 const double coslon = cos( lonrad );
609 const double sinlon = sin( lonrad );
610 const double cosza = cos( zarad );
611 const double sinza = sin( zarad );
612 const double cosaa = cos( aarad );
613 const double sinaa = sin( aarad );
615 const double dr = cosza;
616 const double dlat = sinza * cosaa;
617 const double dlon = sinza * sinaa / coslat;
619 dx = coslat*coslon * dr - sinlat*coslon * dlat - coslat*sinlon * dlon;
620 dy = sinlat * dr + coslat * dlat;
621 dz = coslat*sinlon * dr - sinlat*sinlon * dlat + coslat*coslon * dlon;
666 assert(
abs( sqrt(
dx*
dx + dy*dy + dz*dz ) - 1 ) < 1e-6 );
672 const double coslat = cos(
DEG2RAD * lat );
673 const double sinlat = sin(
DEG2RAD * lat );
674 const double coslon = cos(
DEG2RAD * lon );
675 const double sinlon = sin(
DEG2RAD * lon );
676 const double dr = coslat*coslon*
dx + sinlat*dy + coslat*sinlon*dz;
677 const double dlat = -sinlat*coslon/r*
dx + coslat/r*dy -sinlat*sinlon/r*dz;
678 const double dlon = -sinlon/coslat/r*
dx + coslon/coslat/r*dz;
683 if( za < ANGTOL || za > 180-
ANGTOL )
740 assert( lon6 >= lon5 );
742 if( lon < lon5 && lon+180 <= lon6 )
744 else if( lon > lon6 && lon-180 >= lon5 )
753 assert( lon6 >= lon5 );
755 if( lon < lon5 && lon+180 <= lon6 )
757 else if( lon > lon6 && lon-180 >= lon5 )
799 double x, y, z,
dx, dy, dz;
801 poslos2cart( x, y, z,
dx, dy, dz, r, lat, lon, za, aa );
803 l_tan = sqrt( r*r - ppc*ppc );
805 cart2sph( r_tan, lat_tan, lon_tan, x+
dx*l_tan, y+dy*l_tan, z+dz*l_tan );
841 const double zarad =
DEG2RAD * za;
842 const double aarad =
DEG2RAD * aa;
846 dy = sin( aarad ) *
dx;
847 dx = cos( aarad ) *
dx;
883 const double r = sqrt(
dx*
dx + dy*dy + dz*dz );
916 assert( R.
ncols() == 3 );
917 assert( R.
nrows() == 3 );
918 assert( vrot.
nelem() == 3 );
920 const double u = vrot[0];
921 const double v = vrot[1];
922 const double w = vrot[2];
924 const double u2 = u * u;
925 const double v2 = v * v;
926 const double w2 = w * w;
928 assert( sqrt( u2 + v2 + w2 ) );
930 const double c = cos(
DEG2RAD * a );
931 const double s = sin(
DEG2RAD * a );
934 R(0,0) = u2 + (v2 + w2)*c;
935 R(0,1) = u*v*(1-c) - w*s;
936 R(0,2) = u*w*(1-c) + v*s;
937 R(1,0) = u*v*(1-c) + w*s;
938 R(1,1) = v2 + (u2+w2)*c;
939 R(1,2) = v*w*(1-c) - u*s;
940 R(2,0) = u*w*(1-c) - v*s;
941 R(2,1) = v*w*(1-c)+u*s;
942 R(2,2) = w2 + (u2+v2)*c;
972 const double& aa_grid )
974 assert(
abs( aa_grid ) <= 5 );
982 zaaa2cart( xyz[0], xyz[1], xyz[2], 90, aa0 );
995 zaaa2cart( xyz[0], xyz[1], xyz[2], 90, aa0+aa_grid );
1051 const double r1 = r_geoid[i1] + z_surf[i1];
1052 const double r2 = r_geoid[i1+1] + z_surf[i1+1];
1053 return ( r2 - r1 ) / ( lat_grid[i1+1] - lat_grid[i1] );
1082 return ( r2 - r1 ) / ( lat2 -lat1 );
1109 return r1 + ( lat - lat1 ) * ( r3 - r1 ) / ( lat3 - lat1 );
1149 {
return r15 + ( lon - lon5 ) * ( r16 - r15 ) / ( lon6 -lon5 ); }
1150 else if( lat == lat3 )
1151 {
return r35 + ( lon - lon5 ) * ( r36 - r35 ) / ( lon6 -lon5 ); }
1152 else if( lon == lon5 )
1153 {
return r15 + ( lat - lat1 ) * ( r35 - r15 ) / ( lat3 -lat1 ); }
1154 else if( lon == lon6 )
1155 {
return r16 + ( lat - lat1 ) * ( r36 - r16 ) / ( lat3 -lat1 ); }
1158 const double fdlat = ( lat - lat1 ) / ( lat3 - lat1 );
1159 const double fdlon = ( lon - lon5 ) / ( lon6 - lon5 );
1160 return (1-fdlat)*(1-fdlon)*r15 + fdlat*(1-fdlon)*r35 +
1161 (1-fdlat)*fdlon*r16 + fdlat*fdlon*r36;
1209 const double dang = 1e-5;
1213 r15, r35, r36, r16, lat, lon );
1218 double x, y, z,
dx, dy, dz;
1219 poslos2cart( x, y, z,
dx, dy, dz, r0, lat, lon, 90, aa );
1222 const double l = r0 *
DEG2RAD * dang;
1226 double r2, lat2, lon2, za2, aa2;
1227 cart2poslos( r2, lat2, lon2, za2, aa2, x+
dx*l, y+dy*l, z+dz*l,
dx, dy, dz );
1229 r2 =
rsurf_at_latlon( lat1, lat3, lon5, lon6, r15, r35, r36, r16, lat2,lon2);
1232 return ( r2 - r0 ) / dang;
1283 lat =
interp( itw, lat_grid, gp_lat );
1285 lon =
interp( itw, lon_grid, gp_lon );
1288 const double lat1 = lat_grid[ilat];
1289 const double lat3 = lat_grid[ilat+1];
1290 const double lon5 = lon_grid[ilon];
1291 const double lon6 = lon_grid[ilon+1];
1292 const double r15 = r_geoid(ilat,ilon) + z_surf(ilat,ilon);
1293 const double r35 = r_geoid(ilat+1,ilon) + z_surf(ilat+1,ilon);
1294 const double r36 = r_geoid(ilat+1,ilon+1) + z_surf(ilat+1,ilon+1);
1295 const double r16 = r_geoid(ilat,ilon+1) + z_surf(ilat,ilon+1);
1349 const Index& atmosphere_dim,
1358 if( atmosphere_dim == 1 )
1360 else if( atmosphere_dim == 2 )
1363 z_surface(
joker,0), gp_lat, los[0] );
1372 z_surface, gp_lat, gp_lon, los[1] );
1374 const Numeric rv_surface =
interp( itw, r_geoid, gp_lat, gp_lon ) +
1375 interp( itw, z_surface, gp_lat, gp_lon );
1404 const double& tilt )
1406 assert(
abs(za) <= 180 );
1409 if( za > (90-tilt) || za < (-90-tilt) )
1468 assert(
abs(za) <= 180 );
1470 const double no_crossing = 999;
1478 {
return no_crossing; }
1485 {
return no_crossing; }
1492 {
return no_crossing; }
1498 if( ( rp < r0 &&
abs(za) <= 90 ) ||
1499 ( rp > r0 &&
abs(za) > 90 && r0 >= ppc ) )
1502 {
return no_crossing; }
1517 const double cv = cos(
beta );
1518 const double sv = sin(
beta );
1528 p[0] = ( r0 - rp ) * sv;
1529 p[1] = r0 * cv + c * sv;
1530 p[2] = -r0 * sv / 2 + c * cv;
1531 p[3] = -r0 * cv / 6 - c * sv / 2;
1540 double dlat = no_crossing /
RAD2DEG;
1542 for(
Index i=0; i<4; i++ )
1544 if( roots(i,1) == 0 && roots(i,0) >
dmin && roots(i,0) < dlat )
1545 { dlat = roots(i,0); }
1549 if( dlat < no_crossing && za < 0 )
1604 const double r_surf,
1605 const double r_start,
1606 const double lat_start,
1607 const double lon_start,
1608 const double za_start,
1616 assert( za_start >= 0 );
1617 assert( za_start <= 180 );
1626 if( ( za_start <
ANGTOL && r_start < r_surf ) ||
1627 ( za_start > 180-
ANGTOL && r_start > r_surf ) )
1632 l =
abs( r_surf - r_start );
1637 const double p = x*
dx + y*dy + z*dz;
1638 const double pp = p * p;
1639 const double q = x*x + y*y + z*z - r_surf*r_surf;
1641 const double l1 = -p + sqrt( pp -
q );
1642 const double l2 = -p - sqrt( pp -
q );
1644 if( l1 < 0 && l2 > 0 )
1646 else if( l1 > 0 && l2 < 0 )
1656 lat =
RAD2DEG * asin( ( y+dy*l ) / r );
1657 lon =
RAD2DEG * atan2( z+dz*l, x+
dx*l );
1704 const double& r_start0,
1705 const double& lat_start,
1706 const double& za_start,
1711 const double& rsurface )
1713 double r_start = r_start0;
1716 assert( r_start >= ra -
RTOL );
1717 assert( r_start <= rb +
RTOL );
1722 else if( r_start > rb )
1735 if( za_start <= 90 )
1744 if( ( ra > rsurface ) && ( ra > ppc ) )
1749 else if( ppc >= rsurface )
1766 za_start, r_end, lmax );
1770 { za_v[za_v.
nelem()-1] = 90; }
1832 const double& r_start0,
1833 const double& lat_start,
1834 const double& za_start,
1843 const double& rsurface1,
1844 const double& rsurface3 )
1846 double r_start = r_start0;
1849 assert( lat_start >= lat1 );
1850 assert( lat_start <= lat3 );
1855 const double csurface =
plevel_slope_2d( lat1, lat3, rsurface1, rsurface3 );
1858 const double dlat_left = lat_start - lat1;
1861 const double rlow = r1a + c2*dlat_left;
1862 const double rupp = r1b + c4*dlat_left;
1865 double dlat_endface;
1867 { dlat_endface = lat3 - lat_start; }
1869 { dlat_endface = -dlat_left; }
1872 assert( r_start >= rlow -
RTOL );
1873 assert( r_start <= rupp +
RTOL );
1876 if( r_start < rlow )
1878 else if( r_start > rupp )
1886 double dlat2end = 999;
1887 double abs_za_start =
abs( za_start );
1896 if( r_start > rlow &&
abs(za_start) >
ANGTOL )
1908 if( rsurface1 >= r1a || rsurface3 >= r3a )
1910 double r_surface = rsurface1 + csurface * dlat_left;
1912 assert( r_start >= r_surface );
1916 if(
abs(dlat2surface) <=
abs(dlat2end) )
1918 dlat2end = dlat2surface;
1930 if(
abs(dlat2end) >
abs(dlat_endface) && abs_za_start < 180-
ANGTOL )
1938 if(
abs(dlattry) <
abs(dlat2end) )
1946 if(
abs(dlat2end) >
abs(dlat_endface) )
1948 dlat2end = dlat_endface;
1958 if( abs_za_start > 90 && ( abs_za_start -
abs(dlat2end) ) <= 90 )
1963 if( ( abs_za_start - 90 ) <
abs( dlat2end ) )
1966 dlat2end =
sign(za_start) * ( abs_za_start - 90 );
1981 else if( endface == 1 )
1983 else if( endface == 2 )
1984 { r_end = r1a + c2 * ( dlat_left + dlat2end ); }
1985 else if( endface == 3 )
1987 else if( endface == 4 )
1988 { r_end = r1b + c4 * ( dlat_left + dlat2end ); }
1989 else if( endface == 7 )
1990 { r_end = rsurface1 + csurface * ( dlat_left + dlat2end ); }
1995 za_start, r_end, lmax );
2001 { za_v[za_v.
nelem()-1] = 90; }
2003 { za_v[za_v.
nelem()-1] = -90; }
2007 { lat_v[lat_v.
nelem()-1] = lat1; }
2008 else if( endface == 3 )
2009 { lat_v[lat_v.
nelem()-1] = lat3; }
2011 { lat_v[lat_v.
nelem()-1] = lat_start + dlat2end; }
2078 const double& r_start0,
2079 const double& lat_start0,
2080 const double& lon_start0,
2081 const double& za_start,
2082 const double& aa_start,
2097 const double& rsurface15,
2098 const double& rsurface35,
2099 const double& rsurface36,
2100 const double& rsurface16 )
2102 double r_start = r_start0;
2103 double lat_start = lat_start0;
2104 double lon_start = lon_start0;
2107 assert( lat_start >= lat1 -
LATLONTOL );
2108 assert( lat_start <= lat3 +
LATLONTOL );
2109 assert( !(
abs( lat_start) < 90 && lon_start < lon5 -
LATLONTOL ) );
2110 assert( !(
abs( lat_start) < 90 && lon_start > lon6 +
LATLONTOL ) );
2113 if( lat_start < lat1 )
2114 { lat_start = lat1; }
2115 else if( lat_start > lat3 )
2116 { lat_start = lat3; }
2117 if( lon_start < lon5 )
2118 { lon_start = lon5; }
2119 else if( lon_start > lon6 )
2120 { lon_start = lon6; }
2124 r15a, r35a, r36a, r16a, lat_start, lon_start );
2126 r15b, r35b, r36b, r16b, lat_start, lon_start );
2129 assert( r_start >= rlow -
RTOL );
2130 assert( r_start <= rupp +
RTOL );
2133 if( r_start < rlow )
2135 else if( r_start > rupp )
2139 double x, y, z,
dx, dy, dz;
2140 poslos2cart( x, y, z,
dx, dy, dz, r_start, lat_start, lon_start,
2141 za_start, aa_start );
2148 double r_end, lat_end, lon_end, l_end;
2157 lat_end = lat_start;
2158 lon_end = lon_start;
2159 l_end = rupp - r_start;
2164 else if( za_start > 180-
ANGTOL )
2167 rsurface15, rsurface35, rsurface36, rsurface16,
2168 lat_start, lon_start );
2170 if( rlow > rsurface )
2180 lat_end = lat_start;
2181 lon_end = lon_start;
2182 l_end = r_start - r_end;
2191 double r_corr, lat_corr, lon_corr;
2193 cart2sph( r_corr, lat_corr, lon_corr, x, y, z );
2196 lat_corr -= lat_start;
2197 lon_corr -= lon_start;
2210 double l_acc = 1e-3;
2211 double l_in = 0, l_out = l_end;
2212 bool ready =
false, startup =
true;
2213 double abs_aa =
abs( aa_start );
2215 double l_tan = 99e6;
2217 { l_tan = sqrt( r_start*r_start - ppc*ppc ); }
2219 bool do_surface =
false;
2220 if( rsurface15+
RTOL >= r15a || rsurface35+
RTOL >= r35a ||
2221 rsurface36+
RTOL >= r36a || rsurface16+
RTOL >= r16a )
2222 { do_surface =
true; }
2228 x+
dx*l_end, y+dy*l_end, z+dz*l_end );
2230 lat_end -= lat_corr;
2231 lon_end -= lon_corr;
2235 if(
abs( lat_start ) < 90 && (
abs(aa_start) <
ANGTOL ||
2237 { lon_end = lon_start; }
2242 if( lat_start == 0 )
2244 else if( lat_start > 0 && lat_end > lat_start )
2245 { lat_end = lat_start; }
2246 else if( lat_start < 0 && lat_end < lat_start )
2247 { lat_end = lat_start; }
2253 r15a, r35a, r36a, r16a, lat_end, lon_end );
2255 r15b, r35b, r36b, r16b, lat_end, lon_end );
2259 const double r_surface =
2261 rsurface15, rsurface35, rsurface36, rsurface16,
2264 if( r_surface+
RTOL >= rlow && r_end <= r_surface+
RTOL )
2265 { inside =
false; endface = 7; }
2270 if( lat_end < lat1 )
2271 { inside =
false; endface = 1; }
2272 else if( lat_end > lat3 )
2273 { inside =
false; endface = 3; }
2274 else if( lon_end < lon5 )
2275 { inside =
false; endface = 5; }
2276 else if( lon_end > lon6 )
2277 { inside =
false; endface = 6; }
2278 else if( r_end < rlow )
2279 { inside =
false; endface = 2; }
2280 else if( r_end > rupp )
2281 { inside =
false; endface = 4; }
2288 if( l_end < l_tan && l_end*10 > l_tan )
2296 l_end = ( l_out + l_in ) / 2;
2307 if( ( l_out - l_in ) < l_acc )
2310 { l_end = ( l_out + l_in ) / 2; }
2318 lat_end += lat_corr;
2319 lon_end += lon_corr;
2326 else if( endface == 2 )
2328 r16a, lat_end, lon_end ); }
2329 else if( endface == 3 )
2331 else if( endface == 4 )
2333 r16b, lat_end, lon_end ); }
2334 else if( endface == 5 )
2336 else if( endface == 6 )
2338 else if( endface == 7 )
2340 rsurface35, rsurface36, rsurface16, lat_end, lon_end ); }
2349 r_start, lat_start, lon_start,
2350 za_start, aa_start, ppc );
2355 else if( l_tan == l_end )
2366 n =
Index( ceil(
abs( l_end / lmax ) ) );
2378 lat_v[0] = lat_start;
2379 lon_v[0] = lon_start;
2383 double ldouble = l_end / (double)n;
2386 for(
Index j=1; j<=n; j++ )
2388 const double l = ldouble * (double)j;
2394 cart2poslos( r_v[j], lat_v[j], lon_v[j], za_v[j], aa_v[j],
2395 x+
dx*l, y+dy*l, z+dz*l,
dx, dy, dz );
2397 double rtmp, lattmp, lontmp, zatmp, aatmp;
2399 x+
dx*l, y+dy*l, z+dz*l,
dx, dy, dz );
2415 if( za_start < ANGTOL || za_start > 180-
ANGTOL )
2416 { za_v[n] = za_start; }
2424 if(
abs( lat_start ) < 90 &&
2428 lon_v[n] = lon_start;
2432 for(
Index j=1; j<n; j++ )
2463 const Index& atmosphere_dim,
2466 assert( atmosphere_dim >= 1 );
2467 assert( atmosphere_dim <= 3 );
2469 ppath.
dim = atmosphere_dim;
2472 if( atmosphere_dim < 3 )
2481 ppath.
gp_lon.resize( np );
2483 ppath.
gp_p.resize( np );
2484 if( atmosphere_dim >= 2 )
2485 { ppath.
gp_lat.resize( np ); }
2521 const Index& case_nr )
2542 os <<
"Case number " << case_nr <<
" is not defined.";
2543 throw runtime_error(os.str());
2569 else if( ppath.
background ==
"cloud box level" )
2571 else if( ppath.
background ==
"cloud box interior" )
2577 <<
" is not a valid background case.";
2578 throw runtime_error(os.str());
2600 const Ppath& ppath2 )
2602 assert( ppath1.
np >= ppath2.
np );
2612 ppath1.
z[
Range(0,ppath2.
np)] = ppath2.
z;
2615 for(
Index i=0; i<ppath2.
np; i++ )
2619 if( ppath1.
dim >= 2 )
2622 if( ppath1.
dim == 3 )
2654 const Ppath& ppath2 )
2668 for(
Index i=1; i<n2; i++ )
2672 ppath1.
pos(i1,0) = ppath2.
pos(i,0);
2673 ppath1.
pos(i1,1) = ppath2.
pos(i,1);
2674 ppath1.
los(i1,0) = ppath2.
los(i,0);
2675 ppath1.
z[i1] = ppath2.
z[i];
2678 if( ppath1.
dim >= 2 )
2681 if( ppath1.
dim == 3 )
2683 ppath1.
pos(i1,2) = ppath2.
pos(i,2);
2684 ppath1.
los(i1,1) = ppath2.
los(i,1);
2728 const double& r_geoid,
2733 const double r1 = r_geoid + z_field[ip];
2734 const double dr = z_field[ip+1] - z_field[ip];
2738 ppath.
pos(i,0) = r[i];
2739 ppath.
pos(i,1) = lat[i];
2740 ppath.
los(i,0) = za[i];
2742 ppath.
gp_p[i].idx = ip;
2743 ppath.
gp_p[i].fd[0] = ( r[i] - r1 ) / dr;
2744 ppath.
gp_p[i].fd[1] = 1 - ppath.
gp_p[i].fd[0];
2747 ppath.
z[i] = r[i] - r_geoid;
2750 { ppath.
l_step[i-1] = lstep[i-1]; }
2787 const double& lstep,
2795 const double dlat = lat_grid[ilat+1] - lat_grid[ilat];
2796 const double r1low = r_geoid[ilat] + z_field(ip,ilat);
2797 const double drlow = r_geoid[ilat+1] + z_field(ip,ilat+1) -r1low;
2798 const double r1upp = r_geoid[ilat] + z_field(ip+1,ilat);
2799 const double drupp = r_geoid[ilat+1] + z_field(ip+1,ilat+1) - r1upp;
2800 const double z1low = z_field(ip,ilat);
2801 const double dzlow = z_field(ip,ilat+1) -z1low;
2802 const double z1upp = z_field(ip+1,ilat);
2803 const double dzupp = z_field(ip+1,ilat+1) - z1upp;
2807 ppath.
pos(i,0) = r[i];
2808 ppath.
pos(i,1) = lat[i];
2809 ppath.
los(i,0) = za[i];
2812 double w = ( lat[i] - lat_grid[ilat] ) / dlat;
2815 const double rlow = r1low + w * drlow;
2816 const double rupp = r1upp + w * drupp;
2819 const double zlow = z1low + w * dzlow;
2820 const double zupp = z1upp + w * dzupp;
2822 ppath.
gp_p[i].idx = ip;
2823 ppath.
gp_p[i].fd[0] = ( r[i] - rlow ) / ( rupp - rlow );
2824 ppath.
gp_p[i].fd[1] = 1 - ppath.
gp_p[i].fd[0];
2827 ppath.
z[i] = zlow + ppath.
gp_p[i].fd[0] * ( zupp -zlow );
2829 ppath.
gp_lat[i].idx = ilat;
2830 ppath.
gp_lat[i].fd[0] = ( lat[i] - lat_grid[ilat] ) / dlat;
2835 { ppath.
l_step[i-1] = lstep; }
2878 const double& lstep,
2888 const double lat1 = lat_grid[ilat];
2889 const double lat3 = lat_grid[ilat+1];
2890 const double lon5 = lon_grid[ilon];
2891 const double lon6 = lon_grid[ilon+1];
2892 const double r15a = r_geoid(ilat,ilon) + z_field(ip,ilat,ilon);
2893 const double r35a = r_geoid(ilat+1,ilon) + z_field(ip,ilat+1,ilon);
2894 const double r36a = r_geoid(ilat+1,ilon+1) + z_field(ip,ilat+1,ilon+1);
2895 const double r16a = r_geoid(ilat,ilon+1) + z_field(ip,ilat,ilon+1);
2896 const double r15b = r_geoid(ilat,ilon) + z_field(ip+1,ilat,ilon);
2897 const double r35b = r_geoid(ilat+1,ilon) + z_field(ip+1,ilat+1,ilon);
2898 const double r36b = r_geoid(ilat+1,ilon+1) + z_field(ip+1,ilat+1,ilon+1);
2899 const double r16b = r_geoid(ilat,ilon+1) + z_field(ip+1,ilat,ilon+1);
2900 const double rg15 = r_geoid(ilat,ilon);
2901 const double rg35 = r_geoid(ilat+1,ilon);
2902 const double rg36 = r_geoid(ilat+1,ilon+1);
2903 const double rg16 = r_geoid(ilat,ilon+1);
2904 const double dlat = lat3 - lat1;
2905 const double dlon = lon6 - lon5;
2911 r15a, r35a, r36a, r16a, lat[i], lon[i] );
2913 r15b, r35b, r36b, r16b, lat[i], lon[i] );
2916 ppath.
pos(i,0) = r[i];
2917 ppath.
pos(i,1) = lat[i];
2918 ppath.
pos(i,2) = lon[i];
2919 ppath.
los(i,0) = za[i];
2920 ppath.
los(i,1) = aa[i];
2923 ppath.
gp_p[i].idx = ip;
2924 ppath.
gp_p[i].fd[0] = ( ppath.
pos(i,0) - rlow ) / ( rupp - rlow );
2925 ppath.
gp_p[i].fd[1] = 1 - ppath.
gp_p[i].fd[0];
2930 rg15, rg35, rg36, rg16, lat[i], lon[i] );
2931 const double zlow = rlow - rgeoid;
2932 const double zupp = rupp - rgeoid;
2934 ppath.
z[i] = zlow + ppath.
gp_p[i].fd[0] * ( zupp -zlow );
2937 ppath.
gp_lat[i].idx = ilat;
2938 ppath.
gp_lat[i].fd[0] = ( lat[i] - lat1 ) / dlat;
2947 if(
abs( lat[i] ) < 90 )
2949 ppath.
gp_lon[i].idx = ilon;
2950 ppath.
gp_lon[i].fd[0] = ( lon[i] - lon5 ) / dlon;
2957 ppath.
gp_lon[i].fd[0] = 0;
2958 ppath.
gp_lon[i].fd[1] = 1;
2962 { ppath.
l_step[i-1] = lstep; }
2991 const double& refr_index )
2994 assert(
abs(za) <= 180 );
2996 return r * refr_index * sin(
DEG2RAD *
abs(za) );
3028 const Ppath& ppath )
3031 const Index imax = ppath.
np - 1;
3034 r_start = ppath.
pos(imax,0);
3035 lat_start = ppath.
pos(imax,1);
3036 za_start = ppath.
los(imax,0);
3063 const double& lstep,
3065 const double& r_geoid,
3067 const Index& endface,
3068 const Index& tanpoint,
3094 ppath.
tan_pos[1] = lat_v[np-1];
3140 const Index imax = ppath.
np - 1;
3143 r_start = ppath.
pos(imax,0);
3144 lat_start = ppath.
pos(imax,1);
3145 za_start = ppath.
los(imax,0);
3152 lat1 = lat_grid[ilat];
3153 lat3 = lat_grid[ilat+1];
3163 r1a = r_geoid[ilat] + z_field(ip,ilat);
3164 r3a = r_geoid[ilat+1] + z_field(ip,ilat+1);
3165 r3b = r_geoid[ilat+1] + z_field(ip+1,ilat+1);
3166 r1b = r_geoid[ilat] + z_field(ip+1,ilat);
3172 const double rlow =
rsurf_at_lat( lat1, lat3, r1a, r3a, lat_start );
3173 const double rupp =
rsurf_at_lat( lat1, lat3, r1b, r3b, lat_start );
3194 r1b = r1a; r3b = r3a; c4 = c2;
3195 r1a = r_geoid[ilat] + z_field(ip,ilat);
3196 r3a = r_geoid[ilat+1] + z_field(ip,ilat+1);
3207 r1a = r1b; r3a = r3b; c2 = c4;
3208 r3b = r_geoid[ilat+1] + z_field(ip+1,ilat+1);
3209 r1b = r_geoid[ilat] + z_field(ip+1,ilat);
3215 rsurface1 = r_geoid[ilat] + z_surface[ilat];
3216 rsurface3 = r_geoid[ilat+1] + z_surface[ilat+1];
3238 const double& lstep,
3244 const Index& endface,
3245 const Index& tanpoint,
3250 const Index imax = np-1;
3258 ppath_fill_2d( ppath, r_v, lat_v, za_v, lstep, r_geoid, z_field, lat_grid,
3271 ppath.
tan_pos[1] = lat_v[np-1];
3276 if( endface == 1 || endface == 3 )
3278 else if( endface == 2 || endface == 4 )
3283 if( ppath.
gp_p[imax].fd[0] < 0 || ppath.
gp_p[imax].fd[1] < 0 )
3287 if( ppath.
gp_lat[imax].fd[0] < 0 || ppath.
gp_lat[imax].fd[1] < 0 )
3340 const Index imax = ppath.
np - 1;
3343 r_start = ppath.
pos(imax,0);
3344 lat_start = ppath.
pos(imax,1);
3345 lon_start = ppath.
pos(imax,2);
3346 za_start = ppath.
los(imax,0);
3347 aa_start = ppath.
los(imax,1);
3358 if( lat_start == 90 )
3362 gridpos( gp_tmp, lon_grid, aa_start );
3363 if( aa_start < 180 )
3368 else if( lat_start == -90 )
3372 gridpos( gp_tmp, lon_grid, aa_start );
3373 if( aa_start < 180 )
3384 if( lon_start < lon_grid[nlon-1] )
3387 { ilon = nlon - 2; }
3390 lat1 = lat_grid[ilat];
3391 lat3 = lat_grid[ilat+1];
3392 lon5 = lon_grid[ilon];
3393 lon6 = lon_grid[ilon+1];
3403 r15a = r_geoid(ilat,ilon) + z_field(ip,ilat,ilon);
3404 r35a = r_geoid(ilat+1,ilon) + z_field(ip,ilat+1,ilon);
3405 r36a = r_geoid(ilat+1,ilon+1) + z_field(ip,ilat+1,ilon+1);
3406 r16a = r_geoid(ilat,ilon+1) + z_field(ip,ilat,ilon+1);
3407 r15b = r_geoid(ilat,ilon) + z_field(ip+1,ilat,ilon);
3408 r35b = r_geoid(ilat+1,ilon) + z_field(ip+1,ilat+1,ilon);
3409 r36b = r_geoid(ilat+1,ilon+1) + z_field(ip+1,ilat+1,ilon+1);
3410 r16b = r_geoid(ilat,ilon+1) + z_field(ip+1,ilat,ilon+1);
3417 if( fabs(za_start-90) <=
PTILTMAX )
3423 r15a, r35a, r36a, r16a, lat_start, lon_start, aa_start );
3434 r15b = r15a; r35b = r35a; r36b = r36a; r16b = r16a;
3435 r15a = r_geoid(ilat,ilon) + z_field(ip,ilat,ilon);
3436 r35a = r_geoid(ilat+1,ilon) + z_field(ip,ilat+1,ilon);
3437 r36a = r_geoid(ilat+1,ilon+1) + z_field(ip,ilat+1,ilon+1);
3438 r16a = r_geoid(ilat,ilon+1) + z_field(ip,ilat,ilon+1);
3445 r15b, r35b, r36b, r16b, lat_start, lon_start, aa_start );
3451 r15a = r15b; r35a = r35b; r36a = r36b; r16a = r16b;
3452 r15b = r_geoid(ilat,ilon) + z_field(ip+1,ilat,ilon);
3453 r35b = r_geoid(ilat+1,ilon) + z_field(ip+1,ilat+1,ilon);
3454 r36b = r_geoid(ilat+1,ilon+1) + z_field(ip+1,ilat+1,ilon+1);
3455 r16b = r_geoid(ilat,ilon+1) + z_field(ip+1,ilat,ilon+1);
3461 rsurface15 = r_geoid(ilat,ilon) + z_surface(ilat,ilon);
3462 rsurface35 = r_geoid(ilat+1,ilon) + z_surface(ilat+1,ilon);
3463 rsurface36 = r_geoid(ilat+1,ilon+1) + z_surface(ilat+1,ilon+1);
3464 rsurface16 = r_geoid(ilat,ilon+1) + z_surface(ilat,ilon+1);
3488 const double& lstep,
3496 const Index& endface,
3497 const Index& tanpoint,
3502 const Index imax = np-1;
3511 r_geoid, z_field, lat_grid, lon_grid, ip, ilat, ilon );
3514 assert( ppath.
gp_p[imax].fd[0] > -0.01 );
3515 assert( ppath.
gp_p[imax].fd[0] < 1.01 );
3516 assert( ppath.
gp_lat[imax].fd[0] > -0.01 );
3517 assert( ppath.
gp_lat[imax].fd[0] < 1.01 );
3518 assert( ppath.
gp_lon[imax].fd[0] > -0.01 );
3519 assert( ppath.
gp_lon[imax].fd[0] < 1.01 );
3528 ppath.
tan_pos[1] = lat_v[imax];
3529 ppath.
tan_pos[2] = lon_v[imax];
3534 if( endface == 1 || endface == 3 )
3536 else if( endface == 2 || endface == 4 )
3538 else if( endface == 5 || endface == 6 )
3543 if( ppath.
gp_p[imax].fd[0] < 0 || ppath.
gp_p[imax].fd[1] < 0 )
3547 if( ppath.
gp_lat[imax].fd[0] < 0 || ppath.
gp_lat[imax].fd[1] < 0 )
3551 if( ppath.
gp_lon[imax].fd[0] < 0 || ppath.
gp_lon[imax].fd[1] < 0 )
3585 const double& lmax )
3593 double ltotsum = l_rt.
sum();
3596 { n =
max (
Index( ceil( ltotsum / lmax ) ) + 1,
Index(2)); }
3604 r_v[0] = r_rt[0]; r_v[1] = r_rt[nrt-1];
3605 za_v[0] = za_rt[0]; za_v[1] = za_rt[nrt-1];
3606 lat_v[0] = lat_rt[0]; lat_v[1] = lat_rt[nrt-1];
3608 if( lon_rt.
nelem() > 0 )
3610 lon_v.
resize(n); lon_v[0] = lon_rt[0]; lon_v[1] = lon_rt[nrt-1];
3611 aa_v.
resize(n); aa_v[0] = aa_rt[0]; aa_v[1] = aa_rt[nrt-1];
3616 Vector lsum(nrt), llin(n);
3621 for(
Index i=1; i<nrt; i++ )
3622 { lsum[i] = lsum[i-1] + l_rt[i-1]; }
3630 interp( r_v, itw, r_rt, gp );
3631 interp( za_v, itw, za_rt, gp );
3632 interp( lat_v, itw, lat_rt, gp );
3633 lstep = llin[1] - llin[0];
3635 if( lon_rt.
nelem() > 0 )
3664 const Index& reversed,
3665 const double& lmax )
3672 Vector r_rt(nrt), lat_rt(nrt), za_rt(nrt), l_rt(nrt-1);
3676 for(
Index i=0; i<nrt; i++ )
3678 r_rt[i] = r_array[i];
3679 lat_rt[i] = lat_array[i];
3680 za_rt[i] = za_array[i];
3682 { l_rt[i] = l_array[i]; }
3687 for(
Index i=0; i<nrt; i++ )
3689 const Index i1 = nrt - 1 - i;
3690 r_rt[i] = r_array[i1];
3691 lat_rt[i] = lat_array[0]+ lat_array[nrt-1] - lat_array[i1];
3692 za_rt[i] = 180 - za_array[i1];
3694 { l_rt[i] = l_array[i1-1]; }
3704 r_rt, lat_rt,
Vector(0), za_rt,
Vector(0), l_rt, lmax );
3730 const double& lmax )
3737 Vector r_rt(nrt), lat_rt(nrt), lon_rt(nrt);
3738 Vector za_rt(nrt), aa_rt(nrt),l_rt(nrt-1);
3740 for(
Index i=0; i<nrt; i++ )
3742 r_rt[i] = r_array[i];
3743 lat_rt[i] = lat_array[i];
3744 lon_rt[i] = lon_array[i];
3745 za_rt[i] = za_array[i];
3746 aa_rt[i] = aa_array[i];
3748 { l_rt[i] = l_array[i]; }
3755 r_rt, lat_rt, lon_rt, za_rt, aa_rt, l_rt, lmax );
3795 const double& r_geoid,
3796 const double& z_surface,
3797 const double& lmax )
3800 double r_start, lat_start, za_start;
3824 Index endface, tanpoint;
3827 r_start, lat_start, za_start, ppc, lmax,
3828 r_geoid+z_field[ip], r_geoid+z_field[ip+1], r_geoid+z_surface );
3833 ppath_end_1d( ppath, r_v, lat_v, za_v, lstep, z_field, r_geoid, ip, endface,
3838 if( endface == 0 && tanpoint )
3878 const double& lmax )
3881 double r_start, lat_start, za_start;
3887 double lat1, lat3, r1a, r3a, r3b, r1b, rsurface1, rsurface3;
3891 lat1, lat3, r1a, r3a, r3b, r1b, rsurface1, rsurface3,
3892 ppath, lat_grid, z_field, r_geoid, z_surface );
3906 Index endface, tanpoint;
3909 r_start, lat_start, za_start, ppc, lmax, lat1, lat3,
3910 r1a, r3a, r3b, r1b, rsurface1, rsurface3 );
3914 ppath_end_2d( ppath, r_v, lat_v, za_v, lstep, lat_grid, z_field, r_geoid,
3915 ip, ilat, endface, tanpoint, ppc );
3920 if( endface == 0 && tanpoint )
3928 r_geoid, z_surface, lmax );
3964 const double& lmax )
3967 double r_start, lat_start, lon_start, za_start, aa_start;
3970 Index ip, ilat, ilon;
3974 double lat1, lat3, lon5, lon6;
3975 double r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b;
3976 double rsurface15, rsurface35, rsurface36, rsurface16;
3979 ppath_start_3d( r_start, lat_start, lon_start, za_start, aa_start,
3980 ip, ilat, ilon, lat1, lat3, lon5, lon6,
3981 r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b,
3982 rsurface15, rsurface35, rsurface36, rsurface16,
3983 ppath, lat_grid, lon_grid, z_field, r_geoid, z_surface );
3996 Vector r_v, lat_v, lon_v, za_v, aa_v;
3998 Index endface, tanpoint;
4000 do_gridcell_3d( r_v, lat_v, lon_v, za_v, aa_v, lstep, endface, tanpoint,
4001 r_start, lat_start, lon_start, za_start, aa_start, ppc, lmax,
4002 lat1, lat3, lon5, lon6,
4003 r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b,
4004 rsurface15, rsurface35, rsurface36, rsurface16 );
4008 ppath_end_3d( ppath, r_v, lat_v, lon_v, za_v, aa_v, lstep, lat_grid,
4009 lon_grid, z_field, r_geoid, ip, ilat, ilon, endface, tanpoint, ppc );
4014 if( endface == 0 && tanpoint )
4022 r_geoid, z_surface, lmax );
4105 const Agenda& refr_index_agenda,
4107 const double& lraytrace,
4110 const double& r_surface,
4111 const double& r_geoid,
4122 double lstep, dlat = 9999;
4130 do_gridrange_1d( r_v, lat_v, za_v, lstep, endface, tanpoint, r, lat, za,
4131 ppc_step, -1, r1, r3, r_surface );
4133 assert( r_v.
nelem() == 2 );
4142 if( lstep <= 1.01 * lraytrace )
4145 dlat = lat_v[1] - lat;
4152 { lstep = lraytrace; }
4154 { lstep = -lraytrace; }
4159 dlat =
RAD2DEG * acos( ( r_new*r_new + r*r -
4160 lstep*lstep ) / ( 2 * r_new*r ) );
4163 lstep =
abs( lstep );
4170 rte_vmr_list, refr_index_agenda,
4171 p_grid, r_geoid, z_field, t_field, vmr_field, r );
4173 const double ppc_local = ppc / refr_index;
4175 if( ready && tanpoint )
4177 else if( r >= ppc_local )
4193 r_array.push_back( r );
4194 lat_array.push_back( lat );
4195 za_array.push_back( za );
4196 l_array.push_back( lstep );
4272 const Agenda& refr_index_agenda,
4273 const double& lraytrace,
4280 const double& rsurface1,
4281 const double& rsurface3,
4294 double lstep, dlat = 9999, r_new, lat_new;
4303 r, lat, za, ppc_step, -1, lat1, lat3, r1a, r3a, r3b, r1b,
4304 rsurface1, rsurface3 );
4306 assert( r_v.
nelem() == 2 );
4315 if( lstep <= 1.01 * lraytrace )
4318 dlat = lat_v[1] - lat;
4325 { lstep = lraytrace; }
4327 { lstep = -lraytrace; }
4331 dlat =
RAD2DEG * acos( ( r_new*r_new + r*r -
4332 lstep*lstep ) / ( 2 * r_new*r ) );
4336 lat_new = lat + dlat;
4337 lstep =
abs( lstep );
4341 if( lat_new < lat1 )
4343 else if( lat_new > lat3 )
4348 if( ready && tanpoint )
4359 const double za_rad =
DEG2RAD * za;
4362 rte_temperature, rte_vmr_list, refr_index_agenda,
4363 p_grid, lat_grid, r_geoid, z_field, t_field,
4364 vmr_field, r, lat );
4366 za += -dlat +
RAD2DEG * lstep / refr_index * ( -sin(za_rad) * dndr +
4367 cos(za_rad) * dndlat );
4381 if( lat == lat1 && za < 0 )
4382 { endface = 1; ready = 1; }
4383 else if( lat == lat3 && za > 0 )
4384 { endface = 3; ready = 1; }
4387 r_array.push_back( r );
4388 lat_array.push_back( lat );
4389 za_array.push_back( za );
4390 l_array.push_back( lstep );
4484 const Agenda& refr_index_agenda,
4485 const double& lraytrace,
4498 const double& rsurface15,
4499 const double& rsurface35,
4500 const double& rsurface36,
4501 const double& rsurface16,
4514 Vector r_v, lat_v, lon_v, za_v, aa_v;
4515 double r_new, lat_new, lon_new, za_new, aa_new;
4524 do_gridcell_3d( r_v, lat_v, lon_v, za_v, aa_v, lstep, endface, tanpoint,
4525 r, lat, lon, za, aa, ppc_step, -1, lat1, lat3, lon5, lon6,
4526 r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b,
4527 rsurface15, rsurface35, rsurface36, rsurface16 );
4529 assert( r_v.
nelem() == 2 );
4538 if( lstep <= 1.01 * lraytrace )
4550 double x, y, z,
dx, dy, dz;
4551 poslos2cart( x, y, z,
dx, dy, dz, r, lat, lon, za, aa );
4555 cart2poslos( r_new, lat_new, lon_new, za_new, aa_new,
4556 x+
dx*lstep, y+dy*lstep, z+dz*lstep,
dx, dy, dz );
4560 if( lat_new < lat1 )
4562 else if( lat_new > lat3 )
4564 if( lon_new < lon5 )
4566 else if( lon_new > lon6 )
4574 if( za < ANGTOL || za > 180-
ANGTOL )
4581 if(
abs( lat ) < 90 &&
4593 if( ready && tanpoint )
4606 refr_index, dndr, dndlat, dndlon, rte_pressure,
4607 rte_temperature, rte_vmr_list, refr_index_agenda,
4608 p_grid, lat_grid, lon_grid, r_geoid, z_field,
4609 t_field, vmr_field, r, lat, lon );
4611 const double aterm =
RAD2DEG * lstep / refr_index;
4612 const double za_rad =
DEG2RAD * za;
4613 const double aa_rad =
DEG2RAD * aa;
4614 const double sinza = sin( za_rad );
4615 const double sinaa = sin( aa_rad );
4616 const double cosaa = cos( aa_rad );
4619 if( za < ANGTOL || za > 180-
ANGTOL )
4621 za_new += aterm * ( cos(za_rad) *
4622 ( cosaa * dndlat + sinaa * dndlon ) );
4623 aa_new =
RAD2DEG * atan2( dndlon, dndlat);
4627 za_new += aterm * ( -sinza * dndr + cos(za_rad) *
4628 ( cosaa * dndlat + sinaa * dndlon ) );
4629 aa_new += aterm * sinza * ( cosaa * dndlon - sinaa * dndlat );
4634 { za_new = 180 - za_new; }
4635 else if( za_new < 0 )
4636 { za_new = -za_new; }
4640 else if( aa_new < -180 )
4653 if( lon == lon5 && aa < 0 )
4654 { endface = 5; ready = 1; }
4655 else if( lon == lon6 && aa > 0 )
4656 { endface = 6; ready = 1; }
4657 else if( za > 0 && za < 180 )
4659 if( lat == lat1 && lat != -90 &&
abs( aa ) > 90 )
4660 { endface = 1; ready = 1; }
4661 else if( lat == lat3 && lat != 90 &&
abs( aa ) < 90 )
4662 { endface = 3; ready = 1; }
4666 r_array.push_back( r );
4667 lat_array.push_back( lat );
4668 lon_array.push_back( lon );
4669 za_array.push_back( za );
4670 aa_array.push_back( aa );
4671 l_array.push_back( lstep );
4721 const Agenda& refr_index_agenda,
4726 const double& r_geoid,
4727 const double& z_surface,
4728 const String& rtrace_method,
4729 const double& lraytrace,
4730 const double& lmax )
4733 double r_start, lat_start, za_start;
4751 refr_index_agenda, p_grid, r_geoid, z_field,
4752 t_field, vmr_field, r_start );
4766 r_array.push_back( r_start );
4767 lat_array.push_back( lat_start );
4768 za_array.push_back( za_start );
4771 Index endface, tanpoint;
4773 if( rtrace_method ==
"linear_euler" )
4776 r_array, lat_array, za_array, l_array, endface,
4777 tanpoint, r_start, lat_start, za_start, rte_pressure, rte_temperature,
4778 rte_vmr_list, refr_index, refr_index_agenda, ppc, lraytrace,
4779 r_geoid+z_field[ip], r_geoid+z_field[ip+1], r_geoid + z_surface,
4780 r_geoid, p_grid, z_field, t_field, vmr_field );
4785 bool known_ray_trace_method =
false;
4786 assert( known_ray_trace_method );
4798 r_array, lat_array, za_array, l_array, 0, lmax );
4802 ppath_end_1d( ppath, r_v, lat_v, za_v, lstep, z_field, r_geoid, ip, endface,
4807 if( endface == 0 && tanpoint )
4816 ppath2, rte_pressure, rte_temperature, rte_vmr_list,
4817 refr_index, refr_index_agenda, p_grid, z_field, t_field,
4818 vmr_field, r_geoid, z_surface, rtrace_method, lraytrace, lmax );
4864 const Agenda& refr_index_agenda,
4872 const String& rtrace_method,
4873 const double& lraytrace,
4874 const double& lmax )
4877 double r_start, lat_start, za_start;
4883 double lat1, lat3, r1a, r3a, r3b, r1b, rsurface1, rsurface3;
4887 lat1, lat3, r1a, r3a, r3b, r1b, rsurface1, rsurface3,
4888 ppath, lat_grid, z_field, r_geoid, z_surface );
4899 r_array.push_back( r_start );
4900 lat_array.push_back( lat_start );
4901 za_array.push_back( za_start );
4904 Index endface, tanpoint;
4906 if( rtrace_method ==
"linear_euler" )
4909 r_array, lat_array, za_array, l_array, endface,
4910 tanpoint, r_start, lat_start, za_start, rte_pressure, rte_temperature,
4911 rte_vmr_list, refr_index, refr_index_agenda, lraytrace,
4912 lat1, lat3, r1a, r3a, r3b, r1b, rsurface1, rsurface3,
4913 p_grid, lat_grid, r_geoid, z_field, t_field, vmr_field );
4918 bool known_ray_trace_method =
false;
4919 assert( known_ray_trace_method );
4931 r_array, lat_array, za_array, l_array, 0, lmax );
4935 ppath_end_2d( ppath, r_v, lat_v, za_v, lstep, lat_grid, z_field, r_geoid,
4936 ip, ilat, endface, tanpoint, -1 );
4941 if( endface == 0 && tanpoint )
4949 ppath2, rte_pressure, rte_temperature, rte_vmr_list,
4950 refr_index, refr_index_agenda, p_grid, lat_grid, z_field,
4952 r_geoid, z_surface, rtrace_method, lraytrace, lmax );
4999 const Agenda& refr_index_agenda,
5008 const String& rtrace_method,
5009 const double& lraytrace,
5010 const double& lmax )
5013 double r_start, lat_start, lon_start, za_start, aa_start;
5016 Index ip, ilat, ilon;
5020 double lat1, lat3, lon5, lon6;
5021 double r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b;
5022 double rsurface15, rsurface35, rsurface36, rsurface16;
5025 ppath_start_3d( r_start, lat_start, lon_start, za_start, aa_start,
5026 ip, ilat, ilon, lat1, lat3, lon5, lon6,
5027 r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b,
5028 rsurface15, rsurface35, rsurface36, rsurface16,
5029 ppath, lat_grid, lon_grid, z_field, r_geoid, z_surface );
5037 Array<double> r_array, lat_array, lon_array, za_array, aa_array, l_array;
5040 r_array.push_back( r_start );
5041 lat_array.push_back( lat_start );
5042 lon_array.push_back( lon_start );
5043 za_array.push_back( za_start );
5044 aa_array.push_back( aa_start );
5047 Index endface, tanpoint;
5049 if( rtrace_method ==
"linear_euler" )
5052 aa_array, l_array, endface, tanpoint, r_start,
5053 lat_start, lon_start, za_start, aa_start,
5054 rte_pressure, rte_temperature, rte_vmr_list,
5055 refr_index, refr_index_agenda, lraytrace,
5056 lat1, lat3, lon5, lon6,
5057 r15a, r35a, r36a, r15a, r15b, r35b, r36b, r15b,
5058 rsurface15, rsurface35, rsurface36, rsurface16,
5059 p_grid, lat_grid, lon_grid,
5060 r_geoid, z_field, t_field, vmr_field );
5065 bool known_ray_trace_method =
false;
5066 assert( known_ray_trace_method );
5074 Vector r_v, lat_v, lon_v, za_v, aa_v;
5078 lstep, r_array, lat_array, lon_array,
5079 za_array, aa_array, l_array, lmax );
5083 ppath_end_3d( ppath, r_v, lat_v, lon_v, za_v, aa_v, lstep, lat_grid,
5084 lon_grid, z_field, r_geoid, ip, ilat, ilon, endface, tanpoint, -1 );
5089 if( endface == 0 && tanpoint )
5097 ppath2, rte_pressure, rte_temperature, rte_vmr_list,
5098 refr_index, refr_index_agenda, p_grid, lat_grid,
5099 lon_grid, z_field, t_field, vmr_field,
5100 r_geoid, z_surface, rtrace_method, lraytrace, lmax );
5165 const Index& atmosphere_dim,
5172 const Index& cloudbox_on,
5174 const bool& outside_cloudbox,
5194 if( atmosphere_dim == 1 )
5197 const double r_surface = r_geoid(0,0) + z_surface(0,0);
5200 const double r_top = r_geoid(0,0) + z_field(np-1,0,0);
5203 if( (rte_pos[0] +
RTOL) < r_surface )
5206 os <<
"The ppath starting point is placed "
5207 << (r_surface - rte_pos[0])/1e3 <<
" km below surface level.\n"
5208 <<
"This point must be above the surface.";
5209 throw runtime_error(os.str());
5212 out2 <<
" sensor altitude : " << (rte_pos[0]-r_geoid(0,0))/1e3
5217 if( rte_los[0] > 90 )
5219 geom_tan_pos.resize(2);
5222 out2 <<
" geom. tangent radius : " << geom_tan_pos[0]/1e3
5224 out2 <<
" geom. tangent latitude : " << geom_tan_pos[1] <<
"\n";
5225 out2 <<
" geom. tangent altitude : "
5226 << (geom_tan_pos[0]-r_geoid(0,0))/1e3 <<
" km\n";
5230 ppath.
pos(0,0) = rte_pos[0];
5231 ppath.
los(0,0) = rte_los[0];
5233 ppath.
z[0] = ppath.
pos(0,0) - r_geoid(0,0);
5237 if( rte_pos[0] < r_top )
5245 if( ppath.
pos(0,0) == r_surface && ppath.
los(0,0) > 90 )
5251 if( outside_cloudbox )
5254 if( ppath.
z[0] > z_field(cloudbox_limits[0],0,0) &&
5255 ppath.
z[0] < z_field(cloudbox_limits[1],0,0) )
5258 else if( ( ppath.
z[0] == z_field(cloudbox_limits[0],0,0) &&
5259 ppath.
los(0,0) <= 90 )
5261 ( ppath.
z[0] == z_field(cloudbox_limits[1],0,0) &&
5262 ppath.
los(0,0) > 90 ) )
5274 if( rte_los[0] <= 90 )
5277 out1 <<
" --- WARNING ---, path is totally outside of the "
5278 <<
"model atmosphere\n";
5289 out1 <<
" --- WARNING ---, path is totally outside of the "
5290 <<
"model atmosphere\n";
5296 ppath.
z[0] = z_field(np-1,0,0);
5297 ppath.
pos(0,0) = r_top;
5305 if( ppath.
z[0] == z_field(cloudbox_limits[1],0,0) )
5315 if( ppath.
z[0] <= z_field(np-1,0,0) )
5322 if( geom_tan_pos.nelem() == 2 )
5332 else if( atmosphere_dim == 2 )
5342 bool is_inside =
false;
5343 double rv_geoid=-1, rv_surface=-1;
5347 if( rte_pos[1] >= lat_grid[0] && rte_pos[1] <= lat_grid[nlat-1] )
5349 gridpos( gp_lat, lat_grid, rte_pos[1] );
5352 rv_geoid =
interp( itw, r_geoid(
joker,0), gp_lat );
5353 rv_surface = rv_geoid +
interp( itw, z_surface(
joker,0), gp_lat );
5355 out2 <<
" sensor altitude : " << (rte_pos[0]-rv_geoid)/1e3
5358 if( rte_pos[0] < ( rv_geoid +
5360 { is_inside =
true; }
5368 double geom_tan_z=-2, geom_tan_atmtop=-1;
5370 if(
abs(rte_los[0]) > 90 )
5374 if( rte_los[0] > 0 )
5380 out2 <<
" geom. tangent radius : " << geom_tan_pos[0] / 1e3
5382 out2 <<
" geom. tangent latitude : " << geom_tan_pos[1]
5385 if( geom_tan_pos[1] >= lat_grid[0] &&
5386 geom_tan_pos[1] <= lat_grid[nlat-1] )
5390 gridpos( gp_tan, lat_grid, geom_tan_pos[1] );
5392 geom_tan_z = geom_tan_pos[0] -
5396 out2 <<
" geom. tangent altitude : " << geom_tan_z/1e3
5402 ppath.
pos(0,0) = rte_pos[0];
5403 ppath.
pos(0,1) = rte_pos[1];
5404 ppath.
los(0,0) = rte_los[0];
5410 if( (rte_pos[0] +
RTOL) < rv_surface )
5413 os <<
"The ppath starting point is placed "
5414 << (rv_surface - rte_pos[0])/1e3 <<
" km below surface level.\n"
5415 <<
"This point must be above the surface.";
5416 throw runtime_error(os.str());
5420 if( ( rte_pos[1] == lat_grid[0] && rte_los[0] < 0 ) )
5421 throw runtime_error(
"The sensor is at the lower latitude end "
5422 "point and the zenith angle < 0." );
5423 if( rte_pos[1] == lat_grid[nlat-1] && rte_los[0] >= 0 )
5424 throw runtime_error(
"The sensor is at the upper latitude end "
5425 "point and the zenith angle >= 0." );
5428 ppath.
z[0] = ppath.
pos(0,0) - rv_geoid;
5435 ppath.
gp_lat[0].fd[0] = gp_lat.
fd[0];
5436 ppath.
gp_lat[0].fd[1] = gp_lat.
fd[1];
5446 if( ppath.
pos(0,0) == rv_surface )
5451 gp_lat, ppath.
los(0,0) );
5472 if( ( rte_pos[1] <= lat_grid[0] && rte_los[0] <= 0 ) ||
5473 ( rte_pos[1] >= lat_grid[nlat-1] && rte_los[0] >= 0 ) )
5476 os <<
"The sensor is outside (or at the limit) of the model "
5477 <<
"atmosphere but\nlooks in the wrong direction (wrong sign "
5478 <<
"for the zenith angle?).\nThis case includes nadir "
5479 <<
"looking exactly at the latitude end points.";
5480 throw runtime_error( os.str() );
5484 if(
abs(rte_los[0]) <= 90 )
5487 out1 <<
" ------- WARNING -------: path is totally outside of "
5488 <<
"the model atmosphere\n";
5500 if( rte_pos[1] < lat_grid[0] || rte_pos[1] > lat_grid[nlat-1] )
5504 if( rte_pos[1] > lat_grid[0] )
5505 { ic = nlat - 1; sc =
"upper"; }
5507 rte_pos[1], rte_los[0], lat_grid[ic] );
5508 if( rv < ( r_geoid(ic,0) + z_field(np-1,ic,0) ) )
5511 os <<
"The sensor is outside of the model atmosphere and "
5512 <<
"looks in the\n" << sc <<
" latitude end face.\n"
5513 <<
"The geometrical altitude of the corner point is "
5514 << z_field(np-1,ic,0)/1e3 <<
" km.\n"
5515 <<
"The geometrical altitude of the entrance point is "
5516 << (rv-r_geoid(ic,0))/1e3 <<
" km.";
5517 throw runtime_error( os.str() );
5524 if( ( geom_tan_pos[1] < lat_grid[0] ||
5525 geom_tan_pos[1] > lat_grid[nlat-1] ) )
5529 if( rte_los[0] >= 0 )
5530 { ic = nlat - 1; sc =
"upper"; }
5532 rte_pos[1], rte_los[0], lat_grid[ic] );
5533 if( rv >= ( r_geoid(ic,0) + z_field(np-1,ic,0) ) )
5536 os <<
"The combination of sensor position and line-of-"
5537 <<
"sight gives a\npropagation path that goes above "
5538 <<
"the model atmosphere, with\na tangent point "
5539 <<
"outside the covered latitude range.\nThe latitude "
5540 <<
"of the tangent point is " << geom_tan_pos[1]
5542 throw runtime_error( os.str() );
5555 if( geom_tan_pos[1] >= lat_grid[0] &&
5556 geom_tan_pos[1] <= lat_grid[nlat-1] &&
5557 geom_tan_z >= geom_tan_atmtop )
5560 out1 <<
" ------- WARNING -------: "
5561 <<
"path is totally outside of the model atmosphere\n";
5582 if( rte_pos[1] <= lat_grid[0] )
5588 else if( rte_pos[1] >= lat_grid[nlat-1] )
5590 lat0 = lat_grid[nlat-1];
5597 if( rte_los[0] >= 0 )
5620 rte_pos[1], rte_los[0], lat0 );
5625 double rv1 = r_geoid(ilat0,0) + z_field(np-1,ilat0,0);
5626 double rv2 = r_geoid(ilat0+istep,0) +
5627 z_field(np-1,ilat0+istep,0);
5628 double latstep =
abs( lat_grid[ilat0+istep] -
5630 double c = ( rv2 - rv1 ) / latstep;
5632 if( lat0 != lat_grid[ilat0] )
5633 { rv1 = rv1 + c *
abs( lat0 - lat_grid[ilat0] ); }
5637 if( dlat <= latstep )
5640 ppath.
pos(0,1) = lat0 + (double)istep*dlat;
5641 ppath.
pos(0,0) = rv1 + c * dlat;
5643 rte_los[0], ppath.
pos(0,0) );
5645 rv1 = r_geoid(ilat0,0);
5646 rv2 = r_geoid(ilat0+istep,0);
5647 c = ( rv2 - rv1 ) / latstep;
5648 ppath.
z[0] = ppath.
pos(0,0) - ( rv1 + c *
5649 abs( ppath.
pos(0,1) - lat_grid[ilat0] ) );
5650 ppath.
gp_p[0].idx = np - 2;
5651 ppath.
gp_p[0].fd[0] = 1;
5652 ppath.
gp_p[0].fd[1] = 0;
5658 lat0 = lat_grid[ilat0];
5670 if( geom_tan_pos.
nelem() == 2 )
5690 bool is_inside =
false;
5691 double rv_geoid=-1, rv_surface=-1;
5695 if( rte_pos[1] >= lat_grid[0] && rte_pos[1] <= lat_grid[nlat-1] &&
5696 rte_pos[2] >= lon_grid[0] && rte_pos[2] <= lon_grid[nlon-1] )
5698 gridpos( gp_lat, lat_grid, rte_pos[1] );
5699 gridpos( gp_lon, lon_grid, rte_pos[2] );
5702 rv_geoid =
interp( itw, r_geoid, gp_lat, gp_lon );
5703 rv_surface = rv_geoid +
interp( itw, z_surface, gp_lat, gp_lon );
5705 out2 <<
" sensor altitude : " << (rte_pos[0]-rv_geoid)/1e3
5708 if( rte_pos[0] < ( rv_geoid +
interp( itw,
5709 z_field(np-1,
joker,
joker), gp_lat, gp_lon ) ) )
5710 { is_inside =
true; }
5718 double geom_tan_z=-2, geom_tan_atmtop=-1;
5720 if( rte_los[0] > 90 )
5722 geom_tan_pos.resize(3);
5725 geom_tan_pos[2], dummy, rte_pos[0], rte_pos[1], rte_pos[2],
5726 rte_los[0], rte_los[1],
5728 resolve_lon( geom_tan_pos[2], lon_grid[0], lon_grid[nlon-1] );
5729 out2 <<
" geom. tangent radius : " << geom_tan_pos[0] / 1e3
5731 out2 <<
" geom. tangent latitude : " << geom_tan_pos[1]
5733 out2 <<
" geom. tangent longitude: " << geom_tan_pos[2]
5737 if( geom_tan_pos[1] >= lat_grid[0] &&
5738 geom_tan_pos[1] <= lat_grid[nlat-1] &&
5739 geom_tan_pos[2] >= lon_grid[0] &&
5740 geom_tan_pos[2] <= lon_grid[nlon-1] )
5744 gridpos( gp_tanlat, lat_grid, geom_tan_pos[1] );
5745 gridpos( gp_tanlon, lon_grid, geom_tan_pos[2] );
5747 geom_tan_z = geom_tan_pos[0] -
5748 interp( itw_tan, r_geoid, gp_tanlat, gp_tanlon );
5749 geom_tan_atmtop =
interp( itw_tan,
5750 z_field(np-1,
joker,
joker), gp_tanlat, gp_tanlon );
5751 out2 <<
" geom. tangent altitude : " << geom_tan_z/1e3
5757 ppath.
pos(0,0) = rte_pos[0];
5758 ppath.
pos(0,1) = rte_pos[1];
5759 ppath.
pos(0,2) = rte_pos[2];
5760 ppath.
los(0,0) = rte_los[0];
5761 ppath.
los(0,1) = rte_los[1];
5768 if( (rte_pos[0] +
RTOL) < rv_surface )
5771 os <<
"The ppath starting point is placed "
5772 << (rv_surface - rte_pos[0])/1e3 <<
" km below surface level.\n"
5773 <<
"This point must be above the surface.";
5774 throw runtime_error(os.str());
5778 if( rte_pos[1] > -90 && rte_pos[1] == lat_grid[0] &&
5779 abs( rte_los[1] > 90 ) )
5780 throw runtime_error(
"The sensor is at the lower latitude end "
5781 "point and the absolute value of the azimuth angle > 90." );
5782 if( rte_pos[1] < 90 && rte_pos[1] == lat_grid[nlat-1] &&
5783 abs( rte_los[1] ) <= 90 )
5784 throw runtime_error(
"The sensor is at the upper latitude end "
5785 "point and the absolute value of the azimuth angle <= 90." );
5788 if( rte_pos[2] == lon_grid[0] && rte_los[1] < 0 )
5789 throw runtime_error(
"The sensor is at the lower longitude end "
5790 "point and the azimuth angle < 0." );
5791 if( rte_pos[2] == lon_grid[nlon-1] && rte_los[1] > 0 )
5792 throw runtime_error(
"The sensor is at the upper longitude end "
5793 "point and the azimuth angle > 0." );
5796 ppath.
z[0] = ppath.
pos(0,0) - rv_geoid;
5803 ppath.
gp_lat[0].fd[0] = gp_lat.
fd[0];
5804 ppath.
gp_lat[0].fd[1] = gp_lat.
fd[1];
5806 ppath.
gp_lon[0].fd[0] = gp_lon.
fd[0];
5807 ppath.
gp_lon[0].fd[1] = gp_lon.
fd[1];
5812 z_at_latlon( z_grid, p_grid, lat_grid, lon_grid, z_field,
5817 if( ppath.
pos(0,0) == rv_surface )
5821 r_geoid, z_surface, gp_lat, gp_lon, ppath.
los(0,1) );
5844 if( ppath.
pos(0,1) >= lat_grid[cloudbox_limits[2]] &&
5845 ppath.
pos(0,1) <= lat_grid[cloudbox_limits[3]] &&
5846 ppath.
pos(0,2) >= lon_grid[cloudbox_limits[4]] &&
5847 ppath.
pos(0,2) <= lon_grid[cloudbox_limits[5]] )
5852 const double rv_low = rv_geoid +
interp( itw,
5853 z_field(cloudbox_limits[0],
joker,
joker), gp_lat, gp_lon );
5854 const double rv_upp = rv_geoid +
interp( itw,
5855 z_field(cloudbox_limits[1],
joker,
joker), gp_lat, gp_lon );
5857 if( ppath.
pos(0,0) >= rv_low && ppath.
pos(0,0) <= rv_upp )
5859 if( outside_cloudbox )
5862 else if( ppath.
pos(0,0) <= rv_low-
RTOL &&
5863 ppath.
pos(0,0) >= rv_upp+
RTOL )
5864 { assert( outside_cloudbox ); }
5867 { assert( outside_cloudbox ); }
5881 if( ( rte_pos[1] <= lat_grid[0] &&
abs( rte_los[1] ) >= 90 ) ||
5882 ( rte_pos[1] >= lat_grid[nlat-1] &&
abs( rte_los[1] ) <= 90 ) )
5885 os <<
"The sensor is north or south (or at the limit) of the "
5886 <<
"model atmosphere but\nlooks in the wrong direction.\n";
5887 throw runtime_error( os.str() );
5893 if( ( rte_pos[2] <= lon_grid[0] && rte_los[1] < 0 ) ||
5894 ( rte_pos[2] >= lon_grid[nlon-1] && rte_los[1] > 0 ) )
5897 os <<
"The sensor is east or west (or at the limit) of the "
5898 <<
"model atmosphere but\nlooks in the wrong direction.\n";
5899 throw runtime_error( os.str() );
5903 if(
abs(rte_los[0]) <= 90 )
5906 out1 <<
" ------- WARNING -------: path is totally outside of "
5907 <<
"the model atmosphere\n";
5926 if( geom_tan_pos[1] >= lat_grid[0] &&
5927 geom_tan_pos[1] <= lat_grid[nlat-1] &&
5928 geom_tan_pos[2] >= lon_grid[0] &&
5929 geom_tan_pos[2] <= lon_grid[nlon-1] &&
5930 geom_tan_z >= geom_tan_atmtop )
5933 out1 <<
" ------- WARNING -------: path is totally "
5934 <<
"outside of the model atmosphere\n";
5941 Matrix r_atmtop(nlat,nlon);
5943 for(
Index ilat=0; ilat<nlat; ilat++ )
5945 for(
Index ilon=0; ilon<nlon; ilon++ )
5946 { r_atmtop(ilat,ilon) = r_geoid(ilat,ilon) +
5947 z_field(np-1,ilat,ilon); }
5951 double rtopmin =
min( r_atmtop );
5952 if( rte_pos[0] <= rtopmin )
5955 os <<
"The sensor radius is smaller than the minimum "
5956 <<
"radius of the top of\nthe atmosphere. This gives "
5957 <<
"no possible OK entrance point for the path.";
5958 throw runtime_error( os.str() );
5963 double rtopmax =
max( r_atmtop );
5964 if( geom_tan_pos[0] >= rtopmax )
5967 os <<
"The combination of sensor position and line-of-"
5968 <<
"sight gives a\npropagation path that goes above "
5969 <<
"the model atmosphere, with\na tangent point "
5970 <<
"outside the covered latitude and longitude "
5971 <<
"ranges.\nThe position of the "
5972 <<
"tangent point is:\n lat : " << geom_tan_pos[1]
5973 <<
"\n lon : " << geom_tan_pos[2];
5974 throw runtime_error( os.str() );
5978 double x, y, z,
dx, dy, dz;
5980 rte_pos[1], rte_pos[2], rte_los[0], rte_los[1] );
5983 bool failed =
false;
5986 double r_top, lat_top, lon_top, l_top;
5988 rtopmin, rte_pos[0], rte_pos[1], rte_pos[2],
5989 rte_los[0], x, y, z,
dx, dy, dz );
5990 resolve_lon( lon_top, lon_grid[0], lon_grid[nlon-1] );
5996 if( lat_top < lat_grid[0] || lat_top > lat_grid[nlat-1] ||
5997 lon_top < lon_grid[0] || lon_top > lon_grid[nlon-1] )
6000 rtopmax, rte_pos[0], rte_pos[1], rte_pos[2],
6001 rte_los[0], x, y, z,
dx, dy, dz );
6002 resolve_lon( lon_top, lon_grid[0], lon_grid[nlon-1] );
6004 if( lat_top < lat_grid[0] || lat_top > lat_grid[nlat-1] ||
6005 lon_top < lon_grid[0] || lon_top > lon_grid[nlon-1] )
6014 while( !failed && !ready )
6018 double lat1, lat3, lon5, lon6, r15, r35, r36, r16;
6020 gridpos( gp_lattop, lat_grid, lat_top );
6022 gridpos( gp_lontop, lon_grid, lon_top );
6024 r15 = r_geoid(ilat,ilon) + z_field(np-1,ilat,ilon);
6025 r35 = r_geoid(ilat+1,ilon) + z_field(np-1,ilat+1,ilon);
6026 r36 = r_geoid(ilat+1,ilon+1) + z_field(np-1,ilat+1,ilon+1);
6027 r16 = r_geoid(ilat,ilon+1) + z_field(np-1,ilat,ilon+1);
6028 lat1 = lat_grid[ilat];
6029 lat3 = lat_grid[ilat+1];
6030 lon5 = lon_grid[ilon];
6031 lon6 = lon_grid[ilon+1];
6033 r15, r35, r36, r16, lat_top, lon_top );
6037 double lat_top2, lon_top2;
6039 r_top, rte_pos[0], rte_pos[1], rte_pos[2],
6040 rte_los[0], x, y, z,
dx, dy, dz );
6041 resolve_lon( lon_top2, lon_grid[0], lon_grid[nlon-1] );
6044 if(
abs( lat_top2 - lat_top ) < 1e-6 &&
6045 abs( lon_top2 - lon_top ) < 1e-6 )
6049 else if( lat_top < lat_grid[0] ||
6050 lat_top > lat_grid[nlat-1] ||
6051 lon_top < lon_grid[0] ||
6052 lon_top > lon_grid[nlon-1] )
6062 os <<
"The path does not enter the model atmosphere at "
6063 <<
"the top.\nThe path reaches the top of the "
6064 <<
"atmosphere altitude\napproximately at the "
6065 <<
"position:\n lat : " << lat_top <<
"\n lon : "
6067 throw runtime_error( os.str() );
6072 if( rte_los[0] == 180 )
6074 lat_top = rte_pos[1];
6075 lon_top = rte_pos[2];
6077 else if(
abs( rte_pos[1] ) < 90 && (
abs(rte_los[1]) <
ANGTOL
6079 { lon_top = rte_pos[2]; }
6084 ppath.
pos(0,0) = r_top;
6085 ppath.
pos(0,1) = lat_top;
6086 ppath.
pos(0,2) = lon_top;
6089 ppath.
gp_p[0].idx = np - 2;
6090 ppath.
gp_p[0].fd[0] = 1;
6091 ppath.
gp_p[0].fd[1] = 0;
6098 ppath.
z[0] = ppath.
pos(0,0) -
interp(itw2, r_geoid,
6102 double zatmp, aatmp;
6103 cart2poslos( r_top, lat_top, lon_top, zatmp, aatmp,
6104 x+
dx*l_top, y+dy*l_top, z+dz*l_top,
dx, dy, dz );
6105 ppath.
los(0,0) = zatmp;
6106 ppath.
los(0,1) = aatmp;
6109 if( rte_los[0] == 180 )
6110 { ppath.
los(0,0) = 180; }
6111 if(
abs( rte_pos[1] ) < 90 && (
abs( rte_los[1] ) <
ANGTOL
6113 { ppath.
los(0,1) = rte_los[1]; }
6125 if( geom_tan_pos.
nelem() == 3 )
6175 const Agenda& ppath_step_agenda,
6176 const Index& atmosphere_dim,
6183 const Index& cloudbox_on,
6187 const bool& outside_cloudbox,
6202 if( atmosphere_dim == 1 )
6207 else if( atmosphere_dim == 2 )
6220 assert( outside_cloudbox || cloudbox_on );
6226 out2 <<
" -------------------------------------\n";
6227 out2 <<
" sensor radius : " << rte_pos[0]/1e3 <<
" km\n";
6228 if( atmosphere_dim >= 2 )
6229 out2 <<
" sensor latitude : " << rte_pos[1] <<
"\n";
6230 if( atmosphere_dim == 3 )
6231 out2 <<
" sensor longitude : " << rte_pos[2] <<
"\n";
6232 out2 <<
" sensor zenith angle : " << rte_los[0] <<
"\n";
6233 if( atmosphere_dim == 3 )
6234 out2 <<
" sensor azimuth angle : " << rte_los[1] <<
"\n";
6249 lon_grid, z_field, r_geoid, z_surface,
6250 cloudbox_on, cloudbox_limits, outside_cloudbox, rte_pos, rte_los,
6253 out2 <<
" -------------------------------------\n";
6262 ppath_array.push_back( ppath_step );
6279 lat_grid, lon_grid, z_field, r_geoid, z_surface,
6280 ppath_step_agenda );
6283 const Index n = ppath_step.
np;
6289 throw runtime_error(
6290 "10 000 path points have been reached. Is this an infinite loop?" );
6298 if( outside_cloudbox )
6308 if( atmosphere_dim == 2 )
6314 os <<
"The path exits the atmosphere through the lower "
6315 <<
"latitude end face.\nThe exit point is at an altitude"
6316 <<
"of " << ppath_step.
z[n-1]/1e3 <<
" km.";
6317 throw runtime_error( os.str() );
6322 os <<
"The path exits the atmosphere through the upper "
6323 <<
"latitude end face.\nThe exit point is at an altitude"
6324 <<
" of " << ppath_step.
z[n-1]/1e3 <<
" km.";
6325 throw runtime_error( os.str() );
6328 if( atmosphere_dim == 3 )
6331 if( lat_grid[0] > -90 &&
6335 os <<
"The path exits the atmosphere through the lower "
6336 <<
"latitude end face.\nThe exit point is at an altitude"
6337 <<
" of " << ppath_step.
z[n-1]/1e3 <<
" km.";
6338 throw runtime_error( os.str() );
6340 if( lat_grid[imax_lat] < 90 &&
6344 os <<
"The path exits the atmosphere through the upper"
6345 <<
"latitude end face.\nThe exit point is at an altitude"
6346 <<
" of " << ppath_step.
z[n-1]/1e3 <<
" km.";
6347 throw runtime_error( os.str() );
6354 ppath_step.
los(n-1,1) < 0 &&
6355 abs( ppath_step.
pos(n-1,1) ) < 90 )
6358 if( lon_grid[imax_lon] - lon_grid[0] >= 360 )
6360 ppath_step.
pos(n-1,2) = ppath_step.
pos(n-1,2) + 360;
6362 ppath_step.
pos(n-1,2) );
6367 os <<
"The path exits the atmosphere through the lower "
6368 <<
"longitude end face.\nThe exit point is at an "
6369 <<
"altitude of " << ppath_step.
z[n-1]/1e3 <<
" km.";
6370 throw runtime_error( os.str() );
6375 ppath_step.
los(n-1,1) > 0 &&
6376 abs( ppath_step.
pos(n-1,1) ) < 90 )
6379 if( lon_grid[imax_lon] - lon_grid[0] >= 360 )
6381 ppath_step.
pos(n-1,2) = ppath_step.
pos(n-1,2) - 360;
6383 ppath_step.
pos(n-1,2) );
6388 os <<
"The path exits the atmosphere through the upper "
6389 <<
"longitude end face.\nThe exit point is at an "
6390 <<
"altitude of " << ppath_step.
z[n-1]/1e3 <<
" km.";
6391 throw runtime_error( os.str() );
6402 if( ipos >=
double( cloudbox_limits[0] ) &&
6403 ipos <=
double( cloudbox_limits[1] ) )
6405 if( atmosphere_dim == 1 )
6411 if( ipos >=
double( cloudbox_limits[2] ) &&
6412 ipos <=
double( cloudbox_limits[3] ) )
6414 if( atmosphere_dim == 2 )
6421 if( ipos >=
double( cloudbox_limits[4] ) &&
6422 ipos <=
double( cloudbox_limits[5] ) )
6442 if( ipos1 <=
double( cloudbox_limits[0] ) && ipos1 < ipos2 )
6445 else if( ipos1 >=
double( cloudbox_limits[1] ) && ipos1 > ipos2 )
6448 else if( atmosphere_dim > 1 )
6453 if( ipos1 <=
double( cloudbox_limits[2] ) && ipos1 < ipos2 )
6456 else if( ipos1 >=
double( cloudbox_limits[3] ) && ipos1 > ipos2 )
6459 else if ( atmosphere_dim > 2 )
6464 if( ipos1 <=
double( cloudbox_limits[4] ) && ipos1 < ipos2 )
6467 else if( ipos1 >=
double( cloudbox_limits[5] ) &&
6479 ppath_array.push_back( ppath_step );
6497 Index n = ppath_array[i].np;
6506 { assert( n > 1 ); }
6509 ppath.
z[
Range(np,n-i1) ] = ppath_array[i].z[
Range(i1,n-i1) ];
6518 { ppath.
l_step[
Range(np-1,n-1) ] = ppath_array[i].l_step; }
6521 for(
Index j=i1; j<n; j++ )
6522 { ppath.
gp_p[np+j-i1] = ppath_array[i].gp_p[j]; }
6523 if( atmosphere_dim >= 2 )
6525 for(
Index j=i1; j<n; j++ )
6526 { ppath.
gp_lat[np+j-i1] = ppath_array[i].gp_lat[j]; }
6528 if( atmosphere_dim == 3 )
6530 for(
Index j=i1; j<n; j++ )
6531 { ppath.
gp_lon[np+j-i1] = ppath_array[i].gp_lon[j]; }
6535 if( ppath_array[i].tan_pos.
nelem() )
6538 ppath.
tan_pos = ppath_array[i].tan_pos;
6540 if( ppath_array[i].geom_tan_pos.
nelem() )