Esempio n. 1
0
def data(n_output, rtols, schemes, setups_num):
    resultant_data = {}
    for scheme in schemes:
        resultant_data[scheme] = {}
        if scheme == "BDF":
            for rtol in rtols:
                resultant_data[scheme][rtol] = []
            for settings_idx in range(setups_num):
                settings = setups[settings_idx]
                settings.n_output = n_output
                simulation = Simulation(settings)
                bdf.patch_particulator(simulation.particulator)
                results = simulation.run()
                for rtol in rtols:
                    resultant_data[scheme][rtol].append(results)
        else:
            for rtol in rtols:
                resultant_data[scheme][rtol] = []
                for settings_idx in range(setups_num):
                    settings = setups[settings_idx]
                    settings.rtol_x = rtol
                    settings.rtol_thd = rtol
                    settings.n_output = n_output
                    simulation = Simulation(
                        settings, backend=CPU if scheme == "CPU" else GPU)
                    results = simulation.run()
                    resultant_data[scheme][rtol].append(results)
    return resultant_data
Esempio n. 2
0
def test_water_mass_conservation(settings_idx, mass_of_dry_air, scheme, coord):
    # Arrange
    assert scheme in ('BDF', 'CPU', 'GPU')

    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=mass_of_dry_air,
                        coord=coord)
    settings.n_output = 50
    settings.coord = coord
    simulation = Simulation(settings, GPU if scheme == 'GPU' else CPU)
    qt0 = settings.q0 + liquid_water_mixing_ratio(simulation)

    if scheme == 'BDF':
        bdf.patch_particulator(simulation.particulator)

    # Act
    simulation.particulator.products['S_max'].get()
    output = simulation.run()

    # Assert
    ql = liquid_water_mixing_ratio(simulation)
    qt = simulation.particulator.environment["qv"].to_ndarray() + ql
    significant = 6 if scheme == 'GPU' else 14  # TODO #540
    np.testing.assert_approx_equal(qt, qt0, significant)
    if scheme != 'BDF':
        assert simulation.particulator.products['S_max'].get(
        ) >= output['S'][-1]
Esempio n. 3
0
    def __init__(
        self, settings, products=None, scipy_solver=False, rtol_thd=1e-10, rtol_x=1e-10
    ):
        env = Parcel(
            dt=settings.timestep,
            p0=settings.initial_pressure,
            q0=settings.initial_vapour_mixing_ratio,
            T0=settings.initial_temperature,
            w=settings.vertical_velocity,
            mass_of_dry_air=44 * si.kg,
        )
        n_sd = sum(settings.n_sd_per_mode)
        builder = Builder(n_sd=n_sd, backend=CPU(formulae=settings.formulae))
        builder.set_environment(env)
        builder.add_dynamic(AmbientThermodynamics())
        builder.add_dynamic(Condensation(rtol_thd=rtol_thd, rtol_x=rtol_x))

        volume = env.mass_of_dry_air / settings.initial_air_density
        attributes = {
            k: np.empty(0) for k in ("dry volume", "kappa times dry volume", "n")
        }
        for i, (kappa, spectrum) in enumerate(settings.aerosol_modes_by_kappa.items()):
            sampling = ConstantMultiplicity(spectrum)
            r_dry, n_per_volume = sampling.sample(settings.n_sd_per_mode[i])
            v_dry = settings.formulae.trivia.volume(radius=r_dry)
            attributes["n"] = np.append(attributes["n"], n_per_volume * volume)
            attributes["dry volume"] = np.append(attributes["dry volume"], v_dry)
            attributes["kappa times dry volume"] = np.append(
                attributes["kappa times dry volume"], v_dry * kappa
            )
        r_wet = equilibrate_wet_radii(
            r_dry=settings.formulae.trivia.radius(volume=attributes["dry volume"]),
            environment=env,
            kappa_times_dry_volume=attributes["kappa times dry volume"],
        )
        attributes["volume"] = settings.formulae.trivia.volume(radius=r_wet)

        super().__init__(
            particulator=builder.build(attributes=attributes, products=products)
        )
        if scipy_solver:
            bdf.patch_particulator(self.particulator)

        self.output_attributes = {
            "volume": tuple([] for _ in range(self.particulator.n_sd))
        }
        self.settings = settings

        self.__sanity_checks(attributes, volume)
