00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00035
00036
00037
00038
00039 #include <stdexcept>
00040 #include <iostream>
00041 #include <cstdlib>
00042 #include <cmath>
00043 #include "arts.h"
00044 #include "array.h"
00045 #include "auto_md.h"
00046 #include "check_input.h"
00047 #include "matpackVII.h"
00048 #include "logic.h"
00049 #include "ppath.h"
00050 #include "agenda_class.h"
00051 #include "physics_funcs.h"
00052 #include "lin_alg.h"
00053 #include "math_funcs.h"
00054 #include "messages.h"
00055 #include "xml_io.h"
00056 #include "rte.h"
00057 #include "special_interp.h"
00058 #include "scatrte.h"
00059 #include "m_general.h"
00060 #include "wsv_aux.h"
00061
00062 extern const Numeric PI;
00063 extern const Numeric RAD2DEG;
00064
00065
00066
00067
00068
00069
00070
00071 void DoitAngularGridsSet(
00072 Index& doit_za_grid_size,
00073 Vector& scat_aa_grid,
00074 Vector& scat_za_grid,
00075
00076 const Index& N_za_grid,
00077 const Index& N_aa_grid,
00078 const String& za_grid_opt_file)
00079 {
00080
00081
00082
00083
00084
00085 if (N_za_grid < 16)
00086 throw runtime_error("N_za_grid must be greater than 15 for accurate results");
00087 else if (N_za_grid > 100)
00088 out1 << "Warning: N_za_grid is very large which means that the \n"
00089 << "calculation will be very slow. The recommended value is 19.\n";
00090
00091 if (N_aa_grid < 6)
00092 throw runtime_error("N_aa_grid must be greater than 5 for accurate results");
00093 else if (N_aa_grid > 100)
00094 out1 << "Warning: N_aa_grid is very large which means that the \n"
00095 << "calculation will be very slow. The recommended value is 10.\n";
00096
00097
00098
00099 nlinspace(scat_aa_grid, 0, 360, N_aa_grid);
00100
00101
00102
00103 doit_za_grid_size = N_za_grid;
00104
00105 if( za_grid_opt_file == "" )
00106 nlinspace(scat_za_grid, 0, 180, N_za_grid);
00107 else
00108 xml_read_from_file(za_grid_opt_file, scat_za_grid);
00109
00110 }
00111
00112
00113
00114 void doit_conv_flagAbs(
00115 Index& doit_conv_flag,
00116 Index& doit_iteration_counter,
00117
00118 const Tensor6& doit_i_field,
00119 const Tensor6& doit_i_field_old,
00120
00121 const Vector& epsilon)
00122 {
00123
00124 if( doit_conv_flag != 0 )
00125 throw runtime_error("Convergence flag is non-zero, which means that this\n"
00126 "WSM is not used correctly. *doit_conv_flagAbs* should\n"
00127 "be used only in *doit_conv_test_agenda*\n");
00128
00129
00130 if (doit_iteration_counter > 100)
00131 {
00132 out1 <<"Warning in DOIT calculation:"
00133 <<"Method does not converge (number of iterations \n"
00134 <<"is > 100). Either the cloud particle number density \n"
00135 <<"is too large or the numerical setup for the DOIT \n"
00136 <<"calculation is not correct. In case of limb \n"
00137 <<"simulations please make sure that you use an \n"
00138 <<"optimized zenith angle grid. \n"
00139 <<"*doit_i_field* might be wrong.\n";
00140 doit_conv_flag = 1;
00141 }
00142
00143 const Index N_p = doit_i_field.nvitrines();
00144 const Index N_lat = doit_i_field.nshelves();
00145 const Index N_lon = doit_i_field.nbooks();
00146 const Index N_za = doit_i_field.npages();
00147 const Index N_aa = doit_i_field.nrows();
00148 const Index stokes_dim = doit_i_field.ncols();
00149
00150
00151 if ( epsilon.nelem() != stokes_dim )
00152 throw runtime_error(
00153 "You have to specify limiting values for the "
00154 "convergence test for each Stokes component "
00155 "separately. That means that *epsilon* must "
00156 "have *stokes_dim* elements!"
00157 );
00158
00159
00160 if(!is_size( doit_i_field_old,
00161 N_p, N_lat, N_lon, N_za, N_aa, stokes_dim))
00162 throw runtime_error("The fields (Tensor6) *doit_i_field* and \n"
00163 "*doit_i_field_old* which are compared in the \n"
00164 "convergence test do not have the same size.\n");
00165
00166
00167
00168
00169 out2 << " Number of DOIT iteration: " << doit_iteration_counter << "\n";
00170 doit_iteration_counter +=1;
00171
00172
00173 for (Index p_index = 0; p_index < N_p; p_index++)
00174 {
00175 for (Index lat_index = 0; lat_index < N_lat; lat_index++)
00176 {
00177 for (Index lon_index = 0; lon_index <N_lon; lon_index++)
00178 {
00179 for (Index scat_za_index = 0; scat_za_index < N_za;
00180 scat_za_index++)
00181 {
00182 for (Index scat_aa_index = 0; scat_aa_index < N_aa;
00183 scat_aa_index++)
00184 {
00185 for (Index stokes_index = 0; stokes_index <
00186 stokes_dim; stokes_index ++)
00187 {
00188 Numeric diff =
00189 (doit_i_field(p_index, lat_index, lon_index,
00190 scat_za_index, scat_aa_index,
00191 stokes_index) -
00192 doit_i_field_old(p_index, lat_index,
00193 lon_index, scat_za_index,
00194 scat_aa_index,
00195 stokes_index ));
00196
00197
00198
00199
00200
00201 if( abs(diff) > epsilon[stokes_index])
00202 {
00203 out1 << "difference: " << diff <<"\n";
00204 return;
00205 }
00206
00207
00208 }
00209 }
00210 }
00211 }
00212 }
00213 }
00214
00215
00216 doit_conv_flag = 1;
00217 out2 << " Number of DOIT-iterations: " << doit_iteration_counter << "\n";
00218 }
00219
00220
00221
00222 void doit_conv_flagAbsBT(
00223 Index& doit_conv_flag,
00224 Index& doit_iteration_counter,
00225
00226 const Tensor6& doit_i_field,
00227 const Tensor6& doit_i_field_old,
00228 const Vector& f_grid,
00229 const Index& f_index,
00230
00231 const Vector& epsilon)
00232 {
00233
00234
00235 if( doit_conv_flag != 0 )
00236 throw runtime_error("Convergence flag is non-zero, which means that this \n"
00237 "WSM is not used correctly. *doit_conv_flagAbs* should\n"
00238 "be used only in *doit_conv_test_agenda*\n");
00239
00240 if (doit_iteration_counter > 100)
00241 {
00242 out1 <<"Warning in DOIT calculation at frequency" << f_grid[f_index]
00243 << "GHz: \n"
00244 <<"Method does not converge (number of iterations \n"
00245 <<"is > 100). Either the cloud particle number density \n"
00246 <<"is too large or the numerical setup for the DOIT \n"
00247 <<"calculation is not correct. In case of limb \n"
00248 <<"simulations please make sure that you use an \n"
00249 <<"optimized zenith angle grid. \n"
00250 <<"*doit_i_field* might be wrong.\n";
00251 doit_conv_flag = 1;
00252 }
00253
00254 const Index N_p = doit_i_field.nvitrines();
00255 const Index N_lat = doit_i_field.nshelves();
00256 const Index N_lon = doit_i_field.nbooks();
00257 const Index N_za = doit_i_field.npages();
00258 const Index N_aa = doit_i_field.nrows();
00259 const Index stokes_dim = doit_i_field.ncols();
00260
00261
00262 if ( epsilon.nelem() != stokes_dim )
00263 throw runtime_error(
00264 "You have to specify limiting values for the "
00265 "convergence test for each Stokes component "
00266 "separately. That means that *epsilon* must "
00267 "have *stokes_dim* elements!"
00268 );
00269
00270
00271 if(!is_size( doit_i_field_old,
00272 N_p, N_lat, N_lon, N_za, N_aa, stokes_dim))
00273 throw runtime_error("The fields (Tensor6) *doit_i_field* and \n"
00274 "*doit_i_field_old* which are compared in the \n"
00275 "convergence test do not have the same size.\n");
00276
00277
00278
00279 if( f_grid.nelem() == 0 )
00280 throw runtime_error( "The frequency grid is empty." );
00281 chk_if_increasing( "f_grid", f_grid );
00282
00283
00284 if ( f_index >= f_grid.nelem() )
00285 throw runtime_error("*f_index* is greater than number of elements in the\n"
00286 "frequency grid.\n");
00287
00288
00289
00290 out2 << " Number of DOIT iteration: " << doit_iteration_counter << "\n";
00291 doit_iteration_counter +=1;
00292
00293 for (Index p_index = 0; p_index < N_p; p_index++)
00294 {
00295 for (Index lat_index = 0; lat_index < N_lat; lat_index++)
00296 {
00297 for (Index lon_index = 0; lon_index <N_lon; lon_index++)
00298 {
00299 for (Index scat_za_index = 0; scat_za_index < N_za;
00300 scat_za_index++)
00301 {
00302 for (Index scat_aa_index = 0; scat_aa_index < N_aa;
00303 scat_aa_index++)
00304 {
00305 for (Index stokes_index = 0; stokes_index <
00306 stokes_dim; stokes_index ++)
00307 {
00308 Numeric diff =
00309 abs( doit_i_field(p_index, lat_index, lon_index,
00310 scat_za_index, scat_aa_index,
00311 stokes_index) -
00312 doit_i_field_old(p_index, lat_index,
00313 lon_index, scat_za_index,
00314 scat_aa_index,
00315 stokes_index ));
00316
00317
00318
00319
00320 Numeric diff_bt = invrayjean(diff, f_grid[f_index]);
00321 if( diff_bt > epsilon[stokes_index])
00322 {
00323 out1 << "BT difference: " << diff_bt <<"\n";
00324 return;
00325 }
00326 }
00327 }
00328 }
00329 }
00330 }
00331 }
00332
00333
00334 doit_conv_flag = 1;
00335 out1 << "Number of DOIT-iterations:" << doit_iteration_counter << "\n";
00336 }
00337
00338
00339
00340 void doit_conv_flagLsq(
00341 Index& doit_conv_flag,
00342 Index& doit_iteration_counter,
00343
00344 const Tensor6& doit_i_field,
00345 const Tensor6& doit_i_field_old,
00346 const Vector& f_grid,
00347 const Index& f_index,
00348
00349 const Vector& epsilon)
00350 {
00351
00352
00353 if( doit_conv_flag != 0 )
00354 throw runtime_error("Convergence flag is non-zero, which means that this \n"
00355 "WSM is not used correctly. *doit_conv_flagAbs* should\n"
00356 "be used only in *doit_conv_test_agenda*\n");
00357
00358
00359 if (doit_iteration_counter > 100)
00360 throw runtime_error("Error in DOIT calculation: \n"
00361 "Method does not converge (number of iterations \n"
00362 "is > 100). Either the cloud particle number density \n"
00363 "is too large or the numerical setup for the DOIT \n"
00364 "calculation is not correct. In case of limb \n"
00365 "simulations please make sure that you use an \n"
00366 "optimized zenith angle grid. \n");
00367
00368 const Index N_p = doit_i_field.nvitrines();
00369 const Index N_lat = doit_i_field.nshelves();
00370 const Index N_lon = doit_i_field.nbooks();
00371 const Index N_za = doit_i_field.npages();
00372 const Index N_aa = doit_i_field.nrows();
00373 const Index stokes_dim = doit_i_field.ncols();
00374
00375
00376 if ( epsilon.nelem() != stokes_dim )
00377 throw runtime_error(
00378 "You have to specify limiting values for the "
00379 "convergence test for each Stokes component "
00380 "separately. That means that *epsilon* must "
00381 "have *stokes_dim* elements!"
00382 );
00383
00384
00385 if(!is_size( doit_i_field_old,
00386 N_p, N_lat, N_lon, N_za, N_aa, stokes_dim))
00387 throw runtime_error("The fields (Tensor6) *doit_i_field* and \n"
00388 "*doit_i_field_old* which are compared in the \n"
00389 "convergence test do not have the same size.\n");
00390
00391
00392
00393 if( f_grid.nelem() == 0 )
00394 throw runtime_error( "The frequency grid is empty." );
00395 chk_if_increasing( "f_grid", f_grid );
00396
00397
00398 if ( f_index >= f_grid.nelem() )
00399 throw runtime_error("*f_index* is greater than number of elements in the\n"
00400 "frequency grid.\n");
00401
00402
00403
00404
00405 out2 << " Number of DOIT iteration: " << doit_iteration_counter << "\n";
00406 doit_iteration_counter +=1;
00407
00408 Vector lqs(4, 0.);
00409
00410
00411 doit_conv_flag = 1;
00412 for (Index i = 0; i < epsilon.nelem(); i ++)
00413 {
00414 for (Index p_index = 0; p_index < N_p; p_index++)
00415 {
00416 for (Index lat_index = 0; lat_index < N_lat; lat_index++)
00417 {
00418 for (Index lon_index = 0; lon_index <N_lon; lon_index++)
00419 {
00420 for (Index scat_za_index = 0; scat_za_index < N_za;
00421 scat_za_index++)
00422 {
00423 for (Index scat_aa_index = 0; scat_aa_index < N_aa;
00424 scat_aa_index++)
00425 {
00426 lqs[i]
00427 += pow(
00428 doit_i_field(p_index, lat_index,
00429 lon_index,
00430 scat_za_index, scat_aa_index, i) -
00431 doit_i_field_old(p_index, lat_index,
00432 lon_index, scat_za_index,
00433 scat_aa_index, i)
00434 , 2);
00435 }
00436 }
00437 }
00438 }
00439 }
00440
00441 lqs[i] = sqrt(lqs[i]);
00442 lqs[i] /= (Numeric)(N_p*N_lat*N_lon*N_za*N_aa);
00443
00444
00445 lqs[i] = invrayjean(lqs[i], f_grid[f_index]);
00446
00447 if (lqs[i] >= epsilon[i] )
00448 doit_conv_flag = 0;
00449 }
00450
00451 out1 << "lqs [I]: " << lqs[0] << "\n";
00452
00453 if (doit_conv_flag == 1)
00454 {
00455
00456 out1 << "Number of DOIT-iterations: " << doit_iteration_counter
00457 << "\n";
00458 }
00459 }
00460
00461
00462
00463 void doit_i_fieldIterate(
00464 Workspace& ws,
00465
00466 Tensor6& doit_i_field,
00467
00468 const Agenda& doit_scat_field_agenda,
00469 const Agenda& doit_rte_agenda,
00470 const Agenda& doit_conv_test_agenda
00471 )
00472 {
00473
00474 chk_not_empty( "doit_scat_field_agenda", doit_scat_field_agenda);
00475 chk_not_empty( "doit_rte_agenda", doit_rte_agenda);
00476 chk_not_empty( "doit_conv_test_agenda", doit_conv_test_agenda);
00477
00478
00479
00480
00481
00482
00483 Tensor6 doit_i_field_old_local;
00484 Index doit_conv_flag_local;
00485 Index doit_iteration_counter_local;
00486
00487
00488
00489 Tensor6 doit_scat_field_local
00490 (doit_i_field.nvitrines(), doit_i_field.nshelves(),
00491 doit_i_field.nbooks(), doit_i_field.npages(),
00492 doit_i_field.nrows(), doit_i_field.ncols(), 0.);
00493
00494 doit_conv_flag_local = 0;
00495 doit_iteration_counter_local = 0;
00496
00497 while(doit_conv_flag_local == 0) {
00498
00499
00500 doit_i_field_old_local = doit_i_field;
00501
00502
00503
00504
00505 out2 << " Execute doit_scat_field_agenda. \n";
00506 doit_scat_field_agendaExecute(ws, doit_scat_field_local,
00507 doit_i_field,
00508 doit_scat_field_agenda);
00509
00510
00511 out2 << " Execute doit_rte_agenda. \n";
00512 doit_rte_agendaExecute(ws, doit_i_field, doit_scat_field_local,
00513 doit_rte_agenda);
00514
00515
00516 doit_conv_test_agendaExecute(ws, doit_conv_flag_local,
00517 doit_iteration_counter_local,
00518 doit_i_field,
00519 doit_i_field_old_local,
00520 doit_conv_test_agenda);
00521
00522 }
00523 }
00524
00525
00526
00527 void
00528 doit_i_fieldUpdate1D(
00529 Workspace& ws,
00530
00531 Tensor6& doit_i_field,
00532
00533 const Tensor6& doit_i_field_old,
00534 const Tensor6& doit_scat_field,
00535 const ArrayOfIndex& cloudbox_limits,
00536
00537 const Agenda& abs_scalar_gas_agenda,
00538 const Tensor4& vmr_field,
00539
00540 const Agenda& spt_calc_agenda,
00541 const Vector& scat_za_grid,
00542 const Tensor4& pnd_field,
00543
00544 const Agenda& opt_prop_part_agenda,
00545 const Agenda& opt_prop_gas_agenda,
00546
00547 const Agenda& ppath_step_agenda,
00548 const Vector& p_grid,
00549 const Tensor3& z_field,
00550 const Matrix& r_geoid,
00551 const Matrix& z_surface,
00552
00553 const Tensor3& t_field,
00554 const Vector& f_grid,
00555 const Index& f_index,
00556 const Agenda&,
00557 const Index& doit_za_interp
00558 )
00559 {
00560
00561 out2 << " doit_i_fieldUpdateSeq1D: Radiative transfer calculation in cloudbox\n";
00562 out2 << " ------------------------------------------------------------- \n";
00563
00564
00565
00566
00567 chk_not_empty( "spt_calc_agenda", spt_calc_agenda);
00568 chk_not_empty( "opt_prop_part_agenda", opt_prop_part_agenda);
00569 chk_not_empty( "opt_prop_gas_agenda", opt_prop_gas_agenda);
00570 chk_not_empty( "ppath_step_agenda", ppath_step_agenda);
00571
00572 if (cloudbox_limits.nelem() != 2)
00573 throw runtime_error(
00574 "The cloudbox dimension is not 1D! \n"
00575 "Do you really want to do a 1D calculation? \n"
00576 "If not, use *doit_i_fieldUpdateSeq3D*.\n"
00577 );
00578
00579
00580 const Index N_scat_za = scat_za_grid.nelem();
00581
00582 if (scat_za_grid[0] != 0. || scat_za_grid[N_scat_za-1] != 180.)
00583 throw runtime_error("The range of *scat_za_grid* must [0 180].");
00584
00585 if( p_grid.nelem() < 2 )
00586 throw runtime_error( "The length of *p_grid* must be >= 2." );
00587 chk_if_decreasing( "p_grid", p_grid );
00588
00589 chk_size("z_field", z_field, p_grid.nelem(), 1, 1);
00590 chk_size("t_field", t_field, p_grid.nelem(), 1, 1);
00591
00592 const Vector dummy(1,0.);
00593 chk_atm_surface( "r_geoid", r_geoid, 1, dummy,
00594 dummy);
00595
00596
00597
00598 if( f_grid.nelem() == 0 )
00599 throw runtime_error( "The frequency grid is empty." );
00600 chk_if_increasing( "f_grid", f_grid );
00601
00602
00603 if ( f_index >= f_grid.nelem() )
00604 throw runtime_error("*f_index* is greater than number of elements in the\n"
00605 "frequency grid.\n");
00606
00607 if( !(doit_za_interp == 0 || doit_za_interp == 1 ) )
00608 throw runtime_error( "Interpolation method is not defined. Use \n"
00609 "*doit_za_interpSet*.\n");
00610
00611 const Index stokes_dim = doit_scat_field.ncols();
00612 assert(stokes_dim > 0 || stokes_dim < 5);
00613
00614
00615
00616 assert( is_size( doit_i_field,
00617 (cloudbox_limits[1] - cloudbox_limits[0]) + 1, 1, 1,
00618 N_scat_za, 1, stokes_dim));
00619
00620 assert( is_size( doit_i_field_old,
00621 (cloudbox_limits[1] - cloudbox_limits[0]) + 1, 1, 1,
00622 scat_za_grid.nelem(), 1, stokes_dim));
00623
00624 assert( is_size( doit_scat_field,
00625 (cloudbox_limits[1] - cloudbox_limits[0]) + 1, 1, 1,
00626 N_scat_za, 1, stokes_dim));
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 out3 << "Calculate single particle properties \n";
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646 Tensor5 ext_mat_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
00647 stokes_dim, stokes_dim, 0.);
00648 Tensor4 abs_vec_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
00649 stokes_dim, 0.);
00650
00651
00652 Index scat_aa_index_local = 0;
00653
00654
00655 for( Index scat_za_index_local = 0; scat_za_index_local < N_scat_za;
00656 scat_za_index_local ++)
00657 {
00658
00659
00660
00661
00662
00663 cloud_fieldsCalc(ws, ext_mat_field, abs_vec_field,
00664 spt_calc_agenda,
00665 opt_prop_part_agenda, scat_za_index_local,
00666 scat_aa_index_local,
00667 cloudbox_limits, t_field, pnd_field);
00668
00669
00670
00671
00672
00673 for(Index p_index = cloudbox_limits[0]; p_index
00674 <= cloudbox_limits[1]; p_index ++)
00675 {
00676 cloud_ppath_update1D_noseq(ws, doit_i_field,
00677 p_index, scat_za_index_local,
00678 scat_za_grid,
00679 cloudbox_limits, doit_i_field_old,
00680 doit_scat_field,
00681 abs_scalar_gas_agenda, vmr_field,
00682 opt_prop_gas_agenda, ppath_step_agenda,
00683 p_grid, z_field, r_geoid, z_surface,
00684 t_field, f_grid, f_index, ext_mat_field,
00685 abs_vec_field,
00686 doit_za_interp);
00687 }
00688 }
00689 }
00690
00691
00692
00693 void
00694 doit_i_fieldUpdateSeq1D(
00695 Workspace& ws,
00696
00697 Tensor6& doit_i_field,
00698
00699 const Tensor6& doit_scat_field,
00700 const ArrayOfIndex& cloudbox_limits,
00701
00702 const Agenda& abs_scalar_gas_agenda,
00703 const Tensor4& vmr_field,
00704
00705 const Agenda& spt_calc_agenda,
00706 const Vector& scat_za_grid,
00707 const Tensor4& pnd_field,
00708
00709 const Agenda& opt_prop_part_agenda,
00710 const Agenda& opt_prop_gas_agenda,
00711
00712 const Agenda& ppath_step_agenda,
00713 const Vector& p_grid,
00714 const Tensor3& z_field,
00715 const Matrix& r_geoid,
00716 const Matrix& z_surface,
00717
00718 const Tensor3& t_field,
00719 const Vector& f_grid,
00720 const Index& f_index,
00721 const Agenda& surface_prop_agenda,
00722 const Index& doit_za_interp
00723 )
00724 {
00725
00726 out2<<" doit_i_fieldUpdateSeq1D: Radiative transfer calculation in cloudbox\n";
00727 out2 << " ------------------------------------------------------------- \n";
00728
00729
00730
00731
00732 chk_not_empty( "abs_scalar_gas_agenda", abs_scalar_gas_agenda);
00733 chk_not_empty( "spt_calc_agenda", spt_calc_agenda);
00734 chk_not_empty( "opt_prop_part_agenda", opt_prop_part_agenda);
00735 chk_not_empty( "opt_prop_gas_agenda", opt_prop_gas_agenda);
00736 chk_not_empty( "ppath_step_agenda", ppath_step_agenda);
00737
00738 if (cloudbox_limits.nelem() != 2)
00739 throw runtime_error(
00740 "The cloudbox dimension is not 1D! \n"
00741 "Do you really want to do a 1D calculation? \n"
00742 "For 3D use *doit_i_fieldUpdateSeq3D*.\n"
00743 );
00744
00745
00746 const Index N_scat_za = scat_za_grid.nelem();
00747
00748 if (scat_za_grid[0] != 0. || scat_za_grid[N_scat_za-1] != 180.)
00749 throw runtime_error("The range of *scat_za_grid* must [0 180].");
00750
00751 if( p_grid.nelem() < 2 )
00752 throw runtime_error( "The length of *p_grid* must be >= 2." );
00753 chk_if_decreasing( "p_grid", p_grid );
00754
00755 chk_size("z_field", z_field, p_grid.nelem(), 1, 1);
00756 chk_size("t_field", t_field, p_grid.nelem(), 1, 1);
00757
00758 const Vector dummy(1,0.);
00759 chk_atm_surface( "r_geoid", r_geoid, 1, dummy,
00760 dummy);
00761
00762
00763
00764 if( f_grid.nelem() == 0 )
00765 throw runtime_error( "The frequency grid is empty." );
00766 chk_if_increasing( "f_grid", f_grid );
00767
00768
00769 if ( f_index >= f_grid.nelem() )
00770 throw runtime_error("*f_index* is greater than number of elements in the\n"
00771 "frequency grid.\n");
00772
00773 if( !(doit_za_interp == 0 || doit_za_interp == 1 ) )
00774 throw runtime_error( "Interpolation method is not defined. Use \n"
00775 "*doit_za_interpSet*.\n");
00776
00777 const Index stokes_dim = doit_scat_field.ncols();
00778 assert(stokes_dim > 0 || stokes_dim < 5);
00779
00780
00781
00782 assert( is_size( doit_i_field,
00783 (cloudbox_limits[1] - cloudbox_limits[0]) + 1, 1, 1,
00784 N_scat_za, 1, stokes_dim));
00785
00786 assert( is_size( doit_scat_field,
00787 (cloudbox_limits[1] - cloudbox_limits[0]) + 1, 1, 1,
00788 N_scat_za, 1, stokes_dim));
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 out3 << "Calculate single particle properties \n";
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 Tensor5 ext_mat_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
00809 stokes_dim, stokes_dim, 0.);
00810 Tensor4 abs_vec_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
00811 stokes_dim, 0.);
00812
00813
00814
00815
00816 Numeric theta_lim = 180. - asin((r_geoid(0,0)+
00817 z_field(cloudbox_limits[0],0,0))/
00818 (r_geoid(0,0)+
00819 z_field(cloudbox_limits[1],0,0)))*RAD2DEG;
00820
00821 Index scat_aa_index_local = 0;
00822
00823
00824 for(Index scat_za_index_local = 0; scat_za_index_local < N_scat_za;
00825 scat_za_index_local ++)
00826 {
00827
00828
00829
00830
00831
00832 cloud_fieldsCalc(ws, ext_mat_field, abs_vec_field,
00833 spt_calc_agenda, opt_prop_part_agenda,
00834 scat_za_index_local, scat_aa_index_local,
00835 cloudbox_limits, t_field, pnd_field);
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 if ( scat_za_grid[scat_za_index_local] <= 90.)
00849 {
00850
00851
00852
00853
00854
00855 for(Index p_index = cloudbox_limits[1]-1; p_index
00856 >= cloudbox_limits[0]; p_index --)
00857 {
00858 cloud_ppath_update1D(ws, doit_i_field,
00859 p_index, scat_za_index_local, scat_za_grid,
00860 cloudbox_limits, doit_scat_field,
00861 abs_scalar_gas_agenda, vmr_field,
00862 opt_prop_gas_agenda, ppath_step_agenda,
00863 p_grid, z_field, r_geoid, z_surface,
00864 t_field, f_grid, f_index, ext_mat_field,
00865 abs_vec_field,
00866 surface_prop_agenda, doit_za_interp);
00867 }
00868 }
00869 else if ( scat_za_grid[scat_za_index_local] >= theta_lim)
00870 {
00871
00872
00873
00874 for(Index p_index = cloudbox_limits[0]+1; p_index
00875 <= cloudbox_limits[1]; p_index ++)
00876 {
00877 cloud_ppath_update1D(ws, doit_i_field,
00878 p_index, scat_za_index_local, scat_za_grid,
00879 cloudbox_limits, doit_scat_field,
00880 abs_scalar_gas_agenda, vmr_field,
00881 opt_prop_gas_agenda, ppath_step_agenda,
00882 p_grid, z_field, r_geoid, z_surface,
00883 t_field, f_grid, f_index, ext_mat_field,
00884 abs_vec_field,
00885 surface_prop_agenda, doit_za_interp);
00886 }
00887 }
00888
00889
00890
00891
00892
00893
00894
00895
00896 else if ( scat_za_grid[scat_za_index_local] > 90. &&
00897 scat_za_grid[scat_za_index_local] < theta_lim )
00898 {
00899 for(Index p_index = cloudbox_limits[0]; p_index
00900 <= cloudbox_limits[1]; p_index ++)
00901 {
00902
00903
00904
00905
00906 if (!(p_index == 0 && scat_za_grid[scat_za_index_local] > 90.))
00907 {
00908 cloud_ppath_update1D(ws, doit_i_field,
00909 p_index, scat_za_index_local,
00910 scat_za_grid,
00911 cloudbox_limits, doit_scat_field,
00912 abs_scalar_gas_agenda, vmr_field,
00913 opt_prop_gas_agenda, ppath_step_agenda,
00914 p_grid, z_field, r_geoid, z_surface,
00915 t_field, f_grid, f_index, ext_mat_field,
00916 abs_vec_field,
00917 surface_prop_agenda, doit_za_interp);
00918 }
00919 }
00920 }
00921 }
00922 }
00923
00924
00925
00926 void
00927 doit_i_fieldUpdateSeq3D(Workspace& ws,
00928
00929 Tensor6& doit_i_field,
00930
00931 const Tensor6& doit_scat_field,
00932 const ArrayOfIndex& cloudbox_limits,
00933
00934 const Agenda& abs_scalar_gas_agenda,
00935 const Tensor4& vmr_field,
00936
00937 const Agenda& spt_calc_agenda,
00938 const Vector& scat_za_grid,
00939 const Vector& scat_aa_grid,
00940 const Tensor4& pnd_field,
00941
00942 const Agenda& opt_prop_part_agenda,
00943 const Agenda& opt_prop_gas_agenda,
00944
00945 const Agenda& ppath_step_agenda,
00946 const Vector& p_grid,
00947 const Vector& lat_grid,
00948 const Vector& lon_grid,
00949 const Tensor3& z_field,
00950 const Matrix& r_geoid,
00951 const Matrix& z_surface,
00952
00953 const Tensor3& t_field,
00954 const Vector& f_grid,
00955 const Index& f_index,
00956 const Index& doit_za_interp
00957 )
00958 {
00959 out2<<" doit_i_fieldUpdateSeq3D: Radiative transfer calculatiuon in cloudbox.\n";
00960 out2 << " ------------------------------------------------------------- \n";
00961
00962
00963
00964
00965 chk_not_empty( "abs_scalar_gas_agenda", abs_scalar_gas_agenda);
00966 chk_not_empty( "spt_calc_agenda", spt_calc_agenda);
00967 chk_not_empty( "opt_prop_part_agenda", opt_prop_part_agenda);
00968 chk_not_empty( "opt_prop_gas_agenda", opt_prop_gas_agenda);
00969 chk_not_empty( "ppath_step_agenda", ppath_step_agenda);
00970
00971 if (cloudbox_limits.nelem() != 6)
00972 throw runtime_error(
00973 "The cloudbox dimension is not 3D! \n"
00974 "Do you really want to do a 3D calculation? \n"
00975 "For 1D use *doit_i_fieldUpdateSeq1D*.\n"
00976 );
00977
00978
00979 const Index N_scat_za = scat_za_grid.nelem();
00980
00981 if (scat_za_grid[0] != 0. || scat_za_grid[N_scat_za-1] != 180.)
00982 throw runtime_error("The range of *scat_za_grid* must [0 180].");
00983
00984
00985 const Index N_scat_aa = scat_aa_grid.nelem();
00986
00987 if (scat_aa_grid[0] != 0. || scat_aa_grid[N_scat_aa-1] != 360.)
00988 throw runtime_error("The range of *scat_za_grid* must [0 360].");
00989
00990
00991 chk_atm_grids(3, p_grid, lat_grid, lon_grid);
00992
00993
00994 chk_size("z_field", z_field, p_grid.nelem(), lat_grid.nelem(),
00995 lon_grid.nelem());
00996 chk_size("t_field", t_field, p_grid.nelem(), lat_grid.nelem(),
00997 lon_grid.nelem());
00998
00999 chk_atm_surface( "r_geoid", r_geoid, 3, lat_grid,
01000 lon_grid);
01001
01002
01003
01004 if( f_grid.nelem() == 0 )
01005 throw runtime_error( "The frequency grid is empty." );
01006 chk_if_increasing( "f_grid", f_grid );
01007
01008
01009 if ( f_index >= f_grid.nelem() )
01010 throw runtime_error("*f_index* is greater than number of elements in the\n"
01011 "frequency grid.\n");
01012
01013 if( !(doit_za_interp == 0 || doit_za_interp == 1 ) )
01014 throw runtime_error( "Interpolation method is not defined. Use \n"
01015 "*doit_za_interpSet*.\n");
01016
01017 const Index stokes_dim = doit_scat_field.ncols();
01018 assert(stokes_dim > 0 || stokes_dim < 5);
01019
01020
01021 assert( is_size( doit_i_field,
01022 (cloudbox_limits[1] - cloudbox_limits[0]) + 1,
01023 (cloudbox_limits[3] - cloudbox_limits[2]) + 1,
01024 (cloudbox_limits[5] - cloudbox_limits[4]) + 1,
01025 N_scat_za,
01026 N_scat_aa,
01027 stokes_dim));
01028
01029 assert( is_size( doit_scat_field,
01030 (cloudbox_limits[1] - cloudbox_limits[0]) + 1,
01031 (cloudbox_limits[3] - cloudbox_limits[2]) + 1,
01032 (cloudbox_limits[5] - cloudbox_limits[4]) + 1,
01033 N_scat_za,
01034 N_scat_aa,
01035 stokes_dim));
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045 out3 << "Calculate single particle properties \n";
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 const Index p_low = cloudbox_limits[0];
01056 const Index p_up = cloudbox_limits[1];
01057 const Index lat_low = cloudbox_limits[2];
01058 const Index lat_up = cloudbox_limits[3];
01059 const Index lon_low = cloudbox_limits[4];
01060 const Index lon_up = cloudbox_limits[5];
01061
01062
01063
01064 Tensor5 ext_mat_field(p_up-p_low+1, lat_up-lat_low+1, lon_up-lon_low+1,
01065 stokes_dim, stokes_dim, 0.);
01066 Tensor4 abs_vec_field(p_up-p_low+1, lat_up-lat_low+1, lon_up-lon_low+1,
01067 stokes_dim, 0.);
01068
01069
01070
01071 for(Index scat_za_index = 0; scat_za_index < N_scat_za; scat_za_index ++)
01072 {
01073
01074
01075 for(Index scat_aa_index = 1; scat_aa_index < N_scat_aa; scat_aa_index ++)
01076 {
01077
01078
01079
01080
01081
01082
01083
01084 cloud_fieldsCalc(ws, ext_mat_field, abs_vec_field,
01085 spt_calc_agenda,
01086 opt_prop_part_agenda, scat_za_index,
01087 scat_aa_index, cloudbox_limits, t_field,
01088 pnd_field);
01089
01090
01091 Vector stokes_vec(stokes_dim,0.);
01092
01093 Numeric theta_lim = 180. - asin((r_geoid(0,0)+z_field(p_low,0,0))
01094 /(r_geoid(0,0)+z_field(p_up,0,0)))
01095 *RAD2DEG;
01096
01097
01098 if ( scat_za_grid[scat_za_index] <= 90.)
01099 {
01100
01101
01102
01103
01104
01105 for(Index p_index = p_up-1; p_index >= p_low; p_index --)
01106 {
01107 for(Index lat_index = lat_low; lat_index <= lat_up;
01108 lat_index ++)
01109 {
01110 for(Index lon_index = lon_low; lon_index <= lon_up;
01111 lon_index ++)
01112 {
01113 cloud_ppath_update3D(ws, doit_i_field,
01114 p_index, lat_index,
01115 lon_index, scat_za_index,
01116 scat_aa_index, scat_za_grid,
01117 scat_aa_grid, cloudbox_limits,
01118 doit_scat_field,
01119 abs_scalar_gas_agenda,
01120 vmr_field,
01121 opt_prop_gas_agenda,
01122 ppath_step_agenda, p_grid,
01123 lat_grid, lon_grid, z_field,
01124 r_geoid, z_surface, t_field,
01125 f_grid, f_index,
01126 ext_mat_field, abs_vec_field,
01127 doit_za_interp);
01128 }
01129 }
01130 }
01131 }
01132 else if ( scat_za_grid[scat_za_index] > theta_lim)
01133 {
01134
01135
01136
01137 for(Index p_index = p_low+1; p_index <= p_up; p_index ++)
01138 {
01139 for(Index lat_index = lat_low; lat_index <= lat_up;
01140 lat_index ++)
01141 {
01142 for(Index lon_index = lon_low; lon_index <= lon_up;
01143 lon_index ++)
01144 {
01145 cloud_ppath_update3D(ws, doit_i_field,
01146 p_index, lat_index,
01147 lon_index, scat_za_index,
01148 scat_aa_index, scat_za_grid,
01149 scat_aa_grid, cloudbox_limits,
01150 doit_scat_field,
01151 abs_scalar_gas_agenda,
01152 vmr_field,
01153 opt_prop_gas_agenda,
01154 ppath_step_agenda, p_grid,
01155 lat_grid, lon_grid, z_field,
01156 r_geoid, z_surface, t_field,
01157 f_grid, f_index,
01158 ext_mat_field, abs_vec_field,
01159 doit_za_interp);
01160 }
01161 }
01162 }
01163 }
01164
01165
01166
01167
01168
01169
01170
01171
01172 else if ( scat_za_grid[scat_za_index] > 90. &&
01173 scat_za_grid[scat_za_index] < theta_lim )
01174 {
01175 for(Index p_index = p_low; p_index <= p_up; p_index ++)
01176 {
01177
01178
01179
01180
01181 if (!(p_index == 0 && scat_za_grid[scat_za_index] > 90.))
01182 {
01183 for(Index lat_index = lat_low; lat_index <= lat_up;
01184 lat_index ++)
01185 {
01186 for(Index lon_index = lon_low; lon_index <= lon_up;
01187 lon_index ++)
01188 {
01189 cloud_ppath_update3D(ws, doit_i_field,
01190 p_index,
01191 lat_index,
01192 lon_index, scat_za_index,
01193 scat_aa_index,
01194 scat_za_grid,
01195 scat_aa_grid,
01196 cloudbox_limits,
01197 doit_scat_field,
01198 abs_scalar_gas_agenda,
01199 vmr_field,
01200 opt_prop_gas_agenda,
01201 ppath_step_agenda, p_grid,
01202 lat_grid, lon_grid,
01203 z_field,
01204 r_geoid, z_surface,
01205 t_field, f_grid,
01206 f_index,
01207 ext_mat_field,
01208 abs_vec_field,
01209 doit_za_interp);
01210 }
01211 }
01212 }
01213 }
01214 }
01215 }
01216 }
01217
01218 doit_i_field(joker, joker, joker, joker, 0, joker) =
01219 doit_i_field(joker, joker, joker, joker, N_scat_aa-1, joker);
01220
01221 }
01222
01223
01224
01225 void
01226 doit_i_fieldUpdateSeq1DPP(
01227 Workspace& ws,
01228
01229 Tensor6& doit_i_field,
01230
01231 Index& scat_za_index ,
01232
01233 const Tensor6& doit_scat_field,
01234 const ArrayOfIndex& cloudbox_limits,
01235
01236 const Agenda& abs_scalar_gas_agenda,
01237 const Tensor4& vmr_field,
01238
01239 const Agenda& spt_calc_agenda,
01240 const Vector& scat_za_grid,
01241 const Tensor4& pnd_field,
01242
01243 const Agenda& opt_prop_part_agenda,
01244 const Agenda& opt_prop_gas_agenda,
01245
01246 const Agenda& ppath_step_agenda,
01247 const Vector& p_grid,
01248 const Tensor3& z_field,
01249 const Matrix& r_geoid,
01250
01251 const Tensor3& t_field,
01252 const Vector& f_grid,
01253 const Index& f_index
01254 )
01255 {
01256
01257 out2 << " doit_i_fieldUpdateSeq1DPP: Radiative transfer calculation in cloudbox.\n";
01258 out2 << " --------------------------------------------------------------------- \n";
01259
01260 const Index stokes_dim = doit_scat_field.ncols();
01261
01262
01263
01264
01265 if (stokes_dim < 0 || stokes_dim > 4)
01266 throw runtime_error(
01267 "The dimension of stokes vector must be"
01268 "1,2,3, or 4");
01269
01270 assert( is_size( doit_i_field,
01271 (cloudbox_limits[1] - cloudbox_limits[0]) + 1,
01272 1,
01273 1,
01274 scat_za_grid.nelem(),
01275 1,
01276 stokes_dim));
01277
01278 assert( is_size( doit_scat_field,
01279 (cloudbox_limits[1] - cloudbox_limits[0]) + 1,
01280 1,
01281 1,
01282 scat_za_grid.nelem(),
01283 1,
01284 stokes_dim));
01285
01286
01287 assert( f_index <= f_grid.nelem() );
01288
01289
01290
01291
01292
01293
01294 const Index N_scat_za = scat_za_grid.nelem();
01295
01296
01297
01298
01299
01300
01301 out3 << "Calculate single particle properties \n";
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312 Tensor5 ext_mat_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
01313 stokes_dim, stokes_dim, 0.);
01314 Tensor4 abs_vec_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
01315 stokes_dim, 0.);
01316
01317
01318 for(scat_za_index = 0; scat_za_index < N_scat_za; scat_za_index ++)
01319 {
01320
01321
01322 Index scat_aa_index = 0;
01323
01324 cloud_fieldsCalc(ws, ext_mat_field, abs_vec_field,
01325 spt_calc_agenda,
01326 opt_prop_part_agenda, scat_za_index, scat_aa_index,
01327 cloudbox_limits, t_field,
01328 pnd_field);
01329
01330
01331
01332
01333
01334 Vector stokes_vec(stokes_dim,0.);
01335
01336 if ( scat_za_grid[scat_za_index] <= 90)
01337 {
01338
01339
01340
01341
01342
01343
01344
01345
01346 for(Index p_index = cloudbox_limits[1] -1; p_index
01347 >= cloudbox_limits[0]; p_index --)
01348 {
01349 cloud_ppath_update1D_planeparallel(ws, doit_i_field,
01350 p_index, scat_za_index,
01351 scat_za_grid,
01352 cloudbox_limits,
01353 doit_scat_field,
01354 abs_scalar_gas_agenda,
01355 vmr_field,
01356 opt_prop_gas_agenda,
01357 ppath_step_agenda,
01358 p_grid, z_field, r_geoid,
01359 t_field,
01360 f_grid, f_index,
01361 ext_mat_field,
01362 abs_vec_field);
01363 }
01364 }
01365 else if ( scat_za_grid[scat_za_index] > 90)
01366 {
01367
01368
01369
01370 for(Index p_index = cloudbox_limits[0]+1; p_index
01371 <= cloudbox_limits[1]; p_index ++)
01372 {
01373 cloud_ppath_update1D_planeparallel(ws, doit_i_field,
01374 p_index, scat_za_index,
01375 scat_za_grid,
01376 cloudbox_limits,
01377 doit_scat_field,
01378 abs_scalar_gas_agenda,
01379 vmr_field,
01380 opt_prop_gas_agenda,
01381 ppath_step_agenda,
01382 p_grid, z_field, r_geoid,
01383 t_field,
01384 f_grid, f_index,
01385 ext_mat_field,
01386 abs_vec_field);
01387 }
01388 }
01389
01390 }
01391 }
01392
01393
01394
01395 void DoitInit(
01396
01397 Index& scat_p_index,
01398 Index& scat_lat_index,
01399 Index& scat_lon_index,
01400 Index& scat_za_index,
01401 Index& scat_aa_index,
01402 Tensor6& doit_scat_field,
01403 Tensor6& doit_i_field,
01404 Index& doit_za_interp,
01405 Index& doit_is_initialized,
01406
01407 const Index& stokes_dim,
01408 const Index& atmosphere_dim,
01409 const Vector& scat_za_grid,
01410 const Vector& scat_aa_grid,
01411 const Index& doit_za_grid_size,
01412 const ArrayOfIndex& cloudbox_limits,
01413 const ArrayOfSingleScatteringData& scat_data_raw
01414 )
01415 {
01416
01417
01418 if (stokes_dim < 0 || stokes_dim > 4)
01419 throw runtime_error(
01420 "The dimension of stokes vector must be"
01421 "1,2,3, or 4");
01422
01423 chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
01424
01425
01426 const Index N_scat_za = scat_za_grid.nelem();
01427
01428 if (scat_za_grid[0] != 0. || scat_za_grid[N_scat_za-1] != 180.)
01429 throw runtime_error("The range of *scat_za_grid* must [0 180].");
01430
01431
01432 const Index N_scat_aa = scat_aa_grid.nelem();
01433
01434 if (scat_aa_grid[0] != 0. || scat_aa_grid[N_scat_aa-1] != 360.)
01435 throw runtime_error("The range of *scat_za_grid* must [0 360].");
01436
01437 if (doit_za_grid_size < 16)
01438 throw runtime_error(
01439 "*doit_za_grid_size* must be greater than 15 for accurate results");
01440 else if (doit_za_grid_size > 100)
01441 out1 << "Warning: doit_za_grid_size is very large which means that the \n"
01442 << "calculation will be very slow. The recommended value is 19.\n";
01443
01444 if ( cloudbox_limits.nelem()!= 2*atmosphere_dim)
01445 throw runtime_error(
01446 "*cloudbox_limits* is a vector which contains the"
01447 "upper and lower limit of the cloud for all "
01448 "atmospheric dimensions. So its dimension must"
01449 "be 2 x *atmosphere_dim*");
01450
01451 if (scat_data_raw.nelem() == 0)
01452 throw runtime_error(
01453 "No scattering data files have been added.\n"
01454 "Please use the WSM *ParticleTypeAdd* or \n"
01455 "*ParticleTypeAddAll* to define the cloud \n"
01456 "properties for the scattering calculation.\n"
01457 );
01458
01459
01460
01461
01462
01463
01464 scat_p_index = 0;
01465 scat_lat_index = 0;
01466 scat_lon_index = 0;
01467 scat_za_index = 0;
01468 scat_aa_index = 0;
01469
01470
01471
01472 if (atmosphere_dim == 1)
01473 {
01474 doit_i_field.resize((cloudbox_limits[1] - cloudbox_limits[0]) +1,
01475 1,
01476 1,
01477 scat_za_grid.nelem(),
01478 1,
01479 stokes_dim);
01480
01481 doit_scat_field.resize((cloudbox_limits[1] - cloudbox_limits[0]) +1,
01482 1,
01483 1,
01484 scat_za_grid.nelem(),
01485 1,
01486 stokes_dim);
01487 }
01488 else if (atmosphere_dim == 3)
01489 {
01490 doit_i_field.resize((cloudbox_limits[1] - cloudbox_limits[0]) +1,
01491 (cloudbox_limits[3] - cloudbox_limits[2]) +1,
01492 (cloudbox_limits[5] - cloudbox_limits[4]) +1,
01493 scat_za_grid.nelem(),
01494 scat_aa_grid.nelem(),
01495 stokes_dim);
01496
01497 doit_scat_field.resize((cloudbox_limits[1] - cloudbox_limits[0]) +1,
01498 (cloudbox_limits[3] - cloudbox_limits[2]) +1,
01499 (cloudbox_limits[5] - cloudbox_limits[4]) +1,
01500 scat_za_grid.nelem(),
01501 scat_aa_grid.nelem(),
01502 stokes_dim);
01503 }
01504 else
01505 {
01506 throw runtime_error(
01507 "Scattering calculations are not possible for a 2D"
01508 "atmosphere. If you want to do scattering calculations"
01509 "*atmosphere_dim* has to be either 1 or 3"
01510 );
01511 }
01512
01513 doit_i_field = 0.;
01514 doit_scat_field = 0.;
01515
01516
01517
01518
01519 if (doit_za_interp != 1)
01520 doit_za_interp = 0;
01521
01522 doit_is_initialized = 1;
01523 }
01524
01525
01526
01527 void DoitWriteIterationFields(
01528 const Index& doit_iteration_counter,
01529 const Tensor6& doit_i_field,
01530
01531 const ArrayOfIndex& iterations)
01532 {
01533
01534
01535
01536
01537
01538
01539 ostringstream os;
01540 os << doit_iteration_counter;
01541
01542
01543 if( iterations[0] == 0 )
01544 {
01545 xml_write_to_file("doit_iteration_" + os.str() + ".xml",
01546 doit_i_field);
01547 }
01548
01549
01550 else
01551 {
01552 for (Index i = 0; i<iterations.nelem(); i++)
01553 {
01554 if (doit_iteration_counter == iterations[i])
01555 xml_write_to_file("doit_iteration_" + os.str() + ".xml",
01556 doit_i_field);
01557 }
01558 }
01559 }
01560
01561
01562
01563 void
01564 doit_scat_fieldCalc(Workspace& ws,
01565
01566 Tensor6& doit_scat_field,
01567
01568 const Agenda& pha_mat_spt_agenda,
01569 const Tensor6& doit_i_field,
01570 const Tensor4& pnd_field,
01571 const Tensor3& t_field,
01572 const Index& atmosphere_dim,
01573 const ArrayOfIndex& cloudbox_limits,
01574 const Vector& scat_za_grid,
01575 const Vector& scat_aa_grid,
01576 const Index& doit_za_grid_size
01577 )
01578
01579 {
01580
01581
01582
01583 chk_not_empty( "pha_mat_spt_agenda", pha_mat_spt_agenda);
01584
01585
01586 const Index Nza = scat_za_grid.nelem();
01587
01588 if (scat_za_grid[0] != 0. || scat_za_grid[Nza-1] != 180.)
01589 throw runtime_error("The range of *scat_za_grid* must [0 180].");
01590
01591
01592 const Index Naa = scat_aa_grid.nelem();
01593
01594 if (scat_aa_grid[0] != 0. || scat_aa_grid[Naa-1] != 360.)
01595 throw runtime_error("The range of *scat_za_grid* must [0 360].");
01596
01597
01598 const Index stokes_dim = doit_scat_field.ncols();
01599 assert(stokes_dim > 0 || stokes_dim < 5);
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609 if (atmosphere_dim == 1)
01610 {
01611 assert( is_size(doit_i_field,
01612 (cloudbox_limits[1] - cloudbox_limits[0]) +1,
01613 1, 1, Nza, 1, stokes_dim));
01614 assert( is_size(doit_scat_field,
01615 (cloudbox_limits[1] - cloudbox_limits[0]) +1,
01616 1, 1, scat_za_grid.nelem(), 1, stokes_dim));
01617 }
01618 else if (atmosphere_dim == 3)
01619 {
01620 assert ( is_size( doit_i_field,
01621 (cloudbox_limits[1] - cloudbox_limits[0]) +1,
01622 (cloudbox_limits[3] - cloudbox_limits[2]) +1,
01623 (cloudbox_limits[5] - cloudbox_limits[4]) +1,
01624 Nza, Naa, stokes_dim));
01625 assert ( is_size( doit_scat_field,
01626 (cloudbox_limits[1] - cloudbox_limits[0]) +1,
01627 (cloudbox_limits[3] - cloudbox_limits[2]) +1,
01628 (cloudbox_limits[5] - cloudbox_limits[4]) +1,
01629 Nza, Naa, stokes_dim));
01630 }
01631 else
01632 {
01633 ostringstream os;
01634 os << "The atmospheric dimension must be 1D or 3D \n"
01635 << "for scattering calculations using the DOIT\n"
01636 << "module, but it is not. The value of *atmosphere_dim*\n"
01637 << "is " << atmosphere_dim << ".";
01638 throw runtime_error( os.str() );
01639 }
01640
01641 if ( cloudbox_limits.nelem()!= 2*atmosphere_dim)
01642 throw runtime_error(
01643 "*cloudbox_limits* is a vector which contains the"
01644 "upper and lower limit of the cloud for all "
01645 "atmospheric dimensions. So its dimension must"
01646 "be 2 x *atmosphere_dim*");
01647
01648
01649
01650 if (doit_za_grid_size != Nza)
01651 throw runtime_error(
01652 "The zenith angle grids for the computation of\n"
01653 "the scattering integral and the RT part must \n"
01654 "be equal. Check definitions in \n"
01655 "*DoitAngularGridsSet*. The keyword \n"
01656 "'za_grid_opt_file' should be empty. \n"
01657 );
01658
01659
01660
01661
01662 Tensor4 pha_mat_local(doit_za_grid_size, scat_aa_grid.nelem(),
01663 stokes_dim, stokes_dim, 0.);
01664
01665 Tensor5 pha_mat_spt_local(pnd_field.nbooks(), doit_za_grid_size,
01666 scat_aa_grid.nelem(), stokes_dim, stokes_dim, 0.);
01667
01668
01669 Vector grid_stepsize(2);
01670 grid_stepsize[0] = 180./(Numeric)(doit_za_grid_size - 1);
01671 grid_stepsize[1] = 360./(Numeric)(Naa - 1);
01672
01673 Tensor3 product_field(Nza, Naa, stokes_dim, 0);
01674
01675 out2 << " Calculate the scattered field\n";
01676
01677 if ( atmosphere_dim == 1 )
01678 {
01679 Index scat_aa_index_local = 0;
01680
01681
01682
01683 for (Index p_index = 0; p_index<=cloudbox_limits[1]-cloudbox_limits[0] ;
01684 p_index++)
01685 {
01686 Numeric rte_temperature_local =
01687 t_field(p_index + cloudbox_limits[0], 0, 0);
01688
01689 for (Index scat_za_index_local = 0;
01690 scat_za_index_local < Nza; scat_za_index_local ++)
01691 {
01692
01693 Index index_zero = 0;
01694
01695
01696 out3 << "Calculate the phase matrix \n";
01697 pha_mat_spt_agendaExecute(ws, pha_mat_spt_local,
01698 scat_za_index_local,
01699 index_zero,
01700 index_zero,
01701 p_index,
01702 scat_aa_index_local,
01703 rte_temperature_local,
01704 pha_mat_spt_agenda);
01705
01706
01707 pha_matCalc(pha_mat_local, pha_mat_spt_local, pnd_field,
01708 atmosphere_dim, p_index, 0,
01709 0);
01710
01711 out3 << "Multiplication of phase matrix with incoming" <<
01712 " intensities \n";
01713
01714 product_field = 0;
01715
01716
01717
01718 for (Index za_in = 0; za_in < Nza; ++ za_in)
01719 {
01720 for (Index aa_in = 0; aa_in < Naa; ++ aa_in)
01721 {
01722
01723
01724
01725 for ( Index i = 0; i < stokes_dim; i++)
01726 {
01727 for (Index j = 0; j< stokes_dim; j++)
01728 {
01729 product_field(za_in, aa_in, i) +=
01730 pha_mat_local(za_in, aa_in, i, j) *
01731 doit_i_field(p_index, 0, 0, za_in, 0, j);
01732 }
01733 }
01734
01735 }
01736 }
01737
01738
01739 for (Index i = 0; i < stokes_dim; i++)
01740 {
01741 doit_scat_field( p_index, 0, 0, scat_za_index_local, 0, i)
01742 = AngIntegrate_trapezoid_opti
01743 (product_field(joker, joker, i),
01744 scat_za_grid,
01745 scat_aa_grid,
01746 grid_stepsize);
01747
01748 }
01749 }
01750 }
01751 }
01752
01753
01754
01755 else if( atmosphere_dim == 3 )
01756 {
01757
01758
01759
01760
01761 for (Index p_index = 0; p_index <=
01762 cloudbox_limits[1] - cloudbox_limits[0];
01763 p_index++)
01764 {
01765 for (Index lat_index = 0; lat_index <=
01766 cloudbox_limits[3] - cloudbox_limits[2]; lat_index++)
01767 {
01768 for (Index lon_index = 0; lon_index <=
01769 cloudbox_limits[5]-cloudbox_limits[4]; lon_index++)
01770 {
01771 Numeric rte_temperature_local =
01772 t_field(p_index + cloudbox_limits[0],
01773 lat_index + cloudbox_limits[2],
01774 lon_index + cloudbox_limits[4]);
01775
01776 for (Index scat_aa_index_local = 1;
01777 scat_aa_index_local < Naa;
01778 scat_aa_index_local++)
01779 {
01780 for (Index scat_za_index_local = 0;
01781 scat_za_index_local < Nza;
01782 scat_za_index_local ++)
01783 {
01784 out3 << "Calculate phase matrix \n";
01785 pha_mat_spt_agendaExecute(ws, pha_mat_spt_local,
01786 scat_za_index_local,
01787 lat_index,
01788 lon_index,
01789 p_index,
01790 scat_aa_index_local,
01791 rte_temperature_local,
01792 pha_mat_spt_agenda);
01793
01794 pha_matCalc(pha_mat_local, pha_mat_spt_local,
01795 pnd_field,
01796 atmosphere_dim,
01797 p_index,
01798 lat_index,
01799 lon_index);
01800
01801 product_field = 0;
01802
01803
01804
01805 for (Index za_in = 0; za_in < Nza; ++ za_in)
01806 {
01807 for (Index aa_in = 0; aa_in < Naa; ++ aa_in)
01808 {
01809
01810
01811 for ( Index i = 0; i < stokes_dim; i++)
01812 {
01813 for (Index j = 0; j< stokes_dim; j++)
01814 {
01815 product_field(za_in, aa_in, i) +=
01816 pha_mat_local
01817 (za_in, aa_in, i, j) *
01818 doit_i_field(p_index, lat_index,
01819 lon_index,
01820 scat_za_index_local,
01821 scat_aa_index_local,
01822 j);
01823 }
01824 }
01825 }
01826 }
01827
01828
01829
01830
01831 for (Index i = 0; i < stokes_dim; i++)
01832 {
01833 doit_scat_field( p_index,
01834 lat_index,
01835 lon_index,
01836 scat_za_index_local,
01837 scat_aa_index_local,
01838 i) =
01839 AngIntegrate_trapezoid_opti(product_field
01840 ( joker,
01841 joker, i),
01842 scat_za_grid,
01843 scat_aa_grid,
01844 grid_stepsize);
01845 }
01846 }
01847 }
01848 }
01849 }
01850 }
01851
01852 doit_scat_field(joker, joker, joker, joker, 0, joker) =
01853 doit_scat_field(joker, joker, joker, joker, Naa-1, joker);
01854 }
01855 }
01856
01857
01858
01859 void
01860 doit_scat_fieldCalcLimb(Workspace& ws,
01861
01862 Tensor6& doit_scat_field,
01863
01864 const Agenda& pha_mat_spt_agenda,
01865 const Tensor6& doit_i_field,
01866 const Tensor4& pnd_field,
01867 const Tensor3& t_field,
01868 const Index& atmosphere_dim,
01869 const ArrayOfIndex& cloudbox_limits,
01870 const Vector& scat_za_grid,
01871 const Vector& scat_aa_grid,
01872 const Index& doit_za_grid_size,
01873 const Index& doit_za_interp
01874 )
01875 {
01876
01877
01878
01879 chk_not_empty( "pha_mat_spt_agenda", pha_mat_spt_agenda);
01880
01881
01882 const Index Nza = scat_za_grid.nelem();
01883
01884 if (scat_za_grid[0] != 0. || scat_za_grid[Nza-1] != 180.)
01885 throw runtime_error("The range of *scat_za_grid* must [0 180].");
01886
01887
01888 const Index Naa = scat_aa_grid.nelem();
01889
01890 if (scat_aa_grid[0] != 0. || scat_aa_grid[Naa-1] != 360.)
01891 throw runtime_error("The range of *scat_za_grid* must [0 360].");
01892
01893
01894 const Index stokes_dim = doit_scat_field.ncols();
01895 assert(stokes_dim > 0 || stokes_dim < 5);
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905 if (atmosphere_dim == 1)
01906 {
01907 assert( is_size(doit_i_field,
01908 (cloudbox_limits[1] - cloudbox_limits[0]) +1,
01909 1, 1, Nza, 1, stokes_dim));
01910 assert( is_size(doit_scat_field,
01911 (cloudbox_limits[1] - cloudbox_limits[0]) +1,
01912 1, 1, scat_za_grid.nelem(), 1, stokes_dim));
01913 }
01914 else if (atmosphere_dim == 3)
01915 {
01916 assert ( is_size( doit_i_field,
01917 (cloudbox_limits[1] - cloudbox_limits[0]) +1,
01918 (cloudbox_limits[3] - cloudbox_limits[2]) +1,
01919 (cloudbox_limits[5] - cloudbox_limits[4]) +1,
01920 Nza, Naa, stokes_dim));
01921 assert ( is_size( doit_scat_field,
01922 (cloudbox_limits[1] - cloudbox_limits[0]) +1,
01923 (cloudbox_limits[3] - cloudbox_limits[2]) +1,
01924 (cloudbox_limits[5] - cloudbox_limits[4]) +1,
01925 Nza, Naa, stokes_dim));
01926 }
01927 else
01928 {
01929 ostringstream os;
01930 os << "The atmospheric dimension must be 1D or 3D \n"
01931 << "for scattering calculations using the DOIT\n"
01932 << "module, but it is not. The value of *atmosphere_dim*\n"
01933 << "is " << atmosphere_dim << ".";
01934 throw runtime_error( os.str() );
01935 }
01936
01937 if( !(doit_za_interp == 0 || doit_za_interp == 1 ) )
01938 throw runtime_error( "Interpolation method is not defined. Use \n"
01939 "*doit_za_interpSet*.\n");
01940
01941 if ( cloudbox_limits.nelem()!= 2*atmosphere_dim)
01942 throw runtime_error(
01943 "*cloudbox_limits* is a vector which contains the"
01944 "upper and lower limit of the cloud for all "
01945 "atmospheric dimensions. So its dimension must"
01946 "be 2 x *atmosphere_dim*");
01947
01948 if (doit_za_grid_size < 16)
01949 throw runtime_error(
01950 "*doit_za_grid_size* must be greater than 15 for"
01951 "accurate results");
01952 else if (doit_za_grid_size > 100)
01953 out1 << "Warning: doit_za_grid_size is very large which means that the \n"
01954 << "calculation will be very slow. The recommended value is 19.\n";
01955
01956
01957
01958
01959 Tensor4 pha_mat_local(doit_za_grid_size, scat_aa_grid.nelem(),
01960 stokes_dim, stokes_dim, 0.);
01961
01962 Tensor5 pha_mat_spt_local(pnd_field.nbooks(), doit_za_grid_size,
01963 scat_aa_grid.nelem(), stokes_dim, stokes_dim, 0.);
01964
01965
01966
01967 Vector za_grid;
01968 nlinspace(za_grid, 0, 180, doit_za_grid_size);
01969
01970
01971
01972 ArrayOfGridPos gp_za_i(doit_za_grid_size);
01973 gridpos(gp_za_i, scat_za_grid, za_grid);
01974
01975 Matrix itw_za_i(doit_za_grid_size, 2);
01976 interpweights(itw_za_i, gp_za_i);
01977
01978
01979 Matrix doit_i_field_int(doit_za_grid_size, stokes_dim, 0);
01980
01981
01982
01983 ArrayOfGridPos gp_za(Nza);
01984 gridpos(gp_za, za_grid, scat_za_grid);
01985
01986 Matrix itw_za(Nza, 2);
01987 interpweights(itw_za, gp_za);
01988
01989
01990 Matrix doit_scat_field_org(doit_za_grid_size, stokes_dim, 0);
01991
01992
01993
01994 Vector grid_stepsize(2);
01995 grid_stepsize[0] = 180./(Numeric)(doit_za_grid_size - 1);
01996 grid_stepsize[1] = 360./(Numeric)(Naa - 1);
01997
01998 Tensor3 product_field(doit_za_grid_size, Naa, stokes_dim, 0);
01999
02000 if ( atmosphere_dim == 1 )
02001 {
02002 Index scat_aa_index_local = 0;
02003
02004
02005
02006 for (Index p_index = 0;
02007 p_index <= cloudbox_limits[1]-cloudbox_limits[0];
02008 p_index++)
02009 {
02010 Numeric rte_temperature_local =
02011 t_field(p_index + cloudbox_limits[0], 0, 0);
02012
02013 for (Index i = 0; i < stokes_dim; i++)
02014 {
02015 if (doit_za_interp == 0)
02016 {
02017 interp(doit_i_field_int(joker, i), itw_za_i,
02018 doit_i_field(p_index, 0, 0, joker, 0, i), gp_za_i);
02019 }
02020 else if (doit_za_interp == 1)
02021 {
02022
02023 for(Index za = 0; za < za_grid.nelem(); za++)
02024 {
02025 doit_i_field_int(za, i) =
02026 interp_poly(scat_za_grid,
02027 doit_i_field(p_index, 0, 0, joker, 0, i),
02028 za_grid[za],
02029 gp_za_i[za]);
02030 }
02031 }
02032
02033 else assert(false);
02034 }
02035
02036
02037 for( Index scat_za_index_local = 0;
02038 scat_za_index_local < doit_za_grid_size;
02039 scat_za_index_local++)
02040 {
02041
02042 Index index_zero = 0;
02043
02044
02045 out3 << "Calculate the phase matrix \n";
02046 pha_mat_spt_agendaExecute(ws, pha_mat_spt_local,
02047 scat_za_index_local,
02048 index_zero,
02049 index_zero,
02050 p_index,
02051 scat_aa_index_local,
02052 rte_temperature_local,
02053 pha_mat_spt_agenda);
02054
02055
02056 pha_matCalc(pha_mat_local, pha_mat_spt_local, pnd_field,
02057 atmosphere_dim, p_index, 0,
02058 0);
02059
02060 out3 << "Multiplication of phase matrix with incoming" <<
02061 " intensities \n";
02062
02063 product_field = 0;
02064
02065
02066
02067 for( Index za_in = 0; za_in < doit_za_grid_size; za_in ++)
02068 {
02069 for (Index aa_in = 0; aa_in < Naa; ++ aa_in)
02070 {
02071
02072
02073
02074 for ( Index i = 0; i < stokes_dim; i++)
02075 {
02076 for (Index j = 0; j< stokes_dim; j++)
02077 {
02078 product_field(za_in, aa_in, i) +=
02079 pha_mat_local(za_in, aa_in, i, j) *
02080 doit_i_field_int(za_in, j);
02081 }
02082 }
02083
02084 }
02085 }
02086
02087 out3 << "Compute integral. \n";
02088 for (Index i = 0; i < stokes_dim; i++)
02089 {
02090 doit_scat_field_org(scat_za_index_local, i)=
02091 AngIntegrate_trapezoid_opti(product_field(joker, joker, i),
02092 za_grid,
02093 scat_aa_grid,
02094 grid_stepsize);
02095 }
02096 }
02097
02098
02099
02100 for (Index i = 0; i < stokes_dim; i++)
02101 {
02102 if(doit_za_interp == 0)
02103 {
02104 interp(doit_scat_field(p_index,
02105 0,
02106 0,
02107 joker,
02108 0,
02109 i),
02110 itw_za,
02111 doit_scat_field_org(joker, i),
02112 gp_za);
02113 }
02114 else
02115 {
02116 for(Index za = 0; za < scat_za_grid.nelem(); za++)
02117 {
02118 doit_scat_field(p_index, 0, 0, za, 0, i) =
02119 interp_poly(za_grid,
02120 doit_scat_field_org(joker, i),
02121 scat_za_grid[za],
02122 gp_za[za]);
02123 }
02124 }
02125 }
02126 }
02127
02128 }
02129
02130
02131 else if( atmosphere_dim == 3 ){
02132
02133 for (Index p_index = 0; p_index <= cloudbox_limits[1] - cloudbox_limits[0];
02134 p_index ++)
02135 {
02136 for (Index lat_index = 0; lat_index <=
02137 cloudbox_limits[3] - cloudbox_limits[2]; lat_index++)
02138 {
02139 for (Index lon_index = 0; lon_index <=
02140 cloudbox_limits[5] - cloudbox_limits[4]; lon_index++)
02141 {
02142
02143 Numeric rte_temperature_local =
02144 t_field(p_index + cloudbox_limits[0],
02145 lat_index + cloudbox_limits[2],
02146 lon_index + cloudbox_limits[4]);
02147
02148
02149 for (Index scat_aa_index_local = 1;
02150 scat_aa_index_local < Naa;
02151 scat_aa_index_local++)
02152 {
02153
02154 for (Index i = 0; i < stokes_dim; i++)
02155 {
02156 interp(doit_i_field_int(joker, i), itw_za_i,
02157 doit_i_field(p_index, lat_index, lon_index,
02158 joker, scat_aa_index_local, i), gp_za_i);
02159 }
02160
02161 for (Index scat_za_index_local = 0;
02162 scat_za_index_local < doit_za_grid_size;
02163 scat_za_index_local++)
02164 {
02165
02166 out3 << "Calculate phase matrix \n";
02167 pha_mat_spt_agendaExecute(ws, pha_mat_spt_local,
02168 scat_za_index_local,
02169 lat_index,
02170 lon_index,
02171 p_index,
02172 scat_aa_index_local,
02173 rte_temperature_local,
02174 pha_mat_spt_agenda);
02175
02176 pha_matCalc(pha_mat_local, pha_mat_spt_local,
02177 pnd_field,
02178 atmosphere_dim,
02179 p_index,
02180 lat_index,
02181 lon_index);
02182
02183 product_field = 0;
02184
02185
02186
02187
02188 out3 << "Multiplication of phase matrix with" <<
02189 "incoming intensity \n";
02190
02191 for( Index za_in = 0; za_in < doit_za_grid_size; za_in ++)
02192 {
02193 for (Index aa_in = 0; aa_in < Naa; ++ aa_in)
02194 {
02195
02196
02197 for ( Index i = 0; i < stokes_dim; i++)
02198 {
02199 for (Index j = 0; j< stokes_dim; j++)
02200 {
02201 product_field(za_in, aa_in, i) +=
02202 pha_mat_local(za_in, aa_in, i, j) *
02203 doit_i_field_int(za_in, j);
02204 }
02205 }
02206 }
02207 }
02208
02209 out3 << "Compute the integral \n";
02210
02211 for (Index i = 0; i < stokes_dim; i++)
02212 {
02213 doit_scat_field_org(scat_za_index_local, i) =
02214 AngIntegrate_trapezoid_opti(product_field
02215 ( joker,
02216 joker, i),
02217 za_grid,
02218 scat_aa_grid,
02219 grid_stepsize
02220 );
02221 }
02222
02223 }
02224
02225 for (Index i = 0; i < stokes_dim; i++)
02226 {
02227 interp(doit_scat_field(p_index,
02228 lat_index,
02229 lon_index,
02230 joker,
02231 scat_aa_index_local,
02232 i),
02233 itw_za,
02234 doit_scat_field_org(joker, i),
02235 gp_za);
02236 }
02237 }
02238 }
02239 }
02240 }
02241 doit_scat_field(joker, joker, joker, joker, 0, joker) =
02242 doit_scat_field(joker, joker, joker, joker, Naa-1, joker);
02243 }
02244 out2 << " Finished scattered field.\n";
02245 }
02246
02247
02248
02249 void doit_za_grid_optCalc(
02250 Vector& doit_za_grid_opt,
02251
02252 const Tensor6& doit_i_field,
02253 const Vector& scat_za_grid,
02254 const Index& doit_za_interp,
02255
02256 const Numeric& acc
02257 )
02258 {
02259
02260
02261
02262
02263
02264 chk_size("doit_i_field", doit_i_field,
02265 doit_i_field.nvitrines() , 1, 1, scat_za_grid.nelem(), 1,
02266 doit_i_field.ncols());
02267
02268 if(doit_i_field.ncols()<1 || doit_i_field.ncols()>4)
02269 throw runtime_error("The last dimension of *doit_i_field* corresponds\n"
02270 "to the Stokes dimension, therefore the number of\n"
02271 "columns in *doit_i_field* must be a number between\n"
02272 "1 and 4, but it is not!");
02273
02274 if(scat_za_grid.nelem() < 500)
02275 throw runtime_error("The fine grid (*scat_za_grid*) has less than \n"
02276 "500 grid points which is not sufficient for \n"
02277 "grid_optimization");
02278
02279 if( !(doit_za_interp == 0 || doit_za_interp == 1 ) )
02280 throw runtime_error( "Interpolation method is not defined. Use \n"
02281 "*doit_za_interpSet*.\n");
02282
02283
02284
02285
02286 Matrix doit_i_field_opt_mat;
02287 doit_i_field_opt_mat = 0.;
02288
02289
02290 za_gridOpt(doit_za_grid_opt, doit_i_field_opt_mat,
02291 scat_za_grid, doit_i_field, acc,
02292 doit_za_interp);
02293 }
02294
02295
02296
02297 void doit_za_interpSet(
02298 Index& doit_za_interp,
02299 const Index& atmosphere_dim,
02300
02301 const String& method
02302
02303 )
02304 {
02305 chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
02306
02307 if (atmosphere_dim != 1 && method == "polynomial")
02308 throw runtime_error(
02309 "Polynomial interpolation is only implemented for\n"
02310 "1D DOIT calculations as \n"
02311 "in 3D there can be numerical problems.\n"
02312 "Please use 'linear' interpolation method."
02313 );
02314
02315 if(method == "linear")
02316 doit_za_interp = 0;
02317 else if (method == "polynomial")
02318 doit_za_interp = 1;
02319 else
02320 throw runtime_error("Possible interpolation methods are 'linear' "
02321 "and 'polynomial'.\n");
02322 }
02323
02324
02325
02326 void ScatteringDoit(Workspace& ws,
02327 Tensor6& doit_i_field,
02328 Tensor7& scat_i_p,
02329 Tensor7& scat_i_lat,
02330 Tensor7& scat_i_lon,
02331 Tensor4& doit_i_field1D_spectrum,
02332 const Vector& f_grid,
02333 const Agenda& doit_mono_agenda,
02334 const Index& doit_is_initialized
02335 )
02336
02337 {
02338
02339
02340 chk_not_empty( "doit_mono_agenda", doit_mono_agenda );
02341
02342
02343
02344 if( f_grid.nelem() == 0 )
02345 throw runtime_error( "The frequency grid is empty." );
02346 chk_if_increasing( "f_grid", f_grid );
02347
02348
02349 if (!doit_is_initialized)
02350 throw runtime_error(
02351 "Initialization method *DoitInit* has to be "
02352 "put before\n"
02353 "start of *ScatteringDoit*");
02354
02355
02356
02357
02358
02359
02360 Workspace l_ws (ws);
02361 Agenda l_doit_mono_agenda(doit_mono_agenda);
02362
02363
02364 const Index nf = f_grid.nelem();
02365
02366 #pragma omp parallel firstprivate(l_ws, l_doit_mono_agenda)
02367 #pragma omp for
02368 for (Index f_index = 0; f_index < nf; f_index ++)
02369 {
02370 out1 << "Frequency: " << f_grid[f_index]/1e9 <<" GHz \n" ;
02371 doit_mono_agendaExecute(l_ws, doit_i_field, scat_i_p, scat_i_lat,
02372 scat_i_lon, doit_i_field1D_spectrum,
02373 f_index, l_doit_mono_agenda);
02374 }
02375 }
02376