Exemple #1
0
def test_event_rates(settings_idx):
    # Arrange
    settings = Settings(w_avg=setups[settings_idx].w_avg,
                        N_STP=setups[settings_idx].N_STP,
                        r_dry=setups[settings_idx].r_dry,
                        mass_of_dry_air=1 * si.kg)
    const = settings.formulae.constants
    settings.n_output = 50
    simulation = Simulation(settings)

    # Act
    output = simulation.run()

    # Assert
    rip = np.asarray(output['ripening_rate'])
    act = np.asarray(output['activating_rate'])
    dea = np.asarray(output['deactivating_rate'])
    act_max = np.full(
        (1, ), settings.n_in_dv / simulation.particulator.dt / const.rho_STP)
    convert_to(act_max, 1 / si.mg)
    assert (rip == 0).all()
    assert (act > 0).any()
    assert (dea > 0).any()
    assert 0 < max(act) < act_max[0]
    assert 0 < max(dea) < act_max[0]
Exemple #2
0
 def __init__(self,
              r_bins,
              initial_spectrum_per_mass_of_dry_air,
              show=True):
     super().__init__(*plt.subplots(1, 1))
     self.ax.set_xlim(np.amin(r_bins), np.amax(r_bins))
     self.ax.set_xlabel("particle radius [μm]")
     self.ax.set_ylabel(
         "specific concentration density [mg$^{-1}$ μm$^{-1}$]")
     self.ax.set_xscale("log")
     self.ax.set_yscale("log")
     self.ax.set_ylim(1, 5e3)
     self.ax.grid(True)
     vals = initial_spectrum_per_mass_of_dry_air.size_distribution(
         r_bins * const.si.um)
     const.convert_to(vals, const.si.mg**-1 / const.si.um)
     self.ax.plot(r_bins, vals, label="spectrum sampled at t=0")
     self.spec_wet = self.ax.step(
         r_bins,
         np.full_like(r_bins, np.nan),
         label="binned super-particle wet sizes",
     )[0]
     self.spec_dry = self.ax.step(
         r_bins,
         np.full_like(r_bins, np.nan),
         label="binned super-particle dry sizes",
     )[0]
     self.ax.legend()
     if show:
         plt.show()
    def get(self):
        vals = np.empty(
            [self.particulator.mesh.n_cell,
             len(self.attr_bins_edges) - 1])
        self.recalculate_spectrum_moment(attr=self.volume_attr,
                                         rank=1,
                                         filter_attr=self.volume_attr)

        for i in range(vals.shape[1]):
            self.download_spectrum_moment_to_buffer(rank=0, bin_number=i)
            vals[:, i] = self.buffer.ravel()

        if self.normalise_by_dv:
            vals[:] /= self.particulator.mesh.dv

        self.download_to_buffer(self.particulator.environment['rhod'])
        rhod = self.buffer.ravel()
        for i in range(len(self.attr_bins_edges) - 1):
            dr = self.formulae.trivia.radius(volume=self.attr_bins_edges[i + 1]) - \
                 self.formulae.trivia.radius(volume=self.attr_bins_edges[i])
            vals[:, i] /= rhod * dr

        const.convert_to(vals,
                         const.si.micrometre**-1 * const.si.milligram**-1)

        return np.squeeze(vals.reshape(self.shape))
Exemple #4
0
 def get(self):
     self.download_moment_to_buffer('volume', rank=0,
                                    filter_range=(self.formulae.trivia.volume(self.radius_range[0]),
                                                  self.formulae.trivia.volume(self.radius_range[1])))
     self.buffer[:] /= self.core.mesh.dv
     const.convert_to(self.buffer, const.si.centimetre**-3)
     return self.buffer
Exemple #5
0
 def get(self):
     self.download_moment_to_buffer(
         'volume',
         rank=0,
         attr_range=[0, phys.volume(self.radius_threshold)])
     self.buffer[:] /= self.particles.mesh.dv
     const.convert_to(self.buffer, const.si.centimetre**-3)
     return self.buffer
Exemple #6
0
 def get(self):
     self.download_moment_to_buffer('volume', rank=0)
     result = self.buffer.copy()  # TODO #217
     self.download_to_buffer(self.core.environment['rhod'])
     result[:] /= self.core.mesh.dv
     result[:] /= self.buffer
     const.convert_to(result, const.si.milligram**-1)
     return result
Exemple #7
0
    def get(self) -> float:
        if self.elapsed_time == 0.:
            return 0.

        result = rho_w * self.accumulated_rainfall / self.elapsed_time / (self.dv / self.dz)
        self._reset_counters()
        convert_to(result, si.mm / si.day)
        return result
