使用DeepXDE求解复值PDE时遇ValueError问题求助
解决DeepXDE求解复值PDE时的
ValueError: i=0 is not valid错误 问题场景
我尝试用DeepXDE求解复值偏微分方程,编写代码后运行抛出ValueError: i=0 is not valid错误,相关代码和错误信息如下:
原始代码
import deepxde as dde from deepxde.backend import pytorch import numpy as np geom = dde.geometry.Interval(0, 10000) f = 0.1 omega = 2 * np.pi * f mu = 4 * np.pi * 1e-7 sigma = 100 xc = 100 a = np.sqrt(-1j * omega * mu * sigma) def pde(x, y): y_real, y_imag = y[:, 0:1], y[:, 1:2] dy_xx_real = dde.grad.hessian(y_real, x, component=None, i=0, j=0) dy_xx_imag = dde.grad.hessian(y_imag, x, component=None, i=0, j=0) # dy_xx = dde.grad.hessian(y, x) # return dy_xx + omega * mu * sigma * y return [dy_xx_real - omega * mu * sigma * y_imag, dy_xx_imag + omega * mu * sigma * y_real] def boundary_dirichlet(x, on_boundary): return on_boundary and dde.utils.isclose(x[0], 0) def boundary_robin(x, on_boundary): return on_boundary and dde.utils.isclose(x[0], xc) def func1(x): return 1 bc_1 = dde.icbc.DirichletBC(geom, func1, boundary_dirichlet) bc_3_real = dde.icbc.RobinBC(geom, lambda x, y: -np.real(a)*y, boundary_robin) bc_3_imag = dde.icbc.RobinBC(geom, lambda x, y: -np.imag(a)*y, boundary_robin) data = dde.data.PDE(geom, pde, [bc_1, bc_3_real, bc_3_imag], 16, 5, solution=None, num_test=100) layer_size = [1] + [50] * 3 + [1] activation = "tanh" initializer = "Glorot uniform" net = dde.nn.FNN(layer_size, activation, initializer) model = dde.Model(data, net) model.compile("adam", lr=0.001, metrics=["l2 relative error"]) losshistory, train_state = model.train(iterations=5000) dde.saveplot(losshistory, train_state, issave=True, isplot=True)
错误信息
C:\Users\Thinkpad\anaconda3\envs\PINNs\python.exe C:/Users/Thinkpad/anaconda3/envs/PINNs/Lib/site-packages/deepxde/data/gsghjsg.py Using backend: pytorch Other supported backends: tensorflow.compat.v1, tensorflow, jax, paddle. paddle supports more examples now and is recommended. Compiling model... 'compile' took 0.579541 s Training model... Traceback (most recent call last): File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\data\gsghjsg.py", line 53, in losshistory, train_state = model.train(iterations=5000) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\utils\internal.py", line 22, in wrapper result = f(*args, **kwargs) ^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\model.py", line 631, in train self._test() File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\model.py", line 820, in _test ) = self._outputs_losses( ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\model.py", line 541, in _outputs_losses outs = outputs_losses(inputs, targets, auxiliary_vars) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\model.py", line 316, in outputs_losses_train return outputs_losses( ^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\model.py", line 304, in outputs_losses losses = losses_fn(targets, outputs_, loss_fn, inputs, self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\data\data.py", line 13, in losses_train return self.losses(targets, outputs, loss_fn, inputs, model, aux=aux) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\data\pde.py", line 140, in losses f = self.pde(inputs, outputs_pde) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\data\gsghjsg.py", line 18, in pde dy_xx_imag = dde.grad.hessian(y_imag, x, component=None, i=0, j=0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\gradients.py", line 283, in hessian return hessian._Hessians(ys, xs, component=component, i=i, j=j, grad_y=grad_y) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\gradients.py", line 250, in __call__ self.Hs[key] = Hessian(y, xs, component=component, grad_y=grad_y) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\gradients.py", line 223, in __init__ grad_y = jacobian(y, xs, i=component, j=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\gradients.py", line 181, in jacobian return jacobian._Jacobians(ys, xs, i=i, j=j) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\gradients.py", line 153, in __call__ return self.Js[key](i, j) ^^^^^^^^^^^^^^^^^^ File "C:\Users\Thinkpad\anaconda3\envs\PINNs\Lib\site-packages\deepxde\gradients.py", line 39, in __call__ raise ValueError("i={} is not valid.".format(i)) ValueError: i=0 is not valid. Process finished with exit code 1
错误原因
- 网络输出维度错误:原代码中网络输出层维度为
1,但需要同时拟合复值解的实部和虚部,输出维度应为2,导致后续切片操作y[:,0:1]和y[:,1:2]实际获取的是无效张量。 - 导数调用参数错误:对切片后的单分量张量
y_real/y_imag调用dde.grad.hessian时,指定了component=None和i=0,j=0,而单分量张量不需要指定component参数,内部Jacobian计算时索引越界引发错误。 - 边界条件设置错误:DirichletBC仅约束了实部,未约束虚部;RobinBC的回调函数未区分实部和虚部的输出。
修正后的代码
import deepxde as dde from deepxde.backend import pytorch import numpy as np geom = dde.geometry.Interval(0, 10000) f = 0.1 omega = 2 * np.pi * f mu = 4 * np.pi * 1e-7 sigma = 100 xc = 100 a = np.sqrt(-1j * omega * mu * sigma) a_real = np.real(a) a_imag = np.imag(a) def pde(x, y): # 拆分实部和虚部 y_real = y[:, 0:1] y_imag = y[:, 1:2] # 直接计算二阶导数,单分量不需要指定component参数 dy_xx_real = dde.grad.hessian(y_real, x) dy_xx_imag = dde.grad.hessian(y_imag, x) # 复值PDE拆分后的实部和虚部方程 return [ dy_xx_real + omega * mu * sigma * y_imag, dy_xx_imag - omega * mu * sigma * y_real ] def boundary_dirichlet(x, on_boundary): return on_boundary and dde.utils.isclose(x[0], 0) def boundary_robin(x, on_boundary): return on_boundary and dde.utils.isclose(x[0], xc) # DirichletBC:x=0处,实部为1,虚部为0 def func_dirichlet_real(x): return np.ones_like(x) def func_dirichlet_imag(x): return np.zeros_like(x) bc_real = dde.icbc.DirichletBC(geom, func_dirichlet_real, boundary_dirichlet, component=0) bc_imag = dde.icbc.DirichletBC(geom, func_dirichlet_imag, boundary_dirichlet, component=1) # RobinBC:分别处理实部和虚部的边界条件 def robin_real(x, y): # y的第0分量是实部,导数为一阶导 dy_real = dde.grad.jacobian(y, x, i=0) return dy_real + a_real * y[:,0:1] + a_imag * y[:,1:2] def robin_imag(x, y): dy_imag = dde.grad.jacobian(y, x, i=1) return dy_imag + a_real * y[:,1:2] - a_imag * y[:,0:1] bc_robin_real = dde.icbc.RobinBC(geom, robin_real, boundary_robin) bc_robin_imag = dde.icbc.RobinBC(geom, robin_imag, boundary_robin) data = dde.data.PDE(geom, pde, [bc_real, bc_imag, bc_robin_real, bc_robin_imag], 16, 5, solution=None, num_test=100) # 修正网络输出维度为2,对应实部和虚部 layer_size = [1] + [50] * 3 + [2] activation = "tanh" initializer = "Glorot uniform" net = dde.nn.FNN(layer_size, activation, initializer) model = dde.Model(data, net) model.compile("adam", lr=0.001, metrics=["l2 relative error"]) losshistory, train_state = model.train(iterations=5000) dde.saveplot(losshistory, train_state, issave=True, isplot=True)
关键修改点说明
- 调整网络输出层维度为
2,对应复值解的实部和虚部两个分量。 - 对单分量张量调用
hessian时,移除component、i、j参数,使用默认值即可正确计算二阶导数。 - 完善边界条件:分别为实部和虚部设置Dirichlet约束,RobinBC中正确结合实部和虚部的耦合关系(基于复值边界条件展开)。
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

