-
Notifications
You must be signed in to change notification settings - Fork 47
Homogeneous freezing example + FIX for mark updated attributes in homogeneous freezing and thaw + expanded unit test of record freezing temperature #1682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
tluettm
wants to merge
39
commits into
open-atmos:main
Choose a base branch
from
tluettm:new_hom_freezing_example
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 6 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
121ed92
added new homogeneous freezing example
tluettm b23b733
expanded freezing temperature unit test, and notebook
tluettm 7f269b1
fix mark_updated calls for freezing
slayoo fc604f9
Merge pull request #3 from slayoo/tim/new_hom_freezing_example
tluettm 22aa786
finished example setup for threshold homogeneous freezing
tluettm 4b56496
expanded hom freezing example
tluettm 0345a1a
Changed plot function
tluettm 2e65c9f
added back freezing temperature histogram plots
tluettm 87cd676
added ensemble of realisations
tluettm 03529b1
draft of a smoke test + avoiding relative imports in the notebook to …
slayoo a53d448
note in the noteboo
slayoo 5215b77
added ensemble for numer of super droplets
tluettm 823cbaf
added vertical updraft ensemble
tluettm 3d53216
Merge remote-tracking branch 'upstream' into new_hom_freezing_example
tluettm e11348e
added updraft ensemble and notebook cleanup
tluettm c8b7d28
added ensemble for ccn concentration / droplet size
tluettm 2403fa3
new unit test for homogeneous nucleation rate and changed saturation …
tluettm b4c49ad
addressing pylint
tluettm 21e4d88
added vapour deposition on ice to notebook example
tluettm 3096742
further tinkering with simulation setups
tluettm 83c6659
work done on the example notebook
tluettm aca1e86
Merge branch 'main' into new_hom_freezing_example
tluettm 90da071
'signed water mass' changes applied to scipy solver. scipy solver too…
tluettm e12ed99
addressing pylint
tluettm 7d8f046
additions to __init__.py
tluettm 2964499
improvements to hom_freezing_example
tluettm 8b46b6a
splitted hom_freezing.ipynb intwo two parts, improvements to simulati…
tluettm 7a56320
precommit check for newly added files
tluettm ac5fc4c
added hom. freezing example with coalescence
tluettm 0a053cb
extended hom. freezing example with coalescence
tluettm 6306564
Added plot names to show_plot()
tluettm 223147b
Refresh notebook
tluettm 40c782e
Update to the plots and (temporary) change to module imports
tluettm 65aad6a
added_new_plot_type
tluettm 0e2acaa
added_new_plot variable
tluettm 9cffb9a
added plots for updraft ensemble
tluettm 6ea8681
updated notebooks
tluettm f66516f
Merge branch 'main' into new_hom_freezing_example
tluettm 843620c
changed dry to wet radius initialisation and added lucky droplet meth…
tluettm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
""" | ||
Homogeneous freezing example | ||
""" | ||
|
||
from .settings import Settings |
293 changes: 293 additions & 0 deletions
293
examples/PySDM_examples/homogeneous_freezing/hom_freezing_cloud_droplets.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
107 changes: 107 additions & 0 deletions
107
examples/PySDM_examples/homogeneous_freezing/settings.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import time | ||
|
||
import numpy as np | ||
from pystrict import strict | ||
|
||
from PySDM import Formulae | ||
from PySDM.physics.constants import si | ||
from PySDM.initialisation.spectra import Lognormal | ||
from PySDM.initialisation.sampling import spectral_sampling | ||
from tests.unit_tests.backends.test_oxidation import formulae | ||
|
||
|
||
class Settings: | ||
def __init__( | ||
self, | ||
*, | ||
n_sd: int, | ||
w_updraft: float, | ||
T0: float, | ||
dt: float, | ||
N_dv_droplet_distribution: float, | ||
r_mean_droplet_distribution: float, | ||
sigma_droplet_distribution: float = None, | ||
type_droplet_distribution: str, | ||
p0: float = 200 * si.hectopascals, | ||
RH_0: float = 1.0, | ||
kappa: float = 0.64, | ||
condensation_enable: bool=True, | ||
deposition_enable: bool=True, | ||
hom_freezing: str=None, | ||
): | ||
|
||
print("Setting up simulation with " + hom_freezing) | ||
self.n_sd = n_sd | ||
self.w_updraft = w_updraft | ||
self.N_dv_droplet_distribution = N_dv_droplet_distribution | ||
self.r_mean_droplet_distribution = r_mean_droplet_distribution | ||
self.sigma_droplet_distribution = sigma_droplet_distribution | ||
self.type_droplet_distribution = type_droplet_distribution | ||
|
||
self.mass_of_dry_air = 1000 * si.kilogram | ||
self.initial_pressure = p0 | ||
self.initial_water_supersaturation = RH_0 | ||
# self.initial_ice_supersaturation = RHi_0 | ||
self.kappa = kappa | ||
self.initial_temperature = T0 | ||
|
||
self.condensation_enable = condensation_enable | ||
self.deposition_enable = deposition_enable | ||
|
||
|
||
|
||
if hom_freezing == "threshold": | ||
hom_nucleation_rate = "Null" | ||
self.hom_freezing_type = "threshold" | ||
else: | ||
hom_nucleation_rate = hom_freezing | ||
self.hom_freezing_type = "time-dependent" | ||
|
||
formulae = Formulae( | ||
particle_shape_and_density="MixedPhaseSpheres", | ||
homogeneous_ice_nucleation_rate=hom_nucleation_rate, | ||
seed=time.time_ns() | ||
) | ||
|
||
self.formulae = formulae | ||
|
||
const = self.formulae.constants | ||
# pvs_i = self.formulae.saturation_vapour_pressure.pvs_ice(self.initial_temperature) | ||
pvs_w = self.formulae.saturation_vapour_pressure.pvs_water( | ||
self.initial_temperature | ||
) | ||
self.initial_water_vapour_mixing_ratio = const.eps / ( | ||
self.initial_pressure / self.initial_water_supersaturation / pvs_w - 1 | ||
) | ||
|
||
dry_air_density = ( | ||
self.formulae.trivia.p_d( | ||
self.initial_pressure, self.initial_water_vapour_mixing_ratio | ||
) | ||
/ self.initial_temperature | ||
/ const.Rd | ||
) | ||
|
||
if self.type_droplet_distribution == ("monodisperse"): | ||
self.r_dry = np.ones(self.n_sd) * r_mean_droplet_distribution | ||
self.specific_concentration = ( | ||
np.ones(self.n_sd) | ||
* N_dv_droplet_distribution | ||
/ self.n_sd | ||
/ dry_air_density | ||
) | ||
|
||
elif self.type_droplet_distribution == ("lognormal"): | ||
spectrum = Lognormal( | ||
norm_factor=N_dv_droplet_distribution / dry_air_density, | ||
m_mode=r_mean_droplet_distribution, | ||
s_geom=sigma_droplet_distribution, | ||
) | ||
|
||
self.r_dry, self.specific_concentration = spectral_sampling.Linear( | ||
spectrum | ||
).sample(n_sd) | ||
|
||
self.t_max_duration = 7200 # 3600 * 1.5 # total duration of simulation | ||
self.dt = dt | ||
self.n_output = 10 # int(self.t_duration / 100) #100 # number of output steps |
174 changes: 174 additions & 0 deletions
174
examples/PySDM_examples/homogeneous_freezing/simulation.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
import numpy as np | ||
|
||
import PySDM.products as PySDM_products | ||
from PySDM.backends import CPU | ||
from PySDM.builder import Builder | ||
from PySDM.dynamics import ( | ||
AmbientThermodynamics, | ||
Condensation, | ||
Freezing, | ||
VapourDepositionOnIce, | ||
) | ||
from PySDM.environments import Parcel | ||
from PySDM.physics import constants as const | ||
from PySDM.initialisation import discretise_multiplicities, equilibrate_wet_radii | ||
|
||
|
||
class Simulation: | ||
def __init__(self, settings, backend=CPU): | ||
|
||
dt = settings.dt | ||
|
||
formulae = settings.formulae | ||
|
||
env = Parcel( | ||
mixed_phase=True, | ||
dt=dt, | ||
mass_of_dry_air=settings.mass_of_dry_air, | ||
p0=settings.initial_pressure, | ||
initial_water_vapour_mixing_ratio=settings.initial_water_vapour_mixing_ratio, | ||
T0=settings.initial_temperature, | ||
w=settings.w_updraft, | ||
) | ||
|
||
builder = Builder( | ||
backend=backend( | ||
formulae=settings.formulae, | ||
**( | ||
{"override_jit_flags": {"parallel": False}} | ||
if backend == CPU | ||
else {} | ||
), | ||
), | ||
n_sd=settings.n_sd, | ||
environment=env, | ||
) | ||
|
||
builder.add_dynamic(AmbientThermodynamics()) | ||
if settings.condensation_enable: | ||
builder.add_dynamic(Condensation()) | ||
if settings.deposition_enable: | ||
builder.add_dynamic(VapourDepositionOnIce()) | ||
builder.add_dynamic( | ||
Freezing( | ||
homogeneous_freezing=settings.hom_freezing_type, immersion_freezing=None | ||
) | ||
) | ||
|
||
self.n_sd = settings.n_sd | ||
self.multiplicities = discretise_multiplicities( | ||
settings.specific_concentration * env.mass_of_dry_air | ||
) | ||
self.r_dry = settings.r_dry | ||
v_dry = settings.formulae.trivia.volume(radius=self.r_dry) | ||
kappa = settings.kappa | ||
|
||
self.r_wet = equilibrate_wet_radii( | ||
r_dry=self.r_dry, | ||
environment=builder.particulator.environment, | ||
kappa_times_dry_volume=kappa * v_dry, | ||
) | ||
attributes = { | ||
"multiplicity": self.multiplicities, | ||
"dry volume": v_dry, | ||
"kappa times dry volume": kappa * v_dry, | ||
"signed water mass": formulae.particle_shape_and_density.radius_to_mass( | ||
self.r_wet | ||
), | ||
} | ||
builder.request_attribute("temperature of last freezing") | ||
|
||
products = [ | ||
PySDM_products.ParcelDisplacement(name="z"), | ||
PySDM_products.Time(name="t"), | ||
PySDM_products.AmbientRelativeHumidity(name="RH", unit="%"), | ||
PySDM_products.AmbientRelativeHumidity(name="RH_ice", unit="%"), | ||
PySDM_products.AmbientTemperature(name="T"), | ||
PySDM_products.AmbientPressure(name="p", unit="hPa"), | ||
PySDM_products.WaterMixingRatio(name="water", radius_range=(0, np.inf)), | ||
PySDM_products.WaterMixingRatio(name="ice", radius_range=(-np.inf, 0)), | ||
PySDM_products.WaterMixingRatio( | ||
name="total", radius_range=(-np.inf, np.inf) | ||
), | ||
PySDM_products.AmbientWaterVapourMixingRatio( | ||
name="vapour", var="water_vapour_mixing_ratio" | ||
), | ||
PySDM_products.ParticleConcentration( | ||
name="n_s", unit="1/cm**3", radius_range=(0, np.inf) | ||
), | ||
PySDM_products.ParticleConcentration( | ||
name="n_i", unit="1/cm**3", radius_range=(-np.inf, 0) | ||
), | ||
PySDM_products.MeanRadius(name="r_s", unit="µm", radius_range=(0, np.inf)), | ||
PySDM_products.MeanRadius(name="r_i", unit="µm", radius_range=(-np.inf, 0)), | ||
] | ||
|
||
self.particulator = builder.build(attributes, products) | ||
|
||
self.n_output = settings.n_output | ||
self.n_substeps = int(self.n_output / dt) | ||
self.t_max_duration = settings.t_max_duration | ||
|
||
def save(self, output): | ||
cell_id = 0 | ||
|
||
output["z"].append(self.particulator.products["z"].get()[cell_id]) | ||
output["t"].append(self.particulator.products["t"].get()) | ||
output["RH"].append(self.particulator.products["RH"].get()[cell_id]) | ||
output["RHi"].append(self.particulator.products["RH_ice"].get()[cell_id]) | ||
output["T"].append(self.particulator.products["T"].get()[cell_id]) | ||
output["P"].append(self.particulator.products["p"].get()[cell_id]) | ||
output["LWC"].append(self.particulator.products["water"].get()[cell_id]) | ||
output["IWC"].append(self.particulator.products["ice"].get()[cell_id]) | ||
# output["TWC"].append(self.particulator.products["total"].get()[cell_id]) | ||
output["qv"].append(self.particulator.products["vapour"].get()[cell_id]) | ||
output["ns"].append(self.particulator.products["n_s"].get()[cell_id]) | ||
output["ni"].append(self.particulator.products["n_i"].get()[cell_id]) | ||
output["rs"].append(self.particulator.products["r_s"].get()[cell_id]) | ||
output["ri"].append(self.particulator.products["r_i"].get()[cell_id]) | ||
output["water_mass"].append( | ||
self.particulator.attributes["signed water mass"].data.tolist() | ||
) | ||
output["T_frz"].append( | ||
self.particulator.attributes["temperature of last freezing"].data.tolist() | ||
) | ||
|
||
def run(self): | ||
|
||
print( "Starting simulation..." ) | ||
|
||
output = { | ||
"t": [], | ||
"z": [], | ||
"RH": [], | ||
"RHi": [], | ||
"T": [], | ||
"P": [], | ||
"LWC": [], | ||
"IWC": [], | ||
"qv": [], | ||
"ns": [], | ||
"ni": [], | ||
"rs": [], | ||
"ri": [], | ||
"water_mass": [], | ||
"T_frz": [], | ||
} | ||
|
||
self.save(output) | ||
|
||
while True: | ||
|
||
self.particulator.run(self.n_substeps) | ||
self.save(output) | ||
|
||
# print( output["t"][-1], output["T"][-1], output["LWC"][-1], output["IWC"][-1] ) | ||
|
||
if output["LWC"][-1] == 0: | ||
print("break due to LWC") | ||
break | ||
if output["t"][-1] >= self.t_max_duration: | ||
print("time exceeded") | ||
break | ||
|
||
return output |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's add a smoke test, e.g. checking the Tfz histograms