ARTS  2.0.49
m_optproperties.cc
Go to the documentation of this file.
1 /* Copyright (C) 2002-2008
2  Sreerekha T.R. <rekha@uni-bremen.de>
3  Claudia Emde <claudia.emde@dlr.de>
4  Cory Davies <cory@met.ed.ac.uk>
5 
6  This program is free software; you can redistribute it and/or
7  modify it under the terms of the GNU General Public License as
8  published by the Free Software Foundation; either version 2 of the
9  License, or (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  USA. */
20 
35 /*===========================================================================
36  === External declarations
37  ===========================================================================*/
38 
39 #include <cmath>
40 #include "arts.h"
41 #include "exceptions.h"
42 #include "array.h"
43 #include "matpackIII.h"
44 #include "matpackVII.h"
45 #include "logic.h"
46 #include "interpolation.h"
47 #include "messages.h"
48 #include "xml_io.h"
49 #include "optproperties.h"
50 #include "math_funcs.h"
51 #include "sorting.h"
52 #include "check_input.h"
53 #include "auto_md.h"
54 
55 extern const Numeric PI;
56 extern const Numeric DEG2RAD;
57 extern const Numeric RAD2DEG;
58 
59 #define PART_TYPE scat_data_raw[i_pt].ptype
60 #define F_DATAGRID scat_data_raw[i_pt].f_grid
61 #define T_DATAGRID scat_data_raw[i_pt].T_grid
62 #define ZA_DATAGRID scat_data_raw[i_pt].za_grid
63 #define AA_DATAGRID scat_data_raw[i_pt].aa_grid
64 #define PHA_MAT_DATA_RAW scat_data_raw[i_pt].pha_mat_data //CPD: changed from pha_mat_data
65 #define EXT_MAT_DATA_RAW scat_data_raw[i_pt].ext_mat_data //which wouldn't let me play with
66 #define ABS_VEC_DATA_RAW scat_data_raw[i_pt].abs_vec_data //scat_data_mono.
67 #define PND_LIMIT 1e-12 // If particle number density is below this value,
68  // no transformations will be performed
69 
70 
71 /* Workspace method: Doxygen documentation will be auto-generated */
72 void pha_mat_sptFromData( // Output:
73  Tensor5& pha_mat_spt,
74  // Input:
75  const ArrayOfSingleScatteringData& scat_data_raw,
76  const Vector& scat_za_grid,
77  const Vector& scat_aa_grid,
78  const Index& scat_za_index, // propagation directions
79  const Index& scat_aa_index,
80  const Index& f_index,
81  const Vector& f_grid,
82  const Numeric& rte_temperature,
83  const Tensor4& pnd_field,
84  const Index& scat_p_index,
85  const Index& scat_lat_index,
86  const Index& scat_lon_index,
87  const Verbosity& verbosity
88  )
89 {
91 
92  out3 << "Calculate *pha_mat_spt* from database\n";
93 
94  const Index N_pt = scat_data_raw.nelem();
95  const Index stokes_dim = pha_mat_spt.ncols();
96 
97  if (stokes_dim > 4 || stokes_dim < 1){
98  throw runtime_error("The dimension of the stokes vector \n"
99  "must be 1,2,3 or 4");
100  }
101 
102  assert( pha_mat_spt.nshelves() == N_pt );
103 
104  // Phase matrix in laboratory coordinate system. Dimensions:
105  // [frequency, za_inc, aa_inc, stokes_dim, stokes_dim]
106  Tensor5 pha_mat_data_int;
107 
108 
109  // Loop over the included particle_types
110  for (Index i_pt = 0; i_pt < N_pt; i_pt++)
111  {
112  // If the particle number density at a specific point in the atmosphere for
113  // the i_pt particle type is zero, we don't need to do the transfromation!
114  if (pnd_field(i_pt, scat_p_index, scat_lat_index, scat_lon_index) > PND_LIMIT)
115  {
116 
117  // First we have to transform the data from the coordinate system
118  // used in the database (depending on the kind of particle type
119  // specified by *ptype*) to the laboratory coordinate sytem.
120 
121  // Frequency interpolation:
122 
123  // The data is interpolated on one frequency.
124  pha_mat_data_int.resize(PHA_MAT_DATA_RAW.nshelves(), PHA_MAT_DATA_RAW.nbooks(),
125  PHA_MAT_DATA_RAW.npages(), PHA_MAT_DATA_RAW.nrows(),
126  PHA_MAT_DATA_RAW.ncols());
127 
128 
129  // Gridpositions:
130  GridPos freq_gp;
131  gridpos(freq_gp, F_DATAGRID, f_grid[f_index]);
132 
133  GridPos t_gp;
134  gridpos(t_gp, T_DATAGRID, rte_temperature);
135 
136  // Interpolationweights:
137  Vector itw(4);
138  interpweights(itw, freq_gp, t_gp);
139 
140  for (Index i_za_sca = 0; i_za_sca < PHA_MAT_DATA_RAW.nshelves() ; i_za_sca++)
141  {
142  for (Index i_aa_sca = 0; i_aa_sca < PHA_MAT_DATA_RAW.nbooks(); i_aa_sca++)
143  {
144  for (Index i_za_inc = 0; i_za_inc < PHA_MAT_DATA_RAW.npages();
145  i_za_inc++)
146  {
147  for (Index i_aa_inc = 0; i_aa_inc < PHA_MAT_DATA_RAW.nrows();
148  i_aa_inc++)
149  {
150  for (Index i = 0; i < PHA_MAT_DATA_RAW.ncols(); i++)
151  {
152  pha_mat_data_int(i_za_sca,
153  i_aa_sca, i_za_inc,
154  i_aa_inc, i) =
155  interp(itw,
156  PHA_MAT_DATA_RAW(joker, joker, i_za_sca,
157  i_aa_sca, i_za_inc,
158  i_aa_inc, i),
159  freq_gp, t_gp);
160  }
161  }
162  }
163  }
164  }
165 
166  // Do the transformation into the laboratory coordinate system.
167  for (Index za_inc_idx = 0; za_inc_idx < scat_za_grid.nelem();
168  za_inc_idx ++)
169  {
170  for (Index aa_inc_idx = 0; aa_inc_idx < scat_aa_grid.nelem();
171  aa_inc_idx ++)
172  {
173  pha_matTransform(pha_mat_spt
174  (i_pt, za_inc_idx, aa_inc_idx, joker, joker),
175  pha_mat_data_int,
177  PART_TYPE, scat_za_index, scat_aa_index,
178  za_inc_idx,
179  aa_inc_idx, scat_za_grid, scat_aa_grid,
180  verbosity);
181  }
182  }
183  }
184  }
185 }
186 
187 
188 /* Workspace method: Doxygen documentation will be auto-generated */
190  Tensor5& pha_mat_spt,
191  // Input:
192  const ArrayOfTensor7& pha_mat_sptDOITOpt,
193  const ArrayOfSingleScatteringData& scat_data_mono,
194  const Index& doit_za_grid_size,
195  const Vector& scat_aa_grid,
196  const Index& scat_za_index, // propagation directions
197  const Index& scat_aa_index,
198  const Numeric& rte_temperature,
199  const Tensor4& pnd_field,
200  const Index& scat_p_index,
201  const Index& scat_lat_index,
202  const Index& scat_lon_index,
203  const Verbosity&)
204 {
205  // atmosphere_dim = 3
206  if (pnd_field.ncols() > 1)
207  {
208  assert(pha_mat_sptDOITOpt.nelem() == scat_data_mono.nelem());
209  // I assume that if the size is o.k. for one particle type is will
210  // also be o.k. for more particle types.
211  assert(pha_mat_sptDOITOpt[0].nlibraries() == scat_data_mono[0].T_grid.nelem());
212  assert(pha_mat_sptDOITOpt[0].nvitrines() == doit_za_grid_size);
213  assert(pha_mat_sptDOITOpt[0].nshelves() == scat_aa_grid.nelem() );
214  assert(pha_mat_sptDOITOpt[0].nbooks() == doit_za_grid_size);
215  assert(pha_mat_sptDOITOpt[0].npages() == scat_aa_grid.nelem());
216  }
217 
218  // atmosphere_dim = 1, only zenith angle required for scattered directions.
219  else if ( pnd_field.ncols() == 1 )
220  {
221  //assert(is_size(scat_theta, doit_za_grid_size, 1,
222  // doit_za_grid_size, scat_aa_grid.nelem()));
223 
224  assert(pha_mat_sptDOITOpt.nelem() == scat_data_mono.nelem());
225  // I assume that if the size is o.k. for one particle type is will
226  // also be o.k. for more particle types.
227  assert(pha_mat_sptDOITOpt[0].nlibraries() == scat_data_mono[0].T_grid.nelem());
228  assert(pha_mat_sptDOITOpt[0].nvitrines() == doit_za_grid_size);
229  assert(pha_mat_sptDOITOpt[0].nshelves() == 1);
230  assert(pha_mat_sptDOITOpt[0].nbooks() == doit_za_grid_size);
231  assert(pha_mat_sptDOITOpt[0].npages() == scat_aa_grid.nelem());
232  }
233 
234  assert(doit_za_grid_size > 0);
235 
236  // Create equidistant zenith angle grid
237  Vector za_grid;
238  nlinspace(za_grid, 0, 180, doit_za_grid_size);
239 
240  const Index N_pt = scat_data_mono.nelem();
241  const Index stokes_dim = pha_mat_spt.ncols();
242 
243  if (stokes_dim > 4 || stokes_dim < 1){
244  throw runtime_error("The dimension of the stokes vector \n"
245  "must be 1,2,3 or 4");
246  }
247 
248  assert( pha_mat_spt.nshelves() == N_pt );
249 
250  GridPos T_gp;
251  Vector itw(2);
252 
253  // Initialisation
254  pha_mat_spt = 0.;
255 
256  // Do the transformation into the laboratory coordinate system.
257  for (Index i_pt = 0; i_pt < N_pt; i_pt ++)
258  {
259  // If the particle number density at a specific point in the atmosphere
260  // for the i_pt particle type is zero, we don't need to do the
261  // transfromation!
262  if (pnd_field(i_pt, scat_p_index, scat_lat_index, scat_lon_index) > PND_LIMIT) //TRS
263  {
264  if( scat_data_mono[i_pt].T_grid.nelem() > 1)
265  {
266  ostringstream os;
267  os << "The temperature grid of the scattering data does not cover the \n"
268  "atmospheric temperature at cloud location. The data should \n"
269  "include the value T="<< rte_temperature << " K. \n";
270  chk_interpolation_grids(os.str(), scat_data_mono[i_pt].T_grid, rte_temperature);
271 
272  // Gridpositions:
273  gridpos(T_gp, scat_data_mono[i_pt].T_grid, rte_temperature);
274  // Interpolationweights:
275  interpweights(itw, T_gp);
276  }
277 
278 
279 
280  for (Index za_inc_idx = 0; za_inc_idx < doit_za_grid_size;
281  za_inc_idx ++)
282  {
283  for (Index aa_inc_idx = 0; aa_inc_idx < scat_aa_grid.nelem();
284  aa_inc_idx ++)
285  {
286  if( scat_data_mono[i_pt].T_grid.nelem() == 1)
287  {
288  pha_mat_spt(i_pt, za_inc_idx, aa_inc_idx, joker, joker) =
289  pha_mat_sptDOITOpt[i_pt](0, scat_za_index,
290  scat_aa_index, za_inc_idx,
291  aa_inc_idx, joker, joker);
292  }
293 
294  // Temperature interpolation
295  else
296  {
297  for (Index i = 0; i< stokes_dim; i++)
298  {
299  for (Index j = 0; j< stokes_dim; j++)
300  {
301  pha_mat_spt(i_pt, za_inc_idx, aa_inc_idx, i, j)=
302  interp(itw,pha_mat_sptDOITOpt[i_pt]
303  (joker, scat_za_index,
304  scat_aa_index, za_inc_idx,
305  aa_inc_idx, i, j) , T_gp);
306  }
307  }
308  }
309  }
310  }
311  }// TRS
312  }
313 }
314 
315 
316 /* Workspace method: Doxygen documentation will be auto-generated */
317 void opt_prop_sptFromData(// Output and Input:
318  Tensor3& ext_mat_spt,
319  Matrix& abs_vec_spt,
320  // Input:
321  const ArrayOfSingleScatteringData& scat_data_raw,
322  const Vector& scat_za_grid,
323  const Vector& scat_aa_grid,
324  const Index& scat_za_index, // propagation directions
325  const Index& scat_aa_index,
326  const Index& f_index,
327  const Vector& f_grid,
328  const Numeric& rte_temperature,
329  const Tensor4& pnd_field,
330  const Index& scat_p_index,
331  const Index& scat_lat_index,
332  const Index& scat_lon_index,
333  const Verbosity& verbosity)
334 {
335 
336  const Index N_pt = scat_data_raw.nelem();
337  const Index stokes_dim = ext_mat_spt.ncols();
338  const Numeric za_sca = scat_za_grid[scat_za_index];
339  const Numeric aa_sca = scat_aa_grid[scat_aa_index];
340 
341  if (stokes_dim > 4 || stokes_dim < 1){
342  throw runtime_error("The dimension of the stokes vector \n"
343  "must be 1,2,3 or 4");
344  }
345 
346  assert( ext_mat_spt.npages() == N_pt );
347  assert( abs_vec_spt.nrows() == N_pt );
348 
349  // Phase matrix in laboratory coordinate system. Dimensions:
350  // [frequency, za_inc, aa_inc, stokes_dim, stokes_dim]
351  Tensor3 ext_mat_data_int;
352  Tensor3 abs_vec_data_int;
353 
354  // Initialisation
355  ext_mat_spt = 0.;
356  abs_vec_spt = 0.;
357 
358 
359  // Loop over the included particle_types
360  for (Index i_pt = 0; i_pt < N_pt; i_pt++)
361  {
362  // If the particle number density at a specific point in the atmosphere for
363  // the i_pt particle type is zero, we don't need to do the transfromation
364 
365  if (pnd_field(i_pt, scat_p_index, scat_lat_index, scat_lon_index) > PND_LIMIT)
366  {
367  // First we have to transform the data from the coordinate system
368  // used in the database (depending on the kind of particle type
369  // specified by *ptype*) to the laboratory coordinate sytem.
370 
371  // Frequency interpolation:
372 
373  // The data is interpolated on one frequency.
374  //
375  // Resize the variables for the interpolated data:
376  //
377  ext_mat_data_int.resize(EXT_MAT_DATA_RAW.npages(),
378  EXT_MAT_DATA_RAW.nrows(),
379  EXT_MAT_DATA_RAW.ncols());
380  //
381  abs_vec_data_int.resize(ABS_VEC_DATA_RAW.npages(),
382  ABS_VEC_DATA_RAW.nrows(),
383  ABS_VEC_DATA_RAW.ncols());
384 
385 
386  // Gridpositions:
387  GridPos freq_gp;
388  gridpos(freq_gp, F_DATAGRID, f_grid[f_index]);
389  GridPos t_gp;
390  Vector itw;
391 
392  if ( T_DATAGRID.nelem() > 1)
393  {
394  ostringstream os;
395  os << "The temperature grid of the scattering data does not cover the \n"
396  "atmospheric temperature at cloud location. The data should \n"
397  "include the value T="<< rte_temperature << " K. \n";
398  chk_interpolation_grids(os.str(), T_DATAGRID, rte_temperature);
399 
400  gridpos(t_gp, T_DATAGRID, rte_temperature);
401 
402  // Interpolationweights:
403  itw.resize(4);
404  interpweights(itw, freq_gp, t_gp);
405 
406  for (Index i_za_sca = 0; i_za_sca < EXT_MAT_DATA_RAW.npages();
407  i_za_sca++)
408  {
409  for(Index i_aa_sca = 0; i_aa_sca < EXT_MAT_DATA_RAW.nrows();
410  i_aa_sca++)
411  {
412  //
413  // Interpolation of extinction matrix:
414  //
415  for (Index i = 0; i < EXT_MAT_DATA_RAW.ncols(); i++)
416  {
417  ext_mat_data_int(i_za_sca, i_aa_sca, i) =
419  i_za_sca, i_aa_sca, i),
420  freq_gp, t_gp);
421  }
422  }
423  }
424 
425  for (Index i_za_sca = 0; i_za_sca < ABS_VEC_DATA_RAW.npages();
426  i_za_sca++)
427  {
428  for(Index i_aa_sca = 0; i_aa_sca < ABS_VEC_DATA_RAW.nrows();
429  i_aa_sca++)
430  {
431  //
432  // Interpolation of absorption vector:
433  //
434  for (Index i = 0; i < ABS_VEC_DATA_RAW.ncols(); i++)
435  {
436  abs_vec_data_int(i_za_sca, i_aa_sca, i) =
437  interp(itw, ABS_VEC_DATA_RAW(joker, joker, i_za_sca,
438  i_aa_sca, i),
439  freq_gp, t_gp);
440  }
441  }
442  }
443  }
444  else
445  {
446  // Interpolationweights:
447  itw.resize(2);
448  interpweights(itw, freq_gp);
449 
450  for (Index i_za_sca = 0; i_za_sca < EXT_MAT_DATA_RAW.npages();
451  i_za_sca++)
452  {
453  for(Index i_aa_sca = 0; i_aa_sca < EXT_MAT_DATA_RAW.nrows();
454  i_aa_sca++)
455  {
456  //
457  // Interpolation of extinction matrix:
458  //
459  for (Index i = 0; i < EXT_MAT_DATA_RAW.ncols(); i++)
460  {
461  ext_mat_data_int(i_za_sca, i_aa_sca, i) =
462  interp(itw, EXT_MAT_DATA_RAW(joker, 0,
463  i_za_sca, i_aa_sca, i),
464  freq_gp);
465  }
466  }
467  }
468 
469  for (Index i_za_sca = 0; i_za_sca < ABS_VEC_DATA_RAW.npages();
470  i_za_sca++)
471  {
472  for(Index i_aa_sca = 0; i_aa_sca < ABS_VEC_DATA_RAW.nrows();
473  i_aa_sca++)
474  {
475  //
476  // Interpolation of absorption vector:
477  //
478  for (Index i = 0; i < ABS_VEC_DATA_RAW.ncols(); i++)
479  {
480  abs_vec_data_int(i_za_sca, i_aa_sca, i) =
481  interp(itw, ABS_VEC_DATA_RAW(joker, 0, i_za_sca,
482  i_aa_sca, i),
483  freq_gp);
484  }
485  }
486  }
487  }
488 
489 
490  //
491  // Do the transformation into the laboratory coordinate system.
492  //
493  // Extinction matrix:
494  //
495 
496 
497  ext_matTransform(ext_mat_spt(i_pt, joker, joker),
498  ext_mat_data_int,
500  za_sca, aa_sca,
501  verbosity);
502  //
503  // Absorption vector:
504  //
505  abs_vecTransform(abs_vec_spt(i_pt, joker),
506  abs_vec_data_int,
508  za_sca, aa_sca, verbosity);
509  }
510 
511  }
512 }
513 
514 
515 /* Workspace method: Doxygen documentation will be auto-generated */
516 void ext_matAddPart(Tensor3& ext_mat,
517  const Tensor3& ext_mat_spt,
518  const Tensor4& pnd_field,
519  const Index& atmosphere_dim,
520  const Index& scat_p_index,
521  const Index& scat_lat_index,
522  const Index& scat_lon_index,
523  const Verbosity&)
524 
525 {
526  Index N_pt = ext_mat_spt.npages();
527  Index stokes_dim = ext_mat_spt.nrows();
528 
529  Matrix ext_mat_part(stokes_dim, stokes_dim, 0.0);
530 
531 
532  if (stokes_dim > 4 || stokes_dim < 1){
533  throw runtime_error(
534  "The dimension of stokes vector can be "
535  "only 1,2,3, or 4");
536  }
537  if ( ext_mat_spt.ncols() != stokes_dim){
538 
539  throw runtime_error(" The columns of ext_mat_spt should "
540  "agree to stokes_dim");
541  }
542 
543  if (atmosphere_dim == 1)
544  {
545  // this is a loop over the different particle types
546  for (Index l = 0; l < N_pt; l++)
547  {
548 
549  // now the last two loops over the stokes dimension.
550  for (Index m = 0; m < stokes_dim; m++)
551  {
552  for (Index n = 0; n < stokes_dim; n++)
553  //summation of the product of pnd_field and
554  //ext_mat_spt.
555  ext_mat_part(m, n) +=
556  (ext_mat_spt(l, m, n) * pnd_field(l, scat_p_index, 0, 0));
557  }
558  }
559 
560  //Add particle extinction matrix to *ext_mat*.
561  ext_mat(0, Range(joker), Range(joker)) += ext_mat_part;
562  }
563 
564  if (atmosphere_dim == 3)
565  {
566 
567  // this is a loop over the different particle types
568  for (Index l = 0; l < N_pt; l++)
569  {
570 
571  // now the last two loops over the stokes dimension.
572  for (Index m = 0; m < stokes_dim; m++)
573  {
574  for (Index n = 0; n < stokes_dim; n++)
575  //summation of the product of pnd_field and
576  //ext_mat_spt.
577  ext_mat_part(m, n) += (ext_mat_spt(l, m, n) *
578  pnd_field(l, scat_p_index,
579  scat_lat_index,
580  scat_lon_index));
581 
582  }
583  }
584 
585  //Add particle extinction matrix to *ext_mat*.
586  ext_mat(0, Range(joker), Range(joker)) += ext_mat_part;
587 
588  }
589 
590 }
591 
592 
593 /* Workspace method: Doxygen documentation will be auto-generated */
594 void abs_vecAddPart(Matrix& abs_vec,
595  const Matrix& abs_vec_spt,
596  const Tensor4& pnd_field,
597  const Index& atmosphere_dim,
598  const Index& scat_p_index,
599  const Index& scat_lat_index,
600  const Index& scat_lon_index,
601  const Verbosity&)
602 
603 {
604  Index N_pt = abs_vec_spt.nrows();
605  Index stokes_dim = abs_vec_spt.ncols();
606 
607  Vector abs_vec_part(stokes_dim, 0.0);
608 
609  if ((stokes_dim > 4) || (stokes_dim <1)){
610  throw runtime_error("The dimension of stokes vector "
611  "can be only 1,2,3, or 4");
612  }
613 
614  if (atmosphere_dim == 1)
615  {
616  // this is a loop over the different particle types
617  for (Index l = 0; l < N_pt ; ++l)
618  {
619  // now the loop over the stokes dimension.
620  //(CE:) in the middle was l instead of m
621  for (Index m = 0; m < stokes_dim; ++m)
622  //summation of the product of pnd_field and
623  //abs_vec_spt.
624  abs_vec_part[m] +=
625  (abs_vec_spt(l, m) * pnd_field(l, scat_p_index, 0, 0));
626 
627  }
628  //Add the particle absorption
629  abs_vec(0, Range(joker)) += abs_vec_part;
630  }
631 
632  if (atmosphere_dim == 3)
633  {
634  // this is a loop over the different particle types
635  for (Index l = 0; l < N_pt ; ++l)
636  {
637 
638  // now the loop over the stokes dimension.
639  for (Index m = 0; m < stokes_dim; ++m)
640  //summation of the product of pnd_field and
641  //abs_vec_spt.
642  abs_vec_part[m] += (abs_vec_spt(l, m) *
643  pnd_field(l, scat_p_index,
644  scat_lat_index,
645  scat_lon_index));
646 
647  }
648  //Add the particle absorption
649  abs_vec(0,Range(joker)) += abs_vec_part;
650  }
651 }
652 
653 
654 /* Workspace method: Doxygen documentation will be auto-generated */
655 void ext_matInit(Tensor3& ext_mat,
656  const Vector& f_grid,
657  const Index& stokes_dim,
658  const Index& f_index,
659  const Verbosity& verbosity)
660 {
662 
663  Index freq_dim;
664 
665  if( f_index < 0 )
666  freq_dim = f_grid.nelem();
667  else
668  freq_dim = 1;
669 
670  ext_mat.resize( freq_dim,
671  stokes_dim,
672  stokes_dim );
673  ext_mat = 0; // Initialize to zero!
674 
675  out2 << "Set dimensions of ext_mat as ["
676  << freq_dim << ","
677  << stokes_dim << ","
678  << stokes_dim << "] and initialized to 0.\n";
679 }
680 
681 
682 /* Workspace method: Doxygen documentation will be auto-generated */
683 void ext_matAddGas(Tensor3& ext_mat,
684  const Matrix& abs_scalar_gas,
685  const Verbosity&)
686 {
687  // Number of Stokes parameters:
688  const Index stokes_dim = ext_mat.ncols();
689 
690  // The second dimension of ext_mat must also match the number of
691  // Stokes parameters:
692  if ( stokes_dim != ext_mat.nrows() )
693  throw runtime_error("Row dimension of ext_mat inconsistent with "
694  "column dimension.");
695 
696  // Number of frequencies:
697  const Index f_dim = ext_mat.npages();
698 
699  // This must be consistent with the first dimension of
700  // abs_scalar_gas. Check this:
701  if ( f_dim != abs_scalar_gas.nrows() )
702  throw runtime_error("Frequency dimension of ext_mat and abs_scalar_gas\n"
703  "are inconsistent in ext_matAddGas.");
704 
705  // Sum up absorption over all species.
706  // This gives us an absorption vector for all frequencies. Of course
707  // this includes the special case that there is only one frequency.
708  Vector abs_total(f_dim);
709  for ( Index i=0; i<f_dim; ++i )
710  abs_total[i] = abs_scalar_gas(i,joker).sum();
711 
712  for ( Index i=0; i<stokes_dim; ++i )
713  {
714  // Add the absorption value to all the diagonal elements:
715  ext_mat(joker,i,i) += abs_total[joker];
716 
717  // We don't have to do anything about the off-diagonal
718  // elements!
719  }
720 }
721 
722 
723 /* Workspace method: Doxygen documentation will be auto-generated */
724 void abs_vecInit(Matrix& abs_vec,
725  const Vector& f_grid,
726  const Index& stokes_dim,
727  const Index& f_index,
728  const Verbosity& verbosity)
729 {
731 
732  Index freq_dim;
733 
734  if( f_index < 0 )
735  freq_dim = f_grid.nelem();
736  else
737  freq_dim = 1;
738 
739  abs_vec.resize( freq_dim,
740  stokes_dim );
741  abs_vec = 0; // Initialize to zero!
742 
743  out2 << "Set dimensions of abs_vec as ["
744  << freq_dim << ","
745  << stokes_dim << "] and initialized to 0.\n";
746 }
747 
748 
749 /* Workspace method: Doxygen documentation will be auto-generated */
750 void abs_vecAddGas(Matrix& abs_vec,
751  const Matrix& abs_scalar_gas,
752  const Verbosity&)
753 {
754  // Number of frequencies:
755  const Index f_dim = abs_vec.nrows();
756 
757  // This must be consistent with the first dimension of
758  // abs_scalar_gas. Check this:
759  if ( f_dim != abs_scalar_gas.nrows() )
760  throw runtime_error("Frequency dimension of abs_vec and abs_scalar_gas\n"
761  "are inconsistent in abs_vecAddGas.");
762 
763  // Loop all frequencies. Of course this includes the special case
764  // that there is only one frequency.
765  for ( Index i=0; i<f_dim; ++i )
766  {
767  // Sum up the columns of abs_scalar_gas and add to the first
768  // element of abs_vec.
769  abs_vec(i,0) += abs_scalar_gas(i,joker).sum();
770  }
771 
772  // We don't have to do anything about higher elements of abs_vec,
773  // since scalar gas absorption only influences the first element.
774 }
775 
776 
777 /* Workspace method: Doxygen documentation will be auto-generated */
778 /*
779 void ext_matAddGasZeeman( Tensor3& ext_mat,
780  const Tensor3& ext_mat_zee,
781  const Verbosity&)
782 {
783  // Number of Stokes parameters:
784  const Index stokes_dim = ext_mat.ncols();
785 
786  // The second dimension of ext_mat must also match the number of
787  // Stokes parameters:
788  if ( stokes_dim != ext_mat.nrows() )
789  throw runtime_error("Row dimension of ext_mat inconsistent with "
790  "column dimension.");
791 
792  for ( Index i=0; i<stokes_dim; ++i )
793  {
794  for ( Index j=0; j<stokes_dim; ++j )
795  {
796  // Add the zeeman extinction to extinction matrix.
797  ext_mat(joker,i,j) += ext_mat_zee(joker, i, j);
798  }
799 
800  }
801 }
802 */
803 
804 
805 /* Workspace method: Doxygen documentation will be auto-generated */
806 /*
807 void abs_vecAddGasZeeman( Matrix& abs_vec,
808  const Matrix& abs_vec_zee,
809  const Verbosity&)
810 {
811  // Number of Stokes parameters:
812  const Index stokes_dim = abs_vec_zee.ncols();
813  // that there is only one frequency.
814  for ( Index j=0; j<stokes_dim; ++j )
815  {
816  abs_vec(joker,j) += abs_vec_zee(joker,j);
817  }
818 }
819 */
820 
821 
822 /* Workspace method: Doxygen documentation will be auto-generated */
823 void pha_matCalc(Tensor4& pha_mat,
824  const Tensor5& pha_mat_spt,
825  const Tensor4& pnd_field,
826  const Index& atmosphere_dim,
827  const Index& scat_p_index,
828  const Index& scat_lat_index,
829  const Index& scat_lon_index,
830  const Verbosity&)
831 {
832 
833  Index N_pt = pha_mat_spt.nshelves();
834  Index Nza = pha_mat_spt.nbooks();
835  Index Naa = pha_mat_spt.npages();
836  Index stokes_dim = pha_mat_spt.nrows();
837 
838  pha_mat.resize(Nza, Naa, stokes_dim, stokes_dim);
839 
840  // Initialisation
841  pha_mat = 0.0;
842 
843  if (atmosphere_dim == 1)
844  {
845  // this is a loop over the different particle types
846  for (Index pt_index = 0; pt_index < N_pt; ++ pt_index)
847  {
848  // these are loops over zenith angle and azimuth angle
849  for (Index za_index = 0; za_index < Nza; ++ za_index)
850  {
851  for (Index aa_index = 0; aa_index < Naa; ++ aa_index)
852  {
853 
854  // now the last two loops over the stokes dimension.
855  for (Index stokes_index_1 = 0; stokes_index_1 < stokes_dim;
856  ++ stokes_index_1)
857  {
858  for (Index stokes_index_2 = 0; stokes_index_2 < stokes_dim;
859  ++ stokes_index_2)
860  //summation of the product of pnd_field and
861  //pha_mat_spt.
862  pha_mat(za_index, aa_index,
863  stokes_index_1, stokes_index_2) +=
864 
865  (pha_mat_spt(pt_index, za_index, aa_index,
866  stokes_index_1, stokes_index_2) *
867  pnd_field(pt_index,scat_p_index, 0, 0));
868  }
869  }
870  }
871  }
872  }
873 
874  if (atmosphere_dim == 3)
875  {
876  // this is a loop over the different particle types
877  for (Index pt_index = 0; pt_index < N_pt; ++ pt_index)
878  {
879 
880  // these are loops over zenith angle and azimuth angle
881  for (Index za_index = 0; za_index < Nza; ++ za_index)
882  {
883  for (Index aa_index = 0; aa_index < Naa; ++ aa_index)
884  {
885 
886  // now the last two loops over the stokes dimension.
887  for (Index i = 0; i < stokes_dim; ++ i)
888  {
889  for (Index j = 0; j < stokes_dim; ++ j)
890  {
891  //summation of the product of pnd_field and
892  //pha_mat_spt.
893  pha_mat(za_index, aa_index, i,j ) +=
894  (pha_mat_spt(pt_index, za_index, aa_index, i, j) *
895  pnd_field(pt_index, scat_p_index,
896  scat_lat_index, scat_lon_index));
897 
898 
899  }
900  }
901  }
902  }
903  }
904  }
905 }
906 
907 
908 
909 /* Workspace method: Doxygen documentation will be auto-generated */
910 void scat_data_rawCheck(//Input:
911  const ArrayOfSingleScatteringData& scat_data_raw,
912  const Verbosity& verbosity)
913 {
915 
916  xml_write_to_file("SingleScatteringData", scat_data_raw, FILE_TYPE_ASCII,
917  verbosity);
918 
919  const Index N_pt = scat_data_raw.nelem();
920 
921  // Loop over the included particle_types
922  for (Index i_pt = 0; i_pt < N_pt; i_pt++)
923  {
925  (PHA_MAT_DATA_RAW(0, 0, joker, 0, 0, 0, 0), ZA_DATAGRID);
926 
927  Numeric Cext = EXT_MAT_DATA_RAW(0,0,0,0,0);
928 
929  Numeric Cabs = Cext - Csca;
930 
931  Numeric Cabs_data = ABS_VEC_DATA_RAW(0,0,0,0,0);
932 
933  Numeric Csca_data = Cext - Cabs_data;
934 
935  out1 << " Coefficients in database: \n"
936  << "Cext: " << Cext << " Cabs: " << Cabs_data << " Csca: " << Csca_data
937  << " \n Calculated absorption cooefficient: \n"
938  << "Cabs calculated: " << Cabs
939  << " Csca: " << Csca << "\n";
940 
941  }
942 }
943 
944 
945 /* Workspace method: Doxygen documentation will be auto-generated */
947  ArrayOfTensor7& pha_mat_sptDOITOpt,
948  ArrayOfSingleScatteringData& scat_data_mono,
949  //Input:
950  const Index& doit_za_grid_size,
951  const Vector& scat_aa_grid,
953  scat_data_raw,
954  const Vector& f_grid,
955  const Index& f_index,
956  const Index& atmosphere_dim,
957  const Index& stokes_dim,
958  const Verbosity& verbosity)
959 {
960 
961  // Interpolate all the data in frequency
962  scat_data_monoCalc(scat_data_mono, scat_data_raw, f_grid, f_index, verbosity);
963 
964  // For 1D calculation the scat_aa dimension is not required:
965  Index N_aa_sca;
966  if(atmosphere_dim == 1)
967  N_aa_sca = 1;
968  else
969  N_aa_sca = scat_aa_grid.nelem();
970 
971  Vector za_grid;
972  nlinspace(za_grid, 0, 180, doit_za_grid_size);
973 
974  assert( scat_data_raw.nelem() == scat_data_mono.nelem() );
975 
976  Index N_pt = scat_data_raw.nelem();
977 
978  pha_mat_sptDOITOpt.resize(N_pt);
979 
980  for (Index i_pt = 0; i_pt < N_pt; i_pt++)
981  {
982  Index N_T = scat_data_mono[i_pt].T_grid.nelem();
983  pha_mat_sptDOITOpt[i_pt].resize(N_T, doit_za_grid_size, N_aa_sca,
984  doit_za_grid_size, scat_aa_grid.nelem(),
985  stokes_dim, stokes_dim);
986 
987  // Initialize:
988  pha_mat_sptDOITOpt[i_pt]= 0.;
989 
990  // Calculate all scattering angles for all combinations of incoming
991  // and scattered directions and interpolation.
992  for (Index t_idx = 0; t_idx < N_T; t_idx ++)
993  {
994  // These are the scattered directions as called in *scat_field_calc*
995  for (Index za_sca_idx = 0; za_sca_idx < doit_za_grid_size; za_sca_idx ++)
996  {
997  for (Index aa_sca_idx = 0; aa_sca_idx < N_aa_sca; aa_sca_idx ++)
998  {
999  // Integration is performed over all incoming directions
1000  for (Index za_inc_idx = 0; za_inc_idx < doit_za_grid_size;
1001  za_inc_idx ++)
1002  {
1003  for (Index aa_inc_idx = 0; aa_inc_idx <
1004  scat_aa_grid.nelem();
1005  aa_inc_idx ++)
1006  {
1007  pha_matTransform(pha_mat_sptDOITOpt[i_pt]
1008  (t_idx, za_sca_idx,
1009  aa_sca_idx, za_inc_idx, aa_inc_idx,
1010  joker, joker),
1011  scat_data_mono[i_pt].
1012  pha_mat_data
1013  (0,t_idx,joker,joker,joker,
1014  joker,joker),
1015  scat_data_mono[i_pt].za_grid,
1016  scat_data_mono[i_pt].aa_grid,
1017  scat_data_mono[i_pt].ptype,
1018  za_sca_idx,
1019  aa_sca_idx,
1020  za_inc_idx,
1021  aa_inc_idx,
1022  za_grid,
1023  scat_aa_grid,
1024  verbosity);
1025  }
1026  }
1027  }
1028  }
1029  }
1030  }
1031  }
1032 
1033 
1034 /* Workspace method: Doxygen documentation will be auto-generated */
1036  const ArrayOfSingleScatteringData& scat_data_raw,
1037  const Vector& f_grid,
1038  const Index& f_index,
1039  const Verbosity&)
1040 {
1041  //Extrapolation factor:
1042  //const Numeric extpolfac = 0.5;
1043 
1044  // Check, whether single scattering data contains the right frequencies:
1045  // The check was changed to allow extrapolation at the boundaries of the
1046  // frequency grid.
1047  for (Index i = 0; i<scat_data_raw.nelem(); i++)
1048  {
1049  // check with extrapolation
1050  chk_interpolation_grids("scat_data_raw.f_grid to f_grid",
1051  scat_data_raw[i].f_grid,
1052  f_grid[f_index]);
1053 
1054  // old check without extrapolation
1055  /*if (scat_data_raw[i].f_grid[0] > f_grid[f_index] ||
1056  scat_data_raw[i].f_grid[scat_data_raw[i].f_grid.nelem()-1] < f_grid[f_index])
1057  {
1058  ostringstream os;
1059  os << "Frequency of the scattering calculation " << f_grid[f_index]
1060  << " GHz is not contained \nin the frequency grid of the " << i+1
1061  << "the single scattering data file \n(*ParticleTypeAdd*). "
1062  << "Range:" << scat_data_raw[i].f_grid[0]/1e9 <<" - "
1063  << scat_data_raw[i].f_grid[scat_data_raw[i].f_grid.nelem()-1]/1e9
1064  <<" GHz \n";
1065  throw runtime_error( os.str() );
1066  }*/
1067  }
1068 
1069  const Index N_pt = scat_data_raw.nelem();
1070 
1071  //Initialise scat_data_mono
1072  scat_data_mono.resize(N_pt);
1073 
1074  // Loop over the included particle_types
1075  for (Index i_pt = 0; i_pt < N_pt; i_pt++)
1076  {
1077  // Gridpositions:
1078  GridPos freq_gp;
1079  gridpos(freq_gp, F_DATAGRID, f_grid[f_index]);
1080 
1081  // Interpolationweights:
1082  Vector itw(2);
1083  interpweights(itw, freq_gp);
1084 
1085  //Stuff that doesn't need interpolating
1086  scat_data_mono[i_pt].ptype=PART_TYPE;
1087  scat_data_mono[i_pt].f_grid.resize(1);
1088  scat_data_mono[i_pt].f_grid=f_grid[f_index];
1089  scat_data_mono[i_pt].T_grid=scat_data_raw[i_pt].T_grid;
1090  scat_data_mono[i_pt].za_grid=ZA_DATAGRID;
1091  scat_data_mono[i_pt].aa_grid=AA_DATAGRID;
1092 
1093  //Phase matrix data
1094  scat_data_mono[i_pt].pha_mat_data.resize(1,
1095  PHA_MAT_DATA_RAW.nvitrines(),
1096  PHA_MAT_DATA_RAW.nshelves(),
1097  PHA_MAT_DATA_RAW.nbooks(),
1098  PHA_MAT_DATA_RAW.npages(),
1099  PHA_MAT_DATA_RAW.nrows(),
1100  PHA_MAT_DATA_RAW.ncols());
1101 
1102  for (Index t_index = 0; t_index < PHA_MAT_DATA_RAW.nvitrines(); t_index ++)
1103  {
1104  for (Index i_za_sca = 0; i_za_sca < PHA_MAT_DATA_RAW.nshelves();
1105  i_za_sca++)
1106  {
1107  for (Index i_aa_sca = 0; i_aa_sca < PHA_MAT_DATA_RAW.nbooks();
1108  i_aa_sca++)
1109  {
1110  for (Index i_za_inc = 0; i_za_inc <
1111  PHA_MAT_DATA_RAW.npages();
1112  i_za_inc++)
1113  {
1114  for (Index i_aa_inc = 0;
1115  i_aa_inc < PHA_MAT_DATA_RAW.nrows();
1116  i_aa_inc++)
1117  {
1118  for (Index i = 0; i < PHA_MAT_DATA_RAW.ncols(); i++)
1119  {
1120  scat_data_mono[i_pt].pha_mat_data(0, t_index,
1121  i_za_sca,
1122  i_aa_sca,
1123  i_za_inc,
1124  i_aa_inc, i) =
1125  interp(itw,
1126  PHA_MAT_DATA_RAW(joker, t_index,
1127  i_za_sca,
1128  i_aa_sca, i_za_inc,
1129  i_aa_inc, i),
1130  freq_gp);
1131  }
1132  }
1133  }
1134  }
1135  }
1136  //Extinction matrix data
1137  scat_data_mono[i_pt].ext_mat_data.resize(1, T_DATAGRID.nelem(),
1138  EXT_MAT_DATA_RAW.npages(),
1139  EXT_MAT_DATA_RAW.nrows(),
1140  EXT_MAT_DATA_RAW.ncols());
1141  for (Index i_za_sca = 0; i_za_sca < EXT_MAT_DATA_RAW.npages();
1142  i_za_sca++)
1143  {
1144  for(Index i_aa_sca = 0; i_aa_sca < EXT_MAT_DATA_RAW.nrows();
1145  i_aa_sca++)
1146  {
1147  //
1148  // Interpolation of extinction matrix:
1149  //
1150  for (Index i = 0; i < EXT_MAT_DATA_RAW.ncols(); i++)
1151  {
1152  scat_data_mono[i_pt].ext_mat_data(0, t_index,
1153  i_za_sca, i_aa_sca, i)
1154  = interp(itw, EXT_MAT_DATA_RAW(joker, t_index, i_za_sca,
1155  i_aa_sca, i),
1156  freq_gp);
1157  }
1158  }
1159  }
1160  //Absorption vector data
1161  scat_data_mono[i_pt].abs_vec_data.resize(1, T_DATAGRID.nelem(),
1162  ABS_VEC_DATA_RAW.npages(),
1163  ABS_VEC_DATA_RAW.nrows(),
1164  ABS_VEC_DATA_RAW.ncols());
1165  for (Index i_za_sca = 0; i_za_sca < ABS_VEC_DATA_RAW.npages() ;
1166  i_za_sca++)
1167  {
1168  for(Index i_aa_sca = 0; i_aa_sca < ABS_VEC_DATA_RAW.nrows();
1169  i_aa_sca++)
1170  {
1171  //
1172  // Interpolation of absorption vector:
1173  //
1174  for (Index i = 0; i < ABS_VEC_DATA_RAW.ncols(); i++)
1175  {
1176  scat_data_mono[i_pt].abs_vec_data(0, t_index, i_za_sca,
1177  i_aa_sca, i) =
1178  interp(itw, ABS_VEC_DATA_RAW(joker, t_index, i_za_sca,
1179  i_aa_sca, i),
1180  freq_gp);
1181  }
1182  }
1183  }
1184  }
1185  }
1186 }
1187 
1188 
1189 /* Workspace method: Doxygen documentation will be auto-generated */
1190 void opt_prop_sptFromMonoData(// Output and Input:
1191  Tensor3& ext_mat_spt,
1192  Matrix& abs_vec_spt,
1193  // Input:
1194  const ArrayOfSingleScatteringData& scat_data_mono,
1195  const Vector& scat_za_grid,
1196  const Vector& scat_aa_grid,
1197  const Index& scat_za_index, // propagation directions
1198  const Index& scat_aa_index,
1199  const Numeric& rte_temperature,
1200  const Tensor4& pnd_field,
1201  const Index& scat_p_index,
1202  const Index& scat_lat_index,
1203  const Index& scat_lon_index,
1204  const Verbosity& verbosity)
1205 {
1206  const Index N_pt = scat_data_mono.nelem();
1207  const Index stokes_dim = ext_mat_spt.ncols();
1208  const Numeric za_sca = scat_za_grid[scat_za_index];
1209  const Numeric aa_sca = scat_aa_grid[scat_aa_index];
1210 
1211  if (stokes_dim > 4 || stokes_dim < 1){
1212  throw runtime_error("The dimension of the stokes vector \n"
1213  "must be 1,2,3 or 4");
1214  }
1215 
1216  assert( ext_mat_spt.npages() == N_pt );
1217  assert( abs_vec_spt.nrows() == N_pt );
1218 
1219  // Initialisation
1220  ext_mat_spt = 0.;
1221  abs_vec_spt = 0.;
1222 
1223  GridPos t_gp;
1224 
1225  Vector itw(2);
1226 
1227  // Loop over the included particle_types
1228  for (Index i_pt = 0; i_pt < N_pt; i_pt++)
1229  {
1230  // If the particle number density at a specific point in the atmosphere for
1231  // the i_pt particle type is zero, we don't need to do the transfromation!
1232  if (pnd_field(i_pt, scat_p_index, scat_lat_index, scat_lon_index) > PND_LIMIT)
1233  {
1234 
1235  // First we have to transform the data from the coordinate system
1236  // used in the database (depending on the kind of particle type
1237  // specified by *ptype*) to the laboratory coordinate sytem.
1238 
1239  //
1240  // Do the transformation into the laboratory coordinate system.
1241  //
1242  // Extinction matrix:
1243  //
1244  Index ext_npages = scat_data_mono[i_pt].ext_mat_data.npages();
1245  Index ext_nrows = scat_data_mono[i_pt].ext_mat_data.nrows();
1246  Index ext_ncols = scat_data_mono[i_pt].ext_mat_data.ncols();
1247  Index abs_npages = scat_data_mono[i_pt].abs_vec_data.npages();
1248  Index abs_nrows = scat_data_mono[i_pt].abs_vec_data.nrows();
1249  Index abs_ncols = scat_data_mono[i_pt].abs_vec_data.ncols();
1250  Tensor3 ext_mat_data1temp(ext_npages,ext_nrows,ext_ncols,0.0);
1251  Tensor3 abs_vec_data1temp(abs_npages,abs_nrows,abs_ncols,0.0);
1252 
1253  //Check that scattering data temperature range covers required temperature
1254  ConstVectorView t_grid = scat_data_mono[i_pt].T_grid;
1255 
1256  if (t_grid.nelem() > 1)
1257  {
1258  // if ((rte_temperature<t_grid[0])||(rte_temperature>t_grid[t_grid.nelem()-1]))
1259  // {
1260  // throw runtime_error("rte_temperature outside scattering data temperature range");
1261  // }
1262 
1263  //interpolate over temperature
1264  gridpos(t_gp, scat_data_mono[i_pt].T_grid, rte_temperature);
1265  interpweights(itw, t_gp);
1266  for (Index i_p = 0; i_p < ext_npages ; i_p++)
1267  {
1268  for (Index i_r = 0; i_r < ext_nrows ; i_r++)
1269  {
1270  for (Index i_c = 0; i_c < ext_ncols ; i_c++)
1271  {
1272  ext_mat_data1temp(i_p,i_r,i_c)=interp(itw,
1273  scat_data_mono[i_pt].ext_mat_data(0,joker,i_p,i_r,i_c),t_gp);
1274  }
1275  }
1276  }
1277  }
1278  else
1279  {
1280  ext_mat_data1temp =
1281  scat_data_mono[i_pt].ext_mat_data(0,0,joker,joker,joker);
1282  }
1283 
1284  ext_matTransform(ext_mat_spt(i_pt, joker, joker),
1285  ext_mat_data1temp,
1286  scat_data_mono[i_pt].za_grid,
1287  scat_data_mono[i_pt].aa_grid,
1288  scat_data_mono[i_pt].ptype,
1289  za_sca, aa_sca,
1290  verbosity);
1291  //
1292  // Absorption vector:
1293  //
1294 
1295  if (t_grid.nelem() > 1)
1296  {
1297  //interpolate over temperature
1298  for (Index i_p = 0; i_p < abs_npages ; i_p++)
1299  {
1300  for (Index i_r = 0; i_r < abs_nrows ; i_r++)
1301  {
1302  for (Index i_c = 0; i_c < abs_ncols ; i_c++)
1303  {
1304  abs_vec_data1temp(i_p,i_r,i_c)=interp(itw,
1305  scat_data_mono[i_pt].abs_vec_data(0,joker,i_p,i_r,i_c),t_gp);
1306  }
1307  }
1308  }
1309  }
1310  else
1311  {
1312  abs_vec_data1temp =
1313  scat_data_mono[i_pt].abs_vec_data(0,0,joker,joker,joker);
1314  }
1315 
1316  abs_vecTransform(abs_vec_spt(i_pt, joker),
1317  abs_vec_data1temp,
1318  scat_data_mono[i_pt].za_grid,
1319  scat_data_mono[i_pt].aa_grid,
1320  scat_data_mono[i_pt].ptype,
1321  za_sca, aa_sca,
1322  verbosity);
1323  }
1324 
1325  }
1326 }
1327 
1328 
1329 /* Workspace method: Doxygen documentation will be auto-generated */
1331  Tensor5& pha_mat_spt,
1332  // Input:
1333  const ArrayOfSingleScatteringData& scat_data_mono,
1334  const Index& doit_za_grid_size,
1335  const Vector& scat_aa_grid,
1336  const Index& scat_za_index, // propagation directions
1337  const Index& scat_aa_index,
1338  const Numeric& rte_temperature,
1339  const Tensor4& pnd_field,
1340  const Index& scat_p_index,
1341  const Index& scat_lat_index,
1342  const Index& scat_lon_index,
1343  const Verbosity& verbosity)
1344 {
1345  CREATE_OUT3
1346 
1347  out3 << "Calculate *pha_mat_spt* from scat_data_mono. \n";
1348 
1349  Vector za_grid;
1350  nlinspace(za_grid, 0, 180, doit_za_grid_size);
1351 
1352  const Index N_pt = scat_data_mono.nelem();
1353  const Index stokes_dim = pha_mat_spt.ncols();
1354 
1355 
1356 
1357  if (stokes_dim > 4 || stokes_dim < 1){
1358  throw runtime_error("The dimension of the stokes vector \n"
1359  "must be 1,2,3 or 4");
1360  }
1361 
1362  assert( pha_mat_spt.nshelves() == N_pt );
1363 
1364  GridPos T_gp;
1365  Vector itw(2);
1366 
1367  // Initialisation
1368  pha_mat_spt = 0.;
1369 
1370  for (Index i_pt = 0; i_pt < N_pt; i_pt ++)
1371  {
1372  // If the particle number density at a specific point in the atmosphere
1373  // for the i_pt particle type is zero, we don't need to do the
1374  // transfromation!
1375  if (pnd_field(i_pt, scat_p_index, scat_lat_index, scat_lon_index) >
1376  PND_LIMIT)
1377  {
1378  // Temporary phase matrix wich icludes the all temperatures.
1379  Tensor3 pha_mat_spt_tmp(scat_data_mono[i_pt].T_grid.nelem(),
1380  pha_mat_spt.nrows(), pha_mat_spt.ncols());
1381 
1382  pha_mat_spt_tmp = 0.;
1383 
1384  if( scat_data_mono[i_pt].T_grid.nelem() > 1)
1385  {
1386  ostringstream os;
1387  os << "The temperature grid of the scattering data does not cover the \n"
1388  "atmospheric temperature at cloud location. The data should \n"
1389  "include the value T="<< rte_temperature << " K. \n";
1390  chk_interpolation_grids(os.str(), scat_data_mono[i_pt].T_grid, rte_temperature);
1391 
1392  // Gridpositions:
1393  gridpos(T_gp, scat_data_mono[i_pt].T_grid, rte_temperature);
1394  // Interpolationweights:
1395  interpweights(itw, T_gp);
1396  }
1397 
1398  // Do the transformation into the laboratory coordinate system.
1399  for (Index za_inc_idx = 0; za_inc_idx < doit_za_grid_size;
1400  za_inc_idx ++)
1401  {
1402  for (Index aa_inc_idx = 0; aa_inc_idx < scat_aa_grid.nelem();
1403  aa_inc_idx ++)
1404  {
1405  for (Index t_idx = 0; t_idx <
1406  scat_data_mono[i_pt].T_grid.nelem();
1407  t_idx ++)
1408  {
1409  pha_matTransform( pha_mat_spt_tmp(t_idx, joker, joker),
1410  scat_data_mono[i_pt].
1411  pha_mat_data
1412  (0,0,joker,joker,joker,
1413  joker,joker),
1414  scat_data_mono[i_pt].za_grid,
1415  scat_data_mono[i_pt].aa_grid,
1416  scat_data_mono[i_pt].ptype,
1417  scat_za_index, scat_aa_index,
1418  za_inc_idx,
1419  aa_inc_idx, za_grid, scat_aa_grid,
1420  verbosity );
1421  }
1422  // Temperature interpolation
1423  if( scat_data_mono[i_pt].T_grid.nelem() > 1)
1424  {
1425  for (Index i = 0; i< stokes_dim; i++)
1426  {
1427  for (Index j = 0; j< stokes_dim; j++)
1428  {
1429  pha_mat_spt(i_pt, za_inc_idx, aa_inc_idx, i, j)=
1430  interp(itw, pha_mat_spt_tmp(joker, i, j), T_gp);
1431  }
1432  }
1433  }
1434  else // no temperatue interpolation required
1435  {
1436  pha_mat_spt(i_pt, za_inc_idx, aa_inc_idx, joker, joker) =
1437  pha_mat_spt_tmp(0, joker, joker);
1438  }
1439  }
1440  }
1441  }
1442  }
1443 }
1444 
Matrix
The Matrix class.
Definition: matpackI.h:767
Tensor4::resize
void resize(Index b, Index p, Index r, Index c)
Resize function.
Definition: matpackIV.cc:1404
ConstTensor5View::nbooks
Index nbooks() const
Returns the number of books.
Definition: matpackV.cc:38
exceptions.h
The declarations of all the exception classes.
auto_md.h
gridpos
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
Definition: interpolation.cc:167
PHA_MAT_DATA_RAW
#define PHA_MAT_DATA_RAW
Definition: m_optproperties.cc:64
Tensor3
The Tensor3 class.
Definition: matpackIII.h:340
ConstTensor5View::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackV.cc:56
joker
const Joker joker
interpolation.h
Header file for interpolation.cc.
interp
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPos &tc)
Red 1D Interpolate.
Definition: interpolation.cc:1000
ext_matTransform
void ext_matTransform(MatrixView ext_mat_lab, ConstTensor3View ext_mat_data, ConstVectorView za_datagrid, ConstVectorView aa_datagrid, const ParticleType &ptype, const Numeric &za_sca, const Numeric &aa_sca, const Verbosity &verbosity)
Transformation of extinction matrix.
Definition: optproperties.cc:190
Vector::resize
void resize(Index n)
Resize function.
Definition: matpackI.cc:771
PART_TYPE
#define PART_TYPE
Definition: m_optproperties.cc:59
ConstMatrixView::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackI.cc:796
F_DATAGRID
#define F_DATAGRID
Definition: m_optproperties.cc:60
CREATE_OUT2
#define CREATE_OUT2
Definition: messages.h:207
abs_vecTransform
void abs_vecTransform(VectorView abs_vec_lab, ConstTensor3View abs_vec_data, ConstVectorView za_datagrid, ConstVectorView aa_datagrid, const ParticleType &ptype, const Numeric &za_sca, const Numeric &aa_sca, const Verbosity &verbosity)
Transformation of absorption vector.
Definition: optproperties.cc:85
Tensor4
The Tensor4 class.
Definition: matpackIV.h:375
array.h
This file contains the definition of Array.
DEG2RAD
const Numeric DEG2RAD
CREATE_OUT1
#define CREATE_OUT1
Definition: messages.h:206
Tensor3::resize
void resize(Index p, Index r, Index c)
Resize function.
Definition: matpackIII.cc:863
ConstTensor5View::npages
Index npages() const
Returns the number of pages.
Definition: matpackV.cc:44
ConstTensor3View::npages
Index npages() const
Returns the number of pages.
Definition: matpackIII.h:151
Array
This can be used to make arrays out of anything.
Definition: array.h:103
ZA_DATAGRID
#define ZA_DATAGRID
Definition: m_optproperties.cc:62
pha_mat_sptFromMonoData
void pha_mat_sptFromMonoData(Tensor5 &pha_mat_spt, const ArrayOfSingleScatteringData &scat_data_mono, const Index &doit_za_grid_size, const Vector &scat_aa_grid, const Index &scat_za_index, const Index &scat_aa_index, const Numeric &rte_temperature, const Tensor4 &pnd_field, const Index &scat_p_index, const Index &scat_lat_index, const Index &scat_lon_index, const Verbosity &verbosity)
WORKSPACE METHOD: pha_mat_sptFromMonoData.
Definition: m_optproperties.cc:1330
ext_matAddPart
void ext_matAddPart(Tensor3 &ext_mat, const Tensor3 &ext_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: ext_matAddPart.
Definition: m_optproperties.cc:516
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
Tensor5::resize
void resize(Index s, Index b, Index p, Index r, Index c)
Resize function.
Definition: matpackV.cc:2435
DoitScatteringDataPrepare
void DoitScatteringDataPrepare(ArrayOfTensor7 &pha_mat_sptDOITOpt, ArrayOfSingleScatteringData &scat_data_mono, const Index &doit_za_grid_size, const Vector &scat_aa_grid, const ArrayOfSingleScatteringData &scat_data_raw, const Vector &f_grid, const Index &f_index, const Index &atmosphere_dim, const Index &stokes_dim, const Verbosity &verbosity)
WORKSPACE METHOD: DoitScatteringDataPrepare.
Definition: m_optproperties.cc:946
pha_matTransform
void pha_matTransform(MatrixView pha_mat_lab, ConstTensor5View pha_mat_data, ConstVectorView za_datagrid, ConstVectorView aa_datagrid, const ParticleType &ptype, const Index &za_sca_idx, const Index &aa_sca_idx, const Index &za_inc_idx, const Index &aa_inc_idx, ConstVectorView scat_za_grid, ConstVectorView scat_aa_grid, const Verbosity &verbosity)
Transformation of phase matrix.
Definition: optproperties.cc:345
messages.h
Declarations having to do with the four output streams.
ConstMatrixView::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackI.cc:802
pha_mat_sptFromData
void pha_mat_sptFromData(Tensor5 &pha_mat_spt, const ArrayOfSingleScatteringData &scat_data_raw, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Index &scat_za_index, const Index &scat_aa_index, const Index &f_index, const Vector &f_grid, const Numeric &rte_temperature, const Tensor4 &pnd_field, const Index &scat_p_index, const Index &scat_lat_index, const Index &scat_lon_index, const Verbosity &verbosity)
WORKSPACE METHOD: pha_mat_sptFromData.
Definition: m_optproperties.cc:72
abs_vecInit
void abs_vecInit(Matrix &abs_vec, const Vector &f_grid, const Index &stokes_dim, const Index &f_index, const Verbosity &verbosity)
WORKSPACE METHOD: abs_vecInit.
Definition: m_optproperties.cc:724
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:175
abs_vecAddPart
void abs_vecAddPart(Matrix &abs_vec, const Matrix &abs_vec_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: abs_vecAddPart.
Definition: m_optproperties.cc:594
ConstTensor4View::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackIV.cc:78
optproperties.h
Scattering database structure and functions.
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
Verbosity
Definition: messages.h:50
matpackIII.h
math_funcs.h
abs_vecAddGas
void abs_vecAddGas(Matrix &abs_vec, const Matrix &abs_scalar_gas, const Verbosity &)
WORKSPACE METHOD: abs_vecAddGas.
Definition: m_optproperties.cc:750
pha_mat_sptFromDataDOITOpt
void pha_mat_sptFromDataDOITOpt(Tensor5 &pha_mat_spt, const ArrayOfTensor7 &pha_mat_sptDOITOpt, const ArrayOfSingleScatteringData &scat_data_mono, const Index &doit_za_grid_size, const Vector &scat_aa_grid, const Index &scat_za_index, const Index &scat_aa_index, const Numeric &rte_temperature, const Tensor4 &pnd_field, const Index &scat_p_index, const Index &scat_lat_index, const Index &scat_lon_index, const Verbosity &)
WORKSPACE METHOD: pha_mat_sptFromDataDOITOpt.
Definition: m_optproperties.cc:189
RAD2DEG
const Numeric RAD2DEG
Matrix::resize
void resize(Index r, Index c)
Resize function.
Definition: matpackI.cc:1549
AngIntegrate_trapezoid
Numeric AngIntegrate_trapezoid(ConstMatrixView Integrand, ConstVectorView za_grid, ConstVectorView aa_grid)
AngIntegrate_trapezoid.
Definition: math_funcs.cc:327
scat_data_monoCalc
void scat_data_monoCalc(ArrayOfSingleScatteringData &scat_data_mono, const ArrayOfSingleScatteringData &scat_data_raw, const Vector &f_grid, const Index &f_index, const Verbosity &)
WORKSPACE METHOD: scat_data_monoCalc.
Definition: m_optproperties.cc:1035
ConstTensor3View::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackIII.h:154
nlinspace
void nlinspace(Vector &x, const Numeric start, const Numeric stop, const Index n)
nlinspace
Definition: math_funcs.cc:261
Tensor5
The Tensor5 class.
Definition: matpackV.h:443
ext_matInit
void ext_matInit(Tensor3 &ext_mat, const Vector &f_grid, const Index &stokes_dim, const Index &f_index, const Verbosity &verbosity)
WORKSPACE METHOD: ext_matInit.
Definition: m_optproperties.cc:655
Range
The range class.
Definition: matpackI.h:148
GridPos
Structure to store a grid position.
Definition: interpolation.h:74
ConstTensor5View::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackV.cc:50
logic.h
Header file for logic.cc.
ConstTensor5View::nshelves
Index nshelves() const
Returns the number of shelves.
Definition: matpackV.cc:32
ConstTensor3View::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackIII.h:157
PI
const Numeric PI
EXT_MAT_DATA_RAW
#define EXT_MAT_DATA_RAW
Definition: m_optproperties.cc:65
AA_DATAGRID
#define AA_DATAGRID
Definition: m_optproperties.cc:63
FILE_TYPE_ASCII
@ FILE_TYPE_ASCII
Definition: xml_io.h:39
ABS_VEC_DATA_RAW
#define ABS_VEC_DATA_RAW
Definition: m_optproperties.cc:66
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
PND_LIMIT
#define PND_LIMIT
Definition: m_optproperties.cc:67
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
ext_matAddGas
void ext_matAddGas(Tensor3 &ext_mat, const Matrix &abs_scalar_gas, const Verbosity &)
WORKSPACE METHOD: ext_matAddGas.
Definition: m_optproperties.cc:683
check_input.h
Vector
The Vector class.
Definition: matpackI.h:555
T_DATAGRID
#define T_DATAGRID
Definition: m_optproperties.cc:61
scat_data_rawCheck
void scat_data_rawCheck(const ArrayOfSingleScatteringData &scat_data_raw, const Verbosity &verbosity)
WORKSPACE METHOD: scat_data_rawCheck.
Definition: m_optproperties.cc:910
ConstVectorView
A constant view of a Vector.
Definition: matpackI.h:300
opt_prop_sptFromMonoData
void opt_prop_sptFromMonoData(Tensor3 &ext_mat_spt, Matrix &abs_vec_spt, const ArrayOfSingleScatteringData &scat_data_mono, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Index &scat_za_index, const Index &scat_aa_index, const Numeric &rte_temperature, const Tensor4 &pnd_field, const Index &scat_p_index, const Index &scat_lat_index, const Index &scat_lon_index, const Verbosity &verbosity)
WORKSPACE METHOD: opt_prop_sptFromMonoData.
Definition: m_optproperties.cc:1190
sorting.h
Contains sorting routines.
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:172
interpweights
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
Definition: interpolation.cc:756
matpackVII.h
opt_prop_sptFromData
void opt_prop_sptFromData(Tensor3 &ext_mat_spt, Matrix &abs_vec_spt, const ArrayOfSingleScatteringData &scat_data_raw, const Vector &scat_za_grid, const Vector &scat_aa_grid, const Index &scat_za_index, const Index &scat_aa_index, const Index &f_index, const Vector &f_grid, const Numeric &rte_temperature, const Tensor4 &pnd_field, const Index &scat_p_index, const Index &scat_lat_index, const Index &scat_lon_index, const Verbosity &verbosity)
WORKSPACE METHOD: opt_prop_sptFromData.
Definition: m_optproperties.cc:317
arts.h
The global header file for ARTS.
chk_interpolation_grids
void chk_interpolation_grids(const String &which_interpolation, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac)
Check interpolation grids.
Definition: check_input.cc:390
xml_io.h
This file contains basic functions to handle XML data files.