ARTS  2.3.1285(git:92a29ea9-dirty)
doit.cc
Go to the documentation of this file.
1 /* Copyright (C) 2002-2012 Claudia Emde <claudia.emde@dlr.de>
2 
3  This program is free software; you can redistribute it and/or modify it
4  under the terms of the GNU General Public License as published by the
5  Free Software Foundation; either version 2, or (at your option) any
6  later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  USA.
17 */
18 
29 /*===========================================================================
30  === External declarations
31  ===========================================================================*/
32 
33 #include "doit.h"
34 #include <cmath>
35 #include <cstdlib>
36 #include <iostream>
37 #include <stdexcept>
38 #include "agenda_class.h"
39 #include "array.h"
40 #include "auto_md.h"
41 #include "check_input.h"
42 #include "cloudbox.h"
43 #include "geodetic.h"
44 #include "lin_alg.h"
45 #include "logic.h"
46 #include "math_funcs.h"
47 #include "matpackVII.h"
48 #include "messages.h"
49 #include "physics_funcs.h"
50 #include "ppath.h"
51 #include "propagationmatrix.h"
52 #include "rte.h"
53 #include "sorting.h"
54 #include "special_interp.h"
55 #include "xml_io.h"
56 
57 extern const Numeric PI;
58 extern const Numeric RAD2DEG;
59 
60 //FIXME function name of 'rte_step_doit_replacement' should be replaced by
61 //proper name
62 void rte_step_doit_replacement( //Output and Input:
63  VectorView stokes_vec,
64  MatrixView trans_mat,
65  //Input
66  const PropagationMatrix& ext_mat_av,
67  const StokesVector& abs_vec_av,
68  ConstVectorView sca_vec_av,
69  const Numeric& lstep,
70  const Numeric& rtp_planck_value,
71  const bool& trans_is_precalc) {
72  //Stokes dimension:
73  Index stokes_dim = stokes_vec.nelem();
74 
75  //Test sizes
76  assert(ext_mat_av.NumberOfFrequencies() == 1 and
77  abs_vec_av.NumberOfFrequencies() == 1);
78 
79  //Check inputs:
80  assert(is_size(trans_mat, 1, stokes_dim, stokes_dim));
81  assert(stokes_dim == ext_mat_av.StokesDimensions() and
82  stokes_dim == abs_vec_av.StokesDimensions());
83  assert(is_size(sca_vec_av, stokes_dim));
84  assert(rtp_planck_value >= 0);
85  assert(lstep >= 0);
86  //assert (not ext_mat_av.AnySingular()); This is asserted at a later time in this version...
87 
88  // Check, if only the first component of abs_vec is non-zero:
89 // const bool unpol_abs_vec = abs_vec_av.IsUnpolarized(0);
90 
91 // bool unpol_sca_vec = true;
92 
93 // for (Index i = 1; i < stokes_dim; i++)
94 // if (sca_vec_av[i] != 0) unpol_sca_vec = false;
95 
96  // Calculate transmission by general function, if not precalculated
97 // Index extmat_case = 0;
98  if (!trans_is_precalc) {
100  trans_mat, lstep, ext_mat_av, 0);
101  }
102 
103  //--- Scalar case: ---------------------------------------------------------
104  if (stokes_dim == 1) {
105  stokes_vec[0] = stokes_vec[0] * trans_mat(0, 0) +
106  (abs_vec_av.Kjj()[0] * rtp_planck_value + sca_vec_av[0]) /
107  ext_mat_av.Kjj()[0] * (1 - trans_mat(0, 0));
108  }
109 
110  //--- Vector case: ---------------------------------------------------------
111 
112  // We have here two cases, diagonal or non-diagonal ext_mat_gas
113  // For diagonal ext_mat_gas, we expect abs_vec_gas to only have a
114  // non-zero value in position 1.
115 
116  //- Unpolarised
117 // else if (extmat_case == 1 && unpol_abs_vec && unpol_sca_vec) {
118 // const Numeric invK = 1.0 / ext_mat_av.Kjj()[0];
119 // // Stokes dim 1
120 // stokes_vec[0] = stokes_vec[0] * trans_mat(0, 0) +
121 // (abs_vec_av.Kjj()[0] * rtp_planck_value + sca_vec_av[0]) *
122 // invK * (1 - trans_mat(0, 0));
123 //
124 // // Stokes dims > 1
125 // for (Index i = 1; i < stokes_dim; i++) {
126 // stokes_vec[i] = stokes_vec[i] * trans_mat(i, i) +
127 // sca_vec_av[i] * invK * (1 - trans_mat(i, i));
128 // }
129 // }
130 
131  //- General case
132  else {
133  Matrix invK(stokes_dim, stokes_dim);
134  ext_mat_av.MatrixInverseAtPosition(invK);
135 
136  Vector source = abs_vec_av.VectorAtPosition();
137  source *= rtp_planck_value;
138 
139  for (Index i = 0; i < stokes_dim; i++)
140  source[i] += sca_vec_av[i]; // b = abs_vec * B + sca_vec
141 
142  // solve K^(-1)*b = x
143  Vector x(stokes_dim);
144  mult(x, invK, source);
145 
146  Vector term1(stokes_dim);
147  Vector term2(stokes_dim);
148 
149  Matrix ImT(stokes_dim, stokes_dim);
150  id_mat(ImT);
151  ImT -= trans_mat;
152  mult(term2, ImT, x); // term2: second term of the solution of the RTE with
153  //fixed scattered field
154 
155  // term1: first term of solution of the RTE with fixed scattered field
156  mult(term1, trans_mat, stokes_vec);
157 
158  for (Index i = 0; i < stokes_dim; i++)
159  stokes_vec[i] = term1[i] + term2[i]; // Compute the new Stokes Vector
160  }
161 }
162 
164  // Output and Input:
165  Tensor5View ext_mat_field,
166  Tensor4View abs_vec_field,
167  // Input:
168  const Agenda& spt_calc_agenda,
169  const Index& za_index,
170  const Index& aa_index,
171  const ArrayOfIndex& cloudbox_limits,
172  ConstTensor3View t_field,
173  ConstTensor4View pnd_field,
174  const Verbosity& verbosity) {
175  CREATE_OUT3;
176 
177  // Input variables are checked in the WSMs i_fieldUpdateSeqXXX, from
178  // where this function is called.
179 
180  out3 << "Calculate scattering properties in cloudbox \n";
181 
182  const Index atmosphere_dim = cloudbox_limits.nelem() / 2;
183  const Index N_se = pnd_field.nbooks();
184  const Index stokes_dim = ext_mat_field.ncols();
185 
186  assert(atmosphere_dim == 1 || atmosphere_dim == 3);
187  assert(ext_mat_field.ncols() == ext_mat_field.nrows() &&
188  ext_mat_field.ncols() == abs_vec_field.ncols());
189 
190  const Index Np_cloud = cloudbox_limits[1] - cloudbox_limits[0] + 1;
191 
192  // If atmosohere_dim == 1
193  Index Nlat_cloud = 1;
194  Index Nlon_cloud = 1;
195 
196  if (atmosphere_dim == 3) {
197  Nlat_cloud = cloudbox_limits[3] - cloudbox_limits[2] + 1;
198  Nlon_cloud = cloudbox_limits[5] - cloudbox_limits[4] + 1;
199  }
200 
201  // Initialize ext_mat(_spt), abs_vec(_spt)
202  // Resize and initialize variables for storing optical properties
203  // of all scattering elements.
204  ArrayOfStokesVector abs_vec_spt_local(N_se);
205  for (auto& av : abs_vec_spt_local) {
206  av = StokesVector(1, stokes_dim);
207  av.SetZero();
208  }
209  ArrayOfPropagationMatrix ext_mat_spt_local(N_se);
210  for (auto& pm : ext_mat_spt_local) {
211  pm = PropagationMatrix(1, stokes_dim);
212  pm.SetZero();
213  }
214 
215  StokesVector abs_vec_local;
216  PropagationMatrix ext_mat_local;
217  Numeric rtp_temperature_local;
218 
219  // Calculate ext_mat, abs_vec for all points inside the cloudbox.
220  // sca_vec can be obtained from the workspace variable doit_scat_field.
221  // As we need the average for each layer, it makes sense to calculte
222  // the coefficients once and store them in an array instead of
223  // calculating at each point the coefficient of the point above and
224  // the point below.
225  // To use special interpolation functions for atmospheric fields we
226  // use ext_mat_field and abs_vec_field:
227 
228  // Loop over all positions inside the cloudbox defined by the
229  // cloudbox_limits.
230  for (Index scat_p_index_local = 0; scat_p_index_local < Np_cloud;
231  scat_p_index_local++) {
232  for (Index scat_lat_index_local = 0; scat_lat_index_local < Nlat_cloud;
233  scat_lat_index_local++) {
234  for (Index scat_lon_index_local = 0; scat_lon_index_local < Nlon_cloud;
235  scat_lon_index_local++) {
236  if (atmosphere_dim == 1)
237  rtp_temperature_local =
238  t_field(scat_p_index_local + cloudbox_limits[0], 0, 0);
239  else
240  rtp_temperature_local =
241  t_field(scat_p_index_local + cloudbox_limits[0],
242  scat_lat_index_local + cloudbox_limits[2],
243  scat_lon_index_local + cloudbox_limits[4]);
244 
245  //Calculate optical properties for individual scattering elements:
246  //( Execute agendas silently. )
248  ext_mat_spt_local,
249  abs_vec_spt_local,
250  scat_p_index_local,
251  scat_lat_index_local,
252  scat_lon_index_local,
253  rtp_temperature_local,
254  za_index,
255  aa_index,
256  spt_calc_agenda);
257  /*
258 // so far missing here (accessed through workspace within agenda):
259 // - scat_data
260 // - za_grid, aa_grid
261 // - f_index
262  opt_prop_sptFromScat_data(ext_mat_spt_local, abs_vec_spt_local,
263  scat_data, 1,
264  za_grid, aa_grid,
265  za_index, aa_index,
266  f_index,
267  rtp_temperature_local,
268  pnd_field,
269  scat_p_index_local,
270  scat_lat_index_local,
271  scat_lon_index_local,
272  verbosity);
273 */
274 
275  opt_prop_bulkCalc(ext_mat_local,
276  abs_vec_local,
277  ext_mat_spt_local,
278  abs_vec_spt_local,
279  pnd_field,
280  scat_p_index_local,
281  scat_lat_index_local,
282  scat_lon_index_local,
283  verbosity);
284 
285  // Store coefficients in arrays for the whole cloudbox.
286  abs_vec_field(scat_p_index_local,
287  scat_lat_index_local,
288  scat_lon_index_local,
289  joker) = abs_vec_local.VectorAtPosition();
290 
291  ext_mat_local.MatrixAtPosition(ext_mat_field(scat_p_index_local,
292  scat_lat_index_local,
293  scat_lon_index_local,
294  joker,
295  joker));
296  }
297  }
298  }
299 }
300 
302  // Input and output
303  Tensor6View cloudbox_field_mono,
304  // ppath_step_agenda:
305  const Index& p_index,
306  const Index& za_index,
307  ConstVectorView za_grid,
308  const ArrayOfIndex& cloudbox_limits,
309  ConstTensor6View doit_scat_field,
310  // Calculate scalar gas absorption:
311  const Agenda& propmat_clearsky_agenda,
312  ConstTensor4View vmr_field,
313  // Propagation path calculation:
314  const Agenda& ppath_step_agenda,
315  const Numeric& ppath_lmax,
316  const Numeric& ppath_lraytrace,
317  ConstVectorView p_grid,
318  ConstTensor3View z_field,
319  ConstVectorView refellipsoid,
320  // Calculate thermal emission:
321  ConstTensor3View t_field,
322  ConstVectorView f_grid,
323  const Index& f_index,
324  //particle optical properties
325  ConstTensor5View ext_mat_field,
326  ConstTensor4View abs_vec_field,
327  const Agenda& surface_rtprop_agenda,
328  //const Agenda& surface_rtprop_agenda,
329  const Index& scat_za_interp,
330  const Verbosity& verbosity) {
331  Ppath ppath_step;
332  // Input variables are checked in the WSMs i_fieldUpdateSeqXXX, from
333  // where this function is called.
334 
335  //Initialize ppath for 1D.
336  ppath_init_structure(ppath_step, 1, 1);
337  // See documentation of ppath_init_structure for understanding
338  // the parameters.
339 
340  // Assign value to ppath.pos:
341  ppath_step.pos(0, 0) = z_field(p_index, 0, 0);
342  ppath_step.r[0] = refellipsoid[0] + z_field(p_index, 0, 0);
343 
344  // Define the direction:
345  ppath_step.los(0, 0) = za_grid[za_index];
346 
347  // Define the grid positions:
348  ppath_step.gp_p[0].idx = p_index;
349  ppath_step.gp_p[0].fd[0] = 0;
350  ppath_step.gp_p[0].fd[1] = 1;
351 
352  // Call ppath_step_agenda:
354  ppath_step,
355  ppath_lmax,
356  ppath_lraytrace,
357  Vector(1, f_grid[f_index]),
358  ppath_step_agenda);
359 
360  // Check whether the next point is inside or outside the
361  // cloudbox. Only if the next point lies inside the
362  // cloudbox a radiative transfer step caclulation has to
363  // be performed.
364 
365  if ((cloudbox_limits[0] <= ppath_step.gp_p[1].idx &&
366  cloudbox_limits[1] > ppath_step.gp_p[1].idx) ||
367  (cloudbox_limits[1] == ppath_step.gp_p[1].idx &&
368  abs(ppath_step.gp_p[1].fd[0]) < 1e-6)) {
369  // Stokes dimension
370  const Index stokes_dim = cloudbox_field_mono.ncols();
371  // Number of species
372  const Index N_species = vmr_field.nbooks();
373 
374  // Ppath_step normally has 2 points, the starting
375  // point and the intersection point.
376  // But there can be points in between, when a maximum
377  // lstep is given. We have to interpolate on all the
378  // points in the ppath_step.
379 
380  // Initialize variables for interpolated values
381  Tensor3 ext_mat_int(stokes_dim, stokes_dim, ppath_step.np, 0.);
382  Matrix abs_vec_int(stokes_dim, ppath_step.np, 0.);
383  Matrix sca_vec_int(stokes_dim, ppath_step.np, 0.);
384  Matrix cloudbox_field_mono_int(stokes_dim, ppath_step.np, 0.);
385  Vector t_int(ppath_step.np, 0.);
386  Matrix vmr_list_int(N_species, ppath_step.np, 0.);
387  Vector p_int(ppath_step.np, 0.);
388 
389  interp_cloud_coeff1D(ext_mat_int,
390  abs_vec_int,
391  sca_vec_int,
392  cloudbox_field_mono_int,
393  t_int,
394  vmr_list_int,
395  p_int,
396  ext_mat_field,
397  abs_vec_field,
398  doit_scat_field,
399  cloudbox_field_mono,
400  t_field,
401  vmr_field,
402  p_grid,
403  ppath_step,
404  cloudbox_limits,
405  za_grid,
406  scat_za_interp,
407  verbosity);
408 
409  // ppath_what_background(ppath_step) tells the
410  // radiative background. More information in the
411  // function get_iy_of_background.
412  // if there is no background we proceed the RT
413  Index bkgr = ppath_what_background(ppath_step);
414 
415  // Radiative transfer from one layer to the next, starting
416  // at the intersection with the next layer and propagating
417  // to the considered point.
419  cloudbox_field_mono,
420  propmat_clearsky_agenda,
421  ppath_step,
422  t_int,
423  vmr_list_int,
424  ext_mat_int,
425  abs_vec_int,
426  sca_vec_int,
427  cloudbox_field_mono_int,
428  p_int,
429  cloudbox_limits,
430  f_grid,
431  f_index,
432  p_index,
433  0,
434  0,
435  za_index,
436  0,
437  verbosity);
438 
439  // bkgr=2 indicates that the background is the surface
440  if (bkgr == 2) {
441  // cout << "hit surface "<< ppath_step.gp_p << endl;
442  cloud_RT_surface(ws,
443  cloudbox_field_mono,
444  surface_rtprop_agenda,
445  f_grid,
446  f_index,
447  stokes_dim,
448  ppath_step,
449  cloudbox_limits,
450  za_grid,
451  za_index);
452  }
453 
454  } //end if inside cloudbox
455 }
456 
458  // Output
459  Tensor6View cloudbox_field_mono,
460  // ppath_step_agenda:
461  const Index& p_index,
462  const Index& za_index,
463  ConstVectorView za_grid,
464  const ArrayOfIndex& cloudbox_limits,
465  ConstTensor6View cloudbox_field_mono_old,
466  ConstTensor6View doit_scat_field,
467  // Calculate scalar gas absorption:
468  const Agenda& propmat_clearsky_agenda,
469  ConstTensor4View vmr_field,
470  // Propagation path calculation:
471  const Agenda& ppath_step_agenda,
472  const Numeric& ppath_lmax,
473  const Numeric& ppath_lraytrace,
474  ConstVectorView p_grid,
475  ConstTensor3View z_field,
476  ConstVectorView refellipsoid,
477  // Calculate thermal emission:
478  ConstTensor3View t_field,
479  ConstVectorView f_grid,
480  // used for surface ?
481  const Index& f_index,
482  //particle optical properties
483  ConstTensor5View ext_mat_field,
484  ConstTensor4View abs_vec_field,
485  const Agenda& surface_rtprop_agenda,
486  const Index& scat_za_interp,
487  const Verbosity& verbosity) {
488  Ppath ppath_step;
489  // Input variables are checked in the WSMs i_fieldUpdateSeqXXX, from
490  // where this function is called.
491 
492  //Initialize ppath for 1D.
493  ppath_init_structure(ppath_step, 1, 1);
494  // See documentation of ppath_init_structure for understanding
495  // the parameters.
496 
497  // Assign value to ppath.pos:
498  ppath_step.pos(0, 0) = z_field(p_index, 0, 0);
499  ppath_step.r[0] = refellipsoid[0] + z_field(p_index, 0, 0);
500 
501  // Define the direction:
502  ppath_step.los(0, 0) = za_grid[za_index];
503 
504  // Define the grid positions:
505  ppath_step.gp_p[0].idx = p_index;
506  ppath_step.gp_p[0].fd[0] = 0;
507  ppath_step.gp_p[0].fd[1] = 1;
508 
509  // Call ppath_step_agenda:
511  ppath_step,
512  ppath_lmax,
513  ppath_lraytrace,
514  Vector(1, f_grid[f_index]),
515  ppath_step_agenda);
516 
517  // Check whether the next point is inside or outside the
518  // cloudbox. Only if the next point lies inside the
519  // cloudbox a radiative transfer step caclulation has to
520  // be performed.
521 
522  if ((cloudbox_limits[0] <= ppath_step.gp_p[1].idx &&
523  cloudbox_limits[1] > ppath_step.gp_p[1].idx) ||
524  (cloudbox_limits[1] == ppath_step.gp_p[1].idx &&
525  abs(ppath_step.gp_p[1].fd[0]) < 1e-6)) {
526  // Stokes dimension
527  const Index stokes_dim = cloudbox_field_mono.ncols();
528  // Number of species
529  const Index N_species = vmr_field.nbooks();
530 
531  // Ppath_step normally has 2 points, the starting
532  // point and the intersection point.
533  // But there can be points in between, when a maximum
534  // lstep is given. We have to interpolate on all the
535  // points in the ppath_step.
536 
537  // Initialize variables for interpolated values
538  Tensor3 ext_mat_int(stokes_dim, stokes_dim, ppath_step.np, 0.);
539  Matrix abs_vec_int(stokes_dim, ppath_step.np, 0.);
540  Matrix sca_vec_int(stokes_dim, ppath_step.np, 0.);
541  Matrix cloudbox_field_mono_int(stokes_dim, ppath_step.np, 0.);
542  Vector t_int(ppath_step.np, 0.);
543  Matrix vmr_list_int(N_species, ppath_step.np, 0.);
544  Vector p_int(ppath_step.np, 0.);
545 
546  interp_cloud_coeff1D(ext_mat_int,
547  abs_vec_int,
548  sca_vec_int,
549  cloudbox_field_mono_int,
550  t_int,
551  vmr_list_int,
552  p_int,
553  ext_mat_field,
554  abs_vec_field,
555  doit_scat_field,
556  cloudbox_field_mono_old,
557  t_field,
558  vmr_field,
559  p_grid,
560  ppath_step,
561  cloudbox_limits,
562  za_grid,
563  scat_za_interp,
564  verbosity);
565 
566  // ppath_what_background(ppath_step) tells the
567  // radiative background. More information in the
568  // function get_iy_of_background.
569  // if there is no background we proceed the RT
570  Index bkgr = ppath_what_background(ppath_step);
571 
572  // if 0, there is no background
573  // do this in any case. cause we need downwelling cloudbox_field_mono
574  // at the surface for calculating surface scattering
575 
576  // Radiative transfer from one layer to the next, starting
577  // at the intersection with the next layer and propagating
578  // to the considered point.
580  cloudbox_field_mono,
581  propmat_clearsky_agenda,
582  ppath_step,
583  t_int,
584  vmr_list_int,
585  ext_mat_int,
586  abs_vec_int,
587  sca_vec_int,
588  cloudbox_field_mono_int,
589  p_int,
590  cloudbox_limits,
591  f_grid,
592  f_index,
593  p_index,
594  0,
595  0,
596  za_index,
597  0,
598  verbosity);
599 
600  if (bkgr == 2) {
601  cloud_RT_surface(ws,
602  cloudbox_field_mono,
603  surface_rtprop_agenda,
604  f_grid,
605  f_index,
606  stokes_dim,
607  ppath_step,
608  cloudbox_limits,
609  za_grid,
610  za_index);
611  }
612  } //end if inside cloudbox
613 }
614 
616  Tensor6View cloudbox_field_mono,
617  const Index& p_index,
618  const Index& za_index,
619  ConstVectorView za_grid,
620  const ArrayOfIndex& cloudbox_limits,
621  ConstTensor6View doit_scat_field,
622  // Calculate scalar gas absorption:
623  const Agenda& propmat_clearsky_agenda,
624  ConstTensor4View vmr_field,
625  // Propagation path calculation:
626  ConstVectorView p_grid,
627  ConstTensor3View z_field,
628  // Calculate thermal emission:
629  ConstTensor3View t_field,
630  ConstVectorView f_grid,
631  const Index& f_index,
632  //particle opticla properties
633  ConstTensor5View ext_mat_field,
634  ConstTensor4View abs_vec_field,
635  const Verbosity& verbosity) {
636  CREATE_OUT3;
637 
638  const Index N_species = vmr_field.nbooks();
639  const Index stokes_dim = cloudbox_field_mono.ncols();
640  const Index atmosphere_dim = 1;
641  ArrayOfPropagationMatrix propmat_clearsky;
642  PropagationMatrix ext_mat;
643  StokesVector abs_vec;
644  Matrix matrix_tmp(stokes_dim, stokes_dim);
645  Vector vector_tmp(stokes_dim);
646  Vector rtp_vmr(N_species, 0.);
647  EnergyLevelMap rtp_nlte_dummy;
648  Vector sca_vec_av(stokes_dim, 0);
649 
650  // Radiative transfer from one layer to the next, starting
651  // at the intersection with the next layer and propagating
652  // to the considered point.
653  Vector stokes_vec(stokes_dim);
654  Index bkgr;
655  if ((p_index == 0) && (za_grid[za_index] > 90)) {
656  bkgr = 2;
657  } else {
658  bkgr = 0;
659  }
660 
661  // if 0, there is no background
662  if (bkgr == 0) {
663  if (za_grid[za_index] <= 90.0) {
664  stokes_vec = cloudbox_field_mono(
665  p_index - cloudbox_limits[0] + 1, 0, 0, za_index, 0, joker);
666  Numeric z_field_above = z_field(p_index + 1, 0, 0);
667  Numeric z_field_0 = z_field(p_index, 0, 0);
668 
669  Numeric cos_theta, lstep;
670  if (za_grid[za_index] == 90.0) {
671  //cos_theta = cos((za_grid[za_index] -1)*PI/180.);
672  // cos_theta = cos(89.999999999999*PI/180.);
673  cos_theta = 1e-20;
674 
675  } else {
676  cos_theta = cos(za_grid[za_index] * PI / 180.0);
677  }
678  Numeric dz = (z_field_above - z_field_0);
679 
680  lstep = abs(dz / cos_theta);
681 
682  // Average temperature
683  Numeric rtp_temperature =
684  0.5 * (t_field(p_index, 0, 0) + t_field(p_index + 1, 0, 0));
685  //
686  // Average pressure
687  Numeric rtp_pressure = 0.5 * (p_grid[p_index] + p_grid[p_index + 1]);
688 
689  // Average vmrs
690  for (Index j = 0; j < N_species; j++)
691  rtp_vmr[j] = 0.5 * (vmr_field(j, p_index, 0, 0) +
692  vmr_field(j, p_index + 1, 0, 0));
693  //
694  // Calculate scalar gas absorption and add it to abs_vec
695  // and ext_mat.
696  //
697 
698  const Vector rtp_mag_dummy(3, 0);
699  const Vector ppath_los_dummy;
700 
701  ArrayOfStokesVector nlte_dummy; //FIXME: do this right?
703  partial_dummy; // This is right since there should be only clearsky partials
704  ArrayOfStokesVector partial_source_dummy,
705  partial_nlte_dummy; // This is right since there should be only clearsky partials
707  propmat_clearsky,
708  nlte_dummy,
709  partial_dummy,
710  partial_source_dummy,
711  partial_nlte_dummy,
713  f_grid[Range(f_index, 1)],
714  rtp_mag_dummy,
715  ppath_los_dummy,
716  rtp_pressure,
717  rtp_temperature,
718  rtp_nlte_dummy,
719  rtp_vmr,
720  propmat_clearsky_agenda);
721 
722  opt_prop_sum_propmat_clearsky(ext_mat, abs_vec, propmat_clearsky);
723 
724  for (Index k = 0; k < stokes_dim; k++) {
725  //
726  // Averaging of sca_vec:
727  //
728  sca_vec_av[k] +=
729  0.5 *
730  (doit_scat_field(
731  p_index - cloudbox_limits[0], 0, 0, za_index, 0, k) +
732  doit_scat_field(
733  p_index - cloudbox_limits[0] + 1, 0, 0, za_index, 0, k));
734  }
735 
736  //
737  // Add average particle absorption to abs_vec.
738  //
739  abs_vec.AddAverageAtPosition(
740  abs_vec_field(p_index - cloudbox_limits[0], 0, 0, joker),
741  abs_vec_field(p_index - cloudbox_limits[0] + 1, 0, 0, joker));
742 
743  //
744  // Add average particle extinction to ext_mat.
745  ext_mat.AddAverageAtPosition(
746  ext_mat_field(p_index - cloudbox_limits[0], 0, 0, joker, joker),
747  ext_mat_field(p_index - cloudbox_limits[0] + 1, 0, 0, joker, joker));
748 
749  // Frequency
750  Numeric f = f_grid[f_index];
751  //
752  // Calculate Planck function
753  //
754  Numeric rte_planck_value = planck(f, rtp_temperature);
755 
756  // Some messages:
757  if (out3.sufficient_priority()) {
758  vector_tmp = abs_vec.VectorAtPosition();
759  ext_mat.MatrixAtPosition(matrix_tmp);
760  out3 << "-----------------------------------------\n";
761  out3 << "Input for radiative transfer step \n"
762  << "calculation inside"
763  << " the cloudbox:"
764  << "\n";
765  out3 << "Stokes vector at intersection point: \n" << stokes_vec << "\n";
766  out3 << "lstep: ..." << lstep << "\n";
767  out3 << "------------------------------------------\n";
768  out3 << "Averaged coefficients: \n";
769  out3 << "Planck function: " << rte_planck_value << "\n";
770  out3 << "Scattering vector: " << sca_vec_av << "\n";
771  out3 << "Absorption vector: " << vector_tmp << "\n";
772  out3 << "Extinction matrix: " << matrix_tmp << "\n";
773 
774  assert(!is_singular(matrix_tmp));
775  }
776 
777  // Radiative transfer step calculation. The Stokes vector
778  // is updated until the considered point is reached.
779  rte_step_doit_replacement(stokes_vec,
780  Matrix(stokes_dim, stokes_dim),
781  ext_mat,
782  abs_vec,
783  sca_vec_av,
784  lstep,
785  rte_planck_value);
786 
787  // Assign calculated Stokes Vector to cloudbox_field_mono.
788  cloudbox_field_mono(
789  p_index - cloudbox_limits[0], 0, 0, za_index, 0, joker) =
790  stokes_vec;
791  }
792  if (za_grid[za_index] > 90) {
793  stokes_vec = cloudbox_field_mono(
794  p_index - cloudbox_limits[0] - 1, 0, 0, za_index, 0, joker);
795  Numeric z_field_below = z_field(p_index - 1, 0, 0);
796  Numeric z_field_0 = z_field(p_index, 0, 0);
797 
798  Numeric cos_theta, lstep;
799  if (za_grid[za_index] == 90.0) {
800  cos_theta = cos((za_grid[za_index] - 1) * PI / 180.);
801  //cos_theta = cos(90.00000001*PI/180.);
802  //cout<<"cos_theta"<<cos_theta<<endl;
803  } else {
804  cos_theta = cos(za_grid[za_index] * PI / 180.0);
805  }
806  Numeric dz = (z_field_0 - z_field_below);
807  lstep = abs(dz / cos_theta);
808 
809  // Average temperature
810  Numeric rtp_temperature =
811  0.5 * (t_field(p_index, 0, 0) + t_field(p_index - 1, 0, 0));
812  //
813  // Average pressure
814  Numeric rtp_pressure = 0.5 * (p_grid[p_index] + p_grid[p_index - 1]);
815 
816  //
817  // Average vmrs
818  for (Index k = 0; k < N_species; k++)
819  rtp_vmr[k] = 0.5 * (vmr_field(k, p_index, 0, 0) +
820  vmr_field(k, p_index - 1, 0, 0));
821  //
822  // Calculate scalar gas absorption and add it to abs_vec
823  // and ext_mat.
824  //
825 
826  const Vector rtp_mag_dummy(3, 0);
827  const Vector ppath_los_dummy;
828  ArrayOfStokesVector nlte_dummy; //FIXME: do this right?
830  partial_dummy; // This is right since there should be only clearsky partials
831  ArrayOfStokesVector partial_source_dummy,
832  partial_nlte_dummy; // This is right since there should be only clearsky partials
834  propmat_clearsky,
835  nlte_dummy,
836  partial_dummy,
837  partial_source_dummy,
838  partial_nlte_dummy,
840  f_grid[Range(f_index, 1)],
841  rtp_mag_dummy,
842  ppath_los_dummy,
843  rtp_pressure,
844  rtp_temperature,
845  rtp_nlte_dummy,
846  rtp_vmr,
847  propmat_clearsky_agenda);
848 
849  opt_prop_sum_propmat_clearsky(ext_mat, abs_vec, propmat_clearsky);
850 
851  //
852  // Add average particle extinction to ext_mat.
853  //
854 
855  // cout<<"cloudbox_limits[1]"<<cloudbox_limits[1]<<endl;
856  // cout<<"p_index - cloudbox_limits[0]"<<p_index - cloudbox_limits[0]<<endl;
857  for (Index k = 0; k < stokes_dim; k++) {
858  //
859  // Averaging of sca_vec:
860  //
861  sca_vec_av[k] +=
862  0.5 *
863  (doit_scat_field(
864  p_index - cloudbox_limits[0], 0, 0, za_index, 0, k) +
865  doit_scat_field(
866  p_index - cloudbox_limits[0] - 1, 0, 0, za_index, 0, k));
867  }
868  //
869  // Add average particle absorption to abs_vec.
870  //
871  abs_vec.AddAverageAtPosition(
872  abs_vec_field(p_index - cloudbox_limits[0], 0, 0, joker),
873  abs_vec_field(p_index - cloudbox_limits[0] - 1, 0, 0, joker));
874 
875  //
876  // Add average particle extinction to ext_mat.
877  ext_mat.AddAverageAtPosition(
878  ext_mat_field(p_index - cloudbox_limits[0], 0, 0, joker, joker),
879  ext_mat_field(p_index - cloudbox_limits[0] + 1, 0, 0, joker, joker));
880 
881  // Frequency
882  Numeric f = f_grid[f_index];
883  //
884  // Calculate Planck function
885  //
886  Numeric rte_planck_value = planck(f, rtp_temperature);
887 
888  // Some messages:
889  if (out3.sufficient_priority()) {
890  vector_tmp = abs_vec.VectorAtPosition();
891  ext_mat.MatrixAtPosition(matrix_tmp);
892  out3 << "-----------------------------------------\n";
893  out3 << "Input for radiative transfer step \n"
894  << "calculation inside"
895  << " the cloudbox:"
896  << "\n";
897  out3 << "Stokes vector at intersection point: \n" << stokes_vec << "\n";
898  out3 << "lstep: ..." << lstep << "\n";
899  out3 << "------------------------------------------\n";
900  out3 << "Averaged coefficients: \n";
901  out3 << "Planck function: " << rte_planck_value << "\n";
902  out3 << "Scattering vector: " << sca_vec_av << "\n";
903  out3 << "Absorption vector: " << vector_tmp << "\n";
904  out3 << "Extinction matrix: " << matrix_tmp << "\n";
905 
906  assert(!is_singular(matrix_tmp));
907  }
908 
909  // Radiative transfer step calculation. The Stokes vector
910  // is updated until the considered point is reached.
911  rte_step_doit_replacement(stokes_vec,
912  Matrix(stokes_dim, stokes_dim),
913  ext_mat,
914  abs_vec,
915  sca_vec_av,
916  lstep,
917  rte_planck_value);
918 
919  // Assign calculated Stokes Vector to cloudbox_field_mono.
920  cloudbox_field_mono(
921  p_index - cloudbox_limits[0], 0, 0, za_index, 0, joker) =
922  stokes_vec;
923  }
924 
925  } // if loop end - for non_ground background
926 
927  // bkgr=2 indicates that the background is the surface
928  else if (bkgr == 2) {
929  //Set rte_pos, rte_gp_p and rte_los to match the last point
930  //in ppath.
931  //pos
932  Vector rte_pos(atmosphere_dim);
933  Numeric z_field_0 = z_field(0, 0, 0);
934  rte_pos = z_field_0; //ppath_step.pos(np-1,Range(0,atmosphere_dim));
935  //los
936  Vector rte_los(1);
937  rte_los = za_grid[za_index]; //ppath_step.los(np-1,joker);
938  //gp_p
939  //GridPos rte_gp_p;
940  //rte_gp_p.idx = p_index;
941  //rte_gp_p.fd[0] = 0;
942  //rte_gp_p.fd[1] = 1;
943  //gridpos_copy( rte_gp_p, ppath_step.gp_p[np-1] );
944  // Executes the surface agenda
945  // FIXME: Convert to new agenda scheme before using
946  // surface_rtprop_agenda.execute();
947 
948  throw runtime_error(
949  "Surface reflections inside cloud box not yet handled.");
950  /*
951  See comment in function above
952  // Check returned variables
953  if( surface_emission.nrows() != f_grid.nelem() ||
954  surface_emission.ncols() != stokes_dim )
955  throw runtime_error(
956  "The size of the created *surface_emission* is not correct.");
957 
958  Index nlos = surface_los.nrows();
959 
960  // Define a local vector cloudbox_field_mono_sum which adds the
961  // products of groudnd_refl_coeffs with the downwelling
962  // radiation for each elements of surface_los
963  Vector cloudbox_field_mono_sum(stokes_dim,0);
964  // Loop over the surface_los elements
965  for( Index ilos=0; ilos < nlos; ilos++ )
966  {
967  if( stokes_dim == 1 )
968  {
969  cloudbox_field_mono_sum[0] += surface_refl_coeffs(ilos,f_index,0,0) *
970  cloudbox_field_mono(cloudbox_limits[0],
971  0, 0,
972  (za_grid.nelem() -1 - za_index), 0,
973  0);
974  }
975  else
976  {
977  Vector stokes_vec2(stokes_dim);
978  mult( stokes_vec2,
979  surface_refl_coeffs(ilos,0,joker,joker),
980  cloudbox_field_mono(cloudbox_limits[0],
981  0, 0,
982  (za_grid.nelem() -1 - za_index), 0,
983  joker));
984  for( Index is=0; is < stokes_dim; is++ )
985  {
986  cloudbox_field_mono_sum[is] += stokes_vec2[is];
987  }
988 
989  }
990  }
991  // Copy from *cloudbox_field_mono_sum* to *cloudbox_field_mono*, and add the surface emission
992  for( Index is=0; is < stokes_dim; is++ )
993  {
994  cloudbox_field_mono (cloudbox_limits[0],
995  0, 0,
996  za_index, 0,
997  is) = cloudbox_field_mono_sum[is] + surface_emission(f_index,is);
998  }
999 
1000  //cout<<"za_grid"<<za_grid[za_index]<<endl;
1001  //cout<<"p_index"<<p_index<<endl;
1002  //cout<<"cloudboxlimit[0]"<<cloudbox_limits[0]<<endl;
1003  // now the RT is done to the next point in the path.
1004  //
1005  Vector stokes_vec_local;
1006  stokes_vec_local = cloudbox_field_mono (0,
1007  0, 0,
1008  za_index, 0,
1009  joker);
1010 
1011  Numeric z_field_above = z_field(p_index +1, 0, 0);
1012  //Numeric z_field_0 = z_field(p_index, 0, 0);
1013  Numeric cos_theta;
1014  if (za_grid[za_index] == 90.0)
1015  {
1016  //cos_theta = cos((za_grid[za_index] -1)*PI/180.);
1017  cos_theta = cos(90.00000001*PI/180.);
1018  }
1019  else
1020  {
1021  cos_theta = cos(za_grid[za_index]* PI/180.0);
1022  }
1023  Numeric dz = (z_field_above - z_field_0);
1024 
1025  Numeric lstep = abs(dz/cos_theta) ;
1026 
1027  // Average temperature
1028  Numeric rtp_temperature = 0.5 * (t_field(p_index,0,0)
1029  + t_field(p_index + 1,0,0));
1030 
1031  //
1032  // Average pressure
1033  Numeric rtp_pressure = 0.5 * (p_grid[p_index]
1034  + p_grid[p_index + 1]);
1035 
1036  //
1037  const Index N_species = vmr_field.nbooks();
1038  // Average vmrs
1039  for (Index k = 0; k < N_species; k++)
1040  {
1041  rtp_vmr[k] = 0.5 * (vmr_field(k,p_index,0,0) +
1042  vmr_field(k,p_index + 1,0,0));
1043  }
1044  //
1045  // Calculate scalar gas absorption and add it to abs_vec
1046  // and ext_mat.
1047  //
1048 
1049  // FIXME: Convert to new agenda scheme before using
1050  //abs_scalar_gas_agenda.execute(p_index);
1051 
1052  opt_prop_gas_agendaExecute(ext_mat, abs_vec, abs_scalar_gas,
1053  opt_prop_gas_agenda);
1054 
1055  //
1056  // Add average particle extinction to ext_mat.
1057  //
1058  //cout<<"Reached Here ????????????????????????????????????????????????";
1059  for (Index k = 0; k < stokes_dim; k++)
1060  {
1061  for (Index j = 0; j < stokes_dim; j++)
1062  {
1063  ext_mat(0,k,j) += 0.5 *
1064  (ext_mat_field(p_index - cloudbox_limits[0],0,0,k,j) +
1065  ext_mat_field(p_index - cloudbox_limits[0]+ 1,0,0,k,j));
1066  }
1067 
1068 
1069  //
1070  //
1071  // Add average particle absorption to abs_vec.
1072  //
1073  abs_vec(0,k) += 0.5 *
1074  (abs_vec_field(p_index - cloudbox_limits[0],0,0,k) +
1075  abs_vec_field(p_index - cloudbox_limits[0]+1,0,0,k));
1076  //
1077  // Averaging of sca_vec:
1078  //
1079  sca_vec_av[k] = 0.5*( doit_scat_field(p_index- cloudbox_limits[0],
1080  0, 0, za_index, 0, k)
1081  + doit_scat_field(p_index- cloudbox_limits[0]+1,
1082  0, 0, za_index, 0, k)) ;
1083 
1084  }
1085  // Frequency
1086  Numeric f = f_grid[f_index];
1087  //
1088  // Calculate Planck function
1089  //
1090  Numeric rte_planck_value = planck(f, rtp_temperature);
1091 
1092  assert (!is_singular( ext_mat(0,joker,joker)));
1093 
1094  // Radiative transfer step calculation. The Stokes vector
1095  // is updated until the considered point is reached.
1096  rte_step_doit(stokes_vec_local, ext_mat(0,joker,joker),
1097  abs_vec(0,joker),
1098  sca_vec_av, lstep, rte_planck_value);
1099  // Assign calculated Stokes Vector to cloudbox_field_mono.
1100  cloudbox_field_mono(p_index - cloudbox_limits[0],
1101  0, 0,
1102  za_index, 0,
1103  joker) = stokes_vec_local;
1104  */
1105  } //end else loop over surface
1106 }
1107 
1109  Tensor6View cloudbox_field_mono,
1110  // ppath_step_agenda:
1111  const Index& p_index,
1112  const Index& lat_index,
1113  const Index& lon_index,
1114  const Index& za_index,
1115  const Index& aa_index,
1116  ConstVectorView za_grid,
1117  ConstVectorView aa_grid,
1118  const ArrayOfIndex& cloudbox_limits,
1119  ConstTensor6View doit_scat_field,
1120  // Calculate scalar gas absorption:
1121  const Agenda& propmat_clearsky_agenda,
1122  ConstTensor4View vmr_field,
1123  // Propagation path calculation:
1124  const Agenda& ppath_step_agenda,
1125  const Numeric& ppath_lmax,
1126  const Numeric& ppath_lraytrace,
1127  ConstVectorView p_grid,
1128  ConstVectorView lat_grid,
1129  ConstVectorView lon_grid,
1130  ConstTensor3View z_field,
1131  ConstVectorView refellipsoid,
1132  // Calculate thermal emission:
1133  ConstTensor3View t_field,
1134  ConstVectorView f_grid,
1135  const Index& f_index,
1136  //particle optical properties
1137  ConstTensor5View ext_mat_field,
1138  ConstTensor4View abs_vec_field,
1139  const Index&, //scat_za_interp
1140  const Verbosity& verbosity) {
1141  CREATE_OUT3;
1142 
1143  Ppath ppath_step;
1144  const Index stokes_dim = cloudbox_field_mono.ncols();
1145 
1146  Vector sca_vec_av(stokes_dim, 0);
1147  Vector aa_g(aa_grid.nelem());
1148 
1149  for (Index i = 0; i < aa_grid.nelem(); i++)
1150  aa_g[i] = aa_grid[i] - 180.;
1151 
1152  //Initialize ppath for 3D.
1153  ppath_init_structure(ppath_step, 3, 1);
1154  // See documentation of ppath_init_structure for
1155  // understanding the parameters.
1156 
1157  // The first dimension of pos are the points in
1158  // the propagation path.
1159  // Here we initialize the first point.
1160  // The second is: radius, latitude, longitude
1161 
1162  ppath_step.pos(0, 2) = lon_grid[lon_index];
1163  ppath_step.pos(0, 1) = lat_grid[lat_index];
1164  ppath_step.pos(0, 0) = z_field(p_index, lat_index, lon_index);
1165  // As always on top of the lat. grid positions, OK to call refell2r:
1166  ppath_step.r[0] =
1167  refell2r(refellipsoid, ppath_step.pos(0, 1)) + ppath_step.pos(0, 0);
1168 
1169  // Define the direction:
1170  ppath_step.los(0, 0) = za_grid[za_index];
1171  ppath_step.los(0, 1) = aa_g[aa_index];
1172 
1173  // Define the grid positions:
1174  ppath_step.gp_p[0].idx = p_index;
1175  ppath_step.gp_p[0].fd[0] = 0.;
1176  ppath_step.gp_p[0].fd[1] = 1.;
1177 
1178  ppath_step.gp_lat[0].idx = lat_index;
1179  ppath_step.gp_lat[0].fd[0] = 0.;
1180  ppath_step.gp_lat[0].fd[1] = 1.;
1181 
1182  ppath_step.gp_lon[0].idx = lon_index;
1183  ppath_step.gp_lon[0].fd[0] = 0.;
1184  ppath_step.gp_lon[0].fd[1] = 1.;
1185 
1186  // Call ppath_step_agenda:
1188  ppath_step,
1189  ppath_lmax,
1190  ppath_lraytrace,
1191  Vector(1, f_grid[f_index]),
1192  ppath_step_agenda);
1193 
1194  // Check whether the next point is inside or outside the
1195  // cloudbox. Only if the next point lies inside the
1196  // cloudbox a radiative transfer step caclulation has to
1197  // be performed.
1198  if (is_inside_cloudbox(ppath_step, cloudbox_limits, true)) {
1199  // Gridpositions inside the cloudbox.
1200  // The optical properties are stored only inside the
1201  // cloudbox. For interpolation we use grids
1202  // inside the cloudbox.
1203 
1204  ArrayOfGridPos cloud_gp_p = ppath_step.gp_p;
1205  ArrayOfGridPos cloud_gp_lat = ppath_step.gp_lat;
1206  ArrayOfGridPos cloud_gp_lon = ppath_step.gp_lon;
1207 
1208  for (Index i = 0; i < ppath_step.np; i++) {
1209  cloud_gp_p[i].idx -= cloudbox_limits[0];
1210  cloud_gp_lat[i].idx -= cloudbox_limits[2];
1211  cloud_gp_lon[i].idx -= cloudbox_limits[4];
1212  }
1213  const Index n1 = cloudbox_limits[1] - cloudbox_limits[0];
1214  const Index n2 = cloudbox_limits[3] - cloudbox_limits[2];
1215  const Index n3 = cloudbox_limits[5] - cloudbox_limits[4];
1216  gridpos_upperend_check(cloud_gp_p[0], n1);
1217  gridpos_upperend_check(cloud_gp_p[ppath_step.np - 1], n1);
1218  gridpos_upperend_check(cloud_gp_lat[0], n2);
1219  gridpos_upperend_check(cloud_gp_lat[ppath_step.np - 1], n2);
1220  gridpos_upperend_check(cloud_gp_lon[0], n3);
1221  gridpos_upperend_check(cloud_gp_lon[ppath_step.np - 1], n3);
1222 
1223  Matrix itw(ppath_step.np, 8);
1224  interpweights(itw, cloud_gp_p, cloud_gp_lat, cloud_gp_lon);
1225 
1226  Matrix itw_p(ppath_step.np, 2);
1227  interpweights(itw_p, cloud_gp_p);
1228 
1229  // The zenith angles and azimuth of the propagation path are
1230  // needed as we have to
1231  // interpolate the intensity field and the scattered field on the
1232  // right angles.
1233  VectorView los_grid_za = ppath_step.los(joker, 0);
1234  VectorView los_grid_aa = ppath_step.los(joker, 1);
1235 
1236  for (Index i = 0; i < los_grid_aa.nelem(); i++)
1237  los_grid_aa[i] = los_grid_aa[i] + 180.;
1238 
1239  ArrayOfGridPos gp_za(los_grid_za.nelem());
1240  gridpos(gp_za, za_grid, los_grid_za);
1241 
1242  ArrayOfGridPos gp_aa(los_grid_aa.nelem());
1243  gridpos(gp_aa, aa_grid, los_grid_aa);
1244 
1245  Matrix itw_p_za(ppath_step.np, 32);
1246  interpweights(
1247  itw_p_za, cloud_gp_p, cloud_gp_lat, cloud_gp_lon, gp_za, gp_aa);
1248 
1249  // Ppath_step normally has 2 points, the starting
1250  // point and the intersection point.
1251  // But there can be points in between, when a maximum
1252  // lstep is given. We have to interpolate on all the
1253  // points in the ppath_step.
1254 
1255  Tensor3 ext_mat_int(stokes_dim, stokes_dim, ppath_step.np);
1256  Matrix abs_vec_int(stokes_dim, ppath_step.np);
1257  Matrix sca_vec_int(stokes_dim, ppath_step.np, 0.);
1258  Matrix cloudbox_field_mono_int(stokes_dim, ppath_step.np, 0.);
1259  Vector t_int(ppath_step.np);
1260  Vector vmr_int(ppath_step.np);
1261  Vector p_int(ppath_step.np);
1262  Vector stokes_vec(stokes_dim);
1263  //Tensor3 ext_mat_gas(stokes_dim, stokes_dim, ppath_step.np);
1264  //Matrix abs_vec_gas(stokes_dim, ppath_step.np);
1265 
1266  // Calculate the average of the coefficients for the layers
1267  // to be considered in the
1268  // radiative transfer calculation.
1269 
1270  for (Index i = 0; i < stokes_dim; i++) {
1271  // Extinction matrix requires a second loop
1272  // over stokes_dim
1273  out3 << "Interpolate ext_mat:\n";
1274  for (Index j = 0; j < stokes_dim; j++) {
1275  //
1276  // Interpolation of ext_mat
1277  //
1278  interp(ext_mat_int(i, j, joker),
1279  itw,
1280  ext_mat_field(joker, joker, joker, i, j),
1281  cloud_gp_p,
1282  cloud_gp_lat,
1283  cloud_gp_lon);
1284  }
1285  // Absorption vector:
1286  //
1287  // Interpolation of abs_vec
1288  //
1289  interp(abs_vec_int(i, joker),
1290  itw,
1291  abs_vec_field(joker, joker, joker, i),
1292  cloud_gp_p,
1293  cloud_gp_lat,
1294  cloud_gp_lon);
1295  //
1296  // Scattered field:
1297  //
1298  // Interpolation of sca_vec:
1299  //
1300  out3 << "Interpolate doit_scat_field:\n";
1301  interp(sca_vec_int(i, joker),
1302  itw_p_za,
1303  doit_scat_field(joker, joker, joker, joker, joker, i),
1304  cloud_gp_p,
1305  cloud_gp_lat,
1306  cloud_gp_lon,
1307  gp_za,
1308  gp_aa);
1309  out3 << "Interpolate cloudbox_field_mono:\n";
1310  interp(cloudbox_field_mono_int(i, joker),
1311  itw_p_za,
1312  cloudbox_field_mono(joker, joker, joker, joker, joker, i),
1313  cloud_gp_p,
1314  cloud_gp_lat,
1315  cloud_gp_lon,
1316  gp_za,
1317  gp_aa);
1318  }
1319  //
1320  // Planck function
1321  //
1322  // Interpolate temperature field
1323  //
1324  out3 << "Interpolate temperature field\n";
1325  interp(t_int,
1326  itw,
1327  t_field(joker, joker, joker),
1328  ppath_step.gp_p,
1329  ppath_step.gp_lat,
1330  ppath_step.gp_lon);
1331 
1332  //
1333  // The vmr_field is needed for the gaseous absorption
1334  // calculation.
1335  //
1336  const Index N_species = vmr_field.nbooks();
1337  //
1338  // Interpolated vmr_list, holds a vmr_list for each point in
1339  // ppath_step.
1340  //
1341  Matrix vmr_list_int(N_species, ppath_step.np);
1342 
1343  for (Index i = 0; i < N_species; i++) {
1344  out3 << "Interpolate vmr field\n";
1345  interp(vmr_int,
1346  itw,
1347  vmr_field(i, joker, joker, joker),
1348  ppath_step.gp_p,
1349  ppath_step.gp_lat,
1350  ppath_step.gp_lon);
1351 
1352  vmr_list_int(i, joker) = vmr_int;
1353  }
1354 
1355  // Presssure (needed for the calculation of gas absorption)
1356  itw2p(p_int, p_grid, ppath_step.gp_p, itw_p);
1357 
1358  out3 << "Calculate radiative transfer inside cloudbox.\n";
1360  cloudbox_field_mono,
1361  propmat_clearsky_agenda,
1362  ppath_step,
1363  t_int,
1364  vmr_list_int,
1365  ext_mat_int,
1366  abs_vec_int,
1367  sca_vec_int,
1368  cloudbox_field_mono_int,
1369  p_int,
1370  cloudbox_limits,
1371  f_grid,
1372  f_index,
1373  p_index,
1374  lat_index,
1375  lon_index,
1376  za_index,
1377  aa_index,
1378  verbosity);
1379  } //end if inside cloudbox
1380 }
1381 
1383  //Output
1384  Tensor6View cloudbox_field_mono,
1385  // Input
1386  const Agenda& propmat_clearsky_agenda,
1387  const Ppath& ppath_step,
1388  ConstVectorView t_int,
1389  ConstMatrixView vmr_list_int,
1390  ConstTensor3View ext_mat_int,
1391  ConstMatrixView abs_vec_int,
1392  ConstMatrixView sca_vec_int,
1393  ConstMatrixView cloudbox_field_mono_int,
1394  ConstVectorView p_int,
1395  const ArrayOfIndex& cloudbox_limits,
1396  ConstVectorView f_grid,
1397  const Index& f_index,
1398  const Index& p_index,
1399  const Index& lat_index,
1400  const Index& lon_index,
1401  const Index& za_index,
1402  const Index& aa_index,
1403  const Verbosity& verbosity) {
1404  CREATE_OUT3;
1405 
1406  const Index N_species = vmr_list_int.nrows();
1407  const Index stokes_dim = cloudbox_field_mono.ncols();
1408  const Index atmosphere_dim = cloudbox_limits.nelem() / 2;
1409 
1410  Vector sca_vec_av(stokes_dim, 0);
1411  Vector stokes_vec(stokes_dim, 0.);
1412  EnergyLevelMap rtp_nlte_dummy;
1413  Vector rtp_vmr_local(N_species, 0.);
1414 
1415  // Two propmat_clearsky to average between
1416  ArrayOfPropagationMatrix cur_propmat_clearsky;
1417  ArrayOfPropagationMatrix prev_propmat_clearsky;
1418 
1419  PropagationMatrix ext_mat_local;
1420  StokesVector abs_vec_local;
1421  Matrix matrix_tmp(stokes_dim, stokes_dim);
1422  Vector vector_tmp(stokes_dim);
1423 
1424  // Incoming stokes vector
1425  stokes_vec = cloudbox_field_mono_int(joker, ppath_step.np - 1);
1426 
1427  for (Index k = ppath_step.np - 1; k >= 0; k--) {
1428  // Save propmat_clearsky from previous level by
1429  // swapping it with current level
1430  std::swap(cur_propmat_clearsky, prev_propmat_clearsky);
1431 
1432  //
1433  // Calculate scalar gas absorption
1434  //
1435  const Vector rtp_mag_dummy(3, 0);
1436  const Vector ppath_los_dummy;
1437 
1438  ArrayOfStokesVector nlte_dummy; //FIXME: do this right?
1440  partial_dummy; // This is right since there should be only clearsky partials
1441  ArrayOfStokesVector partial_source_dummy,
1442  partial_nlte_dummy; // This is right since there should be only clearsky partials
1444  cur_propmat_clearsky,
1445  nlte_dummy,
1446  partial_dummy,
1447  partial_source_dummy,
1448  partial_nlte_dummy,
1450  f_grid[Range(f_index, 1)],
1451  rtp_mag_dummy,
1452  ppath_los_dummy,
1453  p_int[k],
1454  t_int[k],
1455  rtp_nlte_dummy,
1456  vmr_list_int(joker, k),
1457  propmat_clearsky_agenda);
1458 
1459  // Skip any further calculations for the first point.
1460  // We need values at two ppath points before we can average.
1461  if (k == ppath_step.np - 1) continue;
1462 
1463  // Average prev_propmat_clearsky with cur_propmat_clearsky
1464  for (Index i = 0; i < prev_propmat_clearsky.nelem(); i++) {
1465  prev_propmat_clearsky[i] += cur_propmat_clearsky[i];
1466  prev_propmat_clearsky[i] *= 0.5;
1467  }
1468 
1470  ext_mat_local, abs_vec_local, prev_propmat_clearsky);
1471 
1472  for (Index i = 0; i < stokes_dim; i++) {
1473  //
1474  // Averaging of sca_vec:
1475  //
1476  sca_vec_av[i] = 0.5 * (sca_vec_int(i, k) + sca_vec_int(i, k + 1));
1477  }
1478 
1479  //
1480  // Add average particle absorption to abs_vec.
1481  //
1482  abs_vec_local.AddAverageAtPosition(abs_vec_int(joker, k),
1483  abs_vec_int(joker, k + 1));
1484 
1485  //
1486  // Add average particle extinction to ext_mat.
1487  //
1488  ext_mat_local.AddAverageAtPosition(ext_mat_int(joker, joker, k),
1489  ext_mat_int(joker, joker, k + 1));
1490 
1491  // Frequency
1492  Numeric f = f_grid[f_index];
1493  //
1494  // Calculate Planck function
1495  //
1496  Numeric rte_planck_value = planck(f, 0.5 * (t_int[k] + t_int[k + 1]));
1497 
1498  // Length of the path between the two layers.
1499  Numeric lstep = ppath_step.lstep[k];
1500 
1501  // Some messages:
1502  if (out3.sufficient_priority()) {
1503  vector_tmp = abs_vec_local.VectorAtPosition();
1504  ext_mat_local.MatrixAtPosition(matrix_tmp);
1505  out3 << "-----------------------------------------\n";
1506  out3 << "Input for radiative transfer step \n"
1507  << "calculation inside"
1508  << " the cloudbox:"
1509  << "\n";
1510  out3 << "Stokes vector at intersection point: \n" << stokes_vec << "\n";
1511  out3 << "lstep: ..." << lstep << "\n";
1512  out3 << "------------------------------------------\n";
1513  out3 << "Averaged coefficients: \n";
1514  out3 << "Planck function: " << rte_planck_value << "\n";
1515  out3 << "Scattering vector: " << sca_vec_av << "\n";
1516  out3 << "Absorption vector: " << vector_tmp << "\n";
1517  out3 << "Extinction matrix: " << matrix_tmp << "\n";
1518 
1519  assert(!is_singular(matrix_tmp));
1520  }
1521 
1522  // Radiative transfer step calculation. The Stokes vector
1523  // is updated until the considered point is reached.
1524  rte_step_doit_replacement(stokes_vec,
1525  Matrix(stokes_dim, stokes_dim),
1526  ext_mat_local,
1527  abs_vec_local,
1528  sca_vec_av,
1529  lstep,
1530  rte_planck_value);
1531 
1532  } // End of loop over ppath_step.
1533  // Assign calculated Stokes Vector to cloudbox_field_mono.
1534  if (atmosphere_dim == 1)
1535  cloudbox_field_mono(
1536  p_index - cloudbox_limits[0], 0, 0, za_index, 0, joker) =
1537  stokes_vec;
1538  else if (atmosphere_dim == 3)
1539  cloudbox_field_mono(p_index - cloudbox_limits[0],
1540  lat_index - cloudbox_limits[2],
1541  lon_index - cloudbox_limits[4],
1542  za_index,
1543  aa_index,
1544  joker) = stokes_vec;
1545 }
1546 
1548  //Output
1549  Tensor6View cloudbox_field_mono,
1550  //Input
1551  const Agenda& surface_rtprop_agenda,
1552  ConstVectorView f_grid,
1553  const Index& f_index,
1554  const Index& stokes_dim,
1555  const Ppath& ppath_step,
1556  const ArrayOfIndex& cloudbox_limits,
1557  ConstVectorView za_grid,
1558  const Index& za_index) {
1559  chk_not_empty("surface_rtprop_agenda", surface_rtprop_agenda);
1560 
1561  Matrix iy;
1562 
1563  // Local output of surface_rtprop_agenda.
1564  Numeric surface_skin_t;
1565  Matrix surface_emission;
1566  Matrix surface_los;
1567  Tensor4 surface_rmatrix;
1568 
1569  //Set rte_pos and rte_los to match the last point in ppath.
1570 
1571  Index np = ppath_step.np;
1572 
1573  Vector rte_pos; // ppath_step.pos contains two columns for 1D
1574  rte_pos.resize(ppath_step.dim);
1575  rte_pos = ppath_step.pos(np - 1, Range(0, ppath_step.dim));
1576 
1577  Vector rte_los;
1578  rte_los.resize(ppath_step.los.ncols());
1579  rte_los = ppath_step.los(np - 1, joker);
1580 
1581  //Execute the surface_rtprop_agenda which gives the surface
1582  //parameters.
1584  surface_skin_t,
1585  surface_emission,
1586  surface_los,
1587  surface_rmatrix,
1588  Vector(1, f_grid[f_index]),
1589  rte_pos,
1590  rte_los,
1591  surface_rtprop_agenda);
1592 
1593  iy = surface_emission;
1594 
1595  Index nlos = surface_los.nrows();
1596 
1597  if (nlos > 0) {
1598  Vector rtmp(stokes_dim); // Reflected Stokes vector for 1 frequency
1599 
1600  for (Index ilos = 0; ilos < nlos; ilos++) {
1601  // Several things needs to be fixed here. As far as I understand it,
1602  // this works only for specular cases and if the lower cloudbox limit
1603  // is exactly at the surface (PE, 120828)
1604 
1605  mult(rtmp,
1606  surface_rmatrix(ilos, 0, joker, joker),
1607  cloudbox_field_mono(cloudbox_limits[0],
1608  0,
1609  0,
1610  (za_grid.nelem() - 1 - za_index),
1611  0,
1612  joker));
1613  iy(0, joker) += rtmp;
1614  }
1615  }
1616  cloudbox_field_mono(cloudbox_limits[0], 0, 0, za_index, 0, joker) =
1617  iy(0, joker);
1618 }
1619 
1620 void cloudbox_field_ngAcceleration(Tensor6& cloudbox_field_mono,
1621  const ArrayOfTensor6& acceleration_input,
1622  const Index& accelerated,
1623  const Verbosity&) {
1624  const Index N_p = cloudbox_field_mono.nvitrines();
1625  const Index N_za = cloudbox_field_mono.npages();
1626 
1627  // Loop over 4 components of Stokes Vector
1628  for (Index i = 0; i < accelerated; ++i) {
1629  ConstMatrixView S1 = acceleration_input[0](joker, 0, 0, joker, 0, i);
1630  ConstMatrixView S2 = acceleration_input[1](joker, 0, 0, joker, 0, i);
1631  ConstMatrixView S3 = acceleration_input[2](joker, 0, 0, joker, 0, i);
1632  ConstMatrixView S4 = acceleration_input[3](joker, 0, 0, joker, 0, i);
1633 
1634  ConstMatrixView J = S4;
1635  Matrix Q1;
1636  Matrix Q2;
1637  Matrix Q3;
1638  Numeric A1 = 0;
1639  Numeric A2B1 = 0;
1640  Numeric B2 = 0;
1641  Numeric C1 = 0;
1642  Numeric C2 = 0;
1643  Numeric NGA = 0;
1644  Numeric NGB = 0;
1645 
1646  // Q1 = -2*S3 + S4 + S2
1647 
1648  Q1 = S3;
1649  Q1 *= -2;
1650  Q1 += S4;
1651  Q1 += S2;
1652 
1653  // Q2 = S4 - S3 - S2 + S1
1654  Q2 = S4;
1655  Q2 -= S3;
1656  Q2 -= S2;
1657  Q2 += S1;
1658 
1659  //Q3 = S4 - S3
1660  Q3 = S4;
1661  Q3 -= S3;
1662 
1663  for (Index p_index = 0; p_index < N_p; ++p_index) {
1664  for (Index za_index = 0; za_index < N_za; ++za_index) {
1665  A1 += Q1(p_index, za_index) * Q1(p_index, za_index) *
1666  J(p_index, za_index);
1667  A2B1 += Q2(p_index, za_index) * Q1(p_index, za_index) *
1668  J(p_index, za_index);
1669  B2 += Q2(p_index, za_index) * Q2(p_index, za_index) *
1670  J(p_index, za_index);
1671  C1 += Q1(p_index, za_index) * Q3(p_index, za_index) *
1672  J(p_index, za_index);
1673  C2 += Q2(p_index, za_index) * Q3(p_index, za_index) *
1674  J(p_index, za_index);
1675  }
1676  }
1677 
1678  NGA = (C1 * B2 - C2 * A2B1) / (A1 * B2 - A2B1 * A2B1);
1679  NGB = (C2 * A1 - C1 * A2B1) / (A1 * B2 - A2B1 * A2B1);
1680 
1681  if (!std::isnan(NGB) && !std::isnan(NGA)) {
1682  // Calculating the accelerated field
1683  for (Index p_index = 0; p_index < N_p; ++p_index) {
1684  for (Index za_index = 0; za_index < N_za; ++za_index) {
1685  Q1(p_index, za_index) = (1 - NGA - NGB) * S4(p_index, za_index) +
1686  NGA * S3(p_index, za_index) +
1687  NGB * S2(p_index, za_index);
1688  }
1689  }
1690  cloudbox_field_mono(joker, 0, 0, joker, 0, i) = Q1;
1691  }
1692  }
1693 }
1694 
1695 void interp_cloud_coeff1D( //Output
1696  Tensor3View ext_mat_int,
1697  MatrixView abs_vec_int,
1698  MatrixView sca_vec_int,
1699  MatrixView cloudbox_field_mono_int,
1700  VectorView t_int,
1701  MatrixView vmr_list_int,
1702  VectorView p_int,
1703  //Input
1704  ConstTensor5View ext_mat_field,
1705  ConstTensor4View abs_vec_field,
1706  ConstTensor6View doit_scat_field,
1707  ConstTensor6View cloudbox_field_mono,
1708  ConstTensor3View t_field,
1709  ConstTensor4View vmr_field,
1710  ConstVectorView p_grid,
1711  const Ppath& ppath_step,
1712  const ArrayOfIndex& cloudbox_limits,
1713  ConstVectorView za_grid,
1714  const Index& scat_za_interp,
1715  const Verbosity& verbosity) {
1716  CREATE_OUT3;
1717 
1718  // Stokes dimension
1719  const Index stokes_dim = cloudbox_field_mono.ncols();
1720 
1721  // Gridpositions inside the cloudbox.
1722  // The optical properties are stored only inside the
1723  // cloudbox. For interpolation we use grids
1724  // inside the cloudbox.
1725  ArrayOfGridPos cloud_gp_p = ppath_step.gp_p;
1726 
1727  for (Index i = 0; i < ppath_step.np; i++)
1728  cloud_gp_p[i].idx -= cloudbox_limits[0];
1729 
1730  // Grid index for points at upper limit of cloudbox must be shifted
1731  const Index n1 = cloudbox_limits[1] - cloudbox_limits[0];
1732  gridpos_upperend_check(cloud_gp_p[0], n1);
1733  gridpos_upperend_check(cloud_gp_p[ppath_step.np - 1], n1);
1734 
1735  Matrix itw(cloud_gp_p.nelem(), 2);
1736  interpweights(itw, cloud_gp_p);
1737 
1738  // The zenith angles of the propagation path are needed as we have to
1739  // interpolate the intensity field and the scattered field on the
1740  // right angles.
1741  Vector los_grid = ppath_step.los(joker, 0);
1742 
1743  ArrayOfGridPos gp_za(los_grid.nelem());
1744  gridpos(gp_za, za_grid, los_grid);
1745 
1746  Matrix itw_p_za(cloud_gp_p.nelem(), 4);
1747  interpweights(itw_p_za, cloud_gp_p, gp_za);
1748 
1749  // Calculate the average of the coefficients for the layers
1750  // to be considered in the
1751  // radiative transfer calculation.
1752 
1753  for (Index i = 0; i < stokes_dim; i++) {
1754  // Extinction matrix requires a second loop
1755  // over stokes_dim
1756  out3 << "Interpolate ext_mat:\n";
1757  for (Index j = 0; j < stokes_dim; j++) {
1758  //
1759  // Interpolation of ext_mat
1760  //
1761  interp(ext_mat_int(i, j, joker),
1762  itw,
1763  ext_mat_field(joker, 0, 0, i, j),
1764  cloud_gp_p);
1765  }
1766  // Particle absorption vector:
1767  //
1768  // Interpolation of abs_vec
1769  // //
1770  out3 << "Interpolate abs_vec:\n";
1771  interp(
1772  abs_vec_int(i, joker), itw, abs_vec_field(joker, 0, 0, i), cloud_gp_p);
1773  //
1774  // Scattered field:
1775  //
1776  //
1777 
1778  out3 << "Interpolate doit_scat_field and cloudbox_field_mono:\n";
1779  if (scat_za_interp == 0) // linear interpolation
1780  {
1781  interp(sca_vec_int(i, joker),
1782  itw_p_za,
1783  doit_scat_field(joker, 0, 0, joker, 0, i),
1784  cloud_gp_p,
1785  gp_za);
1786  interp(cloudbox_field_mono_int(i, joker),
1787  itw_p_za,
1788  cloudbox_field_mono(joker, 0, 0, joker, 0, i),
1789  cloud_gp_p,
1790  gp_za);
1791  } else if (scat_za_interp == 1) //polynomial interpolation
1792  {
1793  // These intermediate variables are needed because polynomial
1794  // interpolation is not implemented as multidimensional
1795  // interpolation.
1796  Tensor3 sca_vec_int_za(
1797  stokes_dim, ppath_step.np, za_grid.nelem(), 0.);
1798  Tensor3 cloudbox_field_mono_int_za(
1799  stokes_dim, ppath_step.np, za_grid.nelem(), 0.);
1800  for (Index za = 0; za < za_grid.nelem(); za++) {
1801  interp(sca_vec_int_za(i, joker, za),
1802  itw,
1803  doit_scat_field(joker, 0, 0, za, 0, i),
1804  cloud_gp_p);
1805  out3 << "Interpolate cloudbox_field_mono:\n";
1806  interp(cloudbox_field_mono_int_za(i, joker, za),
1807  itw,
1808  cloudbox_field_mono(joker, 0, 0, za, 0, i),
1809  cloud_gp_p);
1810  }
1811  for (Index ip = 0; ip < ppath_step.np; ip++) {
1812  sca_vec_int(i, ip) = interp_poly(za_grid,
1813  sca_vec_int_za(i, ip, joker),
1814  los_grid[ip],
1815  gp_za[ip]);
1816  cloudbox_field_mono_int(i, ip) =
1817  interp_poly(za_grid,
1818  cloudbox_field_mono_int_za(i, ip, joker),
1819  los_grid[ip],
1820  gp_za[ip]);
1821  }
1822  }
1823  }
1824  //
1825  // Planck function
1826  //
1827  // Interpolate temperature field
1828  //
1829  out3 << "Interpolate temperature field\n";
1830  interp(t_int, itw, t_field(joker, 0, 0), ppath_step.gp_p);
1831  //
1832  // The vmr_field is needed for the gaseous absorption
1833  // calculation.
1834  //
1835  const Index N_species = vmr_field.nbooks();
1836  //
1837  // Interpolated vmr_list, holds a vmr_list for each point in
1838  // ppath_step.
1839  //
1840  Vector vmr_int(ppath_step.np);
1841 
1842  for (Index i_sp = 0; i_sp < N_species; i_sp++) {
1843  out3 << "Interpolate vmr field\n";
1844  interp(vmr_int, itw, vmr_field(i_sp, joker, 0, 0), ppath_step.gp_p);
1845  vmr_list_int(i_sp, joker) = vmr_int;
1846  }
1847  //
1848  // Interpolate pressure
1849  //
1850  itw2p(p_int, p_grid, ppath_step.gp_p, itw);
1851 }
1852 
1853 void za_gridOpt( //Output:
1854  Vector& za_grid_opt,
1855  Matrix& cloudbox_field_opt,
1856  // Input
1857  ConstVectorView za_grid_fine,
1858  ConstTensor6View cloudbox_field_mono,
1859  const Numeric& acc,
1860  const Index& scat_za_interp) {
1861  Index N_za = za_grid_fine.nelem();
1862 
1863  assert(cloudbox_field_mono.npages() == N_za);
1864 
1865  Index N_p = cloudbox_field_mono.nvitrines();
1866 
1867  Vector i_approx_interp(N_za);
1868  Vector za_reduced(2);
1869 
1870  ArrayOfIndex idx;
1871  idx.push_back(0);
1872  idx.push_back(N_za - 1);
1873  ArrayOfIndex idx_unsorted;
1874 
1875  Numeric max_diff = 100;
1876 
1877  ArrayOfGridPos gp_za(N_za);
1878  Matrix itw(za_grid_fine.nelem(), 2);
1879 
1880  ArrayOfIndex i_sort;
1881  Vector diff_vec(N_za);
1882  Vector max_diff_za(N_p);
1883  ArrayOfIndex ind_za(N_p);
1884  Numeric max_diff_p;
1885  Index ind_p = 0;
1886 
1887  while (max_diff > acc) {
1888  za_reduced.resize(idx.nelem());
1889  cloudbox_field_opt.resize(N_p, idx.nelem());
1890  max_diff_za = 0.;
1891  max_diff_p = 0.;
1892 
1893  // Interpolate reduced intensity field on fine za_grid for
1894  // all pressure levels
1895  for (Index i_p = 0; i_p < N_p; i_p++) {
1896  for (Index i_za_red = 0; i_za_red < idx.nelem(); i_za_red++) {
1897  za_reduced[i_za_red] = za_grid_fine[idx[i_za_red]];
1898  cloudbox_field_opt(i_p, i_za_red) =
1899  cloudbox_field_mono(i_p, 0, 0, idx[i_za_red], 0, 0);
1900  }
1901  // Calculate grid positions
1902  gridpos(gp_za, za_reduced, za_grid_fine);
1903  //linear interpolation
1904  if (scat_za_interp == 0 || idx.nelem() < 3) {
1905  interpweights(itw, gp_za);
1906  interp(i_approx_interp, itw, cloudbox_field_opt(i_p, joker), gp_za);
1907  } else if (scat_za_interp == 1) {
1908  for (Index i_za = 0; i_za < N_za; i_za++) {
1909  i_approx_interp[i_za] = interp_poly(za_reduced,
1910  cloudbox_field_opt(i_p, joker),
1911  za_grid_fine[i_za],
1912  gp_za[i_za]);
1913  }
1914  } else
1915  // Interpolation method not defined
1916  assert(false);
1917 
1918  // Calculate differences between approximated i-vector and
1919  // exact i_vector for the i_p pressure level
1920  for (Index i_za = 0; i_za < N_za; i_za++) {
1921  diff_vec[i_za] = abs(cloudbox_field_mono(i_p, 0, 0, i_za, 0, 0) -
1922  i_approx_interp[i_za]);
1923  if (diff_vec[i_za] > max_diff_za[i_p]) {
1924  max_diff_za[i_p] = diff_vec[i_za];
1925  ind_za[i_p] = i_za;
1926  }
1927  }
1928  // Take maximum value of max_diff_za
1929  if (max_diff_za[i_p] > max_diff_p) {
1930  max_diff_p = max_diff_za[i_p];
1931  ind_p = i_p;
1932  }
1933  }
1934 
1935  //Transform in %
1936  max_diff =
1937  max_diff_p / cloudbox_field_mono(ind_p, 0, 0, ind_za[ind_p], 0, 0) * 100.;
1938 
1939  idx.push_back(ind_za[ind_p]);
1940  idx_unsorted = idx;
1941 
1942  i_sort.resize(idx_unsorted.nelem());
1943  get_sorted_indexes(i_sort, idx_unsorted);
1944 
1945  for (Index i = 0; i < idx_unsorted.nelem(); i++)
1946  idx[i] = idx_unsorted[i_sort[i]];
1947 
1948  za_reduced.resize(idx.nelem());
1949  }
1950 
1951  za_grid_opt.resize(idx.nelem());
1952  cloudbox_field_opt.resize(N_p, idx.nelem());
1953  for (Index i = 0; i < idx.nelem(); i++) {
1954  za_grid_opt[i] = za_grid_fine[idx[i]];
1955  cloudbox_field_opt(joker, i) = cloudbox_field_mono(joker, 0, 0, idx[i], 0, 0);
1956  }
1957 }
1958 
1960  Tensor6& doit_scat_field,
1961  const Tensor6& cloudbox_field_mono,
1962  const ArrayOfIndex& cloudbox_limits,
1963  const Agenda& spt_calc_agenda,
1964  const Index& atmosphere_dim,
1965  const Vector& za_grid,
1966  const Vector& aa_grid,
1967  const Tensor4& pnd_field,
1968  const Tensor3& t_field,
1969  const Numeric& norm_error_threshold,
1970  const Index& norm_debug,
1971  const Verbosity& verbosity) {
1972  if (atmosphere_dim != 1)
1973  throw runtime_error("Only 1D is supported here for now");
1974 
1975  CREATE_OUT0;
1976  CREATE_OUT2;
1977 
1978  // Number of zenith angles.
1979  const Index Nza = za_grid.nelem();
1980 
1981  if (za_grid[0] != 0. || za_grid[Nza - 1] != 180.)
1982  throw runtime_error("The range of *za_grid* must [0 180].");
1983 
1984  // Number of azimuth angles.
1985  const Index Naa = aa_grid.nelem();
1986 
1987  if (Naa > 1 && (aa_grid[0] != 0. || aa_grid[Naa - 1] != 360.))
1988  throw runtime_error("The range of *aa_grid* must [0 360].");
1989 
1990  // Get stokes dimension from *doit_scat_field*:
1991  const Index stokes_dim = doit_scat_field.ncols();
1992  assert(stokes_dim > 0 || stokes_dim < 5);
1993 
1994  // To use special interpolation functions for atmospheric fields we
1995  // use ext_mat_field and abs_vec_field:
1996  Tensor5 ext_mat_field(cloudbox_limits[1] - cloudbox_limits[0] + 1,
1997  1,
1998  1,
1999  stokes_dim,
2000  stokes_dim,
2001  0.);
2002  Tensor4 abs_vec_field(
2003  cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1, stokes_dim, 0.);
2004 
2005  const Index Np = doit_scat_field.nvitrines();
2006 
2007  Tensor5 doit_scat_ext_field(doit_scat_field.nvitrines(),
2008  doit_scat_field.nshelves(),
2009  doit_scat_field.nbooks(),
2010  doit_scat_field.npages(),
2011  doit_scat_field.nrows(),
2012  0.);
2013 
2014  Index aa_index_local = 0;
2015 
2016  // Calculate scattering extinction field
2017  for (Index za_index_local = 0; za_index_local < Nza;
2018  za_index_local++) {
2019  // This function has to be called inside the angular loop, as
2020  // spt_calc_agenda takes *za_index* and *aa_index*
2021  // from the workspace.
2022  cloud_fieldsCalc(ws,
2023  ext_mat_field,
2024  abs_vec_field,
2025  spt_calc_agenda,
2026  za_index_local,
2027  aa_index_local,
2028  cloudbox_limits,
2029  t_field,
2030  pnd_field,
2031  verbosity);
2032 
2033  for (Index p_index = 0;
2034  p_index <= (cloudbox_limits[1] - cloudbox_limits[0]);
2035  p_index++) {
2036  // For all in p_grid (in cloudbox):
2037  // I_ext = (ext_mat_field - abs_vec_field) * cloudbox_field_mono
2038  // equivalent to:
2039  // I_ext = I * (K11-a1) + Q * (K12 - a2) + U * (K13 - a3) + V * (K14 - a4)
2040  for (Index i = 0; i < stokes_dim; i++) {
2041  doit_scat_ext_field(p_index, 0, 0, za_index_local, 0) +=
2042  cloudbox_field_mono(p_index, 0, 0, za_index_local, 0, i) *
2043  (ext_mat_field(p_index, 0, 0, 0, i) -
2044  abs_vec_field(p_index, 0, 0, i));
2045  }
2046  }
2047  }
2048 
2049  Numeric corr_max = .0;
2050  Index corr_max_p_index = -1;
2051 
2052  for (Index p_index = 0; p_index < Np; p_index++) {
2053  // Calculate scattering integrals
2054  const Numeric scat_int = AngIntegrate_trapezoid(
2055  doit_scat_field(p_index, 0, 0, joker, 0, 0), za_grid);
2056 
2057  const Numeric scat_ext_int = AngIntegrate_trapezoid(
2058  doit_scat_ext_field(p_index, 0, 0, joker, 0), za_grid);
2059 
2060  // Calculate factor between scattered extinction field integral
2061  // and scattered field integral
2062  const Numeric corr_factor = scat_ext_int / scat_int;
2063 
2064  // If no scattering is present, the correction factor can become
2065  // inf or nan. We just don't apply it for those cases.
2066  if (!std::isnan(corr_factor) && !std::isinf(corr_factor)) {
2067  if (abs(corr_factor) > abs(corr_max)) {
2068  corr_max = corr_factor;
2069  corr_max_p_index = p_index;
2070  }
2071  if (norm_debug) {
2072  out0 << " DOIT corr_factor: " << 1. - corr_factor
2073  << " ( scat_ext_int: " << scat_ext_int
2074  << ", scat_int: " << scat_int << ")"
2075  << " at p_index " << p_index << "\n";
2076  }
2077  if (abs(1. - corr_factor) > norm_error_threshold) {
2078  ostringstream os;
2079  os << "ERROR: DOIT correction factor exceeds threshold (="
2080  << norm_error_threshold << "): " << setprecision(4)
2081  << 1. - corr_factor << " at p_index " << p_index << "\n";
2082  throw runtime_error(os.str());
2083  } else if (abs(1. - corr_factor) > norm_error_threshold / 2.) {
2084  out0 << " WARNING: DOIT correction factor above threshold/2: "
2085  << 1. - corr_factor << " at p_index " << p_index << "\n";
2086  }
2087 
2088  // Scale scattered field with correction factor
2089  doit_scat_field(p_index, 0, 0, joker, 0, joker) *= corr_factor;
2090  } else if (norm_debug) {
2091  out0 << " DOIT corr_factor ignored: " << 1. - corr_factor
2092  << " ( scat_ext_int: " << scat_ext_int << ", scat_int: " << scat_int
2093  << ")"
2094  << " at p_index " << p_index << "\n";
2095  }
2096  }
2097 
2098  ostringstream os;
2099  if (corr_max_p_index != -1) {
2100  os << " Max. DOIT correction factor in this iteration: " << 1. - corr_max
2101  << " at p_index " << corr_max_p_index << "\n";
2102  } else {
2103  os << " No DOIT correction performed in this iteration.\n";
2104  }
2105 
2106  if (norm_debug)
2107  out0 << os.str();
2108  else
2109  out2 << os.str();
2110 }
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
ArrayOfGridPos gp_lat
Index position with respect to the latitude grid.
Definition: ppath.h:84
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)
Definition: auto_md.cc:25015
Numeric interp_poly(ConstVectorView x, ConstVectorView y, const Numeric &x_i, const GridPos &gp)
Polynomial interpolation.
VectorView VectorAtPosition(const Index iv=0, const Index iz=0, const Index ia=0)
Get a vectorview to the position.
The VectorView class.
Definition: matpackI.h:610
Index nrows() const
Returns the number of rows.
Definition: matpackV.cc:53
void opt_prop_bulkCalc(PropagationMatrix &ext_mat, StokesVector &abs_vec, const ArrayOfPropagationMatrix &ext_mat_spt, const ArrayOfStokesVector &abs_vec_spt, const Tensor4 &pnd_field, const Index &scat_p_index, const Index &scat_lat_index, const Index &scat_lon_index, const Verbosity &)
WORKSPACE METHOD: opt_prop_bulkCalc.
The Tensor4View class.
Definition: matpackIV.h:284
The Agenda class.
Definition: agenda_class.h:44
Index nelem() const
Number of elements.
Definition: array.h:195
Declarations having to do with the four output streams.
void gridpos_upperend_check(GridPos &gp, const Index &ie)
gridpos_upperend_check
void MatrixAtPosition(MatrixView ret, const Index iv=0, const Index iz=0, const Index ia=0) const
Sets the dense matrix.
Matrix los
Line-of-sight at each ppath point.
Definition: ppath.h:66
The Vector class.
Definition: matpackI.h:860
#define abs(x)
The MatrixView class.
Definition: matpackI.h:1093
Index nvitrines() const
Returns the number of vitrines.
Definition: matpackVI.cc:42
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPos &tc)
Red 1D Interpolate.
Index dim
Atmospheric dimensionality.
Definition: ppath.h:50
A constant view of a Tensor6.
Definition: matpackVI.h:149
The Tensor4 class.
Definition: matpackIV.h:421
void ppath_step_agendaExecute(Workspace &ws, Ppath &ppath_step, const Numeric ppath_lmax, const Numeric ppath_lraytrace, const Vector &f_grid, const Agenda &input_agenda)
Definition: auto_md.cc:24814
The range class.
Definition: matpackI.h:160
Array< RetrievalQuantity > ArrayOfRetrievalQuantity
Definition: jacobian.h:402
Vector lstep
The length between ppath points.
Definition: ppath.h:70
Linear algebra functions.
void spt_calc_agendaExecute(Workspace &ws, ArrayOfPropagationMatrix &ext_mat_spt, ArrayOfStokesVector &abs_vec_spt, const Index scat_p_index, const Index scat_lat_index, const Index scat_lon_index, const Numeric rtp_temperature, const Index za_index, const Index aa_index, const Agenda &input_agenda)
Definition: auto_md.cc:24961
void MatrixInverseAtPosition(MatrixView ret, const Index iv=0, const Index iz=0, const Index ia=0) const
Return the matrix inverse at the position.
void cloudbox_field_ngAcceleration(Tensor6 &cloudbox_field_mono, const ArrayOfTensor6 &acceleration_input, const Index &accelerated, const Verbosity &)
Convergence acceleration.
Definition: doit.cc:1620
invlib::Vector< ArtsVector > Vector
invlib wrapper type for ARTS vectors.
Definition: oem.h:32
Matrix pos
The distance between start pos and the last position in pos.
Definition: ppath.h:64
The Tensor6View class.
Definition: matpackVI.h:621
This file contains basic functions to handle XML data files.
void cloud_ppath_update3D(Workspace &ws, Tensor6View cloudbox_field_mono, const Index &p_index, const Index &lat_index, const Index &lon_index, const Index &za_index, const Index &aa_index, ConstVectorView za_grid, ConstVectorView aa_grid, const ArrayOfIndex &cloudbox_limits, ConstTensor6View doit_scat_field, const Agenda &propmat_clearsky_agenda, ConstTensor4View vmr_field, const Agenda &ppath_step_agenda, const Numeric &ppath_lmax, const Numeric &ppath_lraytrace, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid, ConstTensor3View z_field, ConstVectorView refellipsoid, ConstTensor3View t_field, ConstVectorView f_grid, const Index &f_index, ConstTensor5View ext_mat_field, ConstTensor4View abs_vec_field, const Index &, const Verbosity &verbosity)
Radiative transfer calculation along a path inside the cloudbox (3D).
Definition: doit.cc:1108
Vector r
Radius of each ppath point.
Definition: ppath.h:68
Stokes vector is as Propagation matrix but only has 4 possible values.
void opt_prop_sum_propmat_clearsky(PropagationMatrix &ext_mat, StokesVector &abs_vec, const ArrayOfPropagationMatrix &propmat_clearsky)
Get optical properties from propmat_clearsky.
void cloud_RT_no_background(Workspace &ws, Tensor6View cloudbox_field_mono, const Agenda &propmat_clearsky_agenda, const Ppath &ppath_step, ConstVectorView t_int, ConstMatrixView vmr_list_int, ConstTensor3View ext_mat_int, ConstMatrixView abs_vec_int, ConstMatrixView sca_vec_int, ConstMatrixView cloudbox_field_mono_int, ConstVectorView p_int, const ArrayOfIndex &cloudbox_limits, ConstVectorView f_grid, const Index &f_index, const Index &p_index, const Index &lat_index, const Index &lon_index, const Index &za_index, const Index &aa_index, const Verbosity &verbosity)
Calculates RT in the cloudbox (1D)
Definition: doit.cc:1382
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:51
void rte_step_doit_replacement(VectorView stokes_vec, MatrixView trans_mat, const PropagationMatrix &ext_mat_av, const StokesVector &abs_vec_av, ConstVectorView sca_vec_av, const Numeric &lstep, const Numeric &rtp_planck_value, const bool &trans_is_precalc)
Solves monochromatic VRTE for an atmospheric slab with constant conditions.
Definition: doit.cc:62
Contains sorting routines.
A constant view of a Tensor4.
Definition: matpackIV.h:133
Index ppath_what_background(const Ppath &ppath)
Returns the case number for the radiative background.
Definition: ppath.cc:1494
This file contains the definition of Array.
void chk_not_empty(const String &x_name, const Agenda &x)
chk_not_empty
Definition: check_input.cc:694
Index ncols() const
Returns the number of columns.
Definition: matpackI.cc:432
The Tensor3 class.
Definition: matpackIII.h:339
void swap(ComplexVector &v1, ComplexVector &v2)
Swaps two objects.
Definition: complex.cc:731
void AddAverageAtPosition(ConstMatrixView mat1, ConstMatrixView mat2, const Index iv=0, const Index iz=0, const Index ia=0)
Add the average of the two input at position.
_CS_string_type str() const
Definition: sstream.h:491
Stuff related to the propagation matrix.
Declarations for agendas.
void ppath_init_structure(Ppath &ppath, const Index &atmosphere_dim, const Index &np)
Initiates a Ppath structure to hold the given number of points.
Definition: ppath.cc:1426
The Tensor3View class.
Definition: matpackIII.h:239
void cloud_fieldsCalc(Workspace &ws, Tensor5View ext_mat_field, Tensor4View abs_vec_field, const Agenda &spt_calc_agenda, const Index &za_index, const Index &aa_index, const ArrayOfIndex &cloudbox_limits, ConstTensor3View t_field, ConstTensor4View pnd_field, const Verbosity &verbosity)
Calculate ext_mat, abs_vec for all points inside the cloudbox for one.
Definition: doit.cc:163
Index nrows() const
Returns the number of rows.
Definition: matpackVI.cc:54
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
bool is_inside_cloudbox(const Ppath &ppath_step, const ArrayOfIndex &cloudbox_limits, const bool include_boundaries)
Definition: cloudbox.cc:579
A constant view of a Tensor5.
Definition: matpackV.h:143
const Joker joker
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
Index StokesDimensions() const
The stokes dimension of the propagation matrix.
The Matrix class.
Definition: matpackI.h:1193
Numeric refell2r(ConstVectorView refellipsoid, const Numeric &lat)
refell2r
Definition: geodetic.cc:1135
Header file for special_interp.cc.
Propagation path structure and functions.
void get_sorted_indexes(ArrayOfIndex &sorted, const T &data)
get_sorted_indexes
Definition: sorting.h:73
void mult(ComplexVectorView y, const ConstComplexMatrixView &M, const ConstComplexVectorView &x)
Matrix-Vector Multiplication.
Definition: complex.cc:1579
The Tensor5View class.
Definition: matpackV.h:333
Header file for logic.cc.
Radiative transfer in cloudbox.
Index NumberOfFrequencies() const
The number of frequencies of the propagation matrix.
This can be used to make arrays out of anything.
Definition: array.h:40
Index nshelves() const
Returns the number of shelves.
Definition: matpackVI.cc:45
bool is_singular(ConstMatrixView A)
Checks if a square matrix is singular.
Definition: logic.cc:295
Index ncols() const
Returns the number of columns.
Definition: matpackVI.cc:57
VectorView Kjj(const Index iz=0, const Index ia=0)
Vector view to diagonal elements.
void resize(Index n)
Resize function.
Definition: matpackI.cc:404
A constant view of a Tensor3.
Definition: matpackIII.h:132
The Tensor6 class.
Definition: matpackVI.h:1088
void interp_cloud_coeff1D(Tensor3View ext_mat_int, MatrixView abs_vec_int, MatrixView sca_vec_int, MatrixView cloudbox_field_mono_int, VectorView t_int, MatrixView vmr_list_int, VectorView p_int, ConstTensor5View ext_mat_field, ConstTensor4View abs_vec_field, ConstTensor6View doit_scat_field, ConstTensor6View cloudbox_field_mono, ConstTensor3View t_field, ConstTensor4View vmr_field, ConstVectorView p_grid, const Ppath &ppath_step, const ArrayOfIndex &cloudbox_limits, ConstVectorView za_grid, const Index &scat_za_interp, const Verbosity &verbosity)
Interpolate all inputs of the VRTE on a propagation path step.
Definition: doit.cc:1695
A constant view of a Vector.
Definition: matpackI.h:476
Index np
Number of points describing the ppath.
Definition: ppath.h:52
void doit_scat_fieldNormalize(Workspace &ws, Tensor6 &doit_scat_field, const Tensor6 &cloudbox_field_mono, const ArrayOfIndex &cloudbox_limits, const Agenda &spt_calc_agenda, const Index &atmosphere_dim, const Vector &za_grid, const Vector &aa_grid, const Tensor4 &pnd_field, const Tensor3 &t_field, const Numeric &norm_error_threshold, const Index &norm_debug, const Verbosity &verbosity)
Normalization of scattered field.
Definition: doit.cc:1959
ArrayOfGridPos gp_lon
Index position with respect to the longitude grid.
Definition: ppath.h:86
Index npages() const
Returns the number of pages.
Definition: matpackVI.cc:51
const Numeric PI
A constant view of a Matrix.
Definition: matpackI.h:982
void cloud_ppath_update1D_noseq(Workspace &ws, Tensor6View cloudbox_field_mono, const Index &p_index, const Index &za_index, ConstVectorView za_grid, const ArrayOfIndex &cloudbox_limits, ConstTensor6View cloudbox_field_mono_old, ConstTensor6View doit_scat_field, const Agenda &propmat_clearsky_agenda, ConstTensor4View vmr_field, const Agenda &ppath_step_agenda, const Numeric &ppath_lmax, const Numeric &ppath_lraytrace, ConstVectorView p_grid, ConstTensor3View z_field, ConstVectorView refellipsoid, ConstTensor3View t_field, ConstVectorView f_grid, const Index &f_index, ConstTensor5View ext_mat_field, ConstTensor4View abs_vec_field, const Agenda &surface_rtprop_agenda, const Index &scat_za_interp, const Verbosity &verbosity)
Calculation of radiation field along a propagation path step for specified zenith direction and press...
Definition: doit.cc:457
Numeric planck(const Numeric &f, const Numeric &t)
planck
Workspace class.
Definition: workspace_ng.h:40
Index nbooks() const
Returns the number of books.
Definition: matpackIV.cc:57
const Numeric RAD2DEG
Index ncols() const
Returns the number of columns.
Definition: matpackV.cc:56
#define CREATE_OUT0
Definition: messages.h:204
#define CREATE_OUT3
Definition: messages.h:207
bool is_size(ConstVectorView x, const Index &n)
Verifies that the size of x is l.
Definition: logic.cc:79
void id_mat(MatrixView I)
Identity Matrix.
Definition: lin_alg.cc:2240
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)
Definition: auto_md.cc:23495
The structure to describe a propagation path and releated quantities.
Definition: ppath.h:48
Internal cloudbox functions.
Index ncols() const
Returns the number of columns.
Definition: matpackIV.cc:66
void cloud_ppath_update1D_planeparallel(Workspace &ws, Tensor6View cloudbox_field_mono, const Index &p_index, const Index &za_index, ConstVectorView za_grid, const ArrayOfIndex &cloudbox_limits, ConstTensor6View doit_scat_field, const Agenda &propmat_clearsky_agenda, ConstTensor4View vmr_field, ConstVectorView p_grid, ConstTensor3View z_field, ConstTensor3View t_field, ConstVectorView f_grid, const Index &f_index, ConstTensor5View ext_mat_field, ConstTensor4View abs_vec_field, const Verbosity &verbosity)
Radiative transfer calculation inside cloudbox for planeparallel case.
Definition: doit.cc:615
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
#define CREATE_OUT2
Definition: messages.h:206
void cloud_ppath_update1D(Workspace &ws, Tensor6View cloudbox_field_mono, const Index &p_index, const Index &za_index, ConstVectorView za_grid, const ArrayOfIndex &cloudbox_limits, ConstTensor6View doit_scat_field, const Agenda &propmat_clearsky_agenda, ConstTensor4View vmr_field, const Agenda &ppath_step_agenda, const Numeric &ppath_lmax, const Numeric &ppath_lraytrace, ConstVectorView p_grid, ConstTensor3View z_field, ConstVectorView refellipsoid, ConstTensor3View t_field, ConstVectorView f_grid, const Index &f_index, ConstTensor5View ext_mat_field, ConstTensor4View abs_vec_field, const Agenda &surface_rtprop_agenda, const Index &scat_za_interp, const Verbosity &verbosity)
Calculates radiation field along a propagation path step for specified zenith direction and pressure ...
Definition: doit.cc:301
void AddAverageAtPosition(ConstVectorView vec1, ConstVectorView vec2, const Index iv=0, const Index iz=0, const Index ia=0)
Add the average of both inputs at position.
invlib::Matrix< ArtsMatrix > Matrix
invlib wrapper type for ARTS matrices.
Definition: oem.h:34
This file contains declerations of functions of physical character.
Index nrows() const
Returns the number of rows.
Definition: matpackI.cc:429
ArrayOfGridPos gp_p
Index position with respect to the pressure grid.
Definition: ppath.h:82
void cloud_RT_surface(Workspace &ws, Tensor6View cloudbox_field_mono, const Agenda &surface_rtprop_agenda, ConstVectorView f_grid, const Index &f_index, const Index &stokes_dim, const Ppath &ppath_step, const ArrayOfIndex &cloudbox_limits, ConstVectorView za_grid, const Index &za_index)
Calculates RT in the cloudbox.
Definition: doit.cc:1547
Numeric AngIntegrate_trapezoid(ConstMatrixView Integrand, ConstVectorView za_grid, ConstVectorView aa_grid)
AngIntegrate_trapezoid.
Definition: math_funcs.cc:296
void itw2p(VectorView p_values, ConstVectorView p_grid, const ArrayOfGridPos &gp, ConstMatrixView itw)
Converts interpolation weights to pressures.
The Tensor5 class.
Definition: matpackV.h:506
Declaration of functions in rte.cc.
void compute_transmission_matrix_from_averaged_matrix_at_frequency(MatrixView T, const Numeric &r, const PropagationMatrix &averaged_propagation_matrix, const Index iv, const Index iz, const Index ia)
Compute the matrix exponent as the transmission matrix of this propagation matrix.
void resize(Index r, Index c)
Resize function.
Definition: matpackI.cc:1056
void za_gridOpt(Vector &za_grid_opt, Matrix &cloudbox_field_opt, ConstVectorView za_grid_fine, ConstTensor6View cloudbox_field_mono, const Numeric &acc, const Index &scat_za_interp)
Optimize the zenith angle grid.
Definition: doit.cc:1853
Index nbooks() const
Returns the number of books.
Definition: matpackVI.cc:48