Пример #1
0
    def __init__(self, setup, xrange):
        self.setup = setup

        self.v_bins = np.logspace((np.log10(xrange[0])), (np.log10(xrange[1])),
                                  num=64,
                                  endpoint=True)
        self.r_bins = phys.radius(volume=self.v_bins)
Пример #2
0
 def __init__(self, kappa, xd: np.ndarray, n: np.ndarray, drhod_dt, dthd_dt,
              dqv_dt, m_d):
     self.kappa = kappa
     self.rd = phys.radius(volume=xd)
     self.n = n
     self.dqv_dt = dqv_dt
     self.dthd_dt = dthd_dt
     self.drhod_dt = drhod_dt
     self.m_d = m_d
Пример #3
0
 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
Пример #4
0
def test_initialisation(plot=False):
    # TODO: seed as a part of setup?
    setup = Setup()
    setup.steps = []
    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)

    # 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
Пример #5
0
 def get(self):
     self.download_moment_to_buffer('volume', rank=1 / 3)
     self.buffer[:] *= phys.radius(volume=1)
     const.convert_to(self.buffer, const.si.micrometre)
     return self.buffer
Пример #6
0
    def __call__(self):
        self.environment.sync()

        state = self.particles.state
        state.sort_by_cell_id(
        )  # TODO +what about droplets that precipitated out of the domain
        compute_cell_start(self.cell_start, state.cell_id, state.idx,
                           state.SD_num)

        v = state.get_backend_storage("volume")
        n = state.n
        vdry = state.get_backend_storage("dry volume")

        if self.scheme == 'scipy.odeint':
            for cell_id in range(self.particles.mesh.n_cell):
                cell_start = self.cell_start[cell_id]
                cell_end = self.cell_start[cell_id + 1]
                n_sd_in_cell = cell_end - cell_start
                if n_sd_in_cell == 0:
                    continue

                y0 = np.empty(n_sd_in_cell + idx_rw)
                y0[idx_rhod] = self.environment['rhod'][cell_id]
                y0[idx_thd] = self.environment['thd'][cell_id]
                y0[idx_qv] = self.environment['qv'][cell_id]
                y0[idx_rw:] = phys.radius(
                    volume=v[state.idx[cell_start:cell_end]])
                integ = ode.solve_ivp(
                    _ODESystem(
                        self.kappa, vdry[state.idx[cell_start:cell_end]],
                        n[state.idx[cell_start:cell_end]],
                        (self.environment.get_predicted("rhod")[cell_id] -
                         self.environment['rhod'][cell_id]) / self.dt,
                        (self.environment.get_predicted('thd')[cell_id] -
                         self.environment['thd'][cell_id]) / self.dt,
                        (self.environment.get_predicted('qv')[cell_id] -
                         self.environment['qv'][cell_id]) / self.dt,
                        self.environment.get_predicted("rhod")[cell_id] *
                        self.environment.dv),
                    (0., self.dt),
                    y0,
                    method='BDF',
                    # rtol=1e-6,
                    atol=1e-9,
                    # first_step=self.dt,
                    t_eval=[self.dt])
                assert integ.success, integ.message

                dm = 0
                for i in range(cell_end - cell_start):
                    x_new = phys.volume(radius=integ.y[idx_rw + i])
                    x_old = v[state.idx[cell_start + i]]
                    nd = n[state.idx[cell_start + i]]
                    dm += nd * (x_new - x_old) * rho_w
                    v[state.idx[cell_start + i]] = x_new

                m_d = self.environment.get_predicted(
                    'rhod')[cell_id] * self.environment.dv
                dq_sum = -dm / m_d
                dq_ode = integ.y[idx_qv] - self.environment.get_predicted(
                    'qv')[cell_id]

                #dth_sum =
                dth_ode = integ.y[idx_thd] - self.environment.get_predicted(
                    'thd')[cell_id]

                # TODO: move to a separate test
                #np.testing.assert_approx_equal(dq_ode, dq_sum, 4)
                #np.testing.assert_approx_equal(dth_ode, dth_sum)

                self.environment.get_predicted('qv')[cell_id] += dq_sum
                self.environment.get_predicted('thd')[cell_id] += dth_ode
        else:
            raise NotImplementedError()