00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00033
00034
00035
00036
00037 #include "auto_md.h"
00038 #include "montecarlo.h"
00039 #include "mc_interp.h"
00040
00041 #ifdef HAVE_SSTREAM
00042 #include <sstream>
00043 #else
00044 #include "sstream.h"
00045 #endif
00046
00048
00057 void clear_rt_vars_at_gp(Workspace& ws,
00058 MatrixView& ext_mat_mono,
00059 VectorView& abs_vec_mono,
00060 Numeric& temperature,
00061 const Agenda& opt_prop_gas_agenda,
00062 const Agenda& abs_scalar_gas_agenda,
00063 const Index& f_index,
00064 const GridPos& gp_p,
00065 const GridPos& gp_lat,
00066 const GridPos& gp_lon,
00067 const ConstVectorView p_grid,
00068 const ConstVectorView lat_grid,
00069 const ConstVectorView lon_grid,
00070 const ConstTensor3View t_field,
00071 const ConstTensor4View vmr_field)
00072 {
00073 const Index ns = vmr_field.nbooks();
00074 Vector t_vec(1);
00075 Vector p_vec(1);
00076 Matrix itw_p(1,2);
00077 ArrayOfGridPos ao_gp_p(1),ao_gp_lat(1),ao_gp_lon(1);
00078 Matrix vmr_mat(ns,1), itw_field;
00079
00080
00081 Matrix local_abs_scalar_gas,local_abs_vec;
00082 Tensor3 local_ext_mat;
00083 ao_gp_p[0]=gp_p;
00084 ao_gp_lat[0]=gp_lat;
00085 ao_gp_lon[0]=gp_lon;
00086
00087
00088
00089 interpweights( itw_p, ao_gp_p );
00090 itw2p( p_vec, p_grid, ao_gp_p, itw_p );
00091
00092
00093
00094
00095 interp_atmfield_gp2itw( itw_field, 3, p_grid,
00096 lat_grid, lon_grid,
00097 ao_gp_p, ao_gp_lat, ao_gp_lon );
00098
00099 interp_atmfield_by_itw( t_vec, 3, p_grid,
00100 lat_grid, lon_grid, t_field,
00101 ao_gp_p, ao_gp_lat, ao_gp_lon,
00102 itw_field );
00103
00104 for( Index is=0; is<ns; is++ )
00105 {
00106 interp_atmfield_by_itw( vmr_mat(is, joker), 3, p_grid,
00107 lat_grid, lon_grid,
00108 vmr_field(is, joker, joker, joker),
00109 ao_gp_p, ao_gp_lat,
00110 ao_gp_lon, itw_field );
00111 }
00112
00113
00114 temperature = t_vec[0];
00115
00116
00117 abs_scalar_gas_agendaExecute( ws, local_abs_scalar_gas,f_index,p_vec[0],
00118 temperature,vmr_mat(joker,0),abs_scalar_gas_agenda );
00119 opt_prop_gas_agendaExecute( ws, local_ext_mat, local_abs_vec, f_index,
00120 local_abs_scalar_gas, opt_prop_gas_agenda );
00121 ext_mat_mono=local_ext_mat(0, Range(joker), Range(joker));
00122 abs_vec_mono=local_abs_vec(0,Range(joker));
00123 }
00124
00125
00126
00128
00137 void cloudy_rt_vars_at_gp(Workspace& ws,
00138 MatrixView& ext_mat_mono,
00139 VectorView& abs_vec_mono,
00140 VectorView& pnd_vec,
00141 Numeric& temperature,
00142 const Agenda& opt_prop_gas_agenda,
00143 const Agenda& abs_scalar_gas_agenda,
00144 const Index& stokes_dim,
00145 const Index& f_index,
00146 const GridPos gp_p,
00147 const GridPos gp_lat,
00148 const GridPos gp_lon,
00149 const ConstVectorView p_grid_cloud,
00150 const ConstVectorView lat_grid_cloud,
00151 const ConstVectorView lon_grid_cloud,
00152 const ConstTensor3View t_field_cloud,
00153 const ConstTensor4View vmr_field_cloud,
00154 const Tensor4& pnd_field,
00155 const ArrayOfSingleScatteringData& scat_data_mono,
00156 const ArrayOfIndex& cloudbox_limits,
00157 const Vector& rte_los
00158 )
00159
00160 {
00161 const Index ns = vmr_field_cloud.nbooks();
00162 const Index N_pt = pnd_field.nbooks();
00163 Matrix pnd_ppath(N_pt,1);
00164 Vector t_ppath(1);
00165 Vector p_ppath(1);
00166 Matrix itw_p(1,2);
00167 ArrayOfGridPos ao_gp_p(1),ao_gp_lat(1),ao_gp_lon(1);
00168 Matrix vmr_ppath(ns,1), itw_field;
00169 Matrix ext_mat_part(stokes_dim, stokes_dim, 0.0);
00170 Vector abs_vec_part(stokes_dim, 0.0);
00171 Numeric scat_za,scat_aa;
00172
00173
00174 Matrix local_abs_scalar_gas,local_abs_vec;
00175 Tensor3 local_ext_mat;
00176
00177
00178
00179 ao_gp_p[0]=gp_p;
00180 ao_gp_lat[0]=gp_lat;
00181 ao_gp_lon[0]=gp_lon;
00182
00183
00184 cloud_atm_vars_by_gp(p_ppath,t_ppath,vmr_ppath,pnd_ppath,ao_gp_p,
00185 ao_gp_lat,ao_gp_lon,cloudbox_limits,p_grid_cloud,
00186 lat_grid_cloud,lon_grid_cloud,t_field_cloud,
00187 vmr_field_cloud,pnd_field);
00188
00189
00190 temperature = t_ppath[0];
00191
00192 abs_scalar_gas_agendaExecute( ws, local_abs_scalar_gas,f_index,p_ppath[0],
00193 temperature,vmr_ppath(joker,0),abs_scalar_gas_agenda );
00194 opt_prop_gas_agendaExecute( ws, local_ext_mat, local_abs_vec, f_index,
00195 local_abs_scalar_gas, opt_prop_gas_agenda );
00196 ext_mat_mono=local_ext_mat(0, Range(joker), Range(joker));
00197 abs_vec_mono=local_abs_vec(0,Range(joker));
00198 ext_mat_part=0.0;
00199 abs_vec_part=0.0;
00200 scat_za=180-rte_los[0];
00201 scat_aa=rte_los[1]+180;
00202
00203 if (scat_aa>180){scat_aa-=360;}
00204
00205
00206
00207 pnd_vec=pnd_ppath(joker, 0);
00208 opt_propCalc(ext_mat_part,abs_vec_part,scat_za,scat_aa,scat_data_mono,
00209 stokes_dim, pnd_vec, temperature);
00210
00211 ext_mat_mono += ext_mat_part;
00212 abs_vec_mono += abs_vec_part;
00213
00214 }
00215
00216
00217
00219
00243 void cloud_atm_vars_by_gp(
00244 VectorView pressure,
00245 VectorView temperature,
00246 MatrixView vmr,
00247 MatrixView pnd,
00248 const ArrayOfGridPos& gp_p,
00249 const ArrayOfGridPos& gp_lat,
00250 const ArrayOfGridPos& gp_lon,
00251 const ArrayOfIndex& cloudbox_limits,
00252 const ConstVectorView p_grid_cloud,
00253 const ConstVectorView lat_grid_cloud,
00254 const ConstVectorView lon_grid_cloud,
00255 const ConstTensor3View t_field_cloud,
00256 const ConstTensor4View vmr_field_cloud,
00257 const ConstTensor4View pnd_field
00258 )
00259 {
00260 Index np=gp_p.nelem();
00261 assert(pressure.nelem()==np);
00262 Index ns=vmr_field_cloud.nbooks();
00263 Index N_pt=pnd_field.nbooks();
00264 ArrayOfGridPos gp_p_cloud = gp_p;
00265 ArrayOfGridPos gp_lat_cloud = gp_lat;
00266 ArrayOfGridPos gp_lon_cloud = gp_lon;
00267 Index atmosphere_dim=3;
00268
00269 for (Index i = 0; i < np; i++ )
00270 {
00271
00272 gp_p_cloud[i].idx -= cloudbox_limits[0];
00273 gp_lat_cloud[i].idx -= cloudbox_limits[2];
00274 gp_lon_cloud[i].idx -= cloudbox_limits[4];
00275 }
00276
00277 fix_gridpos_at_boundary(gp_p_cloud, p_grid_cloud.nelem());
00278 fix_gridpos_at_boundary(gp_lat_cloud, lat_grid_cloud.nelem());
00279 fix_gridpos_at_boundary(gp_lon_cloud, lon_grid_cloud.nelem());
00280
00281
00282 Matrix itw_p(np,2);
00283
00284
00285 interpweights( itw_p, gp_p_cloud );
00286 itw2p( pressure, p_grid_cloud, gp_p_cloud, itw_p );
00287
00288
00289
00290 Matrix itw_field;
00291
00292 interp_atmfield_gp2itw( itw_field, atmosphere_dim, p_grid_cloud,
00293 lat_grid_cloud, lon_grid_cloud,
00294 gp_p_cloud, gp_lat_cloud, gp_lon_cloud );
00295
00296 interp_atmfield_by_itw( temperature, atmosphere_dim, p_grid_cloud,
00297 lat_grid_cloud, lon_grid_cloud, t_field_cloud,
00298 gp_p_cloud, gp_lat_cloud, gp_lon_cloud,
00299 itw_field );
00300
00301 for( Index is=0; is<ns; is++ )
00302 {
00303 interp_atmfield_by_itw( vmr(is, joker), atmosphere_dim, p_grid_cloud,
00304 lat_grid_cloud, lon_grid_cloud,
00305 vmr_field_cloud(is, joker, joker, joker),
00306 gp_p_cloud, gp_lat_cloud,
00307 gp_lon_cloud, itw_field );
00308 }
00309
00310
00311
00312 for( Index ip=0; ip<N_pt; ip++ )
00313 {
00314
00315
00316 interp_atmfield_by_itw( pnd(ip, joker), atmosphere_dim,
00317 p_grid_cloud, lat_grid_cloud, lon_grid_cloud,
00318 pnd_field(ip, joker, joker, joker),
00319 gp_p_cloud, gp_lat_cloud,
00320 gp_lon_cloud, itw_field );
00321 }
00322 }
00323
00324
00326
00335 void Cloudbox_ppathCalc(Workspace& ws,
00336
00337 Ppath& ppath,
00338 Ppath& ppath_step,
00339
00340 const Agenda& ppath_step_agenda,
00341 const Index& atmosphere_dim,
00342 const Vector& p_grid,
00343 const Vector& lat_grid,
00344 const Vector& lon_grid,
00345 const Tensor3& z_field,
00346 const Matrix& r_geoid,
00347 const Matrix& z_surface,
00348 const ArrayOfIndex& cloudbox_limits,
00349 const Vector& rte_pos,
00350 const Vector& rte_los,
00351 const Index& z_field_is_1D
00352 )
00353 {
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 chk_vector_length( "rte_pos", rte_pos, atmosphere_dim );
00364 chk_if_over_0( "sensor radius", rte_pos[0] );
00365 if( atmosphere_dim < 3 )
00366 {
00367 ostringstream os;
00368 os << "cloudbox_ppath_calc only works for a 3D atmosphere";
00369 throw runtime_error( os.str() );
00370 }
00371 else
00372 {
00373 chk_if_in_range( "sensor latitude", rte_pos[1], -90., 90. );
00374 chk_if_in_range( "sensor longitude", rte_pos[2], -360., 360. );
00375 chk_vector_length( "rte_los", rte_los, 2 );
00376 chk_if_in_range( "sensor zenith angle", rte_los[0], 0., 180. );
00377 chk_if_in_range( "sensor azimuth angle", rte_los[1], -180., 180. );
00378 }
00379
00380
00381
00382
00383
00384 out2 << " -------------------------------------\n";
00385 out2 << " sensor radius : " << rte_pos[0]/1e3 << " km\n";
00386 if( atmosphere_dim == 3 )
00387 out2 << " sensor longitude : " << rte_pos[2] << "\n";
00388 out2 << " sensor zenith angle : " << rte_los[0] << "\n";
00389 if( atmosphere_dim == 3 )
00390 out2 << " sensor azimuth angle : " << rte_los[1] << "\n";
00391
00392
00393
00394
00395
00396
00397 cloudbox_ppath_start_stepping( ppath_step, atmosphere_dim, p_grid, lat_grid,
00398 lon_grid, z_field, r_geoid, z_surface, rte_pos, rte_los,
00399 z_field_is_1D );
00400
00401 out2 << " -------------------------------------\n";
00402
00403
00404
00405
00406
00407
00408
00409 Array<Ppath> ppath_array;
00410 ppath_array.push_back( ppath_step );
00411
00412 Index np = ppath_step.np;
00413 Index istep = 0;
00414
00415
00416
00417 while( !ppath_what_background( ppath_step ) )
00418 {
00419
00420
00421
00422
00423 istep++;
00424
00425 ppath_step_agendaExecute(ws, ppath_step, atmosphere_dim, p_grid,
00426 lat_grid, lon_grid, z_field, r_geoid, z_surface,
00427 ppath_step_agenda );
00428
00429
00430
00431
00432 if( istep > 5000 )
00433 {
00434 WriteXML( "ascii", ppath_step, "", "Ppath", "bugreport_ppath.xml" );
00435 throw runtime_error(
00436 "5000 path points have been reached. Is this an infinite loop?" );
00437 }
00438
00439
00440 const Index n = ppath_step.np;
00441
00442
00443 np += n - 1;
00444
00445
00446
00447
00448
00449 double ipos = double( ppath_step.gp_p[n-1].idx ) +
00450 ppath_step.gp_p[n-1].fd[0];
00451 if( ipos <= double( cloudbox_limits[0] ) ||
00452 ipos >= double( cloudbox_limits[1] ) )
00453 { ppath_set_background( ppath_step, 3 ); }
00454 else
00455 {
00456 ipos = double( ppath_step.gp_lat[n-1].idx ) +
00457 ppath_step.gp_lat[n-1].fd[0];
00458 if( ipos <= double( cloudbox_limits[2] ) ||
00459 ipos >= double( cloudbox_limits[3] ) )
00460 { ppath_set_background( ppath_step, 3 ); }
00461 else
00462 {
00463 ipos = double( ppath_step.gp_lon[n-1].idx ) +
00464 ppath_step.gp_lon[n-1].fd[0];
00465 if( ipos <= double( cloudbox_limits[4] ) ||
00466 ipos >= double( cloudbox_limits[5] ) )
00467 { ppath_set_background( ppath_step, 3 ); }
00468 }
00469 }
00470
00471
00472 ppath_array.push_back( ppath_step );
00473
00474 }
00475
00476
00477
00478
00479 ppath_init_structure( ppath, atmosphere_dim, np );
00480
00481 np = 0;
00482
00483 for( Index i=0; i<ppath_array.nelem(); i++ )
00484 {
00485
00486
00487
00488
00489
00490
00491 Index n = ppath_array[i].np;
00492
00493 if( n )
00494 {
00495
00496 Index i1 = 1;
00497 if( i == 0 )
00498 { i1 = 0; }
00499 else
00500 { assert( n > 1 ); }
00501
00502
00503 ppath.z[ Range(np,n-i1) ] = ppath_array[i].z[ Range(i1,n-i1) ];
00504 ppath.pos( Range(np,n-i1), joker ) =
00505 ppath_array[i].pos( Range(i1,n-i1), joker );
00506 ppath.los( Range(np,n-i1), joker ) =
00507 ppath_array[i].los( Range(i1,n-i1), joker );
00508
00509
00510
00511 if( i > 0 )
00512 { ppath.l_step[ Range(np-1,n-1) ] = ppath_array[i].l_step; }
00513
00514
00515 for( Index j=i1; j<n; j++ )
00516 { ppath.gp_p[np+j-i1] = ppath_array[i].gp_p[j]; }
00517 if( atmosphere_dim >= 2 )
00518 {
00519 for( Index j=i1; j<n; j++ )
00520 { ppath.gp_lat[np+j-i1] = ppath_array[i].gp_lat[j]; }
00521 }
00522 if( atmosphere_dim == 3 )
00523 {
00524 for( Index j=i1; j<n; j++ )
00525 { ppath.gp_lon[np+j-i1] = ppath_array[i].gp_lon[j]; }
00526 }
00527
00528
00529 if( ppath_array[i].tan_pos.nelem() )
00530 {
00531 ppath.tan_pos.resize( ppath_array[i].tan_pos.nelem() );
00532 ppath.tan_pos = ppath_array[i].tan_pos;
00533 }
00534 if( ppath_array[i].geom_tan_pos.nelem() )
00535 {
00536 ppath.geom_tan_pos.resize( ppath_array[i].tan_pos.nelem() );
00537 ppath.geom_tan_pos = ppath_array[i].geom_tan_pos;
00538 }
00539
00540
00541 np += n - i1;
00542
00543 }
00544 }
00545 ppath.method = ppath_step.method;
00546 ppath.refraction = ppath_step.refraction;
00547 ppath.constant = ppath_step.constant;
00548 ppath.background = ppath_step.background;
00549
00550
00551
00552 out3 << " number of path steps : " << istep << "\n";
00553 out3 << " number of path points : " << ppath.z.nelem() << "\n";
00554
00555
00556
00557
00558 if( ppath.refraction && min( z_field(z_field.npages()-1,0,0) ) < 60e3 )
00559 {
00560 out2 << " *** WARNING****\n"
00561 << " The calculated propagation path can be inexact as the "
00562 << "atmosphere\n only extends to "
00563 << min( z_field(z_field.npages()-1,0,0) ) << " km. \n"
00564 << " The importance of this depends on the observation "
00565 << "geometry.\n It is recommended that the top of the atmosphere "
00566 << "is not below 60 km.\n";
00567 }
00568 }
00569
00570
00571
00572
00573
00574
00576
00642 void Cloudbox_ppath_rteCalc( Workspace& ws,
00643 Ppath& ppathcloud,
00644 Ppath& ppath,
00645 Ppath& ppath_step,
00646 Vector& rte_pos,
00647 Vector& rte_los,
00648 Vector& cum_l_step,
00649 ArrayOfMatrix& TArray,
00650 ArrayOfMatrix& ext_matArray,
00651 ArrayOfVector& abs_vecArray,
00652 Vector& t_ppath,
00653
00654
00655 Tensor3& ext_mat,
00656 Matrix& abs_vec,
00657 Numeric& rte_pressure,
00658 Numeric& rte_temperature,
00659 Vector& rte_vmr_list,
00660 Matrix& iy,
00661
00662
00663
00664
00665 Matrix& pnd_ppath,
00666 const Agenda& ppath_step_agenda,
00667 const Index& atmosphere_dim,
00668 const Vector& p_grid,
00669 const Vector& lat_grid,
00670 const Vector& lon_grid,
00671 const Tensor3& z_field,
00672 const Matrix& r_geoid,
00673 const Matrix& z_surface,
00674 const ArrayOfIndex& cloudbox_limits,
00675 const Index& record_ppathcloud,
00676 const Index& record_ppath,
00677 const Agenda& opt_prop_gas_agenda,
00678 const Agenda& abs_scalar_gas_agenda,
00679 const Index& f_index,
00680 const Index& stokes_dim,
00681 const Tensor3& t_field,
00682 const Tensor4& vmr_field,
00683 const Agenda& rte_agenda,
00684 const Agenda& iy_space_agenda,
00685 const Agenda& surface_prop_agenda,
00686 const Agenda& iy_cloudbox_agenda,
00687 const Vector& f_grid,
00688 const Index& photon_number,
00689 const Index& scattering_order,
00690 const Tensor4& pnd_field,
00691 const ArrayOfSingleScatteringData& scat_data_mono,
00692 const Index& z_field_is_1D
00693 )
00694
00695 {
00696
00697 Vector mblock_za_grid_dummy(1);
00698 mblock_za_grid_dummy[0] = 0;
00699 Vector mblock_aa_grid_dummy(0);
00700
00701 Sparse sensor_response_dummy;
00702
00703
00704 Vector y_dummy(0);
00705
00706 const Index cloudbox_on_dummy=0;
00707 Matrix sensor_pos(1,3);
00708 Matrix sensor_los(1,2);
00709 Tensor7 scat_i_p_dummy;
00710 Tensor7 scat_i_lat_dummy;
00711 Tensor7 scat_i_lon_dummy;
00712
00713
00714 Cloudbox_ppathCalc(ws, ppathcloud,ppath_step,ppath_step_agenda,atmosphere_dim,
00715 p_grid,lat_grid,lon_grid,z_field,r_geoid,z_surface,
00716 cloudbox_limits, rte_pos,rte_los,z_field_is_1D);
00717
00718
00719
00720
00721
00722 if (record_ppathcloud)
00723 {
00724
00725
00726
00727 ostringstream filename;
00728 filename <<"ppathcloud" << photon_number <<"_"<<scattering_order;
00729 String longfilename;
00730 filename_xml(longfilename,filename.str());
00731 xml_write_to_file(longfilename, ppathcloud, FILE_TYPE_ASCII);
00732 }
00733
00734 cum_l_stepCalc(cum_l_step,ppathcloud);
00735 Range p_range(cloudbox_limits[0],
00736 cloudbox_limits[1]-cloudbox_limits[0]+1);
00737 Range lat_range(cloudbox_limits[2],
00738 cloudbox_limits[3]-cloudbox_limits[2]+1);
00739 Range lon_range(cloudbox_limits[4],
00740 cloudbox_limits[5]-cloudbox_limits[4]+1);
00741
00742 TArrayCalc(ws, TArray, ext_matArray, abs_vecArray, t_ppath, ext_mat, abs_vec,
00743 rte_pressure, rte_temperature,
00744 rte_vmr_list, pnd_ppath, ppathcloud, opt_prop_gas_agenda,
00745 abs_scalar_gas_agenda, f_index, stokes_dim,
00746 p_grid[p_range], lat_grid[lat_range], lon_grid[lon_range],
00747 t_field(p_range,lat_range,lon_range),
00748 vmr_field(joker,p_range,lat_range,lon_range),
00749 pnd_field,scat_data_mono,cloudbox_limits);
00750
00751 iy_calc_no_jacobian(ws, iy, ppath, ppath_step_agenda,
00752 rte_agenda, iy_space_agenda, surface_prop_agenda,
00753 iy_cloudbox_agenda, atmosphere_dim, p_grid, lat_grid,
00754 lon_grid, z_field, t_field, vmr_field, r_geoid, z_surface,
00755 cloudbox_on_dummy, cloudbox_limits,
00756 rte_pos, rte_los, f_grid,stokes_dim);
00757
00758 for (Index i = 0;i<stokes_dim;i++){assert(!isnan(iy(0,i)));}
00759
00760 if (record_ppath)
00761 {
00762
00763
00764 ostringstream filename;
00765 filename <<"ppath" << photon_number <<"_"<<scattering_order;
00766 String longfilename;
00767 filename_xml(longfilename,filename.str());
00768 xml_write_to_file(longfilename, ppath, FILE_TYPE_ASCII);
00769 }
00770
00771 }
00772
00773
00774
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 void cloudbox_ppath_start_stepping(
00799 Ppath& ppath,
00800 const Index& atmosphere_dim,
00801 ConstVectorView p_grid,
00802 ConstVectorView lat_grid,
00803 ConstVectorView lon_grid,
00804 ConstTensor3View z_field,
00805 ConstMatrixView r_geoid,
00806 ConstMatrixView z_ground _U_,
00807 ConstVectorView rte_pos,
00808 ConstVectorView rte_los,
00809 const Index& z_field_is_1D)
00810 {
00811
00812
00813
00814
00815 ppath_init_structure( ppath, atmosphere_dim, 1 );
00816
00817
00818 const Index np = p_grid.nelem();
00819
00820
00821
00822 if( atmosphere_dim == 3 )
00823 {
00824
00825
00826
00827
00828
00829
00830 double rv_geoid=-1;
00831
00832 GridPos gp_lat, gp_lon;
00833 Vector itw(4);
00834
00835
00836 gridpos( gp_lat, lat_grid, rte_pos[1] );
00837 gridpos( gp_lon, lon_grid, rte_pos[2] );
00838 interpweights( itw, gp_lat, gp_lon );
00839
00840 rv_geoid = interp( itw, r_geoid, gp_lat, gp_lon );
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854 ppath.pos(0,0) = rte_pos[0];
00855 ppath.pos(0,1) = rte_pos[1];
00856 ppath.pos(0,2) = rte_pos[2];
00857 ppath.los(0,0) = rte_los[0];
00858 ppath.los(0,1) = rte_los[1];
00859
00860
00861
00862 ppath.z[0] = ppath.pos(0,0) - rv_geoid;
00863
00864
00865
00866
00867
00868 ppath.gp_lat[0].idx = gp_lat.idx;
00869 ppath.gp_lat[0].fd[0] = gp_lat.fd[0];
00870 ppath.gp_lat[0].fd[1] = gp_lat.fd[1];
00871 ppath.gp_lon[0].idx = gp_lon.idx;
00872 ppath.gp_lon[0].fd[0] = gp_lon.fd[0];
00873 ppath.gp_lon[0].fd[1] = gp_lon.fd[1];
00874
00875
00876
00877 Vector z_grid(np);
00878 if ( z_field_is_1D )
00879 { z_grid=z_field(joker,0,0);}
00880 else
00881 { z_at_latlon( z_grid, p_grid, lat_grid, lon_grid, z_field,
00882 gp_lat, gp_lon );}
00883 gridpos( ppath.gp_p, z_grid, ppath.z );
00884
00885
00886
00887 gridpos_check_fd( ppath.gp_p[0] );
00888 gridpos_check_fd( ppath.gp_lat[0] );
00889 gridpos_check_fd( ppath.gp_lon[0] );
00890
00891 }
00892 }
00893
00894
00896
00907 void cum_l_stepCalc(
00908 Vector& cum_l_step,
00909 const Ppath& ppath
00910 )
00911 {
00912 cum_l_step.resize(ppath.np);
00913 Numeric cumsum = 0.0;
00914 cum_l_step[0] = 0.0;
00915 for (Index i=0; i<ppath.np-1; i++)
00916 {
00917 cumsum += ppath.l_step[i];
00918 cum_l_step[i+1] = cumsum;
00919 }
00920 }
00921
00923
00933 void findZ11max(Vector& Z11maxvector,
00934 const ArrayOfSingleScatteringData& scat_data_mono)
00935 {
00936 Index np=scat_data_mono.nelem();
00937 Z11maxvector.resize(np);
00938
00939 for(Index i = 0;i<np;i++)
00940 {
00941 switch(scat_data_mono[i].ptype){
00942 case PTYPE_MACROS_ISO:
00943 {
00944 Z11maxvector[i]=max(scat_data_mono[i].pha_mat_data(0,joker,joker,0,0,0,0));
00945 }
00946 case PTYPE_HORIZ_AL:
00947 {
00948 Z11maxvector[i]=max(scat_data_mono[i].pha_mat_data(0,joker,joker,0,joker,0,0));
00949 }
00950 default:
00951 Z11maxvector[i]=max(scat_data_mono[i].pha_mat_data(0,joker,joker,joker,joker,joker,0));
00952 }
00953 }
00954 }
00955
00956
00957
00958
00960
00970 bool is_anyptype30(const ArrayOfSingleScatteringData& scat_data_mono)
00971 {
00972 Index np=scat_data_mono.nelem();
00973 bool anyptype30=false;
00974 Index i=0;
00975 while(i < np && anyptype30==false)
00976 {
00977 if(scat_data_mono[i].ptype==PTYPE_HORIZ_AL)
00978 {
00979 anyptype30=true;
00980 }
00981 i+=1;
00982 }
00983 return anyptype30;
00984 }
00985
00987
00999 void iwp_cloud_opt_pathCalc(Workspace& ws,
01000 Numeric& iwp,
01001 Numeric& cloud_opt_path,
01002
01003 const Vector& rte_pos,
01004 const Vector& rte_los,
01005 const Agenda& ppath_step_agenda,
01006 const Vector& p_grid,
01007 const Vector& lat_grid,
01008 const Vector& lon_grid,
01009 const Matrix& r_geoid,
01010 const Matrix& z_surface,
01011 const Tensor3& z_field,
01012 const Tensor3& t_field,
01013 const Tensor4& vmr_field,
01014 const ArrayOfIndex& cloudbox_limits,
01015 const Tensor4& pnd_field,
01016 const ArrayOfSingleScatteringData& scat_data_mono,
01017 const Vector& particle_masses
01018 )
01019 {
01020
01021 Ppath ppath;
01022 Vector local_rte_pos=rte_pos;
01023 Vector local_rte_los=rte_los;
01024 iwp=0;
01025 cloud_opt_path=0;
01026
01027 ppath_calc( ws, ppath, ppath_step_agenda, 3,
01028 p_grid, lat_grid, lon_grid, z_field, r_geoid, z_surface,
01029 1, cloudbox_limits, local_rte_pos, local_rte_los, 1 );
01030
01031 if (ppath_what_background(ppath)>2)
01032 {
01033
01034
01035 local_rte_pos=ppath.pos(ppath.np-1,joker);
01036 local_rte_los=ppath.los(ppath.np-1,joker);
01037
01038 Range p_range(cloudbox_limits[0],
01039 cloudbox_limits[1]-cloudbox_limits[0]+1);
01040 Range lat_range(cloudbox_limits[2],
01041 cloudbox_limits[3]-cloudbox_limits[2]+1);
01042 Range lon_range(cloudbox_limits[4],
01043 cloudbox_limits[5]-cloudbox_limits[4]+1);
01044
01045 ppath_calc( ws, ppath, ppath_step_agenda, 3,
01046 p_grid, lat_grid, lon_grid, z_field, r_geoid, z_surface,
01047 1, cloudbox_limits, local_rte_pos, local_rte_los, 0 );
01048
01049 Matrix pnd_ppath(particle_masses.nelem(),ppath.np);
01050 Vector t_ppath(ppath.np);
01051 Vector p_ppath(ppath.np);
01052 Matrix vmr_ppath(vmr_field.nbooks(),ppath.np);
01053 Matrix ext_mat_part(1, 1, 0.0);
01054 Vector abs_vec_part(1, 0.0);
01055
01056 cloud_atm_vars_by_gp(p_ppath,t_ppath,vmr_ppath,pnd_ppath,ppath.gp_p,
01057 ppath.gp_lat,ppath.gp_lon,cloudbox_limits,p_grid[p_range],
01058 lat_grid[lat_range],lon_grid[lon_range],
01059 t_field(p_range,lat_range,lon_range),
01060 vmr_field(joker,p_range,lat_range,lon_range),
01061 pnd_field);
01062
01063 Vector k_vec(ppath.np);
01064 Vector iwc_vec(ppath.np);
01065
01066 for (Index i = 0; i < ppath.np ; ++i)
01067 {
01068 opt_propCalc(ext_mat_part,abs_vec_part,ppath.los(i,0),ppath.los(i,1),scat_data_mono,
01069 1, pnd_ppath(joker, i), t_ppath[i]);
01070 k_vec[i]=ext_mat_part(0,0);
01071 Vector pnd_vec=pnd_ppath(joker, i);
01072 assert(pnd_vec.nelem()==particle_masses.nelem());
01073 iwc_vec[i]=pnd_vec*particle_masses;
01074 }
01075
01076 for (Index i = 0; i < ppath.np-1 ; ++i)
01077 {
01078
01079 iwp+=0.5*(iwc_vec[i+1]+iwc_vec[i])*ppath.l_step[i];
01080 cloud_opt_path+=0.5*(k_vec[i+1]+k_vec[i])*ppath.l_step[i];
01081 }
01082 }
01083 }
01084
01085
01087
01098 void matrix_exp_p30(MatrixView& M,
01099 ConstMatrixView& A)
01100 {
01101 Index m=A.nrows();
01102 assert( A.ncols()==m );
01103 M=0;
01104 Numeric a=A(0,0);
01105 Numeric b=A(0,1);
01106 M(0,0)=cosh(b);
01107 M(1,1)=cosh(b);
01108 M(0,1)=sinh(b);
01109 M(1,0)=sinh(b);
01110 if ( m>2 )
01111 {
01112 Numeric c=A(2,3);
01113 M(2,2)=cos(c);
01114 if ( m > 3 )
01115 {
01116 M(2,3)=sin(c);
01117 M(3,2)=-sin(c);
01118 }
01119 }
01120 M*=exp(a);
01121 }
01122
01123
01124
01126
01137 void mcPathTraceGeneral(Workspace& ws,
01138 MatrixView& evol_op,
01139 Vector& abs_vec_mono,
01140 Numeric& temperature,
01141 MatrixView& ext_mat_mono,
01142 Rng& rng,
01143 Vector& rte_pos,
01144 Vector& rte_los,
01145 Vector& pnd_vec,
01146 Numeric& g,
01147 Ppath& ppath_step,
01148 Index& termination_flag,
01149 bool& inside_cloud,
01150
01151
01152 const Agenda& opt_prop_gas_agenda,
01153 const Agenda& abs_scalar_gas_agenda,
01154 const Index& stokes_dim,
01155 const Index& f_index,
01156 const Vector& p_grid,
01157 const Vector& lat_grid,
01158 const Vector& lon_grid,
01159 const Tensor3& z_field,
01160 const Matrix& r_geoid,
01161 const Matrix& z_surface,
01162 const Tensor3& t_field,
01163 const Tensor4& vmr_field,
01164 const ArrayOfIndex& cloudbox_limits,
01165 const Tensor4& pnd_field,
01166 const ArrayOfSingleScatteringData& scat_data_mono,
01167 const Index& z_field_is_1D)
01168
01169 {
01170 ArrayOfMatrix evol_opArray(2);
01171 ArrayOfMatrix ext_matArray(2);
01172 ArrayOfVector abs_vecArray(2),pnd_vecArray(2);
01173 Vector tArray(2);
01174 Vector cum_l_step;
01175 Matrix T(stokes_dim,stokes_dim);
01176 Numeric k;
01177 Numeric ds;
01178 Index np=0;
01179 Index istep = 0;
01180 Matrix opt_depth_mat(stokes_dim,stokes_dim),incT(stokes_dim,stokes_dim,0.0);
01181 Matrix old_evol_op(stokes_dim,stokes_dim);
01182
01183
01184 id_mat(evol_op);
01185 evol_opArray[1]=evol_op;
01186
01187 Index rubbish=z_field_is_1D;rubbish+=1;
01188 ppath_start_stepping( ppath_step, 3, p_grid, lat_grid,
01189 lon_grid, z_field, r_geoid, z_surface,
01190 0, cloudbox_limits, false,
01191 rte_pos, rte_los );
01192
01193
01194
01195
01196 Range p_range(cloudbox_limits[0],
01197 cloudbox_limits[1]-cloudbox_limits[0]+1);
01198 Range lat_range(cloudbox_limits[2],
01199 cloudbox_limits[3]-cloudbox_limits[2]+1);
01200 Range lon_range(cloudbox_limits[4],
01201 cloudbox_limits[5]-cloudbox_limits[4]+1);
01202 termination_flag=0;
01203
01204 inside_cloud=is_inside_cloudbox( ppath_step, cloudbox_limits,true );
01205
01206 if (inside_cloud)
01207 {
01208 cloudy_rt_vars_at_gp(ws,ext_mat_mono,abs_vec_mono,pnd_vec,temperature,
01209 opt_prop_gas_agenda,abs_scalar_gas_agenda,
01210 stokes_dim, f_index, ppath_step.gp_p[0], ppath_step.gp_lat[0],
01211 ppath_step.gp_lon[0],p_grid[p_range],lat_grid[lat_range],
01212 lon_grid[lon_range],t_field(p_range,lat_range,lon_range),
01213 vmr_field(joker,p_range,lat_range,lon_range),pnd_field,
01214 scat_data_mono, cloudbox_limits,ppath_step.los(0,joker));
01215 }
01216 else
01217 {
01218 clear_rt_vars_at_gp( ws, ext_mat_mono, abs_vec_mono, temperature,
01219 opt_prop_gas_agenda, abs_scalar_gas_agenda, f_index,
01220 ppath_step.gp_p[0], ppath_step.gp_lat[0], ppath_step.gp_lon[0],
01221 p_grid, lat_grid, lon_grid, t_field, vmr_field );
01222 pnd_vec=0.0;
01223 }
01224 ext_matArray[1]=ext_mat_mono;
01225 abs_vecArray[1]=abs_vec_mono;
01226 tArray[1]=temperature;
01227 pnd_vecArray[1]=pnd_vec;
01228
01229 Numeric r = rng.draw();
01230 while ((evol_op(0,0)>r)&(!termination_flag))
01231 {
01232 istep++;
01233
01234
01235
01236 if( istep > 5000 )
01237 {
01238 throw runtime_error(
01239 "5000 path points have been reached. Is this an infinite loop?" );
01240 }
01241 evol_opArray[0]=evol_opArray[1];
01242 ext_matArray[0]=ext_matArray[1];
01243 abs_vecArray[0]=abs_vecArray[1];
01244 tArray[0]=tArray[1];
01245 pnd_vecArray[0]=pnd_vecArray[1];
01246
01247 ppath_step_geom_3d(ppath_step, p_grid, lat_grid, lon_grid, z_field,
01248 r_geoid, z_surface, -1);
01249 np=ppath_step.np;
01250 cum_l_stepCalc(cum_l_step, ppath_step);
01251
01252
01253 inside_cloud=is_inside_cloudbox( ppath_step, cloudbox_limits, true );
01254 if (inside_cloud)
01255 {
01256 cloudy_rt_vars_at_gp(ws,ext_mat_mono,abs_vec_mono,pnd_vec,temperature,
01257 opt_prop_gas_agenda,abs_scalar_gas_agenda, stokes_dim, f_index,
01258 ppath_step.gp_p[np-1],ppath_step.gp_lat[np-1],
01259 ppath_step.gp_lon[np-1],p_grid[p_range], lat_grid[lat_range],
01260 lon_grid[lon_range],t_field(p_range,lat_range,lon_range),
01261 vmr_field(joker,p_range,lat_range,lon_range),pnd_field,
01262 scat_data_mono, cloudbox_limits,ppath_step.los(np-1,joker));
01263 }
01264 else
01265 {
01266 clear_rt_vars_at_gp(ws, ext_mat_mono,abs_vec_mono,temperature,
01267 opt_prop_gas_agenda, abs_scalar_gas_agenda, f_index,
01268 ppath_step.gp_p[np-1], ppath_step.gp_lat[np-1],
01269 ppath_step.gp_lon[np-1], p_grid, lat_grid, lon_grid, t_field,
01270 vmr_field);
01271 pnd_vec=0.0;
01272 }
01273 ext_matArray[1]=ext_mat_mono;
01274 abs_vecArray[1]=abs_vec_mono;
01275 tArray[1]=temperature;
01276 pnd_vecArray[1]=pnd_vec;
01277 opt_depth_mat=ext_matArray[1];
01278 opt_depth_mat+=ext_matArray[0];
01279 opt_depth_mat*=-cum_l_step[np-1]/2;
01280 incT=0;
01281 if ( stokes_dim == 1 )
01282 {
01283 incT(0,0)=exp(opt_depth_mat(0,0));
01284 }
01285 else if ( is_diagonal( opt_depth_mat))
01286 {
01287 for ( Index j=0;j<stokes_dim;j++)
01288 {
01289 incT(j,j)=exp(opt_depth_mat(j,j));
01290 }
01291 }
01292 else
01293 {
01294
01295 matrix_exp_p30(incT,opt_depth_mat);
01296 }
01297 mult(evol_op,evol_opArray[0],incT);
01298 evol_opArray[1]=evol_op;
01299
01300
01301 Index bg = ppath_what_background(ppath_step);
01302 if ( bg==2 )
01303 {
01304
01305 termination_flag=2;
01306
01307 }
01308
01309 else if (fractional_gp(ppath_step.gp_p[np-1])>=(Numeric)(p_grid.nelem() - 1)-1e-3)
01310 {
01311
01312 termination_flag=1;
01313
01314 }
01315
01316
01317 }
01318 if (termination_flag)
01319 {
01320
01321 rte_pos = ppath_step.pos(np-1,Range(0,3));
01322 rte_los = ppath_step.los(np-1,joker);
01323 g=evol_op(0,0);
01324 }
01325 else
01326 {
01327
01328
01329 k=-log(incT(0,0))/cum_l_step[np-1];
01330 ds=log(evol_opArray[0](0,0)/r)/k;
01331 g=k*r;
01332 Vector x(2,0.0);
01333
01334
01335 ArrayOfGridPos gp(1);
01336 x[1]=cum_l_step[np-1];
01337 Vector itw(2);
01338
01339 gridpos(gp, x, ds);
01340 assert(gp[0].idx==0);
01341 interpweights(itw,gp[0]);
01342 ext_mat_mono = interp(itw,ext_matArray,gp[0]);
01343 opt_depth_mat = ext_mat_mono;
01344 opt_depth_mat+=ext_matArray[gp[0].idx];
01345 opt_depth_mat*=-ds/2;
01346 if ( stokes_dim == 1 )
01347 {
01348 incT(0,0)=exp(opt_depth_mat(0,0));
01349 }
01350 else if ( is_diagonal( opt_depth_mat))
01351 {
01352 for ( Index i=0;i<stokes_dim;i++)
01353 {
01354 incT(i,i)=exp(opt_depth_mat(i,i));
01355 }
01356 }
01357 else
01358 {
01359
01360 matrix_exp_p30(incT,opt_depth_mat);
01361 }
01362 mult(evol_op,evol_opArray[gp[0].idx],incT);
01363 abs_vec_mono = interp(itw, abs_vecArray,gp[0]);
01364 temperature=interp(itw,tArray,gp[0]);
01365 pnd_vec=interp(itw,pnd_vecArray,gp[0]);
01366 if (np > 2)
01367 {
01368 gridpos(gp,cum_l_step,ds);
01369 interpweights(itw,gp[0]);
01370 }
01371 for (Index i=0; i<2; i++)
01372 {
01373 rte_pos[i] = interp(itw,ppath_step.pos(Range(joker),i),gp[0]);
01374 rte_los[i] = interp(itw,ppath_step.los(Range(joker),i),gp[0]);
01375 }
01376 rte_pos[2] = interp(itw,ppath_step.pos(Range(joker),2),gp[0]);
01377 }
01378 }
01379
01381
01393 void mcPathTraceIPA(Workspace& ws,
01394 MatrixView& evol_op,
01395 Vector& abs_vec_mono,
01396 Numeric& temperature,
01397 MatrixView& ext_mat_mono,
01398 Rng& rng,
01399 Vector& rte_pos,
01400 Vector& rte_los,
01401 Vector& pnd_vec,
01402 Numeric& g,
01403 Index& termination_flag,
01404 bool& inside_cloud,
01405 const Agenda& opt_prop_gas_agenda,
01406 const Agenda& abs_scalar_gas_agenda,
01407 const Index& stokes_dim,
01408 const Index& f_index,
01409 const Vector& p_grid,
01410 const Vector& lat_grid,
01411 const Vector& lon_grid,
01412 const Tensor3& z_field,
01413 const Matrix& r_geoid,
01414 const Matrix& z_surface,
01415 const Tensor3& t_field,
01416 const Tensor4& vmr_field,
01417 const ArrayOfIndex& cloudbox_limits,
01418 const Tensor4& pnd_field,
01419 const ArrayOfSingleScatteringData& scat_data_mono,
01420 const Index& z_field_is_1D,
01421 const Ppath& ppath)
01422
01423 {
01424
01425
01426 ArrayOfMatrix evol_opArray(2);
01427 ArrayOfMatrix ext_matArray(2);
01428 ArrayOfVector abs_vecArray(2),pnd_vecArray(2);
01429 GridPos gp_p,gp_lat,gp_lon;
01430 Vector itw(4);
01431 Vector tArray(2);
01432 Vector cum_l_step;
01433 Vector z_grid(p_grid.nelem());
01434 Matrix T(stokes_dim,stokes_dim);
01435 Numeric k;
01436 Numeric x,y,z;
01437 Numeric ds,lstep=0.,dx,dy,dz;
01438 Index istep = 0;
01439 Matrix opt_depth_mat(stokes_dim,stokes_dim),incT(stokes_dim,stokes_dim,0.0);
01440 Matrix old_evol_op(stokes_dim,stokes_dim);
01441 Numeric rv_geoid=0.;
01442 Numeric rv_surface=0.;
01443 Numeric alt;
01444 Numeric gpnum;
01445 const Index np_ipa=ppath.np;
01446 Index i_closest=0;
01447 Numeric gp_diff;
01448 Vector lon_iw(2),lat_iw(2);
01449 Vector l_vec(2);
01450 GridPos gp;
01451 Vector itw1d(2);
01452
01453
01454
01455 if (z_field_is_1D)
01456 {
01457 z_grid=z_field(joker,0,0);
01458 rv_geoid=r_geoid(0,0);
01459 rv_surface=rv_geoid+z_surface(0,0);
01460 }
01461
01462 id_mat(evol_op);
01463 evol_opArray[1]=evol_op;
01464
01465
01466 Ppath ppath_step;
01467
01468 ppath_start_stepping( ppath_step, 3, p_grid, lat_grid,
01469 lon_grid, z_field, r_geoid, z_surface,
01470 0, cloudbox_limits, false,
01471 rte_pos, rte_los );
01472
01473 gp_p=ppath_step.gp_p[0];
01474 gp_lat=ppath_step.gp_lat[0];
01475 gp_lon=ppath_step.gp_lon[0];
01476 rte_pos=ppath_step.pos(0,joker);
01477 rte_los=ppath_step.los(0,joker);
01478
01479 Range p_range(cloudbox_limits[0],
01480 cloudbox_limits[1]-cloudbox_limits[0]+1);
01481 Range lat_range(cloudbox_limits[2],
01482 cloudbox_limits[3]-cloudbox_limits[2]+1);
01483 Range lon_range(cloudbox_limits[4],
01484 cloudbox_limits[5]-cloudbox_limits[4]+1);
01485 termination_flag=0;
01486
01487 inside_cloud=is_inside_cloudbox( ppath_step, cloudbox_limits,false );
01488
01489 if (inside_cloud)
01490 {
01491 cloudy_rt_vars_at_gp(ws, ext_mat_mono,abs_vec_mono,pnd_vec,temperature,
01492 opt_prop_gas_agenda,abs_scalar_gas_agenda, stokes_dim, f_index,
01493 gp_p, gp_lat, gp_lon,p_grid[p_range],
01494 lat_grid[lat_range], lon_grid[lon_range],
01495 t_field(p_range,lat_range,lon_range),
01496 vmr_field(joker,p_range,lat_range,lon_range),
01497 pnd_field,scat_data_mono, cloudbox_limits,rte_los );
01498 }
01499 else
01500 {
01501 clear_rt_vars_at_gp( ws, ext_mat_mono,abs_vec_mono,temperature,
01502 opt_prop_gas_agenda, abs_scalar_gas_agenda, f_index,
01503 gp_p, gp_lat, gp_lon,
01504 p_grid, lat_grid, lon_grid, t_field, vmr_field);
01505 pnd_vec=0.0;
01506 }
01507 ext_matArray[1]=ext_mat_mono;
01508 abs_vecArray[1]=abs_vec_mono;
01509 tArray[1]=temperature;
01510 pnd_vecArray[1]=pnd_vec;
01511
01512 Numeric r = rng.draw();
01513 while ((evol_op(0,0)>r)&(!termination_flag))
01514 {
01515
01516 istep++;
01517 assert(istep<=5000);
01518
01519
01520
01521
01522 evol_opArray[0]=evol_opArray[1];
01523 ext_matArray[0]=ext_matArray[1];
01524 abs_vecArray[0]=abs_vecArray[1];
01525 tArray[0]=tArray[1];
01526 pnd_vecArray[0]=pnd_vecArray[1];
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539 Numeric Dy=(lat_grid[gp_lat.idx+1]-lat_grid[gp_lat.idx])*DEG2RAD*
01540 r_geoid(gp_lat.idx,gp_lon.idx);
01541 Numeric Dx=(lon_grid[gp_lon.idx+1]-lon_grid[gp_lon.idx])*
01542 DEG2RAD*r_geoid(gp_lat.idx,gp_lon.idx)*cos(DEG2RAD*rte_pos[1]);
01543 Numeric Dz=z_field(gp_p.idx+1,gp_lat.idx,gp_lon.idx)-
01544 z_field(gp_p.idx,gp_lat.idx,gp_lon.idx);
01545 Numeric Dxy=sqrt(Dx*Dx+Dy*Dy);
01546 if (Dxy/abs(tan(rte_los[0]*DEG2RAD))>Dz){dz=Dz;}
01547 else {dz=Dxy/abs(tan(rte_los[0]*DEG2RAD));}
01548 Numeric dxy;
01549 if(dz*abs(tan(rte_los[0]*DEG2RAD))>Dxy){dxy=Dxy;}
01550 else{dxy=dz*abs(tan(rte_los[0]*DEG2RAD));}
01551 lstep=sqrt(dxy*dxy+dz*dz);
01552
01553
01554 poslos2cart( x, y, z, dx, dy, dz, rte_pos[0], rte_pos[1], rte_pos[2],
01555 rte_los[0], rte_los[1] );
01556
01557 x+=lstep*dx;
01558 y+=lstep*dy;
01559 z+=lstep*dz;
01560
01561 cart2poslos(rte_pos[0],rte_pos[1],rte_pos[2],rte_los[0],rte_los[1],
01562 x,y,z,dx,dy,dz);
01563
01564 gridpos( gp_lat, lat_grid, rte_pos[1] );
01565 gridpos( gp_lon, lon_grid, rte_pos[2] );
01566 if (!z_field_is_1D)
01567 {
01568 z_at_latlon( z_grid, p_grid, lat_grid, lon_grid, z_field, gp_lat, gp_lon );
01569 interpweights( itw, gp_lat, gp_lon );
01570 rv_geoid = interp( itw, r_geoid, gp_lat, gp_lon );
01571 rv_surface = rv_geoid + interp( itw, z_surface, gp_lat, gp_lon );
01572 }
01573 alt = rte_pos[0] - rv_geoid;
01574
01575 if ((alt>=z_grid[p_grid.nelem()-1])&(rte_los[0]<=90))
01576 {
01577 termination_flag=1;
01578
01579
01580
01581 alt=z_grid[p_grid.nelem()-1];
01582 rte_pos[0]=alt+rv_geoid;
01583 }
01584
01585 if( (rte_pos[0] <= rv_surface)&(rte_los[0]>=90) )
01586 {
01587 termination_flag=2;
01588 rte_pos[0]=rv_surface;
01589 alt = rte_pos[0] - rv_geoid;
01590 }
01591 gridpos( gp_p, z_grid, alt );
01592
01593
01594
01595 gpnum=fractional_gp(gp_p);
01596
01597 gp_diff=abs(fractional_gp(ppath.gp_p[0])-gpnum);
01598 for (Index i=1;i<np_ipa;i++)
01599 {
01600 Numeric new_gp_diff=abs(fractional_gp(ppath.gp_p[i])-gpnum);
01601 if (new_gp_diff<=gp_diff)
01602 {
01603 gp_diff=new_gp_diff;
01604 i_closest=i;
01605 }
01606 else
01607 {
01608
01609 break;
01610 }
01611 }
01612 gp_lat=ppath.gp_lat[i_closest];
01613 gp_lon=ppath.gp_lon[i_closest];
01614 interpweights(lon_iw,gp_lon);
01615 interpweights(lat_iw,gp_lat);
01616
01617 if (!z_field_is_1D)
01618 {
01619 interpweights( itw, gp_lat, gp_lon );
01620 rv_geoid = interp( itw, r_geoid, gp_lat, gp_lon );
01621 }
01622 rte_pos[0]=rv_geoid+interp_atmfield_by_gp(3,p_grid,lat_grid,lon_grid,z_field,
01623 gp_p,gp_lat,gp_lon);
01624 rte_pos[1]=interp(lat_iw, lat_grid,gp_lat);
01625 rte_pos[2]=interp(lon_iw, lon_grid,gp_lon);
01626
01627
01628 inside_cloud=is_gp_inside_cloudbox(gp_p,gp_lat,gp_lon,
01629 cloudbox_limits, false );
01630
01631 if (inside_cloud)
01632 {
01633 cloudy_rt_vars_at_gp(ws,
01634 ext_mat_mono, abs_vec_mono, pnd_vec, temperature,
01635 opt_prop_gas_agenda, abs_scalar_gas_agenda, stokes_dim,
01636 f_index, gp_p,gp_lat, gp_lon, p_grid[p_range],
01637 lat_grid[lat_range], lon_grid[lon_range],
01638 t_field(p_range,lat_range,lon_range),
01639 vmr_field(joker,p_range,lat_range,lon_range),
01640 pnd_field, scat_data_mono, cloudbox_limits,rte_los);
01641 }
01642 else
01643 {
01644 clear_rt_vars_at_gp( ws, ext_mat_mono, abs_vec_mono, temperature,
01645 opt_prop_gas_agenda, abs_scalar_gas_agenda, f_index,
01646 gp_p, gp_lat, gp_lon, p_grid, lat_grid, lon_grid, t_field,
01647 vmr_field);
01648 pnd_vec=0.0;
01649 }
01650
01651 ext_matArray[1]=ext_mat_mono;
01652 abs_vecArray[1]=abs_vec_mono;
01653 tArray[1]=temperature;
01654 pnd_vecArray[1]=pnd_vec;
01655 opt_depth_mat=ext_matArray[1];
01656
01657 opt_depth_mat+=ext_matArray[0];
01658 opt_depth_mat*=-lstep/2;
01659 incT=0;
01660 if ( stokes_dim == 1 )
01661 {
01662 incT(0,0)=exp(opt_depth_mat(0,0));
01663 }
01664 else if ( is_diagonal( opt_depth_mat))
01665 {
01666 for ( Index j=0;j<stokes_dim;j++)
01667 {
01668 incT(j,j)=exp(opt_depth_mat(j,j));
01669 }
01670 }
01671 else
01672 {
01673 matrix_exp_p30(incT,opt_depth_mat);
01674 }
01675 mult(evol_op,evol_opArray[0],incT);
01676 assert(incT(0,0)<1);
01677 assert(evol_op(0,0)<1);
01678 evol_opArray[1]=evol_op;
01679
01680 }
01681 if (termination_flag)
01682 {
01683
01684 g=evol_op(0,0);
01685 }
01686 else
01687 {
01688
01689
01690
01691
01692
01693 k=-log(incT(0,0))/lstep;
01694
01695 ds=log(evol_opArray[0](0,0)/r)/k;
01696 g=k*r;
01697 l_vec=0.0;
01698 l_vec[1]=lstep;
01699
01700 gridpos(gp, l_vec, ds);
01701 interpweights(itw1d,gp);
01702
01703 ext_mat_mono = interp(itw1d,ext_matArray,gp);
01704 opt_depth_mat = ext_mat_mono;
01705 opt_depth_mat+=ext_matArray[gp.idx];
01706 opt_depth_mat*=-ds/2;
01707 if ( stokes_dim == 1 )
01708 {
01709 incT(0,0)=exp(opt_depth_mat(0,0));
01710 }
01711 else if ( is_diagonal( opt_depth_mat))
01712 {
01713 for ( Index i=0;i<stokes_dim;i++)
01714 {
01715 incT(i,i)=exp(opt_depth_mat(i,i));
01716 }
01717 }
01718 else
01719 {
01720
01721 matrix_exp_p30(incT,opt_depth_mat);
01722 }
01723 mult(evol_op,evol_opArray[gp.idx],incT);
01724 abs_vec_mono = interp(itw1d, abs_vecArray,gp);
01725 temperature=interp(itw1d,tArray,gp);
01726 pnd_vec=interp(itw1d,pnd_vecArray,gp);
01727
01728 x+=(ds-lstep)*dx;
01729 y+=(ds-lstep)*dy;
01730 z+=(ds-lstep)*dz;
01731
01732 cart2poslos(rte_pos[0],rte_pos[1],rte_pos[2],rte_los[0],rte_los[1],x,y,z,dx,dy,dz);
01733
01734 }
01735 }
01736
01737
01738
01740
01751 void mcPathTrace(Workspace& ws,
01752 MatrixView& evol_op,
01753 VectorView& abs_vec_mono,
01754 Numeric& rte_temperature,
01755 MatrixView& ext_mat_mono,
01756 Rng& rng,
01757 Vector& rte_pos,
01758 Vector& rte_los,
01759 Vector& pnd_vec,
01760 Numeric& g,
01761 bool& left_cloudbox,
01762 const Agenda& opt_prop_gas_agenda,
01763 const Agenda& abs_scalar_gas_agenda,
01764 const Index& stokes_dim,
01765 const Index& f_index,
01766 const Vector& p_grid,
01767 const Vector& lat_grid,
01768 const Vector& lon_grid,
01769 const Tensor3& z_field,
01770 const Matrix& r_geoid,
01771 const Matrix& z_surface,
01772 const Tensor3& t_field,
01773 const Tensor4& vmr_field,
01774 const ArrayOfIndex& cloudbox_limits,
01775 const Tensor4& pnd_field,
01776 const ArrayOfSingleScatteringData& scat_data_mono,
01777 const Index& z_field_is_1D)
01778
01779 {
01780 ArrayOfMatrix evol_opArray(2);
01781 ArrayOfMatrix ext_matArray(2);
01782 ArrayOfVector abs_vecArray(2),pnd_vecArray(2);
01783 Vector tArray(2);
01784 Vector cum_l_step;
01785 Matrix T(stokes_dim,stokes_dim);
01786 Ppath ppath_step;
01787 Numeric k;
01788 Numeric ds;
01789 Index np=0;
01790 Matrix opt_depth_mat(stokes_dim,stokes_dim),incT(stokes_dim,stokes_dim,0.0);
01791 Matrix old_evol_op(stokes_dim,stokes_dim);
01792 left_cloudbox=false;
01793
01794 id_mat(evol_op);
01795 evol_opArray[1]=evol_op;
01796
01797
01798
01799
01800
01801
01802 cloudbox_ppath_start_stepping( ppath_step, 3, p_grid, lat_grid,
01803 lon_grid, z_field, r_geoid, z_surface, rte_pos,
01804 rte_los ,z_field_is_1D);
01805 Range p_range(cloudbox_limits[0],
01806 cloudbox_limits[1]-cloudbox_limits[0]+1);
01807 Range lat_range(cloudbox_limits[2],
01808 cloudbox_limits[3]-cloudbox_limits[2]+1);
01809 Range lon_range(cloudbox_limits[4],
01810 cloudbox_limits[5]-cloudbox_limits[4]+1);
01811 cloudy_rt_vars_at_gp( ws, ext_mat_mono, abs_vec_mono,pnd_vec, rte_temperature,
01812 opt_prop_gas_agenda, abs_scalar_gas_agenda, stokes_dim, f_index,
01813 ppath_step.gp_p[0], ppath_step.gp_lat[0], ppath_step.gp_lon[0],
01814 p_grid[p_range], lat_grid[lat_range], lon_grid[lon_range],
01815 t_field(p_range,lat_range,lon_range),
01816 vmr_field(joker,p_range,lat_range,lon_range), pnd_field,
01817 scat_data_mono, cloudbox_limits, ppath_step.los(0,joker) );
01818 ext_matArray[1]=ext_mat_mono;
01819 abs_vecArray[1]=abs_vec_mono;
01820 tArray[1]=rte_temperature;
01821 pnd_vecArray[1]=pnd_vec;
01822
01823 Numeric r = rng.draw();
01824 while ((evol_op(0,0)>r)&(!left_cloudbox))
01825 {
01826 evol_opArray[0]=evol_opArray[1];
01827 ext_matArray[0]=ext_matArray[1];
01828 abs_vecArray[0]=abs_vecArray[1];
01829 tArray[0]=tArray[1];
01830 pnd_vecArray[0]=pnd_vecArray[1];
01831
01832 ppath_step_geom_3d(ppath_step, p_grid, lat_grid, lon_grid, z_field,
01833 r_geoid, z_surface, -1);
01834 np=ppath_step.np;
01835 cum_l_stepCalc(cum_l_step, ppath_step);
01836
01837
01838 cloudy_rt_vars_at_gp( ws, ext_mat_mono, abs_vec_mono, pnd_vec,
01839 rte_temperature, opt_prop_gas_agenda, abs_scalar_gas_agenda,
01840 stokes_dim, f_index, ppath_step.gp_p[np-1], ppath_step.gp_lat[np-1],
01841 ppath_step.gp_lon[np-1], p_grid[p_range], lat_grid[lat_range],
01842 lon_grid[lon_range], t_field(p_range,lat_range,lon_range),
01843 vmr_field(joker,p_range,lat_range,lon_range),
01844 pnd_field,scat_data_mono, cloudbox_limits,
01845 ppath_step.los(np-1,joker));
01846 ext_matArray[1]=ext_mat_mono;
01847 abs_vecArray[1]=abs_vec_mono;
01848 tArray[1]=rte_temperature;
01849 pnd_vecArray[1]=pnd_vec;
01850 opt_depth_mat=ext_matArray[1];
01851 opt_depth_mat+=ext_matArray[0];
01852 opt_depth_mat*=-cum_l_step[np-1]/2;
01853 incT=0;
01854 if ( stokes_dim == 1 )
01855 {
01856 incT(0,0)=exp(opt_depth_mat(0,0));
01857 }
01858 else if ( is_diagonal( opt_depth_mat))
01859 {
01860 for ( Index j=0;j<stokes_dim;j++)
01861 {
01862 incT(j,j)=exp(opt_depth_mat(j,j));
01863 }
01864 }
01865 else
01866 {
01867
01868 matrix_exp_p30(incT,opt_depth_mat);
01869 }
01870 mult(evol_op,evol_opArray[0],incT);
01871 evol_opArray[1]=evol_op;
01872 left_cloudbox=not(is_inside_cloudbox(ppath_step,cloudbox_limits,false));
01873 }
01874
01875 if (left_cloudbox)
01876 {
01877
01878 rte_pos = ppath_step.pos(np-1,Range(0,3));
01879 rte_los = ppath_step.los(np-1,joker);
01880 g=evol_op(0,0);
01881 }
01882 else
01883 {
01884
01885
01886 k=-log(incT(0,0))/cum_l_step[np-1];
01887 ds=log(evol_opArray[0](0,0)/r)/k;
01888 g=k*r;
01889 Vector x(2,0.0);
01890
01891
01892 ArrayOfGridPos gp(1);
01893 x[1]=cum_l_step[np-1];
01894 Vector itw(2);
01895
01896 gridpos(gp, x, ds);
01897 assert(gp[0].idx==0);
01898 interpweights(itw,gp[0]);
01899 ext_mat_mono = interp(itw,ext_matArray,gp[0]);
01900 opt_depth_mat = ext_mat_mono;
01901 opt_depth_mat+=ext_matArray[gp[0].idx];
01902 opt_depth_mat*=-ds/2;
01903 if ( stokes_dim == 1 )
01904 {
01905 incT(0,0)=exp(opt_depth_mat(0,0));
01906 }
01907 else if ( is_diagonal( opt_depth_mat))
01908 {
01909 for ( Index i=0;i<stokes_dim;i++)
01910 {
01911 incT(i,i)=exp(opt_depth_mat(i,i));
01912 }
01913 }
01914 else
01915 {
01916
01917 matrix_exp_p30(incT,opt_depth_mat);
01918 }
01919 mult(evol_op,evol_opArray[gp[0].idx],incT);
01920 abs_vec_mono = interp(itw, abs_vecArray,gp[0]);
01921 rte_temperature=interp(itw,tArray,gp[0]);
01922 pnd_vec=interp(itw,pnd_vecArray,gp[0]);
01923 if (np > 2)
01924 {
01925 gridpos(gp,cum_l_step,ds);
01926 interpweights(itw,gp[0]);
01927 }
01928 for (Index i=0; i<2; i++)
01929 {
01930 rte_pos[i] = interp(itw,ppath_step.pos(Range(joker),i),gp[0]);
01931 rte_los[i] = interp(itw,ppath_step.los(Range(joker),i),gp[0]);
01932 }
01933 rte_pos[2] = interp(itw,ppath_step.pos(Range(joker),2),gp[0]);
01934 }
01935 }
01936
01937
01939
01949 void montecarloGetIncoming(Workspace& ws,
01950 Matrix& iy,
01951 Vector& rte_pos,
01952 Vector& rte_los,
01953 Ppath& ppath,
01954 const Agenda& ppath_step_agenda,
01955 const Agenda& rte_agenda,
01956 const Agenda& iy_space_agenda,
01957 const Agenda& surface_prop_agenda,
01958 const Agenda& iy_cloudbox_agenda,
01959 const Vector& p_grid,
01960 const Vector& lat_grid,
01961 const Vector& lon_grid,
01962 const Tensor3& z_field,
01963 const Tensor3& t_field,
01964 const Tensor4& vmr_field,
01965 const Matrix& r_geoid,
01966 const Matrix& z_surface,
01967 const ArrayOfIndex& cloudbox_limits,
01968 const Index& atmosphere_dim,
01969 const Vector& f_grid,
01970 const Index& stokes_dim
01971 )
01972
01973 {
01974
01975
01976 Vector mblock_za_grid_dummy(1);
01977 mblock_za_grid_dummy[0] = 0;
01978 Vector mblock_aa_grid_dummy(0);
01979
01980 Sparse sensor_response_dummy;
01981
01982
01983 Vector y_dummy(0);
01984
01985 const Index cloudbox_on_dummy=0;
01986 Tensor7 scat_i_p_dummy;
01987 Tensor7 scat_i_lat_dummy;
01988 Tensor7 scat_i_lon_dummy;
01989
01990 Vector pos = rte_pos;
01991 Vector los = rte_los;
01992 iy_calc_no_jacobian( ws, iy, ppath,
01993 ppath_step_agenda, rte_agenda, iy_space_agenda,
01994 surface_prop_agenda, iy_cloudbox_agenda,
01995 atmosphere_dim, p_grid, lat_grid, lon_grid, z_field,
01996 t_field, vmr_field, r_geoid, z_surface,
01997 cloudbox_on_dummy, cloudbox_limits,
01998 pos, los, f_grid,stokes_dim );
01999
02000 for (Index i = 0;i<stokes_dim;i++){assert(!isnan(iy(0,i)));}
02001 }
02002
02004
02014 Numeric opt_depth_calc(Workspace& ws,
02015 Tensor3& ext_mat,
02016 Matrix& abs_vec,
02017 Numeric& rte_pressure,
02018 Numeric& rte_temperature,
02019 Vector& rte_vmr_list,
02020 const Ppath& ppath,
02021 const Agenda& opt_prop_gas_agenda,
02022 const Agenda& abs_scalar_gas_agenda,
02023 const Index& f_index,
02024 const Vector& p_grid,
02025 const Vector& lat_grid,
02026 const Vector& lon_grid,
02027 const Tensor3& t_field,
02028 const Tensor4& vmr_field,
02029 const Index& atmosphere_dim)
02030 {
02031 const Index np=ppath.np;
02032 const Index ns = vmr_field.nbooks();
02033 Vector t_ppath(np);
02034
02035 Vector kvector(np);
02036 Numeric opt_depth=0;
02037
02038 Vector p_ppath(np);
02039 Matrix itw_p(np,2);
02040
02041 interpweights( itw_p, ppath.gp_p );
02042 itw2p( p_ppath, p_grid, ppath.gp_p, itw_p );
02043
02044
02045
02046 Matrix vmr_ppath(ns,np), itw_field;
02047
02048 interp_atmfield_gp2itw( itw_field, atmosphere_dim, p_grid, lat_grid,
02049 lon_grid, ppath.gp_p, ppath.gp_lat, ppath.gp_lon );
02050
02051 interp_atmfield_by_itw( t_ppath, atmosphere_dim, p_grid, lat_grid,
02052 lon_grid, t_field,
02053 ppath.gp_p, ppath.gp_lat, ppath.gp_lon, itw_field );
02054
02055 for( Index is=0; is<ns; is++ )
02056 {
02057 interp_atmfield_by_itw( vmr_ppath(is, joker), atmosphere_dim,
02058 p_grid, lat_grid, lon_grid,
02059 vmr_field(is, joker, joker, joker),
02060 ppath.gp_p, ppath.gp_lat,
02061 ppath.gp_lon, itw_field );
02062 }
02063
02064 for (Index i=0; i<ppath.np; i++)
02065 {
02066 Matrix abs_scalar_gas;
02067 rte_pressure = p_ppath[i];
02068 rte_temperature = t_ppath[i];
02069 rte_vmr_list = vmr_ppath(joker,i);
02070 abs_scalar_gas_agendaExecute (ws, abs_scalar_gas, f_index,
02071 rte_pressure, rte_temperature,
02072 rte_vmr_list,
02073 abs_scalar_gas_agenda);
02074 opt_prop_gas_agendaExecute (ws, ext_mat, abs_vec, f_index, abs_scalar_gas,
02075 opt_prop_gas_agenda);
02076 kvector[i]=ext_mat(0,0,0);
02077 }
02078 for (Index i=1; i<ppath.np;i++)
02079 {
02080 opt_depth+=(kvector[i-1]+kvector[i])*ppath.l_step[i-1]/2;
02081 }
02082 return opt_depth;
02083 }
02084
02086
02103 void opt_propCalc(
02104 MatrixView& ext_mat_mono,
02105 VectorView& abs_vec_mono,
02106 const Numeric za,
02107 const Numeric aa,
02108 const ArrayOfSingleScatteringData& scat_data_mono,
02109 const Index& stokes_dim,
02110 const VectorView& pnd_vec,
02111 const Numeric& rte_temperature
02112 )
02113 {
02114 const Index N_pt = scat_data_mono.nelem();
02115
02116 if (stokes_dim > 4 || stokes_dim < 1){
02117 throw runtime_error("The dimension of the stokes vector \n"
02118 "must be 1,2,3 or 4");
02119 }
02120 Matrix ext_mat_mono_spt(stokes_dim,stokes_dim);
02121 Vector abs_vec_mono_spt(stokes_dim);
02122
02123 ext_mat_mono=0.0;
02124 abs_vec_mono=0.0;
02125
02126
02127 for (Index i_pt = 0; i_pt < N_pt; i_pt++)
02128 {
02129 if (pnd_vec[i_pt]>0)
02130 {
02131 opt_propExtract(ext_mat_mono_spt,abs_vec_mono_spt,scat_data_mono[i_pt],za,aa,
02132 rte_temperature,stokes_dim);
02133 ext_mat_mono_spt*=pnd_vec[i_pt];
02134 abs_vec_mono_spt*=pnd_vec[i_pt];
02135 ext_mat_mono+=ext_mat_mono_spt;
02136 abs_vec_mono+=abs_vec_mono_spt;
02137 }
02138 }
02139
02140 }
02141
02143
02162 void opt_propExtract(
02163 MatrixView& ext_mat_mono_spt,
02164 VectorView& abs_vec_mono_spt,
02165 const SingleScatteringData& scat_data,
02166 const Numeric& za,
02167 const Numeric& aa,
02168 const Numeric& rte_temperature,
02169 const Index& stokes_dim
02170 )
02171 {
02172
02173 GridPos t_gp;
02174
02175 gridpos(t_gp, scat_data.T_grid, rte_temperature);
02176 Numeric x=aa;
02177 x+=1;
02178 switch (scat_data.ptype){
02179
02180 case PTYPE_GENERAL:
02181
02182
02183
02184 out0 << "Case PTYPE_GENERAL not yet implemented. \n";
02185 break;
02186
02187 case PTYPE_MACROS_ISO:
02188 {
02189 assert (scat_data.ext_mat_data.ncols() == 1);
02190
02191 Vector itw(2);
02192 interpweights(itw, t_gp);
02193
02194
02195
02196
02197 ext_mat_mono_spt = 0.;
02198
02199 ext_mat_mono_spt(0,0) = interp(itw,scat_data.ext_mat_data(0,joker,0,0,0),t_gp);
02200
02201 abs_vec_mono_spt = 0;
02202
02203 abs_vec_mono_spt[0] = interp(itw,scat_data.abs_vec_data(0,joker,0,0,0),t_gp);
02204
02205 if( stokes_dim == 1 ){
02206 break;
02207 }
02208
02209 ext_mat_mono_spt(1,1) = ext_mat_mono_spt(0,0);
02210
02211 if( stokes_dim == 2 ){
02212 break;
02213 }
02214
02215 ext_mat_mono_spt(2,2) = ext_mat_mono_spt(0,0);
02216
02217 if( stokes_dim == 3 ){
02218 break;
02219 }
02220
02221 ext_mat_mono_spt(3,3) = ext_mat_mono_spt(0,0);
02222 break;
02223 }
02224
02225 case PTYPE_HORIZ_AL:
02226 {
02227 assert (scat_data.ext_mat_data.ncols() == 3);
02228
02229
02230
02231
02232
02233
02234
02235
02236 GridPos za_gp;
02237 Vector itw(4);
02238 Numeric Kjj;
02239 Numeric K12;
02240 Numeric K34;
02241
02242 if (za>90)
02243 {
02244 gridpos(za_gp,scat_data.za_grid,180-za);
02245 }
02246 else
02247 {
02248 gridpos(za_gp,scat_data.za_grid,za);
02249 }
02250
02251 interpweights(itw,t_gp,za_gp);
02252
02253 ext_mat_mono_spt=0.0;
02254 abs_vec_mono_spt=0.0;
02255 Kjj=interp(itw,scat_data.ext_mat_data(0,joker,joker,0,0),t_gp,za_gp);
02256 ext_mat_mono_spt(0,0)=Kjj;
02257 abs_vec_mono_spt[0] = interp(itw,scat_data.abs_vec_data(0,joker,joker,0,0),
02258 t_gp,za_gp);
02259 if( stokes_dim == 1 ){
02260 break;
02261 }
02262
02263 K12=interp(itw,scat_data.ext_mat_data(0,joker,joker,0,1),t_gp,za_gp);
02264 ext_mat_mono_spt(1,1)=Kjj;
02265 ext_mat_mono_spt(0,1)=K12;
02266 ext_mat_mono_spt(1,0)=K12;
02267 abs_vec_mono_spt[1] = interp(itw,scat_data.abs_vec_data(0,joker,joker,0,1),
02268 t_gp,za_gp);
02269
02270 if( stokes_dim == 2 ){
02271 break;
02272 }
02273
02274 ext_mat_mono_spt(2,2)=Kjj;
02275
02276 if( stokes_dim == 3 ){
02277 break;
02278 }
02279
02280 K34=interp(itw,scat_data.ext_mat_data(0,joker,joker,0,2),t_gp,za_gp);
02281 ext_mat_mono_spt(2,3)=K34;
02282 ext_mat_mono_spt(3,2)=-K34;
02283 ext_mat_mono_spt(3,3)=Kjj;
02284 break;
02285
02286 }
02287 default:
02288 out0 << "Not all particle type cases are implemented\n";
02289
02290 }
02291
02292
02293 }
02294
02295
02296
02297
02298
02299
02300
02302
02319 void pha_mat_singleCalc(
02320 MatrixView& Z,
02321 Numeric za_sca,
02322 Numeric aa_sca,
02323 Numeric za_inc,
02324 Numeric aa_inc,
02325 const ArrayOfSingleScatteringData& scat_data_mono,
02326 const Index& stokes_dim,
02327 const VectorView& pnd_vec,
02328 const Numeric& rte_temperature
02329 )
02330 {
02331 Index N_pt=pnd_vec.nelem();
02332
02333 assert(aa_inc>=-180 && aa_inc<=180);
02334 assert(aa_sca>=-180 && aa_sca<=180);
02335
02336 Matrix Z_spt(stokes_dim, stokes_dim, 0.);
02337 Z=0.0;
02338
02339 for (Index i_pt = 0; i_pt < N_pt; i_pt++)
02340 {
02341 if (pnd_vec[i_pt]>0)
02342 {
02343 pha_mat_singleExtract(Z_spt,scat_data_mono[i_pt],za_sca,aa_sca,za_inc,
02344 aa_inc,rte_temperature,stokes_dim);
02345 Z_spt*=pnd_vec[i_pt];
02346 Z+=Z_spt;
02347 }
02348 }
02349 }
02350
02352
02369 void pha_mat_singleExtract(
02370 MatrixView& Z_spt,
02371 const SingleScatteringData& scat_data,
02372 const Numeric& za_sca,
02373 const Numeric& aa_sca,
02374 const Numeric& za_inc,
02375 const Numeric& aa_inc,
02376 const Numeric& rte_temperature,
02377 const Index& stokes_dim
02378 )
02379 {
02380 switch (scat_data.ptype){
02381
02382 case PTYPE_GENERAL:
02383
02384 out0 << "Case PTYPE_GENERAL not yet implemented. \n";
02385 break;
02386
02387 case PTYPE_MACROS_ISO:
02388 {
02389
02390
02391
02392 Vector pha_mat_int(6);
02393 Numeric theta_rad;
02394
02395
02396 interp_scat_angle_temperature(pha_mat_int, theta_rad,
02397 scat_data, za_sca, aa_sca,
02398 za_inc, aa_inc, rte_temperature);
02399
02400
02401 pha_mat_labCalc(Z_spt, pha_mat_int, za_sca, aa_sca, za_inc, aa_inc, theta_rad);
02402
02403 break;
02404 }
02405
02406 case PTYPE_HORIZ_AL:
02407
02408
02409 {
02410 assert (scat_data.pha_mat_data.ncols()==16);
02411 Numeric delta_aa=aa_sca-aa_inc+(aa_sca-aa_inc<-180)*360-
02412 (aa_sca-aa_inc>180)*360;
02413
02414 GridPos t_gp;
02415 GridPos za_sca_gp;
02416 GridPos delta_aa_gp;
02417 GridPos za_inc_gp;
02418 Vector itw(16);
02419 gridpos(t_gp, scat_data.T_grid, rte_temperature);
02420 gridpos(delta_aa_gp,scat_data.aa_grid,abs(delta_aa));
02421 if (za_inc>90)
02422 {
02423 gridpos(za_inc_gp,scat_data.za_grid,180-za_inc);
02424 gridpos(za_sca_gp,scat_data.za_grid,180-za_sca);
02425 }
02426 else
02427 {
02428 gridpos(za_inc_gp,scat_data.za_grid,za_inc);
02429 gridpos(za_sca_gp,scat_data.za_grid,za_sca);
02430 }
02431
02432 interpweights(itw,t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02433
02434 Z_spt(0,0)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02435 Range(joker),0,0),
02436 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02437 if( stokes_dim == 1 ){
02438 break;
02439 }
02440 Z_spt(0,1)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02441 Range(joker),0,1),
02442 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02443 Z_spt(1,0)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02444 Range(joker),0,4),
02445 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02446 Z_spt(1,1)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02447 Range(joker),0,5),
02448 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02449 if( stokes_dim == 2 ){
02450 break;
02451 }
02452 if ((za_inc<=90 && delta_aa>=0)||(za_inc>90 && delta_aa<0))
02453 {
02454 Z_spt(0,2)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02455 Range(joker),0,2),
02456 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02457 Z_spt(1,2)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02458 Range(joker),0,6),
02459 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02460 Z_spt(2,0)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02461 Range(joker),0,8),
02462 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02463 Z_spt(2,1)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02464 Range(joker),0,9),
02465 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02466 }
02467 else
02468 {
02469 Z_spt(0,2)=-interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02470 Range(joker),0,2),
02471 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02472 Z_spt(1,2)=-interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02473 Range(joker),0,6),
02474 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02475 Z_spt(2,0)=-interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02476 Range(joker),0,8),
02477 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02478 Z_spt(2,1)=-interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02479 Range(joker),0,9),
02480 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02481 }
02482 Z_spt(2,2)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02483 Range(joker),0,10),
02484 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02485 if( stokes_dim == 3 ){
02486 break;
02487 }
02488 if ((za_inc<=90 && delta_aa>=0)||(za_inc>90 && delta_aa<0))
02489 {
02490 Z_spt(0,3)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02491 Range(joker),0,3),
02492 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02493 Z_spt(1,3)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02494 Range(joker),0,7),
02495 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02496 Z_spt(3,0)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02497 Range(joker),0,12),
02498 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02499 Z_spt(3,1)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02500 Range(joker),0,13),
02501 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02502 }
02503 else
02504 {
02505 Z_spt(0,3)=-interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02506 Range(joker),0,3),
02507 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02508 Z_spt(1,3)=-interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02509 Range(joker),0,7),
02510 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02511 Z_spt(3,0)=-interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02512 Range(joker),0,12),
02513 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02514 Z_spt(3,1)=-interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02515 Range(joker),0,13),
02516 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02517 }
02518 Z_spt(2,3)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02519 Range(joker),0,11),
02520 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02521 Z_spt(3,2)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02522 Range(joker),0,14),
02523 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02524 Z_spt(3,3)=interp(itw,scat_data.pha_mat_data(0,joker,Range(joker),Range(joker),
02525 Range(joker),0,15),
02526 t_gp,za_sca_gp,delta_aa_gp,za_inc_gp);
02527 break;
02528
02529 }
02530 default:
02531 out0 << "Not all particle type cases are implemented\n";
02532
02533 }
02534 }
02535
02536
02538
02576 void Sample_los (
02577 VectorView& new_rte_los,
02578 Numeric& g_los_csc_theta,
02579 MatrixView& Z,
02580 Rng& rng,
02581 const VectorView& rte_los,
02582 const ArrayOfSingleScatteringData& scat_data_mono,
02583 const Index& stokes_dim,
02584 const VectorView& pnd_vec,
02585 const bool& anyptype30,
02586 const VectorView& Z11maxvector,
02587 Numeric Csca,
02588 const Numeric& rte_temperature
02589 )
02590 {
02591 Numeric Z11max=0;
02592 bool tryagain=true;
02593 Numeric aa_scat = (rte_los[1]>=0) ?-180+rte_los[1]:180+rte_los[1];
02594
02595 if(anyptype30)
02596 {
02597 Index np=pnd_vec.nelem();
02598 assert(scat_data_mono.nelem()==np);
02599 for(Index i=0;i<np;i++)
02600 {
02601 Z11max+=Z11maxvector[i]*pnd_vec[i];
02602 }
02603 }
02604 else
02605 {
02606 Matrix dummyZ(stokes_dim,stokes_dim);
02607
02608
02609 pha_mat_singleCalc(dummyZ,180-rte_los[0],aa_scat,180-rte_los[0],
02610 aa_scat,scat_data_mono,stokes_dim,pnd_vec,rte_temperature);
02611 Z11max=dummyZ(0,0);
02612 }
02614 while(tryagain)
02615 {
02616 new_rte_los[1] = rng.draw()*360-180;
02617 new_rte_los[0] = acos(1-2*rng.draw())*RAD2DEG;
02618
02619 Numeric aa_inc= (new_rte_los[1]>=0) ?
02620 -180+new_rte_los[1]:180+new_rte_los[1];
02621
02622 pha_mat_singleCalc(Z,180-rte_los[0],aa_scat,180-new_rte_los[0],
02623 aa_inc,scat_data_mono,stokes_dim,pnd_vec,rte_temperature);
02624
02625 if (rng.draw()<=Z(0,0)/Z11max)
02626 {
02627 tryagain=false;
02628 }
02629 }
02630 g_los_csc_theta =Z(0,0)/Csca;
02631 }
02632
02633
02635
02649 void Sample_ppathlengthLOS (
02650 Numeric& pathlength,
02651 Numeric& g,
02652 Rng& rng,
02653 const ArrayOfMatrix& TArray,
02654 const ConstVectorView& cum_l_step
02655 )
02656 {
02657 Index npoints=cum_l_step.nelem();
02658 assert(TArray.nelem()==npoints);
02659
02660
02661 Numeric r = rng.draw();
02662
02663 Vector T11vector(npoints);
02664 for (Index i=0;i<npoints;i++)
02665 {
02666 T11vector[i]=TArray[i](0,0);
02667 if (T11vector[i] < 1e-12)
02668 {
02669
02670 T11vector=T11vector[Range(0,i+1)];
02671 npoints=i+1;
02672 break;
02673 }
02674 }
02675 GridPos gp;
02676
02677 gridpos(gp,T11vector,1-r*(1-T11vector[npoints-1]));
02678
02679 Numeric T11,T11A,T11B,sA,sB,K;
02680 T11=1-r*(1-T11vector[npoints-1]);
02681 T11A=T11vector[gp.idx];
02682 T11B=T11vector[gp.idx+1];
02683 sA=cum_l_step[gp.idx];
02684 sB=cum_l_step[gp.idx+1];
02685 K=log(T11A/T11B)/(sB-sA);
02686 assert (K>0);
02687 pathlength=sA+log(T11A/T11)/K;
02688 g=K*T11/(1-T11vector[npoints-1]);
02689 }
02690
02692
02704 void TArrayCalc(Workspace& ws,
02705
02706 ArrayOfMatrix& TArray,
02707 ArrayOfMatrix& ext_matArray,
02708 ArrayOfVector& abs_vecArray,
02709 Vector& t_ppath,
02710 Tensor3& ext_mat,
02711 Matrix& abs_vec,
02712 Numeric& rte_pressure,
02713 Numeric& rte_temperature,
02714 Vector& rte_vmr_list,
02715 Matrix& pnd_ppath,
02716
02717 const Ppath& ppath,
02718 const Agenda& opt_prop_gas_agenda,
02719 const Agenda& abs_scalar_gas_agenda,
02720 const Index& f_index,
02721 const Index& stokes_dim,
02722 const ConstVectorView& p_grid_cloud,
02723 const ConstVectorView& lat_grid_cloud,
02724 const ConstVectorView& lon_grid_cloud,
02725 const ConstTensor3View& t_field_cloud,
02726 const ConstTensor4View& vmr_field_cloud,
02727 const Tensor4& pnd_field,
02728 const ArrayOfSingleScatteringData& scat_data_mono,
02729 const ArrayOfIndex& cloudbox_limits
02730 )
02731 {
02732 const Index np=ppath.np;
02733 const Index ns = vmr_field_cloud.nbooks();
02734 const Index N_pt = pnd_field.nbooks();
02735
02736 Vector scat_za_grid(np);
02737 Vector scat_aa_grid(np);
02738 Vector p_ppath(np);
02739 Matrix vmr_ppath(ns,np);
02740
02741 TArray.resize(np);
02742 ext_matArray.resize(np);
02743 abs_vecArray.resize(np);
02744 pnd_ppath.resize(N_pt,np);
02745 t_ppath.resize(np);
02746 Matrix opt_depth_mat(stokes_dim,stokes_dim),incT(stokes_dim,stokes_dim,0.0);
02747 Matrix zeroMatrix(stokes_dim,stokes_dim,0.0);
02748 Matrix identity(stokes_dim,stokes_dim,0.0);
02749
02750 for (Index i=0; i<stokes_dim; i++){identity(i,i)=1.0;}
02751
02752 Matrix ext_mat_part(stokes_dim, stokes_dim, 0.0);
02753 Vector abs_vec_part(stokes_dim, 0.0);
02754
02755
02756
02757 scat_za_grid=ppath.los(Range(joker),0);
02758 scat_za_grid*=-1.0;
02759 scat_za_grid+=180;
02760 scat_aa_grid=ppath.los(Range(joker),1);
02761 scat_aa_grid+=180;
02762
02763
02764
02765 cloud_atm_vars_by_gp(p_ppath,t_ppath,vmr_ppath,pnd_ppath,ppath.gp_p,
02766 ppath.gp_lat,ppath.gp_lon,cloudbox_limits,p_grid_cloud,
02767 lat_grid_cloud,lon_grid_cloud,t_field_cloud,
02768 vmr_field_cloud,pnd_field);
02769
02770
02771 for (Index scat_za_index=0; scat_za_index<ppath.np; scat_za_index++)
02772 {
02773 Matrix abs_scalar_gas;
02774 Index scat_aa_index=scat_za_index;
02775 rte_pressure = p_ppath[scat_za_index];
02776 rte_temperature = t_ppath[scat_za_index];
02777 rte_vmr_list = vmr_ppath(joker,scat_za_index);
02778 abs_scalar_gas_agendaExecute (ws, abs_scalar_gas, f_index,
02779 rte_pressure, rte_temperature,
02780 rte_vmr_list,
02781 abs_scalar_gas_agenda);
02782 opt_prop_gas_agendaExecute( ws, ext_mat, abs_vec, f_index, abs_scalar_gas,
02783 opt_prop_gas_agenda );
02784 ext_mat_part=0.0;
02785 abs_vec_part=0.0;
02786
02787 if (scat_aa_grid[scat_aa_index]>180){scat_aa_grid[scat_aa_index]-=360;}
02788
02789
02790
02791
02792 opt_propCalc(ext_mat_part,abs_vec_part,scat_za_grid[scat_za_index],
02793 scat_aa_grid[scat_aa_index],scat_data_mono,stokes_dim,
02794 pnd_ppath(joker, scat_za_index),rte_temperature);
02795
02796 ext_mat(0, Range(joker), Range(joker)) += ext_mat_part;
02797 abs_vec(0,Range(joker)) += abs_vec_part;
02798
02799 ext_matArray[scat_za_index]=ext_mat(0,joker,joker);
02800 abs_vecArray[scat_za_index]=abs_vec(0,joker);
02801 }
02802
02803
02804 TArray[0]=identity;
02805 for (Index i=1; i<ppath.np;i++)
02806 {
02807
02808 opt_depth_mat=ext_matArray[i];
02809 opt_depth_mat+=ext_matArray[i-1];
02810 opt_depth_mat*=-ppath.l_step[i-1]/2;
02811 incT=0;
02812 if ( stokes_dim == 1 )
02813 {
02814 incT(0,0)=exp(opt_depth_mat(0,0));
02815 }
02816 else if ( is_diagonal( opt_depth_mat))
02817 {
02818 for ( Index j=0;j<stokes_dim;j++)
02819 {
02820 incT(j,j)=exp(opt_depth_mat(j,j));
02821 }
02822 }
02823 else
02824 {
02825
02826 matrix_exp_p30(incT,opt_depth_mat);
02827 }
02828 TArray[i]=zeroMatrix;
02829 mult(TArray[i],TArray[i-1],incT);
02830 }
02831
02832 }
02833