48 using std::runtime_error;
61 const Index& cloudbox_on,
62 const Index& atmfields_checked,
63 const Index& atmgeom_checked,
64 const Index& cloudbox_checked,
65 const Index& scat_data_checked,
68 const Index& atmosphere_dim,
69 const Index& stokes_dim,
70 const Index& nstreams,
72 const Index& add_straight_angles,
73 const Index& pnd_ncols) {
77 "Cloudbox is off, no scattering calculations to be" 81 if (atmfields_checked != 1)
83 "The atmospheric fields must be flagged to have" 84 " passed a consistency check (atmfields_checked=1).");
85 if (atmgeom_checked != 1)
87 "The atmospheric geometry must be flagged to have" 88 " passed a consistency check (atmgeom_checked=1).");
89 if (cloudbox_checked != 1)
91 "The cloudbox must be flagged to have" 92 " passed a consistency check (cloudbox_checked=1).");
93 if (scat_data_checked != 1)
95 "The scat_data must be flagged to have " 96 "passed a consistency check (scat_data_checked=1).");
98 if (atmosphere_dim != 1)
100 "For running RT4, atmospheric dimensionality" 103 if (stokes_dim < 0 || stokes_dim > 2)
105 "For running RT4, the dimension of stokes vector" 106 " must be 1 or 2.\n");
108 if (cloudbox_limits[0] != 0) {
110 os <<
"RT4 calculations currently only possible with" 111 <<
" lower cloudbox limit\n" 112 <<
"at 0th atmospheric level" 113 <<
" (assumes surface there, ignoring z_surface).\n";
114 throw runtime_error(os.
str());
117 if (cloudbox_limits.
nelem() != 2 * atmosphere_dim)
119 "*cloudbox_limits* is a vector which contains the" 120 " upper and lower limit of the cloud for all" 121 " atmospheric dimensions. So its dimension must" 122 " be 2 x *atmosphere_dim*");
124 if (scat_data.empty())
126 "No single scattering data present.\n" 127 "See documentation of WSV *scat_data* for options to" 128 " make single scattering data available.\n");
132 "*pnd_field* is not 1D! \n" 133 "RT4 can only be used for 1D!\n");
135 if (quad_type.length() > 1) {
137 os <<
"Input parameter *quad_type* not allowed to contain more than a" 138 <<
" single character.\n" 139 <<
"Yours has " << quad_type.length() <<
".\n";
140 throw runtime_error(os.
str());
143 if (quad_type ==
"D" || quad_type ==
"G") {
144 if (add_straight_angles)
148 }
else if (quad_type ==
"L") {
152 os <<
"Unknown quadrature type: " << quad_type
153 <<
".\nOnly D, G, and L allowed.\n";
154 throw runtime_error(os.
str());
161 if (nstreams / 2 * 2 != nstreams) {
163 os <<
"RT4 requires an even number of streams, but yours is " << nstreams
165 throw runtime_error(os.
str());
167 nhstreams = nstreams / 2;
170 nummu = nhstreams + nhza;
173 bool no_arb_ori =
true;
174 for (
Index i_ss = 0; i_ss < scat_data.
nelem(); i_ss++)
175 for (
Index i_se = 0; i_se < scat_data[i_ss].
nelem(); i_se++)
181 os <<
"RT4 can only handle scattering elements of type " <<
PTYPE_TOTAL_RND 185 <<
"but at least one element of other type (" <<
PTYPE_GENERAL <<
"=" 187 throw runtime_error(os.
str());
193 void get_quad_angles(
200 const Index& nhstreams,
202 const Index& nummu) {
203 if (quad_type ==
"D") {
204 double_gauss_quadrature_(
206 }
else if (quad_type ==
"G") {
207 gauss_legendre_quadrature_(
216 if (nhza > 0) mu_values[nhstreams] = 1.;
222 za_grid.
resize(2 * nummu);
223 for (
Index imu = 0; imu < nummu; imu++) {
224 za_grid[imu] = acos(mu_values[imu]) *
RAD2DEG;
225 za_grid[nummu + imu] = 180. - za_grid[imu];
231 void get_rt4surf_props(
237 const String& ground_type,
242 const Index& stokes_dim) {
243 if (surface_skin_t < 0. || surface_skin_t > 1000.) {
245 os <<
"Surface temperature is set to " << surface_skin_t <<
" K,\n" 246 <<
"which is not considered a meaningful value.\n";
247 throw runtime_error(os.
str());
252 if (ground_type ==
"L")
254 if (
min(surface_scalar_reflectivity) < 0 ||
255 max(surface_scalar_reflectivity) > 1) {
257 "All values in *surface_scalar_reflectivity* must be inside [0,1].");
261 if (surface_scalar_reflectivity.
nelem() == f_grid.
nelem())
262 ground_albedo = surface_scalar_reflectivity;
263 else if (surface_scalar_reflectivity.
nelem() == 1)
264 ground_albedo += surface_scalar_reflectivity[0];
267 os <<
"For Lambertian surface reflection, the number of elements in\n" 268 <<
"*surface_scalar_reflectivity* needs to match the length of\n" 269 <<
"*f_grid* or be 1." 270 <<
"\n length of *f_grid* : " << f_grid.
nelem()
271 <<
"\n length of *surface_scalar_reflectivity* : " 272 << surface_scalar_reflectivity.
nelem() <<
"\n";
273 throw runtime_error(os.
str());
276 }
else if (ground_type ==
"S")
278 const Index ref_sto = surface_reflectivity.
nrows();
281 if (ref_sto != surface_reflectivity.
ncols()) {
283 os <<
"The number of rows and columnss in *surface_reflectivity*\n" 284 <<
"must match each other.";
285 throw runtime_error(os.
str());
288 if (
min(surface_reflectivity(
joker, 0, 0)) < 0 ||
289 max(surface_reflectivity(
joker, 0, 0)) > 1) {
291 "All r11 values in *surface_reflectivity* must be inside [0,1].");
295 if (surface_reflectivity.
npages() == f_grid.
nelem())
296 if (ref_sto < stokes_dim)
298 surface_reflectivity;
300 ground_reflec = surface_reflectivity(
302 else if (surface_reflectivity.
npages() == 1)
303 if (ref_sto < stokes_dim)
304 for (
Index f_index = 0; f_index < nf; f_index++)
305 ground_reflec(f_index,
Range(0, ref_sto),
Range(0, ref_sto)) +=
308 for (
Index f_index = 0; f_index < nf; f_index++)
309 ground_reflec(f_index,
joker,
joker) += surface_reflectivity(
310 0,
Range(0, stokes_dim),
Range(0, stokes_dim));
313 os <<
"For specular surface reflection, the number of elements in\n" 314 <<
"*surface_reflectivity* needs to match the length of\n" 315 <<
"*f_grid* or be 1." 316 <<
"\n length of *f_grid* : " << f_grid.
nelem()
317 <<
"\n length of *surface_reflectivity* : " 318 << surface_reflectivity.
npages() <<
"\n";
319 throw runtime_error(os.
str());
322 }
else if (ground_type ==
"F")
325 Matrix n_real(nf, 1), n_imag(nf, 1);
328 surface_complex_refr_index,
329 "surface_complex_refr_index",
331 Vector(1, surface_skin_t));
333 for (
Index f_index = 0; f_index < nf; f_index++) {
334 ground_index[f_index] =
Complex(n_real(f_index, 0), n_imag(f_index, 0));
338 os <<
"Unknown surface type.\n";
339 throw runtime_error(os.
str());
355 const Agenda& propmat_clearsky_agenda,
357 const Index& stokes_dim,
360 const String& ground_type,
367 const Agenda& surface_rtprop_agenda,
372 const Index& auto_inc_nstreams,
374 const Index& za_interp_order,
375 const Index& cos_za_interp,
376 const String& pfct_method,
377 const Index& pfct_aa_grid_size,
417 Vector height(num_layers + 1);
418 Vector temperatures(num_layers + 1);
419 for (
Index i = 0;
i < height.nelem();
i++) {
420 height[
i] = z[num_layers -
i];
421 temperatures[
i] = t[num_layers -
i];
431 Vector scatlayers(num_layers, 0.);
432 Vector gas_extinct(num_layers, 0.);
434 num_scatlayers, 4, nummu, stokes_dim, nummu, stokes_dim, 0.);
436 1, num_scatlayers, 2, nummu, stokes_dim, stokes_dim, 0.);
437 Tensor5 emis_vector(1, num_scatlayers, 2, nummu, stokes_dim, 0.);
443 for (
Index clev = 0; clev < pnd.
ncols(); clev++)
444 pnd_per_level[clev] = pnd(
joker, clev).sum();
445 Numeric pndtot = pnd_per_level.sum();
447 for (
Index i = 0;
i < cboxlims[1] - cboxlims[0];
i++) {
448 scatlayers[num_layers - 1 - cboxlims[0] -
i] = float(i + 1);
452 Tensor3 up_rad(num_layers + 1, nummu, stokes_dim, 0.);
453 Tensor3 down_rad(num_layers + 1, nummu, stokes_dim, 0.);
457 if (!auto_inc_nstreams) {
458 extinct_matrix_allf.
resize(
459 f_grid.
nelem(), num_scatlayers, 2, nummu, stokes_dim, stokes_dim);
461 f_grid.
nelem(), num_scatlayers, 2, nummu, stokes_dim);
462 par_optpropCalc(emis_vector_allf,
472 if (emis_vector_allf.
nshelves() == 1)
485 if (auto_inc_nstreams) {
491 za_grid_orig = za_grid;
496 for (
Index f_index = 0; f_index < f_grid.
nelem(); f_index++) {
510 if (vmr.
ncols() > 0) {
513 propmat_clearsky_agenda,
514 t[
Range(0, num_layers + 1)],
516 p[
Range(0, num_layers + 1)],
517 f_grid[
Range(f_index, 1)]);
520 Index pfct_failed = 0;
522 if (nummu_new < nummu) {
523 if (!auto_inc_nstreams)
526 if (emis_vector_allf.
nshelves() != 1) {
529 extinct_matrix = extinct_matrix_allf(
533 par_optpropCalc(emis_vector,
540 t[
Range(0, num_layers + 1)],
544 sca_optpropCalc(scatter_matrix,
565 #pragma omp critical(fortran_rt4) 568 radtrano_(stokes_dim,
575 ground_albedo[f_index],
576 ground_index[f_index],
583 height.get_c_array(),
584 temperatures.get_c_array(),
585 gas_extinct.get_c_array(),
587 scatlayers.get_c_array(),
588 extinct_matrix.get_c_array(),
589 emis_vector.get_c_array(),
590 scatter_matrix.get_c_array(),
594 up_rad.get_c_array(),
595 down_rad.get_c_array());
600 if (nummu_new < nummu) nummu_new = nummu + 1;
603 Vector mu_values_new, quad_weights_new, aa_grid_new;
610 while (pfct_failed && (2 * nummu_new) <= auto_inc_nstreams) {
613 nhstreams_new = nummu_new - nhza;
614 mu_values_new.
resize(nummu_new);
616 quad_weights_new.
resize(nummu_new);
617 quad_weights_new = 0.;
618 get_quad_angles(mu_values_new,
628 extinct_matrix_new.
resize(
629 1, num_scatlayers, 2, nummu_new, stokes_dim, stokes_dim);
630 extinct_matrix_new = 0.;
631 emis_vector_new.
resize(1, num_scatlayers, 2, nummu_new, stokes_dim);
632 emis_vector_new = 0.;
641 par_optpropCalc(emis_vector_new,
648 t[
Range(0, num_layers + 1)],
653 scatter_matrix_new.
resize(
654 num_scatlayers, 4, nummu_new, stokes_dim, nummu_new, stokes_dim);
655 scatter_matrix_new = 0.;
674 if (pfct_failed) nummu_new = nummu_new + 1;
678 nummu_new = nummu_new - 1;
680 os <<
"Could not increase nstreams sufficiently (current: " 681 << 2 * nummu_new <<
")\n" 682 <<
"to satisfy scattering matrix norm at f[" << f_index
683 <<
"]=" << f_grid[f_index] * 1e-9 <<
" GHz.\n";
688 os <<
"Try higher maximum number of allowed streams (ie. higher" 689 <<
" auto_inc_nstreams than " << auto_inc_nstreams <<
").";
690 throw runtime_error(os.
str());
693 os <<
"Continuing with nstreams=" << 2 * nummu_new
694 <<
". Output for this frequency might be erroneous.";
718 if (ground_type ==
"A")
720 Tensor5 srm_new(1, nummu_new, stokes_dim, nummu_new, stokes_dim, 0.);
721 Tensor3 sev_new(1, nummu_new, stokes_dim, 0.);
725 surface_rtprop_agenda,
726 f_grid[
Range(f_index, 1)],
736 Tensor3 up_rad_new(num_layers + 1, nummu_new, stokes_dim, 0.);
737 Tensor3 down_rad_new(num_layers + 1, nummu_new, stokes_dim, 0.);
740 #pragma omp critical(fortran_rt4) 743 radtrano_(stokes_dim,
750 ground_albedo[f_index],
751 ground_index[f_index],
758 height.get_c_array(),
759 temperatures.get_c_array(),
760 gas_extinct.get_c_array(),
762 scatlayers.get_c_array(),
770 up_rad_new.get_c_array(),
771 down_rad_new.get_c_array());
784 for (
Index j = 0; j < nummu; j++) {
788 gp_za, mu_values_new, mu_values[j], za_interp_order, 0.5);
791 za_grid[
Range(0, nummu_new)],
799 for (
Index k = 0; k < num_layers + 1; k++)
800 for (
Index ist = 0; ist < stokes_dim; ist++) {
801 up_rad(k, j, ist) =
interp(itw, up_rad_new(k,
joker, ist), gp_za);
802 down_rad(k, j, ist) =
808 za_grid = za_grid_orig;
826 Numeric rad_l2f = wavelength / f_grid[f_index];
831 for (
Index j = 0; j < nummu; j++) {
832 for (
Index ist = 0; ist < stokes_dim; ist++) {
833 for (
Index k = cboxlims[1] - cboxlims[0]; k >= 0; k--) {
834 cloudbox_field(f_index, k + ncboxremoved, 0, 0, nummu + j, 0, ist) =
835 up_rad(num_layers - k, j, ist) * rad_l2f;
837 f_index, k + ncboxremoved, 0, 0, nummu - 1 - j, 0, ist) =
838 down_rad(num_layers - k, j, ist) * rad_l2f;
842 for (
Index k = ncboxremoved - 1; k >= 0; k--) {
843 cloudbox_field(f_index, k, 0, 0, nummu + j, 0, ist) =
844 cloudbox_field(f_index, k + 1, 0, 0, nummu + j, 0, ist);
845 cloudbox_field(f_index, k, 0, 0, nummu - 1 + j, 0, ist) =
846 cloudbox_field(f_index, k + 1, 0, 0, nummu - 1 + j, 0, ist);
857 const Index& nummu) {
858 for (
Index j = 0; j < nummu; j++) {
859 za_grid[nummu - 1 - j] = acos(mu_values[j]) *
RAD2DEG;
860 za_grid[nummu + j] = 180. - acos(mu_values[j]) *
RAD2DEG;
869 const Agenda& propmat_clearsky_agenda,
879 assert(gas_extinct.
nelem() == Np - 1);
890 for (
Index i = 0;
i < Np - 1;
i++) {
891 rtp_pressure_local = 0.5 * (p_grid[
i] + p_grid[
i + 1]);
892 rtp_temperature_local = 0.5 * (t_profile[
i] + t_profile[
i + 1]);
895 for (
Index j = 0; j < vmr_profiles.
nrows(); j++)
896 rtp_vmr_local[j] = 0.5 * (vmr_profiles(j, i) + vmr_profiles(j, i + 1));
898 const Vector rtp_mag_dummy(3, 0);
899 const Vector ppath_los_dummy;
907 propmat_clearsky_local,
910 partial_source_dummy,
917 rtp_temperature_local,
918 rtp_nlte_local_dummy,
920 propmat_clearsky_agenda);
923 if (propmat_clearsky_local.
nelem()) {
924 gas_extinct[Np - 2 -
i] = propmat_clearsky_local[0].Kjj()[0];
925 for (
Index j = 1; j < propmat_clearsky_local.
nelem(); j++) {
926 gas_extinct[Np - 2 -
i] += propmat_clearsky_local[j].Kjj()[0];
937 const Index& f_index,
941 const Index& stokes_dim) {
949 assert(emis_vector.
nbooks() == Np_cloud - 1);
950 assert(extinct_matrix.
nshelves() == Np_cloud - 1);
953 Vector T_array = t_profile[
Range(cloudbox_limits[0], Np_cloud)];
955 dir_array(
joker, 0) = za_grid;
995 for (
Index ipc = 0; ipc < Np_cloud - 1; ipc++) {
996 for (
Index fi = 0; fi < abs_vec_bulk.
nbooks(); fi++) {
997 for (
Index imu = 0; imu < nummu; imu++) {
998 for (
Index ist1 = 0; ist1 < stokes_dim; ist1++) {
999 for (
Index ist2 = 0; ist2 < stokes_dim; ist2++) {
1000 extinct_matrix(fi, ipc, 0, imu, ist2, ist1) =
1001 .5 * (ext_mat_bulk(fi, ipc, imu, ist1, ist2) +
1002 ext_mat_bulk(fi, ipc + 1, imu, ist1, ist2));
1003 extinct_matrix(fi, ipc, 1, imu, ist2, ist1) =
1004 .5 * (ext_mat_bulk(fi, ipc, nummu + imu, ist1, ist2) +
1005 ext_mat_bulk(fi, ipc + 1, nummu + imu, ist1, ist2));
1007 emis_vector(fi, ipc, 0, imu, ist1) =
1008 .5 * (abs_vec_bulk(fi, ipc, imu, ist1) +
1009 abs_vec_bulk(fi, ipc + 1, imu, ist1));
1010 emis_vector(fi, ipc, 1, imu, ist1) =
1011 .5 * (abs_vec_bulk(fi, ipc, nummu + imu, ist1) +
1012 abs_vec_bulk(fi, ipc + 1, nummu + imu, ist1));
1019 void sca_optpropCalc(
1025 const Index& f_index,
1028 const Index& stokes_dim,
1031 const String& pfct_method,
1032 const Index& pfct_aa_grid_size,
1033 const Numeric& pfct_threshold,
1034 const Index& auto_inc_nstreams,
1048 scatter_matrix = 0.;
1054 assert(scatter_matrix.
nvitrines() == Np_cloud - 1);
1062 os <<
"Total number of scattering elements in scat_data (" 1065 throw runtime_error(os.
str());
1068 if (pfct_aa_grid_size < 2) {
1070 os <<
"Azimuth grid size for scatt matrix extraction" 1071 <<
" (*pfct_aa_grid_size*) must be >1.\n" 1072 <<
"Yours is " << pfct_aa_grid_size <<
".\n";
1073 throw runtime_error(os.
str());
1076 nlinspace(aa_grid, 0, 180, pfct_aa_grid_size);
1078 Index i_se_flat = 0;
1079 Tensor5 sca_mat(N_se, nza_rt, nza_rt, stokes_dim, stokes_dim, 0.);
1080 Matrix ext_fixT_spt(N_se, nza_rt, 0.), abs_fixT_spt(N_se, nza_rt, 0.);
1085 1. / float(pfct_aa_grid_size - 1);
1093 for (
Index i_ss = 0; i_ss < scat_data.
nelem(); i_ss++) {
1094 for (
Index i_se = 0; i_se < scat_data[i_ss].
nelem(); i_se++) {
1098 if (pfct_method ==
"low")
1100 else if (pfct_method ==
"high")
1106 Matrix pha_mat(stokes_dim, stokes_dim, 0.);
1107 for (
Index iza = 0; iza < nza_rt; iza++) {
1108 for (
Index sza = 0; sza < nza_rt; sza++) {
1109 Matrix pha_mat_int(stokes_dim, stokes_dim, 0.);
1110 for (
Index saa = 0; saa < pfct_aa_grid_size; saa++) {
1126 if (saa == 0 || saa == pfct_aa_grid_size - 1)
1127 pha_mat *= (daa_totrand / 2.);
1129 pha_mat *= daa_totrand;
1130 pha_mat_int += pha_mat;
1132 sca_mat(i_se_flat, iza, sza,
joker,
joker) = pha_mat_int;
1134 ext_fixT_spt(i_se_flat, iza) =
1136 abs_fixT_spt(i_se_flat, iza) =
1142 Tensor4 pha_mat_int(nza_se, nza_se, stokes_dim, stokes_dim, 0.);
1145 assert(aa_datagrid[0] == 0.);
1146 assert(aa_datagrid[naa_se - 1] == 180.);
1155 daa[0] = (aa_datagrid[1] - aa_datagrid[0]) / 360.;
1156 for (
Index saa = 1; saa < naa_se - 1; saa++)
1157 daa[saa] = (aa_datagrid[saa + 1] - aa_datagrid[saa - 1]) / 360.;
1159 (aa_datagrid[naa_se - 1] - aa_datagrid[naa_se - 2]) / 360.;
1164 for (
Index iza = 0; iza < nza_se; iza++)
1165 for (
Index sza = 0; sza < nza_se; sza++) {
1166 for (
Index saa = 0; saa < naa_se; saa++) {
1167 for (
Index ist1 = 0; ist1 < stokes_dim; ist1++)
1168 for (
Index ist2 = 0; ist2 < stokes_dim; ist2++)
1169 pha_mat_int(sza, iza, ist1, ist2) +=
1182 for (
Index iza = 0; iza < nza_rt; iza++) {
1183 for (
Index sza = 0; sza < nza_rt; sza++) {
1187 Matrix pha_mat_lab(stokes_dim, stokes_dim, 0.);
1188 Numeric za_sca = za_grid[sza];
1189 Numeric za_inc = za_grid[iza];
1191 gridpos(za_inc_gp, za_datagrid, za_inc);
1192 gridpos(za_sca_gp, za_datagrid, za_sca);
1195 for (
Index ist1 = 0; ist1 < stokes_dim; ist1++)
1196 for (
Index ist2 = 0; ist2 < stokes_dim; ist2++) {
1197 pha_mat_lab(ist1, ist2) =
1206 sca_mat(i_se_flat, iza, sza,
joker,
joker) = pha_mat_lab;
1208 ext_fixT_spt(i_se_flat, iza) =
1210 abs_fixT_spt(i_se_flat, iza) =
1215 os <<
"Unsuitable particle type encountered.";
1216 throw runtime_error(os.
str());
1222 assert(i_se_flat == N_se);
1230 Index nummu = nza_rt / 2;
1231 for (
Index scat_p_index_local = 0; scat_p_index_local < Np_cloud - 1;
1232 scat_p_index_local++) {
1233 Vector ext_fixT(nza_rt, 0.), abs_fixT(nza_rt, 0.);
1235 for (
Index i_se = 0; i_se < N_se; i_se++) {
1236 Numeric pnd_mean = 0.5 * (pnd_profiles(i_se, scat_p_index_local + 1) +
1237 pnd_profiles(i_se, scat_p_index_local));
1239 for (
Index iza = 0; iza < nummu; iza++) {
1245 for (
Index sza = 0; sza < nummu; sza++) {
1246 for (
Index ist1 = 0; ist1 < stokes_dim; ist1++)
1247 for (
Index ist2 = 0; ist2 < stokes_dim; ist2++) {
1252 scatter_matrix(scat_p_index_local, 0, iza, ist2, sza, ist1) +=
1253 pnd_mean * sca_mat(i_se, iza, sza, ist1, ist2);
1254 scatter_matrix(scat_p_index_local, 1, iza, ist2, sza, ist1) +=
1255 pnd_mean * sca_mat(i_se, nummu + iza, sza, ist1, ist2);
1256 scatter_matrix(scat_p_index_local, 2, iza, ist2, sza, ist1) +=
1257 pnd_mean * sca_mat(i_se, iza, nummu + sza, ist1, ist2);
1258 scatter_matrix(scat_p_index_local, 3, iza, ist2, sza, ist1) +=
1260 sca_mat(i_se, nummu + iza, nummu + sza, ist1, ist2);
1264 ext_fixT[iza] += pnd_mean * ext_fixT_spt(i_se, iza);
1265 abs_fixT[iza] += pnd_mean * abs_fixT_spt(i_se, iza);
1269 for (
Index iza = 0; iza < nummu; iza++) {
1270 for (
Index ih = 0; ih < 2; ih++) {
1271 if (extinct_matrix(scat_p_index_local, ih, iza, 0, 0) > 0.) {
1280 Numeric ext_nom = ext_fixT[iza];
1281 Numeric sca_nom = ext_nom - abs_fixT[iza];
1282 Numeric w0_nom = sca_nom / ext_nom;
1283 assert(w0_nom >= 0.);
1285 for (
Index sza = 0; sza < nummu; sza++) {
1291 (scatter_matrix(scat_p_index_local, ih, iza, 0, sza, 0) +
1292 scatter_matrix(scat_p_index_local, ih + 2, iza, 0, sza, 0));
1300 Numeric w0_act = 2. *
PI * sca_mat_integ / ext_nom;
1301 Numeric pfct_norm = 2. *
PI * sca_mat_integ / sca_nom;
1307 extinct_matrix(scat_p_index_local, ih, iza, 0, 0) -
1308 emis_vector(scat_p_index_local, ih, iza, 0);
1321 if (
abs(w0_act - w0_nom) > pfct_threshold) {
1322 if (pfct_failed >= 0) {
1323 if (auto_inc_nstreams) {
1328 os <<
"Bulk scattering matrix normalization deviates significantly\n" 1329 <<
"from expected value (" << 1e2 *
abs(1. - pfct_norm)
1331 <<
" resulting in albedo deviation of " 1332 <<
abs(w0_act - w0_nom) <<
").\n" 1333 <<
"Something seems wrong with your scattering data " 1334 <<
" (did you run *scat_dataCheck*?)\n" 1335 <<
"or your RT4 setup (try increasing *nstreams* and in case" 1336 <<
" of randomly oriented particles possibly also" 1337 <<
" pfct_aa_grid_size).";
1338 throw runtime_error(os.
str());
1341 }
else if (
abs(w0_act - w0_nom) > pfct_threshold * 0.1 ||
1342 abs(1. - pfct_norm) > 1e-2) {
1345 <<
"Warning: The bulk scattering matrix is not well normalized\n" 1346 <<
"Deviating from expected value by " 1347 << 1e2 *
abs(1. - pfct_norm) <<
"% (and " 1348 <<
abs(w0_act - w0_nom) <<
" in terms of scattering albedo).\n";
1359 pfct_norm = 2. *
PI * sca_mat_integ / sca_nom_paropt;
1384 const Agenda& surface_rtprop_agenda,
1389 const Index& stokes_dim,
1426 chk_not_empty(
"surface_rtprop_agenda", surface_rtprop_agenda);
1430 const String B_unit =
"R";
1433 Vector rtp_pos(1, surf_alt);
1435 for (
Index rmu = 0; rmu < nummu; rmu++) {
1446 Vector rtp_los(1, za_grid[nummu + rmu]);
1456 surface_rtprop_agenda);
1458 assert(surface_los.
ncols() == 1 || nsl == 0);
1472 for (
Index f_index = 0; f_index < nf; f_index++) {
1473 Numeric freq = f_grid[f_index];
1477 planck_function_(surface_skin_t, B_unit.c_str(), wave, B_lambda);
1478 Numeric B_ratio = B_lambda / B_freq;
1479 surf_emis_vec(f_index, rmu,
joker) = surface_emission(f_index,
joker);
1480 surf_emis_vec(f_index, rmu,
joker) *= B_ratio;
1499 for (
Index f_index = 0; f_index < nf; f_index++)
1500 R_arts[f_index] = surface_rmatrix(
joker, f_index, 0, 0).sum();
1504 Vector surf_int_grid(nsl + 1);
1506 surface_los(0, 0) - 0.5 * (surface_los(1, 0) - surface_los(0, 0));
1507 surf_int_grid[nsl] =
1508 surface_los(nsl - 1, 0) +
1509 0.5 * (surface_los(nsl - 1, 0) - surface_los(nsl - 2, 0));
1510 for (
Index imu = 1; imu < nsl; imu++)
1511 surf_int_grid[imu] =
1512 0.5 * (surface_los(imu - 1, 0) + surface_los(imu, 0));
1514 for (
Index imu = 0; imu < nsl; imu++) {
1518 Numeric w = 0.5 * (cos(2. * surf_int_grid[imu]) -
1519 cos(2. * surf_int_grid[imu + 1]));
1528 for (
Index imu = 0; imu < nummu; imu++) {
1540 for (
Index f_index = 0; f_index < nf; f_index++)
1541 for (
Index sto1 = 0; sto1 < stokes_dim; sto1++)
1542 for (
Index sto2 = 0; sto2 < stokes_dim; sto2++)
1543 surf_refl_mat(f_index, imu, sto2, rmu, sto1) =
interp(
1544 itw, surface_rmatrix(
joker, f_index, sto1, sto2), gp_za);
1548 (quad_weights[imu] * mu_values[imu]);
1549 }
catch (
const runtime_error& e) {
1558 for (
Index f_index = 0; f_index < nf; f_index++)
1559 R_arts[f_index] = surface_rmatrix(
joker, f_index, 0, 0).sum();
1566 for (
Index f_index = 0; f_index < nf; f_index++)
1567 for (
Index sto1 = 0; sto1 < stokes_dim; sto1++)
1568 for (
Index sto2 = 0; sto2 < stokes_dim; sto2++)
1569 surf_refl_mat(f_index, rmu, sto2, rmu, sto1) =
1570 surface_rmatrix(0, f_index, sto1, sto2);
1576 for (
Index f_index = 0; f_index < nf; f_index++) {
1578 Numeric R_rt4 = surf_refl_mat(f_index,
joker, 0, rmu, 0).sum();
1580 if (R_arts[f_index] != 0.) {
1582 os <<
"Something went wrong.\n" 1583 <<
"At reflected stream #" << rmu
1584 <<
", power reflection coefficient for RT4\n" 1585 <<
"became 0, although the one from surface_rtprop_agenda is " 1587 throw runtime_error(os.
str());
1590 R_scale = R_arts[f_index] / R_rt4;
1597 void rt4_test(
Tensor4& out_rad,
1606 Numeric max_delta_tau = 1.0E-6;
1609 String ground_type =
"L";
1618 Vector height, temperatures, gas_extinct;
1622 ReadXML(height,
"height", datapath +
"z.xml",
"", verbosity);
1623 ReadXML(temperatures,
"temperatures", datapath +
"T.xml",
"", verbosity);
1624 ReadXML(gas_extinct,
"gas_extinct", datapath +
"abs_gas.xml",
"", verbosity);
1625 ReadXML(abs_data,
"abs_data", datapath +
"abs_par.xml",
"", verbosity);
1626 ReadXML(ext_data,
"ext_data", datapath +
"ext_par.xml",
"", verbosity);
1627 ReadXML(sca_data,
"sca_data", datapath +
"sca_par.xml",
"", verbosity);
1629 Index num_scatlayers = 3;
1630 Vector scatlayers(num_layers, 0.);
1640 Tensor6 scatter_matrix(num_scatlayers, 4, nummu, nstokes, nummu, nstokes);
1641 for (
Index ii = 0; ii < 4; ii++)
1642 for (
Index ij = 0; ij < nummu; ij++)
1643 for (
Index ik = 0; ik < nstokes; ik++)
1644 for (
Index il = 0; il < nummu; il++)
1645 for (
Index im = 0; im < nstokes; im++)
1646 for (
Index in = 0; in < num_scatlayers; in++)
1647 scatter_matrix(in, ii, ij, ik, il, im) =
1648 sca_data(im, il, ik, ij, ii);
1649 Tensor5 extinct_matrix(num_scatlayers, 2, nummu, nstokes, nstokes);
1650 for (
Index ii = 0; ii < 2; ii++)
1651 for (
Index ij = 0; ij < nummu; ij++)
1652 for (
Index ik = 0; ik < nstokes; ik++)
1653 for (
Index il = 0; il < nstokes; il++)
1654 for (
Index im = 0; im < num_scatlayers; im++)
1655 extinct_matrix(im, ii, ij, ik, il) = ext_data(il, ik, ij, ii);
1656 Tensor4 emis_vector(num_scatlayers, 2, nummu, nstokes);
1657 for (
Index ii = 0; ii < 2; ii++)
1658 for (
Index ij = 0; ij < nummu; ij++)
1659 for (
Index ik = 0; ik < nstokes; ik++)
1660 for (
Index il = 0; il < num_scatlayers; il++)
1661 emis_vector(il, ii, ij, ik) = abs_data(ik, ij, ii);
1664 Tensor4 surf_refl_mat(nummu, nstokes, nummu, nstokes, 0.);
1665 Matrix surf_emis_vec(nummu, nstokes, 0.);
1666 Matrix ground_reflec(nstokes, nstokes, 0.);
1670 Tensor3 up_rad(num_layers + 1, nummu, nstokes, 0.);
1671 Tensor3 down_rad(num_layers + 1, nummu, nstokes, 0.);
1679 ground_type.c_str(),
1682 ground_reflec.get_c_array(),
1692 scatlayers.get_c_array(),
1693 extinct_matrix.get_c_array(),
1694 emis_vector.get_c_array(),
1698 mu_values.get_c_array(),
1699 up_rad.get_c_array(),
1700 down_rad.get_c_array());
1714 out_rad.
resize(num_layers + 1, 2, nummu, nstokes);
1715 for (
Index ii = 0; ii < nummu; ii++)
INDEX Index
The type to use for all integer numbers and indices.
void surface_rtprop_agendaExecute(Workspace &ws, Numeric &surface_skin_t, Matrix &surface_emission, Matrix &surface_los, Tensor4 &surface_rmatrix, const Vector &f_grid, const Vector &rtp_pos, const Vector &rtp_los, const Agenda &input_agenda)
A class implementing complex numbers for ARTS.
Index nelem() const
Number of elements.
void resize(Index s, Index b, Index p, Index r, Index c)
Resize function.
const Numeric * get_c_array() const
Conversion to plain C-array.
Index nvitrines() const
Returns the number of vitrines.
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPos &tc)
Red 1D Interpolate.
Contains functions related to application of scattering solver RT4.
Array< RetrievalQuantity > ArrayOfRetrievalQuantity
void reduced_1datm(Vector &p, Vector &z, Vector &t, Matrix &vmr, Matrix &pnd, ArrayOfIndex &cboxlims, Index &ncboxremoved, ConstVectorView p_grid, ConstVectorView z_profile, const Numeric &z_surface, ConstVectorView t_profile, ConstMatrixView vmr_profiles, ConstMatrixView pnd_profiles, const ArrayOfIndex &cloudbox_limits)
reduced_1datm
invlib::Vector< ArtsVector > Vector
invlib wrapper type for ARTS vectors.
cmplx FADDEEVA() w(cmplx z, double relerr)
void opt_prop_Bulk(Tensor5 &ext_mat, Tensor4 &abs_vec, Index &ptype, const ArrayOfTensor5 &ext_mat_ss, const ArrayOfTensor4 &abs_vec_ss, const ArrayOfIndex &ptypes_ss)
one-line descript
Header file for interpolation.cc.
Index nbooks() const
Returns the number of books.
Index nrows() const
Returns the number of rows.
Index nelem() const
Returns the number of elements.
Structure to store a grid position.
A constant view of a Tensor4.
const Numeric COSMIC_BG_TEMP
Global constant, Planck temperature for cosmic background radiation [K].
Index ncols() const
Returns the number of columns.
const Numeric * get_c_array() const
Conversion to plain C-array, const-version.
Index TotalNumberOfElements(const Array< Array< base > > &aa)
Determine total number of elements in an ArrayOfArray.
Index nshelves() const
Returns the number of shelves.
bool is_same_within_epsilon(const Numeric &a, const Numeric &b, const Numeric &epsilon)
Check, if two numbers agree within a given epsilon.
_CS_string_type str() const
std::complex< Numeric > Complex
Index ncols() const
Returns the number of columns.
void nlinspace(Vector &x, const Numeric start, const Numeric stop, const Index n)
nlinspace
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
A constant view of a Tensor5.
NUMERIC Numeric
The type to use for all floating point numbers.
void ReadXML(T &v, const String &v_name, const String &f, const String &f_name, const Verbosity &verbosity)
WORKSPACE METHOD: ReadXML.
Index nlibraries() const
Returns the number of libraries.
void gridpos_poly(ArrayOfGridPosPoly &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac)
The maximum difference from 1 that we allow for a sum check.
const Numeric * get_c_array() const
Conversion to plain C-array.
const Numeric DEG2RAD
Global constant, conversion from degrees to radians.
basic_ostringstream< char, string_char_traits< char >, alloc > ostringstream
Index npages() const
Returns the number of pages.
This can be used to make arrays out of anything.
Index nshelves() const
Returns the number of shelves.
void opt_prop_ScatSpecBulk(ArrayOfTensor5 &ext_mat, ArrayOfTensor4 &abs_vec, ArrayOfIndex &ptype, const ArrayOfArrayOfTensor5 &ext_mat_se, const ArrayOfArrayOfTensor4 &abs_vec_se, const ArrayOfArrayOfIndex &ptypes_se, ConstMatrixView pnds, ConstMatrixView t_ok)
Scattering species bulk extinction and absorption.
const Numeric PI
Global constant, pi.
const Numeric * get_c_array() const
Conversion to plain C-array.
void resize(Index n)
Resize function.
A constant view of a Tensor3.
void pha_matTransform(MatrixView pha_mat_lab, ConstTensor5View pha_mat_data, ConstVectorView za_datagrid, ConstVectorView aa_datagrid, const PType &ptype, const Index &za_sca_idx, const Index &aa_sca_idx, const Index &za_inc_idx, const Index &aa_inc_idx, ConstVectorView za_grid, ConstVectorView aa_grid, const Verbosity &verbosity)
Transformation of phase matrix.
A constant view of a Vector.
Workspace methods and template functions for supergeneric XML IO.
String PTypeToString(const PType &ptype)
Convert particle type enum value to String.
A constant view of a Matrix.
Numeric planck(const Numeric &f, const Numeric &t)
planck
Index nbooks() const
Returns the number of books.
void resize(Index v, Index s, Index b, Index p, Index r, Index c)
Resize function.
Structure to store a grid position for higher order interpolation.
void opt_prop_NScatElems(ArrayOfArrayOfTensor5 &ext_mat, ArrayOfArrayOfTensor4 &abs_vec, ArrayOfArrayOfIndex &ptypes, Matrix &t_ok, const ArrayOfArrayOfSingleScatteringData &scat_data, const Index &stokes_dim, const Vector &T_array, const Matrix &dir_array, const Index &f_index, const Index &t_interp_order)
Extinction and absorption from all scattering elements.
const Numeric * get_c_array() const
Conversion to plain C-array.
A constant view of a ComplexVector.
void propmat_clearsky_agendaExecute(Workspace &ws, ArrayOfPropagationMatrix &propmat_clearsky, ArrayOfStokesVector &nlte_source, ArrayOfPropagationMatrix &dpropmat_clearsky_dx, ArrayOfStokesVector &dnlte_dx_source, ArrayOfStokesVector &nlte_dsource_dx, const ArrayOfRetrievalQuantity &jacobian_quantities, const Vector &f_grid, const Vector &rtp_mag, const Vector &rtp_los, const Numeric rtp_pressure, const Numeric rtp_temperature, const EnergyLevelMap &rtp_nlte, const Vector &rtp_vmr, const Agenda &input_agenda)
void complex_n_interp(MatrixView n_real, MatrixView n_imag, const GriddedField3 &complex_n, const String &varname, ConstVectorView f_grid, ConstVectorView t_grid)
General function for interpolating data of complex n type.
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
Functions for disort interface.
const Numeric SPEED_OF_LIGHT
Scattering database structure and functions.
This file contains declerations of functions of physical character.
Index nrows() const
Returns the number of rows.
void resize(Index b, Index p, Index r, Index c)
Resize function.
const Numeric RAD2DEG
Global constant, conversion from radians to degrees.
Declaration of functions in rte.cc.
const Numeric * get_c_array() const
Conversion to plain C-array.