def __init__(self, particles_builder: ParticlesBuilder, scheme='FTBS', sedimentation=False): particles_builder.request_attribute('terminal velocity') self.particles = particles_builder.particles courant_field = self.particles.environment.get_courant_field_data() # CFL # TODO: this should be done by MPyDATA for d in range(len(courant_field)): assert np.amax(abs(courant_field[d])) <= 1 # TODO: replace with make_calculate_displacement if scheme == 'FTFS': method = self.particles.backend.explicit_in_space elif scheme == 'FTBS': method = self.particles.backend.implicit_in_space else: raise NotImplementedError() self.scheme = method self.enable_sedimentation = sedimentation self.dimension = len(courant_field) self.grid = self.particles.backend.from_ndarray(np.array([courant_field[1].shape[0], courant_field[0].shape[1]], dtype=np.int64)) self.courant = [self.particles.backend.from_ndarray(courant_field[i]) for i in range(self.dimension)] self.displacement = self.particles.backend.from_ndarray(np.zeros((self.dimension, self.particles.n_sd))) self.temp = self.particles.backend.from_ndarray(np.zeros((self.dimension, self.particles.n_sd), dtype=np.int64))
def run(setup): particles_building = ParticlesBuilder(n_sd=setup.n_sd, backend=setup.backend) particles_building.set_environment(Box, {'dv': setup.dv, 'dt': setup.dt}) v, n = constant_multiplicity(setup.n_sd, setup.spectrum, (setup.init_x_min, setup.init_x_max)) attributes = {'n': n, 'volume': v} particles_building.register_dynamic(Coalescence, {"kernel": setup.kernel}) particles = particles_building.get_particles(attributes) states = {} for step in setup.steps: particles.run(step - particles.n_steps) return states, particles.stats
def run(setup): particles_builder = ParticlesBuilder(n_sd=setup.n_sd, backend=setup.backend) particles_builder.set_environment(Box, {"dv": setup.dv, "dt": setup.dt}) attributes = {} attributes['volume'], attributes['n'] = constant_multiplicity(setup.n_sd, setup.spectrum, (setup.init_x_min, setup.init_x_max)) particles_builder.register_dynamic(Coalescence, {"kernel": setup.kernel}) products = {ParticlesVolumeSpectrum: {}} particles = particles_builder.get_particles(attributes, products) vals = {} for step in setup.steps: particles.run(step - particles.n_steps) vals[step] = particles.products['dv/dlnr'].get(setup.radius_bins_edges) vals[step][:] *= setup.rho return vals, particles.stats
def __init__(self, setup): dt_output = setup.total_time / setup.n_steps # TODO: overwritten in jupyter example self.n_substeps = 1 # TODO: while (dt_output / self.n_substeps >= setup.dt_max): self.n_substeps += 1 self.bins_edges = phys.volume(setup.r_bins_edges) particles_builder = ParticlesBuilder(backend=setup.backend, n_sd=setup.n_sd) particles_builder.set_environment( MoistLagrangianParcelAdiabatic, { "dt": dt_output / self.n_substeps, "mass_of_dry_air": setup.mass_of_dry_air, "p0": setup.p0, "q0": setup.q0, "T0": setup.T0, "w": setup.w, "z0": setup.z0 }) environment = particles_builder.particles.environment r_wet = r_wet_init(setup.r_dry, environment, np.zeros_like(setup.n), setup.kappa) particles_builder.register_dynamic( Condensation, { "kappa": setup.kappa, "coord": setup.coord, "adaptive": setup.adaptive, "rtol_x": setup.rtol_x, "rtol_thd": setup.rtol_thd, }) attributes = { 'n': setup.n, 'dry volume': phys.volume(radius=setup.r_dry), 'volume': phys.volume(radius=r_wet) } products = { ParticlesSizeSpectrum: { 'v_bins': phys.volume(setup.r_bins_edges) }, CondensationTimestep: {}, RipeningRate: {} } self.particles = particles_builder.get_particles(attributes, products) self.n_steps = setup.n_steps
def test_coalescence(croupier): # Arrange v_min = 4.186e-15 v_max = 4.186e-12 n_sd = 2**13 steps = [0, 30, 60] X0 = 4 / 3 * np.pi * 30.531e-6**3 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) particles_builder = ParticlesBuilder(n_sd=n_sd, backend=backend) particles_builder.set_environment(Box, {"dt": dt, "dv": dv}) attributes = {} attributes['volume'], attributes['n'] = constant_multiplicity( n_sd, spectrum, (v_min, v_max)) particles_builder.register_dynamic(Coalescence, {"kernel": kernel}) particles = particles_builder.get_particles(attributes) particles.croupier = croupier class Seed: seed = 0 def __call__(self): Seed.seed += 1 return Seed.seed particles.dynamics[str(Coalescence)].seed = Seed() states = {} # Act for step in steps: particles.run(step - particles.n_steps) check(n_part, dv, n_sd, rho, particles.state, step) states[particles.n_steps] = copy.deepcopy(particles.state) # Assert x_max = 0 for state in states.values(): assert x_max < np.amax(backend.to_ndarray(state['volume'])) x_max = np.amax(backend.to_ndarray(state['volume']))
def __init__(self, setup): t_half = setup.z_half / setup.w_avg dt_output = (2 * t_half) / setup.n_output self.n_substeps = 1 while dt_output / self.n_substeps >= setup.dt_max: # TODO dt_max self.n_substeps += 1 particles_builder = ParticlesBuilder(backend=setup.backend, n_sd=1) particles_builder.set_environment( MoistLagrangianParcelAdiabatic, { "dt": dt_output / self.n_substeps, "mass_of_dry_air": setup.mass_of_dry_air, "p0": setup.p0, "q0": setup.q0, "T0": setup.T0, "w": setup.w }) particles_builder.register_dynamic( Condensation, { "kappa": setup.kappa, "rtol_x": setup.rtol_x, "rtol_thd": setup.rtol_thd, }) attributes = {} r_dry = np.array([setup.r_dry]) attributes['dry volume'] = phys.volume(radius=r_dry) attributes['n'] = np.array([setup.n_in_dv], dtype=np.int64) environment = particles_builder.particles.environment r_wet = r_wet_init(r_dry, environment, np.zeros_like(attributes['n']), setup.kappa) attributes['volume'] = phys.volume(radius=r_wet) products = {ParticleMeanRadius: {}} self.particles = particles_builder.get_particles(attributes, products) self.n_output = setup.n_output
def reinit(self): particles_builder = ParticlesBuilder(n_sd=self.setup.n_sd, backend=self.setup.backend) particles_builder.set_environment( MoistEulerian2DKinematic, { "dt": self.setup.dt, "grid": self.setup.grid, "size": self.setup.size, "stream_function": self.setup.stream_function, "field_values": self.setup.field_values, "rhod_of": self.setup.rhod, "mpdata_iga": self.setup.mpdata_iga, "mpdata_tot": self.setup.mpdata_tot, "mpdata_fct": self.setup.mpdata_fct, "mpdata_iters": self.setup.mpdata_iters }) particles_builder.register_dynamic( Condensation, { "kappa": self.setup.kappa, "rtol_x": self.setup.condensation_rtol_x, "rtol_thd": self.setup.condensation_rtol_thd, "coord": self.setup.condensation_coord, "adaptive": self.setup.adaptive, "do_advection": self.setup. processes["fluid advection"], # TODO req. EulerianAdvection "do_condensation": self.setup.processes["condensation"] # do somthing with that }) particles_builder.register_dynamic(EulerianAdvection, {}) if self.setup.processes["particle advection"]: particles_builder.register_dynamic( Displacement, { "scheme": 'FTBS', "sedimentation": self.setup.processes["sedimentation"] }) if self.setup.processes["coalescence"]: particles_builder.register_dynamic(Coalescence, {"kernel": self.setup.kernel}) # TODO # if self.setup.processes["relaxation"]: # raise NotImplementedError() attributes = {} moist_environment_init( attributes, particles_builder.particles.environment, spatial_discretisation=spatial_sampling.pseudorandom, spectral_discretisation=spectral_sampling. constant_multiplicity, # TODO: random spectrum_per_mass_of_dry_air=self.setup. spectrum_per_mass_of_dry_air, r_range=(self.setup.r_min, self.setup.r_max), kappa=self.setup.kappa) products = { ParticlesSizeSpectrum: { 'v_bins': self.setup.v_bins }, TotalParticleConcentration: {}, TotalParticleSpecificConcentration: {}, AerosolConcentration: { 'radius_threshold': self.setup.aerosol_radius_threshold }, AerosolSpecificConcentration: { 'radius_threshold': self.setup.aerosol_radius_threshold }, ParticleMeanRadius: {}, SuperDropletCount: {}, RelativeHumidity: {}, WaterVapourMixingRatio: {}, DryAirDensity: {}, DryAirPotentialTemperature: {}, CondensationTimestep: {}, RipeningRate: {} } self.particles = particles_builder.get_particles(attributes, products) SpinUp(self.particles, self.setup.n_spin_up) # TODO if self.storage is not None: self.storage.init(self.setup)