def __init__(self, setup): self.setup = setup sigma2 = pow(setup.sigma, 2) dx_opt = abs(setup.C_opt / (.5 * sigma2 - setup.r) * setup.l2_opt * sigma2) dt_opt = pow(dx_opt, 2) / sigma2 / setup.l2_opt # adjusting dt so that nt is integer self.dt = setup.T self.nt = 0 while self.dt > dt_opt: self.nt += 1 self.dt = setup.T / self.nt # adjusting dx to match requested l^2 dx = np.sqrt(setup.l2_opt * self.dt) * setup.sigma # calculating actual u number and lambda self.C = -(.5 * sigma2 - setup.r) * (-self.dt) / dx self.l2 = dx * dx / sigma2 / self.dt # adjusting nx and setting S_beg, S_end S_beg = setup.S_match self.nx = 1 while S_beg > setup.S_min: self.nx += 1 S_beg = np.exp(np.log(setup.S_match) - self.nx * dx) self.ix_match = self.nx S_end = setup.S_match while S_end < setup.S_max: self.nx += 1 S_end = np.exp(np.log(S_beg) + (self.nx - 1) * dx) # asset price self.S = np.exp(np.log(S_beg) + np.arange(self.nx) * dx) self.mu_coeff = (0.5 / self.l2, ) self.solvers = {} self.solvers[1] = Factories.advection_diffusion_1d( advectee=setup.payoff(self.S), advector=self.C, options=Options(n_iters=1, non_zero_mu_coeff=True), boundary_conditions=(ExtrapolatedBoundaryCondition(), )) self.solvers[2] = Factories.advection_diffusion_1d( advectee=setup.payoff(self.S), advector=self.C, options=Options(**OPTIONS), boundary_conditions=(ExtrapolatedBoundaryCondition(), ))
def test_diffusion_only_2d(data0=np.array([[0, 0, 0], [0, 1., 0], [0, 0, 0]]), mu_coeff=(.1, .1), n_steps=1): # Arrange options = Options(non_zero_mu_coeff=True) boundary_conditions = tuple([Periodic()] * 2) advectee = ScalarField(data0, options.n_halo, boundary_conditions) advector = VectorField(data=(np.zeros( (data0.shape[0] + 1, data0.shape[1])), np.zeros( (data0.shape[0], data0.shape[1] + 1))), halo=options.n_halo, boundary_conditions=boundary_conditions) solver = Solver(stepper=Stepper(options=options, grid=data0.shape), advector=advector, advectee=advectee) # Act solver.advance(n_steps=n_steps, mu_coeff=mu_coeff) # Assert data1 = solver.advectee.get() np.testing.assert_almost_equal(actual=np.sum(data1), desired=np.sum(data0)) assert np.amax(data0) > np.amax(data1) assert np.amin(data1) >= 0 assert np.count_nonzero(data1) == 5
def test_double_pass_donor_cell(n_iters): courant = .5 options = Options(n_iters=n_iters, DPDC=True, nonoscillatory=True) state = np.array([0, 1, 0], dtype=options.dtype) boundary_conditions = (Periodic(),) mpdata = Solver( stepper=Stepper(options=options, n_dims=state.ndim, non_unit_g_factor=False), advectee=ScalarField( state, halo=options.n_halo, boundary_conditions=boundary_conditions ), advector=VectorField( (np.full(state.shape[0] + 1, courant, dtype=options.dtype),), halo=options.n_halo, boundary_conditions=boundary_conditions ) ) steps = 1 conserved = np.sum(mpdata.advectee.get()) mpdata.advance(steps) assert np.sum(mpdata.advectee.get()) == conserved
def __init__(self, nz, dt, advector_of_t, advectee_of_zZ_at_t0, g_factor_of_zZ, mpdata_settings): self.t = 0 self.dt = dt self.advector_of_t = advector_of_t grid = (nz, ) options = Options(n_iters=mpdata_settings['n_iters'], infinite_gauge=mpdata_settings['iga'], flux_corrected_transport=mpdata_settings['fct'], third_order_terms=mpdata_settings['tot']) stepper = Stepper(options=options, grid=grid, non_unit_g_factor=True) bcs = (ExtrapolatedBoundaryCondition(), ) g_factor = ScalarField(data=g_factor_of_zZ( arakawa_c.z_scalar_coord(grid)), halo=options.n_halo, boundary_conditions=bcs) advector = VectorField(data=(np.full(nz + 1, advector_of_t(0)), ), halo=options.n_halo, boundary_conditions=bcs) self.advectee = ScalarField(data=advectee_of_zZ_at_t0( arakawa_c.z_scalar_coord(grid)), halo=options.n_halo, boundary_conditions=bcs) self.solver = Solver(stepper=stepper, advectee=self.advectee, advector=advector, g_factor=g_factor)
def __init__(self, *, fields, n_iters=2, infinite_gauge=True, flux_corrected_transport=True, third_order_terms=False): self.grid = fields.g_factor.shape self.asynchronous = False self.thread: (Thread, None) = None options = Options( n_iters=n_iters, infinite_gauge=infinite_gauge, flux_corrected_transport=flux_corrected_transport, third_order_terms=third_order_terms ) disable_threads_if_needed = {} if not conf.JIT_FLAGS['parallel']: disable_threads_if_needed['n_threads'] = 1 stepper = Stepper(options=options, grid=self.grid, non_unit_g_factor=True, **disable_threads_if_needed) # CFL condition for d in range(len(fields.advector)): np.testing.assert_array_less(np.abs(fields.advector[d]), 1) self.advector = fields.advector advector_impl = VectorField(fields.advector, halo=options.n_halo, boundary_conditions=(PeriodicBoundaryCondition(), PeriodicBoundaryCondition())) self.g_factor = fields.g_factor g_factor_impl = ScalarField(fields.g_factor.astype(dtype=options.dtype), halo=options.n_halo, boundary_conditions=(PeriodicBoundaryCondition(), PeriodicBoundaryCondition())) self.mpdatas = {} for k, v in fields.advectees.items(): advectee = ScalarField(np.full(self.grid, v, dtype=options.dtype), halo=options.n_halo, boundary_conditions=(PeriodicBoundaryCondition(), PeriodicBoundaryCondition())) self.mpdatas[k] = Solver(stepper=stepper, advectee=advectee, advector=advector_impl, g_factor=g_factor_impl)
def test_make_upwind(self): # Arrange psi_data = np.array((0, 1, 0)) flux_data = np.array((0, 0, 1, 0)) options = Options() halo = options.n_halo traversals = Traversals(grid=psi_data.shape, halo=halo, jit_flags={}, n_threads=1) upwind = make_upwind(options=options, non_unit_g_factor=False, traversals=traversals) bc = [PeriodicBoundaryCondition()] psi = ScalarField(psi_data, halo, bc) psi_impl = psi.impl flux_impl = VectorField((flux_data, ), halo, bc).impl null_impl = ScalarField.make_null(len(psi_data.shape)).impl # Act upwind(psi_impl[0], *flux_impl, *null_impl) # Assert np.testing.assert_array_equal(psi.get(), np.roll(psi_data, 1))
def analysis(setup, grid_layout, psi_coord, options_dict, GC_max): options_str = str(options_dict) options = Options(**options_dict) simulation = Simulation(setup, grid_layout, psi_coord, options, GC_max) result = { "n": [], "n_analytical": [], "error_norm_L2": [], "wall_time": [] } last_step = 0 for n_steps in simulation.out_steps: steps = n_steps - last_step wall_time = simulation.step(steps) if steps > 0 else 0 last_step += steps result['n'].append(simulation.n_of_r.copy()) result['wall_time'].append(wall_time) result['r'] = simulation.r.copy() result['rh'] = simulation.rh.copy() result['dx'] = simulation.dx return Result(grid_layout_str=grid_layout.__class__.__name__, option_str=options_str, result=result, out_steps=simulation.out_steps, dt=simulation.dt)
def test_upwind(shape, ij0, out, courant_number): value = 44 scalar_field_init = np.zeros(shape) scalar_field_init[ij0] = value vector_field_init = ( np.full((shape[0] + 1, shape[1]), courant_number[0]), np.full((shape[0], shape[1] + 1), courant_number[1]) ) options = Options(n_iters=1) bcs = (Periodic(), Periodic()) advectee = ScalarField(scalar_field_init, halo=options.n_halo, boundary_conditions=bcs) advector = VectorField(vector_field_init, halo=options.n_halo, boundary_conditions=bcs) mpdata = Solver( stepper=Stepper(options=options, grid=shape, n_threads=1), advector=advector, advectee=advectee ) mpdata.advance(n_steps=1) np.testing.assert_array_equal( mpdata.advectee.get(), out )
def test_mu_arg_handling(case): opt = Options(non_zero_mu_coeff=case['non_zero_mu_coeff']) advector = VectorField((np.asarray([1., 2, 3]),), opt.n_halo, BCS) advectee = ScalarField(np.asarray([4., 5]), opt.n_halo, BCS) stepper = Stepper(options=opt, n_dims=1) sut = Solver(stepper, advectee, advector, case['g_factor']) sut.advance(1, mu_coeff=case['mu'])
def test_timing_3d(benchmark, options, dtype, static, num_threads): numba.set_num_threads(num_threads) settings = Settings(n=20, dt=1) simulation = Simulation(settings, Options(**options, dtype=dtype), static=static) def reset(): simulation.solver.advectee.get()[:] = settings.advectee n_steps = 10 benchmark.pedantic(simulation.run, (n_steps,), setup=reset, warmup_rounds=1, rounds=1)
def test_shared_advector(): n_x = 100 arr = np.zeros(n_x) opt1 = Options(n_iters=2, DPDC=True) opt2 = Options(n_iters=2) b_c = (Periodic(),) halo = opt1.n_halo assert opt2.n_halo == halo advector = VectorField(data=(np.zeros(n_x + 1),), halo=halo, boundary_conditions=b_c) _ = Solver( stepper=Stepper(options=opt1, grid=(n_x,)), advectee=ScalarField(data=arr, halo=halo, boundary_conditions=b_c), advector=advector ) solver = Solver( stepper=Stepper(options=opt2, grid=(n_x,)), advectee=ScalarField(data=arr, halo=halo, boundary_conditions=b_c), advector=advector ) solver.advance(1)
def make_data(setup, grid, opts): options = Options(**opts) simulation = Simulation(setup=setup, grid_layout=grid, psi_coord=x_id(), opts=options, GC_max=default_GC_max) result = {"wall_time": []} last_step = 0 for n_steps in simulation.out_steps: steps = n_steps - last_step wall_time_per_timestep = simulation.step(steps) last_step += steps result['wall_time'].append(wall_time_per_timestep) return result
def __init__( self, nz, dt, advector_of_t, advectee_of_zZ_at_t0, g_factor_of_zZ, mpdata_settings, ): self.__t = 0 self.dt = dt self.advector_of_t = advector_of_t grid = (nz, ) options = Options( n_iters=mpdata_settings["n_iters"], infinite_gauge=mpdata_settings["iga"], nonoscillatory=mpdata_settings["fct"], third_order_terms=mpdata_settings["tot"], ) stepper = Stepper(options=options, grid=grid, non_unit_g_factor=True) bcs = (Extrapolated(), ) zZ_scalar = arakawa_c.z_scalar_coord(grid) / nz g_factor = ScalarField( data=g_factor_of_zZ(zZ_scalar), halo=options.n_halo, boundary_conditions=bcs, ) advector = VectorField( data=(np.full(nz + 1, advector_of_t(0)), ), halo=options.n_halo, boundary_conditions=bcs, ) self.advectee = ScalarField( data=advectee_of_zZ_at_t0(zZ_scalar), halo=options.n_halo, boundary_conditions=bcs, ) self.solver = Solver( stepper=stepper, advectee=self.advectee, advector=advector, g_factor=g_factor, )
def test_formulae_upwind(): # Arrange psi_data = np.array((0, 1, 0)) flux_data = np.array((0, 0, 1, 0)) options = Options() halo = options.n_halo traversals = Traversals(grid=psi_data.shape, halo=halo, jit_flags=options.jit_flags, n_threads=1) upwind = make_upwind(options=options, non_unit_g_factor=False, traversals=traversals) boundary_conditions = (Periodic(), ) psi = ScalarField(psi_data, halo, boundary_conditions) psi.assemble(traversals) psi_impl = psi.impl flux = VectorField((flux_data, ), halo, boundary_conditions) flux.assemble(traversals) flux_impl = flux.impl # Act with warnings.catch_warnings(): warnings.simplefilter('ignore', category=NumbaExperimentalFeatureWarning) upwind( traversals.null_impl, _Impl(field=psi_impl[IMPL_META_AND_DATA], bc=psi_impl[IMPL_BC]), _Impl(field=flux_impl[IMPL_META_AND_DATA], bc=flux_impl[IMPL_BC]), _Impl(field=traversals.null_impl.scalar[IMPL_META_AND_DATA], bc=traversals.null_impl.scalar[IMPL_BC])) # Assert np.testing.assert_array_equal(psi.get(), np.roll(psi_data, 1))
def test_upwind_1d(): state = np.array([0, 1, 0]) courant = 1 options = Options(n_iters=1) mpdata = Solver( stepper=Stepper(options=options, n_dims=len(state.shape), non_unit_g_factor=False), advectee=ScalarField( state.astype(options.dtype), halo=options.n_halo, boundary_conditions=(Periodic(),) ), advector=VectorField( (np.full(state.shape[0] + 1, courant, dtype=options.dtype),), halo=options.n_halo, boundary_conditions=(Periodic(),) ) ) n_steps = 5 conserved = np.sum(mpdata.advectee.get()) mpdata.advance(n_steps) assert np.sum(mpdata.advectee.get()) == conserved
from PyMPDATA.arakawa_c.traversals import Traversals from PyMPDATA.arakawa_c.meta import META_HALO_VALID from PyMPDATA import Options, ScalarField, VectorField, ConstantBoundaryCondition from PyMPDATA.arakawa_c.indexers import indexers from PyMPDATA.arakawa_c.enumerations import MAX_DIM_NUM, INNER, MID3D, OUTER, IMPL_META_AND_DATA, IMPL_BC, \ META_AND_DATA_META, ARG_FOCUS, INVALID_INDEX import pytest import numba import numpy as np jit_flags = Options().jit_flags @numba.njit(**jit_flags) def cell_id(i, j, k): if i == INVALID_INDEX: i = 0 if j == INVALID_INDEX: j = 0 return 100 * i + 10 * j + k @numba.njit(**jit_flags) def _cell_id_scalar(value, arg_1_vec, arg_2_scl, arg_3_scl, arg_4_scl): focus = arg_1_vec[ARG_FOCUS] if focus != arg_2_scl[ARG_FOCUS]: raise Exception() if focus != arg_3_scl[ARG_FOCUS]: raise Exception() if focus != arg_4_scl[ARG_FOCUS]: raise Exception()
def rhod_of_z(arg): return 1 - arg * 1e-4 RHOD = np.repeat(rhod_of_z((np.arange(GRID[1]) + 1 / 2) / GRID[1]).reshape( (1, GRID[1])), GRID[0], axis=0) VALUES = {'th': np.full(GRID, 300), 'qv': np.full(GRID, .001)} @pytest.mark.parametrize( "options", (Options(n_iters=1), Options(n_iters=2), Options(n_iters=2, nonoscillatory=True), Options(n_iters=3, nonoscillatory=True), Options(n_iters=2, nonoscillatory=True, infinite_gauge=True), Options(nonoscillatory=True, infinite_gauge=True, third_order_terms=True), Options(nonoscillatory=False, infinite_gauge=True), Options(nonoscillatory=False, third_order_terms=True), Options(nonoscillatory=False, infinite_gauge=True, third_order_terms=True))) def test_single_timestep(options): # Arrange stepper = Stepper(options=options, grid=GRID, non_unit_g_factor=True) advector = nondivergent_vector_field_2d(GRID, SIZE, TIMESTEP, stream_function, options.n_halo) g_factor = ScalarField(RHOD.astype(dtype=options.dtype), halo=options.n_halo,
from PyMPDATA_examples.Molenkamp_test_as_in_Jaruga_et_al_2015_Fig_12.simulation import Simulation from PyMPDATA_examples.Molenkamp_test_as_in_Jaruga_et_al_2015_Fig_12.setup import Setup from PyMPDATA import Options from joblib import Parallel, delayed options = { 'upwind': Options(n_iters=1), '2+fct': Options(n_iters=2, flux_corrected_transport=True), '3+fct+tot': Options(n_iters=3, flux_corrected_transport=True, third_order_terms=True), '2+fct+iga': Options(n_iters=2, flux_corrected_transport=True, infinite_gauge=True) } def compute_panel(panel): setup = Setup(n_rotations=6) simulation = Simulation(setup, options[panel]) if panel == 'upwind': return simulation.state simulation.run() return simulation.state def fig_12_data(): data = Parallel(n_jobs=-2)( delayed(compute_panel)(panel) for panel in ['upwind', '2+fct', '3+fct+tot', '2+fct+iga']) return data
# pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring import pytest from PyMPDATA import Options from PyMPDATA.impl.domain_decomposition import make_subdomain JIT_FLAGS = Options().jit_flags @pytest.mark.parametrize( "span, rank, size, result", [(10, 0, 1, (0, 10)), pytest.param(1, 1, 1, (0, 1), marks=pytest.mark.xfail(raises=ValueError)), (10, 0, 3, (0, 4)), (10, 1, 3, (4, 8)), (10, 2, 3, (8, 10)), (10, 0, 11, (0, 1)), (10, 9, 11, (9, 10))]) def test_subdomain(span, rank, size, result): subdomain = make_subdomain(JIT_FLAGS) assert subdomain(span, rank, size) == result
import numpy as np import pytest from PyMPDATA import Solver, Stepper, ScalarField, VectorField, Options from PyMPDATA.boundary_conditions import Periodic BCS = (Periodic(),) @pytest.mark.parametrize("case", ( {'g_factor': None, 'non_zero_mu_coeff': True, 'mu': None}, {'g_factor': None, 'non_zero_mu_coeff': True, 'mu': (0,)}, pytest.param({ 'g_factor': None, 'non_zero_mu_coeff': False, 'mu': (0,) }, marks=pytest.mark.xfail(strict=True)), pytest.param({ 'g_factor': ScalarField(np.asarray([1., 1]), Options().n_halo, BCS), 'non_zero_mu_coeff': True, 'mu': None }, marks=pytest.mark.xfail(strict=True)) )) def test_mu_arg_handling(case): opt = Options(non_zero_mu_coeff=case['non_zero_mu_coeff']) advector = VectorField((np.asarray([1., 2, 3]),), opt.n_halo, BCS) advectee = ScalarField(np.asarray([4., 5]), opt.n_halo, BCS) stepper = Stepper(options=opt, n_dims=1) sut = Solver(stepper, advectee, advector, case['g_factor']) sut.advance(1, mu_coeff=case['mu'])
def test_mpdata_2d(case_data): case = { "nx": case_data[0], "ny": case_data[1], "Cx": case_data[2], "Cy": case_data[3], "nt": case_data[4], "ni": case_data[5], "dimsplit": case_data[6], "input": case_data[7], "output": case_data[8] } # Arrange data = case["input"].reshape((case["nx"], case["ny"])) courant = [case["Cx"], case["Cy"]] options = Options(n_iters=case["ni"], dimensionally_split=case["dimsplit"]) grid = data.shape advector_data = [ np.full((grid[0] + 1, grid[1]), courant[0], dtype=options.dtype), np.full((grid[0], grid[1] + 1), courant[1], dtype=options.dtype) ] bcs = (Periodic(), Periodic()) advector = VectorField(advector_data, halo=options.n_halo, boundary_conditions=bcs) advectee = ScalarField(data=data.astype(dtype=options.dtype), halo=options.n_halo, boundary_conditions=bcs) stepper = Stepper(options=options, grid=grid, non_unit_g_factor=False) mpdata = Solver(stepper=stepper, advectee=advectee, advector=advector) sut = mpdata
def __init__(self, *, advectees, stream_function, rhod_of_zZ, dt, grid, size, displacement, n_iters=2, infinite_gauge=True, nonoscillatory=True, third_order_terms=False): self.grid = grid self.size = size self.dt = dt self.stream_function = stream_function self.stream_function_time_dependent = ( "t" in inspect.signature(stream_function).parameters) self.asynchronous = False self.thread: (Thread, None) = None self.displacement = displacement self.t = 0 options = Options( n_iters=n_iters, infinite_gauge=infinite_gauge, nonoscillatory=nonoscillatory, third_order_terms=third_order_terms, ) disable_threads_if_needed = {} if not conf.JIT_FLAGS["parallel"]: disable_threads_if_needed["n_threads"] = 1 stepper = Stepper(options=options, grid=self.grid, non_unit_g_factor=True, **disable_threads_if_needed) advector_impl = VectorField( ( np.full((grid[0] + 1, grid[1]), np.nan), np.full((grid[0], grid[1] + 1), np.nan), ), halo=options.n_halo, boundary_conditions=(Periodic(), Periodic()), ) g_factor = make_rhod(self.grid, rhod_of_zZ) g_factor_impl = ScalarField( g_factor.astype(dtype=options.dtype), halo=options.n_halo, boundary_conditions=(Periodic(), Periodic()), ) self.g_factor_vec = ( rhod_of_zZ(zZ=x_vec_coord(self.grid)[-1]), rhod_of_zZ(zZ=z_vec_coord(self.grid)[-1]), ) self.mpdatas = {} for k, v in advectees.items(): advectee_impl = ScalarField( np.asarray(v, dtype=options.dtype), halo=options.n_halo, boundary_conditions=(Periodic(), Periodic()), ) self.mpdatas[k] = Solver( stepper=stepper, advectee=advectee_impl, advector=advector_impl, g_factor=g_factor_impl, )
delta_y = (yrange[1] - yrange[0]) / gridsize[1] for i in range(gridsize[0]): for j in range(gridsize[1]): psi[i, j] = pdf(xrange[0] + delta_x * (i + .5), yrange[0] + delta_y * (j + .5)) coord_x = np.linspace(xrange[0] + delta_x / 2, xrange[1] - delta_x / 2, gridsize[0]) coord_y = np.linspace(yrange[0] + delta_y / 2, yrange[1] - delta_y / 2, gridsize[1]) return coord_x, coord_y, psi @pytest.mark.parametrize( "options", [ Options(n_iters=1), Options(n_iters=2), Options(n_iters=3, infinite_gauge=True), Options(n_iters=2, infinite_gauge=True, nonoscillatory=True), # Options(n_iters=3, infinite_gauge=False, third_order_terms=True), # Options(n_iters=3, infinite_gauge=True, third_order_terms=True, nonoscillatory=True), ]) @pytest.mark.parametrize("grid_static_str", ("static", "dynamic")) # pylint: disable-next=redefined-outer-name def test_timing_2d(benchmark, options, grid_static_str, num_threads, plot=False): if grid_static_str == "static": grid_static = True
# pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring import pytest import numpy as np from PyMPDATA_examples.Smolarkiewicz_1984 import Settings, Simulation from PyMPDATA import Options # https://github.com/igfuw/libmpdataxx/blob/master/tests/paper_2015_GMD/4_revolving_sphere_3d/... STATS = { # ...refdata/stats_upwind.txt.gz Options(n_iters=1): { 0: { 'min(solution)': 0.00000000, 'max(solution)': 4.00000000, }, 566: { 'max(solution)': 1.72131033, 'min(solution)': 0.00000000, 'Linf': 3.38441916, 'L2': 0.00567238, 'L1': 0.00128141, } }, # ...refdata/stats_basic.txt.gz Options(n_iters=2): { 0: { 'min(solution)': 0.00000000, 'max(solution)': 4.00000000, }, 556: { 'max(solution)': 4.94170863, 'min(solution)': 0.00000000,