Time-dependent Heat Equation
The full solution can be found at basic_pdes.ipynb.
Problem Setup
\[\frac{\partial u}{\partial t} = 0.4 \frac{\partial^2 u}{\partial x^2}, x\in [0,1], t\in[0,1],\]
\[u(0,t)=u(1,t)=0, u(x,0)=\sin(\pi x)\]
Solution is \(u(x,t)=e^{-0.4\pi^2t} \sin(\pi x)\)
Implementation
-
Import necessary packages
-
Define problem
Here, we first set up the endogenous variables, equations, and initialize boundary conditions.pde2 = PDEModel("time_heat") # define pde model to solve pde2.set_state(["x", "t"], {"x": [0, 1.], "t": [0, 1.]}) # set the state variable, which defines the dimensionality of the problem pde2.add_endog("u") # we use endogenous variable to represent the function we want to approximate pde2.add_endog_equation(r"$\frac{\partial u}{\partial t} = 0.4 * \frac{\partial^2 u}{\partial x^2}$", label="base_pde") # endogenous equations are used to represent the PDE zero_xs = torch.zeros((100, 2)) # Create a tensor for boundary condition at x = 0, with t values from 0 to 1 zero_xs[:, 1] = torch.Tensor(np.linspace(0, 1, 100)) one_xs = torch.ones((100, 2)) # Create a tensor for boundary condition at x = 1, with t values from 0 to 1 one_xs[:, 1] = torch.Tensor(np.linspace(0, 1, 100)) zero_ts = torch.zeros((100, 2)) # Create a tensor for initial condition at t = 0, with x values from 0 to 1 zero_ts[:, 0] = torch.Tensor(np.linspace(0, 1, 100)) u_zero_ts = torch.sin(torch.pi * zero_ts[:, 0:1]) pde2.add_endog_condition("u", "u(SV)", {"SV": zero_xs}, Comparator.EQ, "0", {}, label="bc_zerox") # Add boundary condition pde2.add_endog_condition("u", "u(SV)", {"SV": one_xs}, Comparator.EQ, "0", {}, label="bc_onex") # Add boundary condition pde2.add_endog_condition("u", "u(SV)", {"SV": zero_ts}, Comparator.EQ, "u_zero_ts", {"u_zero_ts": u_zero_ts}, label="ic") # Add initial condition
-
Train and evaluate
-
To load a trained model
-
Plot the solutions
fig, ax = plt.subplots(1, 1, figsize=(5, 5), subplot_kw={"projection": "3d"}) x_np = np.linspace(0, 1, 100) t_np = np.linspace(0, 1, 100) X, T = np.meshgrid(x_np, t_np) exact_Z = np.exp(-0.4*np.pi**2 * T) * np.sin(np.pi*X) ax.plot_surface(X, T, exact_Z, label="exact", alpha=0.6) pde2.endog_vars["u"].plot("u", {"x": [0, 1.], "y": [0, 1.]}, ax=ax) plt.subplots_adjust() plt.show()