You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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. 网络输出维度错误:原代码中网络输出层维度为1,但需要同时拟合复值解的实部和虚部,输出维度应为2,导致后续切片操作y[:,0:1]和y[:,1:2]实际获取的是无效张量。
  2. 导数调用参数错误:对切片后的单分量张量y_real/y_imag调用dde.grad.hessian时,指定了component=None和i=0,j=0,而单分量张量不需要指定component参数,内部Jacobian计算时索引越界引发错误。
  3. 边界条件设置错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:44:52