ARTS  2.0.49
m_doit.cc
Go to the documentation of this file.
1 /* Copyright (C) 2002-2008
2  Claudia Emde <claudia.emde@dlr.de>
3  Sreerekha T.R. <rekha@uni-bremen.de>
4 
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of the GNU General Public License as published by the
7  Free Software Foundation; either version 2, or (at your option) any
8  later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18  USA.
19 */
20 
35 /*===========================================================================
36  === External declarations
37  ===========================================================================*/
38 
39 #include <stdexcept>
40 #include <iostream>
41 #include <cstdlib>
42 #include <cmath>
43 #include "arts.h"
44 #include "array.h"
45 #include "auto_md.h"
46 #include "check_input.h"
47 #include "matpackVII.h"
48 #include "logic.h"
49 #include "ppath.h"
50 #include "agenda_class.h"
51 #include "physics_funcs.h"
52 #include "lin_alg.h"
53 #include "math_funcs.h"
54 #include "messages.h"
55 #include "xml_io.h"
56 #include "rte.h"
57 #include "special_interp.h"
58 #include "doit.h"
59 #include "m_general.h"
60 #include "wsv_aux.h"
61 
62 extern const Numeric PI;
63 extern const Numeric RAD2DEG;
64 
65 /*===========================================================================
66  === The functions (in alphabetical order)
67  ===========================================================================*/
68 
69 
70 /* Workspace method: Doxygen documentation will be auto-generated */
71 void DoitAngularGridsSet(// WS Output:
72  Index& doit_za_grid_size,
73  Vector& scat_aa_grid,
74  Vector& scat_za_grid,
75  // Keywords:
76  const Index& N_za_grid,
77  const Index& N_aa_grid,
78  const String& za_grid_opt_file,
79  const Verbosity& verbosity)
80 {
81  // Check input
82  //
83  // The recommended values were found by testing the accuracy and the speed of
84  // 1D DOIT calculations for different grid sizes. For 3D calculations it can
85  // be necessary to use more grid points.
86  if (N_za_grid < 16)
87  throw runtime_error("N_za_grid must be greater than 15 for accurate results");
88  else if (N_za_grid > 100)
89  {
91  out1 << "Warning: N_za_grid is very large which means that the \n"
92  << "calculation will be very slow. The recommended value is 19.\n";
93  }
94 
95  if (N_aa_grid < 6)
96  throw runtime_error("N_aa_grid must be greater than 5 for accurate results");
97  else if (N_aa_grid > 100)
98  {
100  out1 << "Warning: N_aa_grid is very large which means that the \n"
101  << "calculation will be very slow. The recommended value is 10.\n";
102  }
103 
104  // Azimuth angle grid (the same is used for the scattering integral and
105  // for the radiative transfer.
106  nlinspace(scat_aa_grid, 0, 360, N_aa_grid);
107 
108  // Zenith angle grid:
109  // Number of zenith angle grid points (only for scattering integral):
110  doit_za_grid_size = N_za_grid;
111 
112  if( za_grid_opt_file == "" )
113  nlinspace(scat_za_grid, 0, 180, N_za_grid);
114  else
115  xml_read_from_file(za_grid_opt_file, scat_za_grid, verbosity);
116 
117 }
118 
119 
120 /* Workspace method: Doxygen documentation will be auto-generated */
121 void doit_conv_flagAbs(//WS Input and Output:
122  Index& doit_conv_flag,
123  Index& doit_iteration_counter,
124  // WS Input:
125  const Tensor6& doit_i_field,
126  const Tensor6& doit_i_field_old,
127  // Keyword:
128  const Vector& epsilon,
129  const Verbosity& verbosity)
130 {
133 
134  //------------Check the input---------------------------------------
135  if( doit_conv_flag != 0 )
136  throw runtime_error("Convergence flag is non-zero, which means that this\n"
137  "WSM is not used correctly. *doit_conv_flagAbs* should\n"
138  "be used only in *doit_conv_test_agenda*\n");
139 
140 
141  if (doit_iteration_counter > 100)
142  {
143  out1 <<"Warning in DOIT calculation:"
144  <<"Method does not converge (number of iterations \n"
145  <<"is > 100). Either the cloud particle number density \n"
146  <<"is too large or the numerical setup for the DOIT \n"
147  <<"calculation is not correct. In case of limb \n"
148  <<"simulations please make sure that you use an \n"
149  <<"optimized zenith angle grid. \n"
150  <<"*doit_i_field* might be wrong.\n";
151  doit_conv_flag = 1;
152  }
153 
154  const Index N_p = doit_i_field.nvitrines();
155  const Index N_lat = doit_i_field.nshelves();
156  const Index N_lon = doit_i_field.nbooks();
157  const Index N_za = doit_i_field.npages();
158  const Index N_aa = doit_i_field.nrows();
159  const Index stokes_dim = doit_i_field.ncols();
160 
161  // Check keyword "epsilon":
162  if ( epsilon.nelem() != stokes_dim )
163  throw runtime_error(
164  "You have to specify limiting values for the "
165  "convergence test for each Stokes component "
166  "separately. That means that *epsilon* must "
167  "have *stokes_dim* elements!"
168  );
169 
170  // Check if doit_i_field and doit_i_field_old have the same dimensions:
171  if(!is_size( doit_i_field_old,
172  N_p, N_lat, N_lon, N_za, N_aa, stokes_dim))
173  throw runtime_error("The fields (Tensor6) *doit_i_field* and \n"
174  "*doit_i_field_old* which are compared in the \n"
175  "convergence test do not have the same size.\n");
176 
177  //-----------End of checks-------------------------------------------------
178 
179 
180  out2 << " Number of DOIT iteration: " << doit_iteration_counter << "\n";
181  doit_iteration_counter +=1;
182 
183 
184  for (Index p_index = 0; p_index < N_p; p_index++)
185  {
186  for (Index lat_index = 0; lat_index < N_lat; lat_index++)
187  {
188  for (Index lon_index = 0; lon_index <N_lon; lon_index++)
189  {
190  for (Index scat_za_index = 0; scat_za_index < N_za;
191  scat_za_index++)
192  {
193  for (Index scat_aa_index = 0; scat_aa_index < N_aa;
194  scat_aa_index++)
195  {
196  for (Index stokes_index = 0; stokes_index <
197  stokes_dim; stokes_index ++)
198  {
199  Numeric diff =
200  (doit_i_field(p_index, lat_index, lon_index,
201  scat_za_index, scat_aa_index,
202  stokes_index) -
203  doit_i_field_old(p_index, lat_index,
204  lon_index, scat_za_index,
205  scat_aa_index,
206  stokes_index ));
207 
208  // If the absolute difference of the components
209  // is larger than the pre-defined values, return
210  // to *doit_i_fieldIterarte* and do next iteration
211 
212  if( abs(diff) > epsilon[stokes_index])
213  {
214  out1 << "difference: " << diff <<"\n";
215  return;
216  }
217 
218 
219  }// End loop stokes_dom.
220  }// End loop scat_aa_grid.
221  }// End loop scat_za_grid.
222  }// End loop lon_grid.
223  }// End loop lat_grid.
224  } // End p_grid.
225 
226  // Convergence test has been successful, doit_conv_flag can be set to 1.
227  doit_conv_flag = 1;
228  out2 << " Number of DOIT-iterations: " << doit_iteration_counter << "\n";
229 }
230 
231 
232 /* Workspace method: Doxygen documentation will be auto-generated */
233 void doit_conv_flagAbsBT(//WS Input and Output:
234  Index& doit_conv_flag,
235  Index& doit_iteration_counter,
236  // WS Input:
237  const Tensor6& doit_i_field,
238  const Tensor6& doit_i_field_old,
239  const Vector& f_grid,
240  const Index& f_index,
241  // Keyword:
242  const Vector& epsilon,
243  const Verbosity& verbosity)
244 {
247 
248  //------------Check the input---------------------------------------
249 
250  if( doit_conv_flag != 0 )
251  throw runtime_error("Convergence flag is non-zero, which means that this \n"
252  "WSM is not used correctly. *doit_conv_flagAbs* should\n"
253  "be used only in *doit_conv_test_agenda*\n");
254 
255  if (doit_iteration_counter > 100)
256  {
257  out1 <<"Warning in DOIT calculation at frequency" << f_grid[f_index]
258  << "GHz: \n"
259  <<"Method does not converge (number of iterations \n"
260  <<"is > 100). Either the cloud particle number density \n"
261  <<"is too large or the numerical setup for the DOIT \n"
262  <<"calculation is not correct. In case of limb \n"
263  <<"simulations please make sure that you use an \n"
264  <<"optimized zenith angle grid. \n"
265  <<"*doit_i_field* might be wrong.\n";
266  doit_conv_flag = 1;
267  }
268 
269  const Index N_p = doit_i_field.nvitrines();
270  const Index N_lat = doit_i_field.nshelves();
271  const Index N_lon = doit_i_field.nbooks();
272  const Index N_za = doit_i_field.npages();
273  const Index N_aa = doit_i_field.nrows();
274  const Index stokes_dim = doit_i_field.ncols();
275 
276  // Check keyword "epsilon":
277  if ( epsilon.nelem() != stokes_dim )
278  throw runtime_error(
279  "You have to specify limiting values for the "
280  "convergence test for each Stokes component "
281  "separately. That means that *epsilon* must "
282  "have *stokes_dim* elements!"
283  );
284 
285  // Check if doit_i_field and doit_i_field_old have the same dimensions:
286  if(!is_size( doit_i_field_old,
287  N_p, N_lat, N_lon, N_za, N_aa, stokes_dim))
288  throw runtime_error("The fields (Tensor6) *doit_i_field* and \n"
289  "*doit_i_field_old* which are compared in the \n"
290  "convergence test do not have the same size.\n");
291 
292  // Frequency grid
293  //
294  if( f_grid.nelem() == 0 )
295  throw runtime_error( "The frequency grid is empty." );
296  chk_if_increasing( "f_grid", f_grid );
297 
298  // Is the frequency index valid?
299  if ( f_index >= f_grid.nelem() )
300  throw runtime_error("*f_index* is greater than number of elements in the\n"
301  "frequency grid.\n");
302 
303  //-----------End of checks--------------------------------
304 
305  out2 << " Number of DOIT iteration: " << doit_iteration_counter << "\n";
306  doit_iteration_counter +=1;
307 
308  for (Index p_index = 0; p_index < N_p; p_index++)
309  {
310  for (Index lat_index = 0; lat_index < N_lat; lat_index++)
311  {
312  for (Index lon_index = 0; lon_index <N_lon; lon_index++)
313  {
314  for (Index scat_za_index = 0; scat_za_index < N_za;
315  scat_za_index++)
316  {
317  for (Index scat_aa_index = 0; scat_aa_index < N_aa;
318  scat_aa_index++)
319  {
320  for (Index stokes_index = 0; stokes_index <
321  stokes_dim; stokes_index ++)
322  {
323  Numeric diff =
324  abs( doit_i_field(p_index, lat_index, lon_index,
325  scat_za_index, scat_aa_index,
326  stokes_index) -
327  doit_i_field_old(p_index, lat_index,
328  lon_index, scat_za_index,
329  scat_aa_index,
330  stokes_index ));
331 
332  // If the absolute difference of the components
333  // is larger than the pre-defined values, return
334  // to *doit_i_fieldIterarte* and do next iteration
335  Numeric diff_bt = invrayjean(diff, f_grid[f_index]);
336  if( diff_bt > epsilon[stokes_index])
337  {
338  out1 << "BT difference: " << diff_bt <<"\n";
339  return;
340  }
341  }// End loop stokes_dom.
342  }// End loop scat_aa_grid.
343  }// End loop scat_za_grid.
344  }// End loop lon_grid.
345  }// End loop lat_grid.
346  } // End p_grid.
347 
348  // Convergence test has been successful, doit_conv_flag can be set to 1.
349  doit_conv_flag = 1;
350  out1 << "Number of DOIT-iterations:" << doit_iteration_counter << "\n";
351 }
352 
353 
354 /* Workspace method: Doxygen documentation will be auto-generated */
355 void doit_conv_flagLsq(//WS Output:
356  Index& doit_conv_flag,
357  Index& doit_iteration_counter,
358  // WS Input:
359  const Tensor6& doit_i_field,
360  const Tensor6& doit_i_field_old,
361  const Vector& f_grid,
362  const Index& f_index,
363  // Keyword:
364  const Vector& epsilon,
365  const Verbosity& verbosity)
366 {
369 
370  //------------Check the input---------------------------------------
371 
372  if( doit_conv_flag != 0 )
373  throw runtime_error("Convergence flag is non-zero, which means that this \n"
374  "WSM is not used correctly. *doit_conv_flagAbs* should\n"
375  "be used only in *doit_conv_test_agenda*\n");
376 
377 
378  if (doit_iteration_counter > 100)
379  throw runtime_error("Error in DOIT calculation: \n"
380  "Method does not converge (number of iterations \n"
381  "is > 100). Either the cloud particle number density \n"
382  "is too large or the numerical setup for the DOIT \n"
383  "calculation is not correct. In case of limb \n"
384  "simulations please make sure that you use an \n"
385  "optimized zenith angle grid. \n");
386 
387  const Index N_p = doit_i_field.nvitrines();
388  const Index N_lat = doit_i_field.nshelves();
389  const Index N_lon = doit_i_field.nbooks();
390  const Index N_za = doit_i_field.npages();
391  const Index N_aa = doit_i_field.nrows();
392  const Index stokes_dim = doit_i_field.ncols();
393 
394  // Check keyword "epsilon":
395  if ( epsilon.nelem() != stokes_dim )
396  throw runtime_error(
397  "You have to specify limiting values for the "
398  "convergence test for each Stokes component "
399  "separately. That means that *epsilon* must "
400  "have *stokes_dim* elements!"
401  );
402 
403  // Check if doit_i_field and doit_i_field_old have the same dimensions:
404  if(!is_size( doit_i_field_old,
405  N_p, N_lat, N_lon, N_za, N_aa, stokes_dim))
406  throw runtime_error("The fields (Tensor6) *doit_i_field* and \n"
407  "*doit_i_field_old* which are compared in the \n"
408  "convergence test do not have the same size.\n");
409 
410  // Frequency grid
411  //
412  if( f_grid.nelem() == 0 )
413  throw runtime_error( "The frequency grid is empty." );
414  chk_if_increasing( "f_grid", f_grid );
415 
416  // Is the frequency index valid?
417  if ( f_index >= f_grid.nelem() )
418  throw runtime_error("*f_index* is greater than number of elements in the\n"
419  "frequency grid.\n");
420 
421  //-----------End of checks--------------------------------
422 
423 
424  out2 << " Number of DOIT iteration: " << doit_iteration_counter << "\n";
425  doit_iteration_counter +=1;
426 
427  Vector lqs(4, 0.);
428 
429  // Will be set to zero if convergence not fullfilled
430  doit_conv_flag = 1;
431  for (Index i = 0; i < epsilon.nelem(); i ++)
432  {
433  for (Index p_index = 0; p_index < N_p; p_index++)
434  {
435  for (Index lat_index = 0; lat_index < N_lat; lat_index++)
436  {
437  for (Index lon_index = 0; lon_index <N_lon; lon_index++)
438  {
439  for (Index scat_za_index = 0; scat_za_index < N_za;
440  scat_za_index++)
441  {
442  for (Index scat_aa_index = 0; scat_aa_index < N_aa;
443  scat_aa_index++)
444  {
445  lqs[i]
446  += pow(
447  doit_i_field(p_index, lat_index,
448  lon_index,
449  scat_za_index, scat_aa_index, i) -
450  doit_i_field_old(p_index, lat_index,
451  lon_index, scat_za_index,
452  scat_aa_index, i)
453  , 2);
454  }// End loop scat_aa_grid.
455  }// End loop scat_za_grid.
456  }// End loop lon_grid.
457  }// End loop lat_grid.
458  } // End p_grid.
459 
460  lqs[i] = sqrt(lqs[i]);
461  lqs[i] /= (Numeric)(N_p*N_lat*N_lon*N_za*N_aa);
462 
463  // Convert difference to Rayleigh Jeans BT
464  lqs[i] = invrayjean(lqs[i], f_grid[f_index]);
465 
466  if (lqs[i] >= epsilon[i] )
467  doit_conv_flag = 0;
468  }
469  // end loop stokes_index
470  out1 << "lqs [I]: " << lqs[0] << "\n";
471 
472  if (doit_conv_flag == 1)
473  {
474  // Convergence test has been successful,
475  out1 << "Number of DOIT-iterations: " << doit_iteration_counter
476  << "\n";
477  }
478 }
479 
480 
481 /* Workspace method: Doxygen documentation will be auto-generated */
483  // WS Input and Output:
484  Tensor6& doit_i_field,
485  // WS Input:
486  const Agenda& doit_scat_field_agenda,
487  const Agenda& doit_rte_agenda,
488  const Agenda& doit_conv_test_agenda,
489  const Verbosity& verbosity)
490 {
492 
493  //---------------Check input---------------------------------
494  chk_not_empty( "doit_scat_field_agenda", doit_scat_field_agenda);
495  chk_not_empty( "doit_rte_agenda", doit_rte_agenda);
496  chk_not_empty( "doit_conv_test_agenda", doit_conv_test_agenda);
497 
498  //doit_i_field can not be checked here, because there is no way
499  //to find out the size without including a lot more interface
500  //variables
501  //-----------End of checks--------------------------------------
502 
503  Tensor6 doit_i_field_old_local;
504  Index doit_conv_flag_local;
505  Index doit_iteration_counter_local;
506 
507  // Resize and initialize doit_scat_field,
508  // which has the same dimensions as doit_i_field
509  Tensor6 doit_scat_field_local
510  (doit_i_field.nvitrines(), doit_i_field.nshelves(),
511  doit_i_field.nbooks(), doit_i_field.npages(),
512  doit_i_field.nrows(), doit_i_field.ncols(), 0.);
513 
514  doit_conv_flag_local = 0;
515  doit_iteration_counter_local = 0;
516 
517  while(doit_conv_flag_local == 0) {
518 
519  // 1. Copy doit_i_field to doit_i_field_old.
520  doit_i_field_old_local = doit_i_field;
521 
522  // 2.Calculate scattered field vector for all points in the cloudbox.
523 
524  // Calculate the scattered field.
525  out2 << " Execute doit_scat_field_agenda. \n";
526  doit_scat_field_agendaExecute(ws, doit_scat_field_local,
527  doit_i_field,
528  doit_scat_field_agenda);
529 
530  // Update doit_i_field.
531  out2 << " Execute doit_rte_agenda. \n";
532  doit_rte_agendaExecute(ws, doit_i_field, doit_scat_field_local,
533  doit_rte_agenda);
534 
535  //Convergence test.
536  doit_conv_test_agendaExecute(ws, doit_conv_flag_local,
537  doit_iteration_counter_local,
538  doit_i_field,
539  doit_i_field_old_local,
540  doit_conv_test_agenda);
541 
542  }//end of while loop, convergence is reached.
543 }
544 
545 
546 /* Workspace method: Doxygen documentation will be auto-generated */
547 void
549  // WS Input and Output:
550  Tensor6& doit_i_field,
551  // WS Input:
552  const Tensor6& doit_i_field_old,
553  const Tensor6& doit_scat_field,
554  const ArrayOfIndex& cloudbox_limits,
555  // Calculate scalar gas absorption:
556  const Agenda& abs_scalar_gas_agenda,
557  const Tensor4& vmr_field,
558  // Optical properties for single particle type:
559  const Agenda& spt_calc_agenda,
560  const Vector& scat_za_grid,
561  const Tensor4& pnd_field,
562  // Optical properties for gases and particles:
563  const Agenda& opt_prop_part_agenda,
564  const Agenda& opt_prop_gas_agenda,
565  // Propagation path calculation:
566  const Agenda& ppath_step_agenda,
567  const Vector& p_grid,
568  const Tensor3& z_field,
569  const Matrix& r_geoid,
570  const Matrix& z_surface,
571  // Calculate thermal emission:
572  const Tensor3& t_field,
573  const Vector& f_grid,
574  const Index& f_index,
575  const Agenda& surface_prop_agenda,
576  const Index& doit_za_interp,
577  const Verbosity& verbosity
578  )
579 {
582 
583  out2 << " doit_i_fieldUpdate1D: Radiative transfer calculation in cloudbox\n";
584  out2 << " ------------------------------------------------------------- \n";
585 
586  // ---------- Check the input ----------------------------------------
587 
588  // Agendas
589  chk_not_empty( "spt_calc_agenda", spt_calc_agenda);
590  chk_not_empty( "opt_prop_part_agenda", opt_prop_part_agenda);
591  chk_not_empty( "opt_prop_gas_agenda", opt_prop_gas_agenda);
592  chk_not_empty( "ppath_step_agenda", ppath_step_agenda);
593 
594  if (cloudbox_limits.nelem() != 2)
595  throw runtime_error(
596  "The cloudbox dimension is not 1D! \n"
597  "Do you really want to do a 1D calculation? \n"
598  "If not, use *doit_i_fieldUpdateSeq3D*.\n"
599  );
600 
601  // Number of zenith angles.
602  const Index N_scat_za = scat_za_grid.nelem();
603 
604  if (scat_za_grid[0] != 0. || scat_za_grid[N_scat_za-1] != 180.)
605  throw runtime_error("The range of *scat_za_grid* must [0 180].");
606 
607  if( p_grid.nelem() < 2 )
608  throw runtime_error( "The length of *p_grid* must be >= 2." );
609  chk_if_decreasing( "p_grid", p_grid );
610 
611  chk_size("z_field", z_field, p_grid.nelem(), 1, 1);
612  chk_size("t_field", t_field, p_grid.nelem(), 1, 1);
613 
614  const Vector dummy(1,0.);
615  chk_atm_surface( "r_geoid", r_geoid, 1, dummy,
616  dummy);
617 
618  // Frequency grid
619  //
620  if( f_grid.nelem() == 0 )
621  throw runtime_error( "The frequency grid is empty." );
622  chk_if_increasing( "f_grid", f_grid );
623 
624  // Is the frequency index valid?
625  if ( f_index >= f_grid.nelem() )
626  throw runtime_error("*f_index* is greater than number of elements in the\n"
627  "frequency grid.\n");
628 
629  if( !(doit_za_interp == 0 || doit_za_interp == 1 ) )
630  throw runtime_error( "Interpolation method is not defined. Use \n"
631  "*doit_za_interpSet*.\n");
632 
633  const Index stokes_dim = doit_scat_field.ncols();
634  assert(stokes_dim > 0 || stokes_dim < 5);
635 
636 
637  // These variables are calculated internally, so assertions should be o.k.
638  assert( is_size( doit_i_field,
639  (cloudbox_limits[1] - cloudbox_limits[0]) + 1, 1, 1,
640  N_scat_za, 1, stokes_dim));
641 
642  assert( is_size( doit_i_field_old,
643  (cloudbox_limits[1] - cloudbox_limits[0]) + 1, 1, 1,
644  scat_za_grid.nelem(), 1, stokes_dim));
645 
646  assert( is_size( doit_scat_field,
647  (cloudbox_limits[1] - cloudbox_limits[0]) + 1, 1, 1,
648  N_scat_za, 1, stokes_dim));
649 
650  // FIXME: Check *vmr_field*
651 
652  // -------------- End of checks --------------------------------------
653 
654 
655  //=======================================================================
656  // Calculate scattering coefficients for all positions in the cloudbox
657  //=======================================================================
658  out3 << "Calculate single particle properties \n";
659 
660  // At this place only the particle properties are calculated. Gaseous
661  // absorption is calculated inside the radiative transfer part. Inter-
662  // polating absorption coefficients for gaseous species gives very bad
663  // results, so they are calulated for interpolated VMRs,
664  // temperature and pressure.
665 
666  // To use special interpolation functions for atmospheric fields we
667  // use ext_mat_field and abs_vec_field:
668  Tensor5 ext_mat_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
669  stokes_dim, stokes_dim, 0.);
670  Tensor4 abs_vec_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
671  stokes_dim, 0.);
672 
673  //Only dummy variable:
674  Index scat_aa_index_local = 0;
675 
676  //Loop over all directions, defined by scat_za_grid
677  for( Index scat_za_index_local = 0; scat_za_index_local < N_scat_za;
678  scat_za_index_local ++)
679  {
680  // This function has to be called inside the angular loop, as
681  // spt_calc_agenda takes *scat_za_index_local* and *scat_aa_index*
682  // from the workspace.
683  // *scat_p_index* is needed for communication with agenda
684  // *opt_prop_part_agenda*.
685  cloud_fieldsCalc(ws, ext_mat_field, abs_vec_field,
686  spt_calc_agenda,
687  opt_prop_part_agenda, scat_za_index_local,
688  scat_aa_index_local,
689  cloudbox_limits, t_field, pnd_field, verbosity);
690 
691  //======================================================================
692  // Radiative transfer inside the cloudbox
693  //=====================================================================
694 
695  for(Index p_index = cloudbox_limits[0]; p_index
696  <= cloudbox_limits[1]; p_index ++)
697  {
698  if ( (p_index!=0) || (scat_za_grid[scat_za_index_local] <= 90.))
699  {
700  cloud_ppath_update1D_noseq(ws, doit_i_field,
701  p_index, scat_za_index_local,
702  scat_za_grid,
703  cloudbox_limits, doit_i_field_old,
704  doit_scat_field,
705  abs_scalar_gas_agenda, vmr_field,
706  opt_prop_gas_agenda, ppath_step_agenda,
707  p_grid, z_field, r_geoid, z_surface,
708  t_field, f_grid, f_index, ext_mat_field,
709  abs_vec_field,
710  surface_prop_agenda, doit_za_interp,
711  verbosity);
712  }
713  }
714  }// Closes loop over scat_za_grid.
715 }
716 
717 
718 /* Workspace method: Doxygen documentation will be auto-generated */
719 void
721  // WS Input and Output:
722  Tensor6& doit_i_field,
723  // WS Input:
724  const Tensor6& doit_scat_field,
725  const ArrayOfIndex& cloudbox_limits,
726  // Calculate scalar gas absorption:
727  const Agenda& abs_scalar_gas_agenda,
728  const Tensor4& vmr_field,
729  // Optical properties for single particle type:
730  const Agenda& spt_calc_agenda,
731  const Vector& scat_za_grid,
732  const Tensor4& pnd_field,
733  // Optical properties for gases and particles:
734  const Agenda& opt_prop_part_agenda,
735  const Agenda& opt_prop_gas_agenda,
736  // Propagation path calculation:
737  const Agenda& ppath_step_agenda,
738  const Vector& p_grid,
739  const Tensor3& z_field,
740  const Matrix& r_geoid,
741  const Matrix& z_surface,
742  // Calculate thermal emission:
743  const Tensor3& t_field,
744  const Vector& f_grid,
745  const Index& f_index,
746  const Agenda& surface_prop_agenda, //STR
747  const Index& doit_za_interp,
748  const Verbosity& verbosity)
749 {
752 
753  out2<<" doit_i_fieldUpdateSeq1D: Radiative transfer calculation in cloudbox\n";
754  out2 << " ------------------------------------------------------------- \n";
755 
756  // ---------- Check the input ----------------------------------------
757 
758  // Agendas
759  chk_not_empty( "abs_scalar_gas_agenda", abs_scalar_gas_agenda);
760  chk_not_empty( "spt_calc_agenda", spt_calc_agenda);
761  chk_not_empty( "opt_prop_part_agenda", opt_prop_part_agenda);
762  chk_not_empty( "opt_prop_gas_agenda", opt_prop_gas_agenda);
763  chk_not_empty( "ppath_step_agenda", ppath_step_agenda);
764 
765  if (cloudbox_limits.nelem() != 2)
766  throw runtime_error(
767  "The cloudbox dimension is not 1D! \n"
768  "Do you really want to do a 1D calculation? \n"
769  "For 3D use *doit_i_fieldUpdateSeq3D*.\n"
770  );
771 
772  // Number of zenith angles.
773  const Index N_scat_za = scat_za_grid.nelem();
774 
775  if (scat_za_grid[0] != 0. || scat_za_grid[N_scat_za-1] != 180.)
776  throw runtime_error("The range of *scat_za_grid* must [0 180].");
777 
778  if( p_grid.nelem() < 2 )
779  throw runtime_error( "The length of *p_grid* must be >= 2." );
780  chk_if_decreasing( "p_grid", p_grid );
781 
782  chk_size("z_field", z_field, p_grid.nelem(), 1, 1);
783  chk_size("t_field", t_field, p_grid.nelem(), 1, 1);
784 
785  const Vector dummy(1,0.);
786  chk_atm_surface( "r_geoid", r_geoid, 1, dummy,
787  dummy);
788 
789  // Frequency grid
790  //
791  if( f_grid.nelem() == 0 )
792  throw runtime_error( "The frequency grid is empty." );
793  chk_if_increasing( "f_grid", f_grid );
794 
795  // Is the frequency index valid?
796  if ( f_index >= f_grid.nelem() )
797  throw runtime_error("*f_index* is greater than number of elements in the\n"
798  "frequency grid.\n");
799 
800  if( !(doit_za_interp == 0 || doit_za_interp == 1 ) )
801  throw runtime_error( "Interpolation method is not defined. Use \n"
802  "*doit_za_interpSet*.\n");
803 
804  const Index stokes_dim = doit_scat_field.ncols();
805  assert(stokes_dim > 0 || stokes_dim < 5);
806 
807 
808  // These variables are calculated internally, so assertions should be o.k.
809  assert( is_size( doit_i_field,
810  (cloudbox_limits[1] - cloudbox_limits[0]) + 1, 1, 1,
811  N_scat_za, 1, stokes_dim));
812 
813  assert( is_size( doit_scat_field,
814  (cloudbox_limits[1] - cloudbox_limits[0]) + 1, 1, 1,
815  N_scat_za, 1, stokes_dim));
816 
817  // FIXME: Check *vmr_field*
818 
819  // -------------- End of checks --------------------------------------
820 
821 
822  //=======================================================================
823  // Calculate scattering coefficients for all positions in the cloudbox
824  //=======================================================================
825  out3 << "Calculate single particle properties \n";
826 
827  // At this place only the particle properties are calculated. Gaseous
828  // absorption is calculated inside the radiative transfer part. Inter-
829  // polating absorption coefficients for gaseous species gives very bad
830  // results, so they are calulated for interpolated VMRs,
831  // temperature and pressure.
832 
833  // To use special interpolation functions for atmospheric fields we
834  // use ext_mat_field and abs_vec_field:
835  Tensor5 ext_mat_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
836  stokes_dim, stokes_dim, 0.);
837  Tensor4 abs_vec_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
838  stokes_dim, 0.);
839 
840 
841  // If theta is between 90° and the limiting value, the intersection point
842  // is exactly at the same level as the starting point (cp. AUG)
843  Numeric theta_lim = 180. - asin((r_geoid(0,0)+
844  z_field(cloudbox_limits[0],0,0))/
845  (r_geoid(0,0)+
846  z_field(cloudbox_limits[1],0,0)))*RAD2DEG;
847  //Only dummy variables:
848  Index scat_aa_index_local = 0;
849 
850  //Loop over all directions, defined by scat_za_grid
851  for(Index scat_za_index_local = 0; scat_za_index_local < N_scat_za;
852  scat_za_index_local ++)
853  {
854  // This function has to be called inside the angular loop, as
855  // spt_calc_agenda takes *scat_za_index* and *scat_aa_index*
856  // from the workspace.
857  // *scat_p_index* is needed for communication with agenda
858  // *opt_prop_part_agenda*.
859  cloud_fieldsCalc(ws, ext_mat_field, abs_vec_field,
860  spt_calc_agenda, opt_prop_part_agenda,
861  scat_za_index_local, scat_aa_index_local,
862  cloudbox_limits, t_field, pnd_field, verbosity);
863 
864 
865 
866  // xml_write_to_file("ext_mat_field.xml", ext_mat_field );
867  // xml_write_to_file("abs_vec_field.xml", ext_mat_field );
868 
869  //======================================================================
870  // Radiative transfer inside the cloudbox
871  //=====================================================================
872 
873 
874  // Sequential update for uplooking angles
875  if ( scat_za_grid[scat_za_index_local] <= 90.)
876  {
877  // Loop over all positions inside the cloud box defined by the
878  // cloudbox_limits excluding the upper boundary. For uplooking
879  // directions, we start from cloudbox_limits[1]-1 and go down
880  // to cloudbox_limits[0] to do a sequential update of the
881  // radiation field
882  for(Index p_index = cloudbox_limits[1]-1; p_index
883  >= cloudbox_limits[0]; p_index --)
884  {
885  cloud_ppath_update1D(ws, doit_i_field,
886  p_index, scat_za_index_local, scat_za_grid,
887  cloudbox_limits, doit_scat_field,
888  abs_scalar_gas_agenda, vmr_field,
889  opt_prop_gas_agenda, ppath_step_agenda,
890  p_grid, z_field, r_geoid, z_surface,
891  t_field, f_grid, f_index, ext_mat_field,
892  abs_vec_field,
893  surface_prop_agenda, doit_za_interp,
894  verbosity);
895  }
896  }
897  else if ( scat_za_grid[scat_za_index_local] >= theta_lim)
898  {
899  //
900  // Sequential updating for downlooking angles
901  //
902  for(Index p_index = cloudbox_limits[0]+1; p_index
903  <= cloudbox_limits[1]; p_index ++)
904  {
905  cloud_ppath_update1D(ws, doit_i_field,
906  p_index, scat_za_index_local, scat_za_grid,
907  cloudbox_limits, doit_scat_field,
908  abs_scalar_gas_agenda, vmr_field,
909  opt_prop_gas_agenda, ppath_step_agenda,
910  p_grid, z_field, r_geoid, z_surface,
911  t_field, f_grid, f_index, ext_mat_field,
912  abs_vec_field,
913  surface_prop_agenda, doit_za_interp,
914  verbosity);
915  }// Close loop over p_grid (inside cloudbox).
916  } // end if downlooking.
917 
918  //
919  // Limb looking:
920  // We have to include a special case here, as we may miss the endpoints
921  // when the intersection point is at the same level as the aactual point.
922  // To be save we loop over the full cloudbox. Inside the function
923  // cloud_ppath_update1D it is checked whether the intersection point is
924  // inside the cloudbox or not.
925  else if ( scat_za_grid[scat_za_index_local] > 90. &&
926  scat_za_grid[scat_za_index_local] < theta_lim )
927  {
928  for(Index p_index = cloudbox_limits[0]; p_index
929  <= cloudbox_limits[1]; p_index ++)
930  {
931  // For this case the cloudbox goes down to the surface and we
932  // look downwards. These cases are outside the cloudbox and
933  // not needed. Switch is included here, as ppath_step_agenda
934  // gives an error for such cases.
935  if (!(p_index == 0 && scat_za_grid[scat_za_index_local] > 90.))
936  {
937  cloud_ppath_update1D(ws, doit_i_field,
938  p_index, scat_za_index_local,
939  scat_za_grid,
940  cloudbox_limits, doit_scat_field,
941  abs_scalar_gas_agenda, vmr_field,
942  opt_prop_gas_agenda, ppath_step_agenda,
943  p_grid, z_field, r_geoid, z_surface,
944  t_field, f_grid, f_index, ext_mat_field,
945  abs_vec_field,
946  surface_prop_agenda, doit_za_interp,
947  verbosity);
948  }
949  }
950  }
951  }// Closes loop over scat_za_grid.
952 } // End of the function.
953 
954 
955 /* Workspace method: Doxygen documentation will be auto-generated */
956 void
958  // WS Output and Input:
959  Tensor6& doit_i_field,
960  // WS Input:
961  const Tensor6& doit_scat_field,
962  const ArrayOfIndex& cloudbox_limits,
963  // Calculate scalar gas absorption:
964  const Agenda& abs_scalar_gas_agenda,
965  const Tensor4& vmr_field,
966  // Optical properties for single particle type:
967  const Agenda& spt_calc_agenda,
968  const Vector& scat_za_grid,
969  const Vector& scat_aa_grid,
970  const Tensor4& pnd_field,
971  // Optical properties for gases and particles:
972  const Agenda& opt_prop_part_agenda,
973  const Agenda& opt_prop_gas_agenda,
974  // Propagation path calculation:
975  const Agenda& ppath_step_agenda,
976  const Vector& p_grid,
977  const Vector& lat_grid,
978  const Vector& lon_grid,
979  const Tensor3& z_field,
980  const Matrix& r_geoid,
981  const Matrix& z_surface,
982  // Calculate thermal emission:
983  const Tensor3& t_field,
984  const Vector& f_grid,
985  const Index& f_index,
986  const Index& doit_za_interp,
987  const Verbosity& verbosity)
988 {
991 
992  out2<<" doit_i_fieldUpdateSeq3D: Radiative transfer calculatiuon in cloudbox.\n";
993  out2 << " ------------------------------------------------------------- \n";
994 
995  // ---------- Check the input ----------------------------------------
996 
997  // Agendas
998  chk_not_empty( "abs_scalar_gas_agenda", abs_scalar_gas_agenda);
999  chk_not_empty( "spt_calc_agenda", spt_calc_agenda);
1000  chk_not_empty( "opt_prop_part_agenda", opt_prop_part_agenda);
1001  chk_not_empty( "opt_prop_gas_agenda", opt_prop_gas_agenda);
1002  chk_not_empty( "ppath_step_agenda", ppath_step_agenda);
1003 
1004  if (cloudbox_limits.nelem() != 6)
1005  throw runtime_error(
1006  "The cloudbox dimension is not 3D! \n"
1007  "Do you really want to do a 3D calculation? \n"
1008  "For 1D use *doit_i_fieldUpdateSeq1D*.\n"
1009  );
1010 
1011  // Number of zenith angles.
1012  const Index N_scat_za = scat_za_grid.nelem();
1013 
1014  if (scat_za_grid[0] != 0. || scat_za_grid[N_scat_za-1] != 180.)
1015  throw runtime_error("The range of *scat_za_grid* must [0 180].");
1016 
1017  // Number of azimuth angles.
1018  const Index N_scat_aa = scat_aa_grid.nelem();
1019 
1020  if (scat_aa_grid[0] != 0. || scat_aa_grid[N_scat_aa-1] != 360.)
1021  throw runtime_error("The range of *scat_za_grid* must [0 360].");
1022 
1023  // Check atmospheric grids
1024  chk_atm_grids(3, p_grid, lat_grid, lon_grid);
1025 
1026  // Check atmospheric fields
1027  chk_size("z_field", z_field, p_grid.nelem(), lat_grid.nelem(),
1028  lon_grid.nelem());
1029  chk_size("t_field", t_field, p_grid.nelem(), lat_grid.nelem(),
1030  lon_grid.nelem());
1031 
1032  chk_atm_surface( "r_geoid", r_geoid, 3, lat_grid,
1033  lon_grid);
1034 
1035  // Frequency grid
1036  //
1037  if( f_grid.nelem() == 0 )
1038  throw runtime_error( "The frequency grid is empty." );
1039  chk_if_increasing( "f_grid", f_grid );
1040 
1041  // Is the frequency index valid?
1042  if ( f_index >= f_grid.nelem() )
1043  throw runtime_error("*f_index* is greater than number of elements in the\n"
1044  "frequency grid.\n");
1045 
1046  if( !(doit_za_interp == 0 || doit_za_interp == 1 ) )
1047  throw runtime_error( "Interpolation method is not defined. Use \n"
1048  "*doit_za_interpSet*.\n");
1049 
1050  const Index stokes_dim = doit_scat_field.ncols();
1051  assert(stokes_dim > 0 || stokes_dim < 5);
1052 
1053  // These variables are calculated internally, so assertions should be o.k.
1054  assert( is_size( doit_i_field,
1055  (cloudbox_limits[1] - cloudbox_limits[0]) + 1,
1056  (cloudbox_limits[3] - cloudbox_limits[2]) + 1,
1057  (cloudbox_limits[5] - cloudbox_limits[4]) + 1,
1058  N_scat_za,
1059  N_scat_aa,
1060  stokes_dim));
1061 
1062  assert( is_size( doit_scat_field,
1063  (cloudbox_limits[1] - cloudbox_limits[0]) + 1,
1064  (cloudbox_limits[3] - cloudbox_limits[2]) + 1,
1065  (cloudbox_limits[5] - cloudbox_limits[4]) + 1,
1066  N_scat_za,
1067  N_scat_aa,
1068  stokes_dim));
1069 
1070  // FIXME: Check *vmr_field*
1071 
1072  // ---------- End of checks ------------------------------------------
1073 
1074 
1075  //=======================================================================
1076  // Calculate coefficients for all positions in the cloudbox
1077  //=======================================================================
1078  out3 << "Calculate single particle properties \n";
1079 
1080  // At this place only the particle properties are calculated. Gaseous
1081  // absorption is calculated inside the radiative transfer part. Inter-
1082  // polating absorption coefficients for gaseous species gives very bad
1083  // results, so they are
1084  // calulated for interpolated VMRs, temperature and pressure.
1085 
1086  // Define shorter names for cloudbox_limits.
1087 
1088  const Index p_low = cloudbox_limits[0];
1089  const Index p_up = cloudbox_limits[1];
1090  const Index lat_low = cloudbox_limits[2];
1091  const Index lat_up = cloudbox_limits[3];
1092  const Index lon_low = cloudbox_limits[4];
1093  const Index lon_up = cloudbox_limits[5];
1094 
1095  // To use special interpolation functions for atmospheric fields we
1096  // use ext_mat_field and abs_vec_field:
1097  Tensor5 ext_mat_field(p_up-p_low+1, lat_up-lat_low+1, lon_up-lon_low+1,
1098  stokes_dim, stokes_dim, 0.);
1099  Tensor4 abs_vec_field(p_up-p_low+1, lat_up-lat_low+1, lon_up-lon_low+1,
1100  stokes_dim, 0.);
1101 
1102 
1103  //Loop over all directions, defined by scat_za_grid
1104  for(Index scat_za_index = 0; scat_za_index < N_scat_za; scat_za_index ++)
1105  {
1106  //Loop over azimuth directions (scat_aa_grid). First and last point in
1107  // azimuth angle grid are euqal. Start with second element.
1108  for(Index scat_aa_index = 1; scat_aa_index < N_scat_aa; scat_aa_index ++)
1109  {
1110  //==================================================================
1111  // Radiative transfer inside the cloudbox
1112  //==================================================================
1113 
1114  // This function has to be called inside the angular loop, as
1115  // it spt_calc_agenda takes *scat_za_index* and *scat_aa_index*
1116  // from the workspace.
1117  cloud_fieldsCalc(ws, ext_mat_field, abs_vec_field,
1118  spt_calc_agenda,
1119  opt_prop_part_agenda, scat_za_index,
1120  scat_aa_index, cloudbox_limits, t_field,
1121  pnd_field, verbosity);
1122 
1123 
1124  Vector stokes_vec(stokes_dim,0.);
1125 
1126  Numeric theta_lim = 180. - asin((r_geoid(0,0)+z_field(p_low,0,0))
1127  /(r_geoid(0,0)+z_field(p_up,0,0)))
1128  *RAD2DEG;
1129 
1130  // Sequential update for uplooking angles
1131  if ( scat_za_grid[scat_za_index] <= 90.)
1132  {
1133  // Loop over all positions inside the cloud box defined by the
1134  // cloudbox_limits exculding the upper boundary. For uplooking
1135  // directions, we start from cloudbox_limits[1]-1 and go down
1136  // to cloudbox_limits[0] to do a sequential update of the
1137  // aradiation field
1138  for(Index p_index = p_up-1; p_index >= p_low; p_index --)
1139  {
1140  for(Index lat_index = lat_low; lat_index <= lat_up;
1141  lat_index ++)
1142  {
1143  for(Index lon_index = lon_low; lon_index <= lon_up;
1144  lon_index ++)
1145  {
1146  cloud_ppath_update3D(ws, doit_i_field,
1147  p_index, lat_index,
1148  lon_index, scat_za_index,
1149  scat_aa_index, scat_za_grid,
1150  scat_aa_grid, cloudbox_limits,
1151  doit_scat_field,
1152  abs_scalar_gas_agenda,
1153  vmr_field,
1154  opt_prop_gas_agenda,
1155  ppath_step_agenda, p_grid,
1156  lat_grid, lon_grid, z_field,
1157  r_geoid, z_surface, t_field,
1158  f_grid, f_index,
1159  ext_mat_field, abs_vec_field,
1160  doit_za_interp,
1161  verbosity);
1162  }
1163  }
1164  }
1165  }// close up-looking case
1166  else if ( scat_za_grid[scat_za_index] > theta_lim)
1167  {
1168  //
1169  // Sequential updating for downlooking angles
1170  //
1171  for(Index p_index = p_low+1; p_index <= p_up; p_index ++)
1172  {
1173  for(Index lat_index = lat_low; lat_index <= lat_up;
1174  lat_index ++)
1175  {
1176  for(Index lon_index = lon_low; lon_index <= lon_up;
1177  lon_index ++)
1178  {
1179  cloud_ppath_update3D(ws, doit_i_field,
1180  p_index, lat_index,
1181  lon_index, scat_za_index,
1182  scat_aa_index, scat_za_grid,
1183  scat_aa_grid, cloudbox_limits,
1184  doit_scat_field,
1185  abs_scalar_gas_agenda,
1186  vmr_field,
1187  opt_prop_gas_agenda,
1188  ppath_step_agenda, p_grid,
1189  lat_grid, lon_grid, z_field,
1190  r_geoid, z_surface, t_field,
1191  f_grid, f_index,
1192  ext_mat_field, abs_vec_field,
1193  doit_za_interp,
1194  verbosity);
1195  }
1196  }
1197  }
1198  } // end if downlooking.
1199 
1200  //
1201  // Limb looking:
1202  // We have to include a special case here, as we may miss the endpoints
1203  // when the intersection point is at the same level as the actual point.
1204  // To be save we loop over the full cloudbox. Inside the function
1205  // cloud_ppath_update3D it is checked whether the intersection point is
1206  // inside the cloudbox or not.
1207  else if ( scat_za_grid[scat_za_index] > 90. &&
1208  scat_za_grid[scat_za_index] < theta_lim )
1209  {
1210  for(Index p_index = p_low; p_index <= p_up; p_index ++)
1211  {
1212  // For this case the cloudbox goes down to the surface an we
1213  // look downwards. These cases are outside the cloudbox and
1214  // not needed. Switch is included here, as ppath_step_agenda
1215  // gives an error for such cases.
1216  if (!(p_index == 0 && scat_za_grid[scat_za_index] > 90.))
1217  {
1218  for(Index lat_index = lat_low; lat_index <= lat_up;
1219  lat_index ++)
1220  {
1221  for(Index lon_index = lon_low; lon_index <= lon_up;
1222  lon_index ++)
1223  {
1224  cloud_ppath_update3D(ws, doit_i_field,
1225  p_index,
1226  lat_index,
1227  lon_index, scat_za_index,
1228  scat_aa_index,
1229  scat_za_grid,
1230  scat_aa_grid,
1231  cloudbox_limits,
1232  doit_scat_field,
1233  abs_scalar_gas_agenda,
1234  vmr_field,
1235  opt_prop_gas_agenda,
1236  ppath_step_agenda, p_grid,
1237  lat_grid, lon_grid,
1238  z_field,
1239  r_geoid, z_surface,
1240  t_field, f_grid,
1241  f_index,
1242  ext_mat_field,
1243  abs_vec_field,
1244  doit_za_interp,
1245  verbosity);
1246  }
1247  }
1248  }
1249  }
1250  }
1251  } // Closes loop over aa_grid.
1252  }// Closes loop over scat_za_grid.
1253 
1254  doit_i_field(joker, joker, joker, joker, 0, joker) =
1255  doit_i_field(joker, joker, joker, joker, N_scat_aa-1, joker);
1256 
1257 }
1258 
1259 
1260 /* Workspace method: Doxygen documentation will be auto-generated */
1261 void
1263  // WS Output:
1264  Tensor6& doit_i_field,
1265  // spt_calc_agenda:
1266  Index& scat_za_index ,
1267  // WS Input:
1268  const Tensor6& doit_scat_field,
1269  const ArrayOfIndex& cloudbox_limits,
1270  // Calculate scalar gas absorption:
1271  const Agenda& abs_scalar_gas_agenda,
1272  const Tensor4& vmr_field,
1273  // Optical properties for single particle type:
1274  const Agenda& spt_calc_agenda,
1275  const Vector& scat_za_grid,
1276  const Tensor4& pnd_field,
1277  // Optical properties for gases and particles:
1278  const Agenda& opt_prop_part_agenda,
1279  const Agenda& opt_prop_gas_agenda,
1280  // Propagation path calculation:
1281  const Agenda& ppath_step_agenda,
1282  const Vector& p_grid,
1283  const Tensor3& z_field,
1284  const Matrix& r_geoid,
1285  // Calculate thermal emission:
1286  const Tensor3& t_field,
1287  const Vector& f_grid,
1288  const Index& f_index,
1289  const Verbosity& verbosity)
1290 {
1291  CREATE_OUT2
1292  CREATE_OUT3
1293 
1294  out2 << " doit_i_fieldUpdateSeq1DPP: Radiative transfer calculation in cloudbox.\n";
1295  out2 << " --------------------------------------------------------------------- \n";
1296 
1297  const Index stokes_dim = doit_scat_field.ncols();
1298  // const Index atmosphere_dim = 1;
1299 
1300  //Check the input
1301 
1302  if (stokes_dim < 0 || stokes_dim > 4)
1303  throw runtime_error(
1304  "The dimension of stokes vector must be"
1305  "1,2,3, or 4");
1306 
1307  assert( is_size( doit_i_field,
1308  (cloudbox_limits[1] - cloudbox_limits[0]) + 1,
1309  1,
1310  1,
1311  scat_za_grid.nelem(),
1312  1,
1313  stokes_dim));
1314 
1315  assert( is_size( doit_scat_field,
1316  (cloudbox_limits[1] - cloudbox_limits[0]) + 1,
1317  1,
1318  1,
1319  scat_za_grid.nelem(),
1320  1,
1321  stokes_dim));
1322 
1323  // Is the frequency index valid?
1324  assert( f_index <= f_grid.nelem() );
1325 
1326  // End of checks
1327 
1328 
1329 
1330  // Number of zenith angles.
1331  const Index N_scat_za = scat_za_grid.nelem();
1332 
1333 
1334 
1335  //=======================================================================
1336  // Calculate scattering coefficients for all positions in the cloudbox
1337  //=======================================================================
1338  out3 << "Calculate single particle properties \n";
1339 
1340  // At this place only the particle properties are calculated. Gaseous
1341  // absorption is calculated inside the radiative transfer part. Inter-
1342  // polating absorption coefficients for gaseous species gives very bad
1343  // results, so they are
1344  // calulated for interpolated VMRs, temperature and pressure.
1345 
1346  // To use special interpolation functions for atmospheric fields we
1347  // use ext_mat_field and abs_vec_field:
1348 
1349  Tensor5 ext_mat_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
1350  stokes_dim, stokes_dim, 0.);
1351  Tensor4 abs_vec_field(cloudbox_limits[1] - cloudbox_limits[0] + 1, 1, 1,
1352  stokes_dim, 0.);
1353 
1354  //Loop over all directions, defined by scat_za_grid
1355  for(scat_za_index = 0; scat_za_index < N_scat_za; scat_za_index ++)
1356  {
1357 
1358  //Only dummy variables:
1359  Index scat_aa_index = 0;
1360 
1361  cloud_fieldsCalc(ws, ext_mat_field, abs_vec_field,
1362  spt_calc_agenda,
1363  opt_prop_part_agenda, scat_za_index, scat_aa_index,
1364  cloudbox_limits, t_field,
1365  pnd_field, verbosity);
1366 
1367  //======================================================================
1368  // Radiative transfer inside the cloudbox
1369  //=====================================================================
1370 
1371  Vector stokes_vec(stokes_dim,0.);
1372  // Sequential update for uplooking angles
1373  if ( scat_za_grid[scat_za_index] <= 90)
1374  {
1375  // Loop over all positions inside the cloud box defined by the
1376  // cloudbox_limits exculding the upper boundary. For uplooking
1377  // directions, we start from cloudbox_limits[1]-1 and go down
1378  // to cloudbox_limits[0] to do a sequential update of the
1379  // aradiation field
1380 
1381  // Loop over all positions inside the cloudbox defined by the
1382  // cloudbox_limits.
1383  for(Index p_index = cloudbox_limits[1] -1; p_index
1384  >= cloudbox_limits[0]; p_index --)
1385  {
1386  cloud_ppath_update1D_planeparallel(ws, doit_i_field,
1387  p_index, scat_za_index,
1388  scat_za_grid,
1389  cloudbox_limits,
1390  doit_scat_field,
1391  abs_scalar_gas_agenda,
1392  vmr_field,
1393  opt_prop_gas_agenda,
1394  ppath_step_agenda,
1395  p_grid, z_field, r_geoid,
1396  t_field,
1397  f_grid, f_index,
1398  ext_mat_field,
1399  abs_vec_field,
1400  verbosity);
1401  }
1402  }
1403  else if ( scat_za_grid[scat_za_index] > 90)
1404  {
1405  //
1406  // Sequential updating for downlooking angles
1407  //
1408  for(Index p_index = cloudbox_limits[0]+1; p_index
1409  <= cloudbox_limits[1]; p_index ++)
1410  {
1411  cloud_ppath_update1D_planeparallel(ws, doit_i_field,
1412  p_index, scat_za_index,
1413  scat_za_grid,
1414  cloudbox_limits,
1415  doit_scat_field,
1416  abs_scalar_gas_agenda,
1417  vmr_field,
1418  opt_prop_gas_agenda,
1419  ppath_step_agenda,
1420  p_grid, z_field, r_geoid,
1421  t_field,
1422  f_grid, f_index,
1423  ext_mat_field,
1424  abs_vec_field,
1425  verbosity);
1426  }// Close loop over p_grid (inside cloudbox).
1427  } // end if downlooking.
1428 
1429  }// Closes loop over scat_za_grid.
1430 }
1431 
1432 
1433 /* Workspace method: Doxygen documentation will be auto-generated */
1434 void DoitInit(//WS Output
1435  Index& scat_p_index,
1436  Index& scat_lat_index,
1437  Index& scat_lon_index,
1438  Index& scat_za_index,
1439  Index& scat_aa_index,
1440  Tensor6& doit_scat_field,
1441  Tensor6& doit_i_field,
1442  Index& doit_is_initialized,
1443  // WS Input
1444  const Index& stokes_dim,
1445  const Index& atmosphere_dim,
1446  const Vector& scat_za_grid,
1447  const Vector& scat_aa_grid,
1448  const Index& doit_za_grid_size,
1449  const Index& cloudbox_on,
1450  const ArrayOfIndex& cloudbox_limits,
1451  const ArrayOfSingleScatteringData& scat_data_raw,
1452  const Verbosity& verbosity)
1453 {
1454  if (!cloudbox_on)
1455  {
1456  CREATE_OUT0
1457  doit_is_initialized = 0;
1458  out0 << " Cloudbox is off, DOIT calculation will be skipped.\n";
1459  return;
1460  }
1461 
1462  // -------------- Check the input ------------------------------
1463 
1464  if (stokes_dim < 0 || stokes_dim > 4)
1465  throw runtime_error(
1466  "The dimension of stokes vector must be"
1467  "1,2,3, or 4");
1468 
1469  chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
1470 
1471  // Number of zenith angles.
1472  const Index N_scat_za = scat_za_grid.nelem();
1473 
1474  if (scat_za_grid[0] != 0. || scat_za_grid[N_scat_za-1] != 180.)
1475  throw runtime_error("The range of *scat_za_grid* must [0 180].");
1476 
1477  // Number of azimuth angles.
1478  const Index N_scat_aa = scat_aa_grid.nelem();
1479 
1480  if (scat_aa_grid[0] != 0. || scat_aa_grid[N_scat_aa-1] != 360.)
1481  throw runtime_error("The range of *scat_za_grid* must [0 360].");
1482 
1483  if (doit_za_grid_size < 16)
1484  throw runtime_error(
1485  "*doit_za_grid_size* must be greater than 15 for accurate results");
1486  else if (doit_za_grid_size > 100)
1487  {
1488  CREATE_OUT1
1489  out1 << "Warning: doit_za_grid_size is very large which means that the \n"
1490  << "calculation will be very slow. The recommended value is 19.\n";
1491  }
1492 
1493  if ( cloudbox_limits.nelem()!= 2*atmosphere_dim)
1494  throw runtime_error(
1495  "*cloudbox_limits* is a vector which contains the"
1496  "upper and lower limit of the cloud for all "
1497  "atmospheric dimensions. So its dimension must"
1498  "be 2 x *atmosphere_dim*");
1499 
1500  if (scat_data_raw.nelem() == 0)
1501  throw runtime_error(
1502  "No scattering data files have been added.\n"
1503  "Please use the WSM *ParticleTypeAdd* or \n"
1504  "*ParticleTypeAddAll* to define the cloud \n"
1505  "properties for the scattering calculation.\n"
1506  );
1507 
1508  //------------- end of checks ---------------------------------------
1509 
1510 
1511  // Initialize indices
1512 
1513  scat_p_index = 0;
1514  scat_lat_index = 0;
1515  scat_lon_index = 0;
1516  scat_za_index = 0;
1517  scat_aa_index = 0;
1518 
1519 
1520  // Resize and initialize radiation field in the cloudbox
1521  if (atmosphere_dim == 1)
1522  {
1523  doit_i_field.resize((cloudbox_limits[1] - cloudbox_limits[0]) +1,
1524  1,
1525  1,
1526  scat_za_grid.nelem(),
1527  1,
1528  stokes_dim);
1529 
1530  doit_scat_field.resize((cloudbox_limits[1] - cloudbox_limits[0]) +1,
1531  1,
1532  1,
1533  scat_za_grid.nelem(),
1534  1,
1535  stokes_dim);
1536  }
1537  else if (atmosphere_dim == 3)
1538  {
1539  doit_i_field.resize((cloudbox_limits[1] - cloudbox_limits[0]) +1,
1540  (cloudbox_limits[3] - cloudbox_limits[2]) +1,
1541  (cloudbox_limits[5] - cloudbox_limits[4]) +1,
1542  scat_za_grid.nelem(),
1543  scat_aa_grid.nelem(),
1544  stokes_dim);
1545 
1546  doit_scat_field.resize((cloudbox_limits[1] - cloudbox_limits[0]) +1,
1547  (cloudbox_limits[3] - cloudbox_limits[2]) +1,
1548  (cloudbox_limits[5] - cloudbox_limits[4]) +1,
1549  scat_za_grid.nelem(),
1550  scat_aa_grid.nelem(),
1551  stokes_dim);
1552  }
1553  else
1554  {
1555  throw runtime_error(
1556  "Scattering calculations are not possible for a 2D"
1557  "atmosphere. If you want to do scattering calculations"
1558  "*atmosphere_dim* has to be either 1 or 3"
1559  );
1560  }
1561 
1562  doit_i_field = 0.;
1563  doit_scat_field = 0.;
1564  doit_is_initialized = 1;
1565 }
1566 
1567 
1568 /* Workspace method: Doxygen documentation will be auto-generated */
1570  const Index& doit_iteration_counter,
1571  const Tensor6& doit_i_field,
1572  //Keyword:
1573  const ArrayOfIndex& iterations,
1574  const Verbosity& verbosity)
1575 {
1576  // Checks of doit_i_field have been done elsewhere, e.g. in
1577  // scat_fieldCalc(Limb).
1578 
1579  // If the number of iterations is less than a number specified in the
1580  // keyword *iterations*, this number will be ignored.
1581 
1582  ostringstream os;
1583  os << doit_iteration_counter;
1584 
1585  // All iterations are written to files
1586  if( iterations[0] == 0 )
1587  {
1588  xml_write_to_file("doit_iteration_" + os.str() + ".xml",
1589  doit_i_field, FILE_TYPE_ASCII, verbosity);
1590  }
1591 
1592  // Only the iterations given by the keyword are written to a file
1593  else
1594  {
1595  for (Index i = 0; i<iterations.nelem(); i++)
1596  {
1597  if (doit_iteration_counter == iterations[i])
1598  xml_write_to_file("doit_iteration_" + os.str() + ".xml",
1599  doit_i_field, FILE_TYPE_ASCII, verbosity);
1600  }
1601  }
1602 }
1603 
1604 
1605 /* Workspace method: Doxygen documentation will be auto-generated */
1606 void
1608  // WS Output and Input
1609  Tensor6& doit_scat_field,
1610  //WS Input:
1611  const Agenda& pha_mat_spt_agenda,
1612  const Tensor6& doit_i_field,
1613  const Tensor4& pnd_field,
1614  const Tensor3& t_field,
1615  const Index& atmosphere_dim,
1616  const ArrayOfIndex& cloudbox_limits,
1617  const Vector& scat_za_grid,
1618  const Vector& scat_aa_grid,
1619  const Index& doit_za_grid_size,
1620  const Verbosity& verbosity)
1621 
1622 {
1623  CREATE_OUT2
1624  CREATE_OUT3
1625 
1626  // ------------ Check the input -------------------------------
1627 
1628  // Agenda for calculation of phase matrix
1629  chk_not_empty( "pha_mat_spt_agenda", pha_mat_spt_agenda);
1630 
1631  // Number of zenith angles.
1632  const Index Nza = scat_za_grid.nelem();
1633 
1634  if (scat_za_grid[0] != 0. || scat_za_grid[Nza-1] != 180.)
1635  throw runtime_error("The range of *scat_za_grid* must [0 180].");
1636 
1637  // Number of azimuth angles.
1638  const Index Naa = scat_aa_grid.nelem();
1639 
1640  if (scat_aa_grid[0] != 0. || scat_aa_grid[Naa-1] != 360.)
1641  throw runtime_error("The range of *scat_za_grid* must [0 360].");
1642 
1643  // Get stokes dimension from *doit_scat_field*:
1644  const Index stokes_dim = doit_scat_field.ncols();
1645  assert(stokes_dim > 0 || stokes_dim < 5);
1646 
1647  // Size of particle number density field can not be checked here,
1648  // because the function does not use the atmospheric grids.
1649  // Check will be included after fixing the size of pnd field, so
1650  // that it is defined only inside the cloudbox.
1651 
1652  // Check atmospheric dimension and dimensions of
1653  // radiation field (*doit_i_field*) and scattering integral field
1654  // (*doit_scat_field*)
1655  if (atmosphere_dim == 1)
1656  {
1657  assert( is_size(doit_i_field,
1658  (cloudbox_limits[1] - cloudbox_limits[0]) +1,
1659  1, 1, Nza, 1, stokes_dim));
1660  assert( is_size(doit_scat_field,
1661  (cloudbox_limits[1] - cloudbox_limits[0]) +1,
1662  1, 1, scat_za_grid.nelem(), 1, stokes_dim));
1663  }
1664  else if (atmosphere_dim == 3)
1665  {
1666  assert ( is_size( doit_i_field,
1667  (cloudbox_limits[1] - cloudbox_limits[0]) +1,
1668  (cloudbox_limits[3] - cloudbox_limits[2]) +1,
1669  (cloudbox_limits[5] - cloudbox_limits[4]) +1,
1670  Nza, Naa, stokes_dim));
1671  assert ( is_size( doit_scat_field,
1672  (cloudbox_limits[1] - cloudbox_limits[0]) +1,
1673  (cloudbox_limits[3] - cloudbox_limits[2]) +1,
1674  (cloudbox_limits[5] - cloudbox_limits[4]) +1,
1675  Nza, Naa, stokes_dim));
1676  }
1677  else
1678  {
1679  ostringstream os;
1680  os << "The atmospheric dimension must be 1D or 3D \n"
1681  << "for scattering calculations using the DOIT\n"
1682  << "module, but it is not. The value of *atmosphere_dim*\n"
1683  << "is " << atmosphere_dim << ".";
1684  throw runtime_error( os.str() );
1685  }
1686 
1687  if ( cloudbox_limits.nelem()!= 2*atmosphere_dim)
1688  throw runtime_error(
1689  "*cloudbox_limits* is a vector which contains the"
1690  "upper and lower limit of the cloud for all "
1691  "atmospheric dimensions. So its dimension must"
1692  "be 2 x *atmosphere_dim*");
1693 
1694  // This function should only be used for down-looking cases where no
1695  // optimized zenith angle grid is required.
1696  if (doit_za_grid_size != Nza)
1697  throw runtime_error(
1698  "The zenith angle grids for the computation of\n"
1699  "the scattering integral and the RT part must \n"
1700  "be equal. Check definitions in \n"
1701  "*DoitAngularGridsSet*. The keyword \n"
1702  "'za_grid_opt_file' should be empty. \n"
1703  );
1704 
1705  // ------ end of checks -----------------------------------------------
1706 
1707  // Initialize variables *pha_mat* and *pha_mat_spt*
1708  Tensor4 pha_mat_local(doit_za_grid_size, scat_aa_grid.nelem(),
1709  stokes_dim, stokes_dim, 0.);
1710 
1711  Tensor5 pha_mat_spt_local(pnd_field.nbooks(), doit_za_grid_size,
1712  scat_aa_grid.nelem(), stokes_dim, stokes_dim, 0.);
1713 
1714  // Equidistant step size for integration
1715  Vector grid_stepsize(2);
1716  grid_stepsize[0] = 180./(Numeric)(doit_za_grid_size - 1);
1717  grid_stepsize[1] = 360./(Numeric)(Naa - 1);
1718 
1719  Tensor3 product_field(Nza, Naa, stokes_dim, 0);
1720 
1721  out2 << " Calculate the scattered field\n";
1722 
1723  if ( atmosphere_dim == 1 )
1724  {
1725  Index scat_aa_index_local = 0;
1726 
1727  // Get pha_mat at the grid positions
1728  // Since atmosphere_dim = 1, there is no loop over lat and lon grids
1729  for (Index p_index = 0; p_index<=cloudbox_limits[1]-cloudbox_limits[0] ;
1730  p_index++)
1731  {
1732  Numeric rte_temperature_local =
1733  t_field(p_index + cloudbox_limits[0], 0, 0);
1734  //There is only loop over zenith angle grid ; no azimuth angle grid.
1735  for (Index scat_za_index_local = 0;
1736  scat_za_index_local < Nza; scat_za_index_local ++)
1737  {
1738  // Dummy index
1739  Index index_zero = 0;
1740 
1741  // Calculate the phase matric of a single particle type
1742  out3 << "Calculate the phase matrix \n";
1743  pha_mat_spt_agendaExecute(ws, pha_mat_spt_local,
1744  scat_za_index_local,
1745  index_zero,
1746  index_zero,
1747  p_index,
1748  scat_aa_index_local,
1749  rte_temperature_local,
1750  pha_mat_spt_agenda);
1751 
1752  // Sum over all particle types
1753  pha_matCalc(pha_mat_local, pha_mat_spt_local, pnd_field,
1754  atmosphere_dim, p_index, 0,
1755  0, verbosity);
1756 
1757  out3 << "Multiplication of phase matrix with incoming" <<
1758  " intensities \n";
1759 
1760  product_field = 0;
1761 
1762  // za_in and aa_in are for incoming zenith and azimuth
1763  //angle direction for which pha_mat is calculated
1764  for (Index za_in = 0; za_in < Nza; ++ za_in)
1765  {
1766  for (Index aa_in = 0; aa_in < Naa; ++ aa_in)
1767  {
1768  // Multiplication of phase matrix with incoming
1769  // intensity field.
1770 
1771  for ( Index i = 0; i < stokes_dim; i++)
1772  {
1773  for (Index j = 0; j< stokes_dim; j++)
1774  {
1775  product_field(za_in, aa_in, i) +=
1776  pha_mat_local(za_in, aa_in, i, j) *
1777  doit_i_field(p_index, 0, 0, za_in, 0, j);
1778  }
1779  }
1780 
1781  }//end aa_in loop
1782  }//end za_in loop
1783  //integration of the product of ifield_in and pha
1784  // over zenith angle and azimuth angle grid. It calls
1785  for (Index i = 0; i < stokes_dim; i++)
1786  {
1787  doit_scat_field( p_index, 0, 0, scat_za_index_local, 0, i)
1789  (product_field(joker, joker, i),
1790  scat_za_grid,
1791  scat_aa_grid,
1792  grid_stepsize);
1793 
1794  }//end i loop
1795  }//end za_prop loop
1796  }//end p_index loop
1797  }//end atmosphere_dim = 1
1798 
1799 
1800  //atmosphere_dim = 3
1801  else if( atmosphere_dim == 3 )
1802  {
1803  /*there is a loop over pressure, latitude and longitudeindex
1804  when we calculate the pha_mat from pha_mat_spt and pnd_field
1805  using the method pha_matCalc. */
1806 
1807  for (Index p_index = 0; p_index <=
1808  cloudbox_limits[1] - cloudbox_limits[0];
1809  p_index++)
1810  {
1811  for (Index lat_index = 0; lat_index <=
1812  cloudbox_limits[3] - cloudbox_limits[2]; lat_index++)
1813  {
1814  for (Index lon_index = 0; lon_index <=
1815  cloudbox_limits[5]-cloudbox_limits[4]; lon_index++)
1816  {
1817  Numeric rte_temperature_local =
1818  t_field(p_index + cloudbox_limits[0],
1819  lat_index + cloudbox_limits[2],
1820  lon_index + cloudbox_limits[4]);
1821 
1822  for (Index scat_aa_index_local = 1;
1823  scat_aa_index_local < Naa;
1824  scat_aa_index_local++)
1825  {
1826  for (Index scat_za_index_local = 0;
1827  scat_za_index_local < Nza;
1828  scat_za_index_local ++)
1829  {
1830  out3 << "Calculate phase matrix \n";
1831  pha_mat_spt_agendaExecute(ws, pha_mat_spt_local,
1832  scat_za_index_local,
1833  lat_index,
1834  lon_index,
1835  p_index,
1836  scat_aa_index_local,
1837  rte_temperature_local,
1838  pha_mat_spt_agenda);
1839 
1840  pha_matCalc(pha_mat_local, pha_mat_spt_local,
1841  pnd_field,
1842  atmosphere_dim,
1843  p_index,
1844  lat_index,
1845  lon_index,
1846  verbosity);
1847 
1848  product_field = 0;
1849 
1850  //za_in and aa_in are the incoming directions
1851  //for which pha_mat_spt is calculated
1852  for (Index za_in = 0; za_in < Nza; ++ za_in)
1853  {
1854  for (Index aa_in = 0; aa_in < Naa; ++ aa_in)
1855  {
1856  // Multiplication of phase matrix
1857  // with incloming intensity field.
1858  for ( Index i = 0; i < stokes_dim; i++)
1859  {
1860  for (Index j = 0; j< stokes_dim; j++)
1861  {
1862  product_field(za_in, aa_in, i) +=
1863  pha_mat_local
1864  (za_in, aa_in, i, j) *
1865  doit_i_field(p_index, lat_index,
1866  lon_index,
1867  scat_za_index_local,
1868  scat_aa_index_local,
1869  j);
1870  }
1871  }
1872  }//end aa_in loop
1873  }//end za_in loop
1874  //integration of the product of ifield_in and pha
1875  //over zenith angle and azimuth angle grid. It
1876  //calls here the integration routine
1877  //AngIntegrate_trapezoid_opti
1878  for (Index i = 0; i < stokes_dim; i++)
1879  {
1880  doit_scat_field( p_index,
1881  lat_index,
1882  lon_index,
1883  scat_za_index_local,
1884  scat_aa_index_local,
1885  i) =
1886  AngIntegrate_trapezoid_opti(product_field
1887  ( joker,
1888  joker, i),
1889  scat_za_grid,
1890  scat_aa_grid,
1891  grid_stepsize);
1892  }//end i loop
1893  }//end aa_prop loop
1894  }//end za_prop loop
1895  }//end lon loop
1896  }// end lat loop
1897  }// end p loop
1898  // aa = 0 is the same as aa = 180:
1899  doit_scat_field(joker, joker, joker, joker, 0, joker) =
1900  doit_scat_field(joker, joker, joker, joker, Naa-1, joker);
1901  }// end atmosphere_dim = 3
1902 }
1903 
1904 
1905 /* Workspace method: Doxygen documentation will be auto-generated */
1906 void
1908  // WS Output and Input
1909  Tensor6& doit_scat_field,
1910  //WS Input:
1911  const Agenda& pha_mat_spt_agenda,
1912  const Tensor6& doit_i_field,
1913  const Tensor4& pnd_field,
1914  const Tensor3& t_field,
1915  const Index& atmosphere_dim,
1916  const ArrayOfIndex& cloudbox_limits,
1917  const Vector& scat_za_grid,
1918  const Vector& scat_aa_grid,
1919  const Index& doit_za_grid_size,
1920  const Index& doit_za_interp,
1921  const Verbosity& verbosity)
1922 {
1923  CREATE_OUT2
1924  CREATE_OUT3
1925 
1926  // ------------ Check the input -------------------------------
1927 
1928  // Agenda for calculation of phase matrix
1929  chk_not_empty( "pha_mat_spt_agenda", pha_mat_spt_agenda);
1930 
1931  // Number of zenith angles.
1932  const Index Nza = scat_za_grid.nelem();
1933 
1934  if (scat_za_grid[0] != 0. || scat_za_grid[Nza-1] != 180.)
1935  throw runtime_error("The range of *scat_za_grid* must [0 180].");
1936 
1937  // Number of azimuth angles.
1938  const Index Naa = scat_aa_grid.nelem();
1939 
1940  if (scat_aa_grid[0] != 0. || scat_aa_grid[Naa-1] != 360.)
1941  throw runtime_error("The range of *scat_za_grid* must [0 360].");
1942 
1943  // Get stokes dimension from *doit_scat_field*:
1944  const Index stokes_dim = doit_scat_field.ncols();
1945  assert(stokes_dim > 0 || stokes_dim < 5);
1946 
1947  // Size of particle number density field can not be checked here,
1948  // because the function does not use the atmospheric grids.
1949  // Check will be included after fixing the size of pnd field, so
1950  // that it is defined only inside the cloudbox.
1951 
1952  // Check atmospheric dimension and dimensions of
1953  // radiation field (*doit_i_field*) and scattering integral field
1954  // (*doit_scat_field*)
1955  if (atmosphere_dim == 1)
1956  {
1957  assert( is_size(doit_i_field,
1958  (cloudbox_limits[1] - cloudbox_limits[0]) +1,
1959  1, 1, Nza, 1, stokes_dim));
1960  assert( is_size(doit_scat_field,
1961  (cloudbox_limits[1] - cloudbox_limits[0]) +1,
1962  1, 1, scat_za_grid.nelem(), 1, stokes_dim));
1963  }
1964  else if (atmosphere_dim == 3)
1965  {
1966  assert ( is_size( doit_i_field,
1967  (cloudbox_limits[1] - cloudbox_limits[0]) +1,
1968  (cloudbox_limits[3] - cloudbox_limits[2]) +1,
1969  (cloudbox_limits[5] - cloudbox_limits[4]) +1,
1970  Nza, Naa, stokes_dim));
1971  assert ( is_size( doit_scat_field,
1972  (cloudbox_limits[1] - cloudbox_limits[0]) +1,
1973  (cloudbox_limits[3] - cloudbox_limits[2]) +1,
1974  (cloudbox_limits[5] - cloudbox_limits[4]) +1,
1975  Nza, Naa, stokes_dim));
1976  }
1977  else
1978  {
1979  ostringstream os;
1980  os << "The atmospheric dimension must be 1D or 3D \n"
1981  << "for scattering calculations using the DOIT\n"
1982  << "module, but it is not. The value of *atmosphere_dim*\n"
1983  << "is " << atmosphere_dim << ".";
1984  throw runtime_error( os.str() );
1985  }
1986 
1987  if( !(doit_za_interp == 0 || doit_za_interp == 1 ) )
1988  throw runtime_error( "Interpolation method is not defined. Use \n"
1989  "*doit_za_interpSet*.\n");
1990 
1991  if ( cloudbox_limits.nelem()!= 2*atmosphere_dim)
1992  throw runtime_error(
1993  "*cloudbox_limits* is a vector which contains the"
1994  "upper and lower limit of the cloud for all "
1995  "atmospheric dimensions. So its dimension must"
1996  "be 2 x *atmosphere_dim*");
1997 
1998  if (doit_za_grid_size < 16)
1999  throw runtime_error(
2000  "*doit_za_grid_size* must be greater than 15 for"
2001  "accurate results");
2002  else if (doit_za_grid_size > 100)
2003  {
2004  CREATE_OUT1
2005  out1 << "Warning: doit_za_grid_size is very large which means that the \n"
2006  << "calculation will be very slow. The recommended value is 19.\n";
2007  }
2008 
2009  // ------ end of checks -----------------------------------------------
2010 
2011  // Initialize variables *pha_mat* and *pha_mat_spt*
2012  Tensor4 pha_mat_local(doit_za_grid_size, scat_aa_grid.nelem(),
2013  stokes_dim, stokes_dim, 0.);
2014 
2015  Tensor5 pha_mat_spt_local(pnd_field.nbooks(), doit_za_grid_size,
2016  scat_aa_grid.nelem(), stokes_dim, stokes_dim, 0.);
2017 
2018 
2019  // Create the grids for the calculation of the scattering integral.
2020  Vector za_grid;
2021  nlinspace(za_grid, 0, 180, doit_za_grid_size);
2022 
2023  // Two interpolations are required. First we have to interpolate the
2024  // intensity field on the equidistant grid:
2025  ArrayOfGridPos gp_za_i(doit_za_grid_size);
2026  gridpos(gp_za_i, scat_za_grid, za_grid);
2027 
2028  Matrix itw_za_i(doit_za_grid_size, 2);
2029  interpweights(itw_za_i, gp_za_i);
2030 
2031  // Intensity field interpolated on equidistant grid.
2032  Matrix doit_i_field_int(doit_za_grid_size, stokes_dim, 0);
2033 
2034  // Second, we have to interpolate the scattering integral on the RT
2035  // zenith angle grid.
2036  ArrayOfGridPos gp_za(Nza);
2037  gridpos(gp_za, za_grid, scat_za_grid);
2038 
2039  Matrix itw_za(Nza, 2);
2040  interpweights(itw_za, gp_za);
2041 
2042  // Original scattered field, on equidistant zenith angle grid.
2043  Matrix doit_scat_field_org(doit_za_grid_size, stokes_dim, 0);
2044 
2045  // Grid stepsize of zenith and azimuth angle grid, these are needed for the
2046  // integration function.
2047  Vector grid_stepsize(2);
2048  grid_stepsize[0] = 180./(Numeric)(doit_za_grid_size - 1);
2049  grid_stepsize[1] = 360./(Numeric)(Naa - 1);
2050 
2051  Tensor3 product_field(doit_za_grid_size, Naa, stokes_dim, 0);
2052 
2053  if ( atmosphere_dim == 1 )
2054  {
2055  Index scat_aa_index_local = 0;
2056 
2057  // Get pha_mat at the grid positions
2058  // Since atmosphere_dim = 1, there is no loop over lat and lon grids
2059  for (Index p_index = 0;
2060  p_index <= cloudbox_limits[1]-cloudbox_limits[0];
2061  p_index++)
2062  {
2063  Numeric rte_temperature_local =
2064  t_field(p_index + cloudbox_limits[0], 0, 0);
2065  // Interpolate intensity field:
2066  for (Index i = 0; i < stokes_dim; i++)
2067  {
2068  if (doit_za_interp == 0)
2069  {
2070  interp(doit_i_field_int(joker, i), itw_za_i,
2071  doit_i_field(p_index, 0, 0, joker, 0, i), gp_za_i);
2072  }
2073  else if (doit_za_interp == 1)
2074  {
2075  // Polynomial
2076  for(Index za = 0; za < za_grid.nelem(); za++)
2077  {
2078  doit_i_field_int(za, i) =
2079  interp_poly(scat_za_grid,
2080  doit_i_field(p_index, 0, 0, joker, 0, i),
2081  za_grid[za],
2082  gp_za_i[za]);
2083  }
2084  }
2085  // doit_za_interp must be 0 or 1 (linear or polynomial)!!!
2086  else assert(false);
2087  }
2088 
2089  //There is only loop over zenith angle grid; no azimuth angle grid.
2090  for( Index scat_za_index_local = 0;
2091  scat_za_index_local < doit_za_grid_size;
2092  scat_za_index_local++)
2093  {
2094  // Dummy index
2095  Index index_zero = 0;
2096 
2097  // Calculate the phase matrix of a single particle type
2098  out3 << "Calculate the phase matrix \n";
2099  pha_mat_spt_agendaExecute(ws, pha_mat_spt_local,
2100  scat_za_index_local,
2101  index_zero,
2102  index_zero,
2103  p_index,
2104  scat_aa_index_local,
2105  rte_temperature_local,
2106  pha_mat_spt_agenda);
2107 
2108  // Sum over all particle types
2109  pha_matCalc(pha_mat_local, pha_mat_spt_local, pnd_field,
2110  atmosphere_dim, p_index, 0,
2111  0, verbosity);
2112 
2113  out3 << "Multiplication of phase matrix with incoming" <<
2114  " intensities \n";
2115 
2116  product_field = 0;
2117 
2118  // za_in and aa_in are for incoming zenith and azimuth
2119  // angle direction for which pha_mat is calculated
2120  for( Index za_in = 0; za_in < doit_za_grid_size; za_in ++)
2121  {
2122  for (Index aa_in = 0; aa_in < Naa; ++ aa_in)
2123  {
2124  // Multiplication of phase matrix with incoming
2125  // intensity field.
2126 
2127  for ( Index i = 0; i < stokes_dim; i++)
2128  {
2129  for (Index j = 0; j< stokes_dim; j++)
2130  {
2131  product_field(za_in, aa_in, i) +=
2132  pha_mat_local(za_in, aa_in, i, j) *
2133  doit_i_field_int(za_in, j);
2134  }
2135  }
2136 
2137  }//end aa_in loop
2138  }//end za_in loop
2139 
2140  out3 << "Compute integral. \n";
2141  for (Index i = 0; i < stokes_dim; i++)
2142  {
2143  doit_scat_field_org(scat_za_index_local, i)=
2144  AngIntegrate_trapezoid_opti(product_field(joker, joker, i),
2145  za_grid,
2146  scat_aa_grid,
2147  grid_stepsize);
2148  }//end i loop
2149  }//end za_prop loop
2150 
2151  // Interpolation on scat_za_grid, which is used in
2152  //radiative transferpart.
2153  for (Index i = 0; i < stokes_dim; i++)
2154  {
2155  if(doit_za_interp == 0) // linear interpolation
2156  {
2157  interp(doit_scat_field(p_index,
2158  0,
2159  0,
2160  joker,
2161  0,
2162  i),
2163  itw_za,
2164  doit_scat_field_org(joker, i),
2165  gp_za);
2166  }
2167  else // polynomial interpolation
2168  {
2169  for(Index za = 0; za < scat_za_grid.nelem(); za++)
2170  {
2171  doit_scat_field(p_index, 0, 0, za, 0, i) =
2172  interp_poly(za_grid,
2173  doit_scat_field_org(joker, i),
2174  scat_za_grid[za],
2175  gp_za[za]);
2176  }
2177  }
2178  }
2179  }//end p_index loop
2180 
2181  }//end atmosphere_dim = 1
2182 
2183 
2184  else if( atmosphere_dim == 3 ){
2185  // Loop over all positions
2186  for (Index p_index = 0; p_index <= cloudbox_limits[1] - cloudbox_limits[0];
2187  p_index ++)
2188  {
2189  for (Index lat_index = 0; lat_index <=
2190  cloudbox_limits[3] - cloudbox_limits[2]; lat_index++)
2191  {
2192  for (Index lon_index = 0; lon_index <=
2193  cloudbox_limits[5] - cloudbox_limits[4]; lon_index++)
2194  {
2195 
2196  Numeric rte_temperature_local =
2197  t_field(p_index + cloudbox_limits[0],
2198  lat_index + cloudbox_limits[2],
2199  lon_index + cloudbox_limits[4]);
2200 
2201  // Loop over scattered directions
2202  for (Index scat_aa_index_local = 1;
2203  scat_aa_index_local < Naa;
2204  scat_aa_index_local++)
2205  {
2206  // Interpolate intensity field:
2207  for (Index i = 0; i < stokes_dim; i++)
2208  {
2209  interp(doit_i_field_int(joker, i), itw_za_i,
2210  doit_i_field(p_index, lat_index, lon_index,
2211  joker, scat_aa_index_local, i), gp_za_i);
2212  }
2213 
2214  for (Index scat_za_index_local = 0;
2215  scat_za_index_local < doit_za_grid_size;
2216  scat_za_index_local++)
2217  {
2218 
2219  out3 << "Calculate phase matrix \n";
2220  pha_mat_spt_agendaExecute(ws, pha_mat_spt_local,
2221  scat_za_index_local,
2222  lat_index,
2223  lon_index,
2224  p_index,
2225  scat_aa_index_local,
2226  rte_temperature_local,
2227  pha_mat_spt_agenda);
2228 
2229  pha_matCalc(pha_mat_local, pha_mat_spt_local,
2230  pnd_field,
2231  atmosphere_dim,
2232  p_index,
2233  lat_index,
2234  lon_index,
2235  verbosity);
2236 
2237  product_field = 0;
2238 
2239 
2240  //za_in and aa_in are the incoming directions
2241  //for which pha_mat_spt is calculated
2242  out3 << "Multiplication of phase matrix with" <<
2243  "incoming intensity \n";
2244 
2245  for( Index za_in = 0; za_in < doit_za_grid_size; za_in ++)
2246  {
2247  for (Index aa_in = 0; aa_in < Naa; ++ aa_in)
2248  {
2249  // Multiplication of phase matrix
2250  // with incloming intensity field.
2251  for ( Index i = 0; i < stokes_dim; i++)
2252  {
2253  for (Index j = 0; j< stokes_dim; j++)
2254  {
2255  product_field(za_in, aa_in, i) +=
2256  pha_mat_local(za_in, aa_in, i, j) *
2257  doit_i_field_int(za_in, j);
2258  }
2259  }
2260  }//end aa_in loop
2261  }//end za_in loop
2262 
2263  out3 << "Compute the integral \n";
2264 
2265  for (Index i = 0; i < stokes_dim; i++)
2266  {
2267  doit_scat_field_org(scat_za_index_local, i) =
2268  AngIntegrate_trapezoid_opti(product_field
2269  ( joker,
2270  joker, i),
2271  za_grid,
2272  scat_aa_grid,
2273  grid_stepsize
2274  );
2275  }//end stokes_dim loop
2276 
2277  }//end za_prop loop
2278  //Interpolate on original za_grid.
2279  for (Index i = 0; i < stokes_dim; i++)
2280  {
2281  interp(doit_scat_field(p_index,
2282  lat_index,
2283  lon_index,
2284  joker,
2285  scat_aa_index_local,
2286  i),
2287  itw_za,
2288  doit_scat_field_org(joker, i),
2289  gp_za);
2290  }
2291  } // end aa_prop loop
2292  }//end lon loop
2293  }//end lat loop
2294  }// end p loop
2295  doit_scat_field(joker, joker, joker, joker, 0, joker) =
2296  doit_scat_field(joker, joker, joker, joker, Naa-1, joker);
2297  }// end atm_dim=3
2298  out2 << " Finished scattered field.\n";
2299 }
2300 
2301 
2302 /* Workspace method: Doxygen documentation will be auto-generated */
2303 void doit_za_grid_optCalc(//WS Output
2304  Vector& doit_za_grid_opt,
2305  // WS Input:
2306  const Tensor6& doit_i_field,
2307  const Vector& scat_za_grid,
2308  const Index& doit_za_interp,
2309  //Keywords:
2310  const Numeric& acc,
2311  const Verbosity&)
2312 {
2313  //-------- Check the input ---------------------------------
2314 
2315  // Here it is checked whether doit_i_field is 1D and whether it is
2316  // consistent with scat_za_grid. The number of pressure levels and the
2317  // number of stokes components does not matter.
2318  chk_size("doit_i_field", doit_i_field,
2319  doit_i_field.nvitrines() , 1, 1, scat_za_grid.nelem(), 1,
2320  doit_i_field.ncols());
2321 
2322  if(doit_i_field.ncols()<1 || doit_i_field.ncols()>4)
2323  throw runtime_error("The last dimension of *doit_i_field* corresponds\n"
2324  "to the Stokes dimension, therefore the number of\n"
2325  "columns in *doit_i_field* must be a number between\n"
2326  "1 and 4, but it is not!");
2327 
2328  if(scat_za_grid.nelem() < 500)
2329  throw runtime_error("The fine grid (*scat_za_grid*) has less than \n"
2330  "500 grid points which is not sufficient for \n"
2331  "grid_optimization");
2332 
2333  if( !(doit_za_interp == 0 || doit_za_interp == 1 ) )
2334  throw runtime_error( "Interpolation method is not defined. Use \n"
2335  "*doit_za_interpSet*.\n");
2336 
2337  // ------------- end of checks -------------------------------------
2338 
2339  // Here only used as dummy variable.
2340  Matrix doit_i_field_opt_mat;
2341  doit_i_field_opt_mat = 0.;
2342 
2343  // Optimize zenith angle grid.
2344  za_gridOpt(doit_za_grid_opt, doit_i_field_opt_mat,
2345  scat_za_grid, doit_i_field, acc,
2346  doit_za_interp);
2347 }
2348 
2349 
2350 /* Workspace method: Doxygen documentation will be auto-generated */
2351 void doit_za_interpSet(Index& doit_za_interp,
2352  const Index& atmosphere_dim,
2353  //Keyword
2354  const String& method,
2355  const Verbosity&)
2356 {
2357  chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
2358 
2359  if (atmosphere_dim != 1 && method == "polynomial")
2360  throw runtime_error(
2361  "Polynomial interpolation is only implemented for\n"
2362  "1D DOIT calculations as \n"
2363  "in 3D there can be numerical problems.\n"
2364  "Please use 'linear' interpolation method."
2365  );
2366 
2367  if(method == "linear")
2368  doit_za_interp = 0;
2369  else if (method == "polynomial")
2370  doit_za_interp = 1;
2371  else
2372  throw runtime_error("Possible interpolation methods are 'linear' "
2373  "and 'polynomial'.\n");
2374 }
2375 
2376 
2377 /* Workspace method: Doxygen documentation will be auto-generated */
2379  Tensor6& doit_i_field,
2380  Tensor7& scat_i_p,
2381  Tensor7& scat_i_lat,
2382  Tensor7& scat_i_lon,
2383  Tensor4& doit_i_field1D_spectrum,
2384  const Index& cloudbox_on,
2385  const Vector& f_grid,
2386  const Agenda& doit_mono_agenda,
2387  const Index& doit_is_initialized,
2388  const Verbosity& verbosity)
2389 
2390 {
2391  CREATE_OUT2
2392 
2393  //-------- Check input -------------------------------------------
2394 
2395  // Don't do anything if there's no cloudbox defined.
2396  if (!cloudbox_on) return;
2397 
2398  chk_not_empty( "doit_mono_agenda", doit_mono_agenda );
2399 
2400  // Frequency grid
2401  //
2402  if( f_grid.nelem() == 0 )
2403  throw runtime_error( "The frequency grid is empty." );
2404  chk_if_increasing( "f_grid", f_grid );
2405 
2406  // Check whether DoitInit was executed
2407  if (!doit_is_initialized)
2408  throw runtime_error(
2409  "Initialization method *DoitInit* has to be "
2410  "put before\n"
2411  "start of *ScatteringDoit*");
2412 
2413  //-------- end of checks ----------------------------------------
2414 
2415 
2416  // We have to make a local copy of the Workspace and the agendas because
2417  // only non-reference types can be declared firstprivate in OpenMP
2418  Workspace l_ws (ws);
2419  Agenda l_doit_mono_agenda(doit_mono_agenda);
2420 
2421  // OMP likes simple loop end conditions, so we make a local copy here:
2422  const Index nf = f_grid.nelem();
2423 
2424 /*#pragma omp parallel for \
2425  if(!arts_omp_in_parallel() && nf>1) \
2426  default(none) \
2427  shared(out2, f_grid, doit_i_field1D_spectrum, scat_i_lon, \
2428  scat_i_lat, scat_i_p, doit_i_field) \
2429  firstprivate(l_ws, l_doit_mono_agenda) */
2430 /*#pragma omp parallel for \
2431  if(!arts_omp_in_parallel() && nf>1) \
2432  firstprivate(l_ws, l_doit_mono_agenda)*/
2433  for (Index f_index = 0; f_index < nf; f_index ++)
2434  {
2435  ostringstream os;
2436  os << "Frequency: " << f_grid[f_index]/1e9 <<" GHz \n" ;
2437  out2 << os.str();
2438 
2439  doit_mono_agendaExecute(l_ws, doit_i_field, scat_i_p, scat_i_lat,
2440  scat_i_lon, doit_i_field1D_spectrum,
2441  f_index, l_doit_mono_agenda);
2442  }
2443 }
2444 
2445 
2446 /* Workspace method: Doxygen documentation will be auto-generated */
2447 void DoitCloudboxFieldPut(//WS Output:
2448  Tensor7& scat_i_p,
2449  Tensor7& scat_i_lat,
2450  Tensor7& scat_i_lon,
2451  Tensor4& doit_i_field1D_spectrum,
2452  //WS Input:
2453  const Tensor6& doit_i_field,
2454  const Vector& f_grid,
2455  const Index& f_index,
2456  const Vector& p_grid,
2457  const Vector& lat_grid,
2458  const Vector& lon_grid,
2459  const Vector& scat_za_grid,
2460  const Vector& scat_aa_grid,
2461  const Index& stokes_dim,
2462  const Index& atmosphere_dim,
2463  const ArrayOfIndex& cloudbox_limits,
2464  const Matrix& sensor_pos,
2465  const Tensor3& z_field,
2466  const Verbosity& verbosity)
2467 {
2468  // Some sizes:
2469  Index N_f = f_grid.nelem();
2470  Index N_za = scat_za_grid.nelem();
2471  Index N_aa = scat_aa_grid.nelem();
2472  Index N_p = cloudbox_limits[1] - cloudbox_limits[0] +1;
2473 
2474  // Some checks:
2475 
2476  assert( f_index < f_grid.nelem() );
2477 
2478  chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
2479 
2480  // Grids have to be adapted to atmosphere_dim.
2481  chk_atm_grids( atmosphere_dim, p_grid, lat_grid, lon_grid );
2482 
2483  // Check the input:
2484  if (stokes_dim < 0 || stokes_dim > 4)
2485  throw runtime_error(
2486  "The dimension of stokes vector must be"
2487  "1,2,3, or 4");
2488 
2489  if ( cloudbox_limits.nelem()!= 2*atmosphere_dim)
2490  throw runtime_error(
2491  "*cloudbox_limits* is a vector which contains the"
2492  "upper and lower limit of the cloud for all "
2493  "atmospheric dimensions. So its dimension must"
2494  "be 2 x *atmosphere_dim*");
2495  // End of checks.
2496 
2497  // Resize and initialize *doit_i_field_spectra*
2498  doit_i_field1D_spectrum.resize(N_f, N_p, N_za, stokes_dim);
2499  doit_i_field1D_spectrum = 0;
2500 
2501  // Put the doit_i_field at the cloudbox boundary into the interface variable
2502  // scat_i_p.
2503  if(atmosphere_dim == 1)
2504  {
2505  bool in_cloudbox = false;
2506  // Check if sensor inside the cloudbox:
2507  //loop over all sensor positions
2508  for (Index i = 0; i < sensor_pos.ncols(); i++)
2509  {
2510  // ??? (CE) I think this is worng
2511  if(sensor_pos(i, 0) >= z_field(cloudbox_limits[0], 0, 0) &&
2512  sensor_pos(i, 0) <= z_field(cloudbox_limits[1], 0, 0) )
2513  {
2514  CREATE_OUT2
2515  in_cloudbox = true;
2516  out2 << " Sensor position in cloudbox, store radiation field\n"
2517  << " in cloudbox for all frequencies. \n";
2518  }
2519  }
2520 
2521  // Check size of doit_i_field.
2522  assert ( is_size( doit_i_field,
2523  (cloudbox_limits[1] - cloudbox_limits[0]) + 1,
2524  1,
2525  1,
2526  N_za,
2527  1,
2528  stokes_dim));
2529 
2530  assert ( is_size( scat_i_p,
2531  N_f, 2, 1, 1, N_za, 1, stokes_dim ));
2532 
2533  for (Index za = 0; za < N_za; za++)
2534  {
2535  for (Index i = 0; i < stokes_dim; i++)
2536  {
2537 
2538  //doit_i_field at lower boundary
2539  scat_i_p(f_index, 0, 0, 0,
2540  za, 0, i) =
2541  doit_i_field(0, 0, 0, za, 0, i);
2542  //doit_i_field at upper boundary
2543  scat_i_p(f_index, 1, 0, 0,
2544  za, 0, i) =
2545  doit_i_field(cloudbox_limits[1] - cloudbox_limits[0],
2546  0, 0, za, 0, i);
2547 
2548  // If a sensor pos is inside the cloudbox we also need to
2549  // define *doit_i_field1D_spectra*
2550  if( in_cloudbox)
2551  {
2552  doit_i_field1D_spectrum(f_index, joker, za, i) =
2553  doit_i_field(joker, 0, 0, za, 0, i);
2554  }
2555 
2556  }//end stokes_dim
2557  }//end za loop
2558 
2559 
2560  }//end atmosphere_dim = 1
2561 
2562  if(atmosphere_dim == 3)
2563  {
2564  // Some sizes relevant for 3D atmosphere
2565  Index N_lat = cloudbox_limits[3] - cloudbox_limits[2] + 1;
2566  Index N_lon = cloudbox_limits[5] - cloudbox_limits[4] + 1;
2567 
2568  // Check size of doit_i_field.
2569  assert ( is_size( doit_i_field,
2570  cloudbox_limits[1] - cloudbox_limits[0] + 1,
2571  N_lat,
2572  N_lon,
2573  N_za,
2574  N_aa,
2575  stokes_dim));
2576 
2577  // Resize interface variables:
2578  scat_i_p.resize(N_f, 2, N_lat, N_lon, N_za, N_aa, stokes_dim);
2579  scat_i_lat.resize(N_f, N_p, 2, N_lon, N_za, N_aa, stokes_dim);
2580  scat_i_lon.resize(N_f, N_p, N_lat, 2, N_za, N_aa, stokes_dim);
2581 
2582  for (Index za = 0; za < N_za; za++)
2583  {
2584  for (Index aa = 0; aa < N_aa; aa++)
2585  {
2586  for (Index i = 0; i < stokes_dim; i++)
2587  {
2588  //
2589  // Put doit_i_field in scat_i_p:
2590  //
2591  for (Index lat = 0; lat < N_lat; lat++)
2592  {
2593  for (Index lon = 0; lon < N_lon; lon++)
2594  {
2595  //doit_i_field at lower boundary
2596  scat_i_p(f_index, 0, lat, lon,
2597  za, aa, i) =
2598  doit_i_field(0, lat, lon, za, aa, i);
2599  //doit_i_field at upper boundary
2600  scat_i_p(f_index, 1, lat, lon,
2601  za, aa, i) =
2602  doit_i_field(cloudbox_limits[1]-cloudbox_limits[0],
2603  lat, lon, za, aa, i);
2604  }
2605  }
2606  //
2607  // Put doit_i_field in scat_i_lat:
2608  //
2609  for (Index p = 0; p < N_p; p++)
2610  {
2611  for (Index lon = 0; lon < N_lon; lon++)
2612  {
2613  //doit_i_field at lower boundary
2614  scat_i_lat(f_index, p, 0, lon,
2615  za, aa, i) =
2616  doit_i_field(p, 0, lon, za, aa, i);
2617  //doit_i_field at upper boundary
2618  scat_i_lat(f_index, p, 1, lon,
2619  za, aa, i) =
2620  doit_i_field(p, cloudbox_limits[3]-
2621  cloudbox_limits[2],
2622  lon, za, aa, i);
2623  }
2624  //
2625  // Put doit_i_field in scat_i_lon:
2626  for (Index lat = 0; lat < N_lat; lat++)
2627  {
2628  //doit_i_field at lower boundary
2629  scat_i_lon(f_index, p, lat, 0,
2630  za, aa, i) =
2631  doit_i_field(p, lat, 0, za, aa, i);
2632  //doit_i_field at upper boundary
2633  scat_i_lon(f_index, p, lat, 1,
2634  za, aa, i) =
2635  doit_i_field(p, lat, cloudbox_limits[5]-
2636  cloudbox_limits[4], za, aa, i);
2637  }
2638  }
2639  }
2640  }
2641  }
2642  }
2643 }
2644 
2645 
2646 
2647 /* Workspace method: Doxygen documentation will be auto-generated */
2649  Tensor7& scat_i_p,
2650  Tensor7& scat_i_lat,
2651  Tensor7& scat_i_lon,
2652  const Agenda& iy_clearsky_basic_agenda,
2653  const Index& atmosphere_dim,
2654  const Vector& lat_grid,
2655  const Vector& lon_grid,
2656  const Tensor3& z_field,
2657  const Matrix& r_geoid,
2658  const Index& cloudbox_on,
2659  const ArrayOfIndex& cloudbox_limits,
2660  const Vector& f_grid,
2661  const Index& stokes_dim,
2662  const Vector& scat_za_grid,
2663  const Vector& scat_aa_grid,
2664  const Verbosity&)
2665 {
2666  // Don't do anything if there's no cloudbox defined.
2667  if (!cloudbox_on) return;
2668 
2669  Index Nf = f_grid.nelem();
2670  Index Np_cloud = cloudbox_limits[1] - cloudbox_limits[0] + 1;
2671  Index Nza = scat_za_grid.nelem();
2672  Index Ni = stokes_dim;
2673  Matrix iy;
2674  Ppath ppath;
2675 
2676  //--- Check input ----------------------------------------------------------
2677  if( !(atmosphere_dim == 1 || atmosphere_dim == 3) )
2678  throw runtime_error( "The atmospheric dimensionality must be 1 or 3.");
2679  if( scat_za_grid[0] != 0. || scat_za_grid[Nza-1] != 180. )
2680  throw runtime_error(
2681  "*scat_za_grid* must include 0 and 180 degrees as endpoints." );
2682  //--------------------------------------------------------------------------
2683 
2684 
2685  if( atmosphere_dim == 1 )
2686  {
2687  // Resize interface variables:
2688  scat_i_p.resize( Nf, 2, 1, 1, Nza, 1, Ni );
2689  scat_i_lat.resize( 0, 0, 0, 0, 0, 0, 0 );
2690  scat_i_lon.resize( 0, 0, 0, 0, 0, 0, 0 );
2691 
2692  //Define the variables for position and direction.
2693  Vector los(1), pos(1);
2694 
2695  //--- Get scat_i_p at lower and upper boundary
2696  // (boundary=0: lower, boundary=1: upper)
2697  for (Index boundary = 0; boundary <= 1; boundary++)
2698  {
2699  pos[0] = r_geoid(0,0) + z_field( cloudbox_limits[boundary], 0, 0 );
2700 
2701  for (Index scat_za_index = 0; scat_za_index < Nza; scat_za_index ++)
2702  {
2703  los[0] = scat_za_grid[scat_za_index];
2704 
2705  iy_clearsky_basic_agendaExecute( ws, iy, pos, los, 0,
2706  iy_clearsky_basic_agenda );
2707 
2708  scat_i_p( joker, boundary, 0, 0, scat_za_index, 0, joker ) = iy;
2709  }
2710  }
2711  }
2712 
2713 
2714  //--- atmosphere_dim = 3: --------------------------------------------------
2715  else
2716  {
2717  Index Naa = scat_aa_grid.nelem();
2718 
2719  if( scat_aa_grid[0] != 0. || scat_aa_grid[Naa-1] != 360. )
2720  throw runtime_error(
2721  "*scat_aa_grid* must include 0 and 360 degrees as endpoints." );
2722 
2723  Index Nlat_cloud = cloudbox_limits[3] - cloudbox_limits[2] + 1;
2724  Index Nlon_cloud = cloudbox_limits[5] - cloudbox_limits[4] + 1;
2725 
2726  // Convert scat_aa_grid to "sensor coordinates"
2727  // (-180° < azimuth angle < 180°)
2728  //
2729  Vector aa_grid(Naa);
2730  for(Index i = 0; i<Naa; i++)
2731  aa_grid[i] = scat_aa_grid[i] - 180;
2732 
2733  // Resize interface variables:
2734  scat_i_p.resize( Nf, 2, Nlat_cloud, Nlon_cloud, Nza, Naa, Ni );
2735  scat_i_lat.resize( Nf, Np_cloud, 2, Nlon_cloud, Nza, Naa, Ni );
2736  scat_i_lon.resize( Nf, Np_cloud, Nlat_cloud, 2, Nza, Naa, Ni );
2737 
2738  // Define the variables for position and direction.
2739  Vector los(2), pos(3);
2740 
2741 
2742  //--- Get scat_i_p at lower and upper boundary
2743  // (boundary=0: lower, boundary=1: upper)
2744  for (Index boundary = 0; boundary <= 1; boundary++)
2745  {
2746  for (Index lat_index = 0; lat_index < Nlat_cloud; lat_index++ )
2747  {
2748  for (Index lon_index = 0; lon_index < Nlon_cloud; lon_index++ )
2749  {
2750  pos[0] = r_geoid(lat_index + cloudbox_limits[2],
2751  lon_index + cloudbox_limits[4])
2752  + z_field(cloudbox_limits[boundary],
2753  lat_index + cloudbox_limits[2],
2754  lon_index + cloudbox_limits[4]);
2755  pos[1] = lat_grid[lat_index + cloudbox_limits[2]];
2756  pos[2] = lon_grid[lon_index + cloudbox_limits[4]];
2757 
2758  for (Index scat_za_index = 0; scat_za_index < Nza;
2759  scat_za_index ++)
2760  {
2761  for (Index scat_aa_index = 0; scat_aa_index < Naa;
2762  scat_aa_index ++)
2763  {
2764  los[0] = scat_za_grid[scat_za_index];
2765  los[1] = aa_grid[scat_aa_index];
2766 
2767  // For end points of scat_za_index (0 & 180deg), we
2768  // only need to perform calculations for one scat_aa
2769  // and set the others to same value
2770 // if( !( ( scat_za_index == 0 ||
2771 // scat_za_index == (Nza-1) ) &&
2772 // scat_aa_index == 0 ) )
2773  if( ( scat_za_index != 0 &&
2774  scat_za_index != (Nza-1) ) ||
2775  scat_aa_index == 0 )
2776  {
2777  iy_clearsky_basic_agendaExecute( ws, iy, pos, los,
2778  0, iy_clearsky_basic_agenda );
2779  }
2780 
2781  scat_i_p( joker, boundary, lat_index, lon_index,
2782  scat_za_index, scat_aa_index, joker) = iy;
2783  }
2784  }
2785  }
2786  }
2787  }
2788 
2789  //--- Get scat_i_lat (2nd and 3rd boundary)
2790  for (Index boundary = 0; boundary <= 1; boundary++)
2791  {
2792  for (Index p_index = 0; p_index < Np_cloud; p_index++ )
2793  {
2794  for (Index lon_index = 0; lon_index < Nlon_cloud; lon_index++ )
2795  {
2796  pos[0] = r_geoid(cloudbox_limits[boundary+2],
2797  lon_index + cloudbox_limits[4])
2798  + z_field(p_index + cloudbox_limits[0],
2799  cloudbox_limits[boundary+2],
2800  lon_index + cloudbox_limits[4]);
2801  pos[1] = lat_grid[cloudbox_limits[boundary+2]];
2802  pos[2] = lon_grid[lon_index + cloudbox_limits[4]];
2803 
2804  for (Index scat_za_index = 0; scat_za_index < Nza;
2805  scat_za_index ++)
2806  {
2807  for (Index scat_aa_index = 0; scat_aa_index < Naa;
2808  scat_aa_index ++)
2809  {
2810  los[0] = scat_za_grid[scat_za_index];
2811  los[1] = aa_grid[scat_aa_index];
2812 
2813  // For end points of scat_za_index, we need only to
2814  // perform calculations for first scat_aa
2815  if( !( ( scat_za_index == 0 ||
2816  scat_za_index == (Nza-1) ) &&
2817  scat_aa_index == 0 ) )
2818  {
2819  iy_clearsky_basic_agendaExecute( ws, iy, pos, los,
2820  0, iy_clearsky_basic_agenda );
2821  }
2822 
2823  scat_i_lat( joker, p_index, boundary, lon_index,
2824  scat_za_index, scat_aa_index, joker) = iy;
2825  }
2826  }
2827  }
2828  }
2829  }
2830 
2831  //--- Get scat_i_lon (1st and 2nd boundary):
2832  for (Index boundary = 0; boundary <= 1; boundary++)
2833  {
2834  for (Index p_index = 0; p_index < Np_cloud; p_index++ )
2835  {
2836  for (Index lat_index = 0; lat_index < Nlat_cloud; lat_index++ )
2837  {
2838  pos[0] = r_geoid(lat_index + cloudbox_limits[2],
2839  cloudbox_limits[boundary+4])
2840  + z_field(p_index + cloudbox_limits[0],
2841  lat_index + cloudbox_limits[2],
2842  cloudbox_limits[boundary+4]);
2843  pos[1] = lat_grid[lat_index + cloudbox_limits[2]];
2844  pos[2] = lon_grid[cloudbox_limits[boundary+4]];
2845 
2846  for (Index scat_za_index = 0; scat_za_index < Nza;
2847  scat_za_index ++)
2848  {
2849  for (Index scat_aa_index = 0; scat_aa_index < Naa;
2850  scat_aa_index ++)
2851  {
2852  los[0] = scat_za_grid[scat_za_index];
2853  los[1] = aa_grid[scat_aa_index];
2854 
2855  // For end points of scat_za_index, we need only to
2856  // perform calculations for first scat_aa
2857  if( !( ( scat_za_index == 0 ||
2858  scat_za_index == (Nza-1) ) &&
2859  scat_aa_index == 0 ) )
2860  {
2861  iy_clearsky_basic_agendaExecute( ws, iy, pos, los,
2862  0, iy_clearsky_basic_agenda );
2863  }
2864 
2865  scat_i_lon( joker, p_index, lat_index, boundary,
2866  scat_za_index, scat_aa_index, joker) = iy;
2867  }
2868  }
2869  }
2870  }
2871  }
2872  }// End atmosphere_dim = 3.
2873 }
2874 
2875 
2876 /* Workspace method: Doxygen documentation will be auto-generated */
2878  Tensor7& scat_i_p,
2879  Tensor7& scat_i_lat,
2880  Tensor7& scat_i_lon,
2881  Index& cloudbox_on,
2882  const Agenda& iy_clearsky_basic_agenda,
2883  const Index& atmosphere_dim,
2884  const Vector& lat_grid,
2885  const Vector& lon_grid,
2886  const Tensor3& z_field,
2887  const Matrix& r_geoid,
2888  const ArrayOfIndex& cloudbox_limits,
2889  const Vector& f_grid,
2890  const Index& stokes_dim,
2891  const Vector& scat_za_grid,
2892  const Vector& scat_aa_grid,
2893  const Verbosity&)
2894 {
2895  // Don't do anything if there's no cloudbox defined.
2896  if (!cloudbox_on) return;
2897 
2898  Index Nf = f_grid.nelem();
2899  Index Np_cloud = cloudbox_limits[1] - cloudbox_limits[0] + 1;
2900  Index Nlat_cloud = cloudbox_limits[3] - cloudbox_limits[2] + 1;
2901  Index Nlon_cloud = cloudbox_limits[5] - cloudbox_limits[4] + 1;
2902  Index Nza = scat_za_grid.nelem();
2903  Index Naa = scat_aa_grid.nelem();
2904  Index Ni = stokes_dim;
2905  Matrix iy;
2906  Ppath ppath;
2907 
2908 
2909  //--- Check input ----------------------------------------------------------
2910  if( atmosphere_dim != 3 )
2911  throw runtime_error( "The atmospheric dimensionality must be 3.");
2912 // if( cloudbox_on == 0 || cloudbox_limits.nelem() == 0 )
2913 // throw runtime_error( "The cloudbox must be activated, and it is not.");
2914  if( scat_za_grid[0] != 0. || scat_za_grid[Nza-1] != 180. )
2915  throw runtime_error(
2916  "*scat_za_grid* must include 0 and 180 degrees as endpoints." );
2917  if( scat_aa_grid[0] != 0. || scat_aa_grid[Naa-1] != 360. )
2918  throw runtime_error(
2919  "*scat_aa_grid* must include 0 and 360 degrees as endpoints." );
2920  //--------------------------------------------------------------------------
2921 
2922  // Dummy variable for flag cloudbox_on. It has to be 0 here not to get
2923  // stuck in an infinite loop (if some propagation path hits the cloud
2924  // box at some other position.
2925  cloudbox_on = 0;
2926 
2927  // Convert scat_za_grid to "sensor coordinates"
2928  //(-180° < azimuth angle < 180°)
2929  //
2930  Vector aa_grid(Naa);
2931  for(Index i = 0; i<Naa; i++)
2932  aa_grid[i] = scat_aa_grid[i] - 180;
2933 
2934  // As the atmosphere is spherically symmetric we only have to calculate
2935  // one azimuth angle.
2936  Index aa_index = 0;
2937 
2938  // Resize interface variables:
2939  scat_i_p.resize(Nf, 2, Nlat_cloud, Nlon_cloud, Nza, Naa, Ni);
2940  scat_i_lat.resize(Nf, Np_cloud, 2, Nlon_cloud, Nza, Naa, Ni);
2941  scat_i_lon.resize(Nf, Np_cloud, Nlat_cloud, 2, Nza, Naa, Ni);
2942 
2943  // Define the variables for position and direction.
2944  Vector los(2), pos(3);
2945 
2946  // These variables are constant for all calculations:
2947  pos[1] = lat_grid[cloudbox_limits[2]];
2948  pos[2] = lon_grid[cloudbox_limits[4]];
2949  los[1] = aa_grid[aa_index];
2950 
2951  // Calculate scat_i_p, scat_i_lat, scat_i_lon
2952  for (Index p_index = 0; p_index < Np_cloud; p_index++ )
2953  {
2954  pos[0] = r_geoid(cloudbox_limits[2], cloudbox_limits[4])
2955  + z_field(cloudbox_limits[0] + p_index, cloudbox_limits[2],
2956  cloudbox_limits[4]);
2957 
2958  for (Index scat_za_index = 0; scat_za_index < Nza; scat_za_index++ )
2959  {
2960  los[0] = scat_za_grid[scat_za_index];
2961 
2962  iy_clearsky_basic_agendaExecute( ws, iy, pos, los, 0,
2963  iy_clearsky_basic_agenda );
2964 
2965  for (Index aa = 0; aa < Naa; aa ++)
2966  {
2967  // scat_i_p lower boundary
2968  if(p_index == 0)
2969  {
2970  for (Index lat = 0; lat < Nlat_cloud; lat ++)
2971  {
2972  for (Index lon = 0; lon < Nlon_cloud; lon ++)
2973  {
2974  scat_i_p( joker, 0, lat, lon, scat_za_index, aa,
2975  joker )
2976  = iy;
2977  }
2978  }
2979  }
2980  //scat_i_p at upper boundary
2981  else if (p_index == Np_cloud-1)
2982  for (Index lat = 0; lat < Nlat_cloud; lat ++)
2983  {
2984  for (Index lon = 0; lon < Nlon_cloud; lon ++)
2985  {
2986  scat_i_p( joker, 1, lat, lon, scat_za_index, aa,
2987  joker )
2988  = iy;
2989  }
2990  }
2991 
2992  // scat_i_lat (both boundaries)
2993  for (Index lat = 0; lat < 2; lat ++)
2994  {
2995  for (Index lon = 0; lon < Nlon_cloud; lon ++)
2996  {
2997  scat_i_lat( joker, p_index, lat, lon,
2998  scat_za_index, aa, joker)
2999  = iy;
3000  }
3001  }
3002 
3003  // scat_i_lon (both boundaries)
3004  for (Index lat = 0; lat < Nlat_cloud; lat ++)
3005  {
3006  for (Index lon = 0; lon < 2; lon ++)
3007  {
3008  scat_i_lon( joker, p_index, lat, lon,
3009  scat_za_index, aa, joker)
3010  = iy;
3011  }
3012  }
3013  }
3014  }
3015  }
3016  cloudbox_on = 1;
3017 }
3018 
3019 
3020 /* Workspace method: Doxygen documentation will be auto-generated */
3022  Matrix& iy_error,
3023  Index& iy_error_type,
3024  Matrix& iy_aux,
3025  ArrayOfTensor3& diy_dx,
3026  const Tensor3& iy_transmission,
3027  const Tensor7& scat_i_p,
3028  const Tensor7& scat_i_lat,
3029  const Tensor7& scat_i_lon,
3030  const Tensor4& doit_i_field1D_spectrum,
3031  const GridPos& rte_gp_p,
3032  const GridPos& rte_gp_lat,
3033  const GridPos& rte_gp_lon,
3034  const Vector& rte_los,
3035  const Index& jacobian_do,
3036  const Index& cloudbox_on,
3037  const ArrayOfIndex& cloudbox_limits,
3038  const Index& atmosphere_dim,
3039  const Index& stokes_dim,
3040  const Vector& scat_za_grid,
3041  const Vector& scat_aa_grid,
3042  const Vector& f_grid,
3043  const Verbosity& verbosity)
3044 {
3045  // Retrieval variables
3046  if( jacobian_do )
3047  throw runtime_error(
3048  "This method does not provide any jacobians (jacobian_do must be 0)" );
3049  diy_dx.resize(0);
3050 
3051  const Index nf = f_grid.nelem();
3052 
3053  // iy
3054  iy_interp_cloudbox_field( iy, scat_i_p, scat_i_lat, scat_i_lon,
3055  doit_i_field1D_spectrum, rte_gp_p,
3056  rte_gp_lat, rte_gp_lon, rte_los, cloudbox_on,
3057  cloudbox_limits, atmosphere_dim, stokes_dim,
3058  scat_za_grid, scat_aa_grid, f_grid, "linear",
3059  verbosity );
3060 
3061  // As a temporary solution, create an "epsilon vector" matching
3062  // [0.5,0.1,0.1,0.1] K. This shall be replaced with the epsilion vector
3063  // inputted to doit_conv_flag (then must be made to a WSV).
3064  const Numeric e = rayjean( (f_grid[0]+f_grid[nf-1])/2.0, 1 );
3065  Vector eps(4,e/10);
3066  eps[0] = e/2;
3067 
3068  // iy_aux and iy_error
3069  //
3070  iy_aux.resize( nf, stokes_dim );
3071  iy_error.resize( nf, stokes_dim );
3072  iy_error_type = 2;
3073  //
3074  for( Index iv=0; iv<nf; iv++ )
3075  {
3076  for( Index is=0; is<stokes_dim; is++ )
3077  {
3078  iy_aux( iv, is ) = iy_transmission( iv, is, is );
3079  iy_error( iv, is ) = iy_aux( iv, is ) * eps[is];
3080  }
3081  }
3082 }
3083 
3084 
3085 /* Workspace method: Doxygen documentation will be auto-generated */
3087  Matrix& iy_error,
3088  Index& iy_error_type,
3089  Matrix& iy_aux,
3090  ArrayOfTensor3& diy_dx,
3091  const Tensor3& iy_transmission,
3092  const Tensor7& scat_i_p,
3093  const Tensor7& scat_i_lat,
3094  const Tensor7& scat_i_lon,
3095  const Tensor4& doit_i_field1D_spectrum,
3096  const GridPos& rte_gp_p,
3097  const GridPos& rte_gp_lat,
3098  const GridPos& rte_gp_lon,
3099  const Vector& rte_los,
3100  const Index& jacobian_do,
3101  const Index& cloudbox_on,
3102  const ArrayOfIndex& cloudbox_limits,
3103  const Index& atmosphere_dim,
3104  const Index& stokes_dim,
3105  const Vector& scat_za_grid,
3106  const Vector& scat_aa_grid,
3107  const Vector& f_grid,
3108  const Verbosity& verbosity)
3109 {
3110  // Retrieval varaibles
3111  if( jacobian_do )
3112  throw runtime_error(
3113  "This method does not provide any jacobians (jacobian_do must be 0)" );
3114  diy_dx.resize(0);
3115 
3116  const Index nf = f_grid.nelem();
3117 
3118  // iy
3119  iy_interp_cloudbox_field( iy, scat_i_p, scat_i_lat, scat_i_lon,
3120  doit_i_field1D_spectrum, rte_gp_p,
3121  rte_gp_lat, rte_gp_lon, rte_los, cloudbox_on,
3122  cloudbox_limits, atmosphere_dim, stokes_dim,
3123  scat_za_grid, scat_aa_grid, f_grid, "polynomial",
3124  verbosity );
3125 
3126  // As a temporary solution, create an "epsilon vector" matching
3127  // [0.5,0.1,0.1,0.1] K. This shall be replaced with the epsilion vector
3128  // inputted to doit_conv_flag (then must be made to a WSV).
3129  const Numeric e = rayjean( (f_grid[0]+f_grid[nf-1])/2.0, 1 );
3130  Vector eps(4,e/10);
3131  eps[0] = e/2;
3132 
3133  // iy_aux and iy_error
3134  //
3135  iy_aux.resize( nf, stokes_dim );
3136  iy_error.resize( nf, stokes_dim );
3137  iy_error_type = 2;
3138  //
3139  for( Index iv=0; iv<nf; iv++ )
3140  {
3141  for( Index is=0; is<stokes_dim; is++ )
3142  {
3143  iy_aux( iv, is ) = iy_transmission( iv, is, is );
3144  iy_error( iv, is ) = iy_aux( iv, is ) * eps[is];
3145  }
3146  }
3147 }
3148 
3149 /* Workspace method: Doxygen documentation will be auto-generated */
3151  const Tensor7& scat_i_p,
3152  const Tensor7& scat_i_lat,
3153  const Tensor7& scat_i_lon,
3154  const Vector& f_grid,
3155  const Index& f_index,
3156  const Vector& p_grid,
3157  const Vector& lat_grid,
3158  const Vector& lon_grid,
3159  const ArrayOfIndex& cloudbox_limits,
3160  const Index& atmosphere_dim,
3161  //Keyword:
3162  const Index& all_frequencies,
3163  const Verbosity& verbosity)
3164 {
3165  CREATE_OUT2
3166 
3167  out2 << " Interpolate boundary clearsky field to obtain the initial field.\n";
3168 
3169  // Initial field only needs to be calculated from clearsky field for the
3170  // first frequency. For the next frequencies the solution field from the
3171  // previous frequencies is used.
3172  if(atmosphere_dim == 1)
3173  {
3174  if(f_index == 0 || all_frequencies == true){
3175  Index N_f = scat_i_p.nlibraries();
3176  if (f_grid.nelem() != N_f){
3177 
3178  throw runtime_error(" scat_i_p should have same frequency "
3179  " dimension as f_grid");
3180  }
3181 
3182  if(scat_i_p.nvitrines() != 2){
3183  throw runtime_error("scat_i_p should have exactly two elements "
3184  "in pressure dimension which correspond to the "
3185  "two cloudbox bounding pressure levels");
3186  }
3187 
3188 
3189  Index N_za = scat_i_p.npages() ;
3190  Index N_aa = scat_i_p.nrows();
3191  Index N_i = scat_i_p.ncols();
3192 
3193  //1. interpolation - pressure grid
3194 
3195  doit_i_field.resize((cloudbox_limits[1]- cloudbox_limits[0])+1,
3196  1,
3197  1,
3198  N_za,
3199  N_aa,
3200  N_i);
3201 
3202  doit_i_field = 0.;
3203 
3204  /*the old grid is having only two elements, corresponding to the
3205  cloudbox_limits and the new grid have elements corresponding to
3206  all grid points inside the cloudbox plus the cloud_box_limits*/
3207 
3208  ArrayOfGridPos p_gp((cloudbox_limits[1]- cloudbox_limits[0])+1);
3209 
3210  p2gridpos(p_gp,
3211  p_grid[Range(cloudbox_limits[0],
3212  2,
3213  (cloudbox_limits[1]- cloudbox_limits[0]))],
3214  p_grid[Range(cloudbox_limits[0],
3215  (cloudbox_limits[1]- cloudbox_limits[0])+1)]);
3216 
3217  Matrix itw((cloudbox_limits[1]- cloudbox_limits[0])+1, 2);
3218  interpweights ( itw, p_gp );
3219 
3220 
3221 
3222  for (Index za_index = 0; za_index < N_za ; ++ za_index)
3223  {
3224  for (Index aa_index = 0; aa_index < N_aa ; ++ aa_index)
3225  {
3226  for (Index i = 0 ; i < N_i ; ++ i)
3227  {
3228 
3229  VectorView target_field = doit_i_field(Range(joker),
3230  0,
3231  0,
3232  za_index,
3233  aa_index,
3234  i);
3235 
3236  ConstVectorView source_field = scat_i_p(f_index,
3237  Range(joker),
3238  0,
3239  0,
3240  za_index,
3241  aa_index,
3242  i);
3243 
3244  interp(target_field,
3245  itw,
3246  source_field,
3247  p_gp);
3248  }
3249 
3250  }
3251  }
3252  }
3253  else{// no interpolation is required for other frequencies,
3254  // but the boundary needs to be set correctly.
3255  doit_i_field(0, 0, 0, Range(joker), Range(joker), Range(joker))=
3256  scat_i_p(f_index, 0, 0, 0, Range(joker), Range(joker),
3257  Range(joker));
3258  doit_i_field(doit_i_field.nvitrines()-1, 0, 0, Range(joker),
3259  Range(joker), Range(joker))=
3260  scat_i_p(f_index, 1, 0, 0, Range(joker), Range(joker),
3261  Range(joker));
3262  }
3263  }
3264  else if(atmosphere_dim == 3)
3265  {
3266  if (all_frequencies == false)
3267  throw runtime_error("Error in doit_i_fieldSetClearsky: For 3D "
3268  "all_frequencies option is not implemented \n");
3269 
3270  Index N_f = scat_i_p.nlibraries();
3271  if (scat_i_lat.nlibraries() != N_f ||
3272  scat_i_lon.nlibraries() != N_f){
3273 
3274  throw runtime_error(" scat_i_p, scat_i_lat, scat_i_lon should have "
3275  "same frequency dimension");
3276  }
3277  Index N_p = cloudbox_limits[1] - cloudbox_limits[0] + 1;
3278  if(scat_i_lon.nvitrines() != N_p ||
3279  scat_i_lat.nvitrines() != N_p ){
3280  throw runtime_error("scat_i_lat and scat_i_lon should have "
3281  "same pressure grid dimension as p_grid");
3282  }
3283 
3284  Index N_lat = cloudbox_limits[3] - cloudbox_limits[2] + 1;
3285 
3286  if(scat_i_lon.nshelves() != N_lat ||
3287  scat_i_p.nshelves() != N_lat){
3288  throw runtime_error("scat_i_p and scat_i_lon should have "
3289  "same latitude grid dimension as lat_grid");
3290  }
3291 
3292  Index N_lon = cloudbox_limits[5] - cloudbox_limits[4] + 1;
3293  if(scat_i_lat.nbooks() != N_lon ||
3294  scat_i_p.nbooks() != N_lon ){
3295  throw runtime_error("scat_i_p and scat_i_lat should have "
3296  "same longitude grid dimension as lon_grid");
3297  }
3298  if(scat_i_p.nvitrines() != 2){
3299  throw runtime_error("scat_i_p should have exactly two elements "
3300  "in pressure dimension which correspond to the "
3301  "two cloudbox bounding pressure levels");
3302  }
3303 
3304  if(scat_i_lat.nshelves() != 2){
3305  throw runtime_error("scat_i_lat should have exactly two elements "
3306  "in latitude dimension which correspond to the "
3307  "two cloudbox bounding latitude levels");
3308  }
3309  if(scat_i_lon.nbooks() != 2){
3310  throw runtime_error("scat_i_lon should have exactly two elements "
3311  "in longitude dimension which correspond to the "
3312  "two cloudbox bounding longitude levels");
3313  }
3314  Index N_za = scat_i_p.npages() ;
3315  if (scat_i_lat.npages() != N_za ||
3316  scat_i_lon.npages() != N_za){
3317 
3318  throw runtime_error(" scat_i_p, scat_i_lat, scat_i_lon should have "
3319  "same zenith angle dimension");
3320  }
3321  Index N_aa = scat_i_p.nrows();
3322  if (scat_i_lat.nrows() != N_aa ||
3323  scat_i_lon.nrows() != N_aa){
3324 
3325  throw runtime_error(" scat_i_p, scat_i_lat, scat_i_lon should have "
3326  "same azimuth angle dimension");
3327  }
3328  Index N_i = scat_i_p.ncols();
3329  if (scat_i_lat.ncols() != N_i ||
3330  scat_i_lon.ncols() != N_i){
3331 
3332  throw runtime_error(" scat_i_p, scat_i_lat, scat_i_lon should have "
3333  "same value for stokes_dim and can take only"
3334  "values 1,2,3 or 4");
3335  }
3336 
3337  //1. interpolation - pressure grid, latitude grid and longitude grid
3338 
3339 
3340  //doit_i_field
3341  doit_i_field.resize((cloudbox_limits[1]- cloudbox_limits[0])+1,
3342  (cloudbox_limits[3]- cloudbox_limits[2])+1,
3343  (cloudbox_limits[5]- cloudbox_limits[4])+1,
3344  N_za,
3345  N_aa,
3346  N_i);
3347 
3348 
3349 
3350  ArrayOfGridPos p_gp((cloudbox_limits[1]- cloudbox_limits[0])+1);
3351  ArrayOfGridPos lat_gp((cloudbox_limits[3]- cloudbox_limits[2])+1);
3352  ArrayOfGridPos lon_gp((cloudbox_limits[5]- cloudbox_limits[4])+1);
3353 
3354  /*the old grid is having only two elements, corresponding to the
3355  cloudbox_limits and the new grid have elements corresponding to
3356  all grid points inside the cloudbox plus the cloud_box_limits*/
3357 
3358  p2gridpos(p_gp,
3359  p_grid[Range(cloudbox_limits[0],
3360  2,
3361  (cloudbox_limits[1]- cloudbox_limits[0]))],
3362  p_grid[Range(cloudbox_limits[0],
3363  (cloudbox_limits[1]- cloudbox_limits[0])+1)]);
3364  gridpos(lat_gp,
3365  lat_grid[Range(cloudbox_limits[2],
3366  2,
3367  (cloudbox_limits[3]- cloudbox_limits[2]))],
3368  lat_grid[Range(cloudbox_limits[2],
3369  (cloudbox_limits[3]- cloudbox_limits[2])+1)]);
3370  gridpos(lon_gp,
3371  lon_grid[Range(cloudbox_limits[4],
3372  2,
3373  (cloudbox_limits[5]- cloudbox_limits[4]))],
3374  lon_grid[Range(cloudbox_limits[4],
3375  (cloudbox_limits[5]- cloudbox_limits[4])+1)]);
3376 
3377 
3378  //interpolation weights corresponding to pressure, latitude and
3379  //longitude grids.
3380 
3381  Matrix itw_p((cloudbox_limits[1]- cloudbox_limits[0])+1, 2);
3382  Matrix itw_lat((cloudbox_limits[3]- cloudbox_limits[2])+1, 2);
3383  Matrix itw_lon((cloudbox_limits[5]- cloudbox_limits[4])+1, 2);
3384 
3385  interpweights ( itw_p, p_gp );
3386  interpweights ( itw_lat, lat_gp );
3387  interpweights ( itw_lon, lon_gp );
3388 
3389  // interpolation - pressure grid
3390  for (Index lat_index = 0;
3391  lat_index <= (cloudbox_limits[3]-cloudbox_limits[2]); ++ lat_index)
3392  {
3393  for (Index lon_index = 0;
3394  lon_index <= (cloudbox_limits[5]-cloudbox_limits[4]);
3395  ++ lon_index)
3396  {
3397  for (Index za_index = 0; za_index < N_za ; ++ za_index)
3398  {
3399  for (Index aa_index = 0; aa_index < N_aa ; ++ aa_index)
3400  {
3401  for (Index i = 0 ; i < N_i ; ++ i)
3402  {
3403 
3404  VectorView target_field = doit_i_field(Range(joker),
3405  lat_index,
3406  lon_index,
3407  za_index,
3408  aa_index,
3409  i);
3410 
3411  ConstVectorView source_field = scat_i_p(f_index,
3412  Range(joker),
3413  lat_index,
3414  lon_index,
3415  za_index,
3416  aa_index,
3417  i);
3418 
3419  interp(target_field,
3420  itw_p,
3421  source_field,
3422  p_gp);
3423  }
3424  }
3425  }
3426  }
3427  }
3428  //interpolation latitude
3429  for (Index p_index = 0;
3430  p_index <= (cloudbox_limits[1]-cloudbox_limits[0]) ; ++ p_index)
3431  {
3432  for (Index lon_index = 0;
3433  lon_index <= (cloudbox_limits[5]-cloudbox_limits[4]) ;
3434  ++ lon_index)
3435  {
3436  for (Index za_index = 0; za_index < N_za ; ++ za_index)
3437  {
3438  for (Index aa_index = 0; aa_index < N_aa ; ++ aa_index)
3439  {
3440  for (Index i = 0 ; i < N_i ; ++ i)
3441  {
3442 
3443  VectorView target_field = doit_i_field
3444  (p_index, Range(joker), lon_index,
3445  za_index, aa_index, i);
3446 
3447  ConstVectorView source_field = scat_i_lat
3448  (f_index, p_index, Range(joker),
3449  lon_index, za_index, aa_index, i);
3450 
3451  interp(target_field,
3452  itw_lat,
3453  source_field,
3454  lat_gp);
3455  }
3456  }
3457  }
3458  }
3459  }
3460  //interpolation -longitude
3461  for (Index p_index = 0;
3462  p_index <= (cloudbox_limits[1]-cloudbox_limits[0]); ++ p_index)
3463  {
3464  for (Index lat_index = 0;
3465  lat_index <= (cloudbox_limits[3]-cloudbox_limits[2]);
3466  ++ lat_index)
3467  {
3468  for (Index za_index = 0; za_index < N_za ; ++ za_index)
3469  {
3470  for (Index aa_index = 0; aa_index < N_aa ; ++ aa_index)
3471  {
3472  for (Index i = 0 ; i < N_i ; ++ i)
3473  {
3474 
3475  VectorView target_field = doit_i_field(p_index,
3476  lat_index,
3477  Range(joker),
3478  za_index,
3479  aa_index,
3480  i);
3481 
3482  ConstVectorView source_field = scat_i_lon(f_index,
3483  p_index,
3484  lat_index,
3485  Range(joker),
3486  za_index,
3487  aa_index,
3488  i);
3489 
3490  interp(target_field,
3491  itw_lon,
3492  source_field,
3493  lon_gp);
3494  }
3495  }
3496  }
3497  }
3498  }
3499  //end of interpolation
3500  }//ends atmosphere_dim = 3
3501 }
3502 
3503 
3504 /* Workspace method: Doxygen documentation will be auto-generated */
3505 void doit_i_fieldSetConst(//WS Output:
3506  Tensor6& doit_i_field,
3507  //WS Input:
3508  const Tensor7& scat_i_p,
3509  const Tensor7& scat_i_lat,
3510  const Tensor7& scat_i_lon,
3511  const Vector& p_grid,
3512  const Vector& lat_grid,
3513  const Vector& lon_grid,
3514  const ArrayOfIndex& cloudbox_limits,
3515  const Index& atmosphere_dim,
3516  const Index& stokes_dim,
3517  // Keyword
3518  const Vector& doit_i_field_values,
3519  const Verbosity& verbosity)
3520 {
3521  CREATE_OUT2
3522  CREATE_OUT3
3523 
3524  out2 << " Set initial field to constant values: " << doit_i_field_values << "\n";
3525 
3526  // In the 1D case the atmospheric layers are defined by p_grid and the
3527  // required interface is scat_i_p.
3528  Index N_za = scat_i_p.npages();
3529  Index N_aa = scat_i_p.nrows();
3530  Index N_i = stokes_dim;
3531  Index Np_cloud = cloudbox_limits[1] - cloudbox_limits[0] + 1;
3532  Index Nlat_cloud = cloudbox_limits[3] - cloudbox_limits[2] + 1;
3533  Index Nlon_cloud = cloudbox_limits[5] - cloudbox_limits[4] + 1;
3534 
3535  chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
3536 
3537  // Grids have to be adapted to atmosphere_dim.
3538  chk_atm_grids( atmosphere_dim, p_grid, lat_grid, lon_grid );
3539 
3540  // Check the input:
3541  if (stokes_dim < 0 || stokes_dim > 4)
3542  throw runtime_error(
3543  "The dimension of stokes vector must be"
3544  "1,2,3, or 4");
3545 
3546  if ( cloudbox_limits.nelem()!= 2*atmosphere_dim)
3547  throw runtime_error(
3548  "*cloudbox_limits* is a vector which contains the"
3549  "upper and lower limit of the cloud for all "
3550  "atmospheric dimensions. So its dimension must"
3551  "be 2 x *atmosphere_dim*");
3552 
3553 
3554 
3555  if(atmosphere_dim == 1)
3556  {
3557  out3 << " atm_dim = 1\n";
3558 
3559  // Define the size of doit_i_field.
3560  doit_i_field.resize((cloudbox_limits[1] - cloudbox_limits[0])+1, 1, 1, N_za,
3561  1, N_i);
3562  doit_i_field = 0.;
3563 
3564  // Loop over all zenith angle directions.
3565  for (Index za_index = 0; za_index < N_za; za_index++)
3566  {
3567  for (Index i = 0; i < stokes_dim; i++)
3568  {
3569  //set the value for the upper boundary
3570  doit_i_field(cloudbox_limits[1]-cloudbox_limits[0], 0, 0, za_index,
3571  0, i) =
3572  scat_i_p(0, 1, 0, 0, za_index, 0, i);
3573  //set the value for the lower boundary
3574  doit_i_field(0, 0, 0, za_index, 0, i) =
3575  scat_i_p(0, 0, 0, 0, za_index, 0, i);
3576  for (Index scat_p_index = 1; scat_p_index < cloudbox_limits[1] -
3577  cloudbox_limits[0]; scat_p_index++ )
3578  // The field inside the cloudbox is set to some arbitrary value.
3579  doit_i_field(scat_p_index, 0, 0, za_index, 0, i) = doit_i_field_values[i];
3580  }
3581  }
3582  }
3583  else
3584  {
3585  if ( !is_size(scat_i_p, 1, 2, Nlat_cloud,
3586  Nlon_cloud, N_za, N_aa, stokes_dim)
3587  || !is_size(scat_i_lat, 1, Np_cloud, 2,
3588  Nlon_cloud, N_za, N_aa, stokes_dim)
3589  || !is_size(scat_i_lon, 1, Np_cloud,
3590  Nlat_cloud, 2, N_za, N_aa, stokes_dim) )
3591  throw runtime_error(
3592  "One of the interface variables (*scat_i_p*, "
3593  "*scat_i_lat* or *scat_i_lon*) does not have "
3594  "the right dimensions. \n Probably you have "
3595  "calculated them before for another value of "
3596  "*stokes_dim*."
3597  );
3598 
3599 
3600 
3601  out3 << "atm_dim = 3\n";
3602  doit_i_field.resize((cloudbox_limits[1]- cloudbox_limits[0])+1,
3603  (cloudbox_limits[3]- cloudbox_limits[2])+1,
3604  (cloudbox_limits[5]- cloudbox_limits[4])+1,
3605  N_za,
3606  N_aa,
3607  N_i);
3608 
3609  doit_i_field = 0.;
3610 
3611 
3612  // Loop over all directions:
3613  for (Index za_index = 0; za_index < N_za; za_index++)
3614  {
3615  for (Index aa_index = 0; aa_index < N_aa; aa_index++)
3616  {
3617  for (Index i = 0; i < stokes_dim; i++)
3618  {
3619  // pressure boundaries
3620  //
3621  for (Index lat_index = cloudbox_limits[2];
3622  lat_index <= cloudbox_limits[3]; lat_index++)
3623  {
3624  for (Index lon_index = cloudbox_limits[4];
3625  lon_index <= cloudbox_limits[5]; lon_index++)
3626  {
3627  //set the value for the upper pressure boundary
3628  doit_i_field(cloudbox_limits[1]-cloudbox_limits[0],
3629  lat_index-cloudbox_limits[2],
3630  lon_index-cloudbox_limits[4],
3631  za_index, aa_index, i) =
3632  scat_i_p(0, 1, lat_index-cloudbox_limits[2],
3633  lon_index-cloudbox_limits[4],
3634  za_index, aa_index, i);
3635  //set the value for the lower pressure boundary
3636  doit_i_field(0, lat_index-cloudbox_limits[2],
3637  lon_index-cloudbox_limits[4],
3638  za_index, aa_index, i) =
3639  scat_i_p(0, 0, lat_index-cloudbox_limits[2],
3640  lon_index-cloudbox_limits[4],
3641  za_index, aa_index, i);
3642  }
3643  }
3644 
3645  for (Index p_index = cloudbox_limits[0];
3646  p_index <= cloudbox_limits[1]; p_index++)
3647  {
3648  // latitude boundaries
3649  //
3650  for (Index lon_index = cloudbox_limits[4];
3651  lon_index <= cloudbox_limits[5]; lon_index++)
3652  {
3653  // first boundary
3654  doit_i_field(p_index-cloudbox_limits[0],
3655  cloudbox_limits[3]-cloudbox_limits[2],
3656  lon_index-cloudbox_limits[4],
3657  za_index, aa_index, i) =
3658  scat_i_lat(0, p_index-cloudbox_limits[0],
3659  1, lon_index-cloudbox_limits[4],
3660  za_index, aa_index, i);
3661  // second boundary
3662  doit_i_field(p_index-cloudbox_limits[0], 0,
3663  lon_index-cloudbox_limits[4],
3664  za_index, aa_index, i) =
3665  scat_i_lat(0, p_index-cloudbox_limits[0], 0,
3666  lon_index-cloudbox_limits[4],
3667  za_index, aa_index, i);
3668 
3669  }
3670  // longitude boundaries
3671  for (Index lat_index = cloudbox_limits[2];
3672  lat_index <= cloudbox_limits[3]; lat_index++)
3673  {
3674  // first boundary
3675  doit_i_field(p_index-cloudbox_limits[0],
3676  lat_index-cloudbox_limits[2],
3677  cloudbox_limits[5]-cloudbox_limits[4],
3678  za_index, aa_index, i) =
3679  scat_i_lon(0, p_index-cloudbox_limits[0],
3680  lat_index-cloudbox_limits[2], 1,
3681  za_index, aa_index, i);
3682  // second boundary
3683  doit_i_field(p_index-cloudbox_limits[0],
3684  lat_index-cloudbox_limits[2],
3685  0,
3686  za_index, aa_index, i) =
3687  scat_i_lon(0, p_index-cloudbox_limits[0],
3688  lat_index-cloudbox_limits[2], 0,
3689  za_index, aa_index, i);
3690  } //lat_grid loop
3691  } //p_grid loop
3692  //
3693  // Set the initial field to a constant value inside the
3694  // cloudbox:
3695  //
3696  for( Index p_index = (cloudbox_limits[0]+1);
3697  p_index < cloudbox_limits[1] ;
3698  p_index ++)
3699  {
3700  for (Index lat_index = (cloudbox_limits[2]+1);
3701  lat_index < cloudbox_limits[3];
3702  lat_index++)
3703  {
3704  for (Index lon_index = (cloudbox_limits[4]+1);
3705  lon_index < cloudbox_limits[5];
3706  lon_index++)
3707  {
3708  doit_i_field(p_index-cloudbox_limits[0],
3709  lat_index-cloudbox_limits[2],
3710  lon_index-cloudbox_limits[4],
3711  za_index, aa_index, i) =
3712  doit_i_field_values[i];
3713  }
3714  }
3715  }
3716  } // stokes loop
3717  } // aa_grid loop
3718  } // za_grid loop
3719 
3720  } // atmosphere dim = 3
3721 }
Matrix
The Matrix class.
Definition: matpackI.h:767
iy_interp_cloudbox_field
void iy_interp_cloudbox_field(Matrix &iy, const Tensor7 &scat_i_p, const Tensor7 &scat_i_lat, const Tensor7 &scat_i_lon, const Tensor4 &doit_i_field1D_spectrum, const GridPos &rte_gp_p, const GridPos &rte_gp_lat, const GridPos &rte_gp_lon, const Vector &rte_los, const Index &cloudbox_on, const ArrayOfIndex &cloudbox_limits, const Index &atmosphere_dim, const Index &stokes_dim, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Vector &f_grid, const String &interpmeth, const Verbosity &verbosity)
Interpolation of cloud box intensity field.
Definition: doit.cc:2033
Tensor4::resize
void resize(Index b, Index p, Index r, Index c)
Resize function.
Definition: matpackIV.cc:1404
ConstTensor7View::nshelves
Index nshelves() const
Returns the number of shelves.
Definition: matpackVII.cc:43
ConstTensor6View::nshelves
Index nshelves() const
Returns the number of shelves.
Definition: matpackVI.cc:37
doit_za_grid_optCalc
void doit_za_grid_optCalc(Vector &doit_za_grid_opt, const Tensor6 &doit_i_field, const Vector &scat_za_grid, const Index &doit_za_interp, const Numeric &acc, const Verbosity &)
WORKSPACE METHOD: doit_za_grid_optCalc.
Definition: m_doit.cc:2303
doit_i_fieldUpdateSeq1D
void doit_i_fieldUpdateSeq1D(Workspace &ws, Tensor6 &doit_i_field, const Tensor6 &doit_scat_field, const ArrayOfIndex &cloudbox_limits, const Agenda &abs_scalar_gas_agenda, const Tensor4 &vmr_field, const Agenda &spt_calc_agenda, const Vector &scat_za_grid, const Tensor4 &pnd_field, const Agenda &opt_prop_part_agenda, const Agenda &opt_prop_gas_agenda, const Agenda &ppath_step_agenda, const Vector &p_grid, const Tensor3 &z_field, const Matrix &r_geoid, const Matrix &z_surface, const Tensor3 &t_field, const Vector &f_grid, const Index &f_index, const Agenda &surface_prop_agenda, const Index &doit_za_interp, const Verbosity &verbosity)
WORKSPACE METHOD: doit_i_fieldUpdateSeq1D.
Definition: m_doit.cc:720
auto_md.h
Tensor6::resize
void resize(Index v, Index s, Index b, Index p, Index r, Index c)
Resize function.
Definition: matpackVI.cc:2845
chk_atm_surface
void chk_atm_surface(const String &x_name, const Matrix &x, const Index &dim, ConstVectorView lat_grid, ConstVectorView lon_grid)
chk_atm_surface
Definition: check_input.cc:821
pha_mat_spt_agendaExecute
void pha_mat_spt_agendaExecute(Workspace &ws, Tensor5 &pha_mat_spt, const Index scat_za_index, const Index scat_lat_index, const Index scat_lon_index, const Index scat_p_index, const Index scat_aa_index, const Numeric rte_temperature, const Agenda &input_agenda)
Definition: auto_md.cc:10216
interp_poly
Numeric interp_poly(ConstVectorView x, ConstVectorView y, const Numeric &x_i, const GridPos &gp)
Polynomial interpolation.
Definition: interpolation.cc:2909
doit_mono_agendaExecute
void doit_mono_agendaExecute(Workspace &ws, Tensor6 &doit_i_field, Tensor7 &scat_i_p, Tensor7 &scat_i_lat, Tensor7 &scat_i_lon, Tensor4 &doit_i_field1D_spectrum, const Index f_index, const Agenda &input_agenda)
Definition: auto_md.cc:9233
chk_if_increasing
void chk_if_increasing(const String &x_name, const ArrayOfIndex &x)
chk_if_increasing
Definition: check_input.cc:126
gridpos
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
Definition: interpolation.cc:167
cloud_ppath_update1D
void cloud_ppath_update1D(Workspace &ws, Tensor6View doit_i_field, const Index &p_index, const Index &scat_za_index, ConstVectorView scat_za_grid, const ArrayOfIndex &cloudbox_limits, ConstTensor6View doit_scat_field, const Agenda &abs_scalar_gas_agenda, ConstTensor4View vmr_field, const Agenda &opt_prop_gas_agenda, const Agenda &ppath_step_agenda, ConstVectorView p_grid, ConstTensor3View z_field, ConstMatrixView r_geoid, ConstMatrixView z_surface, ConstTensor3View t_field, ConstVectorView f_grid, const Index &f_index, ConstTensor5View ext_mat_field, ConstTensor4View abs_vec_field, const Agenda &surface_prop_agenda, const Index &scat_za_interp, const Verbosity &verbosity)
cloud_ppath_update1D
Definition: doit.cc:247
doit_i_fieldUpdateSeq1DPP
void doit_i_fieldUpdateSeq1DPP(Workspace &ws, Tensor6 &doit_i_field, Index &scat_za_index, const Tensor6 &doit_scat_field, const ArrayOfIndex &cloudbox_limits, const Agenda &abs_scalar_gas_agenda, const Tensor4 &vmr_field, const Agenda &spt_calc_agenda, const Vector &scat_za_grid, const Tensor4 &pnd_field, const Agenda &opt_prop_part_agenda, const Agenda &opt_prop_gas_agenda, const Agenda &ppath_step_agenda, const Vector &p_grid, const Tensor3 &z_field, const Matrix &r_geoid, const Tensor3 &t_field, const Vector &f_grid, const Index &f_index, const Verbosity &verbosity)
WORKSPACE METHOD: doit_i_fieldUpdateSeq1DPP.
Definition: m_doit.cc:1262
Tensor3
The Tensor3 class.
Definition: matpackIII.h:340
ConstTensor6View::npages
Index npages() const
Returns the number of pages.
Definition: matpackVI.cc:49
za_gridOpt
void za_gridOpt(Vector &za_grid_opt, Matrix &doit_i_field_opt, ConstVectorView za_grid_fine, ConstTensor6View doit_i_field, const Numeric &acc, const Index &scat_za_interp)
Definition: doit.cc:1886
p2gridpos
void p2gridpos(ArrayOfGridPos &gp, ConstVectorView old_pgrid, ConstVectorView new_pgrid, const Numeric &extpolfac)
p2gridpos
Definition: special_interp.cc:810
ConstTensor7View::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackVII.cc:67
joker
const Joker joker
ScatteringDoit
void ScatteringDoit(Workspace &ws, Tensor6 &doit_i_field, Tensor7 &scat_i_p, Tensor7 &scat_i_lat, Tensor7 &scat_i_lon, Tensor4 &doit_i_field1D_spectrum, const Index &cloudbox_on, const Vector &f_grid, const Agenda &doit_mono_agenda, const Index &doit_is_initialized, const Verbosity &verbosity)
WORKSPACE METHOD: ScatteringDoit.
Definition: m_doit.cc:2378
interp
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPos &tc)
Red 1D Interpolate.
Definition: interpolation.cc:1000
doit_rte_agendaExecute
void doit_rte_agendaExecute(Workspace &ws, Tensor6 &doit_i_field, const Tensor6 &doit_scat_field, const Agenda &input_agenda)
Definition: auto_md.cc:9306
chk_not_empty
void chk_not_empty(const String &x_name, const Agenda &x)
chk_not_empty
Definition: check_input.cc:880
ConstTensor6View::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackVI.cc:55
doit_i_fieldSetClearsky
void doit_i_fieldSetClearsky(Tensor6 &doit_i_field, const Tensor7 &scat_i_p, const Tensor7 &scat_i_lat, const Tensor7 &scat_i_lon, const Vector &f_grid, const Index &f_index, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const ArrayOfIndex &cloudbox_limits, const Index &atmosphere_dim, const Index &all_frequencies, const Verbosity &verbosity)
WORKSPACE METHOD: doit_i_fieldSetClearsky.
Definition: m_doit.cc:3150
doit.h
Radiative transfer in cloudbox.
iyInterpCloudboxField
void iyInterpCloudboxField(Matrix &iy, Matrix &iy_error, Index &iy_error_type, Matrix &iy_aux, ArrayOfTensor3 &diy_dx, const Tensor3 &iy_transmission, const Tensor7 &scat_i_p, const Tensor7 &scat_i_lat, const Tensor7 &scat_i_lon, const Tensor4 &doit_i_field1D_spectrum, const GridPos &rte_gp_p, const GridPos &rte_gp_lat, const GridPos &rte_gp_lon, const Vector &rte_los, const Index &jacobian_do, const Index &cloudbox_on, const ArrayOfIndex &cloudbox_limits, const Index &atmosphere_dim, const Index &stokes_dim, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Vector &f_grid, const Verbosity &verbosity)
WORKSPACE METHOD: iyInterpCloudboxField.
Definition: m_doit.cc:3021
AngIntegrate_trapezoid_opti
Numeric AngIntegrate_trapezoid_opti(ConstMatrixView Integrand, ConstVectorView za_grid, ConstVectorView aa_grid, ConstVectorView grid_stepsize)
AngIntegrate_trapezoid_opti.
Definition: math_funcs.cc:377
cloud_fieldsCalc
void cloud_fieldsCalc(Workspace &ws, Tensor5View ext_mat_field, Tensor4View abs_vec_field, const Agenda &spt_calc_agenda, const Agenda &opt_prop_part_agenda, const Index &scat_za_index, const Index &scat_aa_index, const ArrayOfIndex &cloudbox_limits, ConstTensor3View t_field, ConstTensor4View pnd_field, const Verbosity &verbosity)
cloud_fieldsCalc
Definition: doit.cc:86
CREATE_OUT2
#define CREATE_OUT2
Definition: messages.h:207
doit_scat_fieldCalcLimb
void doit_scat_fieldCalcLimb(Workspace &ws, Tensor6 &doit_scat_field, const Agenda &pha_mat_spt_agenda, const Tensor6 &doit_i_field, const Tensor4 &pnd_field, const Tensor3 &t_field, const Index &atmosphere_dim, const ArrayOfIndex &cloudbox_limits, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Index &doit_za_grid_size, const Index &doit_za_interp, const Verbosity &verbosity)
WORKSPACE METHOD: doit_scat_fieldCalcLimb.
Definition: m_doit.cc:1907
Tensor4
The Tensor4 class.
Definition: matpackIV.h:375
array.h
This file contains the definition of Array.
doit_conv_flagLsq
void doit_conv_flagLsq(Index &doit_conv_flag, Index &doit_iteration_counter, const Tensor6 &doit_i_field, const Tensor6 &doit_i_field_old, const Vector &f_grid, const Index &f_index, const Vector &epsilon, const Verbosity &verbosity)
WORKSPACE METHOD: doit_conv_flagLsq.
Definition: m_doit.cc:355
is_size
bool is_size(ConstVectorView x, const Index &n)
Verifies that the size of x is l.
Definition: logic.cc:90
Ppath
The structure to describe a propagation path and releated quantities.
Definition: ppath.h:59
CREATE_OUT1
#define CREATE_OUT1
Definition: messages.h:206
Agenda
The Agenda class.
Definition: agenda_class.h:44
iy_clearsky_basic_agendaExecute
void iy_clearsky_basic_agendaExecute(Workspace &ws, Matrix &iy, const Vector &rte_pos, const Vector &rte_los, const Index cloudbox_on, const Agenda &input_agenda)
Definition: auto_md.cc:9589
DoitInit
void DoitInit(Index &scat_p_index, Index &scat_lat_index, Index &scat_lon_index, Index &scat_za_index, Index &scat_aa_index, Tensor6 &doit_scat_field, Tensor6 &doit_i_field, Index &doit_is_initialized, const Index &stokes_dim, const Index &atmosphere_dim, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Index &doit_za_grid_size, const Index &cloudbox_on, const ArrayOfIndex &cloudbox_limits, const ArrayOfSingleScatteringData &scat_data_raw, const Verbosity &verbosity)
WORKSPACE METHOD: DoitInit.
Definition: m_doit.cc:1434
ConstTensor7View::nlibraries
Index nlibraries() const
Returns the number of libraries.
Definition: matpackVII.cc:31
invrayjean
Numeric invrayjean(const Numeric &i, const Numeric &f)
invrayjean
Definition: physics_funcs.cc:170
Array< Index >
DoitWriteIterationFields
void DoitWriteIterationFields(const Index &doit_iteration_counter, const Tensor6 &doit_i_field, const ArrayOfIndex &iterations, const Verbosity &verbosity)
WORKSPACE METHOD: DoitWriteIterationFields.
Definition: m_doit.cc:1569
ConstTensor6View::nvitrines
Index nvitrines() const
Returns the number of vitrines.
Definition: matpackVI.cc:31
DoitAngularGridsSet
void DoitAngularGridsSet(Index &doit_za_grid_size, Vector &scat_aa_grid, Vector &scat_za_grid, const Index &N_za_grid, const Index &N_aa_grid, const String &za_grid_opt_file, const Verbosity &verbosity)
WORKSPACE METHOD: DoitAngularGridsSet.
Definition: m_doit.cc:71
agenda_class.h
Declarations for agendas.
xml_read_from_file
void xml_read_from_file(const String &filename, T &type, const Verbosity &verbosity)
Reads data from XML file.
Definition: xml_io.cc:850
Tensor7::resize
void resize(Index l, Index v, Index s, Index b, Index p, Index r, Index c)
Resize function.
Definition: matpackVII.cc:5341
pha_matCalc
void pha_matCalc(Tensor4 &pha_mat, const Tensor5 &pha_mat_spt, const Tensor4 &pnd_field, const Index &atmosphere_dim, const Index &scat_p_index, const Index &scat_lat_index, const Index &scat_lon_index, const Verbosity &)
WORKSPACE METHOD: pha_matCalc.
Definition: m_optproperties.cc:823
CREATE_OUT3
#define CREATE_OUT3
Definition: messages.h:208
CREATE_OUT0
#define CREATE_OUT0
Definition: messages.h:205
iyInterpPolyCloudboxField
void iyInterpPolyCloudboxField(Matrix &iy, Matrix &iy_error, Index &iy_error_type, Matrix &iy_aux, ArrayOfTensor3 &diy_dx, const Tensor3 &iy_transmission, const Tensor7 &scat_i_p, const Tensor7 &scat_i_lat, const Tensor7 &scat_i_lon, const Tensor4 &doit_i_field1D_spectrum, const GridPos &rte_gp_p, const GridPos &rte_gp_lat, const GridPos &rte_gp_lon, const Vector &rte_los, const Index &jacobian_do, const Index &cloudbox_on, const ArrayOfIndex &cloudbox_limits, const Index &atmosphere_dim, const Index &stokes_dim, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Vector &f_grid, const Verbosity &verbosity)
WORKSPACE METHOD: iyInterpPolyCloudboxField.
Definition: m_doit.cc:3086
messages.h
Declarations having to do with the four output streams.
doit_conv_flagAbsBT
void doit_conv_flagAbsBT(Index &doit_conv_flag, Index &doit_iteration_counter, const Tensor6 &doit_i_field, const Tensor6 &doit_i_field_old, const Vector &f_grid, const Index &f_index, const Vector &epsilon, const Verbosity &verbosity)
WORKSPACE METHOD: doit_conv_flagAbsBT.
Definition: m_doit.cc:233
ConstMatrixView::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackI.cc:802
my_basic_string
The implementation for String, the ARTS string class.
Definition: mystring.h:62
abs
#define abs(x)
Definition: continua.cc:13094
RAD2DEG
const Numeric RAD2DEG
rayjean
Numeric rayjean(const Numeric &f, const Numeric &t)
rayjean
Definition: physics_funcs.cc:252
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:175
VectorView
The VectorView class.
Definition: matpackI.h:373
ConstTensor7View::nvitrines
Index nvitrines() const
Returns the number of vitrines.
Definition: matpackVII.cc:37
physics_funcs.h
doit_i_fieldUpdateSeq3D
void doit_i_fieldUpdateSeq3D(Workspace &ws, Tensor6 &doit_i_field, const Tensor6 &doit_scat_field, const ArrayOfIndex &cloudbox_limits, const Agenda &abs_scalar_gas_agenda, const Tensor4 &vmr_field, const Agenda &spt_calc_agenda, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Tensor4 &pnd_field, const Agenda &opt_prop_part_agenda, const Agenda &opt_prop_gas_agenda, const Agenda &ppath_step_agenda, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &z_field, const Matrix &r_geoid, const Matrix &z_surface, const Tensor3 &t_field, const Vector &f_grid, const Index &f_index, const Index &doit_za_interp, const Verbosity &verbosity)
WORKSPACE METHOD: doit_i_fieldUpdateSeq3D.
Definition: m_doit.cc:957
ConstTensor7View::npages
Index npages() const
Returns the number of pages.
Definition: matpackVII.cc:55
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
lin_alg.h
Linear algebra functions.
Verbosity
Definition: messages.h:50
ConstTensor4View::nbooks
Index nbooks() const
Returns the number of books.
Definition: matpackIV.cc:60
math_funcs.h
doit_conv_flagAbs
void doit_conv_flagAbs(Index &doit_conv_flag, Index &doit_iteration_counter, const Tensor6 &doit_i_field, const Tensor6 &doit_i_field_old, const Vector &epsilon, const Verbosity &verbosity)
WORKSPACE METHOD: doit_conv_flagAbs.
Definition: m_doit.cc:121
Matrix::resize
void resize(Index r, Index c)
Resize function.
Definition: matpackI.cc:1549
cloud_ppath_update1D_planeparallel
void cloud_ppath_update1D_planeparallel(Workspace &ws, Tensor6View doit_i_field, const Index &p_index, const Index &scat_za_index, ConstVectorView scat_za_grid, const ArrayOfIndex &cloudbox_limits, ConstTensor6View doit_scat_field, const Agenda &abs_scalar_gas_agenda, ConstTensor4View vmr_field, const Agenda &opt_prop_gas_agenda, const Agenda &ppath_step_agenda, ConstVectorView p_grid, ConstTensor3View z_field, ConstMatrixView r_geoid, 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:1382
nlinspace
void nlinspace(Vector &x, const Numeric start, const Numeric stop, const Index n)
nlinspace
Definition: math_funcs.cc:261
ConstTensor6View::nbooks
Index nbooks() const
Returns the number of books.
Definition: matpackVI.cc:43
Tensor5
The Tensor5 class.
Definition: matpackV.h:443
Range
The range class.
Definition: matpackI.h:148
GridPos
Structure to store a grid position.
Definition: interpolation.h:74
ConstTensor7View::nbooks
Index nbooks() const
Returns the number of books.
Definition: matpackVII.cc:49
ppath.h
Propagation path structure and functions.
doit_conv_test_agendaExecute
void doit_conv_test_agendaExecute(Workspace &ws, Index &doit_conv_flag, Index &doit_iteration_counter, const Tensor6 &doit_i_field, const Tensor6 &doit_i_field_old, const Agenda &input_agenda)
Definition: auto_md.cc:9105
logic.h
Header file for logic.cc.
cloud_ppath_update1D_noseq
void cloud_ppath_update1D_noseq(Workspace &ws, Tensor6View doit_i_field, const Index &p_index, const Index &scat_za_index, ConstVectorView scat_za_grid, const ArrayOfIndex &cloudbox_limits, ConstTensor6View doit_i_field_old, ConstTensor6View doit_scat_field, const Agenda &abs_scalar_gas_agenda, ConstTensor4View vmr_field, const Agenda &opt_prop_gas_agenda, const Agenda &ppath_step_agenda, ConstVectorView p_grid, ConstTensor3View z_field, ConstMatrixView r_geoid, ConstMatrixView z_surface, ConstTensor3View t_field, ConstVectorView f_grid, const Index &f_index, ConstTensor5View ext_mat_field, ConstTensor4View abs_vec_field, const Agenda &surface_prop_agenda, const Index &scat_za_interp, const Verbosity &verbosity)
cloud_ppath_update1D_noseq
Definition: doit.cc:392
chk_atm_grids
void chk_atm_grids(const Index &dim, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid)
chk_atm_grids
Definition: check_input.cc:603
rte.h
Declaration of functions in rte.cc.
Workspace
Workspace class.
Definition: workspace_ng.h:47
special_interp.h
Header file for special_interp.cc.
FILE_TYPE_ASCII
@ FILE_TYPE_ASCII
Definition: xml_io.h:39
doit_i_fieldUpdate1D
void doit_i_fieldUpdate1D(Workspace &ws, Tensor6 &doit_i_field, const Tensor6 &doit_i_field_old, const Tensor6 &doit_scat_field, const ArrayOfIndex &cloudbox_limits, const Agenda &abs_scalar_gas_agenda, const Tensor4 &vmr_field, const Agenda &spt_calc_agenda, const Vector &scat_za_grid, const Tensor4 &pnd_field, const Agenda &opt_prop_part_agenda, const Agenda &opt_prop_gas_agenda, const Agenda &ppath_step_agenda, const Vector &p_grid, const Tensor3 &z_field, const Matrix &r_geoid, const Matrix &z_surface, const Tensor3 &t_field, const Vector &f_grid, const Index &f_index, const Agenda &surface_prop_agenda, const Index &doit_za_interp, const Verbosity &verbosity)
WORKSPACE METHOD: doit_i_fieldUpdate1D.
Definition: m_doit.cc:548
doit_scat_field_agendaExecute
void doit_scat_field_agendaExecute(Workspace &ws, Tensor6 &doit_scat_field, const Tensor6 &doit_i_field, const Agenda &input_agenda)
Definition: auto_md.cc:9172
DoitCloudboxFieldPut
void DoitCloudboxFieldPut(Tensor7 &scat_i_p, Tensor7 &scat_i_lat, Tensor7 &scat_i_lon, Tensor4 &doit_i_field1D_spectrum, const Tensor6 &doit_i_field, const Vector &f_grid, const Index &f_index, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Index &stokes_dim, const Index &atmosphere_dim, const ArrayOfIndex &cloudbox_limits, const Matrix &sensor_pos, const Tensor3 &z_field, const Verbosity &verbosity)
WORKSPACE METHOD: DoitCloudboxFieldPut.
Definition: m_doit.cc:2447
doit_za_interpSet
void doit_za_interpSet(Index &doit_za_interp, const Index &atmosphere_dim, const String &method, const Verbosity &)
WORKSPACE METHOD: doit_za_interpSet.
Definition: m_doit.cc:2351
xml_write_to_file
void xml_write_to_file(const String &filename, const T &type, const FileType ftype, const Verbosity &verbosity)
Write data to XML file.
Definition: xml_io.cc:1017
PI
const Numeric PI
chk_size
void chk_size(const String &x_name, ConstVectorView x, const Index &c)
Runtime check for size of Vector.
Definition: check_input.cc:911
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
chk_if_in_range
void chk_if_in_range(const String &x_name, const Index &x, const Index &x_low, const Index &x_high)
chk_if_in_range
Definition: check_input.cc:95
ConstTensor7View::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackVII.cc:61
Tensor6
The Tensor6 class.
Definition: matpackVI.h:937
check_input.h
CloudboxGetIncoming
void CloudboxGetIncoming(Workspace &ws, Tensor7 &scat_i_p, Tensor7 &scat_i_lat, Tensor7 &scat_i_lon, const Agenda &iy_clearsky_basic_agenda, const Index &atmosphere_dim, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &z_field, const Matrix &r_geoid, const Index &cloudbox_on, const ArrayOfIndex &cloudbox_limits, const Vector &f_grid, const Index &stokes_dim, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Verbosity &)
WORKSPACE METHOD: CloudboxGetIncoming.
Definition: m_doit.cc:2648
doit_scat_fieldCalc
void doit_scat_fieldCalc(Workspace &ws, Tensor6 &doit_scat_field, const Agenda &pha_mat_spt_agenda, const Tensor6 &doit_i_field, const Tensor4 &pnd_field, const Tensor3 &t_field, const Index &atmosphere_dim, const ArrayOfIndex &cloudbox_limits, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Index &doit_za_grid_size, const Verbosity &verbosity)
WORKSPACE METHOD: doit_scat_fieldCalc.
Definition: m_doit.cc:1607
Vector
The Vector class.
Definition: matpackI.h:555
doit_i_fieldIterate
void doit_i_fieldIterate(Workspace &ws, Tensor6 &doit_i_field, const Agenda &doit_scat_field_agenda, const Agenda &doit_rte_agenda, const Agenda &doit_conv_test_agenda, const Verbosity &verbosity)
WORKSPACE METHOD: doit_i_fieldIterate.
Definition: m_doit.cc:482
ConstVectorView
A constant view of a Vector.
Definition: matpackI.h:300
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:172
ConstTensor6View::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackVI.cc:61
chk_if_decreasing
void chk_if_decreasing(const String &x_name, ConstVectorView x)
chk_if_decreasing
Definition: check_input.cc:316
CloudboxGetIncoming1DAtm
void CloudboxGetIncoming1DAtm(Workspace &ws, Tensor7 &scat_i_p, Tensor7 &scat_i_lat, Tensor7 &scat_i_lon, Index &cloudbox_on, const Agenda &iy_clearsky_basic_agenda, const Index &atmosphere_dim, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &z_field, const Matrix &r_geoid, const ArrayOfIndex &cloudbox_limits, const Vector &f_grid, const Index &stokes_dim, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Verbosity &)
WORKSPACE METHOD: CloudboxGetIncoming1DAtm.
Definition: m_doit.cc:2877
wsv_aux.h
Auxiliary header stuff related to workspace variable groups.
interpweights
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
Definition: interpolation.cc:756
doit_i_fieldSetConst
void doit_i_fieldSetConst(Tensor6 &doit_i_field, const Tensor7 &scat_i_p, const Tensor7 &scat_i_lat, const Tensor7 &scat_i_lon, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const ArrayOfIndex &cloudbox_limits, const Index &atmosphere_dim, const Index &stokes_dim, const Vector &doit_i_field_values, const Verbosity &verbosity)
WORKSPACE METHOD: doit_i_fieldSetConst.
Definition: m_doit.cc:3505
Tensor7
The Tensor7 class.
Definition: matpackVII.h:1912
matpackVII.h
cloud_ppath_update3D
void cloud_ppath_update3D(Workspace &ws, Tensor6View doit_i_field, const Index &p_index, const Index &lat_index, const Index &lon_index, const Index &scat_za_index, const Index &scat_aa_index, ConstVectorView scat_za_grid, ConstVectorView scat_aa_grid, const ArrayOfIndex &cloudbox_limits, ConstTensor6View doit_scat_field, const Agenda &abs_scalar_gas_agenda, ConstTensor4View vmr_field, const Agenda &opt_prop_gas_agenda, const Agenda &ppath_step_agenda, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid, ConstTensor3View z_field, ConstMatrixView r_geoid, ConstMatrixView z_surface, 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:581
arts.h
The global header file for ARTS.
xml_io.h
This file contains basic functions to handle XML data files.
m_general.h
Template functions for general supergeneric ws methods.