Esempio n. 4
0
def test_just_do_it(scheme, adaptive, backend_class=CPU):
    # Arrange
    if scheme == 'BDF' and (not adaptive or backend_class is GPU):
        return

    settings = Settings(dt_output=10 * si.second)
    settings.adaptive = adaptive
    if scheme == 'BDF':
        settings.dt_max = settings.dt_output  # TODO #334 'BDF')
    elif not adaptive:
        settings.dt_max = 1 * si.second

    simulation = Simulation(settings, backend_class)
    if scheme == 'BDF':
        bdf.patch_particulator(simulation.particulator)

    # Act
    output = simulation.run()
    r = np.array(output['r']).T * si.metres
    n = settings.n / (settings.mass_of_dry_air * si.kilogram)

    # Assert
    condition = (r > 1 * si.micrometre)
    NTOT = n_tot(n, condition)
    N1 = NTOT[:int(1 / 3 * len(NTOT))]
    N2 = NTOT[int(1 / 3 * len(NTOT)):int(2 / 3 * len(NTOT))]
    N3 = NTOT[int(2 / 3 * len(NTOT)):]

    n_unit = 1 / si.microgram
    assert min(N1) == 0.0 * n_unit
    assert .6 * n_unit < max(N1) < .8 * n_unit
    assert .17 * n_unit < min(N2) < .18 * n_unit
    assert .35 * n_unit < max(N2) < .41 * n_unit
    assert .1 * n_unit < min(N3) < .11 * n_unit
    assert .27 * n_unit < max(N3) < .4 * n_unit

    # TODO #527
    if backend_class is not GPU:
        assert max(output['ripening rate']) > 0
Esempio n. 5
0
    def __init__(self, settings, products=None):
        env = Parcel(
            dt=settings.dt,
            mass_of_dry_air=settings.mass_of_dry_air,
            p0=settings.p0,
            q0=settings.q0,
            T0=settings.T0,
            w=settings.w,
        )
        n_sd = settings.n_sd_per_mode * len(settings.aerosol.modes)
        builder = Builder(n_sd=n_sd, backend=CPU(formulae=settings.formulae))
        builder.set_environment(env)

        attributes = {
            "dry volume": np.empty(0),
            "dry volume organic": np.empty(0),
            "kappa times dry volume": np.empty(0),
            "n": np.ndarray(0),
        }
        for mode in settings.aerosol.modes:
            r_dry, n_in_dv = settings.spectral_sampling(
                spectrum=mode["spectrum"]).sample(settings.n_sd_per_mode)
            V = settings.mass_of_dry_air / settings.rho0
            N = n_in_dv * V
            v_dry = settings.formulae.trivia.volume(radius=r_dry)
            attributes["n"] = np.append(attributes["n"], N)
            attributes["dry volume"] = np.append(attributes["dry volume"],
                                                 v_dry)
            attributes["dry volume organic"] = np.append(
                attributes["dry volume organic"], mode["f_org"] * v_dry)
            attributes["kappa times dry volume"] = np.append(
                attributes["kappa times dry volume"],
                v_dry * mode["kappa"][settings.model],
            )
        for attribute in attributes.values():
            assert attribute.shape[0] == n_sd

        np.testing.assert_approx_equal(
            np.sum(attributes["n"]) / V,
            Sum(
                tuple(
                    settings.aerosol.modes[i]["spectrum"]
                    for i in range(len(settings.aerosol.modes)))).norm_factor,
            significant=5,
        )
        r_wet = equilibrate_wet_radii(
            r_dry=settings.formulae.trivia.radius(
                volume=attributes["dry volume"]),
            environment=env,
            kappa_times_dry_volume=attributes["kappa times dry volume"],
            f_org=attributes["dry volume organic"] / attributes["dry volume"],
        )
        attributes["volume"] = settings.formulae.trivia.volume(radius=r_wet)

        if settings.model == "Constant":
            del attributes["dry volume organic"]

        builder.add_dynamic(AmbientThermodynamics())
        builder.add_dynamic(Condensation())

        products = products or (
            PySDM_products.ParcelDisplacement(name="z"),
            PySDM_products.Time(name="t"),
            PySDM_products.PeakSupersaturation(unit="%", name="S_max"),
            PySDM_products.AmbientRelativeHumidity(unit="%", name="RH"),
            PySDM_products.ParticleConcentration(
                name="n_c_cm3",
                unit="cm^-3",
                radius_range=settings.cloud_radius_range),
            PySDM_products.ParticleSizeSpectrumPerVolume(
                radius_bins_edges=settings.wet_radius_bins_edges),
            PySDM_products.ActivableFraction(),
        )

        particulator = builder.build(attributes=attributes, products=products)
        if settings.BDF:
            bdf.patch_particulator(particulator)
        self.settings = settings
        super().__init__(particulator=particulator)
