ARTS  2.2.66
m_disort.cc
Go to the documentation of this file.
1 /* Copyright (C) 2006-2012 Claudia Emde <claudia.emde@dlr.de>
2 
3  This program is free software; you can redistribute it and/or modify it
4  under the terms of the GNU General Public License as published by the
5  Free Software Foundation; either version 2, or (at your option) any
6  later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  USA.
17 */
18 
32 /*===========================================================================
33  === External declarations
34  ===========================================================================*/
35 
36 #include <stdexcept>
37 #include <iostream>
38 #include <cstdlib>
39 #include <cstring>
40 #include <cmath>
41 #include "arts.h"
42 #include "array.h"
43 #include "auto_md.h"
44 #include "messages.h"
45 #include "xml_io.h"
46 #include "m_general.h"
47 #include "wsv_aux.h"
48 //#include "disort.h"
49 //#include "physics_funcs.h"
50 //#include "disort_DISORT.h"
51 
52 extern const Numeric PI;
53 extern const Numeric RAD2DEG;
54 extern const Numeric SPEED_OF_LIGHT;
55 extern const Numeric COSMIC_BG_TEMP;
56 
57 
58 
59 /*
60 // * Workspace method: Doxygen documentation will be auto-generated * //
61 #ifdef ENABLE_DISORT
62 void ScatteringDisort(Workspace& ws,
63  // WS Output:
64  Tensor7& scat_i_p,
65  Tensor7& scat_i_lat,
66  Tensor7& scat_i_lon,
67  Index& f_index,
68  ArrayOfSingleScatteringData& scat_data_array_mono,
69  Tensor4& doit_i_field1D_spectrum,
70  // WS Input
71  const Index& atmfields_checked,
72  const Index& atmgeom_checked,
73  const Index& cloudbox_checked,
74  const ArrayOfIndex& cloudbox_limits,
75  const Index& stokes_dim,
76  const Agenda& opt_prop_part_agenda,
77  const Agenda& abs_scalar_gas_agenda,
78  const Agenda& spt_calc_agenda,
79  const Tensor4& pnd_field,
80  const Tensor3& t_field,
81  const Tensor3& z_field,
82  const Vector& p_grid,
83  const Tensor4& vmr_field,
84  const ArrayOfSingleScatteringData& scat_data_array,
85  const Vector& f_grid,
86  const Vector& scat_za_grid,
87  const Matrix& surface_emissivity_field,
88  const Verbosity& verbosity)
89 {
90  CREATE_OUT1;
91 
92  if( atmfields_checked != 1 )
93  throw runtime_error( "The atmospheric fields must be flagged to have "
94  "passed a consistency check (atmfields_checked=1)." );
95  if( atmgeom_checked != 1 )
96  throw runtime_error( "The atmospheric geometry must be flagged to have "
97  "passed a consistency check (atmgeom_checked=1)." );
98  if( cloudbox_checked != 1 )
99  throw runtime_error( "The cloudbox must be flagged to have "
100  "passed a consistency check (cloudbox_checked=1)." );
101 
102  out1<< "Start DISORT calculation...\n";
103 
104  if(pnd_field.ncols() != 1)
105  throw runtime_error(
106  "*pnd_field* is not 1D! \n"
107  "DISORT can only be used for 1D! \n" );
108 
109  if (stokes_dim != 1)
110  throw runtime_error( "DISORT can only be used for unpolarized \n"
111  "calculations (i.e., stokes_dim=1),\n" );
112 
113  // NOTE: It is at the moment not possible to combine particle types
114  // being stored on different scattering angle grids.
115  // Ask whether this is required. Temperature dependance also not yet
116  // implemented.
117 
118  // DISORT calculations are done over the whole atmosphere because it is
119  // only possible to give a constant value, i.e. cosmic background,
120  // as input, not a radiation field at the to of the domain
121  Index nlyr=pnd_field.npages()-1;
122 
123  // Check whether cloudbox expands over the whole atmosphere
124 
125  if(cloudbox_limits.nelem()!=2 || cloudbox_limits[0] != 0 ||
126  cloudbox_limits[1] != pnd_field.npages()-1)
127  throw runtime_error("The cloudbox is not set correctly for DISORT.\n"
128  "Please use *cloudboxSetFullAtm*. \n");
129 
130  scat_i_p.resize(f_grid.nelem(), 2, 1, 1,
131  scat_za_grid.nelem(), 1, 1);
132 
133  scat_i_p = 0.;
134 
135  doit_i_field1D_spectrum.resize(f_grid.nelem(), pnd_field.npages(),
136  scat_za_grid.nelem(), 1);
137 
138  doit_i_field1D_spectrum= 0;
139  // Scat_i_lat, lon ---> only dummies, not used further
140  scat_i_lat.resize(1,1,1,1,1,1,1);
141  scat_i_lat = 0.;
142  scat_i_lon.resize(1,1,1,1,1,1,1);
143  scat_i_lon = 0.;
144 
145  // Input variables for DISORT
146  // Optical depth of layers
147  Vector dtauc(nlyr, 0.);
148  // Single scattering albedo of layers
149  Vector ssalb(nlyr, 0.);
150 
151  // Phase function
152  Matrix phase_function(nlyr,scat_data_array[0].za_grid.nelem(), 0.);
153  // Scattering angle grid, assumed here that it is the same for
154  // all particle types
155  Vector scat_angle_grid(scat_data_array[0].za_grid.nelem(), 0.);
156  scat_angle_grid = scat_data_array[0].za_grid;
157 
158  // Number of streams, I think in microwave 8 is more that sufficient
159  Index nstr=8 ;
160  Index n_legendre=nstr+1;
161 
162  // Legendre polynomials of phase function
163  Matrix pmom(nlyr, n_legendre, 0.);
164 
165  // Intensities to be computed for user defined polar (zenith angles)
166  Index usrang = TRUE_;
167  Index numu = scat_za_grid.nelem();
168  Vector umu(numu);
169  // Transform to mu, starting with negative values
170  for (Index i = 0; i<numu; i++)
171  umu[i]=cos(scat_za_grid[numu-i-1]*PI/180);
172 
173  // Since we have no solar source there is no angular dependance
174  Index nphi = 1;
175  Vector phi(nphi, 0.);
176 
177  Index ibcnd=0;
178 
179  // Properties of solar beam, set to zero as they are not needed
180  Numeric fbeam =0.;
181  Numeric umu0=0.;
182  Numeric phi0=0.;
183 
184  // surface, Lambertian if set to TRUE_
185  Index lamber = TRUE_;
186  Numeric albedo = 1-surface_emissivity_field(0,0);
187  // only needed for bidirectional reflecting surface
188  Vector hl(1,0.);
189 
190  //temperature of surface and cloudbox top
191  Numeric btemp = t_field(0,0,0);
192  Numeric ttemp = t_field(cloudbox_limits[1], 0, 0);
193 
194  // Top of the atmosphere, emissivity = 0
195  Numeric temis = 0.;
196 
197  // we don't need delta-scaling in microwave region
198  Index deltam = FALSE_;
199 
200  // include thermal emission (very important)
201  Index plank = TRUE_;
202 
203  // calculate also intensities, not only fluxes
204  Index onlyfl = FALSE_;
205 
206  // Convergence criterium
207  Numeric accur = 0.005;
208 
209  // Specify what to be printed --> normally nothing
210  Index *prnt = new Index[7];
211  prnt[0]=FALSE_; // Input variables
212  prnt[1]=FALSE_; // fluxes
213  prnt[2]=FALSE_; // azimuthally averaged intensities at user
214  //and comp. angles
215  prnt[3]=FALSE_; // azimuthally averaged intensities at user levels
216  //and angles
217  prnt[4]=FALSE_; // intensities at user levels and angles
218  prnt[5]=FALSE_; // planar transmissivity and albedo
219  prnt[6]=FALSE_; // phase function moments
220 
221  char header[127];
222  memset (header, 0, 127);
223 
224  Index maxcly = nlyr; // Maximum number of layers
225  Index maxulv = nlyr+1; // Maximum number of user defined tau
226  Index maxumu = scat_za_grid.nelem(); // maximum number of zenith angles
227  Index maxcmu = n_legendre-1; // maximum number of Legendre polynomials
228  Index maxphi = 1; //no azimuthal dependance
229 
230  // Declaration of Output variables
231  Vector rfldir(maxulv);
232  Vector rfldn(maxulv);
233  Vector flup(maxulv);
234  Vector dfdt(maxulv);
235  Vector uavg(maxulv);
236  Tensor3 uu(maxphi, maxulv, scat_za_grid.nelem(), 0.); // Intensity
237  Matrix u0u(maxulv, scat_za_grid.nelem()); // Azimuthally averaged intensity
238  Vector albmed(scat_za_grid.nelem()); // Albedo of cloudbox
239  Vector trnmed(scat_za_grid.nelem()); // Transmissivity
240 
241  Vector t(nlyr+1);
242 
243  for (Index i = 0; i < t.nelem(); i++)
244  {
245  t[i] = t_field(cloudbox_limits[1]-i,0,0);
246  }
247 
248  //dummies
249  Index ntau = 0;
250  Vector utau(maxulv,0.);
251 
252  // Loop over frequencies
253  for (f_index = 0; f_index < f_grid.nelem(); f_index ++)
254  {
255  dtauc=0.;
256  ssalb=0.;
257  phase_function=0.;
258  pmom=0.;
259 
260  scat_data_array_monoCalc(scat_data_array_mono, scat_data_array, f_grid, f_index, verbosity);
261 
262  dtauc_ssalbCalc(ws, dtauc, ssalb, opt_prop_part_agenda,
263  abs_scalar_gas_agenda, spt_calc_agenda,
264  pnd_field,
265  t_field, z_field, p_grid, vmr_field, f_grid[Range(f_index,1)]);
266  //cout << "dtauc " << dtauc << endl
267  // << "ssalb " << ssalb << endl;
268 
269  phase_functionCalc(phase_function, scat_data_array_mono, pnd_field);
270  //cout << "phase function" << phase_function(15,joker) << "\n";
271 
272  pmomCalc(pmom, phase_function, scat_angle_grid, n_legendre, verbosity);
273  //for (Index i=0; i<nlyr; i++)
274  // cout << "pmom " << pmom(i,joker) << "\n";
275 
276  // Wavenumber in [1/cm^2]
277  Numeric wvnmlo = f_grid[f_index]/(100*SPEED_OF_LIGHT);
278  Numeric wvnmhi = wvnmlo;
279 
280  // calculate radiant quantities at boundary of computational layers.
281  Index usrtau = FALSE_;
282 
283  // Cosmic background
284  Numeric fisot = planck2( f_grid[f_index], COSMIC_BG_TEMP );
285 
286  DEBUG_VAR(dtauc)
287  // Call disort
288  disort_(&nlyr, dtauc.get_c_array(),
289  ssalb.get_c_array(), pmom.get_c_array(),
290  t.get_c_array(), &wvnmlo, &wvnmhi,
291  &usrtau, &ntau, utau.get_c_array(),
292  &nstr, &usrang, &numu,
293  umu.get_c_array(), &nphi,
294  phi.get_c_array(),
295  &ibcnd, &fbeam,
296  &umu0, &phi0, &fisot,
297  &lamber,
298  &albedo, hl.get_c_array(),
299  &btemp, &ttemp, &temis,
300  &deltam,
301  &plank, &onlyfl, &accur,
302  prnt, header,
303  &maxcly, &maxulv,
304  &maxumu, &maxcmu,
305  &maxphi, rfldir.get_c_array(),
306  rfldn.get_c_array(),
307  flup.get_c_array(), dfdt.get_c_array(),
308  uavg.get_c_array(),
309  uu.get_c_array(), u0u.get_c_array(),
310  albmed.get_c_array(),
311  trnmed.get_c_array());
312 
313  cout << "intensity " << uu << endl;
314 
315 
316  for(Index j = 0; j<numu; j++)
317  {
318  for(Index k = 0; k< nlyr; k++)
319  doit_i_field1D_spectrum(f_index, k+1, j, 0) =
320  uu(0,nlyr-k-1,j);
321 
322  scat_i_p(f_index, 0, 0, 0, j, 0, 0) =
323  uu(0, nlyr-1, j );
324  scat_i_p(f_index, 1, 0, 0, j, 0, 0) =
325  uu(0, 0, j);
326  }
327  }
328  delete [] prnt;
329 
330 #else
331 void ScatteringDisort(Workspace&,
332  // WS Output:
333  Tensor7&,
334  Tensor7&,
335  Tensor7&,
336  Index&,
337  ArrayOfSingleScatteringData&,
338  Tensor4&,
339  // WS Input
340  const Index&,
341  const Index&,
342  const Index&,
343  const ArrayOfIndex&,
344  const Index&,
345  const Agenda&,
346  const Agenda&,
347  const Agenda&,
348  const Tensor4&,
349  const Tensor3&,
350  const Tensor3&,
351  const Vector&,
352  const Tensor4&,
353  const ArrayOfSingleScatteringData&,
354  const Vector&,
355  const Vector&,
356  const Matrix&,
357  const Verbosity&)
358 {
359  throw runtime_error ("This version of ARTS was compiled without DISORT support.");
360 #endif // *ENABLE_DISORT*
361 }
362 */
363 
364 // No Disort support in ARTS2.2. Use ARTS2.3 or higher.
365 /* Workspace method: Doxygen documentation will be auto-generated */
367  // WS Output:
368  Tensor7&,
369  Tensor7&,
370  Tensor7&,
371  Index&,
373  Tensor4&,
374  // WS Input
375  const Index&,
376  const Index&,
377  const Index&,
378  const ArrayOfIndex&,
379  const Index&,
380  const Agenda&,
381  const Agenda&,
382  const Agenda&,
383  const Tensor4&,
384  const Tensor3&,
385  const Tensor3&,
386  const Vector&,
387  const Tensor4&,
389  const Vector&,
390  const Vector&,
391  const Matrix&,
392  const Verbosity&)
393 {
394  throw runtime_error ("No DISORT support in ARTS2.2.\n"
395  "For using DISORT, switch to ARTS2.3 or higher.");
396 }
397 
398 
399 
Matrix
The Matrix class.
Definition: matpackI.h:788
auto_md.h
Tensor3
The Tensor3 class.
Definition: matpackIII.h:348
SPEED_OF_LIGHT
const Numeric SPEED_OF_LIGHT
ScatteringDisort
void ScatteringDisort(Workspace &, Tensor7 &, Tensor7 &, Tensor7 &, Index &, ArrayOfSingleScatteringData &, Tensor4 &, const Index &, const Index &, const Index &, const ArrayOfIndex &, const Index &, const Agenda &, const Agenda &, const Agenda &, const Tensor4 &, const Tensor3 &, const Tensor3 &, const Vector &, const Tensor4 &, const ArrayOfSingleScatteringData &, const Vector &, const Vector &, const Matrix &, const Verbosity &)
WORKSPACE METHOD: ScatteringDisort.
Definition: m_disort.cc:366
Tensor4
The Tensor4 class.
Definition: matpackIV.h:383
array.h
This file contains the definition of Array.
COSMIC_BG_TEMP
const Numeric COSMIC_BG_TEMP
PI
const Numeric PI
Agenda
The Agenda class.
Definition: agenda_class.h:44
Array
This can be used to make arrays out of anything.
Definition: array.h:107
RAD2DEG
const Numeric RAD2DEG
messages.h
Declarations having to do with the four output streams.
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:29
Verbosity
Definition: messages.h:50
Workspace
Workspace class.
Definition: workspace_ng.h:47
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:35
Vector
The Vector class.
Definition: matpackI.h:556
wsv_aux.h
Auxiliary header stuff related to workspace variable groups.
Tensor7
The Tensor7 class.
Definition: matpackVII.h:1931
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.