def test_wet_vs_dry_spectrum(plot=False): # Arrange setup = Setup() # Act simulation = Simulation(setup) wet_volume = simulation.particles.state['volume'] wet_volume = simulation.particles.backend.to_ndarray(wet_volume) r_wet = phys.radius(volume=wet_volume) / si.nanometre n = simulation.particles.backend.to_ndarray( simulation.particles.state['n']) dry_volume = simulation.particles.state['dry volume'] dry_volume = simulation.particles.backend.to_ndarray(dry_volume) r_dry = phys.radius(volume=dry_volume) / si.nanometre # Plot if plot: plt.plot(r_wet, n) plt.plot(r_dry, n) plt.xscale('log') plt.yscale('log') plt.show() # Assert assert (r_dry < r_wet).all()
def test_dry_spectrum_y(plot=False): setup = Setup() simulation = Simulation(setup) dry_volume = simulation.particles.state['dry volume'] dry_volume = simulation.particles.backend.to_ndarray(dry_volume) rd = phys.radius(volume=dry_volume) / si.nanometre nd = simulation.particles.backend.to_ndarray( simulation.particles.state['n']) dr = (rd[1:] - rd[0:-1]) env = simulation.particles.environment dn_dr = (nd[0:-1] / env.mass_of_dry_air * env["rhod"] / dr) dn_dr /= (1 / si.centimetre**3) if plot: plt.figure(figsize=(5, 5)) plt.xscale('log') plt.yscale('log') plt.xlim(1e1, 1e3) plt.ylim(1e-9, 1e3) plt.yticks(10.**np.arange(-8, 3, step=2)) plt.plot(rd[0:-1], dn_dr) plt.show() # from fig. 1b assert 1e-3 < dn_dr[0] < 1e-2 assert 1e1 < max(dn_dr) < 1e2 assert 0 < dn_dr[-1] < 1e-9
def impl(dy_dt, x, T, p, n, RH, kappa, rd, thd, dot_thd, dot_qv, m_d_mean, rhod_mean): for i in range(len(x)): dy_dt[idx_x + i] = dx_dt( x[i], phys.dr_dt_MM(phys.radius(volume(x[i])), T, p, RH, kappa, rd[i])) dqv_dt = dot_qv - np.sum( n * volume(x) * dy_dt[idx_x:]) * rho_w / m_d_mean dy_dt[idx_thd] = dot_thd + phys.dthd_dt(rhod_mean, thd, T, dqv_dt)
def __init__(self, kappa, dry_volume: np.ndarray, n: np.ndarray, dthd_dt, dqv_dt, m_d_mean, rhod_mean, qt): self.kappa = kappa self.rd = phys.radius(volume=dry_volume) self.n = n self.dqv_dt = dqv_dt self.dthd_dt = dthd_dt self.rhod_mean = rhod_mean self.m_d_mean = m_d_mean self.qt = qt
def get(self): vals = np.empty([self.core.mesh.n_cell, len(self.v_bins) - 1]) for i in range(len(self.v_bins) - 1): self.download_moment_to_buffer( attr=self.volume_attr, rank=0, filter_attr=self.volume_attr, filter_range=(self.v_bins[i], self.v_bins[i + 1]) ) vals[:, i] = self.buffer.ravel() if self.normalise_by_dv: vals[:] /= self.core.mesh.dv self.download_to_buffer(self.core.environment['rhod']) rhod = self.buffer.ravel() for i in range(len(self.v_bins) - 1): dr = phys.radius(volume=self.v_bins[i + 1]) - phys.radius(volume=self.v_bins[i]) vals[:, i] /= rhod * dr const.convert_to(vals, const.si.micrometre**-1 * const.si.milligram**-1) return np.squeeze(vals.reshape(self.shape))
def test_dry_spectrum_x(): settings = Settings() simulation = Simulation(settings) dry_volume = simulation.core.particles['dry volume'].to_ndarray() rd = phys.radius(volume=dry_volume) / si.nanometre rd = rd[::-1] assert round(rd[1 - 1], 0) == 503 assert round(rd[10 - 1], 0) == 355 assert round(rd[50 - 1], 1) == 75.3 assert round(rd[100 - 1], 1) == 10.8
def test_dry_spectrum_x(): setup = Setup() simulation = Simulation(setup) dry_volume = simulation.particles.state['dry volume'] dry_volume = simulation.particles.backend.to_ndarray(dry_volume) rd = phys.radius(volume=dry_volume) / si.nanometre rd = rd[::-1] assert round(rd[1 - 1], 0) == 503 assert round(rd[10 - 1], 0) == 355 assert round(rd[50 - 1], 1) == 75.3 assert round(rd[100 - 1], 1) == 10.8
def test_wet_vs_dry_spectrum(plot=False): # Arrange settings = Settings() # Act simulation = Simulation(settings) wet_volume = simulation.core.particles['volume'].to_ndarray() r_wet = phys.radius(volume=wet_volume) / si.nanometre n = simulation.core.particles['n'].to_ndarray() dry_volume = simulation.core.particles['dry volume'].to_ndarray() r_dry = phys.radius(volume=dry_volume) / si.nanometre # Plot if plot: plt.plot(r_wet, n) plt.plot(r_dry, n) plt.xscale('log') plt.yscale('log') plt.show() # Assert assert (r_dry < r_wet).all()
def reinit(self, products): self.products = products self.product_select.options = [(f"{val.description} [{val.unit}]", key) for key, val in products.items() if len(val.shape) == 2] r_bins = phys.radius(volume=self.setup.v_bins) const.convert_to(r_bins, const.si.micrometres) self.spectrumOutput = Output() with self.spectrumOutput: self.spectrumPlot = _SpectrumPlot(r_bins) clear_output() self.plots = {} self.outputs = {} for key, product in products.items(): if len(product.shape) == 2: self.outputs[key] = Output() with self.outputs[key]: self.plots[key] = _ImagePlot(self.setup.grid, self.setup.size, product) clear_output() self.plot_box = Box() if len(products.keys()) > 0: layout_flex_end = Layout(display='flex', justify_content='flex-end') save_map = Button(icon='save') save_map.on_click(self.handle_save_map) save_spe = Button(icon='save') save_spe.on_click(self.handle_save_spe) self.plots_box.children = (HBox(children=( VBox(children=( Box(layout=layout_flex_end, children=(save_map, )), HBox((self.slider['Z'], self.plot_box)), HBox((self.slider['X'], ), layout=layout_flex_end))), VBox(layout=Layout(), children=(save_spe, self.spectrumOutput)))), ) for widget in (self.step_slider, self.play): widget.value = 0 widget.max = len(self.setup.steps) - 1 for j, xz in enumerate(('X', 'Z')): slider = self.slider[xz] mx = self.setup.grid[j] slider.max = mx slider.value = (0, mx) self.replot()
def save(self, output): cell_id = 0 output["r_bins_values"].append( self.particles.products["Particles Wet Size Spectrum"].get()) volume = self.particles.state['volume'].to_ndarray() output["r"].append(phys.radius(volume=volume)) output["S"].append(self.particles.environment["RH"][cell_id] - 1) output["qv"].append(self.particles.environment["qv"][cell_id]) output["T"].append(self.particles.environment["T"][cell_id]) output["z"].append(self.particles.environment["z"][cell_id]) output["t"].append(self.particles.environment["t"][cell_id]) output["dt_cond_max"].append( self.particles.products["dt_cond"].get_max().copy()) output["dt_cond_min"].append( self.particles.products["dt_cond"].get_min().copy()) self.particles.products["dt_cond"].reset() output['ripening_rate'].append( self.particles.products['ripening_rate'].get()[cell_id].copy())
def test_initialisation(plot=False): # TODO: seed as a part of setup? setup = Setup() setup.n_steps = -1 setup.grid = (10, 5) setup.n_sd_per_gridbox = 2000 simulation = Simulation(setup, None) n_bins = 32 n_levels = setup.grid[1] n_cell = np.prod(np.array(setup.grid)) n_moments = 1 v_bins = np.logspace((np.log10(phys.volume(radius=setup.r_min))), (np.log10(phys.volume(radius=10 * setup.r_max))), num=n_bins, endpoint=True) r_bins = phys.radius(volume=v_bins) histogram_dry = np.empty((len(r_bins) - 1, n_levels)) histogram_wet = np.empty_like(histogram_dry) moment_0 = setup.backend.array(n_cell, dtype=int) moments = setup.backend.array((n_moments, n_cell), dtype=float) tmp = np.empty(n_cell) simulation.reinit() # Act (moments) simulation.run() particles = simulation.particles environment = simulation.particles.environment rhod = setup.backend.to_ndarray(environment["rhod"]).reshape( setup.grid).mean(axis=0) for i in range(len(histogram_dry)): particles.state.moments(moment_0, moments, specs={}, attr_name='dry volume', attr_range=(v_bins[i], v_bins[i + 1])) particles.backend.download(moment_0, tmp) histogram_dry[i, :] = tmp.reshape( setup.grid).sum(axis=0) / (particles.mesh.dv * setup.grid[0]) particles.state.moments(moment_0, moments, specs={}, attr_name='volume', attr_range=(v_bins[i], v_bins[i + 1])) particles.backend.download(moment_0, tmp) histogram_wet[i, :] = tmp.reshape( setup.grid).sum(axis=0) / (particles.mesh.dv * setup.grid[0]) # Plot if plot: for level in range(0, n_levels): color = str(.5 * (2 + (level / (n_levels - 1)))) pyplot.step(r_bins[:-1] * si.metres / si.micrometres, histogram_dry[:, level] / si.metre**3 * si.centimetre**3, where='post', color=color, label="level " + str(level)) pyplot.step(r_bins[:-1] * si.metres / si.micrometres, histogram_wet[:, level] / si.metre**3 * si.centimetre**3, where='post', color=color, linestyle='--') pyplot.grid() pyplot.xscale('log') pyplot.xlabel('particle radius [µm]') pyplot.ylabel('concentration per bin [cm^{-3}]') pyplot.legend() pyplot.show() # Assert - location of maximum for level in range(n_levels): real_max = setup.spectrum_per_mass_of_dry_air.distribution_params[2] idx_max_dry = np.argmax(histogram_dry[:, level]) idx_max_wet = np.argmax(histogram_wet[:, level]) assert r_bins[idx_max_dry] < real_max < r_bins[idx_max_dry + 1] assert idx_max_dry < idx_max_wet # Assert - total number for level in reversed(range(n_levels)): mass_conc_dry = np.sum(histogram_dry[:, level]) / rhod[level] mass_conc_wet = np.sum(histogram_wet[:, level]) / rhod[level] mass_conc_STP = setup.spectrum_per_mass_of_dry_air.norm_factor assert .5 * mass_conc_STP < mass_conc_dry < 1.5 * mass_conc_STP np.testing.assert_approx_equal(mass_conc_dry, mass_conc_wet) # Assert - decreasing number density total_above = 0 for level in reversed(range(n_levels)): total_below = np.sum(histogram_dry[:, level]) assert total_below > total_above total_above = total_below
def get(self, unit=const.si.micrometre): self.download_moment_to_buffer('volume', rank=1 / 3) self.buffer[:] *= phys.radius(volume=1) const.convert_to(self.buffer, unit) return self.buffer
def reinit(self, products): self.products = products self.product_select.options = [(f"{val.description} [{val.unit}]", key) for key, val in products.items() if len(val.shape) == 2] r_bins = phys.radius(volume=self.settings.v_bins) const.convert_to(r_bins, const.si.micrometres) self.spectrumOutput = Output() with self.spectrumOutput: self.spectrumPlot = _SpectrumPlot(r_bins) clear_output() self.timeseriesOutput = Output() with self.timeseriesOutput: default_figsize = rcParams["figure.figsize"] fig_kw = { 'figsize': (2.25 * default_figsize[0], default_figsize[1] / 2) } fig, ax = pyplot.subplots(1, 1, **fig_kw) self.timeseriesPlot = _TimeseriesPlot( fig, ax, self.settings.steps * self.settings.dt) clear_output() self.plots = {} self.outputs = {} for key, product in products.items(): if len(product.shape) == 2: self.outputs[key] = Output() with self.outputs[key]: fig, ax = pyplot.subplots(1, 1) self.plots[key] = _ImagePlot(fig, ax, self.settings.grid, self.settings.size, product, show=True, lines=True) clear_output() self.plot_box = Box() if len(products.keys()) > 0: layout_flex_end = Layout(display='flex', justify_content='flex-end') save_map = Button(icon='save') save_map.on_click(self.handle_save_map) save_spe = Button(icon='save') save_spe.on_click(self.handle_save_spe) self.plots_box.children = (VBox(children=(HBox(children=( VBox(children=( Box(layout=layout_flex_end, children=(save_map, )), HBox((self.slider['Z'], self.plot_box)), HBox((self.slider['X'], ), layout=layout_flex_end))), VBox(layout=Layout(), children=(save_spe, self.spectrumOutput)) )), HBox((self.timeseriesOutput, )))), ) for widget in (self.step_slider, self.play): widget.value = 0 widget.max = len(self.settings.steps) - 1 for j, xz in enumerate(('X', 'Z')): slider = self.slider[xz] mx = self.settings.grid[j] slider.max = mx slider.value = (0, mx) self.replot()