def test_simulation_persistence(compression, tmp_path): """test whether a tracker can accurately store information about simulation""" path = tmp_path / "test_simulation_persistence.hdf5" storage = FileStorage(path, compression=compression) # write some simulation data pde = DiffusionPDE() grid = UnitGrid([16, 16]) # generate grid state = ScalarField.random_uniform(grid, 0.2, 0.3) pde.solve(state, t_range=0.11, dt=0.001, tracker=storage.tracker(interval=0.05)) storage.close() # read the data storage = FileStorage(path) np.testing.assert_almost_equal(storage.times, [0, 0.05, 0.1]) data = np.array(storage.data) assert data.shape == (3, ) + state.data.shape grid_res = storage.grid assert grid == grid_res grid_res = storage.grid assert grid == grid_res
def test_diffusion_cached(): """test some caching of rhs of the simple diffusion model""" grid = UnitGrid([8]) c0 = ScalarField.random_uniform(grid) # first run without cache eq1 = DiffusionPDE(diffusivity=1) eq1.cache_rhs = False c1a = eq1.solve(c0, t_range=1, dt=0.1, backend="numba", tracker=None) eq1.diffusivity = 0.1 c1b = eq1.solve(c1a, t_range=1, dt=0.1, backend="numba", tracker=None) # then run with cache eq2 = DiffusionPDE(diffusivity=1) eq2.cache_rhs = True c2a = eq2.solve(c0, t_range=1, dt=0.1, backend="numba", tracker=None) eq2.diffusivity = 0.1 c2b = eq2.solve(c2a, t_range=1, dt=0.1, backend="numba", tracker=None) eq2._cache = {} # clear cache c2c = eq2.solve(c2a, t_range=1, dt=0.1, backend="numba", tracker=None) np.testing.assert_allclose(c1a.data, c2a.data) assert not np.allclose(c1b.data, c2b.data) np.testing.assert_allclose(c1b.data, c2c.data)
def test_storage_truncation(tmp_path): """ test whether simple trackers can be used """ file = tmp_path / "test_storage_truncation.hdf5" for truncate in [True, False]: storages = [MemoryStorage()] if module_available("h5py"): storages.append(FileStorage(file)) tracker_list = [s.tracker(interval=0.01) for s in storages] grid = UnitGrid([8, 8]) state = ScalarField.random_uniform(grid, 0.2, 0.3) pde = DiffusionPDE() pde.solve(state, t_range=0.1, dt=0.001, tracker=tracker_list) if truncate: for storage in storages: storage.clear() pde.solve(state, t_range=[0.1, 0.2], dt=0.001, tracker=tracker_list) times = np.arange(0.1, 0.201, 0.01) if not truncate: times = np.r_[np.arange(0, 0.101, 0.01), times] for storage in storages: msg = f"truncate={truncate}, storage={storage}" np.testing.assert_allclose(storage.times, times, err_msg=msg) assert not storage.has_collection
def test_unsupported_stochastic_solvers(): """test some solvers that do not support stochasticity""" field = ScalarField.random_uniform(UnitGrid([16]), -1, 1) eq = DiffusionPDE(noise=1) with pytest.raises(RuntimeError): eq.solve(field, 1, method="explicit", scheme="runge-kutta", tracker=None) with pytest.raises(RuntimeError): eq.solve(field, 1, method="scipy", scheme="runge-kutta", tracker=None)
def test_writing_to_storage(tmp_path): """test whether data is written to storage""" state = ScalarField.random_uniform(UnitGrid([3])) pde = DiffusionPDE() path = tmp_path / "test_writing_to_storage.hdf5" data = FileStorage(filename=path) pde.solve(state, t_range=1.1, dt=0.1, tracker=[data.tracker(0.5)]) assert len(data) == 3
def test_length_scale_tracker(tmp_path): """test the length scale tracker""" path = tmp_path / "test_length_scale_tracker.json" grid = CartesianGrid([[0, 10 * np.pi]], 64, periodic=True) field = ScalarField.from_expression(grid, "sin(2 * x)") pde = DiffusionPDE() tracker = LengthScaleTracker(0.05, filename=path) pde.solve(field, t_range=0.1, backend="numpy", tracker=tracker) for ls in tracker.length_scales: assert ls == pytest.approx(np.pi, rel=1e-3) assert path.stat().st_size > 0 # wrote some result
def test_diffusion_time_dependent_bcs(backend): """test PDE with time-dependent BCs""" field = ScalarField(UnitGrid([3])) eq = DiffusionPDE(bc={"value_expression": "Heaviside(t - 1.5)"}) storage = MemoryStorage() eq.solve(field, t_range=10, dt=1e-2, backend=backend, tracker=storage.tracker(1)) np.testing.assert_allclose(storage[1].data, 0) np.testing.assert_allclose(storage[-1].data, 1, rtol=1e-3)
def main(equation: str = "cahn-hilliard", t_range: float = 100, size: int = 32): """main routine testing the performance Args: equation (str): Chooses the equation to consider t_range (float): Sets the total duration that should be solved for size (int): The number of grid points along each axis """ print("Reports duration in seconds (smaller is better)\n") # determine grid and initial state grid = UnitGrid([size, size], periodic=False) field = ScalarField.random_uniform(grid) print(f"GRID: {grid}") # determine the equation to solve if equation == "diffusion": eq = DiffusionPDE() elif equation == "cahn-hilliard": eq = CahnHilliardPDE() else: raise ValueError(f"Undefined equation `{equation}`") print(f"EQUATION: ∂c/∂t = {eq.expression}") print("\nSOLVER PERFORMANCE:") expected = eq.solve(field, t_range=t_range, dt=1e-5, tracker=None) solvers = { "Euler, fixed": (1e-3, ExplicitSolver(eq, scheme="euler", adaptive=False)), "Euler, adaptive": (1e-3, ExplicitSolver(eq, scheme="euler", adaptive=True)), "Runge-Kutta, fixed": (1e-3, ExplicitSolver(eq, scheme="rk", adaptive=False)), "Runge-Kutta, adaptive": (1e-3, ExplicitSolver(eq, scheme="rk", adaptive=True)), "implicit": (1e-3, ImplicitSolver(eq)), "scipy": (None, ScipySolver(eq)), } for name, (dt, solver) in solvers.items(): solver.backend = "numba" controller = Controller(solver, t_range=t_range, tracker=None) result = controller.run(field, dt=dt) # call once to pre-compile and test result if np.allclose(result.data, expected.data, atol=1e-2): # report the duration print(f"{name:>21s}: {controller.info['profiler']['solver']:.3g}") else: # report the mismatch print(f"{name:>21s}: MISMATCH")
def test_simple_diffusion_flux_right(): """test a simple diffusion equation with flux boundary on the right""" grid = CartesianGrid([[0, 1]], [16]) c = ScalarField.random_uniform(grid, 0, 1) b_l = {"type": "value", "value": 0} b_r = {"type": "derivative", "value": 3} pde = DiffusionPDE(bc=[b_l, b_r]) sol = pde.solve(c, t_range=5, dt=0.001, tracker=None) np.testing.assert_allclose(sol.data, 3 * grid.axes_coords[0], rtol=5e-3)
def main(): xstep=5 tstep=1 v=73.82/60#Unit:cm/s tmin=0 tmax=500 bc_T=f'-1*{llambda}/{h}*c.diff(x)+(Piecewise(\ ((25+{T_Kelvin}),tt<=20/{v}),\ ((25+150/{v}*(tt-20/{v})+{T_Kelvin}),And(20/{v}<tt,tt<=25/{v})),\ ((175+{T_Kelvin}),And(25/{v}<tt,tt<=197.5/{v})),\ ((175+20/{v}*(tt-197.5/{v})+{T_Kelvin}),And(197.5/{v}<tt,tt<=202.5/{v})),\ ((195+{T_Kelvin}),And(202.5/{v}<tt,tt<=233/{v})),\ ((195+40/{v}*(tt-233/{v})+{T_Kelvin}),And(233/{v}<tt,tt<=238/{v})),\ ((235+{T_Kelvin}),And(238/{v}<tt,tt<=268.5/{v})),\ ((235+20/{v}*(tt-268.5/{v})+{T_Kelvin}),And(268.5/{v}<tt,tt<=273.5/{v})),\ ((255+{T_Kelvin}),And(273.5/{v}<tt,tt<=344.5/{v})),\ ((255-230/{v}*(tt-344.5/{v})+{T_Kelvin}),And(344.5/{v}<tt,tt<=435.5/{v})),\ ((25+{T_Kelvin}),true)).subs(tt,t))' #ture需要小写,f'string'string里面有{}可以传递全局参数参数 grid = CartesianGrid([[0, x_max]], [int(xstep)],periodic=False) state=ScalarField(grid=grid,data=T_origin+T_Kelvin) eq = DiffusionPDE(diffusivity=alpha, bc={'value_expression':bc_T},) storage = MemoryStorage() eq.solve(state, t_range=(tmin,tmax),dt=1e-3, tracker=storage.tracker(tstep)) def temp_curve(): p=[] for i in range(int((tmax-tmin)/tstep)): p.append(storage.data[i][-1]) q=np.asarray(p) plt.plot(np.linspace(tmin,tmax,int((tmax-tmin)/tstep),endpoint=0),q,label='Temperature') plt.xlabel('Time') plt.ylabel('Temprature') plt.show() def plotky(): plot_kymograph(storage) #temp_curve() plotky()
def test_inhomogeneous_bcs(): """test simulation with inhomogeneous boundary conditions""" # single coordinate grid = CartesianGrid([[0, 2 * np.pi], [0, 1]], [32, 2], periodic=[True, False]) state = ScalarField(grid) pde = DiffusionPDE(bc=["natural", {"type": "value", "value": "sin(x)"}]) sol = pde.solve(state, t_range=1e1, dt=1e-2, tracker=None) data = sol.get_line_data(extract="project_x") np.testing.assert_almost_equal( data["data_y"], 0.9 * np.sin(data["data_x"]), decimal=2 ) # double coordinate grid = CartesianGrid([[0, 1], [0, 1]], [8, 8], periodic=False) state = ScalarField(grid) pde = DiffusionPDE(bc={"type": "value", "value": "x + y"}) sol = pde.solve(state, t_range=1e1, dt=1e-3, tracker=None) expect = ScalarField.from_expression(grid, "x + y") np.testing.assert_almost_equal(sol.data, expect.data)
def test_simple_diffusion_value(): """test a simple diffusion equation with constant boundaries""" grid = CartesianGrid([[0, 1]], [16]) c = ScalarField.random_uniform(grid, 0, 1) b_l = {"type": "value", "value": 0} b_r = {"type": "value", "value": 1} pde = DiffusionPDE(bc=[b_l, b_r]) sol, info = pde.solve(c, t_range=1, dt=0.001, tracker=None, ret_info=True) assert isinstance(info, dict) np.testing.assert_allclose(sol.data, grid.axes_coords[0], rtol=5e-3)
#!/usr/bin/env python3 from pde import UnitGrid, ScalarField, DiffusionPDE, MemoryStorage, movie_scalar eq = DiffusionPDE() # define the physics grid = UnitGrid([16, 16]) # generate grid state = ScalarField.random_uniform(grid, 0.2, 0.3) # generate initial condition storage = MemoryStorage() # create storage tracker = storage.tracker(interval=1) # create associated tracker eq.solve(state, t_range=2, dt=0.005, tracker=tracker) # create movie from stored data movie_scalar(storage, '/tmp/diffusion.mov')
def test_solver_in_pde_class(): """ test whether solver instances can be used in pde instances """ field = ScalarField.random_uniform(UnitGrid([16, 16]), -1, 1) eq = DiffusionPDE() eq.solve(field, t_range=1, method=ScipySolver, tracker=None)
#!/usr/bin/env python3 from pde import DiffusionPDE, UnitGrid, ScalarField eq = DiffusionPDE(diffusivity=0.1) # define the pde grid = UnitGrid([64, 64]) # generate grid state = ScalarField.random_uniform(grid, 0.2, 0.3) # generate initial condition result = eq.solve(state, t_range=10) result.plot(show=True)
""" Diffusion on a Cartesian grid ============================= This example shows how to solve the diffusion equation on a Cartesian grid. """ from pde import CartesianGrid, ScalarField, DiffusionPDE grid = CartesianGrid([[-1, 1], [0, 2]], [30, 16]) # generate grid state = ScalarField(grid) # generate initial condition state.add_interpolated([0, 1], 1) eq = DiffusionPDE() # define the pde result = eq.solve(state, t_range=1, dt=0.001) result.plot()
#!/usr/bin/env python3 from pde import UnitGrid, ScalarField, DiffusionPDE grid = UnitGrid([16, 16], periodic=[False, True]) # generate grid state = ScalarField.random_uniform(grid, 0.2, 0.3) # generate initial condition # set boundary conditions `bc` for all axes bc_x_left = {'type': 'derivative', 'value': 0.1} bc_x_right = {'type': 'value', 'value': 0} bc_x = [bc_x_left, bc_x_right] bc_y = 'periodic' eq = DiffusionPDE(bc=[bc_x, bc_y]) result = eq.solve(state, t_range=10, dt=0.005) result.plot(show=True)
#!/usr/bin/env python3 from pde import (DiffusionPDE, UnitGrid, ScalarField, MemoryStorage, PlotTracker, PrintTracker, RealtimeIntervals) eq = DiffusionPDE() # define the pde grid = UnitGrid([16, 16]) # generate grid state = ScalarField.random_uniform(grid, 0.2, 0.3) # generate initial condition storage = MemoryStorage() trackers = [ 'progress', # show progress bar during simulation 'steady_state', # abort when steady state is reached storage.tracker(interval=1), # store data every simulation time unit PlotTracker(show=True), # show images during simulation # print some output every 5 real seconds: PrintTracker(interval=RealtimeIntervals(duration=5)) ] eq.solve(state, 10, dt=0.1, tracker=trackers) storage[0].plot(show=True)