Skip to content

Commit 2f33cbf

Browse files
removal of time-tracking in parcel env. code (in favour of using Particulator's step counter); removal of unneeded fields: formulae and params (#1509)
Co-authored-by: Agnieszka Żaba <azaba@agh.edu.pl>
1 parent cfcd7ab commit 2f33cbf

File tree

4 files changed

+61
-68
lines changed

4 files changed

+61
-68
lines changed

PySDM/environments/parcel.py

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,52 +30,42 @@ def __init__(
3030
mixed_phase=False,
3131
variables: Optional[List[str]] = None,
3232
):
33-
variables = (variables or []) + ["rhod", "z", "t"]
33+
variables = (variables or []) + ["rhod", "z"]
3434
super().__init__(dt, Mesh.mesh_0d(), variables, mixed_phase=mixed_phase)
3535

3636
self.p0 = p0
3737
self.initial_water_vapour_mixing_ratio = initial_water_vapour_mixing_ratio
3838
self.T0 = T0
3939
self.z0 = z0
4040
self.mass_of_dry_air = mass_of_dry_air
41-
4241
self.w = w if callable(w) else lambda _: w
43-
44-
self.formulae = None
4542
self.delta_liquid_water_mixing_ratio = np.nan
46-
self.params = None
4743

4844
@property
4945
def dv(self):
5046
rhod_mean = (self.get_predicted("rhod")[0] + self["rhod"][0]) / 2
51-
return self.formulae.trivia.volume_of_density_mass(
47+
return self.particulator.formulae.trivia.volume_of_density_mass(
5248
rhod_mean, self.mass_of_dry_air
5349
)
5450

5551
def register(self, builder):
56-
self.formulae = builder.particulator.formulae
57-
pd0 = self.formulae.trivia.p_d(self.p0, self.initial_water_vapour_mixing_ratio)
58-
rhod0 = self.formulae.state_variable_triplet.rhod_of_pd_T(pd0, self.T0)
59-
self.mesh.dv = self.formulae.trivia.volume_of_density_mass(
52+
formulae = builder.particulator.formulae
53+
pd0 = formulae.trivia.p_d(self.p0, self.initial_water_vapour_mixing_ratio)
54+
rhod0 = formulae.state_variable_triplet.rhod_of_pd_T(pd0, self.T0)
55+
self.mesh.dv = formulae.trivia.volume_of_density_mass(
6056
rhod0, self.mass_of_dry_air
6157
)
6258

6359
Moist.register(self, builder)
6460

65-
params = (
66-
self.initial_water_vapour_mixing_ratio,
67-
self.formulae.trivia.th_std(pd0, self.T0),
68-
rhod0,
69-
self.z0,
70-
0,
71-
)
72-
self["water_vapour_mixing_ratio"][:] = params[0]
73-
self["thd"][:] = params[1]
74-
self["rhod"][:] = params[2]
75-
self["z"][:] = params[3]
76-
self["t"][:] = params[4]
61+
self["water_vapour_mixing_ratio"][:] = self.initial_water_vapour_mixing_ratio
62+
self["thd"][:] = formulae.trivia.th_std(pd0, self.T0)
63+
self["rhod"][:] = rhod0
64+
self["z"][:] = self.z0
7765

78-
self._tmp["water_vapour_mixing_ratio"][:] = params[0]
66+
self._tmp["water_vapour_mixing_ratio"][
67+
:
68+
] = self.initial_water_vapour_mixing_ratio
7969
self.sync_parcel_vars()
8070
Moist.sync(self)
8171
self.notify()
@@ -94,7 +84,7 @@ def init_attributes(
9484
n_in_dv = np.array([n_in_dv])
9585

9686
attributes = {}
97-
dry_volume = self.formulae.trivia.volume(radius=r_dry)
87+
dry_volume = self.particulator.formulae.trivia.volume(radius=r_dry)
9888
attributes["kappa times dry volume"] = dry_volume * kappa
9989
attributes["multiplicity"] = n_in_dv
10090
r_wet = equilibrate_wet_radii(
@@ -103,43 +93,44 @@ def init_attributes(
10393
kappa_times_dry_volume=attributes["kappa times dry volume"],
10494
rtol=rtol,
10595
)
106-
attributes["volume"] = self.formulae.trivia.volume(radius=r_wet)
96+
attributes["volume"] = self.particulator.formulae.trivia.volume(radius=r_wet)
10797
if include_dry_volume_in_attribute:
10898
attributes["dry volume"] = dry_volume
10999
return attributes
110100

111101
def advance_parcel_vars(self):
102+
"""compute new values of displacement, dry-air density and volume,
103+
and write them to self._tmp and self.mesh.dv"""
112104
dt = self.particulator.dt
105+
formulae = self.particulator.formulae
113106
T = self["T"][0]
114107
p = self["p"][0]
115-
t = self["t"][0]
116108

117-
dz_dt = self.w(t + dt / 2) # "mid-point"
109+
dz_dt = self.w((self.particulator.n_steps + 1 / 2) * dt) # "mid-point"
118110
water_vapour_mixing_ratio = (
119111
self["water_vapour_mixing_ratio"][0]
120112
- self.delta_liquid_water_mixing_ratio / 2
121113
)
122114

123-
# derivate evaluated at p_old, T_old, mixrat_mid, w_mid
124-
drho_dz = self.formulae.hydrostatics.drho_dz(
125-
g=self.formulae.constants.g_std,
115+
# derivative evaluated at p_old, T_old, mixrat_mid, w_mid
116+
drho_dz = formulae.hydrostatics.drho_dz(
117+
g=formulae.constants.g_std,
126118
p=p,
127119
T=T,
128120
water_vapour_mixing_ratio=water_vapour_mixing_ratio,
129-
lv=self.formulae.latent_heat.lv(T),
121+
lv=formulae.latent_heat.lv(T),
130122
d_liquid_water_mixing_ratio__dz=(
131123
self.delta_liquid_water_mixing_ratio / dz_dt / dt
132124
),
133125
)
134-
drhod_dz = drho_dz
126+
drhod_dz = drho_dz # TODO #407
135127

136-
self.particulator.backend.explicit_euler(self._tmp["t"], dt, 1)
137128
self.particulator.backend.explicit_euler(self._tmp["z"], dt, dz_dt)
138129
self.particulator.backend.explicit_euler(
139130
self._tmp["rhod"], dt, dz_dt * drhod_dz
140131
)
141132

142-
self.mesh.dv = self.formulae.trivia.volume_of_density_mass(
133+
self.mesh.dv = formulae.trivia.volume_of_density_mass(
143134
(self._tmp["rhod"][0] + self["rhod"][0]) / 2, self.mass_of_dry_air
144135
)
145136

examples/PySDM_examples/Rozanski_and_Sonntag_1982/figs_4_5_6.ipynb

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -74,29 +74,29 @@
7474
"metadata": {},
7575
"outputs": [],
7676
"source": [
77-
"formulae = Formulae(\n",
77+
"FORMULAE = Formulae(\n",
7878
" isotope_equilibrium_fractionation_factors='HoritaAndWesolowski1994',\n",
7979
" isotope_meteoric_water_line='Dansgaard1964',\n",
8080
" isotope_ratio_evolution='MerlivatAndJouzel1979',\n",
8181
")\n",
82-
"BACKEND = CPU(formulae, override_jit_flags={'parallel': False})\n",
83-
"const = formulae.constants\n",
84-
"trivia = formulae.trivia\n",
82+
"BACKEND = CPU(FORMULAE, override_jit_flags={'parallel': False})\n",
83+
"CONST = FORMULAE.constants\n",
84+
"TRIVIA = FORMULAE.trivia\n",
8585
"\n",
8686
"FIG4_CAPTION_PARAMS = {\n",
87-
" 'T_init': const.T0 + 25 * si.K,\n",
87+
" 'T_init': CONST.T0 + 25 * si.K,\n",
8888
" 'P_init': 1000 * si.mbar,\n",
89-
" 'RH_init': 80 * const.PER_CENT,\n",
89+
" 'RH_init': 80 * CONST.PER_CENT,\n",
9090
" # note: R0 in the caption, but negative, hence delta\n",
91-
" 'delta_2H_init': -74.7 * const.PER_MILLE,\n",
91+
" 'delta_2H_init': -74.7 * CONST.PER_MILLE,\n",
9292
" # the \"K\" parameter\n",
9393
" 'isotope_exchange_factor': 1.,\n",
9494
" # the \"N_L\" parameter, note: mixing ratio in the caption, but per-volume units, hence density; assuming 1 kg/m3\n",
9595
" 'autoconversion_mixrat_threshold': 1 * si.g / si.m**3 / (1 * si.kg / si.m**3)\n",
9696
"}\n",
9797
"\n",
9898
"ARBITRARY_PARAMS = {\n",
99-
" 'delta_18O_init': formulae.isotope_meteoric_water_line.d18O_of_d2H(\n",
99+
" 'delta_18O_init': FORMULAE.isotope_meteoric_water_line.d18O_of_d2H(\n",
100100
" delta_2H=FIG4_CAPTION_PARAMS['delta_2H_init']\n",
101101
" ),\n",
102102
" 'N_SUPER_DROPLETS': 1,\n",
@@ -106,10 +106,10 @@
106106
"}\n",
107107
"ARBITRARY_PARAMS['PARCEL_CTOR_ARGS'] = {\n",
108108
" 'p0': FIG4_CAPTION_PARAMS['P_init'],\n",
109-
" 'initial_water_vapour_mixing_ratio': const.eps / ( # TODO #1207: use a physics formula \n",
109+
" 'initial_water_vapour_mixing_ratio': CONST.eps / ( # TODO #1207: use a physics formula \n",
110110
" FIG4_CAPTION_PARAMS['P_init']\n",
111111
" / FIG4_CAPTION_PARAMS['RH_init']\n",
112-
" / formulae.saturation_vapour_pressure.pvs_water(FIG4_CAPTION_PARAMS['T_init'])\n",
112+
" / FORMULAE.saturation_vapour_pressure.pvs_water(FIG4_CAPTION_PARAMS['T_init'])\n",
113113
" - 1\n",
114114
" ),\n",
115115
" 'T0': FIG4_CAPTION_PARAMS['T_init'],\n",
@@ -162,11 +162,11 @@
162162
" alpha_old = {}\n",
163163
" dRv__dt = {}\n",
164164
" for isotope in self.isotopes:\n",
165-
" alpha_fun = getattr(formulae.isotope_equilibrium_fractionation_factors, f'alpha_l_{isotope}')\n",
165+
" alpha_fun = getattr(self.particulator.formulae.isotope_equilibrium_fractionation_factors, f'alpha_l_{isotope}')\n",
166166
" alpha_old[isotope] = alpha_fun(self[\"T\"][0])\n",
167167
" alpha_new = alpha_fun(self._tmp[\"T\"][0])\n",
168168
" \n",
169-
" dRv__dt[isotope] = self[f'Rv_{isotope}'][0] * self.formulae.isotope_ratio_evolution.d_Rv_over_Rv(\n",
169+
" dRv__dt[isotope] = self[f'Rv_{isotope}'][0] * self.particulator.formulae.isotope_ratio_evolution.d_Rv_over_Rv(\n",
170170
" alpha=alpha_old[isotope],\n",
171171
" d_alpha=(alpha_new - alpha_old[isotope]) / self.dt,\n",
172172
" n_vapour=self['water_vapour_mixing_ratio'][0],\n",
@@ -231,9 +231,9 @@
231231
" builder.add_dynamic(dynamics.Condensation())\n",
232232
"\n",
233233
" for isotope in isotopes:\n",
234-
" builder.particulator.environment[f\"Rv_{isotope}\"][:] = formulae.trivia.isotopic_delta_2_ratio(\n",
234+
" builder.particulator.environment[f\"Rv_{isotope}\"][:] = TRIVIA.isotopic_delta_2_ratio(\n",
235235
" delta=(FIG4_CAPTION_PARAMS if isotope == \"2H\" else ARBITRARY_PARAMS)[f'delta_{isotope}_init'],\n",
236-
" reference_ratio=getattr(const, f\"VSMOW_R_{isotope}\")\n",
236+
" reference_ratio=getattr(CONST, f\"VSMOW_R_{isotope}\")\n",
237237
" )\n",
238238
" \n",
239239
" super().__init__(particulator = builder.build(\n",
@@ -12223,7 +12223,7 @@
1222312223
"PLOT_KEY = 'd'\n",
1222412224
"print(output[PLOT_KEY][0]['Δz'])\n",
1222512225
"\n",
12226-
"temp_C = output[PLOT_KEY][0][\"T\"] - const.T0\n",
12226+
"temp_C = output[PLOT_KEY][0][\"T\"] - CONST.T0\n",
1222712227
"alt_km = in_unit(output[PLOT_KEY][0][\"z\"], si.km) \n",
1222812228
"\n",
1222912229
"fig, axs = pyplot.subplots(2, 4, squeeze=False, sharey=True, figsize=(11.5, 11.5), tight_layout=True)\n",
@@ -12238,7 +12238,7 @@
1223812238
"axs[0,0].yaxis.set_major_locator(ticker.MultipleLocator(5))\n",
1223912239
"\n",
1224012240
"axs[0,0].plot(\n",
12241-
" output[PLOT_KEY][0]['RH'] / const.PER_CENT,\n",
12241+
" output[PLOT_KEY][0]['RH'] / CONST.PER_CENT,\n",
1224212242
" temp_C,\n",
1224312243
" color='purple',\n",
1224412244
" label='RH',\n",
@@ -12277,9 +12277,9 @@
1227712277
" (ARBITRARY_PARAMS['N_ITERATIONS']-1) // ARBITRARY_PARAMS['N_PLOT_PROFILES']\n",
1227812278
" ):\n",
1227912279
" deltas = {\n",
12280-
" iso: formulae.trivia.isotopic_ratio_2_delta(\n",
12280+
" iso: TRIVIA.isotopic_ratio_2_delta(\n",
1228112281
" ratio=output[PLOT_KEY][iteration][f'{ratio}_{iso}'][level_indices['CB']:],\n",
12282-
" reference_ratio=getattr(const, f\"VSMOW_R_{iso}\")\n",
12282+
" reference_ratio=getattr(CONST, f\"VSMOW_R_{iso}\")\n",
1228312283
" ) for iso in ISOTOPES\n",
1228412284
" }\n",
1228512285
" \n",
@@ -12292,15 +12292,15 @@
1229212292
" for ax, iso, color in ((axs[plot_row, 1], '2H', 'green'), (axs[plot_row, 2], \"18O\", 'brown')):\n",
1229312293
" ax.set_title(title)\n",
1229412294
" ax.plot(\n",
12295-
" in_unit(deltas[iso], const.PER_MILLE),\n",
12295+
" in_unit(deltas[iso], CONST.PER_MILLE),\n",
1229612296
" temp_C[level_indices['CB']:],\n",
1229712297
" color=color,\n",
1229812298
" **iter_kwargs\n",
1229912299
" )\n",
1230012300
" axs[plot_row, 3].plot(\n",
1230112301
" in_unit(\n",
12302-
" formulae.isotope_meteoric_water_line.excess_d(delta_2H=deltas[\"2H\"], delta_18O=deltas[\"18O\"]),\n",
12303-
" const.PER_MILLE\n",
12302+
" FORMULAE.isotope_meteoric_water_line.excess_d(delta_2H=deltas[\"2H\"], delta_18O=deltas[\"18O\"]),\n",
12303+
" CONST.PER_MILLE\n",
1230412304
" ),\n",
1230512305
" temp_C[level_indices['CB']:],\n",
1230612306
" color='black',\n",
@@ -14719,19 +14719,19 @@
1471914719
" colors = {'vapour': 'red', 'rain': 'blue'}\n",
1472014720
" linewidth = 1 + .5 * PARAMS_KEYS.index(key)\n",
1472114721
" line_v = axs.plot(\n",
14722-
" in_unit(formulae.trivia.isotopic_ratio_2_delta(\n",
14722+
" in_unit(TRIVIA.isotopic_ratio_2_delta(\n",
1472314723
" ratio=data[key]['CT'][\"Rv_2H\"][1:],\n",
14724-
" reference_ratio=const.VSMOW_R_2H\n",
14725-
" ), const.PER_MILLE),\n",
14724+
" reference_ratio=CONST.VSMOW_R_2H\n",
14725+
" ), CONST.PER_MILLE),\n",
1472614726
" label=f\"vapour at the cloud top ({in_unit(levels['CT'], si.km)} km)\",\n",
1472714727
" color=colors['vapour'],\n",
1472814728
" linewidth=linewidth\n",
1472914729
" )\n",
1473014730
"\n",
14731-
" rain_data = in_unit(formulae.trivia.isotopic_ratio_2_delta(\n",
14731+
" rain_data = in_unit(TRIVIA.isotopic_ratio_2_delta(\n",
1473214732
" ratio=data[key]['CB'][\"Rr_2H\"][1:],\n",
14733-
" reference_ratio=const.VSMOW_R_2H\n",
14734-
" ), const.PER_MILLE)\n",
14733+
" reference_ratio=CONST.VSMOW_R_2H\n",
14734+
" ), CONST.PER_MILLE)\n",
1473514735
" line_r = twinx.plot(\n",
1473614736
" rain_data,\n",
1473714737
" label=f\"rain at the cloud base ({in_unit(levels['CB'], si.km)} km)\",\n",

examples/PySDM_examples/Yang_et_al_2018/simulation.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def __init__(self, settings, backend=CPU):
6969
PySDM_products.ActivatedMeanRadius(
7070
name="r_act", count_activated=True, count_unactivated=False
7171
),
72+
PySDM_products.Time(name="t"),
7273
]
7374

7475
attributes = environment.init_attributes(
@@ -88,7 +89,8 @@ def save(self, output):
8889
volume = _sp.attributes["volume"].to_ndarray()
8990
output["r"].append(self.formulae.trivia.radius(volume=volume))
9091
output["S"].append(_sp.environment["RH"][cell_id] - 1)
91-
for key in ("water_vapour_mixing_ratio", "T", "z", "t"):
92+
output["t"].append(_sp.products["t"].get())
93+
for key in ("water_vapour_mixing_ratio", "T", "z"):
9294
output[key].append(_sp.environment[key][cell_id])
9395
for key in (
9496
"dt_cond_max",

tests/smoke_tests/parcel_d/rozanski_and_sonntag_1982/test_figs_4_5_6.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ class TestFigs456:
2424
@staticmethod
2525
def test_fig_5_vapour_asymptote(variables):
2626
delta_vapour_at_the_cloud_top_per_mille = in_unit(
27-
variables["formulae"].trivia.isotopic_ratio_2_delta(
27+
variables["FORMULAE"].trivia.isotopic_ratio_2_delta(
2828
ratio=variables["data"][variables["PLOT_KEY"]]["CT"]["Rv_2H"][1:],
29-
reference_ratio=variables["const"].VSMOW_R_2H,
29+
reference_ratio=variables["CONST"].VSMOW_R_2H,
3030
),
31-
variables["const"].PER_MILLE,
31+
variables["CONST"].PER_MILLE,
3232
)
3333

3434
d_delta = np.diff(delta_vapour_at_the_cloud_top_per_mille)
@@ -45,11 +45,11 @@ def test_fig_5_vapour_asymptote(variables):
4545
@staticmethod
4646
def test_fig_5_rain_at_the_cloud_base(variables):
4747
delta_rain_at_the_cloud_base_per_mille = in_unit(
48-
variables["formulae"].trivia.isotopic_ratio_2_delta(
48+
variables["FORMULAE"].trivia.isotopic_ratio_2_delta(
4949
ratio=variables["data"][variables["PLOT_KEY"]]["CB"]["Rr_2H"][1:],
50-
reference_ratio=variables["const"].VSMOW_R_2H,
50+
reference_ratio=variables["CONST"].VSMOW_R_2H,
5151
),
52-
variables["const"].PER_MILLE,
52+
variables["CONST"].PER_MILLE,
5353
)
5454

5555
d_delta = np.diff(delta_rain_at_the_cloud_base_per_mille)

0 commit comments

Comments
 (0)