Exemple #8
0
 def get(self):
     self.download_moment_to_buffer('volume', rank=0,
                                    filter_range=[0, phys.volume(self.radius_threshold)])
     result = self.buffer.copy()  # TODO
     self.download_to_buffer(self.core.environment['rhod'])
     result[:] /= self.core.mesh.dv
     result[:] /= self.buffer
     const.convert_to(result, const.si.milligram**-1)
     return result
Exemple #9
0
 def get(self):
     self.download_moment_to_buffer('dry volume', rank=1)
     self.buffer[:] *= self.density
     result = np.copy(self.buffer)
     self.download_moment_to_buffer('dry volume', rank=0)
     result[:] *= self.buffer
     self.download_to_buffer(self.core.environment['rhod'])
     result[:] /= self.core.mesh.dv
     result[:] /= self.buffer
     convert_to(result, si.ug / si.kg)
     return result
Exemple #10
0
 def get(self):
     tmp = np.empty_like(self.buffer)
     self.download_moment_to_buffer('volume', rank=2/3,
                                    filter_range=(self.formulae.trivia.volume(self.radius_range[0]),
                                                  self.formulae.trivia.volume(self.radius_range[1])))
     tmp[:] = self.buffer[:]
     self.download_moment_to_buffer('volume', rank=1,
                                    filter_range=(self.formulae.trivia.volume(self.radius_range[0]),
                                                  self.formulae.trivia.volume(self.radius_range[1])))
     CloudDropletEffectiveRadius.__get_impl(self.buffer, tmp)
     const.convert_to(self.buffer, const.si.micrometre)
     return self.buffer
Exemple #11
0
 def get(self):
     if self.timestep_count == 0:
         return self.event_count
     else:
         self.event_count[:] /= (self.timestep_count * self.particulator.dt * self.particulator.mesh.dv)
         self.download_to_buffer(self.particulator.environment['rhod'])
         self.event_count[:] /= self.buffer[:]
         self.buffer[:] = self.event_count[:]
         self.timestep_count = 0
         self.event_count[:] = 0
         convert_to(self.buffer, 1/si.mg)
         return self.buffer
Exemple #12
0
 def get(self):
     self.download_moment_to_buffer('volume', rank=0,
                                    filter_range=(self.formulae.trivia.volume(self.radius_range[0]),
                                                  self.formulae.trivia.volume(self.radius_range[1])))
     self.buffer[:] /= self.particulator.mesh.dv
     if self.specific:
         result = self.buffer.copy()  # TODO #217
         self.download_to_buffer(self.particulator.environment['rhod'])
         result[:] /= self.buffer
     else:
         result = self.buffer
     const.convert_to(result, const.si.mg**-1 if self.specific else const.si.centimetre**-3)
     return result
Exemple #13
0
    def test_at_t_0():
        # Arrange
        settings = Settings(n_sd=100, dt=1 * si.s, n_substep=5)
        settings.t_max = 0
        simulation = Simulation(settings)
        specific_gravities = SpecificGravities(
            simulation.particulator.formulae.constants)

        # Act
        output = simulation.run()

        # Assert
        np.testing.assert_allclose(output['RH'][0], 95)
        np.testing.assert_allclose(output['gas_S_IV_ppb'][0], 0.2)
        np.testing.assert_allclose(output['gas_N_mIII_ppb'][0], 0.1)
        np.testing.assert_allclose(output['gas_H2O2_ppb'], 0.5)
        np.testing.assert_allclose(output['gas_N_V_ppb'], 0.1)
        np.testing.assert_allclose(output['gas_O3_ppb'], 50)
        np.testing.assert_allclose(output['gas_C_IV_ppb'], 360 * 1000)

        rtol = 0.15

        mass_conc_SO4mm = 2
        mass_conc_NH4p = 0.375
        num_conc_SO4mm = mass_conc_SO4mm / Substance.from_formula(
            "SO4").mass * si.gram / si.mole
        num_conc_NH4p = mass_conc_NH4p / Substance.from_formula(
            "NH4").mass * si.gram / si.mole
        np.testing.assert_allclose(num_conc_NH4p, num_conc_SO4mm, rtol=.005)
        mass_conc_H = num_conc_NH4p * Substance.from_formula(
            "H").mass * si.gram / si.mole
        np.testing.assert_allclose(
            actual=np.asarray(output['q_dry']) * np.asarray(output['rhod']),
            desired=mass_conc_NH4p + mass_conc_SO4mm + mass_conc_H,
            rtol=rtol)

        expected = {k: 0 for k in AQUEOUS_COMPOUNDS}
        expected['S_VI'] = mass_conc_SO4mm * si.ug / si.m**3
        expected['N_mIII'] = mass_conc_NH4p * si.ug / si.m**3

        for key in expected:
            mole_fraction = np.asarray(output[f"aq_{key}_ppb"])
            convert_to(mole_fraction, 1 / PPB)
            compound = AQUEOUS_COMPOUNDS[key][0]  # sic!
            np.testing.assert_allclose(
                actual=(settings.formulae.trivia.mole_fraction_2_mixing_ratio(
                    mole_fraction,
                    specific_gravity=specific_gravities[compound]) *
                        np.asarray(output['rhod'])),
                desired=expected[key],
                rtol=rtol)
 def get(self):
     self.download_moment_to_buffer('volume',
                                    rank=0,
                                    filter_range=[
                                        0,
                                        self.formulae.trivia.volume(
                                            self.radius_threshold)
                                    ])
     result = self.buffer.copy()  # TODO #217
     self.download_to_buffer(self.particulator.environment['rhod'])
     result[:] /= self.particulator.mesh.dv
     result[:] /= self.buffer
     const.convert_to(result, const.si.milligram**-1)
     return result
