ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_PhysProp.H
Go to the documentation of this file.
1 
2 // Properties of aerosols that are used by radiation and other parameterizations.
3 
4 #ifndef ERF_PHYS_PROP_H_
5 #define ERF_PHYS_PROP_H_
6 
7 #include "YAKL_netcdf.h"
8 #include "rrtmgp_const.h"
9 #include "ERF_Rad_constants.H"
10 #include <complex>
11 #include <cstring>
12 #include <fstream>
13 
14 using yakl::fortran::parallel_for;
15 using yakl::fortran::SimpleBounds;
16 
17 class PhysProp {
18  public:
19  // Data from one input dataset is stored in a structure of type(physprop_type).
20  struct physprop_t {
21  std::string sourcefile; // Absolute pathname of data file.
22  std::string opticsmethod; // one of {hygro, nonhygro}
23 
24  // for hygroscopic species of externally mixed aerosols
25  real2d sw_hygro_ext;
26  real2d sw_hygro_ssa;
27  real2d sw_hygro_asm;
28  real2d lw_hygro_abs;
29 
30  // for nonhygroscopic species of externally mixed aerosols
36  real1d lw_abs;
37 
38  // complex refractive index
43 
44  // for radius-dependent mass-specific quantities
45  real2d r_sw_ext;
46  real2d r_sw_scat;
47  real2d r_sw_ascat;
48  real2d r_lw_abs;
49  real1d mu;
50 
51  // for modal optics
52  real4d extpsw; // specific extinction
53  real4d abspsw; // specific absorption
54  real4d asmpsw; // asymmetry factor
55  real4d absplw; // specific absorption
56  real2d refrtabsw; // table of real refractive indices for aerosols visible
57  real2d refitabsw; // table of imag refractive indices for aerosols visible
58  real2d refrtablw; // table of real refractive indices for aerosols infrared
59  real2d refitablw; // table of imag refractive indices for aerosols infrared
60 
61  // microphysics parameters.
62  std::string aername; // for output of number concentration
63  real density_aer; // density of aerosol (kg/m3)
64  real hygro_aer; // hygroscopicity of aerosol
65  real dryrad_aer; // number mode radius (m) of aerosol size distribution
66  real dispersion_aer; // geometric standard deviation of aerosol size distribution
67  real num_to_mass_aer; // ratio of number concentration to mass concentration (#/kg)
68  // *** Is this actually (kg/#) ???
69  //mode parameters
70  int ncoef; // number of Chebyshev coefficients
71  int prefr; // dimension in table of real refractive indices
72  int prefi; // dimension in table of imag refractive indices
73  real sigmag; // geometric standard deviation of the number distribution for aerosol mode
74  real dgnum; // geometric dry mean diameter of the number distribution for aerosol mode
75  real dgnumlo; // lower limit of dgnum
76  real dgnumhi; // upper limit of dgnum
77  real rhcrystal; // crystallization relative humidity for mode
78  real rhdeliques; // deliquescence relative humidity for mode
79  };
80 
81  // This module stores data in an array of physprop_type structures. The way this data
82  // is accessed outside the module is via a physprop ID, which is an index into the array.
83  std::vector<physprop_t> physprop;
84 
85  //Temporary storage location for filenames in namelist, and construction of dynamic index
86  // to properties. The unique filenames specified in the namelist are the identifiers of
87  // the properties. Searching the uniquefilenames array provides the index into the physprop
88  // array.
89  std::vector<std::string> uniquefilenames;
90 
91  public:
92  void physprop_accum_unique_files (const std::string& filename,
93  const std::string& type)
94  {
95  // Count number of aerosols in input radname array. Aerosols are identified
96  // as strings with a ".nc" suffix.
97  // Construct a cumulative list of unique filenames containing physical property data.
98 
99  // check if filename is either a bulk aerosol or a mode
100  if (type == "A" || type == "M") {
101  // check if this filename has been used by another aerosol. If not
102  // then add it to the list of unique names.
103  if (physprop_get_id(filename) < 0)
104  uniquefilenames.push_back(filename);
105  }
106  }
107 
108  // Read properties from the aerosol data files.
109  // ***N.B.*** The calls to physprop_accum_unique_files must be made before calling
110  // this init routine. physprop_accum_unique_files is responsible for building
111  // the list of files to be read here.
113  {
114  int numphysprops = uniquefilenames.size();
115  physprop.resize(numphysprops);
116 
117  for(auto fileindex = 0; fileindex < numphysprops; ++fileindex) {
118  physprop[fileindex].sourcefile = uniquefilenames[fileindex];
119  aerosol_optics_init(physprop[fileindex]);
120  }
121  }
122 
123  // Look for filename in the global list of unique filenames (module data uniquefilenames).
124  // If found, return it's index in the list. Otherwise return -1.
125  int physprop_get_id (std::string filename) const
126  {
127  auto physprop_id = -1;
128  auto numphysprops = uniquefilenames.size();
129  for(auto iphysprop = 0; iphysprop < numphysprops; ++iphysprop) {
130  if(uniquefilenames[iphysprop] == filename) {
131  physprop_id = iphysprop;
132  break;
133  }
134  }
135  return physprop_id;
136  }
137 
138  void get_sourcefile (int& id, std::string& sourcefile) const
139  {
140  if (id < 0 || id > physprop.size())
141  printf("get_sourcefile: illegal ID value %d\n", id);
142  sourcefile = physprop[id].sourcefile;
143  }
144 
145  void get_opticstype (int& id, std::string& opticstype) const
146  {
147  if (id < 0 || id > physprop.size())
148  printf("get_opticstype: illegal ID value %d\n", id);
149  opticstype = physprop[id].opticsmethod;
150  }
151 
152  void get_sw_hygro_ext (int& id, real2d& sw_hygro_ext) const
153  {
154  if (id < 0 || id > physprop.size())
155  printf("get_sw_hygro_ext: illegal ID value %d\n", id);
156  sw_hygro_ext = physprop[id].sw_hygro_ext;
157  }
158 
159  void get_sw_hygro_ssa (int& id, real2d& sw_hygro_ssa) const
160  {
161  if (id < 0 || id > physprop.size())
162  printf("get_sw_hygro_ssa: illegal ID value %d\n", id);
163  sw_hygro_ssa = physprop[id].sw_hygro_ssa;
164  }
165 
166  void get_sw_hygro_asm (int& id, real2d& sw_hygro_asm) const
167  {
168  if (id < 0 || id > physprop.size())
169  printf("get_sw_hygro_asm: illegal ID value %d\n", id);
170  sw_hygro_asm = physprop[id].sw_hygro_asm;
171  }
172 
173  void get_lw_hygro_abs (int& id, real2d& lw_hygro_abs) const
174  {
175  if (id < 0 || id > physprop.size())
176  printf("get_lw_hygro_abs: illegal ID value %d\n", id);
177  lw_hygro_abs = physprop[id].lw_hygro_abs;
178  }
179 
180  void get_sw_nonhygro_ext (int& id, real1d& sw_nonhygro_ext) const
181  {
182  if (id < 0 || id > physprop.size())
183  printf("get_sw_nonhygro_ext: illegal ID value %d\n", id);
184  sw_nonhygro_ext = physprop[id].sw_nonhygro_ext;
185  }
186 
187  void get_sw_nonhygro_ssa (int& id, real1d& sw_nonhygro_ssa) const
188  {
189  if (id < 0 || id > physprop.size())
190  printf("get_sw_nonhygro_ssa: illegal ID value %d\n", id);
191  sw_nonhygro_ssa = physprop[id].sw_nonhygro_ssa;
192  }
193 
194  void get_sw_nonhygro_asm (int& id, real1d& sw_nonhygro_asm) const
195  {
196  if (id < 0 || id > physprop.size())
197  printf("get_sw_nonhygro_asm: illegal ID value %d\n", id);
198  sw_nonhygro_asm = physprop[id].sw_nonhygro_asm;
199  }
200 
201  void get_sw_nonhygro_scat (int& id, real1d& sw_nonhygro_scat) const
202  {
203  if (id < 0 || id > physprop.size())
204  printf("get_sw_nonhygro_scat: illegal ID value %d\n", id);
205  sw_nonhygro_scat = physprop[id].sw_nonhygro_scat;
206  }
207 
208  void get_sw_nonhygro_ascat (int& id, real1d& sw_nonhygro_ascat) const
209  {
210  if (id < 0 || id > physprop.size())
211  printf("get_sw_nonhygro_ascat: illegal ID value %d\n", id);
212  sw_nonhygro_ascat = physprop[id].sw_nonhygro_ascat;
213  }
214 
215  void get_lw_abs (int& id, real1d& lw_abs) const
216  {
217  if (id < 0 || id > physprop.size())
218  printf("get_lw_abs: illegal ID value %d\n", id);
219  lw_abs = physprop[id].lw_abs;
220  }
221 
222  void get_ref_real_aer_sw (int& id, real1d& ref_real_aer_sw) const
223  {
224  if (id < 0 || id > physprop.size())
225  printf("get_ref_real_aer_sw: illegal ID value %d\n", id);
226  ref_real_aer_sw = physprop[id].refindex_real_aer_sw;
227  }
228 
229  void get_ref_real_aer_lw (int& id, real1d& ref_real_aer_lw) const
230  {
231  if (id < 0 || id > physprop.size())
232  printf("get_ref_real_aer_lw: illegal ID value %d\n", id);
233  ref_real_aer_lw = physprop[id].refindex_real_aer_lw;
234  }
235 
236  void get_ref_im_aer_sw (int& id, real1d& ref_im_aer_sw) const
237  {
238  if (id < 0 || id > physprop.size())
239  printf("get_ref_im_aer_sw: illegal ID value %d\n", id);
240  ref_im_aer_sw = physprop[id].refindex_im_aer_sw;
241  }
242 
243  void get_ref_im_aer_lw (int& id, real1d& ref_im_aer_lw) const
244  {
245  if (id < 0 || id > physprop.size())
246  printf("get_ref_im_aer_lw: illegal ID value %d\n", id);
247  ref_im_aer_lw = physprop[id].refindex_im_aer_lw;
248  }
249 
250  void get_r_sw_ext (int& id, real2d& r_sw_ext) const
251  {
252  if (id < 0 || id > physprop.size())
253  printf("get_r_sw_ext: illegal ID value %d\n", id);
254  r_sw_ext = physprop[id].r_sw_ext;
255  }
256 
257  void get_r_sw_scat (int& id, real2d& r_sw_scat) const
258  {
259  if (id < 0 || id > physprop.size())
260  printf("get_r_sw_scat: illegal ID value %d\n", id);
261  r_sw_scat = physprop[id].r_sw_scat;
262  }
263 
264  void get_r_sw_ascat (int& id, real2d& r_sw_ascat) const
265  {
266  if (id < 0 || id > physprop.size())
267  printf("get_r_sw_ascat: illegal ID value %d\n", id);
268  r_sw_ascat = physprop[id].r_sw_ascat;
269  }
270 
271  void get_r_lw_abs (int& id, real2d& r_lw_abs) const
272  {
273  if (id < 0 || id > physprop.size())
274  printf("get_r_lw_abs: illegal ID value %d\n", id);
275  r_lw_abs = physprop[id].r_lw_abs;
276  }
277 
278  void get_mu (int& id, real1d& mu) const
279  {
280  if (id < 0 || id > physprop.size())
281  printf("get_mu: illegal ID value %d\n", id);
282  mu = physprop[id].mu;
283  }
284 
285  void get_extpsw (int& id, real4d& extpsw) const
286  {
287  if (id < 0 || id > physprop.size())
288  printf("get_expsw: illegal ID value %d\n", id);
289  extpsw = physprop[id].extpsw;
290  }
291 
292  void get_abspsw (int& id, real4d& abspsw) const
293  {
294  if (id < 0 || id > physprop.size())
295  printf("get_abspsw: illegal ID value %d\n", id);
296  abspsw = physprop[id].abspsw;
297  }
298 
299  void get_asmpsw (int& id, real4d& asmpsw) const
300  {
301  if (id < 0 || id > physprop.size())
302  printf("get_asmpsw: illegal ID value %d\n", id);
303  asmpsw = physprop[id].asmpsw;
304  }
305 
306  void get_absplw (int& id, real4d& absplw) const
307  {
308  if (id < 0 || id > physprop.size())
309  printf("get_absplw: illegal ID value %d\n", id);
310  absplw = physprop[id].absplw;
311  }
312 
313  void get_refrtabsw (int& id, real2d& refrtabsw) const
314  {
315  if (id < 0 || id > physprop.size())
316  printf("get_refrtabsw: illegal ID value %d\n", id);
317  refrtabsw = physprop[id].refrtabsw;
318  }
319 
320  void get_refitabsw (int& id, real2d& refitabsw) const
321  {
322  if (id < 0 || id > physprop.size())
323  printf("get_refitabsw: illegal ID value %d\n", id);
324  refitabsw = physprop[id].refitabsw;
325  }
326 
327  void get_refrtablw (int& id, real2d& refrtablw) const
328  {
329  if (id < 0 || id > physprop.size())
330  printf("get_refrtablw: illegal ID value %d\n", id);
331  refrtablw = physprop[id].refrtablw;
332  }
333 
334  void get_refitablw (int& id, real2d& refitablw) const
335  {
336  if (id < 0 || id > physprop.size())
337  printf("ger_refitablw: illegal ID value %d\n", id);
338  refitablw = physprop[id].refitablw;
339  }
340 
341  void get_aername(int& id, std::string& aername) const
342  {
343  if (id < 0 || id > physprop.size())
344  printf("get_aername: illegal ID value %d\n", id);
345  aername = physprop[id].aername;
346  }
347 
348  void get_density_aer(int& id, real& density_aer) const
349  {
350  if (id < 0 || id > physprop.size())
351  printf("get_density_aer: illegal ID value %d\n", id);
352  density_aer = physprop[id].density_aer;
353  }
354 
355  void get_hygro_aer (int& id, real& hygro_aer) const
356  {
357  if (id < 0 || id > physprop.size())
358  printf("get_hygro_aer: illegal ID value %d\n", id);
359  hygro_aer = physprop[id].hygro_aer;
360  }
361 
362  void get_dryrad_aer (int& id, real& dryrad_aer) const
363  {
364  if (id < 0 || id > physprop.size())
365  printf("get_dryrad_aer: illegal ID value %d\n", id);
366  dryrad_aer = physprop[id].dryrad_aer;
367  }
368 
369  void get_dispersion_aer (int& id, real& dispersion_aer) const
370  {
371  if (id < 0 || id > physprop.size())
372  printf("get_dispersion_aer: illegal ID value %d\n", id);
373  dispersion_aer = physprop[id].dispersion_aer;
374  }
375 
376  void get_num_to_mass_aer (int& id, real& num_to_mass_aer) const
377  {
378  if (id < 0 || id > physprop.size())
379  printf("get_num_to_mass_aer: illegal ID value %d\n", id);
380  num_to_mass_aer = physprop[id].num_to_mass_aer;
381  }
382 
383  void get_ncoef (int& id, int& ncoef) const
384  {
385  if (id < 0 || id > physprop.size())
386  printf("get_ncoef: illegal ID value %d\n", id);
387  ncoef = physprop[id].ncoef;
388  }
389 
390  void get_prefr (int& id, int& prefr) const
391  {
392  if (id < 0 || id > physprop.size())
393  printf("get_prefr: illegal ID value %d\n", id);
394  prefr = physprop[id].prefr;
395  }
396 
397  void get_prefi (int& id, int& prefi) const
398  {
399  if (id < 0 || id > physprop.size())
400  printf("get_prefi: illegal ID value %d\n", id);
401  prefi = physprop[id].prefi;
402  }
403 
404  void get_sigmag (int& id, real& sigmag) const
405  {
406  if (id < 0 || id > physprop.size())
407  printf("get_sigmag: illegal ID value %d\n", id);
408  sigmag = physprop[id].sigmag;
409  }
410 
411  void get_dgnum (int& id, real& dgnum) const
412  {
413  if (id < 0 || id > physprop.size())
414  printf("get_dgnum: illegal ID value %d\n", id);
415  dgnum = physprop[id].dgnum;
416  }
417 
418  void get_dgnumlo (int& id, real& dgnumlo) const
419  {
420  if (id < 0 || id > physprop.size())
421  printf("get_dgnumlo: illegal ID value %d\n", id);
422  dgnumlo = physprop[id].dgnumlo;
423  }
424 
425  void get_dgnumhi (int& id, real& dgnumhi) const
426  {
427  if (id < 0 || id > physprop.size())
428  printf("get_dgnumhi: illegal ID value %d\n", id);
429  dgnumhi = physprop[id].dgnumhi;
430  }
431 
432  void get_rhcrystal (int& id, real& rhcrystal) const
433  {
434  if (id < 0 || id > physprop.size())
435  printf("get_rhcrystal: illegal ID value %d\n", id);
436  rhcrystal = physprop[id].rhcrystal;
437  }
438 
439  void get_rhdeliques (int& id, real& rhdeliques) const
440  {
441  if (id < 0 || id > physprop.size())
442  printf("get_rhdeliques: illegal ID value %d\n", id);
443  rhdeliques = physprop[id].rhdeliques;
444  }
445 
446  // Determine the opticstype, then call the
447  // appropriate routine to read the data.
448  void aerosol_optics_init (physprop_t& phys_prop)
449  {
450  using charHost1d = FArray<char,1,yakl::memHost>;
451  yakl::SimpleNetCDF prop;
452  prop.open(phys_prop.sourcefile, yakl::NETCDF_MODE_READ);
453  charHost1d temp;
454  prop.read(temp, "opticsmethod");
455  for (auto ichar = 1 ; ichar <= temp.extent(0); ichar++)
456  if (!isspace(temp(ichar))) phys_prop.opticsmethod += temp(ichar);
457 
458  if(strcmp(phys_prop.opticsmethod.c_str(),"zero") == 0) {
459  zero_optics_init(phys_prop, prop);
460  } else if (strcmp(phys_prop.opticsmethod.c_str(),"hygro") == 0) {
461  hygro_optics_init(phys_prop, prop);
462  } else if (strcmp(phys_prop.opticsmethod.c_str(),"hygroscopic") == 0) {
463  hygroscopic_optics_init(phys_prop, prop);
464  } else if (strcmp(phys_prop.opticsmethod.c_str(),"nonhygro") == 0) {
465  nonhygro_optics_init(phys_prop, prop);
466  } else if (strcmp(phys_prop.opticsmethod.c_str(),"insoluble") == 0) {
467  insoluble_optics_init(phys_prop, prop);
468  } else if (strcmp(phys_prop.opticsmethod.c_str(),"volcanic_radius") == 0) {
469  volcanic_radius_optics_init(phys_prop, prop);
470  } else if (strcmp(phys_prop.opticsmethod.c_str(),"volcanic") == 0) {
471  volcanic_optics_init(phys_prop, prop);
472  } else if (strcmp(phys_prop.opticsmethod.c_str(),"modal") == 0) {
473  modal_optics_init(phys_prop, prop);
474  } else {
475  amrex::Print() << "no options available\n";
476  }
477  }
478 
479  void hygro_optics_init (physprop_t& phys_prop, yakl::SimpleNetCDF& prop)
480  {
481  real1d frh;
482  real2d fsw_ext;
483  real2d fsw_ssa;
484  real2d fsw_asm;
485  real2d flw_abs;
486 
487  auto nrh = RadConstants::nrh;
488  //auto nbnd = prop.getDimSize( "lw_band" );
489  auto nswbands = prop.getDimSize( "sw_band" );
490 
491  prop.read( fsw_ext, "ext_sw");
492  prop.read( fsw_ssa, "ssa_sw");
493  prop.read( fsw_asm, "asm_sw");
494  prop.read( flw_abs, "abs_lw");
495  prop.read( frh, "rh");
496 
497  real1d fswe("fswe",nrh),
498  fsws("fsws",nrh),
499  fswa("fswa",nrh);
500 
501  // interpolate onto cam's rh mesh
502  for(auto kbnd = 0; kbnd < nswbands; ++kbnd) {
503  for(auto krh = 0; krh < nrh; ++krh) {
504  fswe(krh) = fsw_ext(krh,kbnd)/fsw_ext(1,kbnd);
505  fsws(krh) = fsw_ssa(krh,kbnd)/fsw_ssa(1,kbnd);
506  fswa(krh) = fsw_asm(krh,kbnd)/fsw_asm(1,kbnd);
507  }
508 
509  // interpolation
510  for(auto krh = 0; krh < nrh; ++krh) {
511  auto rh = 1.0/nrh*(krh-1);
512  phys_prop.sw_hygro_ext(krh,kbnd) = exp_interpol(frh,fswe,rh)*fsw_ext(1,kbnd);
513  phys_prop.sw_hygro_ssa(krh,kbnd) = lin_interpol(frh,fsws,rh)*fsw_ssa(1,kbnd);
514  phys_prop.sw_hygro_asm(krh,kbnd) = lin_interpol(frh,fswa,rh)*fsw_asm(1,kbnd);
515  }
516  }
517 
518  // read refractive index data if available
519  refindex_aer_init(phys_prop, prop);
520 
521  // read bulk aero props
522  bulk_props_init(phys_prop, prop);
523  }
524 
525  // Read optics data of type 'nonhygro'
526  void zero_optics_init (physprop_t& phys_prop, yakl::SimpleNetCDF& prop)
527  {
528  auto nlwbands = prop.getDimSize( "lw_band" );
529  auto nswbands = prop.getDimSize( "sw_band" );
530 
531  // perhaps this doesn't even need allocated.
532  phys_prop.sw_nonhygro_ext = real1d("sw_nonhygro_ext", nswbands);
533  phys_prop.sw_nonhygro_ssa = real1d("sw_nonhygro_ssa", nswbands);
534  phys_prop.sw_nonhygro_asm = real1d("sw_nonhygro_asm", nswbands);
535  phys_prop.lw_abs = real1d("lwabs", nlwbands);
536 
537  yakl::memset(phys_prop.sw_nonhygro_ext, 0.);
538  yakl::memset(phys_prop.sw_nonhygro_ssa, 0.);
539  yakl::memset(phys_prop.sw_nonhygro_asm, 0.);
540  yakl::memset(phys_prop.lw_abs, 0.);
541  }
542 
543  void insoluble_optics_init (physprop_t& phys_prop, yakl::SimpleNetCDF& prop)
544  {
545  auto nbnd = prop.getDimSize( "lw_band" );
546  auto nswbands = prop.getDimSize( "sw_band" );
547  realHost2d ext_sw, ssa_sw, asm_sw, abs_lw;
548 
549  phys_prop.sw_nonhygro_ext = real1d("sw_nonhygro_ext", nswbands);
550  phys_prop.sw_nonhygro_ssa = real1d("sw_nonhygro_ssa", nswbands);
551  phys_prop.sw_nonhygro_asm = real1d("sw_nonhygro_asm", nswbands);
552  phys_prop.lw_abs = real1d("lw_abs", nbnd);
553 
554  prop.read( ext_sw, "ext_sw");
555  prop.read( ssa_sw, "ssa_sw");
556  prop.read( asm_sw, "asm_sw");
557  prop.read( abs_lw, "abs_lw");
558 
559  parallel_for (SimpleBounds<1>(nswbands), YAKL_LAMBDA (int i)
560  {
561  phys_prop.sw_nonhygro_ext(i) = ext_sw(i,1);
562  phys_prop.sw_nonhygro_ssa(i) = ssa_sw(i,1);
563  phys_prop.sw_nonhygro_asm(i) = asm_sw(i,1);
564  });
565 
566  parallel_for (SimpleBounds<1>(nbnd), YAKL_LAMBDA (int i)
567  {
568  phys_prop.lw_abs(i) = abs_lw(i,1);
569  });
570 
571  // read refractive index data if available
572  refindex_aer_init(phys_prop, prop);
573 
574  // read bulk aero props
575  bulk_props_init(phys_prop, prop);
576  }
577 
578  // Read optics data of type 'volcanic_radius'
579  void volcanic_radius_optics_init (physprop_t& phys_prop, yakl::SimpleNetCDF& prop)
580  {
581  //auto n_mu_samples = prop.getDimSize( "mu_samples" );
582  //auto nbnd = prop.getDimSize( "lw_band" );
583  //auto nswbands = prop.getDimSize( "sw_band" );
584 
585  prop.read( phys_prop.r_sw_ext, "bext_sw");
586  prop.read( phys_prop.r_sw_scat, "bsca_sw");
587  prop.read( phys_prop.r_sw_ascat, "basc_sw");
588  prop.read( phys_prop.r_lw_abs, "babs_lw");
589  prop.read( phys_prop.mu, "mu_samples");
590 
591  // read bulk aero props
592  bulk_props_init(phys_prop, prop);
593  }
594 
595  // Read optics data of type 'volcanic'
596  void volcanic_optics_init (physprop_t& phys_prop, yakl::SimpleNetCDF& prop)
597  {
598  //auto nbnd = prop.getDimSize( "lw_band" );
599  //auto nswbands = prop.getDimSize( "sw_band" );
600 
601  prop.read( phys_prop.sw_nonhygro_ext, "bext_sw");
602  prop.read( phys_prop.sw_nonhygro_scat, "bsca_sw");
603  prop.read( phys_prop.sw_nonhygro_ascat, "basc_sw");
604  prop.read( phys_prop.lw_abs, "babs_lw");
605 
606  // read bulk aero props
607  bulk_props_init(phys_prop, prop);
608  }
609 
610  // Read optics data of type 'hygroscopic' and interpolate it to CAM's rh mesh.
611  void hygroscopic_optics_init (physprop_t& phys_prop, yakl::SimpleNetCDF& prop)
612  {
613  // temp data from hygroscopic file before interpolation onto cam-rh-mesh
614  //int nfilerh; // number of rh values in file
615  real1d frh;
616  real2d fsw_ext, fsw_ssa, fsw_asm, flw_abs;
617 
618  auto nrh = RadConstants::nrh;
619  auto nlwbands = prop.getDimSize( "lw_band" );
620  auto nswbands = prop.getDimSize( "sw_band" );
621 
622  phys_prop.sw_hygro_ext = real2d("sw_hygro_ext",nrh,nswbands);
623  phys_prop.sw_hygro_ssa = real2d("sw_hygro_ssa",nrh,nswbands);
624  phys_prop.sw_hygro_asm = real2d("sw_hygro_asm",nrh,nswbands);
625  phys_prop.lw_hygro_abs = real2d("lw_hygro_abs",nrh,nlwbands);
626 
627  prop.read( fsw_ext, "ext_sw");
628  prop.read( fsw_ssa, "ssa_sw");
629  prop.read( fsw_asm, "asm_sw");
630  prop.read( flw_abs, "abs_lw");
631  prop.read( frh, "rh");
632 
633  real1d fswe("",nrh), fsws("",nrh),
634  fswa("",nrh), flwa("",nrh);
635 
636  // interpolate onto cam's rh mesh
637  parallel_for (SimpleBounds<2> (nswbands, nrh), YAKL_LAMBDA (int kbnd, int krh)
638  {
639  fswe(krh) = fsw_ext(krh,kbnd) / fsw_ext(1,kbnd);
640  fsws(krh) = fsw_ssa(krh,kbnd) / fsw_ssa(1,kbnd);
641  fswa(krh) = fsw_asm(krh,kbnd) / fsw_asm(1,kbnd);
642  });
643 
644  parallel_for (SimpleBounds<2> (nswbands, nrh), YAKL_LAMBDA (int kbnd, int krh)
645  {
646  auto rh = 1.0 / nrh * (krh - 1);
647  phys_prop.sw_hygro_ext(krh,kbnd) = exp_interpol( frh, fswe, rh ) * fsw_ext(1, kbnd);
648  phys_prop.sw_hygro_ssa(krh,kbnd) = lin_interpol( frh, fswe, rh ) * fsw_ssa(1, kbnd);
649  phys_prop.sw_hygro_asm(krh,kbnd) = lin_interpol( frh, fswa, rh ) * fsw_asm(1, kbnd);
650  });
651 
652  // interpolate long wave
653  parallel_for (SimpleBounds<2> (nlwbands, nrh), YAKL_LAMBDA (int kbnd, int krh)
654  {
655  flwa(krh) = flw_abs(krh,kbnd) / flw_abs(1,kbnd);
656  });
657 
658  parallel_for (SimpleBounds<2> (nlwbands, nrh), YAKL_LAMBDA (int kbnd, int krh)
659  {
660  auto rh = 1.0 / nrh * (krh - 1);
661  phys_prop.lw_hygro_abs(krh,kbnd) = exp_interpol( frh, flwa, rh ) * flw_abs(1, kbnd);
662  });
663 
664  // read refractive index data if available
665  refindex_aer_init(phys_prop, prop);
666 
667  // bulk aero props
668  bulk_props_init(phys_prop, prop);
669  }
670 
671  // Read optics data of type 'nonhygro'
672  void nonhygro_optics_init (physprop_t& phys_prop, yakl::SimpleNetCDF& prop)
673  {
674  //auto nlwbands = prop.getDimSize( "lw_band" );
675  //auto nswbands = prop.getDimSize( "sw_band" );
676 
677  prop.read( phys_prop.sw_nonhygro_ext, "ext_sw");
678  prop.read( phys_prop.sw_nonhygro_ssa, "ssa_sw");
679  prop.read( phys_prop.sw_nonhygro_asm, "asm_sw");
680  prop.read( phys_prop.lw_abs, "abs_lw");
681 
682  // read refractive index data if available
683  refindex_aer_init(phys_prop, prop);
684 
685  // read bulk aero props
686  bulk_props_init(phys_prop, prop);
687  }
688 
689  // Read refractive indices of aerosol
690  void refindex_aer_init (physprop_t& phys_prop, yakl::SimpleNetCDF& prop)
691  {
692  prop.read(phys_prop.refindex_real_aer_sw, "refindex_real_aer_sw");
693  prop.read(phys_prop.refindex_im_aer_sw, "refindex_im_aer_sw");
694 
695  prop.read(phys_prop.refindex_real_aer_lw, "refindex_real_aer_lw");
696  prop.read(phys_prop.refindex_im_aer_lw, "refindex_im_aer_lw");
697  }
698 
699  // Read optics data for modal aerosols
700  void modal_optics_init (physprop_t& phys_prop, yakl::SimpleNetCDF& prop)
701  {
702  // NOTE: Definitions for real arrays come from rrtmgp_const.h
703  // and they default to styleFortran ordering.
704  realHost5d extpsw, abspsw, asmpsw, absplw;
705  auto nlwbnd = prop.getDimSize( "lw_band" );
706  auto nswbnd = prop.getDimSize( "sw_band" );
707  auto ncoef = prop.getDimSize( "coef_number" );
708  auto prefr = prop.getDimSize( "refindex_real" );
709  auto prefi = prop.getDimSize( "refindex_im" );
710  phys_prop.ncoef = ncoef;
711  phys_prop.prefr = prefr;
712  phys_prop.prefi = prefi;
713 
714  prop.read(extpsw, "extpsw" );
715  prop.read(abspsw, "abspsw" );
716  prop.read(asmpsw, "asmpsw" );
717  prop.read(absplw, "absplw" );
718 
719  // styleFortran ordering to be consistent with realHost5d definition
720  phys_prop.extpsw = real4d("extpsw", ncoef, prefr, prefi, nswbnd);
721  phys_prop.abspsw = real4d("abspsw", ncoef, prefr, prefi, nswbnd);
722  phys_prop.asmpsw = real4d("asmpsw", ncoef, prefr, prefi, nswbnd);
723  phys_prop.absplw = real4d("absplw", ncoef, prefr, prefi, nswbnd);
724 
725  parallel_for (SimpleBounds<4>(nswbnd, prefr, prefi, ncoef),
726  YAKL_LAMBDA (int i, int j, int k, int l)
727  {
728  phys_prop.extpsw(i,j,k,l) = extpsw(i,j,k,1,l);
729  phys_prop.abspsw(i,j,k,l) = abspsw(i,j,k,1,l);
730  phys_prop.asmpsw(i,j,k,l) = asmpsw(i,j,k,1,l);
731  });
732 
733  parallel_for (SimpleBounds<4>(nlwbnd, prefr, prefi, ncoef),
734  YAKL_LAMBDA (int i, int j, int k, int l)
735  {
736  phys_prop.absplw(i,j,k,l) = absplw(i,j,k,1,l);
737  });
738 
739  prop.read(phys_prop.refrtabsw, "refindex_real_sw" );
740  prop.read(phys_prop.refitabsw, "refindex_im_sw" );
741  prop.read(phys_prop.refrtablw, "refindex_real_lw" );
742  prop.read(phys_prop.refitablw, "refindex_im_lw" );
743 
744  prop.read(phys_prop.sigmag, "sigmag" );
745  prop.read(phys_prop.dgnum, "dgnum" );
746 
747  prop.read(phys_prop.dgnumlo, "dgnumlo" );
748  prop.read(phys_prop.dgnumhi, "dgnumhi" );
749 
750  prop.read(phys_prop.rhcrystal, "rhcrystal" );
751  prop.read(phys_prop.rhdeliques, "rhdeliques" );
752  }
753 
754  void bulk_props_init (physprop_t& phys_prop, yakl::SimpleNetCDF& prop)
755  {
756  using charHost1d = FArray<char,1,yakl::memHost>;
757  charHost1d temp;
758  prop.read(temp, "name");
759  phys_prop.aername = "";
760  for (auto ichar = 1 ; ichar <= temp.extent(0); ichar++)
761  if (!isspace(temp(ichar))) phys_prop.aername += temp(ichar);
762 
763  // Read props for bulk aerosols
764  prop.read( phys_prop.density_aer, "density" );
765  prop.read( phys_prop.dispersion_aer, "sigma_logr" );
766  prop.read( phys_prop.dryrad_aer, "dryrad" );
767  prop.read( phys_prop.hygro_aer, "hygroscopicity" );
768  prop.read( phys_prop.num_to_mass_aer, "num_to_mass_ratio" );
769  }
770 
771  // Purpose:
772  //interpolates f(x) to point y
773  //assuming f(x) = f(x0) exp a(x - x0)
774  //where a = ( ln f(x1) - ln f(x0) ) / (x1 - x0)
775  //x0 <= x <= x1
776  //assumes x is monotonically increasing
777  real exp_interpol (const real1d& x, const real1d& f, const real& y)
778  {
779  auto n = x.extent(0);
780  int k;
781 
782  // find k such that x(k) < y =< x(k+1)
783  // set k = 1 if y <= x(1) and k = n-1 if y > x(n)
784  if (y <= x(1)) {
785  k = 1;
786  }
787  else if (y >= x(n)) {
788  k = n - 1;
789  }
790  else {
791  k = 1;
792  while (y > x(k+1) && k < n) {
793  k = k + 1;
794  }
795  }
796 
797  // interpolate
798  auto a = (log(f(k+1)/f(k)))/(x(k+1)-x(k));
799  return f(k)*exp(a*(y-x(k)));
800  }
801 
802  //Purpose:
803  // interpolates f(x) to point y
804  // assuming f(x) = f(x0) + a * (x - x0)
805  // where a = ( f(x1) - f(x0) ) / (x1 - x0)
806  // x0 <= x <= x1
807  // assumes x is monotonically increasing
808  //
809  real lin_interpol (const real1d& x, const real1d& f, const real& y)
810  {
811  auto n = x.extent(0);
812  int k;
813  // find k such that x(k) < y =< x(k+1)
814  // set k = 1 if y <= x(1) and k = n-1 if y > x(n)
815  if (y <= x(1)) {
816  k = 1;
817  }
818  else if (y >= x(n)) {
819  k = n - 1;
820  }
821  else {
822  k = 1;
823  while (y > x(k+1) && k < n) {
824  k = k + 1;
825  }
826  }
827  // interpolate
828  auto a = (f(k+1)-f(k))/(x(k+1)-x(k));
829  return f(k)+a*(y-x(k));
830  }
831 
832  // Purpose:
833  // write out aerosol optical properties
834  // for a set of test rh values
835  // to test hygroscopic growth interpolation
836  void aer_optics_log_rh (std::string name, const real1d& ext, const real1d& ssa, const real1d& asmin)
837  {
838  const int nrh_test = 36;
839  //int krh;
840  real1d rh_test("rh_test", nrh_test);
841  //auto nrh = ext.extent(0);
842 
843  parallel_for (SimpleBounds<1> (nrh_test), YAKL_LAMBDA (int krh_test)
844  {
845  rh_test(krh_test) = sqrt(sqrt(sqrt(sqrt(((krh_test - 1.0) / (nrh_test - 1))))));
846  });
847 
848  // loop through test rh values
849  parallel_for (SimpleBounds<1> (nrh_test), YAKL_LAMBDA (int krh_test)
850  {
851  /*
852  // find corresponding rh index
853  auto rh = rh_test(krh_test);
854  auto krh = std::min(floor( (rh) * nrh ) + 1, static_cast<real>(nrh - 1));
855  auto wrh = (rh) *nrh - krh;
856  auto exti = ext(krh + 1) * (wrh + 1) - ext(krh) * wrh;
857  auto ssai = ssa(krh + 1) * (wrh + 1) - ssa(krh) * wrh;
858  auto asmi = asmin(krh + 1) * (wrh + 1) - asmin(krh) * wrh;
859  */
860  });
861  }
862 };
863 
864 #endif
Definition: ERF_PhysProp.H:17
void hygroscopic_optics_init(physprop_t &phys_prop, yakl::SimpleNetCDF &prop)
Definition: ERF_PhysProp.H:611
void physprop_init()
Definition: ERF_PhysProp.H:112
void get_sw_nonhygro_ssa(int &id, real1d &sw_nonhygro_ssa) const
Definition: ERF_PhysProp.H:187
void volcanic_optics_init(physprop_t &phys_prop, yakl::SimpleNetCDF &prop)
Definition: ERF_PhysProp.H:596
void refindex_aer_init(physprop_t &phys_prop, yakl::SimpleNetCDF &prop)
Definition: ERF_PhysProp.H:690
void aer_optics_log_rh(std::string name, const real1d &ext, const real1d &ssa, const real1d &asmin)
Definition: ERF_PhysProp.H:836
void get_r_sw_ext(int &id, real2d &r_sw_ext) const
Definition: ERF_PhysProp.H:250
void get_sw_nonhygro_ext(int &id, real1d &sw_nonhygro_ext) const
Definition: ERF_PhysProp.H:180
void get_ref_real_aer_sw(int &id, real1d &ref_real_aer_sw) const
Definition: ERF_PhysProp.H:222
void get_sw_nonhygro_scat(int &id, real1d &sw_nonhygro_scat) const
Definition: ERF_PhysProp.H:201
void bulk_props_init(physprop_t &phys_prop, yakl::SimpleNetCDF &prop)
Definition: ERF_PhysProp.H:754
void get_prefr(int &id, int &prefr) const
Definition: ERF_PhysProp.H:390
void get_sourcefile(int &id, std::string &sourcefile) const
Definition: ERF_PhysProp.H:138
void get_ref_im_aer_sw(int &id, real1d &ref_im_aer_sw) const
Definition: ERF_PhysProp.H:236
void aerosol_optics_init(physprop_t &phys_prop)
Definition: ERF_PhysProp.H:448
void get_lw_hygro_abs(int &id, real2d &lw_hygro_abs) const
Definition: ERF_PhysProp.H:173
void get_sigmag(int &id, real &sigmag) const
Definition: ERF_PhysProp.H:404
void get_dgnum(int &id, real &dgnum) const
Definition: ERF_PhysProp.H:411
void modal_optics_init(physprop_t &phys_prop, yakl::SimpleNetCDF &prop)
Definition: ERF_PhysProp.H:700
void get_r_lw_abs(int &id, real2d &r_lw_abs) const
Definition: ERF_PhysProp.H:271
void get_refitablw(int &id, real2d &refitablw) const
Definition: ERF_PhysProp.H:334
std::vector< std::string > uniquefilenames
Definition: ERF_PhysProp.H:89
void get_ref_real_aer_lw(int &id, real1d &ref_real_aer_lw) const
Definition: ERF_PhysProp.H:229
void get_hygro_aer(int &id, real &hygro_aer) const
Definition: ERF_PhysProp.H:355
void get_mu(int &id, real1d &mu) const
Definition: ERF_PhysProp.H:278
void get_sw_nonhygro_asm(int &id, real1d &sw_nonhygro_asm) const
Definition: ERF_PhysProp.H:194
void get_abspsw(int &id, real4d &abspsw) const
Definition: ERF_PhysProp.H:292
void get_opticstype(int &id, std::string &opticstype) const
Definition: ERF_PhysProp.H:145
void get_extpsw(int &id, real4d &extpsw) const
Definition: ERF_PhysProp.H:285
void hygro_optics_init(physprop_t &phys_prop, yakl::SimpleNetCDF &prop)
Definition: ERF_PhysProp.H:479
void insoluble_optics_init(physprop_t &phys_prop, yakl::SimpleNetCDF &prop)
Definition: ERF_PhysProp.H:543
void get_aername(int &id, std::string &aername) const
Definition: ERF_PhysProp.H:341
real lin_interpol(const real1d &x, const real1d &f, const real &y)
Definition: ERF_PhysProp.H:809
void get_ref_im_aer_lw(int &id, real1d &ref_im_aer_lw) const
Definition: ERF_PhysProp.H:243
void physprop_accum_unique_files(const std::string &filename, const std::string &type)
Definition: ERF_PhysProp.H:92
void get_sw_hygro_ssa(int &id, real2d &sw_hygro_ssa) const
Definition: ERF_PhysProp.H:159
void get_ncoef(int &id, int &ncoef) const
Definition: ERF_PhysProp.H:383
real exp_interpol(const real1d &x, const real1d &f, const real &y)
Definition: ERF_PhysProp.H:777
void get_sw_hygro_ext(int &id, real2d &sw_hygro_ext) const
Definition: ERF_PhysProp.H:152
void get_refrtablw(int &id, real2d &refrtablw) const
Definition: ERF_PhysProp.H:327
void get_r_sw_scat(int &id, real2d &r_sw_scat) const
Definition: ERF_PhysProp.H:257
void get_sw_nonhygro_ascat(int &id, real1d &sw_nonhygro_ascat) const
Definition: ERF_PhysProp.H:208
void get_dryrad_aer(int &id, real &dryrad_aer) const
Definition: ERF_PhysProp.H:362
void get_dispersion_aer(int &id, real &dispersion_aer) const
Definition: ERF_PhysProp.H:369
void get_refrtabsw(int &id, real2d &refrtabsw) const
Definition: ERF_PhysProp.H:313
void get_asmpsw(int &id, real4d &asmpsw) const
Definition: ERF_PhysProp.H:299
void get_rhdeliques(int &id, real &rhdeliques) const
Definition: ERF_PhysProp.H:439
int physprop_get_id(std::string filename) const
Definition: ERF_PhysProp.H:125
void get_num_to_mass_aer(int &id, real &num_to_mass_aer) const
Definition: ERF_PhysProp.H:376
void get_refitabsw(int &id, real2d &refitabsw) const
Definition: ERF_PhysProp.H:320
void get_density_aer(int &id, real &density_aer) const
Definition: ERF_PhysProp.H:348
void nonhygro_optics_init(physprop_t &phys_prop, yakl::SimpleNetCDF &prop)
Definition: ERF_PhysProp.H:672
void volcanic_radius_optics_init(physprop_t &phys_prop, yakl::SimpleNetCDF &prop)
Definition: ERF_PhysProp.H:579
std::vector< physprop_t > physprop
Definition: ERF_PhysProp.H:83
void get_absplw(int &id, real4d &absplw) const
Definition: ERF_PhysProp.H:306
void get_r_sw_ascat(int &id, real2d &r_sw_ascat) const
Definition: ERF_PhysProp.H:264
void get_rhcrystal(int &id, real &rhcrystal) const
Definition: ERF_PhysProp.H:432
void zero_optics_init(physprop_t &phys_prop, yakl::SimpleNetCDF &prop)
Definition: ERF_PhysProp.H:526
void get_prefi(int &id, int &prefi) const
Definition: ERF_PhysProp.H:397
void get_sw_hygro_asm(int &id, real2d &sw_hygro_asm) const
Definition: ERF_PhysProp.H:166
void get_dgnumlo(int &id, real &dgnumlo) const
Definition: ERF_PhysProp.H:418
void get_lw_abs(int &id, real1d &lw_abs) const
Definition: ERF_PhysProp.H:215
void get_dgnumhi(int &id, real &dgnumhi) const
Definition: ERF_PhysProp.H:425
static constexpr int nrh
Definition: ERF_RadConstants.H:77
Definition: ERF_PhysProp.H:20
real1d refindex_im_aer_sw
Definition: ERF_PhysProp.H:40
real dgnumhi
Definition: ERF_PhysProp.H:76
real rhdeliques
Definition: ERF_PhysProp.H:78
real4d asmpsw
Definition: ERF_PhysProp.H:54
real4d absplw
Definition: ERF_PhysProp.H:55
real1d refindex_im_aer_lw
Definition: ERF_PhysProp.H:42
real2d r_sw_ext
Definition: ERF_PhysProp.H:45
real2d refrtabsw
Definition: ERF_PhysProp.H:56
real2d lw_hygro_abs
Definition: ERF_PhysProp.H:28
real dgnumlo
Definition: ERF_PhysProp.H:75
real1d refindex_real_aer_sw
Definition: ERF_PhysProp.H:39
real1d sw_nonhygro_ext
Definition: ERF_PhysProp.H:31
std::string sourcefile
Definition: ERF_PhysProp.H:21
real sigmag
Definition: ERF_PhysProp.H:73
real1d sw_nonhygro_ascat
Definition: ERF_PhysProp.H:35
real dryrad_aer
Definition: ERF_PhysProp.H:65
std::string aername
Definition: ERF_PhysProp.H:62
real dgnum
Definition: ERF_PhysProp.H:74
real1d sw_nonhygro_asm
Definition: ERF_PhysProp.H:33
real2d refitabsw
Definition: ERF_PhysProp.H:57
real1d lw_abs
Definition: ERF_PhysProp.H:36
real2d refitablw
Definition: ERF_PhysProp.H:59
real density_aer
Definition: ERF_PhysProp.H:63
real2d r_sw_ascat
Definition: ERF_PhysProp.H:47
real1d mu
Definition: ERF_PhysProp.H:49
std::string opticsmethod
Definition: ERF_PhysProp.H:22
real1d refindex_real_aer_lw
Definition: ERF_PhysProp.H:41
real4d extpsw
Definition: ERF_PhysProp.H:52
real num_to_mass_aer
Definition: ERF_PhysProp.H:67
real1d sw_nonhygro_ssa
Definition: ERF_PhysProp.H:32
real1d sw_nonhygro_scat
Definition: ERF_PhysProp.H:34
int ncoef
Definition: ERF_PhysProp.H:70
real2d refrtablw
Definition: ERF_PhysProp.H:58
int prefi
Definition: ERF_PhysProp.H:72
real2d r_sw_scat
Definition: ERF_PhysProp.H:46
real dispersion_aer
Definition: ERF_PhysProp.H:66
int prefr
Definition: ERF_PhysProp.H:71
real2d sw_hygro_ssa
Definition: ERF_PhysProp.H:26
real4d abspsw
Definition: ERF_PhysProp.H:53
real2d sw_hygro_asm
Definition: ERF_PhysProp.H:27
real rhcrystal
Definition: ERF_PhysProp.H:77
real2d r_lw_abs
Definition: ERF_PhysProp.H:48
real hygro_aer
Definition: ERF_PhysProp.H:64
real2d sw_hygro_ext
Definition: ERF_PhysProp.H:25