Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| """ | |
| Assuming constant D | |
| Original PDE, after multiplied by T (Normalize by final time) | |
| u_t = D laplace u + ρ u(1-u) | |
| where t = [0 1], D = D T, ρ = ρ T | |
| For radial symmetry solution , u(r,θ)=u(r), any derivative w.r.t angle is 0 | |
| see wiki https://en.wikipedia.org/wiki/Laplace_operator | |
| In polar coordinate , laplace u(r,θ) = u_rr + 1/r u_r | |
| In spherical coordinate , laplace u(r,θ,φ) = u_rr + 2/r u_r | |
| https://en.wikipedia.org/wiki/Del_in_cylindrical_and_spherical_coordinates | |
| In polar coordinate , grad u = u_r | |
| In spherical coordinate , grad u = u_r | |
| At r=R, Neuman boundary condition u_r = 0 | |
| At r=0, symmetric at origin, u_r = 0 | |
| Therefore, the whole pde is 1d pde on domain [0,R]: | |
| 2D u_t = D (u_xx + 1/x u_x) + ρ u (1-u), neuman bc | |
| 3D u_t = D (u_xx + 2/x u_x) + ρ u (1-u), neuman bc | |
| In PINN, we use a diffused domain, x=[0,1] | |
| (uϕ)_t = D div ( ϕ grad u) + ρ ϕ u(1-u) | |
| = D grad ϕ . grad u + D ϕ laplace u + ρ ϕ u(1-u) | |
| We have | |
| 2D u_t = D ( ϕ_x u_x + ϕ u_xx + ϕ 1/x u_x ) + ρ ϕ u (1-u), | |
| 3D u_t = D ( ϕ_x u_x + ϕ u_xx + ϕ 2/x u_x ) + ρ ϕ u (1-u), | |
| neuman bc at x=0 (for radial symmetry) | |
| choose neuman bc at x=1 (can be arbitrary) | |
| based on the manual | |
| https://py-pde.readthedocs.io/en/latest/getting_started.html | |
| this package use finite difference. The grid points are placed at cell center | |
| By default of pde.solve, ScipySolver with an automatic, adaptive time step provided by scipy is used. | |
| """ | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| from pde import PDE, CartesianGrid, MemoryStorage, ScalarField, plot_kymograph, UnitGrid | |
| Dim = 2# dimesion | |
| R = 0.5 # circle domain | |
| N = 50 # grid size | |
| T = 300 # final time | |
| xi,h = np.linspace(0,0.5,N,retstep=True) | |
| # time normalized coefficients | |
| D = T*0.13e-4 | |
| rho = T*0.025 | |
| #%% this does not use diffused domain | |
| # based on the example | |
| #https://py-pde.readthedocs.io/en/latest/examples_gallery/pde_heterogeneous_diffusion.html#sphx-glr-examples-gallery-pde-heterogeneous-diffusion-py | |
| eq = PDE({"u": f"{D}*laplace(u) + {Dim-1}*{D}*d_dx(u)/x + {rho}*u * (1-u)"},bc = {'derivative': 0}) | |
| grid = CartesianGrid([[0, R]], N) | |
| u0 = ScalarField.from_expression(grid, "0.1*exp(-1000*x**2)") | |
| # solve the equation and store the trajectory | |
| storage = MemoryStorage() | |
| eq.solve(u0, t_range=1, tracker=storage.tracker(0.1)) #interface to sample the solution | |
| #%% plot_kymograph(storage) | |
| x = np.array(storage.grid.coordinate_arrays) | |
| y = np.array(storage.data) | |
| plt.plot(x.T,y.T) | |
| #%% this part use diffused domain | |
| phi = "(0.5+0.5* tanh((0.5-x)/0.01))" | |
| pde = f"{D}*dot(gradient({phi}),gradient(u)) + {D}*{phi}*laplace(u) + {Dim-1}*{D}*{phi}*d_dx(u)/x + {phi}*{rho}*u*(1-u)" | |
| eq = PDE({"u": pde},bc = {'derivative': 0}) | |
| # the witdith of the diffused domain is approximated 0.02 | |
| # need to choose h such that arond 5 grid point resolve the interface | |
| grid = CartesianGrid([[0, 0.7]], 200) | |
| u0 = ScalarField.from_expression(grid, "0.1*exp(-1000*x**2)") | |
| # solve the equation and store the trajectory | |
| storage = MemoryStorage() | |
| eq.solve(u0, t_range=1, tracker=storage.tracker(0.1)) | |
| # plot_kymograph(storage) | |
| x = np.array(storage.grid.coordinate_arrays) | |
| y = np.array(storage.data) | |
| plt.plot(x.T,y.T) | |
| plt.xlim([0,R]) |