Exemple #15
0
    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()
Exemple #16
0
    def get(self):
        vals = np.empty([self.core.mesh.n_cell, len(self.attr_bins_edges) - 1])
        self.recalculate_spectrum_moment(attr=f'moles_{self.key}',
                                         rank=1,
                                         filter_attr='dry volume')

        for i in range(vals.shape[1]):
            self.download_spectrum_moment_to_buffer(rank=1, bin_number=i)
            vals[:, i] = self.buffer.ravel()
            self.download_spectrum_moment_to_buffer(rank=0, bin_number=i)
            vals[:, i] *= self.buffer.ravel()

        vals *= self.molar_mass / np.diff(
            np.log10(2 * self.dry_radius_bins_edges)) / self.core.mesh.dv
        convert_to(vals, si.ug)

        if self.specific:
            self.download_to_buffer(self.core.environment['rhod'])
            vals[:] /= self.buffer
        return vals
Exemple #17
0
    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 get(self):
        vals = np.empty(
            [self.particulator.mesh.n_cell,
             len(self.attr_bins_edges) - 1])
        self.recalculate_spectrum_moment(attr='volume',
                                         filter_attr='freezing temperature',
                                         rank=0)

        for i in range(vals.shape[1]):
            self.download_spectrum_moment_to_buffer(rank=0, bin_number=i)
            vals[:, i] = self.buffer.ravel()

        self.download_to_buffer(self.particulator.environment['rhod'])
        rhod = self.buffer.ravel()
        for i in range(len(self.attr_bins_edges) - 1):
            dT = abs(self.attr_bins_edges[i + 1] - self.attr_bins_edges[i])
            vals[:, i] /= rhod * dT * self.particulator.mesh.dv

        const.convert_to(vals, const.si.milligram**-1 / const.si.K)

        return np.squeeze(vals.reshape(self.shape))
 def get(self):
     volume_bins_edges = self.formulae.trivia.volume(
         self.dry_radius_bins_edges)
     vals = np.empty(len(volume_bins_edges) - 1)
     for i in range(len(vals)):
         self.download_moment_to_buffer(
             attr=f'moles_{self.key}',
             rank=1,
             filter_attr='dry volume',
             filter_range=(volume_bins_edges[i], volume_bins_edges[i + 1]))
         vals[i] = self.buffer[0]
         self.download_moment_to_buffer(
             attr='volume',
             rank=0,
             filter_attr='dry volume',
             filter_range=(volume_bins_edges[i], volume_bins_edges[i + 1]))
         vals[i] *= self.buffer[0]
     vals *= self.molar_mass / np.diff(
         np.log10(2 * self.dry_radius_bins_edges)) / self.core.mesh.dv
     convert_to(vals, si.ug)
     return vals