Esempio n. 6
0
def run_parcel(
    w,
    sol2,
    N2,
    rad2,
    n_sd_per_mode,
    RH0=1.0,
    T0=294 * si.K,
    p0=1e5 * si.Pa,
    n_steps=50,
    mass_of_dry_air=1e3 * si.kg,
    dt=2 * si.s,
):
    products = (
        PySDM_products.WaterMixingRatio(unit="g/kg", name="ql"),
        PySDM_products.PeakSupersaturation(name="S max"),
        PySDM_products.AmbientRelativeHumidity(name="RH"),
        PySDM_products.ParcelDisplacement(name="z"),
    )

    formulae = Formulae()
    const = formulae.constants
    pv0 = RH0 * formulae.saturation_vapour_pressure.pvs_Celsius(T0 - const.T0)
    q0 = const.eps * pv0 / (p0 - pv0)

    env = Parcel(dt=dt,
                 mass_of_dry_air=mass_of_dry_air,
                 p0=p0,
                 q0=q0,
                 w=w,
                 T0=T0)

    aerosol = AerosolARG(M2_sol=sol2, M2_N=N2, M2_rad=rad2)
    n_sd = n_sd_per_mode * len(aerosol.modes)

    builder = Builder(backend=CPU(), n_sd=n_sd)
    builder.set_environment(env)
    builder.add_dynamic(AmbientThermodynamics())
    builder.add_dynamic(Condensation())
    builder.add_dynamic(Magick())

    attributes = {
        k: np.empty(0)
        for k in ("dry volume", "kappa times dry volume", "n")
    }
    for i, mode in enumerate(aerosol.modes):
        kappa, spectrum = mode["kappa"]["CompressedFilmOvadnevaite"], mode[
            "spectrum"]
        r_dry, concentration = ConstantMultiplicity(spectrum).sample(
            n_sd_per_mode)
        v_dry = builder.formulae.trivia.volume(radius=r_dry)
        specific_concentration = concentration / builder.formulae.constants.rho_STP
        attributes["n"] = np.append(
            attributes["n"], specific_concentration * env.mass_of_dry_air)
        attributes["dry volume"] = np.append(attributes["dry volume"], v_dry)
        attributes["kappa times dry volume"] = np.append(
            attributes["kappa times dry volume"], v_dry * kappa)

    r_wet = equilibrate_wet_radii(
        r_dry=builder.formulae.trivia.radius(volume=attributes["dry volume"]),
        environment=env,
        kappa_times_dry_volume=attributes["kappa times dry volume"],
    )
    attributes["volume"] = builder.formulae.trivia.volume(radius=r_wet)

    particulator = builder.build(attributes, products=products)
    bdf.patch_particulator(particulator)

    output = {product.name: [] for product in particulator.products.values()}
    output_attributes = {
        "n": tuple([] for _ in range(particulator.n_sd)),
        "volume": tuple([] for _ in range(particulator.n_sd)),
        "critical volume": tuple([] for _ in range(particulator.n_sd)),
        "critical supersaturation":
        tuple([] for _ in range(particulator.n_sd)),
    }

    for _ in range(n_steps):
        particulator.run(steps=1)
        for product in particulator.products.values():
            value = product.get()
            output[product.name].append(value[0])
        for key, attr in output_attributes.items():
            attr_data = particulator.attributes[key].to_ndarray()
            for drop_id in range(particulator.n_sd):
                attr[drop_id].append(attr_data[drop_id])

    error = np.zeros(len(aerosol.modes))
    activated_fraction_S = np.zeros(len(aerosol.modes))
    activated_fraction_V = np.zeros(len(aerosol.modes))
    for j, mode in enumerate(aerosol.modes):
        activated_drops_j_S = 0
        activated_drops_j_V = 0
        RHmax = np.nanmax(np.asarray(output["RH"]))
        for i, volume in enumerate(output_attributes["volume"]):
            if j * n_sd_per_mode <= i < (j + 1) * n_sd_per_mode:
                if output_attributes["critical supersaturation"][i][-1] < RHmax:
                    activated_drops_j_S += output_attributes["n"][i][-1]
                if output_attributes["critical volume"][i][-1] < volume[-1]:
                    activated_drops_j_V += output_attributes["n"][i][-1]
        Nj = np.asarray(output_attributes["n"])[j * n_sd_per_mode:(j + 1) *
                                                n_sd_per_mode, -1]
        max_multiplicity_j = np.max(Nj)
        sum_multiplicity_j = np.sum(Nj)
        error[j] = max_multiplicity_j / sum_multiplicity_j
        activated_fraction_S[j] = activated_drops_j_S / sum_multiplicity_j
        activated_fraction_V[j] = activated_drops_j_V / sum_multiplicity_j

    Output = namedtuple(
        "Output",
        [
            "profile",
            "attributes",
            "aerosol",
            "activated_fraction_S",
            "activated_fraction_V",
            "error",
        ],
    )
    return Output(
        profile=output,
        attributes=output_attributes,
        aerosol=aerosol,
        activated_fraction_S=activated_fraction_S,
        activated_fraction_V=activated_fraction_V,
        error=error,
    )