示例#1
0
def main():
    settings = Settings()

    settings.n_sd_per_gridbox = 25
    settings.grid = (25, 25)
    settings.simulation_time = 5400 * si.second

    storage = Storage()
    simulation = Simulation(settings, storage)
    simulation.reinit()
    simulation.run()
    temp_file = TemporaryFile('.nc')
    exporter = NetCDFExporter(storage, settings, simulation, temp_file.absolute_path)
    exporter.run()
示例#2
0
def test_export(tmp_path):
    # Arrange
    settings = Settings()
    settings.simulation_time = settings.dt
    settings.output_interval = settings.dt

    storage = Storage()
    simulator = Simulation(settings, storage)
    _, temp_file = tempfile.mkstemp(dir=tmp_path, suffix='.nc')
    sut = NetCDFExporter(storage, settings, simulator, temp_file)

    simulator.reinit()
    simulator.run()

    # Act
    sut.run()
示例#3
0
def test_spin_up(fastmath, plot=False):
    # Arrange
    settings = Settings(fastmath=fastmath)
    settings.dt = .5 * si.second
    settings.grid = (3, 25)
    settings.simulation_time = 20 * settings.dt
    settings.output_interval = 1 * settings.dt

    storage = DummyStorage()
    simulation = Simulation(settings, storage)
    simulation.reinit()

    # Act
    simulation.run()

    # Plot
    if plot:
        levels = np.arange(settings.grid[1])
        for step, datum in enumerate(storage.profiles):
            pyplot.plot(datum["qv_env"], levels, label=str(step))
        pyplot.legend()
        pyplot.show()

    # Assert
    step_num = len(storage.profiles) - 1
    for step in range(step_num):
        next = storage.profiles[step + 1]["qv_env"]
        prev = storage.profiles[step]["qv_env"]
        eps = 1e-3
        assert ((prev + eps) >= next).all()
    assert storage.profiles[step_num]["qv_env"][-1] < 7.
示例#4
0
def test_environment():
    # Arrange
    settings = Settings()
    settings.simulation_time = -1 * settings.dt
    simulation = Simulation(settings, None)
    simulation.reinit()

    # Act
    simulation.run()
    rhod = simulation.core.environment["rhod"].to_ndarray().reshape(
        settings.grid)

    # Assert - same in all columns
    for column in range(settings.grid[0]):
        np.testing.assert_array_equal(rhod[column, :], rhod[0, :])

    # Assert - decreasing with altitude
    rhod_below = 2 * si.kilograms / si.metre**3
    for level in range(settings.grid[1]):
        rhod_above = rhod[0, level]
        assert rhod_above < rhod_below
        rhod_below = rhod_above
示例#5
0
def main():
    settings = Settings()

    settings.grid = (25, 25)
    settings.simulation_time = settings.dt * 100
    settings.output_interval = settings.dt * 10
    settings.processes = {
        "particle advection": True,
        "fluid advection": True,
        "coalescence": True,
        "condensation": False,
        "sedimentation": True,
    }

    n_sd = range(14, 16, 1)

    times = {}
    backends = [(CPU, "sync"), (CPU, "async")]
    if GPU.ENABLE:
        backends.append((GPU, "async"))
    for backend, mode in backends:
        if backend is CPU:
            PySDM.backends.numba.conf.NUMBA_PARALLEL = mode
            reload_CPU_backend()
        key = f"{backend} (mode={mode})"
        times[key] = []
        for sd in n_sd:
            settings.n_sd_per_gridbox = sd
            storage = Storage()
            simulation = Simulation(settings, storage, backend)
            simulation.reinit(products=[WallTime()])
            simulation.run()
            times[key].append(storage.load('wall_time')[-1])

    from matplotlib import pyplot as plt
    for parallelization, t in times.items():
        plt.plot(n_sd, t, label=parallelization)
    plt.legend()
    plt.loglog()
    plt.savefig("benchmark.pdf", format="pdf")
