121 assert(
abs(za) <= 180 );
153 assert(
abs(a_za) <= 180 );
154 assert( r >= ppc -
RTOL );
195 assert(
abs(za) <= 180 );
223 assert(
abs(za0) <= 180 );
224 assert(
abs(za) <= 180 );
225 assert( ( za0 >= 0 && za >= 0 ) || ( za0 < 0 && za < 0 ) );
227 return lat0 + za0 - za;
251 assert( r >= ppc -
RTOL );
254 {
return sqrt( r*r - ppc*ppc ); }
281 return sqrt( l*l + ppc*ppc );
306 assert(
abs(za0) <= 180 );
307 assert( ( za0 >= 0 && lat >= lat0 ) || ( za0 <= 0 && lat <= lat0 ) );
310 const Numeric za = za0 + lat0 -lat;
351 const bool& tanpoint,
360 if( l1 < 0 ) { l2 *= -1; }
376 lstep = ( l2 - l1 ) / (
Numeric)n;
387 for(
Index i=1; i<n; i++ )
404 for(
Index i=1; i<=n; i++ )
408 lstep =
abs( lstep );
496 dy = sin( aarad ) *
dx;
497 dx = cos( aarad ) *
dx;
525 assert( R.
ncols() == 3 );
526 assert( R.
nrows() == 3 );
527 assert( vrot.
nelem() == 3 );
537 assert( sqrt( u2 + v2 + w2 ) );
543 R(0,0) = u2 + (v2 + w2)*c;
544 R(0,1) = u*v*(1-c) -
w*s;
545 R(0,2) = u*
w*(1-c) + v*s;
546 R(1,0) = u*v*(1-c) +
w*s;
547 R(1,1) = v2 + (u2+w2)*c;
548 R(1,2) = v*
w*(1-c) - u*s;
549 R(2,0) = u*
w*(1-c) - v*s;
550 R(2,1) = v*
w*(1-c)+u*s;
551 R(2,2) = w2 + (u2+v2)*c;
583 assert(
abs( aa_grid ) <= 5 );
591 zaaa2cart( xyz[0], xyz[1], xyz[2], 90, aa0 );
604 zaaa2cart( xyz[0], xyz[1], xyz[2], 90, aa0+aa_grid );
642 const Numeric& refr_index_air )
645 assert(
abs(za) <= 180 );
647 return r * refr_index_air * sin(
DEG2RAD *
abs(za) );
680 assert( lon6 >= lon5 );
682 if( lon < lon5 && lon+180 <= lon6 )
684 else if( lon > lon6 && lon-180 >= lon5 )
711 while( it < ppath.
np-1 && ppath.
pos(it+1,0) < zmin )
714 zmin = ppath.
pos(it,0);
716 if( it == 0 || it == ppath.
np-1 )
750 return r1 + ( lat - lat1 ) * ( r3 - r1 ) / ( lat3 - lat1 );
791 const Numeric r1 =
refell2r( refellipsoid, lat_grid[i1] ) + z_surf[i1];
792 const Numeric r2 =
refell2r( refellipsoid, lat_grid[i1+1] ) + z_surf[i1+1];
794 c1 = ( r2 - r1 ) / ( lat_grid[i1+1] - lat_grid[i1] );
824 c1 = ( r2 - r1 ) / ( lat2 - lat1 );
879 assert(
abs(za) <= 180 );
882 if( za > (90-tilt) || za < (-90-tilt) )
923 assert(
abs( za_start ) <= 180 );
924 assert( r_start >= ppc );
930 if( ( r_start >= r_hit && absza <= 90 ) || ppc > r_hit )
936 if( absza > 90 && r_start <= r_hit )
1001 assert( zaabs != 180 );
1002 assert(
abs(c1) > 0 );
1025 p0[0] = r0s - rp*sv;
1027 p0[2] = -r0s/2 + cc;
1028 p0[3] = -r0c/6 - cs/2;
1029 p0[4] = r0s/24 - cc/6;
1030 p0[5] = r0c/120 + cs/24;
1031 p0[6] = -r0s/720 + cc/120;
1038 if(
abs( 90 - zaabs ) > 89.9 )
1040 else if(
abs( 90 - zaabs ) > 75 )
1045 int solutionfailure = 1;
1047 while( solutionfailure)
1051 p = p0[
Range(0,n+1)];
1053 if( solutionfailure )
1054 { n -= 1; assert( n > 0 ); }
1060 if(
abs(r0-rp) < 1e-9 )
1066 for(
Index i=0; i<n; i++ )
1068 if( roots(i,1) == 0 && roots(i,0) >
dmin && roots(i,0) < dlat )
1069 { dlat = roots(i,0); }
1137 assert( absza <= 180 );
1138 assert( lat_start >=lat1 && lat_start <= lat3 );
1149 l =
max( 1e-9, r - r_start0 );
1154 else if( absza > 180-
ANGTOL )
1160 l =
max( 1e-9, r_start0 - r );
1173 if( rmax-rmin < 1e-6 )
1179 {
if( r_start < rmax ) { r_start = r = rmax; } }
1181 {
if( r_start > rmin ) { r_start = r = rmin; } }
1183 r_crossing_2d( lat, l, r, r_start, lat_start, za_start, ppc );
1186 if( lat > lat3 || lat < lat1 )
1196 {
if( r_start < rmin ) { r_start = rmin; } }
1198 {
if( r_start > rmax ) { r_start = rmax; } }
1203 if( r_start > rmax )
1206 r_crossing_2d( lat, l, r, r_start, lat_start, za_start, ppc );
1208 else if( r_start < rmin )
1211 r_crossing_2d( lat, l, r, r_start, lat_start, za_start, ppc );
1214 { r = r_start; lat = lat_start; l = 0; za = za_start; }
1217 if( lat < lat1 || lat > lat3 )
1226 const Numeric rpl = r1 + cpl*(lat-lat1);
1230 {
if( r < rpl ) { r = rpl; } }
1232 {
if( r > rpl ) { r = rpl; } }
1236 { za = lat_start + za_start - lat; };
1244 if( lat < lat1 || lat > lat3 )
1253 za = lat_start + za_start - lat;
1256 if( absza>90 &&
abs(za)<90 )
1310 {
return r15 + ( lon - lon5 ) * ( r16 - r15 ) / ( lon6 -lon5 ); }
1311 else if( lat == lat3 )
1312 {
return r35 + ( lon - lon5 ) * ( r36 - r35 ) / ( lon6 -lon5 ); }
1313 else if( lon == lon5 )
1314 {
return r15 + ( lat - lat1 ) * ( r35 - r15 ) / ( lat3 -lat1 ); }
1315 else if( lon == lon6 )
1316 {
return r16 + ( lat - lat1 ) * ( r36 - r16 ) / ( lat3 -lat1 ); }
1319 const Numeric fdlat = ( lat - lat1 ) / ( lat3 - lat1 );
1320 const Numeric fdlon = ( lon - lon5 ) / ( lon6 - lon5 );
1321 return (1-fdlat)*(1-fdlon)*r15 + fdlat*(1-fdlon)*r35 +
1322 (1-fdlat)*fdlon*r16 + fdlat*fdlon*r36;
1370 if( r15==r35 && r15==r36 && r15==r16 && r35==r36 && r35==r16 && r36==r16 )
1380 r15, r35, r36, r16, lat, lon );
1392 r15, r35, r36, r16, lat2, lon2 ) - r0;
1397 r15, r35, r36, r16, lat2, lon2 ) - r0;
1400 c1 = 0.5 * ( 4*dr1 - dr2 );
1401 c2 = (dr1-c1)/(dang*dang);
1454 if( lat_grid[llat] >
POLELAT )
1455 { ilat = llat - 1; }
1457 {
throw runtime_error(
"The upper latitude end of the atmosphere "
1458 "reached, that is not allowed." ); }
1461 if( ilon >= lon_grid.
nelem() - 1 )
1466 {
throw runtime_error(
"The upper longitude end of the atmosphere "
1467 "reached, that is not allowed." ); }
1474 lat =
interp( itw, lat_grid, gp_lat );
1476 lon =
interp( itw, lon_grid, gp_lon );
1479 const Numeric lat1 = lat_grid[ilat];
1480 const Numeric lat3 = lat_grid[ilat+1];
1481 const Numeric lon5 = lon_grid[ilon];
1482 const Numeric lon6 = lon_grid[ilon+1];
1485 const Numeric r15 = re1 + z_surf(ilat,ilon);
1486 const Numeric r35 = re3 + z_surf(ilat+1,ilon);
1487 const Numeric r36 = re3 + z_surf(ilat+1,ilon+1);
1488 const Numeric r16 = re1 + z_surf(ilat,ilon+1);
1490 plevel_slope_3d( c1, c2, lat1, lat3, lon5, lon6, r15, r35, r36, r16,
1543 p0[0] = r0s - rp*sv;
1545 p0[2] = -r0s/2 + c1c + c2s;
1546 p0[3] = -r0c/6 - c1s/2 + c2c;
1547 p0[4] = r0s/24 - c1c/6 - c2s/2;
1548 p0[5] = r0c/120 + c1s/24 - c2c/6;
1549 p0[6] = -r0s/720 + c1c/120 + c2s/24;
1557 if(
abs( 90 - za ) > 89.9 )
1559 else if(
abs( 90 - za ) > 75 )
1564 int solutionfailure = 1;
1566 while( solutionfailure)
1570 p = p0[
Range(0,n+1)];
1572 if( solutionfailure )
1573 { n -= 1; assert( n > 0 ); }
1586 for(
Index i=0; i<n; i++ )
1588 if( roots(i,1) == 0 && roots(i,0) >
dmin && roots(i,0) < dlat )
1589 { dlat = roots(i,0); }
1655 assert( za_start >= 0 );
1656 assert( za_start <= 180 );
1660 if( ( r_start >= r_hit && za_start <= 90 ) || ppc > r_hit )
1666 if( za_start < ANGTOL || za_start > 180-
ANGTOL )
1668 l =
abs( r_hit - r_start );
1677 const Numeric q = x*x + y*y + z*z - r_hit*r_hit;
1695 lat =
RAD2DEG * asin( ( z+dz*l ) / r_hit );
1696 lon =
RAD2DEG * atan2( y+dy*l, x+
dx*l );
1728 const Index& atmosphere_dim,
1732 assert( atmosphere_dim >= 1 );
1733 assert( atmosphere_dim <= 3 );
1735 ppath.
dim = atmosphere_dim;
1754 ppath.
gp_p.resize( np );
1755 if( atmosphere_dim >= 2 )
1757 ppath.
gp_lat.resize( np );
1758 if( atmosphere_dim == 3 )
1759 { ppath.
gp_lon.resize( np ); }
1792 const Index& case_nr )
1816 os <<
"Case number " << case_nr <<
" is not defined.";
1817 throw runtime_error(os.str());
1843 else if( ppath.
background ==
"cloud box level" )
1845 else if( ppath.
background ==
"cloud box interior" )
1853 <<
" is not a valid background case.";
1854 throw runtime_error(os.str());
1878 const Ppath& ppath2,
1879 const Index& ncopy )
1887 assert( ppath1.
np >= n );
1901 if( n == ppath1.
np )
1916 for(
Index i=0; i<n; i++ )
1920 if( ppath1.
dim >= 2 )
1923 if( ppath1.
dim == 3 )
1950 const Ppath& ppath2 )
1964 for(
Index i=1; i<n2; i++ )
1968 ppath1.
pos(i1,0) = ppath2.
pos(i,0);
1969 ppath1.
pos(i1,1) = ppath2.
pos(i,1);
1970 ppath1.
los(i1,0) = ppath2.
los(i,0);
1971 ppath1.
r[i1] = ppath2.
r[i];
1976 if( ppath1.
dim >= 2 )
1979 if( ppath1.
dim == 3 )
1981 ppath1.
pos(i1,2) = ppath2.
pos(i,2);
1982 ppath1.
los(i1,1) = ppath2.
los(i,1);
2022 const Ppath& ppath )
2025 const Index imax = ppath.
np - 1;
2028 r_start = ppath.
r[imax];
2029 lat_start = ppath.
pos(imax,1);
2030 za_start = ppath.
los(imax,0);
2063 const Index& endface,
2075 const Numeric r1 = refellipsoid[0] + z_field[ip];
2076 const Numeric dr = z_field[ip+1] - z_field[ip];
2078 for(
Index i=0; i<np; i++ )
2080 ppath.
r[i] = r_v[i];
2081 ppath.
pos(i,0) = r_v[i] - refellipsoid[0];
2082 ppath.
pos(i,1) = lat_v[i];
2083 ppath.
los(i,0) = za_v[i];
2084 ppath.
nreal[i] = n_v[i];
2085 ppath.
ngroup[i] = ng_v[i];
2087 ppath.
gp_p[i].idx = ip;
2088 ppath.
gp_p[i].fd[0] = ( r_v[i] - r1 ) / dr;
2089 ppath.
gp_p[i].fd[1] = 1 - ppath.
gp_p[i].fd[0];
2093 { ppath.
lstep[i-1] = lstep[i-1]; }
2103 else if( endface <= 4 )
2143 const Index imax = ppath.
np - 1;
2146 r_start = ppath.
r[imax];
2147 lat_start = ppath.
pos(imax,1);
2148 za_start = ppath.
los(imax,0);
2155 lat1 = lat_grid[ilat];
2156 lat3 = lat_grid[ilat+1];
2169 r1a = re1 + z_field(ip,ilat);
2170 r3a = re3 + z_field(ip,ilat+1);
2171 r3b = re3 + z_field(ip+1,ilat+1);
2172 r1b = re1 + z_field(ip+1,ilat);
2201 r1b = r1a; r3b = r3a;
2202 r1a = re1 + z_field(ip,ilat);
2203 r3a = re3 + z_field(ip,ilat+1);
2214 r1a = r1b; r3a = r3b;
2215 r3b = re3 + z_field(ip+1,ilat+1);
2216 r1b = re1 + z_field(ip+1,ilat);
2222 rsurface1 = re1 + z_surface[ilat];
2223 rsurface3 = re3 + z_surface[ilat+1];
2253 const Index& endface,
2258 const Index imax = np-1;
2267 const Numeric dlat = lat_grid[ilat+1] - lat_grid[ilat];
2268 const Numeric z1low = z_field(ip,ilat);
2269 const Numeric z1upp = z_field(ip+1,ilat);
2270 const Numeric dzlow = z_field(ip,ilat+1) -z1low;
2271 const Numeric dzupp = z_field(ip+1,ilat+1) - z1upp;
2273 const Numeric r1low = re + z1low;
2274 const Numeric r1upp = re + z1upp;
2275 re =
refell2r( refellipsoid, lat_grid[ilat+1] );
2276 const Numeric drlow = re + z_field(ip,ilat+1) - r1low;
2277 const Numeric drupp = re + z_field(ip+1,ilat+1) - r1upp;
2279 for(
Index i=0; i<np; i++ )
2281 ppath.
r[i] = r_v[i];
2282 ppath.
pos(i,1) = lat_v[i];
2283 ppath.
los(i,0) = za_v[i];
2284 ppath.
nreal[i] = n_v[i];
2285 ppath.
ngroup[i] = ng_v[i];
2288 Numeric w = ( lat_v[i] - lat_grid[ilat] ) / dlat;
2291 const Numeric rlow = r1low +
w * drlow;
2292 const Numeric rupp = r1upp +
w * drupp;
2295 const Numeric zlow = z1low +
w * dzlow;
2296 const Numeric zupp = z1upp +
w * dzupp;
2298 ppath.
gp_p[i].idx = ip;
2299 ppath.
gp_p[i].fd[0] = ( r_v[i] - rlow ) / ( rupp - rlow );
2300 ppath.
gp_p[i].fd[1] = 1 - ppath.
gp_p[i].fd[0];
2303 ppath.
pos(i,0) = zlow + ppath.
gp_p[i].fd[0] * ( zupp -zlow );
2305 ppath.
gp_lat[i].idx = ilat;
2306 ppath.
gp_lat[i].fd[0] = ( lat_v[i] - lat_grid[ilat] ) / dlat;
2311 { ppath.
lstep[i-1] = lstep[i-1]; }
2322 if( endface == 1 || endface == 3 )
2324 else if( endface == 2 || endface == 4 )
2329 if( ppath.
gp_p[imax].fd[0] < 0 || ppath.
gp_p[imax].fd[1] < 0 )
2333 if( ppath.
gp_lat[imax].fd[0] < 0 || ppath.
gp_lat[imax].fd[1] < 0 )
2386 const Index imax = ppath.
np - 1;
2389 r_start = ppath.
r[imax];
2390 lat_start = ppath.
pos(imax,1);
2391 lon_start = ppath.
pos(imax,2);
2392 za_start = ppath.
los(imax,0);
2393 aa_start = ppath.
los(imax,1);
2404 if( lat_start == 90 )
2408 gridpos( gp_tmp, lon_grid, aa_start );
2409 if( aa_start < 180 )
2414 else if( lat_start == -90 )
2418 gridpos( gp_tmp, lon_grid, aa_start );
2419 if( aa_start < 180 )
2430 if( lon_start < lon_grid[nlon-1] )
2433 { ilon = nlon - 2; }
2436 lat1 = lat_grid[ilat];
2437 lat3 = lat_grid[ilat+1];
2438 lon5 = lon_grid[ilon];
2439 lon6 = lon_grid[ilon+1];
2452 r15a = re1 + z_field(ip,ilat,ilon);
2453 r35a = re3 + z_field(ip,ilat+1,ilon);
2454 r36a = re3 + z_field(ip,ilat+1,ilon+1);
2455 r16a = re1 + z_field(ip,ilat,ilon+1);
2456 r15b = re1 + z_field(ip+1,ilat,ilon);
2457 r35b = re3 + z_field(ip+1,ilat+1,ilon);
2458 r36b = re3 + z_field(ip+1,ilat+1,ilon+1);
2459 r16b = re1 + z_field(ip+1,ilat,ilon+1);
2466 if( fabs(za_start-90) <= 10 )
2473 r15a, r35a, r36a, r16a, lat_start, lon_start, aa_start );
2479 r15b = r15a; r35b = r35a; r36b = r36a; r16b = r16a;
2480 r15a = re1 + z_field(ip,ilat,ilon);
2481 r35a = re3 + z_field(ip,ilat+1,ilon);
2482 r36a = re3 + z_field(ip,ilat+1,ilon+1);
2483 r16a = re1 + z_field(ip,ilat,ilon+1);
2491 r15b, r35b, r36b, r16b, lat_start, lon_start, aa_start );
2497 r15a = r15b; r35a = r35b; r36a = r36b; r16a = r16b;
2498 r15b = re1 + z_field(ip+1,ilat,ilon);
2499 r35b = re3 + z_field(ip+1,ilat+1,ilon);
2500 r36b = re3 + z_field(ip+1,ilat+1,ilon+1);
2501 r16b = re1 + z_field(ip+1,ilat,ilon+1);
2507 rsurface15 = re1 + z_surface(ilat,ilon);
2508 rsurface35 = re3 + z_surface(ilat+1,ilon);
2509 rsurface36 = re3 + z_surface(ilat+1,ilon+1);
2510 rsurface16 = re1 + z_surface(ilat,ilon+1);
2544 const Index& endface,
2549 const Index imax = np-1;
2558 const Numeric lat1 = lat_grid[ilat];
2559 const Numeric lat3 = lat_grid[ilat+1];
2560 const Numeric lon5 = lon_grid[ilon];
2561 const Numeric lon6 = lon_grid[ilon+1];
2564 const Numeric r15a = re1 + z_field(ip,ilat,ilon);
2565 const Numeric r35a = re3 + z_field(ip,ilat+1,ilon);
2566 const Numeric r36a = re3 + z_field(ip,ilat+1,ilon+1);
2567 const Numeric r16a = re1 + z_field(ip,ilat,ilon+1);
2568 const Numeric r15b = re1 + z_field(ip+1,ilat,ilon);
2569 const Numeric r35b = re3 + z_field(ip+1,ilat+1,ilon);
2570 const Numeric r36b = re3 + z_field(ip+1,ilat+1,ilon+1);
2571 const Numeric r16b = re1 + z_field(ip+1,ilat,ilon+1);
2572 const Numeric dlat = lat3 - lat1;
2573 const Numeric dlon = lon6 - lon5;
2575 for(
Index i=0; i<np; i++ )
2579 r15a, r35a, r36a, r16a, lat_v[i], lon_v[i] );
2581 r15b, r35b, r36b, r16b, lat_v[i], lon_v[i] );
2584 ppath.
r[i] = r_v[i];
2585 ppath.
pos(i,1) = lat_v[i];
2586 ppath.
pos(i,2) = lon_v[i];
2587 ppath.
los(i,0) = za_v[i];
2588 ppath.
los(i,1) = aa_v[i];
2589 ppath.
nreal[i] = n_v[i];
2590 ppath.
ngroup[i] = ng_v[i];
2593 ppath.
gp_p[i].idx = ip;
2594 ppath.
gp_p[i].fd[0] = ( r_v[i] - rlow ) / ( rupp - rlow );
2595 ppath.
gp_p[i].fd[1] = 1 - ppath.
gp_p[i].fd[0];
2600 re1, re3, re3, re1, lat_v[i], lon_v[i] );
2601 const Numeric zlow = rlow - re;
2602 const Numeric zupp = rupp - re;
2604 ppath.
pos(i,0) = zlow + ppath.
gp_p[i].fd[0] * ( zupp -zlow );
2607 ppath.
gp_lat[i].idx = ilat;
2608 ppath.
gp_lat[i].fd[0] = ( lat_v[i] - lat1 ) / dlat;
2619 ppath.
gp_lon[i].idx = ilon;
2620 ppath.
gp_lon[i].fd[0] = ( lon_v[i] - lon5 ) / dlon;
2627 ppath.
gp_lon[i].fd[0] = 0;
2628 ppath.
gp_lon[i].fd[1] = 1;
2632 { ppath.
lstep[i-1] = lstep[i-1]; }
2641 if( endface == 1 || endface == 3 )
2643 else if( endface == 2 || endface == 4 )
2645 else if( endface == 5 || endface == 6 )
2650 if( ppath.
gp_p[imax].fd[0] < 0 || ppath.
gp_p[imax].fd[1] < 0 )
2654 if( ppath.
gp_lat[imax].fd[0] < 0 || ppath.
gp_lat[imax].fd[1] < 0 )
2658 if( ppath.
gp_lon[imax].fd[0] < 0 || ppath.
gp_lon[imax].fd[1] < 0 )
2717 assert( r_start >= ra -
RTOL );
2718 assert( r_start <= rb +
RTOL );
2723 else if( r_start > rb )
2727 bool tanpoint =
false;
2731 if( za_start <= 90 )
2732 { endface = 4; r_end = rb; }
2737 if( ra > rsurface && ra > ppc )
2738 { endface = 2; r_end = ra; }
2741 else if( rsurface > ppc )
2742 { endface = 7; r_end = rsurface; }
2746 { endface = 4; r_end = rb; tanpoint =
true; }
2749 assert( endface > 0 );
2752 za_start, r_end, tanpoint, lmax );
2791 Numeric r_start, lat_start, za_start;
2818 r_start, lat_start, za_start, ppc, lmax,
2819 refellipsoid[0]+z_field[ip], refellipsoid[0]+z_field[ip+1],
2820 refellipsoid[0]+z_surface );
2825 Vector(np,1), z_field, refellipsoid, ip, endface, ppc );
2860 Numeric lat_start = lat_start0;
2862 assert( icall < 4 );
2865 assert( lat_start >= lat1 -
LATLONTOL );
2866 assert( lat_start <= lat3 +
LATLONTOL );
2869 if( lat_start < lat1 )
2870 { lat_start = lat1; }
2871 else if( lat_start > lat3 )
2872 { lat_start = lat3; }
2879 assert( r_start >= rlow -
RTOL );
2880 assert( r_start <= rupp +
RTOL );
2883 if( r_start < rlow )
2885 else if( r_start > rupp )
2893 bool unsafe =
false;
2894 bool do_surface =
false;
2900 Numeric r_end, lat_end, l_end;
2908 l_end = rupp - r_start;
2913 else if( absza > 180-
ANGTOL )
2918 if( rlow > rsurface )
2920 l_end = r_start - rlow;
2925 l_end = r_start - rsurface;
2939 cart2pol( r_corr, lat_corr, x, z, lat_start, za_start );
2942 lat_corr -= lat_start;
2955 { l_end = l_start; }
2957 { l_end = 2 * ( rupp - rlow ); }
2959 Numeric l_in = 0, l_out = l_end;
2960 bool ready =
false, startup =
true;
2962 if( rsurface1+
RTOL >= r1a || rsurface3+
RTOL >= r3a )
2963 { do_surface =
true; }
2967 cart2pol( r_end, lat_end, x+
dx*l_end, z+dz*l_end, lat_start,
2970 lat_end -= lat_corr;
2979 rsurface3, lat_end );
2980 if( r_surface >= rlow && r_end <= r_surface )
2981 { inside =
false; endface = 7; }
2986 if( lat_end < lat1 )
2987 { inside =
false; endface = 1; }
2988 else if( lat_end > lat3 )
2989 { inside =
false; endface = 3; }
2990 else if( r_end < rlow )
2991 { inside =
false; endface = 2; }
2996 { inside =
false; endface = 4; }
3010 l_end = ( l_out + l_in ) / 2;
3021 if( ( l_out - l_in ) <
LACC )
3024 { l_end = ( l_out + l_in ) / 2; }
3035 n =
Index( ceil(
abs( l_end / lmax ) ) );
3045 lat_v[0] = lat_start;
3052 for(
Index j=1; j<=n; j++ )
3056 lat_start, za_start );
3074 rsurface1, rsurface3, lat_v[j] );
3075 const Numeric r_test =
max( r_surface, rlow );
3076 if( r_v[j] < r_test )
3077 { ready =
false;
break; }
3079 else if( r_v[j] < rlow )
3080 { ready =
false;
break; }
3084 { ready =
false;
break; }
3094 { lat_v[n] = lat1; }
3095 else if( endface == 2 )
3096 { r_v[n] =
rsurf_at_lat( lat1, lat3, r1a, r3a, lat_v[n] ); }
3097 else if( endface == 3 )
3098 { lat_v[n] = lat3; }
3099 else if( endface == 4 )
3100 { r_v[n] =
rsurf_at_lat( lat1, lat3, r1b, r3b, lat_v[n] ); }
3101 else if( endface == 7 )
3102 { r_v[n] =
rsurf_at_lat( lat1, lat3, rsurface1, rsurface3,
3111 lat_start, za_start, l, icall+1, ppc, lmax,
3112 lat1, lat3, r1a, r3a, r3b, r1b,
3113 rsurface1, rsurface3 );
3145 Numeric r_start, lat_start, za_start;
3151 Numeric lat1, lat3, r1a, r3a, r3b, r1b, rsurface1, rsurface3;
3155 lat1, lat3, r1a, r3a, r3b, r1b, rsurface1, rsurface3,
3156 ppath, lat_grid, z_field, refellipsoid, z_surface );
3172 lat_start, za_start, -1, 0, ppc, lmax,
3173 lat1, lat3, r1a, r3a, r3b, r1b,
3174 rsurface1, rsurface3 );
3178 Vector(np,1), lat_grid, z_field, refellipsoid, ip, ilat,
3226 Numeric lat_start = lat_start0;
3227 Numeric lon_start = lon_start0;
3229 assert( icall < 4 );
3232 assert( lat_start >= lat1 -
LATLONTOL );
3233 assert( lat_start <= lat3 +
LATLONTOL );
3238 if( lat_start < lat1 )
3239 { lat_start = lat1; }
3240 else if( lat_start > lat3 )
3241 { lat_start = lat3; }
3242 if( lon_start < lon5 )
3243 { lon_start = lon5; }
3244 else if( lon_start > lon6 )
3245 { lon_start = lon6; }
3249 r15a, r35a, r36a, r16a, lat_start, lon_start );
3251 r15b, r35b, r36b, r16b, lat_start, lon_start );
3254 assert( r_start >= rlow -
RTOL );
3255 assert( r_start <= rupp +
RTOL );
3258 if( r_start < rlow )
3260 else if( r_start > rupp )
3265 poslos2cart( x, y, z,
dx, dy, dz, r_start, lat_start, lon_start,
3266 za_start, aa_start );
3269 bool unsafe =
false;
3270 bool do_surface =
false;
3276 Numeric r_end, lat_end, lon_end, l_end;
3283 l_end = rupp - r_start;
3288 else if( za_start > 180-
ANGTOL )
3291 rsurface15, rsurface35, rsurface36, rsurface16,
3292 lat_start, lon_start );
3294 if( rlow > rsurface )
3296 l_end = r_start - rlow;
3301 l_end = r_start - rsurface;
3313 Numeric r_corr, lat_corr, lon_corr;
3315 cart2sph( r_corr, lat_corr, lon_corr, x, y, z, lat_start, lon_start,
3316 za_start, aa_start );
3319 lat_corr -= lat_start;
3320 lon_corr -= lon_start;
3333 { l_end = l_start; }
3335 { l_end = 2 * ( rupp - rlow ); }
3337 Numeric l_in = 0, l_out = l_end;
3338 bool ready =
false, startup =
true;
3340 if( rsurface15+
RTOL >= r15a || rsurface35+
RTOL >= r35a ||
3341 rsurface36+
RTOL >= r36a || rsurface16+
RTOL >= r16a )
3342 { do_surface =
true; }
3346 cart2sph( r_end, lat_end, lon_end, x+
dx*l_end, y+dy*l_end,
3347 z+dz*l_end, lat_start, lon_start, za_start, aa_start );
3349 lat_end -= lat_corr;
3350 lon_end -= lon_corr;
3356 { lon_end = lon_start; }
3361 r15a, r35a, r36a, r16a, lat_end, lon_end );
3367 rsurface15, rsurface35, rsurface36, rsurface16,
3369 if( r_surface >= rlow && r_end <= r_surface )
3370 { inside =
false; endface = 7; }
3375 if( lat_end < lat1 )
3376 { inside =
false; endface = 1; }
3377 else if( lat_end > lat3 )
3378 { inside =
false; endface = 3; }
3379 else if( lon_end < lon5 )
3380 { inside =
false; endface = 5; }
3381 else if( lon_end > lon6 )
3382 { inside =
false; endface = 6; }
3383 else if( r_end < rlow )
3384 { inside =
false; endface = 2; }
3388 r15b, r35b, r36b, r16b, lat_end, lon_end );
3390 { inside =
false; endface = 4; }
3404 l_end = ( l_out + l_in ) / 2;
3415 if( ( l_out - l_in ) <
LACC )
3418 { l_end = ( l_out + l_in ) / 2; }
3429 n =
Index( ceil(
abs( l_end / lmax ) ) );
3441 lat_v[0] = lat_start;
3442 lon_v[0] = lon_start;
3450 for(
Index j=1; j<=n; j++ )
3453 cart2poslos( r_v[j], lat_v[j], lon_v[j], za_v[j], aa_v[j], x+
dx*l,
3454 y+dy*l, z+dz*l,
dx, dy, dz, ppc, lat_start, lon_start,
3455 za_start, aa_start );
3473 r36a, r16a, lat_v[j], lon_v[j] );
3477 lat1, lat3, lon5, lon6, rsurface15, rsurface35,
3478 rsurface36, rsurface16, lat_v[j], lon_v[j] );
3479 const Numeric r_test =
max( r_surface, rlow );
3480 if( r_v[j] < r_test )
3481 { ready =
false;
break; }
3483 else if( r_v[j] < rlow )
3484 { ready =
false;
break; }
3487 r36b, r16b, lat_v[j], lon_v[j] );
3489 { ready =
false;
break; }
3499 { lat_v[n] = lat1; }
3500 else if( endface == 2 )
3502 r15a, r35a, r36a, r16a,
3503 lat_v[n], lon_v[n] ); }
3504 else if( endface == 3 )
3505 { lat_v[n] = lat3; }
3506 else if( endface == 4 )
3508 r15b, r35b, r36b, r16b,
3509 lat_v[n], lon_v[n] ); }
3510 else if( endface == 5 )
3511 { lon_v[n] = lon5; }
3512 else if( endface == 6 )
3513 { lon_v[n] = lon6; }
3514 else if( endface == 7 )
3516 rsurface15, rsurface35,
3517 rsurface36, rsurface16,
3518 lat_v[n], lon_v[n] ); }
3526 r_start, lat_start, lon_start, za_start, aa_start,
3527 l, icall+1, ppc, lmax, lat1, lat3, lon5, lon6,
3528 r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b,
3529 rsurface15, rsurface35, rsurface36, rsurface16 );
3563 Numeric r_start, lat_start, lon_start, za_start, aa_start;
3566 Index ip, ilat, ilon;
3570 Numeric lat1, lat3, lon5, lon6;
3571 Numeric r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b;
3572 Numeric rsurface15, rsurface35, rsurface36, rsurface16;
3575 ppath_start_3d( r_start, lat_start, lon_start, za_start, aa_start,
3576 ip, ilat, ilon, lat1, lat3, lon5, lon6,
3577 r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b,
3578 rsurface15, rsurface35, rsurface36, rsurface16,
3579 ppath, lat_grid, lon_grid, z_field, refellipsoid, z_surface );
3592 Vector r_v, lat_v, lon_v, za_v, aa_v;
3597 r_start, lat_start, lon_start, za_start, aa_start,
3598 -1, 0, ppc, lmax, lat1, lat3, lon5, lon6,
3599 r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b,
3600 rsurface15, rsurface35, rsurface36, rsurface16 );
3605 Vector(np,1),
Vector(np,1), lat_grid, lon_grid, z_field,
3606 refellipsoid, ip, ilat, ilon, endface, ppc );
3674 const Agenda& refr_index_air_agenda,
3687 Numeric refr_index_air, refr_index_air_group;
3689 refr_index_air_agenda, p_grid, refellipsoid,
3690 z_field, t_field, vmr_field, f_grid, r );
3691 r_array.push_back( r );
3692 lat_array.push_back( lat );
3693 za_array.push_back( za );
3694 n_array.push_back( refr_index_air );
3695 ng_array.push_back( refr_index_air_group );
3699 Numeric lstep, lcum = 0, dlat;
3708 ppc_step, -1, r1, r3, rsurface );
3709 assert( r_v.
nelem() == 2 );
3717 if( lstep <= lraytrace )
3720 dlat = lat_v[1] - lat;
3734 { za_flagside = 180-za_flagside; }
3741 dlat = lat_new - lat;
3750 refr_index_air_agenda, p_grid, refellipsoid, z_field,
3751 t_field, vmr_field, f_grid, r );
3758 za += (
RAD2DEG * lstep / refr_index_air) * ( -sin(za_rad) * dndr );
3767 if( ready || ( lmax > 0 && lcum + lraytrace > lmax ) )
3769 r_array.push_back( r );
3770 lat_array.push_back( lat );
3771 za_array.push_back( za );
3772 n_array.push_back( refr_index_air );
3773 ng_array.push_back( refr_index_air_group );
3774 l_array.push_back( lcum );
3820 const Agenda& refr_index_air_agenda,
3821 const String& rtrace_method,
3825 Numeric r_start, lat_start, za_start;
3841 Numeric refr_index_air, refr_index_air_group;
3843 refr_index_air_agenda, p_grid, refellipsoid,
3844 z_field, t_field, vmr_field, f_grid, r_start );
3855 Array<Numeric> r_array, lat_array, za_array, l_array, n_array, ng_array;
3858 if( rtrace_method ==
"linear_basic" )
3869 n_array, ng_array, endface, p_grid, refellipsoid, z_field, t_field,
3870 vmr_field, f_grid, lmax, refr_index_air_agenda, lraytrace,
3871 refellipsoid[0] + z_surface, refellipsoid[0]+z_field(ip,0,0),
3872 refellipsoid[0]+z_field(ip+1,0,0), r_start, lat_start, za_start );
3883 Vector r_v(np), lat_v(np), za_v(np), l_v(np-1), n_v(np), ng_v(np);
3884 for(
Index i=0; i<np; i++ )
3886 r_v[i] = r_array[i];
3887 lat_v[i] = lat_array[i];
3888 za_v[i] = za_array[i];
3889 n_v[i] = n_array[i];
3890 ng_v[i] = ng_array[i];
3892 { l_v[i] = l_array[i]; }
3895 ppath_end_1d( ppath, r_v, lat_v, za_v, l_v, n_v, ng_v, z_field(
joker,0,0),
3896 refellipsoid, ip, endface, ppc );
3964 const Agenda& refr_index_air_agenda,
3982 Numeric refr_index_air, refr_index_air_group;
3984 refr_index_air_agenda, p_grid, lat_grid, refellipsoid,
3985 z_field, t_field, vmr_field, f_grid, r, lat );
3986 r_array.push_back( r );
3987 lat_array.push_back( lat );
3988 za_array.push_back( za );
3989 n_array.push_back( refr_index_air );
3990 ng_array.push_back( refr_index_air_group );
3994 Numeric lstep, lcum = 0, dlat;
4003 lraytrace, 0, ppc_step, -1, lat1, lat3,
4004 r1a, r3a, r3b, r1b, rsurface1, rsurface3 );
4005 assert( r_v.
nelem() == 2 );
4013 if( lstep <= lraytrace )
4016 dlat = lat_v[1] - lat;
4030 { za_flagside =
sign(za)*180-za_flagside; }
4037 dlat = lat_new - lat;
4046 else if( lat > lat3 )
4053 dndlat, refr_index_air_agenda, p_grid, lat_grid,
4054 refellipsoid, z_field, t_field, vmr_field, f_grid,
4062 za += (
RAD2DEG * lstep / refr_index_air) * ( -sin(za_rad) * dndr +
4063 cos(za_rad) * dndlat );
4073 if( lat == lat1 && za < 0 )
4074 { endface = 1; ready = 1; }
4075 else if( lat == lat3 && za > 0 )
4076 { endface = 3; ready = 1; }
4079 if( ready || ( lmax > 0 && lcum + lraytrace > lmax ) )
4081 r_array.push_back( r );
4082 lat_array.push_back( lat );
4083 za_array.push_back( za );
4084 n_array.push_back( refr_index_air );
4085 ng_array.push_back( refr_index_air_group );
4086 l_array.push_back( lcum );
4133 const Agenda& refr_index_air_agenda,
4134 const String& rtrace_method,
4138 Numeric r_start, lat_start, za_start;
4144 Numeric lat1, lat3, r1a, r3a, r3b, r1b, rsurface1, rsurface3;
4148 lat1, lat3, r1a, r3a, r3b, r1b, rsurface1, rsurface3,
4149 ppath, lat_grid, z_field(
joker,
joker,0), refellipsoid,
4158 Array<Numeric> r_array, lat_array, za_array, l_array, n_array, ng_array;
4161 if( rtrace_method ==
"linear_basic" )
4164 n_array, ng_array, endface, p_grid, lat_grid,
4165 refellipsoid, z_field, t_field, vmr_field,
4167 refr_index_air_agenda, lraytrace, lat1, lat3,
4168 rsurface1, rsurface3, r1a, r3a, r3b, r1b,
4169 r_start, lat_start, za_start );
4180 Vector r_v(np), lat_v(np), za_v(np), l_v(np-1), n_v(np), ng_v(np);
4181 for(
Index i=0; i<np; i++ )
4183 r_v[i] = r_array[i];
4184 lat_v[i] = lat_array[i];
4185 za_v[i] = za_array[i];
4186 n_v[i] = n_array[i];
4187 ng_v[i] = ng_array[i];
4189 { l_v[i] = l_array[i]; }
4192 ppath_end_2d( ppath, r_v, lat_v, za_v, l_v, n_v, ng_v, lat_grid,
4193 z_field(
joker,
joker,0), refellipsoid, ip, ilat, endface, -1 );
4278 const Agenda& refr_index_air_agenda,
4306 Numeric refr_index_air, refr_index_air_group;
4308 refr_index_air_agenda, p_grid, lat_grid, lon_grid,
4309 refellipsoid, z_field, t_field, vmr_field, f_grid,
4311 r_array.push_back( r );
4312 lat_array.push_back( lat );
4313 lon_array.push_back( lon );
4314 za_array.push_back( za );
4315 aa_array.push_back( aa );
4316 n_array.push_back( refr_index_air );
4317 ng_array.push_back( refr_index_air_group );
4320 Vector r_v, lat_v, lon_v, za_v, aa_v;
4331 r, lat, lon, za, aa, lraytrace, 0,
4332 ppc_step, -1, lat1, lat3, lon5, lon6,
4333 r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b,
4334 rsurface15, rsurface35, rsurface36, rsurface16 );
4335 assert( r_v.
nelem() == 2 );
4340 if( lstep <= lraytrace )
4353 Numeric x, y, z,
dx, dy, dz, lat_new, lon_new;
4355 poslos2cart( x, y, z,
dx, dy, dz, r, lat, lon, za, aa );
4357 cart2poslos( r, lat_new, lon_new, za_new, aa_new, x+
dx*lstep,
4358 y+dy*lstep, z+dz*lstep,
dx, dy, dz, ppc_step,
4372 dndr, dndlat, dndlon, refr_index_air_agenda,
4373 p_grid, lat_grid, lon_grid, refellipsoid,
4374 z_field, t_field, vmr_field,
4375 f_grid, r, lat, lon );
4381 const Numeric sinza = sin( za_rad );
4382 const Numeric sinaa = sin( aa_rad );
4383 const Numeric cosaa = cos( aa_rad );
4385 Vector los(2); los[0] = za_new; los[1] = aa_new;
4387 if( za < ANGTOL || za > 180-
ANGTOL )
4389 los[0] += aterm * ( cos(za_rad) *
4390 ( cosaa * dndlat + sinaa * dndlon ) );
4391 los[1] =
RAD2DEG * atan2( dndlon, dndlat);
4395 los[0] += aterm * ( -sinza * dndr + cos(za_rad) *
4396 ( cosaa * dndlat + sinaa * dndlon ) );
4397 los[1] += aterm * sinza * ( cosaa * dndlon - sinaa * dndlat );
4408 if( za > 0 && za < 180 )
4410 if( lon == lon5 && aa < 0 )
4411 { endface = 5; ready = 1; }
4412 else if( lon == lon6 && aa > 0 )
4413 { endface = 6; ready = 1; }
4414 else if( lat == lat1 && lat != -90 &&
abs( aa ) > 90 )
4415 { endface = 1; ready = 1; }
4416 else if( lat == lat3 && lat != 90 &&
abs( aa ) < 90 )
4417 { endface = 3; ready = 1; }
4421 if( ready || ( lmax > 0 && lcum + lraytrace > lmax ) )
4423 r_array.push_back( r );
4424 lat_array.push_back( lat );
4425 lon_array.push_back( lon );
4426 za_array.push_back( za );
4427 aa_array.push_back( aa );
4428 n_array.push_back( refr_index_air );
4429 ng_array.push_back( refr_index_air_group );
4430 l_array.push_back( lcum );
4479 const Agenda& refr_index_air_agenda,
4480 const String& rtrace_method,
4484 Numeric r_start, lat_start, lon_start, za_start, aa_start;
4487 Index ip, ilat, ilon;
4491 Numeric lat1, lat3, lon5, lon6;
4492 Numeric r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b;
4493 Numeric rsurface15, rsurface35, rsurface36, rsurface16;
4496 ppath_start_3d( r_start, lat_start, lon_start, za_start, aa_start,
4497 ip, ilat, ilon, lat1, lat3, lon5, lon6,
4498 r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b,
4499 rsurface15, rsurface35, rsurface36, rsurface16,
4500 ppath, lat_grid, lon_grid, z_field, refellipsoid, z_surface );
4508 Array<Numeric> r_array, lat_array, lon_array, za_array, aa_array;
4512 if( rtrace_method ==
"linear_basic" )
4515 aa_array, l_array, n_array, ng_array, endface,
4516 refellipsoid, p_grid, lat_grid, lon_grid,
4517 z_field, t_field, vmr_field,
4518 f_grid, lmax, refr_index_air_agenda, lraytrace,
4519 lat1, lat3, lon5, lon6,
4520 rsurface15, rsurface35, rsurface36, rsurface16,
4521 r15a, r35a, r36a, r16a, r15b, r35b, r36b, r16b,
4522 r_start, lat_start, lon_start, za_start, aa_start );
4533 Vector r_v(np), lat_v(np), lon_v(np), za_v(np), aa_v(np), l_v(np-1);
4534 Vector n_v(np), ng_v(np);
4535 for(
Index i=0; i<np; i++ )
4537 r_v[i] = r_array[i];
4538 lat_v[i] = lat_array[i];
4539 lon_v[i] = lon_array[i];
4540 za_v[i] = za_array[i];
4541 aa_v[i] = aa_array[i];
4542 n_v[i] = n_array[i];
4543 ng_v[i] = ng_array[i];
4545 { l_v[i] = l_array[i]; }
4549 ppath_end_3d( ppath, r_v, lat_v, lon_v, za_v, aa_v, l_v, n_v, ng_v, lat_grid,
4550 lon_grid, z_field, refellipsoid, ip, ilat, ilon, endface, -1 );
4608 const Index& atmosphere_dim,
4615 const Index& cloudbox_on,
4617 const bool& ppath_inside_cloudbox_do,
4635 if( atmosphere_dim == 1 )
4638 ppath.
end_pos[0] = rte_pos[0];
4640 ppath.
end_los[0] = rte_los[0];
4643 if( rte_pos[0] < z_field(lp,0,0) )
4646 if( (rte_pos[0] +
RTOL) < z_surface(0,0) )
4649 os <<
"The ppath starting point is placed "
4650 << (z_surface(0,0) - rte_pos[0])/1e3
4651 <<
" km below the surface.";
4652 throw runtime_error(os.str());
4657 ppath.
r[0] = refellipsoid[0] + rte_pos[0];
4666 if( ppath.
pos(0,0) <= z_surface(0,0) && ppath.
los(0,0) > 90 )
4671 if( cloudbox_on && !ppath_inside_cloudbox_do )
4674 if( fgp >= cloudbox_limits[0] && fgp <= cloudbox_limits[1] )
4682 assert( fgp >= cloudbox_limits[0] && fgp <= cloudbox_limits[1] );
4696 if( rte_los[0] <= 90 ||
4697 ppath.
constant >= refellipsoid[0] + z_field(lp,0,0) )
4699 ppath.
pos(0,0) = rte_pos[0];
4701 ppath.
r[0] = refellipsoid[0] + rte_pos[0];
4702 ppath.
los(0,0) = rte_los[0];
4705 out1 <<
" --- WARNING ---, path is totally outside of the "
4706 <<
"model atmosphere\n";
4712 ppath.
r[0] = refellipsoid[0] + z_field(lp,0,0);
4713 ppath.
pos(0,0) = z_field(lp,0,0);
4719 refellipsoid[0] + rte_pos[0] ) -
4723 ppath.
gp_p[0].idx = lp-1;
4724 ppath.
gp_p[0].fd[0] = 1;
4725 ppath.
gp_p[0].fd[1] = 0;
4728 if( cloudbox_on && cloudbox_limits[1] == lp )
4736 else if( atmosphere_dim == 2 )
4739 ppath.
end_pos[0] = rte_pos[0];
4740 ppath.
end_pos[1] = rte_pos[1];
4741 ppath.
end_los[0] = rte_los[0];
4750 bool islatin =
false;
4753 if( rte_pos[1] > lat_grid[0] && rte_pos[1] < lat_grid[llat] )
4756 gridpos( gp_lat, lat_grid, rte_pos[1] );
4758 z_toa =
interp( itw, z_field(lp,
joker,0), gp_lat );
4759 r_e =
refell2d( refellipsoid, lat_grid, gp_lat );
4762 { r_e =
refell2r( refellipsoid, rte_pos[1] ); }
4765 if( islatin && rte_pos[0] < z_toa )
4770 if( (rte_pos[0] +
RTOL) < z_s )
4773 os <<
"The ppath starting point is placed "
4774 << (z_s - rte_pos[0])/1e3 <<
" km below the surface.";
4775 throw runtime_error(os.str());
4780 ppath.
r[0] = r_e + rte_pos[0];
4786 atmosphere_dim, p_grid, lat_grid, lon_grid, z_field, rte_pos );
4793 if( ppath.
pos(0,0) <= z_s )
4798 z_surface(
joker,0), gp_lat, ppath.
los(0,0) );
4812 if( cloudbox_on && !ppath_inside_cloudbox_do )
4816 if( fgp >= cloudbox_limits[0] && fgp <= cloudbox_limits[1] &&
4817 fgl >= cloudbox_limits[2] && fgl <= cloudbox_limits[3] )
4826 assert( fgp >= cloudbox_limits[0] && fgp <= cloudbox_limits[1] &&
4827 fgl >= cloudbox_limits[2] && fgl <= cloudbox_limits[3] );
4835 if( ( rte_pos[1] <= lat_grid[0] && rte_los[0] <= 0 ) ||
4836 ( rte_pos[1] >= lat_grid[llat] && rte_los[0] >= 0 ) )
4839 os <<
"The sensor is outside (or at the limit) of the model "
4840 <<
"atmosphere but\nlooks in the wrong direction (wrong sign "
4841 <<
"for the zenith angle?).\nThis case includes nadir "
4842 <<
"looking exactly at the latitude end points.";
4843 throw runtime_error( os.str() );
4849 const Numeric r_p = r_e + rte_pos[0];
4854 Numeric r_toa_min = 99e99, r_toa_max = -1;
4855 for(
Index ilat=0; ilat<=llat; ilat++ )
4857 r_toa[ilat] =
refell2r( refellipsoid, lat_grid[ilat] ) +
4859 if( r_toa[ilat] < r_toa_min )
4860 { r_toa_min = r_toa[ilat]; }
4861 if( r_toa[ilat] > r_toa_max )
4862 { r_toa_max = r_toa[ilat]; }
4864 if( r_p <= r_toa_max )
4867 os <<
"The sensor is horizontally outside (or at the limit) of "
4868 <<
"the model\natmosphere, but is at a radius smaller than "
4869 <<
"the maximum value of\nthe top-of-the-atmosphere radii. "
4870 <<
"This is not allowed. Make the\nmodel atmosphere larger "
4871 <<
"to also cover the sensor position?";
4872 throw runtime_error( os.str() );
4876 if(
abs(rte_los[0]) <= 90 )
4878 ppath.
pos(0,0) = rte_pos[0];
4879 ppath.
pos(0,1) = rte_pos[1];
4880 ppath.
r[0] = r_e + rte_pos[0];
4881 ppath.
los(0,0) = rte_los[0];
4884 out1 <<
" ------- WARNING -------: path is totally outside of "
4885 <<
"the model atmosphere\n";
4891 bool above=
false, ready=
false, failed=
false;
4898 { above=
true; ready=
true; }
4901 if( islatin || ppath.
constant > r_toa_min )
4909 while( !ready && !failed )
4926 if( latt < lat_grid[0] || latt > lat_grid[llat] )
4938 gridpos( gp_latt, lat_grid, latt );
4940 rt =
interp( itwt, r_toa, gp_latt );
4948 os <<
"The path does not enter the model atmosphere. It "
4949 <<
"reaches the\ntop of the atmosphere "
4950 <<
"altitude around latitude " << latt <<
" deg.";
4951 throw runtime_error( os.str() );
4955 ppath.
pos(0,0) = rte_pos[0];
4956 ppath.
pos(0,1) = rte_pos[1];
4957 ppath.
r[0] = r_e + rte_pos[0];
4958 ppath.
los(0,0) = rte_los[0];
4961 out1 <<
" ------- WARNING -------: path is totally outside "
4962 <<
"of the model atmosphere\n";
4976 ppath.
gp_p[0].idx = lp-1;
4977 ppath.
gp_p[0].fd[0] = 1;
4978 ppath.
gp_p[0].fd[1] = 0;
4984 if( cloudbox_on && cloudbox_limits[1] == lp )
4987 if( fgp >= (
Numeric)cloudbox_limits[2] &&
4988 fgp <= (
Numeric)cloudbox_limits[3] )
5006 resolve_lon( lon2use, lon_grid[0], lon_grid[llon] );
5009 ppath.
end_pos[0] = rte_pos[0];
5010 ppath.
end_pos[1] = rte_pos[1];
5012 ppath.
end_los[0] = rte_los[0];
5013 ppath.
end_los[1] = rte_los[1];
5019 bool islatlonin =
false;
5023 if( rte_pos[1] >= lat_grid[0] && rte_pos[1] <= lat_grid[llat] &&
5024 lon2use >= lon_grid[0] && lon2use <= lon_grid[llon] )
5027 gridpos( gp_lat, lat_grid, rte_pos[1] );
5028 gridpos( gp_lon, lon_grid, lon2use );
5031 r_e =
refell2d( refellipsoid, lat_grid, gp_lat );
5034 { r_e =
refell2r( refellipsoid, rte_pos[1] ); }
5037 if( islatlonin && rte_pos[0] < z_toa )
5039 const Numeric z_s =
interp( itw, z_surface, gp_lat, gp_lon );
5042 if( (rte_pos[0] +
RTOL) < z_s )
5045 os <<
"The ppath starting point is placed "
5046 << (z_s - rte_pos[0])/1e3 <<
" km below the surface.";
5047 throw runtime_error(os.str());
5052 ppath.
r[0] = r_e + rte_pos[0];
5057 atmosphere_dim, p_grid, lat_grid, lon_grid, z_field, rte_pos );
5065 if( ppath.
pos(0,0) <= z_s )
5070 z_surface, gp_lat, gp_lon, ppath.
los(0,1) );
5084 if( cloudbox_on && !ppath_inside_cloudbox_do )
5089 if( fgp >= cloudbox_limits[0] && fgp <= cloudbox_limits[1] &&
5090 fgl >= cloudbox_limits[2] && fgl <= cloudbox_limits[3] &&
5091 fgo >= cloudbox_limits[4] && fgo <= cloudbox_limits[5] )
5101 assert( fgp >= cloudbox_limits[0] && fgp <= cloudbox_limits[1] &&
5102 fgl >= cloudbox_limits[2] && fgl <= cloudbox_limits[3] &&
5103 fgo >= cloudbox_limits[4] && fgo <= cloudbox_limits[5] );
5112 if( ( rte_pos[1] <= lat_grid[0] &&
abs( rte_los[1] ) >= 90 ) ||
5113 ( rte_pos[1] >= lat_grid[llat] &&
abs( rte_los[1] ) <= 90 ) )
5116 os <<
"The sensor is north or south (or at the limit) of the "
5117 <<
"model atmosphere\nbut looks in the wrong direction.";
5118 throw runtime_error( os.str() );
5124 if( ( lon2use <= lon_grid[0] && rte_los[1] < 0 ) ||
5125 ( lon2use >= lon_grid[llon] && rte_los[1] > 0 ) )
5128 os <<
"The sensor is east or west (or at the limit) of the "
5129 <<
"model atmosphere\nbut looks in the wrong direction.";
5130 throw runtime_error( os.str() );
5136 const Numeric r_p = r_e + rte_pos[0];
5140 Matrix r_toa(llat+1,llon+1);
5141 Numeric r_toa_min = 99e99, r_toa_max = -1;
5142 for(
Index ilat=0; ilat<=llat; ilat++ )
5145 for(
Index ilon=0; ilon<=llon; ilon++ )
5147 r_toa(ilat,ilon) = r_lat+ z_field(lp,ilat,ilon);
5148 if( r_toa(ilat,ilon) < r_toa_min )
5149 { r_toa_min = r_toa(ilat,ilon); }
5150 if( r_toa(ilat,ilon) > r_toa_max )
5151 { r_toa_max = r_toa(ilat,ilon); }
5155 if( r_p <= r_toa_max )
5158 os <<
"The sensor is horizontally outside (or at the limit) of "
5159 <<
"the model\natmosphere, but is at a radius smaller than "
5160 <<
"the maximum value of\nthe top-of-the-atmosphere radii. "
5161 <<
"This is not allowed. Make the\nmodel atmosphere larger "
5162 <<
"to also cover the sensor position?";
5163 throw runtime_error( os.str() );
5167 if( rte_los[0] <= 90 )
5169 ppath.
pos(0,0) = rte_pos[0];
5170 ppath.
pos(0,1) = rte_pos[1];
5171 ppath.
pos(0,1) = lon2use;
5172 ppath.
r[0] = r_e + rte_pos[0];
5173 ppath.
los(0,0) = rte_los[0];
5174 ppath.
los(0,1) = rte_los[1];
5177 out1 <<
" ------- WARNING -------: path is totally outside of "
5178 <<
"the model atmosphere\n";
5184 bool above=
false, ready=
false, failed=
false;
5191 { above=
true; ready=
true; }
5194 if( islatlonin || ppath.
constant > r_toa_min )
5203 rte_los[0], rte_los[1] );
5207 while( !ready && !failed )
5220 lon2use, rte_los[0], ppath.
constant,
5221 x, y, z,
dx, dy, dz );
5225 if( latt < lat_grid[0] || latt > lat_grid[llat] ||
5226 lont < lon_grid[0] || lont > lon_grid[llon] )
5238 gridpos( gp_latt, lat_grid, latt );
5239 gridpos( gp_lont, lon_grid, lont );
5241 rt =
interp( itwt, r_toa, gp_latt, gp_lont );
5249 os <<
"The path does not enter the model atmosphere. It\n"
5250 <<
"reaches the top of the atmosphere altitude around:\n"
5251 <<
" lat: " << latt <<
" deg.\n lon: " << lont
5253 throw runtime_error( os.str() );
5257 ppath.
pos(0,0) = rte_pos[0];
5258 ppath.
pos(0,1) = rte_pos[1];
5259 ppath.
pos(0,1) = lon2use;
5260 ppath.
r[0] = r_e + rte_pos[0];
5261 ppath.
los(0,0) = rte_los[0];
5262 ppath.
los(0,1) = rte_los[1];
5265 out1 <<
" ------- WARNING -------: path is totally outside "
5266 <<
"of the model atmosphere\n";
5274 ppath.
los(0,0), ppath.
los(0,1),x+
dx*lt, y+dy*lt,
5275 z+dz*lt,
dx, dy, dz, ppath.
constant, rte_pos[1],
5276 lon2use, rte_los[0], rte_los[1] );
5277 assert(
abs( ppath.
r[0] -rt ) <
RTOL );
5285 ppath.
gp_p[0].idx = lp-1;
5286 ppath.
gp_p[0].fd[0] = 1;
5287 ppath.
gp_p[0].fd[1] = 0;
5294 if( cloudbox_on && cloudbox_limits[1] == lp )
5298 if( fgp1 >= (
Numeric)cloudbox_limits[2] &&
5299 fgp1 <= (
Numeric)cloudbox_limits[3] &&
5300 fgp2 >= (
Numeric)cloudbox_limits[4] &&
5301 fgp2 <= (
Numeric)cloudbox_limits[5])
5347 const Agenda& ppath_step_agenda,
5348 const Index& atmosphere_dim,
5356 const Vector& refellipsoid,
5358 const Index& cloudbox_on,
5362 const Numeric& ppath_lraytrace,
5363 const bool& ppath_inside_cloudbox_do,
5374 if( ppath_inside_cloudbox_do && !cloudbox_on )
5375 throw runtime_error(
"The WSV *ppath_inside_cloudbox_do* can only be set "
5376 "to 1 if also *cloudbox_on* is 1." );
5392 lon_grid, z_field, refellipsoid, z_surface,
5393 cloudbox_on, cloudbox_limits, ppath_inside_cloudbox_do,
5394 rte_pos, rte_los, verbosity );
5428 z_field, vmr_field, f_grid,
5429 ppath_step_agenda );
5434 const Index n = ppath_step.
np;
5440 throw runtime_error(
5441 "10 000 path points have been reached. Is this an infinite loop?" );
5449 if( !ppath_inside_cloudbox_do )
5455 (
abs(ppath_step.
los(n-1,0))<90 &&
5462 if( atmosphere_dim == 2 )
5468 os <<
"The path exits the atmosphere through the lower "
5469 <<
"latitude end face.\nThe exit point is at an altitude"
5470 <<
" of " << ppath_step.
pos(n-1,0)/1e3 <<
" km.";
5471 throw runtime_error( os.str() );
5476 os <<
"The path exits the atmosphere through the upper "
5477 <<
"latitude end face.\nThe exit point is at an altitude"
5478 <<
" of " << ppath_step.
pos(n-1,0)/1e3 <<
" km.";
5479 throw runtime_error( os.str() );
5482 if( atmosphere_dim == 3 )
5485 if( lat_grid[0] > -90 &&
5489 os <<
"The path exits the atmosphere through the lower "
5490 <<
"latitude end face.\nThe exit point is at an altitude"
5491 <<
" of " << ppath_step.
pos(n-1,0)/1e3 <<
" km.";
5492 throw runtime_error( os.str() );
5494 if( lat_grid[imax_lat] < 90 &&
5498 os <<
"The path exits the atmosphere through the upper "
5499 <<
"latitude end face.\nThe exit point is at an altitude"
5500 <<
" of " << ppath_step.
pos(n-1,0)/1e3 <<
" km.";
5501 throw runtime_error( os.str() );
5508 ppath_step.
los(n-1,1) < 0 &&
5509 abs( ppath_step.
pos(n-1,1) ) < 90 )
5512 if( lon_grid[imax_lon] - lon_grid[0] >= 360 )
5514 ppath_step.
pos(n-1,2) = ppath_step.
pos(n-1,2) + 360;
5516 ppath_step.
pos(n-1,2) );
5521 os <<
"The path exits the atmosphere through the lower "
5522 <<
"longitude end face.\nThe exit point is at an "
5523 <<
"altitude of " << ppath_step.
pos(n-1,0)/1e3
5525 throw runtime_error( os.str() );
5530 ppath_step.
los(n-1,1) > 0 &&
5531 abs( ppath_step.
pos(n-1,1) ) < 90 )
5534 if( lon_grid[imax_lon] - lon_grid[0] >= 360 )
5536 ppath_step.
pos(n-1,2) = ppath_step.
pos(n-1,2) - 360;
5538 ppath_step.
pos(n-1,2) );
5543 os <<
"The path exits the atmosphere through the upper "
5544 <<
"longitude end face.\nThe exit point is at an "
5545 <<
"altitude of " << ppath_step.
pos(n-1,0)/1e3
5547 throw runtime_error( os.str() );
5558 if( ipos >=
Numeric( cloudbox_limits[0] ) &&
5559 ipos <=
Numeric( cloudbox_limits[1] ) )
5561 if( atmosphere_dim == 1 )
5567 if( ipos >=
Numeric( cloudbox_limits[2] ) &&
5568 ipos <=
Numeric( cloudbox_limits[3] ) )
5570 if( atmosphere_dim == 2 )
5577 if( ipos >=
Numeric( cloudbox_limits[4] ) &&
5578 ipos <=
Numeric( cloudbox_limits[5] ) )
5598 assert( ipos1 >= cloudbox_limits[0] );
5599 assert( ipos1 <= cloudbox_limits[1] );
5600 if( ipos1 <= cloudbox_limits[0] && ipos1 < ipos2 )
5603 else if( ipos1 >=
Numeric( cloudbox_limits[1] ) && ipos1 > ipos2 )
5606 else if( atmosphere_dim > 1 )
5611 assert( ipos1 >= cloudbox_limits[2] );
5612 assert( ipos1 <= cloudbox_limits[3] );
5613 if( ipos1 <=
Numeric( cloudbox_limits[2] ) && ipos1 < ipos2 )
5616 else if( ipos1 >=
Numeric( cloudbox_limits[3] ) && ipos1 > ipos2 )
5619 else if ( atmosphere_dim > 2 )
5624 assert( ipos1 >= cloudbox_limits[4] );
5625 assert( ipos1 <= cloudbox_limits[5] );
5626 if( ipos1 <=
Numeric( cloudbox_limits[4] ) && ipos1<ipos2 )
5629 else if( ipos1 >=
Numeric( cloudbox_limits[5] ) &&
5648 ppath_array.push_back( ppath_step );
5668 z_field, vmr_field, f_grid,
5669 ppath_step_agenda );
5679 for(
Index i=0; i<na; i++ )
5685 Index n = ppath_array[i].np;
5693 ppath.
r[
Range(np,n-i1) ] = ppath_array[i].r[
Range(i1,n-i1) ];
5699 ppath_array[i].nreal[
Range(i1,n-i1) ];
5701 ppath_array[i].ngroup[
Range(i1,n-i1) ];
5702 ppath.
lstep[
Range(np-i1,n-1) ] = ppath_array[i].lstep;
5705 for(
Index j=i1; j<n; j++ )
5706 { ppath.
gp_p[np+j-i1] = ppath_array[i].gp_p[j]; }
5707 if( atmosphere_dim >= 2 )
5709 for(
Index j=i1; j<n; j++ )
5710 { ppath.
gp_lat[np+j-i1] = ppath_array[i].gp_lat[j]; }
5712 if( atmosphere_dim == 3 )
5714 for(
Index j=i1; j<n; j++ )
5715 { ppath.
gp_lon[np+j-i1] = ppath_array[i].gp_lon[j]; }