40 assert(
abs( sqrt( dx*dx + dy*dy + dz*dz ) - 1 ) < 1e-6 );
46 const double coslat = cos(
DEG2RAD * lat );
47 const double sinlat = sin(
DEG2RAD * lat );
48 const double coslon = cos(
DEG2RAD * lon );
49 const double sinlon = sin(
DEG2RAD * lon );
50 const double dr = coslat*coslon*dx + coslat*sinlon*dy + sinlat*dz;
51 const double dlat = -sinlat*coslon/r*dx - sinlat*sinlon/r*dy + coslat/r*dz;
52 const double dlon = -sinlon/coslat/r*dx + coslon/coslat/r*dy;
57 if( za < ANGTOL || za > 180-
ANGTOL )
78 { aa =
RAD2DEG * atan2( dy, dx ); }
104 r = sqrt( x*x + y*y + z*z );
149 sqrt( r1*r1 + r2*r2 - 2 * r1 * r2 * cos(
DEG2RAD * dlat ) ) );
204 assert( lat_start >= -90 );
205 assert( lat_start <= 90 );
206 assert( lat_hit >= -90 );
207 assert( lat_hit <= 90 );
210 if( za_start == 0 || za_start == 180 ||
abs(lat_hit) == 90 )
214 else if(
abs( lat_hit ) < 1e-7 )
220 const Numeric a = t2 * ( dx*dx + dy*dy ) - dz*dz;
221 const Numeric b = 2 * ( t2 * ( x*dx + y*dy ) - z*dz );
222 const Numeric c = t2 * ( x*x + y*y ) - z*z;
232 const Numeric e = -0.5*sqrt(b*b-4*a*c)/a;
241 if( l1 > 0 &&
abs(
sign(z+dz*l1)-zsign)>0.01 )
243 if( l2 > 0 &&
abs(
sign(z+dz*l2)-zsign)>0.01 )
253 if( lmin >= 0 && lmax < 1e-6 )
259 else if( lmax > 1e-6 )
271 r = sqrt( pow(xp,2.0) + pow(yp,2.0) + pow(z+dz*l,2.0) );
272 lon =
RAD2DEG * atan2( yp, xp );
326 if( lon_hit == lon_start || za_start == 0 || za_start == 180 ||
327 aa_start == 0 ||
abs(aa_start) == 180 )
332 const double tanlon = tan(
DEG2RAD * lon_hit );
333 l = ( y - x*tanlon ) / ( dx*tanlon - dy );
342 r = sqrt( pow(x+dx*l,2.0) + pow(y+dy*l,2.0) + pow(zp,2.0) );
343 lat =
RAD2DEG * asin( zp / r );
411 assert( za_start <= 180 );
412 assert( lat_start >=lat1 && lat_start <= lat3 );
413 assert( lon_start >=lon5 && lon_start <= lon6 );
427 l =
max( 1e-9, r - r_start0 );
432 else if( za_start > 180-
ANGTOL )
440 l =
max( 1e-9, r_start0 - r );
454 if( rmax-rmin <
RTOL/10 )
460 {
if( r_start < rmax ) { r_start = r = rmax; } }
462 {
if( r_start > rmin ) { r_start = r = rmin; } }
464 r_crossing_3d( lat, lon, l, r, r_start, lat_start, lon_start,
465 za_start, ppc, x, y, z, dx, dy, dz );
468 if( lat > lat3 || lat < lat1 || lon > lon6 || lon < lon5 )
478 {
if( r_start < rmin ) { r_start = rmin; } }
480 {
if( r_start > rmax ) { r_start = rmax; } }
486 r_crossing_3d( lat, lon, l, r, r_start, lat_start, lon_start,
487 za_start, ppc, x, y, z, dx, dy, dz );
489 else if( r_start < rmin )
492 r_crossing_3d( lat, lon, l, r, r_start, lat_start, lon_start,
493 za_start, ppc, x, y, z, dx, dy, dz );
496 { r = r_start; lat = lat_start; lon = lon_start; l = 0; }
499 if( lat < lat1 || lat > lat3 || lon < lon5 || lon > lon6 )
507 r15, r35, r36, r16, lat, lon );
511 {
if( r < rpl ) { r = rpl; } }
513 {
if( r > rpl ) { r = rpl; } }
518 { za = za_start; aa = aa_start; }
520 {
cart2poslos( d1, d2, d3, za, aa, x+dx*l, y+dy*l, z+dz*l,
521 dx, dy, dz, ppc, lat_start, lon_start,
522 za_start, aa_start );
523 assert(
abs(d1-r) < 1e-3 );
524 assert(
abs(d2-lat) < 1e-8 );
525 assert(
abs(d3-lon) < 1e-8 );
531 r15, r35, r36, r16, lat, lon, aa );
545 if( lat < lat1 || lat > lat3 || lon < lon5 || lon > lon6 )
551 r15, r35, r36, r16, lat, lon );
552 distance3D( l, r_start, lat_start, lon_start, r, lat, lon );
652 poslos2cart( x, y, z, dx, dy, dz, r_start, lat_start, lon_start,
653 za_start, aa_start );
657 za_start, aa_start, x, y, z, dx, dy, dz, ppc,
658 lat1, lat3, lon5, lon6, r15a, r35a, r36a, r16a,
true );
663 if( rsurface15 >= r15a || rsurface35 >= r35a ||
664 rsurface36 >= r36a || rsurface16 >= r16a )
668 za_start, aa_start, x, y, z, dx, dy, dz, ppc,
669 lat1, lat3, lon5, lon6, rsurface15, rsurface35,
670 rsurface36, rsurface16,
true );
672 if( rt > 0 && lt <= l )
673 { endface = 7; r = rt; lat = latt; lon = lont; l = lt; }
681 za_start, aa_start, x, y, z, dx, dy, dz, ppc,
682 lat1, lat3, lon5, lon6, r15b, r35b, r36b, r16b,
684 if( rt > 0 && lt < l )
685 { endface = 4; r = rt; lat = latt; lon = lont; l = lt; }
692 x, y, z, dx, dy, dz );
693 if( rt > 0 && lt < l )
694 { endface = 1; r = rt; lat = lat1; lon = lont; l = lt; }
701 x, y, z, dx, dy, dz );
702 if( rt > 0 && lt < l )
703 { endface = 3; r = rt; lat = lat3; lon = lont; l = lt; }
707 if( !( r>0 && lat>=lat1 && lat<=lat3 && lon>=lon5 && lon<=lon6 ) )
711 x, y, z, dx, dy, dz );
712 if( rt > 0 && lt < l )
713 { endface = 5; r = rt; lat = latt; lon = lon5; l = lt; }
717 if( !( r>0 && lat>=lat1 && lat<=lat3 && lon>=lon5 && lon<=lon6 ) )
721 x, y, z, dx, dy, dz );
722 if( rt > 0 && lt < l )
723 { endface = 6; r = rt; lat = latt; lon = lon6; l = lt; }
736 za_start, aa_start, ppc );
749 n =
Index( ceil(
abs( l / lmax ) ) );
761 lat_v[0] = lat_start;
762 lon_v[0] = lon_start;
768 for(
Index j=1; j<=n; j++ )
772 cart2poslos( r_v[j], lat_v[j], lon_v[j], za_v[j], aa_v[j],
773 x+dx*lj, y+dy*lj, z+dz*lj, dx, dy, dz, ppc,
774 lat_start, lon_start, za_start, aa_start );
874 if( rsurface1 >= r1a || rsurface3 >= r3a )
878 lat1, lat3, rsurface1, rsurface3,
true );
880 if( rt > 0 && lt <= l )
881 { endface = 7; r = rt; lat = latt; l = lt; }
888 lat1, lat3, r1b, r3b,
false );
889 if( rt > 0 && lt < l )
890 { endface = 4; r = rt; lat = latt; }
897 { endface = 1; lat = lat1; }
899 { endface = 3; lat = lat3; }
908 if( absza > 90 && ( absza -
abs(lat_start-lat) ) < 90 )
911 { tanpoint =
false; }
914 za_start, r, tanpoint, lmax );
917 if( endface == 1 || endface == 3 )
918 { lat_v[lat_v.
nelem()-1] = lat; }
987 const Agenda& refr_index_air_agenda,
1010 refr_index_air_agenda, p_grid, refellipsoid, z_field,
1011 t_field, vmr_field, f_grid, r1 );
1013 refr_index_air_agenda, p_grid, refellipsoid, z_field,
1014 t_field, vmr_field, f_grid, r3 );
1015 if( refr3 < refr1 * (r1/r3) * sin(
DEG2RAD *
abs(za) ) )
1018 os <<
"For path between r1=" << r1 <<
"(n-1=" << refr1-1. <<
") and r2=" 1019 << r3 <<
"(n-1=" << refr3-1. <<
"),\n" 1020 <<
"path calculation will run into refractive back-bending issues.\n" 1021 <<
"We are currently NOT ABLE to handle them. Consider repeating\n" 1022 <<
"your calculation without taking refraction into account.";
1023 throw runtime_error(os.str());
1031 Numeric refr_index_air, refr_index_air_group;
1033 refr_index_air_agenda, p_grid, refellipsoid, z_field,
1034 t_field, vmr_field, f_grid, r );
1035 r_array.push_back( r );
1036 lat_array.push_back( lat );
1037 za_array.push_back( za );
1038 n_array.push_back( refr_index_air );
1039 ng_array.push_back( refr_index_air_group );
1055 if( ( r < r1 -
RTOL ) || ( r > r3 +
RTOL ) )
1057 throw runtime_error(
1058 "Ooops. Path undetectedly left the grid cell.\n" 1059 "This should not happen. But there are issues with cases of high\n" 1060 "refractivity gradients. Seems you unfortunately encountered such\n" 1061 "a case. Little to be done about this now (if this is an option\n" 1062 "for you, run the case without considering refraction). For further\n" 1063 "details, contact Patrick Eriksson.");
1067 do_gridrange_1d( r_v, lat_v, za_v, lstep, endface, r, lat, za, ppc_step,
1068 -1, r1, r3, r_surface );
1069 assert( r_v.
nelem() == 2 );
1073 if( lstep <= lraytrace )
1078 za_flagside = za_v[1];
1090 { za_flagside = 80; }
1102 refr_index_air_agenda, p_grid, refellipsoid,
1103 z_field, t_field, vmr_field, f_grid, r );
1107 const Numeric ppc_local = ppc / refr_index_air;
1109 if( r >= ppc_local )
1118 if( ready || ( lmax > 0 && lcum + lraytrace > lmax ) )
1120 r_array.push_back( r );
1121 lat_array.push_back( lat );
1122 za_array.push_back( za );
1123 n_array.push_back( refr_index_air );
1124 ng_array.push_back( refr_index_air_group );
1125 l_array.push_back( lcum );
INDEX Index
The type to use for all integer numbers and indices.
void latlon_at_aa(Numeric &lat2, Numeric &lon2, const Numeric &lat1, const Numeric &lon1, const Numeric &aa, const Numeric &ddeg)
latlon_at_aa
Numeric geompath_za_at_r(const Numeric &ppc, const Numeric &a_za, const Numeric &r)
geompath_za_at_r
const Numeric LON_NOT_FOUND
Numeric za_geom2other_point(const Numeric &r1, const Numeric &lat1, const Numeric &r2, const Numeric &lat2)
za_geom2other_point
Numeric geompath_r_at_l(const Numeric &ppc, const Numeric &l)
geompath_r_at_l
void do_gridcell_2d(Vector &r_v, Vector &lat_v, Vector &za_v, Numeric &lstep, Index &endface, const Numeric &r_start, const Numeric &lat_start, const Numeric &za_start, const Numeric &ppc, const Numeric &lmax, const Numeric &lat1, const Numeric &lat3, const Numeric &r1a, const Numeric &r3a, const Numeric &r3b, const Numeric &r1b, const Numeric &rsurface1, const Numeric &rsurface3)
do_gridcell_2d
void plevel_slope_3d(Numeric &c1, Numeric &c2, const Numeric &lat1, const Numeric &lat3, const Numeric &lon5, const Numeric &lon6, const Numeric &r15, const Numeric &r35, const Numeric &r36, const Numeric &r16, const Numeric &lat, const Numeric &lon, const Numeric &aa)
plevel_slope_3d
Numeric rslope_crossing3d(const Numeric &rp, const Numeric &za, const Numeric &r0, Numeric c1, Numeric c2)
rslope_crossing3d
const Numeric LAT_NOT_FOUND
void get_refr_index_1d(Workspace &ws, Numeric &refr_index_air, Numeric &refr_index_air_group, const Agenda &refr_index_air_agenda, ConstVectorView p_grid, ConstVectorView refellipsoid, ConstTensor3View z_field, ConstTensor3View t_field, ConstTensor4View vmr_field, ConstVectorView f_grid, const Numeric &r)
get_refr_index_1d
Numeric geompath_lat_at_za(const Numeric &za0, const Numeric &lat0, const Numeric &za)
geompath_lat_at_za
void plevel_crossing_3d(Numeric &r, Numeric &lat, Numeric &lon, Numeric &l, const Numeric &r_start0, const Numeric &lat_start, const Numeric &lon_start, const Numeric &za_start, const Numeric &aa_start, const Numeric &x, const Numeric &y, const Numeric &z, const Numeric &dx, const Numeric &dy, const Numeric &dz, const Numeric &ppc, const Numeric &lat1, const Numeric &lat3, const Numeric &lon5, const Numeric &lon6, const Numeric &r15, const Numeric &r35, const Numeric &r36, const Numeric &r16, const bool &above)
plevel_crossing_3d
void resolve_lon(Numeric &lon, const Numeric &lon5, const Numeric &lon6)
resolve_lon
Index nelem() const
Returns the number of elements.
Numeric geometrical_ppc(const Numeric &r, const Numeric &za)
geometrical_ppc
A constant view of a Tensor4.
Numeric sign(const Numeric &x)
sign
const Numeric L_NOT_FOUND
void do_gridrange_1d(Vector &r_v, Vector &lat_v, Vector &za_v, Numeric &lstep, Index &endface, const Numeric &r_start0, const Numeric &lat_start, const Numeric &za_start, const Numeric &ppc, const Numeric &lmax, const Numeric &ra, const Numeric &rb, const Numeric &rsurface)
do_gridrange_1d
void geompath_from_r1_to_r2(Vector &r, Vector &lat, Vector &za, Numeric &lstep, const Numeric &ppc, const Numeric &r1, const Numeric &lat1, const Numeric &za1, const Numeric &r2, const bool &tanpoint, const Numeric &lmax)
geompath_from_r1_to_r2
void cart2poslos(double &r, double &lat, double &lon, double &za, double &aa, const double &x, const double &y, const double &z, const double &dx, const double &dy, const double &dz)
cart2poslos
void cart2sph(double &r, double &lat, double &lon, const double &x, const double &y, const double &z)
cart2sph
const Numeric R_NOT_FOUND
NUMERIC Numeric
The type to use for all floating point numbers.
void distance3D(Numeric &l, const Numeric &r1, const Numeric &lat1, const Numeric &lon1, const Numeric &r2, const Numeric &lat2, const Numeric &lon2)
distance3D
const Numeric DEG2RAD
Global constant, conversion from degrees to radians.
void r_crossing_3d(Numeric &lat, Numeric &lon, Numeric &l, const Numeric &r_hit, const Numeric &r_start, const Numeric &lat_start, const Numeric &lon_start, const Numeric &za_start, const Numeric &ppc, const Numeric &x, const Numeric &y, const Numeric &z, const Numeric &dx, const Numeric &dy, const Numeric &dz)
r_crossing_3d
void raytrace_1d_linear_basic(Workspace &ws, Array< Numeric > &r_array, Array< Numeric > &lat_array, Array< Numeric > &za_array, Array< Numeric > &l_array, Array< Numeric > &n_array, Array< Numeric > &ng_array, Index &endface, ConstVectorView refellipsoid, ConstVectorView p_grid, ConstVectorView z_field, ConstTensor3View t_field, ConstTensor4View vmr_field, ConstVectorView f_grid, const Numeric &lmax, const Agenda &refr_index_air_agenda, const Numeric &lraytrace, const Numeric &ppc, const Numeric &r_surface, const Numeric &r1, const Numeric &r3, Numeric &r, Numeric &lat, Numeric &za)
raytrace_1d_linear_basic
Numeric rsurf_at_latlon(const Numeric &lat1, const Numeric &lat3, const Numeric &lon5, const Numeric &lon6, const Numeric &r15, const Numeric &r35, const Numeric &r36, const Numeric &r16, const Numeric &lat, const Numeric &lon)
rsurf_at_latlon
void lat_crossing_3d(Numeric &r, Numeric &lon, Numeric &l, const Numeric &lat_hit, const Numeric &lat_start, const Numeric &za_start, const Numeric &x, const Numeric &y, const Numeric &z, const Numeric &dx, const Numeric &dy, const Numeric &dz)
lat_crossing_3d
Numeric geompath_r_at_lat(const Numeric &ppc, const Numeric &lat0, const Numeric &za0, const Numeric &lat)
geompath_r_at_lat
void resize(Index n)
Assignment operator from VectorView.
A constant view of a Tensor3.
A constant view of a Vector.
void do_gridcell_3d(Vector &r_v, Vector &lat_v, Vector &lon_v, Vector &za_v, Vector &aa_v, Numeric &lstep, Index &endface, const Numeric &r_start, const Numeric &lat_start, const Numeric &lon_start, const Numeric &za_start, const Numeric &aa_start, const Numeric &ppc, const Numeric &lmax, const Numeric &lat1, const Numeric &lat3, const Numeric &lon5, const Numeric &lon6, const Numeric &r15a, const Numeric &r35a, const Numeric &r36a, const Numeric &r16a, const Numeric &r15b, const Numeric &r35b, const Numeric &r36b, const Numeric &r16b, const Numeric &rsurface15, const Numeric &rsurface35, const Numeric &rsurface36, const Numeric &rsurface16)
do_gridcell_3d
void lon_crossing_3d(Numeric &r, Numeric &lat, Numeric &l, const Numeric &lon_hit, const Numeric &lon_start, const Numeric &za_start, const Numeric &aa_start, const Numeric &x, const Numeric &y, const Numeric &z, const Numeric &dx, const Numeric &dy, const Numeric &dz)
lon_crossing_3d
void plevel_crossing_2d(Numeric &r, Numeric &lat, Numeric &l, const Numeric &r_start0, const Numeric &lat_start, const Numeric &za_start, const Numeric &ppc, const Numeric &lat1, const Numeric &lat3, const Numeric &r1, const Numeric &r3, const bool &above)
plevel_crossing_2d
void geompath_tanpos_3d(Numeric &r_tan, Numeric &lat_tan, Numeric &lon_tan, Numeric &l_tan, const Numeric &r, const Numeric &lat, const Numeric &lon, const Numeric &za, const Numeric &aa, const Numeric &ppc)
geompath_tanpos_3d
void poslos2cart(Numeric &x, Numeric &z, Numeric &dx, Numeric &dz, const Numeric &r, const Numeric &lat, const Numeric &za)
poslos2cart
Numeric geompath_l_at_r(const Numeric &ppc, const Numeric &r)
geompath_l_at_r
const Numeric RAD2DEG
Global constant, conversion from radians to degrees.