示例#6
0
def test_initialisation(backend, plot=False):
    settings = Settings()
    settings.simulation_time = -1 * settings.dt
    settings.grid = (10, 5)
    settings.n_sd_per_gridbox = 5000

    simulation = Simulation(settings, None, backend)

    n_levels = settings.grid[1]
    n_cell = int(np.prod(np.array(settings.grid)))
    n_moments = 1

    r_bins = settings.formulae.trivia.radius(volume=settings.v_bins)

    histogram_dry = np.empty((len(r_bins) - 1, n_levels))
    histogram_wet = np.empty_like(histogram_dry)

    moment_0 = backend.Storage.empty(n_cell, dtype=int)
    moments = backend.Storage.empty((n_moments, n_cell), dtype=float)
    tmp = np.empty(n_cell)
    simulation.reinit()

    # Act (moments)
    simulation.run()
    particles = simulation.core
    environment = simulation.core.environment
    rhod = environment["rhod"].to_ndarray().reshape(settings.grid).mean(axis=0)

    for i in range(len(histogram_dry)):
        particles.particles.moments(moment_0,
                                    moments,
                                    specs={},
                                    attr_name='dry volume',
                                    attr_range=(settings.v_bins[i],
                                                settings.v_bins[i + 1]))
        moment_0.download(tmp)
        histogram_dry[i, :] = tmp.reshape(
            settings.grid).sum(axis=0) / (particles.mesh.dv * settings.grid[0])

        particles.particles.moments(moment_0,
                                    moments,
                                    specs={},
                                    attr_name='volume',
                                    attr_range=(settings.v_bins[i],
                                                settings.v_bins[i + 1]))
        moment_0.download(tmp)
        histogram_wet[i, :] = tmp.reshape(
            settings.grid).sum(axis=0) / (particles.mesh.dv * settings.grid[0])

    # Plot
    if plot:
        for level in range(0, n_levels):
            color = str(.75 * (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 - 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 = settings.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,
                                       significant=5)

    # 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 __init__(self):
        settings = Settings()

        self.ui_th_std0 = FloatSlider(description="$\\theta_0$ [K]",
                                      value=settings.th_std0,
                                      min=280,
                                      max=300)
        self.ui_qv0 = FloatSlider(description="q$_{v0}$ [g/kg]",
                                  value=settings.qv0 * 1000,
                                  min=5,
                                  max=10)
        self.ui_p0 = FloatSlider(description="p$_0$ [hPa]",
                                 value=settings.p0 / 100,
                                 min=900,
                                 max=1100)
        self.ui_kappa = FloatSlider(description="$\\kappa$ [1]",
                                    value=settings.kappa,
                                    min=0,
                                    max=1.5)
        self.ui_amplitude = FloatSlider(
            description="$\\psi_{_{mx}}$[kg/s/m$^{_2}$]",
            value=settings.rho_w_max,
            min=-1,
            max=1)
        self.ui_nx = IntSlider(value=settings.grid[0],
                               min=10,
                               max=100,
                               description="nx")
        self.ui_nz = IntSlider(value=settings.grid[1],
                               min=10,
                               max=100,
                               description="nz")
        self.ui_dt = FloatSlider(value=settings.dt,
                                 min=.5,
                                 max=60,
                                 description="dt (Eulerian)")
        self.ui_simulation_time = IntSlider(
            value=settings.simulation_time,
            min=1800,
            max=7200,
            description="simulation time $[s]$")
        self.ui_condensation_rtol_x = IntSlider(
            value=np.log10(settings.condensation_rtol_thd),
            min=-9,
            max=-3,
            description="log$_{10}$(rtol$_x$)")
        self.ui_condensation_rtol_thd = IntSlider(
            value=np.log10(settings.condensation_rtol_thd),
            min=-9,
            max=-3,
            description="log$_{10}$(rtol$_\\theta$)")
        self.ui_condensation_adaptive = Checkbox(
            value=settings.condensation_adaptive,
            description='condensation adaptive time-step')
        self.ui_coalescence_adaptive = Checkbox(
            value=settings.condensation_adaptive,
            description='coalescence adaptive time-step')
        self.ui_processes = [
            Checkbox(value=settings.processes[key], description=key)
            for key in settings.processes.keys()
        ]
        self.ui_sdpg = IntSlider(value=settings.n_sd_per_gridbox,
                                 description="n_sd/gridbox",
                                 min=1,
                                 max=1000)
        self.fct_description = "MPDATA: flux-corrected transport option"
        self.tot_description = "MPDATA: third-order terms option"
        self.iga_description = "MPDATA: infinite gauge option"
        self.nit_description = "MPDATA: number of iterations (1=UPWIND)"
        self.ui_mpdata_options = [
            Checkbox(value=settings.mpdata_fct,
                     description=self.fct_description),
            Checkbox(value=settings.mpdata_tot,
                     description=self.tot_description),
            Checkbox(value=settings.mpdata_iga,
                     description=self.iga_description),
            IntSlider(value=settings.mpdata_iters,
                      description=self.nit_description,
                      min=1,
                      max=5)
        ]
        self.ui_formulae_options = [
            Dropdown(description=k,
                     options=physics.formulae._choices(getattr(physics,
                                                               k)).keys(),
                     value=v.default) for k, v in inspect.signature(
                         physics.Formulae.__init__).parameters.items()
            if k not in ('self', 'fastmath', 'seed')
        ]
        self.ui_formulae_options.append(
            Checkbox(value=inspect.signature(
                physics.Formulae.__init__).parameters['fastmath'].default,
                     description='fastmath'))
        self.ui_output_options = {
            'interval':
            IntSlider(description='interval [s]',
                      value=settings.output_interval,
                      min=30,
                      max=60 * 15),
            'aerosol_radius_threshold':
            FloatSlider(description='aerosol/cloud threshold [um]',
                        value=settings.aerosol_radius_threshold /
                        physics.si.um,
                        min=.1,
                        max=1,
                        step=.1),
            'drizzle_radius_threshold':
            IntSlider(description='cloud/drizzle threshold [um]',
                      value=settings.drizzle_radius_threshold / physics.si.um,
                      min=10,
                      max=100,
                      step=5)
        }

        # TODO #37
        self.v_bins = settings.v_bins
        self.size = settings.size
        self.condensation_substeps = settings.condensation_substeps
        self.condensation_dt_cond_range = settings.condensation_dt_cond_range
        self.condensation_schedule = settings.condensation_schedule
        self.kernel = settings.kernel
        self.spectrum_per_mass_of_dry_air = settings.spectrum_per_mass_of_dry_air
        self.coalescence_dt_coal_range = settings.coalescence_dt_coal_range
        self.coalescence_optimized_random = settings.coalescence_optimized_random
        self.coalescence_substeps = settings.coalescence_substeps

        for attr in ('n_sd', 'rhod', 'field_values', 'versions', 'n_spin_up',
                     'stream_function'):
            setattr(self, attr, getattr(settings, attr))