Skip to content

Commit 0e3d01f

Browse files
authored
Merge pull request #273 from trontrytel/thesis_plots
Thesis plots
2 parents 136d997 + f508ddb commit 0e3d01f

15 files changed

+859
-162
lines changed

src/particles_impl_chem_henry.ipp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,9 @@ namespace libcloudphxx
191191

192192
// implicit solution to the eq. 8.22 from chapter 8.4.2
193193
// in Peter Warneck Chemistry of the Natural Atmosphere
194-
return
195-
(
196-
( m_old
194+
real_t mass_helper =
195+
(
196+
( m_old
197197
+
198198
(dt * si::seconds) * (V * si::cubic_metres)
199199
* common::henry::mass_trans(
@@ -210,7 +210,9 @@ namespace libcloudphxx
210210
* common::henry::mass_trans(rw2, (D * si::metres * si::metres / si::seconds),
211211
acc_coeff * si::seconds / si::seconds, T, (M_gas * si::kilograms / si::moles))
212212
/ Henry / common::moist_air::kaBoNA<real_t>() / T)
213-
) / si::kilograms;
213+
) / si::kilograms ;
214+
215+
return mass_helper;// > 0 ? mass_helper : 0;
214216
}
215217
};
216218
};

src/particles_impl_chem_react.ipp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ namespace libcloudphxx
1919
{ // returns the change in mass per second of each chemical compounds
2020
// due to oxidation reaction
2121
const int chem_iter;
22+
const real_t dt;
2223

2324
// ctor
24-
chem_rhs_helper(const int &chem_iter) :
25-
chem_iter(chem_iter)
25+
chem_rhs_helper(const int &chem_iter, const real_t dt) :
26+
chem_iter(chem_iter), dt(dt)
2627
{}
2728

2829
BOOST_GPU_ENABLED
@@ -67,7 +68,14 @@ namespace libcloudphxx
6768
O3_react = V * m_O3 / M_O3<real_t>() / V * m_S_IV / M_SO2_H2O<real_t>() / V
6869
/ (real_t(1) + Kt_SO2 / conc_H + Kt_SO2 * Kt_HSO3 / conc_H / conc_H)
6970
* (R_O3_k0 + R_O3_k1 * Kt_SO2 / conc_H + R_O3_k2 * Kt_SO2 * Kt_HSO3 / conc_H / conc_H);
70-
71+
72+
// check if reaction rate won't take more O3 than there is
73+
O3_react = (O3_react * dt * si::seconds < m_O3 / M_O3<real_t>()) ? O3_react :
74+
m_O3 / M_O3<real_t>() / (dt * si::seconds);
75+
// check if reaction rate won't take more S_IV than there is
76+
O3_react = (O3_react * dt * si::seconds < m_S_IV / M_SO2_H2O<real_t>()) ? O3_react :
77+
m_S_IV / M_SO2_H2O<real_t>() / (dt * si::seconds);
78+
7179
// helper for H2O2 reaction
7280
quantity<divide_typeof_helper<si::amount, si::time>::type, real_t>
7381
H2O2_react = V * R_H2O2_k * Kt_SO2
@@ -76,6 +84,13 @@ namespace libcloudphxx
7684
/ (real_t(1) + Kt_SO2 / conc_H + Kt_SO2 * Kt_HSO3 / conc_H / conc_H)
7785
/ (real_t(1) + R_S_H2O2_K<real_t>() * conc_H);
7886

87+
// check if reaction rate won't take more H2O2 than there is
88+
H2O2_react = (H2O2_react * dt * si::seconds < m_H2O2 / M_H2O2<real_t>()) ? H2O2_react :
89+
m_H2O2 / M_H2O2<real_t>() / (dt * si::seconds);
90+
// check if reaction rate won't take more S_IV than there is (this silently gives precedence to O3 reaction)
91+
H2O2_react = (H2O2_react * dt * si::seconds < m_S_IV / M_SO2_H2O<real_t>() - O3_react * dt * si::seconds) ?
92+
H2O2_react : m_S_IV / M_SO2_H2O<real_t>() / (dt * si::seconds) - O3_react;
93+
7994
switch (chem_iter)
8095
{
8196
case SO2:
@@ -104,7 +119,8 @@ namespace libcloudphxx
104119
// functor called by odeint
105120
template <typename real_t>
106121
struct chem_rhs
107-
{
122+
{
123+
const real_t dt;
108124
const thrust_device::vector<real_t> &V;
109125
const thrust_device::vector<unsigned int> &chem_flag;
110126

@@ -119,12 +135,13 @@ namespace libcloudphxx
119135

120136
// ctor
121137
chem_rhs(
138+
const real_t dt,
122139
const thrust_device::vector<real_t> &V,
123140
const pi_t &T,
124141
const typename thrust_device::vector<real_t>::const_iterator &m_H,
125142
const thrust_device::vector<unsigned int> &chem_flag
126143
) :
127-
V(V), T(T), m_H(m_H), n_part(V.size()), chem_flag(chem_flag)
144+
dt(dt), V(V), T(T), m_H(m_H), n_part(V.size()), chem_flag(chem_flag)
128145
{}
129146

130147
void operator()(
@@ -179,7 +196,7 @@ namespace libcloudphxx
179196
// output
180197
dot_psi.begin() + (chem_iter - chem_rhs_beg) * n_part,
181198
// op
182-
chem_rhs_helper<real_t>(chem_iter),
199+
chem_rhs_helper<real_t>(chem_iter, dt),
183200
// condition
184201
thrust::identity<unsigned int>()
185202
);
@@ -259,6 +276,7 @@ namespace libcloudphxx
259276
// do chemical reactions
260277
chem_stepper.do_step(
261278
detail::chem_rhs<real_t>(
279+
dt,
262280
V,
263281
thrust::make_permutation_iterator(T.begin(), ijk.begin()),
264282
chem_bgn[H],

src/particles_pimpl_ctor.ipp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ namespace libcloudphxx
162162
> runge_kutta_fehlberg78 or the bulirsch_stoer with a very high order. But
163163
> should benchmark both steppers and choose the faster one.
164164
*/
165-
boost::numeric::odeint::euler<
165+
boost::numeric::odeint::runge_kutta4<
166166
thrust_device::vector<real_t>, // state_type
167167
real_t, // value_type
168168
thrust_device::vector<real_t>, // deriv_type

src/particles_step.ipp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,21 @@ namespace libcloudphxx
138138
//cleanup - TODO think of something better
139139
pimpl->chem_cleanup();
140140
}
141-
141+
142142
if (opts.chem_dsc)
143143
{ //dissociation
144144
pimpl->chem_dissoc();
145+
146+
//cleanup - TODO think of something better
147+
pimpl->chem_cleanup();
145148
}
146-
149+
147150
if (opts.chem_rct)
148151
{ //oxidation
149152
pimpl->chem_react(pimpl->opts_init.dt / pimpl->opts_init.sstp_chem);
153+
154+
//cleanup - TODO think of something better
155+
pimpl->chem_cleanup();
150156
}
151157
}
152158
}

tests/paper_GMD_2015/src/kin_cloud_2d_lgrngn.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ class kin_cloud_2d_lgrngn : public kin_cloud_2d_common<ct_params_t>
7070
rng_num++;
7171
}
7272
}
73+
{
74+
// rw3(rd)
75+
int rng_num = 0;
76+
for (auto &rng_moms : params.out_dry)
77+
{
78+
auto &rng(rng_moms.first);
79+
prtcls->diag_dry_rng(rng.first / si::metres, rng.second / si::metres);
80+
prtcls->diag_wet_mom(3);
81+
this->record_aux(aux_name("rw3ofrd", rng_num, 3), prtcls->outbuf());
82+
rng_num++;
83+
}
84+
}
7385
}
7486