Exemple #20
0
def plot(var, qlabel, fname, output, vmin=None, vmax=None, line=None):
    line = line or {15: ":", 20: "--", 25: "-", 30: "-."}
    dt = output["t"][1] - output["t"][0]
    dz = output["z"][1] - output["z"][0]
    tgrid = np.concatenate(((output["t"][0] - dt / 2, ), output["t"] + dt / 2))
    zgrid = np.concatenate(((output["z"][0] - dz / 2, ), output["z"] + dz / 2))
    convert_to(zgrid, si.km)

    fig = pyplot.figure(constrained_layout=True)
    gs = fig.add_gridspec(25, 5)
    ax1 = fig.add_subplot(gs[:-1, 0:4])
    mesh = ax1.pcolormesh(tgrid, zgrid, output[var], cmap="twilight")

    ax1.set_xlabel("time [s]")
    ax1.set_ylabel("z [km]")
    ax1.set_ylim(0, None)

    cbar = fig.colorbar(mesh, fraction=0.05, location="top")
    cbar.set_label(qlabel)

    ax2 = fig.add_subplot(gs[:-1, 4:], sharey=ax1)
    ax2.set_xlabel(qlabel)
    # ax2.set_yticks([], minor=False)

    last_t = 0
    for i, t in enumerate(output["t"]):
        x, z = output[var][:, i], output["z"].copy()
        convert_to(z, si.km)
        params = {"color": "black"}
        for line_t, line_s in line.items():
            if last_t < line_t * si.min <= t:
                params["ls"] = line_s
                ax2.plot(x, z, **params)
                if vmin is not None and vmax is not None:
                    ax1.axvline(t, ymin=vmin, ymax=vmax, **params)
                else:
                    ax1.axvline(t, **params)
        last_t = t

    show_plot(filename=fname, inline_format="png")
 def get(self, unit=const.si.micrometre):
     self.download_moment_to_buffer('volume', rank=1 / 3)
     self.buffer[:] /= const.pi_4_3**(1 / 3)
     const.convert_to(self.buffer, unit)
     return self.buffer
Exemple #22
0
 def get(self):
     self.download_to_buffer(self.environment['qv'])
     const.convert_to(self.buffer, const.si.gram / const.si.kilogram)
     return self.buffer
Exemple #23
0
    def reinit(self, products):
        self.products = products
        self.product_select.options = tuple(
            (f"{val.name} [{val.unit}]", key)
            for key, val in sorted(self.products.items(),
                                   key=lambda item: item[1].name)
            if len(val.shape) == 2)
        opts = [
            ("particle size spectra", "size"),
            ("terminal velocity", "terminal velocity"),
        ]
        if "freezable specific concentration" in products:
            opts.append(("freezing temperature spectra", "temperature"))
        if "immersed surface area" in products:
            pass  # TODO #599
        self.spectrum_select.options = tuple(opts)

        r_bins = self.settings.r_bins_edges.copy()
        const.convert_to(r_bins, const.si.micrometres)
        self.spectrumOutputs = {}
        self.spectrumPlots = {}
        for key in ("size", "terminal velocity", "temperature"):
            self.spectrumOutputs[key] = Output()
            with self.spectrumOutputs[key]:
                self.spectrumPlots[key] = (
                    _SpectrumPlot(r_bins,
                                  self.settings.spectrum_per_mass_of_dry_air)
                    if key == "size" else _TemperaturePlot(
                        self.settings.T_bins_edges, self.settings.formulae)
                    if key == "temperature" else _TerminalVelocityPlot(
                        self.settings.terminal_velocity_radius_bin_edges,
                        self.settings.formulae,
                    ))
                clear_output()

        self.timeseriesOutput = Output()
        with self.timeseriesOutput:
            default_figsize = rcParams["figure.figsize"]
            fig_kw = {
                "figsize": (2.5 * default_figsize[0], default_figsize[1] / 2)
            }
            fig, ax = pyplot.subplots(1, 1, **fig_kw)
            self.timeseriesPlot = _TimeseriesPlot(
                fig, ax, self.settings.output_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()
        self.spectrum_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, self.product_select),
                        ),
                        HBox((self.slider["Z"], self.plot_box)),
                        HBox((self.slider["X"], ), layout=layout_flex_end),
                    )),
                    VBox(
                        layout=Layout(),
                        children=(
                            Box(
                                children=(save_spe, self.spectrum_select),
                                layout=layout_flex_end,
                            ),
                            self.spectrum_box,
                        ),
                    ),
                )),
                HBox((self.timeseriesOutput, )),
            )), )

        for widget in (self.step_slider, self.play):
            widget.value = 0
            widget.max = len(self.settings.output_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()
Exemple #24
0
 def get(self):
     super().get()
     const.convert_to(self.buffer, const.si.gram / const.si.kilogram)
     return self.buffer
Exemple #25
0
 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 get(self):
     self.download_moment_to_buffer('volume', rank=0)
     self.buffer[:] /= self.particles.mesh.dv
     const.convert_to(self.buffer, const.si.centimetre**-3)
     return self.buffer
Exemple #27
0
    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()