def test_fake_numba(): # Arrange sut = DimensionalAnalysis() # Act & Assert assert hasattr(Formulae().saturation_vapour_pressure.pvs_Celsius, "py_func") with sut: assert not hasattr( Formulae().saturation_vapour_pressure.pvs_Celsius, "py_func") assert hasattr(Formulae().saturation_vapour_pressure.pvs_Celsius, "py_func")
def __init__(self, w_avg: float, N_STP: float, r_dry: float, mass_of_dry_air: float, coord: str = 'VolumeLogarithm'): self.formulae = Formulae( saturation_vapour_pressure='AugustRocheMagnus', condensation_coordinate=coord) self.p0 = 1000 * si.hectopascals self.RH0 = .98 self.kappa = .2 # TODO #441 self.T0 = 300 * si.kelvin self.z_half = 150 * si.metres pvs = self.formulae.saturation_vapour_pressure.pvs_Celsius(self.T0 - const.T0) self.q0 = const.eps / (self.p0 / self.RH0 / pvs - 1) self.w_avg = w_avg self.r_dry = r_dry self.N_STP = N_STP self.n_in_dv = N_STP / const.rho_STP * mass_of_dry_air self.mass_of_dry_air = mass_of_dry_air self.n_output = 500 self.rtol_x = condensation.default_rtol_x self.rtol_thd = condensation.default_rtol_thd self.coord = 'volume logarithm' self.dt_cond_range = condensation.default_cond_range
def test___str__(): # Arrange sut = Formulae() # Act result = str(sut) # Assert assert len(result) > 0
def __init__(self, backend, n_sd=0, formulae=None): if formulae is None: formulae = Formulae() Core.__init__(self, n_sd, backend(formulae)) self.core = self self.environment = DummyEnvironment() self.environment.register(self) self.req_attr = {'n': Multiplicities(self), 'cell id': CellID(self)} self.particles = None
def __init__(self, n_sd, backend, formulae=Formulae()): assert inspect.isclass(backend) self.formulae = formulae self.core = Core(n_sd, backend(formulae)) self.req_attr = { 'n': Multiplicities(self), 'volume': Volume(self), 'cell id': CellID(self) } self.aerosol_radius_threshold = 0 self.condensation_params = None
def test_pvs(): with DimensionalAnalysis(): # Arrange formulae = Formulae() si = constants.si sut = formulae.saturation_vapour_pressure.pvs_Celsius T = 300 * si.kelvins # Act pvs = sut(T) # Assert assert pvs.units == si.hectopascals
def test_analytic_solution_underflow(x): # Arrange formulae = Formulae() b = 1.5e3 x_0 = formulae.trivia.volume(radius=30.531e-6) N_0 = 2 ** 23 sut = Golovin(b) # Act value = sut.analytic_solution(x=x, t=1200, x_0=x_0, N_0=N_0) # Assert assert np.all(np.isfinite(value))
def test_lv(): with DimensionalAnalysis(): # Arrange si = constants.si T = 300 * si.kelvins formulae = Formulae() sut = formulae.latent_heat.lv # Act latent_heat = sut(T) # Assert assert latent_heat.check('[energy]/[mass]')
def test_r_cr(): with DimensionalAnalysis(): # Arrange si = constants.si formulae = Formulae() sut = formulae.hygroscopicity.r_cr kp = .5 rd = .1 * si.micrometre T = 300 * si.kelvins sgm = constants.sgm # Act r_cr = sut(kp, rd**3, T, sgm) # Assert assert r_cr.to_base_units().units == si.metres
def __init__(self, settings, backend=CPU): dt_output = settings.total_time / settings.n_steps # TODO #334 overwritten in jupyter example self.n_substeps = 1 # TODO #334 use condensation substeps while (dt_output / self.n_substeps >= settings.dt_max): self.n_substeps += 1 self.formulae = Formulae(condensation_coordinate=settings.coord, saturation_vapour_pressure='AugustRocheMagnus') self.bins_edges = self.formulae.trivia.volume(settings.r_bins_edges) builder = Builder(backend=backend, n_sd=settings.n_sd, formulae=self.formulae) builder.set_environment(Parcel( dt=dt_output / self.n_substeps, mass_of_dry_air=settings.mass_of_dry_air, p0=settings.p0, q0=settings.q0, T0=settings.T0, w=settings.w, z0=settings.z0 )) environment = builder.core.environment builder.add_dynamic(AmbientThermodynamics()) condensation = Condensation( kappa=settings.kappa, adaptive=settings.adaptive, rtol_x=settings.rtol_x, rtol_thd=settings.rtol_thd, dt_cond_range=settings.dt_cond_range ) builder.add_dynamic(condensation) products = [ PySDM_products.ParticlesWetSizeSpectrum(v_bins=self.formulae.trivia.volume(settings.r_bins_edges)), PySDM_products.CondensationTimestepMin(), PySDM_products.CondensationTimestepMax(), PySDM_products.RipeningRate() ] attributes = environment.init_attributes( n_in_dv=settings.n, kappa=settings.kappa, r_dry=settings.r_dry ) self.core = builder.build(attributes, products) self.n_steps = settings.n_steps
def test_toms748(fun): sut = toms748_solve if 'NUMBA_DISABLE_JIT' in os.environ else toms748_solve.py_func a = -.5 b = .5 rtol = 1e-6 wt = Formulae().trivia.within_tolerance actual, iters = sut(f2, (), ax=a, bx=b, fax=f2(a), fbx=f2(b), max_iter=10, rtol=rtol, within_tolerance=wt) expected = toms748(f2, a, b) np.testing.assert_almost_equal(actual, expected)
def test_coalescence(backend, croupier, adaptive): if backend == ThrustRTC and croupier == 'local': # TODO #358 return if backend == ThrustRTC and adaptive and croupier == 'global': # TODO #329 return # Arrange formulae = Formulae(seed=256) n_sd = 2**14 steps = [0, 100, 200] X0 = formulae.trivia.volume(radius=30.531e-6) n_part = 2**23 / si.metre**3 dv = 1e6 * si.metres**3 dt = 1 * si.seconds norm_factor = n_part * dv rho = 1000 * si.kilogram / si.metre**3 kernel = Golovin(b=1.5e3) # [s-1] spectrum = Exponential(norm_factor=norm_factor, scale=X0) builder = Builder(n_sd=n_sd, backend=backend(formulae=formulae)) builder.set_environment(Box(dt=dt, dv=dv)) attributes = {} attributes['volume'], attributes['n'] = ConstantMultiplicity( spectrum).sample(n_sd) builder.add_dynamic( Coalescence(kernel, croupier=croupier, adaptive=adaptive)) particulator = builder.build(attributes) volumes = {} # Act for step in steps: particulator.run(step - particulator.n_steps) check(n_part, dv, n_sd, rho, particulator.attributes, step) volumes[particulator. n_steps] = particulator.attributes['volume'].to_ndarray() # Assert x_max = 0 for volume in volumes.values(): assert x_max < np.amax(volume) x_max = np.amax(volume)
def test_equilibrate_pH_non_trivial(init_conc, env_T): equilibria = { 'water': Equilibrium.from_string(f"H2O = H+ + OH-; {K_H2O / M / M}"), 'ammonia': Equilibrium.from_string( f"NH3 + H2O = NH4+ + OH-; {EQUILIBRIUM_CONST['K_NH3'].at(env_T) / M}" ), 'sulfonic_first': Equilibrium.from_string( f"H2SO3(aq) = H+ + HSO3-; {EQUILIBRIUM_CONST['K_SO2'].at(env_T) / M}" ), 'sulfonic_second': Equilibrium.from_string( f"HSO3- = H+ + SO3-2; {EQUILIBRIUM_CONST['K_HSO3'].at(env_T) / M}" ), 'carbonic_first': Equilibrium.from_string( f"H2CO3(aq) = H+ + HCO3-; {EQUILIBRIUM_CONST['K_CO2'].at(env_T) / M}" ), 'carbonic_second': Equilibrium.from_string( f"HCO3- = H+ + CO3-2; {EQUILIBRIUM_CONST['K_HCO3'].at(env_T) / M}" ) } substances = [ Species.from_formula(f) for f in 'H2O OH- H+ NH3 NH4+ H2CO3(aq) HCO3- CO3-2 H2SO3(aq) HSO3- SO3-2'. split() ] eqsys = EqSystem(equilibria.values(), substances) x, sol, sane = eqsys.root(init_conc) assert sol['success'] and sane H_idx = 2 assert substances[H_idx].name == 'H+' expected_pH = -np.log10(x[H_idx]) eqs = {} for key in EQUILIBRIUM_CONST.keys(): eqs[key] = np.full(1, EQUILIBRIUM_CONST[key].at(env_T)) actual_pH = np.empty(1) formulae = Formulae() ChemistryMethods.equilibrate_H_body( within_tolerance=formulae.trivia.within_tolerance, pH2H=formulae.trivia.pH2H, H2pH=formulae.trivia.H2pH, N_mIII=np.full(1, init_conc['NH3'] * 1e3), N_V=np.full(1, init_conc['HNO3(aq)'] * 1e3), C_IV=np.full(1, init_conc['H2CO3(aq)'] * 1e3), S_IV=np.full(1, init_conc['H2SO3(aq)'] * 1e3), S_VI=np.full(1, init_conc['HSO4-'] * 1e3), K_HNO3=eqs['K_HNO3'].data, K_HCO3=eqs['K_HCO3'].data, K_HSO3=eqs['K_HSO3'].data, K_HSO4=eqs['K_HSO4'].data, K_CO2=eqs['K_CO2'].data, K_NH3=eqs['K_NH3'].data, K_SO2=eqs['K_SO2'].data, cell_id=np.zeros(1, dtype=int), # output do_chemistry_flag=np.empty(1), pH=actual_pH, # params H_min=formulae.trivia.pH2H(aqueous_chemistry.default_pH_max), H_max=formulae.trivia.pH2H(aqueous_chemistry.default_pH_min), ionic_strength_threshold=aqueous_chemistry. default_ionic_strength_threshold, rtol=aqueous_chemistry.default_pH_rtol) np.testing.assert_allclose(actual_pH[0], expected_pH, rtol=1e-5)
from PySDM.physics.aqueous_chemistry.support import M, EquilibriumConsts from PySDM.physics.constants import ROOM_TEMP, K_H2O from PySDM.physics.formulae import Formulae from PySDM.backends.numba.impl._chemistry_methods import ChemistryMethods from PySDM.dynamics import aqueous_chemistry from chempy import Equilibrium from chempy.equilibria import EqSystem from chempy.chemistry import Species import numpy as np import pytest from collections import defaultdict formulae = Formulae() EQUILIBRIUM_CONST = EquilibriumConsts(formulae).EQUILIBRIUM_CONST class Test_pH: @staticmethod def test_equilibrate_pH_pure_water(): # Arrange eqs = {} for key in EQUILIBRIUM_CONST.keys(): eqs[key] = np.full(1, EQUILIBRIUM_CONST[key].at(ROOM_TEMP)) # Act result = np.empty(1) ChemistryMethods.equilibrate_H_body( within_tolerance=formulae.trivia.within_tolerance, pH2H=formulae.trivia.pH2H, H2pH=formulae.trivia.H2pH,