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 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 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_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)
def test_inhomogeneous_bcs(): """ test simulation with inhomogeneous boundary conditions """ 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)
def test_diffusion_single(): """test some methods of the simple diffusion model""" eq = DiffusionPDE() assert isinstance(str(eq), str) assert isinstance(repr(eq), str) assert not eq.explicit_time_dependence grid = UnitGrid([4, 4]) state = ScalarField.random_uniform(grid) field = eq.evolution_rate(state) assert isinstance(field, ScalarField) assert field.grid == grid
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 test_stochastic_solvers(backend): """ test simple version of the stochastic solver """ field = ScalarField.random_uniform(UnitGrid([16]), -1, 1) eq = DiffusionPDE() seq = DiffusionPDE(noise=1e-6) solver1 = ExplicitSolver(eq, backend=backend) c1 = Controller(solver1, t_range=1, tracker=None) s1 = c1.run(field, dt=1e-3) solver2 = ExplicitSolver(seq, backend=backend) c2 = Controller(solver2, t_range=1, tracker=None) s2 = c2.run(field, dt=1e-3) np.testing.assert_allclose(s1.data, s2.data, rtol=1e-4, atol=1e-4) assert not solver1.info["stochastic"] assert solver2.info["stochastic"]
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_stochastic_adaptive_solver(caplog): """test using an adaptive, stochastic solver""" field = ScalarField.random_uniform(UnitGrid([16]), -1, 1) eq = DiffusionPDE(noise=1e-6) with caplog.at_level(logging.WARNING): solver = ExplicitSolver(eq, backend="numpy", adaptive=True) c = Controller(solver, t_range=1, tracker=None) c.run(field, dt=1e-2) assert "fixed" in caplog.text
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_no_dt(): """ test scipy solver without timestep """ grid = UnitGrid([16]) field = ScalarField.random_uniform(grid, -1, 1) eq = DiffusionPDE() c1 = Controller(ScipySolver(eq), t_range=1, tracker=None) s1 = c1.run(field, dt=1e-3) c2 = Controller(ScipySolver(eq), t_range=1, tracker=None) s2 = c2.run(field) np.testing.assert_allclose(s1.data, s2.data, rtol=1e-3, atol=1e-3)
def test_compare_solvers(solver_class): """compare several solvers""" field = ScalarField.random_uniform(UnitGrid([8, 8]), -1, 1) eq = DiffusionPDE() # ground truth c1 = Controller(ExplicitSolver(eq, scheme="runge-kutta"), t_range=0.1, tracker=None) s1 = c1.run(field, dt=5e-3) c2 = Controller(solver_class(eq), t_range=0.1, tracker=None) with np.errstate(under="ignore"): s2 = c2.run(field, dt=5e-3) np.testing.assert_allclose(s1.data, s2.data, rtol=1e-2, atol=1e-2)
def test_compare_explicit(): """ test explicit solvers """ grid = UnitGrid([16, 16]) field = ScalarField.random_uniform(grid, -1, 1) eq = DiffusionPDE() c1 = Controller(ExplicitSolver(eq), t_range=0.1, tracker=None) s1 = c1.run(field, dt=2e-3) c2 = Controller(ExplicitSolver(eq, scheme="runge-kutta"), t_range=0.1, tracker=None) with np.errstate(under="ignore"): s2 = c2.run(field, dt=2e-3) np.testing.assert_allclose(s1.data, s2.data, rtol=1e-2, atol=1e-2)
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_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=["auto_periodic_neumann", { "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)
#!/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)
""" Solver comparison ================= This example shows how to set up solvers explicitly and how to extract diagnostic information. """ from pde import (UnitGrid, ScalarField, FieldCollection, DiffusionPDE, ExplicitSolver, ScipySolver, Controller) # initialize the grid, an initial condition, and the PDE grid = UnitGrid([32, 32]) field = ScalarField.random_uniform(grid, -1, 1) eq = DiffusionPDE() # try the explicit solver solver1 = ExplicitSolver(eq) controller1 = Controller(solver1, t_range=1, tracker=None) sol1 = controller1.run(field, dt=1e-3) sol1.label = 'explicit solver' print('Diagnostic information from first run:') print(controller1.diagnostics) print() # try the standard scipy solver solver2 = ScipySolver(eq) controller2 = Controller(solver2, t_range=1, tracker=None) sol2 = controller2.run(field) sol2.label = 'scipy solver' print('Diagnostic information from second run:')
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)
""" 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()
""" Using simulation trackers ========================= This example illustrates how trackers can be used to analyze simulations. """ from pde import (DiffusionPDE, UnitGrid, ScalarField, MemoryStorage, PlotTracker, PrintTracker, RealtimeIntervals) grid = UnitGrid([32, 32]) # generate grid state = ScalarField.random_uniform(grid) # 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 = DiffusionPDE(0.1) # define the PDE eq.solve(state, 3, dt=0.1, tracker=trackers) for field in storage: print(field.integral)
#!/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 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)
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)
#!/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')
""" Spherically symmetric PDE ========================= This example illustrates how to solve a PDE in a spherically symmetric geometry. """ from pde import DiffusionPDE, SphericalGrid, ScalarField grid = SphericalGrid(radius=[1, 5], shape=128) # generate grid state = ScalarField.random_uniform(grid) # generate initial condition eq = DiffusionPDE(0.1) # define the PDE result = eq.solve(state, t_range=0.1, dt=0.001) result.plot(kind='image')