以下是用于求解具有周期性边界条件的热/扩散方程的代码。因此,在计算每个RK步骤的导数函数时,我需要在输入向量和Toeplitz矩阵之间做一个点积。对于第一次迭代(已通过scipy.integrate结果检查),这是正确发生的,而对于第二次以后,则出了问题,解决方案崩溃了。我无法弄清楚什么是问题所在。请帮忙。 该代码是对https://gist.github.com/michaelosthege/a75b565d3f653721fa235a07eb089912的修改。
import abc
import theano.tensor as tt
import theano
import numpy as np
from scipy.linalg import inv, toeplitz
#################################### Integrator class #############################
class Integrator(object):
__metaclass__ = abc.ABCMeta
def step(self, t, dt, y, dydt, theta):
raise NotImplementedError()
class TheanoIntegrationOps(object):
def __init__(self, dydt_theano, integrator:Integrator):
self.dydt_theano = dydt_theano
self.integrator = integrator
return super().__init__()
def __step_theano(self, t, y_t, dt_t, nrk4steps, t_theta):
return self.integrator.step(t, dt_t, y_t, self.dydt_theano,
nrk4steps, t_theta)
def __call__(self, y0, theta, times, nrk4steps):
t_y0 = tt.as_tensor_variable(y0)
t_theta = tt.as_tensor_variable(theta)
t_times = tt.as_tensor_variable(times)
dt = (times[1] - times[0])/nrk4steps
Y_hat, updates = theano.scan(fn=self.__step_theano,
outputs_info =[{'initial':t_y0}],
sequences=[t_times],
non_sequences=[dt, nrk4steps, t_theta],
n_steps=len(times)-1)
Y_hat = tt.concatenate((t_y0[None,:], Y_hat))
Y_hat = tt.transpose(Y_hat)
return Y_hat
# Simple RK integrator
class RungeKutta(Integrator):
def step(self, t, dt, y, dydt, nrk4steps, theta):
for i in range(nrk4steps.eval()):
k1 = dt*dydt(y, t, theta)
k2 = dt*dydt(y + 0.5*k1, t, theta)
k3 = dt*dydt(y + 0.5*k2, t, theta)
k4 = dt*dydt(y + k3, t, theta)
y = y + (1./6.)*k1 + (1./3.)*k2 + (1./3.)*k3 + (1./6.)*k4
return y
#################################################################
# The derivative function for heat equation
def dydt(c, t, theta):
nx = 128
gridx = np.arange(0.0, 1, 1.0/nx)
dx = gridx[1] - gridx[0]
z = np.zeros_like(gridx)
z[0] = -2
z[1] = 1
z[-1] = 1
diff = 2
diff_matrix = toeplitz(z) / dx**2
diff_matrix = tt.as_tensor_variable(diff_matrix)
dc_dt = tt.zeros_like(c)
# This is what causes the problem
dc_dt = theano.dot(c, diff_matrix)
return dc_dt
if __name__=="__main__":
# Number of RK4 iterations between each time point
nrk4steps = 1
# Time points
times=np.linspace(0,1,101)
# Initial Condition
nx = 128
gridx = np.arange(0.0, 1, 1.0/nx)
T_y0 = np.sin(2*np.pi*gridx)
# Diffusion constant
T_theta = [2.0,]
integrator = RungeKutta()
Y_hat_TV = TheanoIntegrationOps(dydt, integrator)(
T_y0, T_theta, times, nrk4steps)
Ysim = np.transpose(Y_hat_TV.eval())
print(Ysim)
~