7587
libcloudphxx::lgrngn::arrinfo_t<real_t> make_arrinfo(

tests/paper_GMD_2015/tests/chem_sandbox/calc_chem.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ int main(int ac, char** av)
1414
{
1515
if (ac != 2) error_macro("expecting one argument - CMAKE_BINARY_DIR");
1616

17-
string bins_wet_str, bins_dry_str;
17+
string bins_wet_str, bins_dry_str, bins_wet_str_2;
1818

1919
{
2020
ostringstream tmp;
@@ -32,31 +32,41 @@ int main(int ac, char** av)
3232
bins_wet_str = tmp.str();
3333
}
3434

35+
{
36+
ostringstream tmp;
37+
vector<quantity<si::length>> left_edges = bins_wet();
38+
for (int i = 0; i < left_edges.size()-1; ++i)
39+
tmp << float(left_edges[i] / si::metres) << ":" << float(left_edges[i + 1] / si::metres) << "|0,3;";
40+
bins_wet_str_2 = tmp.str();
41+
}
42+
43+
3544
for (const string &kernel : {"hall_pinsky_stratocumulus"})
36-
/* {"hall", "hall_davis_no_waals",
45+
/* {"hall", "hall_davis_no_waals",
3746
"onishi_hall", "onishi_hall_davis_no_waals",
3847
"vohl_davis_no_waals",
3948
"hall_pinsky_stratocumulus"
4049
}) */
4150
{
4251

4352
string opts_common =
44-
//"--outfreq=11800 --nt=11800 --spinup=10000 --nx=76 --nz=76 --relax_th_rv=false --rng_seed=44 ";
45-
"--outfreq=200 --nt=11800 --spinup=10000 --nx=76 --nz=76 --relax_th_rv=false --rng_seed=44 ";
53+
//"--outfreq=11800 --dt=1 --nt=11800 --spinup=10000 --nx=76 --nz=76 --relax_th_rv=false --rng_seed=44 ";
54+
"--outfreq=200 --dt=1 --nt=11800 --spinup=10000 --nx=76 --nz=76 --relax_th_rv=false --rng_seed=44 ";
4655
set<string> opts_micro({
47-
"--micro=lgrngn_chem --outdir=out_"+kernel+" --backend=CUDA --adv_serial=False --sd_conc=100 "
56+
"--micro=lgrngn_chem --outdir=out_"+kernel+" --backend=CUDA --adv_serial=False --sd_conc=256 "
4857
"--sstp_cond=10 --coal=True --sedi=True "
4958
"--w_max=.6 "
5059
"--chem_switch=True --chem_dsl=True --chem_dsc=True --chem_rho=1.8e3 --sstp_chem=10 "
5160
//chem_rct switched on afetr spinup in set_chem
5261
"--mean_rd1=0.05e-6 --sdev_rd1=1.8 --n1_stp=50e6 "
5362
"--mean_rd2=0.1e-6 --sdev_rd2=1.5 --n2_stp=0 "
5463
"--kernel="+kernel+" --terminal_velocity=beard77fast "
55-
"--SO2_g_0=.2e-9 --O3_g_0=50e-9 --H2O2_g_0=.5e-9 --CO2_g_0=360e-6 --NH3_g_0=.1e-9 --HNO3_g_0=.1e-9 "
64+
//"--SO2_g_0=.2e-9 --O3_g_0=25e-9 --H2O2_g_0=.4e-9 --CO2_g_0=360e-6 --NH3_g_0=.4e-9 --HNO3_g_0=.1e-9 "
65+
"--SO2_g_0=.2e-9 --O3_g_0=25e-9 --H2O2_g_0=.4e-9 --CO2_g_0=360e-6 --NH3_g_0=.1e-9 --HNO3_g_0=.1e-9 "
5666
" --out_wet=\""
5767
".5e-6:25e-6|0,1,2,3;" // FSSP
5868
"25e-6:1|0,3;" // "rain"
59-
+ bins_wet_str + // aerosol spectrum (wet)
69+
+ bins_wet_str_2 + // aerosol spectrum (wet)
6070
"\""
6171
" --out_dry=\""
6272
"0.:1.|0,1;"
@@ -67,7 +77,7 @@ int main(int ac, char** av)
6777
"\""
6878
" --out_wet_pH=\""
6979
+ bins_wet_str + // spectrum for S_VI and H+ (wet)
70-
"\""
80+
"\""
7181
});
7282

7383
for (auto &opts_m : opts_micro)
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
"""
2+
Plots size distributions from updraft and downdraft
3+
from above cloud base and from below cloud base
4+
"""
5+
import numpy as np
6+
import h5py as h5
7+
import Gnuplot as gp
8+
import math as mt
9+
10+
# all the collision kernels
11+
kernels = {"out_hall_pinsky_stratocumulus"}
12+
13+
ub_cover = {"out_hall_pinsky_stratocumulus" : 0}
14+
ua_cover = {"out_hall_pinsky_stratocumulus" : 0}
15+
db_cover = {"out_hall_pinsky_stratocumulus" : 0}
16+
da_cover = {"out_hall_pinsky_stratocumulus" : 0}
17+
18+
# left and right edges of bins for dry and wet radius
19+
dry_edges = np.fromiter( (1e-6 * 10**(-3 + i * .1) for i in xrange(41)), dtype="float")
20+
wet_edges = np.fromiter( (1e-6 * 10**(-3 + i * .1) for i in xrange(56)), dtype="float")
21+
num_dry = dry_edges.size - 1
22+
num_wet = wet_edges.size - 1
23+
24+
for kernel in kernels:
25+
26+
# helper arrays for storing initial and cutoff dry radii as well as final and cutoff wet radii
27+
n_dry_ub = np.zeros(num_dry)
28+
n_dry_ua = np.zeros(num_dry)
29+
n_dry_db = np.zeros(num_dry)
30+
n_dry_da = np.zeros(num_dry)
31+
32+
n_wet_ub = np.zeros(num_wet)
33+
n_wet_ua = np.zeros(num_wet)
34+
n_wet_db = np.zeros(num_wet)
35+
n_wet_da = np.zeros(num_wet)
36+
37+
for run in {"seed_44"}:
38+
# open hdf5 files with data
39+
h5f_cst = h5.File('data/case_base/' + kernel + '/const.h5', 'r')
40+
h5f_ini = h5.File('data/case_base/' + kernel + '/timestep0000000000.h5', 'r')
41+
h5f_fin = h5.File('data/case_base/' + kernel + '/timestep0000011800.h5', 'r')
42+
43+
x_grid = h5f_cst['X'][:-1][:-1]
44+
y_grid = h5f_cst['Y'][:-1][:-1]
45+
46+
idx_ub = np.where((x_grid > 1 ) & (x_grid < 37) & (y_grid > 15) & (y_grid < 45))
47+
idx_ua = np.where((x_grid > 1 ) & (x_grid < 37) & (y_grid > 45) & (y_grid < 70))
48+
idx_db = np.where((x_grid > 39) & (x_grid < 76) & (y_grid > 15) & (y_grid < 45))
49+
idx_da = np.where((x_grid > 39) & (x_grid < 76) & (y_grid > 45) & (y_grid < 70))
50+
51+
# count dry cloudy and rainy grid cells
52+
ub_cover[kernel] += idx_ub[0].size
53+
ua_cover[kernel] += idx_ua[0].size
54+
db_cover[kernel] += idx_db[0].size
55+
da_cover[kernel] += idx_da[0].size
56+
57+
for i in range(num_dry-1): # first bin id for total conc
58+
name = "rd_rng" + str(i+1).zfill(3) + "_mom0"
59+
tmp_ini = 1e-6 * h5f_ini[name][:]
60+
tmp_fin = 1e-6 * h5f_fin[name][:]
61+
62+
n_dry_ub[i] += tmp_fin[idx_ub].sum() / idx_ub[0].size / (mt.log(dry_edges[i+1], 10) - mt.log(dry_edges[i], 10))
63+
n_dry_ua[i] += tmp_fin[idx_ua].sum() / idx_ua[0].size / (mt.log(dry_edges[i+1], 10) - mt.log(dry_edges[i], 10))
64+
n_dry_db[i] += tmp_fin[idx_db].sum() / idx_db[0].size / (mt.log(dry_edges[i+1], 10) - mt.log(dry_edges[i], 10))
65+
n_dry_da[i] += tmp_fin[idx_da].sum() / idx_da[0].size / (mt.log(dry_edges[i+1], 10) - mt.log(dry_edges[i], 10))
66+
67+
for i in range(num_wet-2): # first two bins are for total cloud and rain water conc
68+
name = "rw_rng" + str(i+2).zfill(3) + "_mom0"
69+
tmp_fin = 1e-6 * h5f_fin[name][:]
70+
71+
n_wet_ub[i] += tmp_fin[idx_ub].sum() / idx_ub[0].size / (mt.log(wet_edges[i+1], 10) - mt.log(wet_edges[i], 10))
72+
n_wet_ua[i] += tmp_fin[idx_ua].sum() / idx_ua[0].size / (mt.log(wet_edges[i+1], 10) - mt.log(wet_edges[i], 10))
73+
n_wet_db[i] += tmp_fin[idx_db].sum() / idx_db[0].size / (mt.log(wet_edges[i+1], 10) - mt.log(wet_edges[i], 10))
74+
n_wet_da[i] += tmp_fin[idx_da].sum() / idx_da[0].size / (mt.log(wet_edges[i+1], 10) - mt.log(wet_edges[i], 10))
75+
76+
# close hdf5 files
77+
h5f_ini.close()
78+
h5f_fin.close()
79+
80+
ub_cover[kernel] = ub_cover[kernel] / 76. / 76 * 100
81+
ua_cover[kernel] = ua_cover[kernel] / 76. / 76 * 100
82+
db_cover[kernel] = db_cover[kernel] / 76. / 76 * 100
83+
da_cover[kernel] = da_cover[kernel] / 76. / 76 * 100
84+
85+
print kernel, " ", ub_cover[kernel]
86+
print kernel, " ", ua_cover[kernel]
87+
print kernel, " ", db_cover[kernel]
88+
print kernel, " ", da_cover[kernel]
89+
90+
# plotting
91+
ymin = 0.001
92+
ymax = 1000
93+
xmin = 0.001
94+
xmax = 5
95+
96+
g = gp.Gnuplot()
97+
g('reset')
98+
g('set term svg dynamic enhanced font "Verdana, 14"')
99+
g('set output "plots/' + kernel + '_aerosol_ud.svg" ')
100+
g('set logscale xy')
101+
g('set key samplen 1.2')
102+
g('set xtics rotate by 65 right (.01, .1, 1, 10, 100)')
103+
g('set ytics (.001, .01, .1, 1, 10, 100, 1000)')
104+
g('set xlabel "particle radius [um]"')
105+
g('set ylabel "dN/dlog_{10}(r) [mg^{-1} per log_{10}(size interval)]"')
106+
g('set xrange [' + str(xmin) + ':' + str(xmax) + ']')
107+
g('set yrange [' + str(ymin) + ':' + str(ymax) + ']')
108+
g('set grid')
109+
g('set nokey')
110+
111+
plot_rd_ub = gp.PlotItems.Data(dry_edges[:-1] * 1e6 , n_dry_ub, with_="steps lw 4 lc rgb 'black'")
112+
plot_rd_ua = gp.PlotItems.Data(dry_edges[:-1] * 1e6 , n_dry_ua, with_="steps lw 4 lc rgb 'green'")
113+
plot_rd_db = gp.PlotItems.Data(dry_edges[:-1] * 1e6 , n_dry_db, with_="steps lw 4 lc rgb 'red'")
114+
plot_rd_da = gp.PlotItems.Data(dry_edges[:-1] * 1e6 , n_dry_da, with_="steps lw 4 lc rgb 'blue'")
115+
116+
g.plot(plot_rd_ub, plot_rd_ua, plot_rd_db, plot_rd_da)
117+
118+
# plotting
119+
ymin = 0.001
120+
ymax = 1000
121+
xmin = 0.001
122+
xmax = 500
123+
124+
g = gp.Gnuplot()
125+
g('reset')
126+
g('set term svg dynamic enhanced font "Verdana, 14"')
127+
g('set output "plots/' + kernel + '_rain_ud.svg" ')
128+
g('set logscale xy')
129+
g('set key samplen 1.2')
130+
g('set xtics rotate by 65 right (.01, .1, 1, 10, 100)')
131+
g('set ytics (.001, .01, .1, 1, 10, 100, 1000)')
132+
g('set xlabel "particle radius [um]"')
133+
g('set ylabel "dN/dlog_{10}(r) [mg^{-1} per log_{10}(size interval)]"')
134+
g('set xrange [' + str(xmin) + ':' + str(xmax) + ']')
135+
g('set yrange [' + str(ymin) + ':' + str(ymax) + ']')
136+
g('set grid')
137+
g('set nokey')
138+
139+
plot_rw_ub = gp.PlotItems.Data(wet_edges[:-1] * 1e6 , n_wet_ub, with_="steps lw 4 lc rgb 'black'")
140+
plot_rw_ua = gp.PlotItems.Data(wet_edges[:-1] * 1e6 , n_wet_ua, with_="steps lw 4 lc rgb 'green'")
141+
plot_rw_db = gp.PlotItems.Data(wet_edges[:-1] * 1e6 , n_wet_db, with_="steps lw 4 lc rgb 'red'")
142+
plot_rw_da = gp.PlotItems.Data(wet_edges[:-1] * 1e6 , n_wet_da, with_="steps lw 4 lc rgb 'blue'")
143+
144+
g.plot(plot_rw_ub, plot_rw_ua, plot_rw_db, plot_rw_da)

0 commit comments

Comments
 (0)