Возникли проблемы с вычислением остатков PDEPython

Программы на Python
Anonymous
 Возникли проблемы с вычислением остатков PDE

Сообщение Anonymous »

Привет всем! Я вычисляю остатки PDE для наборов данных The_Well (например, turbulent_radiative_layer_2D и shear_flow), используя конечные разности, но остатки намного больше, чем я ожидаю. Данные генерируются путем моделирования, поэтому я ожидал, что остатки будут близки к нулю.
Что я делаю
  • Я вычисляю производные с помощью центральной разностной схемы (второй порядок внутри, односторонний на границах). Вот моя производная функция:

    Код: Выделить всё

     import torch
    
    def compute_derivative(u, delta, order=1, axis=1):
    """
    Compute numerical derivatives along a specified axis.
    
    Args:
    u: Input tensor with shape [B, T, X, Y] (or [B, T, X, Y, C] for vector fields).
    delta: grid spacing along the chosen axis.
    order: 1 for first derivative, 2 for second derivative.
    axis: 1=time, 2=x, 3=y.
    """
    derivative = torch.zeros_like(u)
    
    if order == 1:
    # second-order central differences in interior, one-sided at boundaries
    if axis == 1:  # time
    derivative[:, 1:-1, :, :] = (u[:, 2:, :, :] - u[:, :-2, :, :]) / (2.0 * delta)
    derivative[:, 0:1, :, :]  = (-3.0*u[:, 0:1, :, :] + 4.0*u[:, 1:2, :, :] - u[:, 2:3, :, :]) / (2.0 * delta)
    derivative[:, -1:, :, :]  = (3.0*u[:, -1:, :, :] - 4.0*u[:, -2:-1, :, :] + u[:, -3:-2, :, :]) / (2.0 * delta)
    elif axis == 2:  # x
    derivative[:, :, 1:-1, :] = (u[:, :, 2:, :] - u[:, :, :-2, :]) / (2.0 * delta)
    derivative[:, :, 0:1, :]  = (-3.0*u[:, :, 0:1, :] + 4.0*u[:, :, 1:2, :] - u[:, :, 2:3, :]) / (2.0 * delta)
    derivative[:, :, -1:, :]  = (3.0*u[:, :, -1:, :] - 4.0*u[:, :, -2:-1, :] + u[:, :, -3:-2, :]) / (2.0 * delta)
    elif axis == 3:  # y
    derivative[:, :, :, 1:-1] = (u[:, :, :, 2:] - u[:, :, :, :-2]) / (2.0 * delta)
    derivative[:, :, :, 0:1]  = (-3.0*u[:, :, :, 0:1] + 4.0*u[:, :, :, 1:2] - u[:, :, :, 2:3]) / (2.0 * delta)
    derivative[:, :, :, -1:]  = (3.0*u[:, :, :, -1:] - 4.0*u[:, :, :, -2:-1] + u[:, :, :, -3:-2]) / (2.0 * delta)
    
    elif order == 2:
    # second-order second derivative
    if axis == 1:
    derivative[:, 1:-1, :, :] = (u[:, 2:, :, :] - 2*u[:, 1:-1, :, :] + u[:, :-2, :, :]) / (delta**2)
    derivative[:, 0:1, :, :]  = (u[:, 2:3, :, :] - 2*u[:, 1:2, :, :] + u[:, 0:1, :, :]) / (delta**2)
    derivative[:, -1:, :, :]  = (u[:, -1:, :, :] - 2*u[:, -2:-1, :, :] + u[:, -3:-2, :, :]) / (delta**2)
    elif axis == 2:
    derivative[:, :, 1:-1, :] = (u[:, :, 2:, :] - 2*u[:, :, 1:-1, :] + u[:, :, :-2, :]) / (delta**2)
    derivative[:, :, 0:1, :]  = (u[:, :, 2:3, :] - 2*u[:, :, 1:2, :] + u[:, :, 0:1, :]) / (delta**2)
    derivative[:, :, -1:, :]  = (u[:, :, -1:, :] - 2*u[:, :, -2:-1, :] + u[:, :, -3:-2, :]) / (delta**2)
    elif axis == 3:
    derivative[:, :, :, 1:-1] = (u[:, :, :, 2:] - 2*u[:, :, :, 1:-1] + u[:, :, :, :-2]) / (delta**2)
    derivative[:, :, :, 0:1]  = (u[:, :, :, 2:3] - 2*u[:, :, :, 1:2] + u[:, :, :, 0:1]) / (delta**2)
    derivative[:, :, :, -1:]  = (u[:, :, :, -1:] - 2*u[:, :, :, -2:-1] + u[:, :, :, -3:-2]) / (delta**2)
    
    return derivative
    
  • Из файла HDF5 загружаю поля с фигурами:

    Код: Выделить всё

     pressure: (4, 200, 256, 512)
    tracer:   (4, 200, 256, 512)
    velocity: (4, 200, 256, 512, 2)
    
    Я вызываю Compute_Physics_loss(...) со скоростью[...,0] и Velocity[...,1] как Velocity_x и Velocity_y.
  • Используемые мной PDE:
    Импульс (форма компонента)
    $$ \partial_t \mathbf{u} + \nabla p - \nu \Delta \mathbf{u} = -\mathbf{u}\cdot\nabla\mathbf{u}. $$
    Tracer
    $$ \partial_t s - D\Delta s = -\mathbf{u}\cdot\nabla s, $$
    где ν = 1/Reynolds и D = ν/Schmidt.
    и вычисляются члены PDE используя

    Код: Выделить всё

     # time derivatives (one-order)
    du_x_dt = compute_derivative(velocity_x, dt, order=1, axis=1)
    du_y_dt = compute_derivative(velocity_y, dt, order=1, axis=1)
    ds_dt = compute_derivative(tracer, dt, order=1, axis=1)
    
    # spatial derivatives
    # pressure gradients (one-order)
    dp_dx = compute_derivative(pressure, dx, order=1, axis=2)
    dp_dy = compute_derivative(pressure, dy, order=1, axis=3)
    
    # velocity Laplacian (second-order)
    du_x_dx2 = compute_derivative(velocity_x, dx, order=2, axis=2)
    du_x_dy2 = compute_derivative(velocity_x, dy, order=2, axis=3)
    laplacian_u_x = du_x_dx2 + du_x_dy2
    
    du_y_dx2 = compute_derivative(velocity_y, dx, order=2, axis=2)
    du_y_dy2 = compute_derivative(velocity_y, dy, order=2, axis=3)
    laplacian_u_y = du_y_dx2 + du_y_dy2
    
    # tracer Laplacian (second-order)
    ds_dx2 = compute_derivative(tracer, dx, order=2, axis=2)
    ds_dy2 = compute_derivative(tracer, dy, order=2, axis=3)
    laplacian_s = ds_dx2 + ds_dy2
    
    # convection term (u·∇u)
    du_x_dx = compute_derivative(velocity_x, dx, order=1, axis=2)
    du_x_dy = compute_derivative(velocity_x, dy, order=1, axis=3)
    advection_u_x = velocity_x * du_x_dx + velocity_y * du_x_dy
    
    du_y_dx = compute_derivative(velocity_y, dx, order=1, axis=2)
    du_y_dy = compute_derivative(velocity_y, dy, order=1, axis=3)
    advection_u_y = velocity_x * du_y_dx + velocity_y * du_y_dy
    
    # convection term (u·∇s)
    ds_dx = compute_derivative(tracer, dx, order=1, axis=2)
    ds_dy = compute_derivative(tracer, dy, order=1, axis=3)
    advection_s = velocity_x * ds_dx + velocity_y * ds_dy
    
  • Я вычисляю тензоры остатков (форма [B, T, X, Y]) как:

    Код: Выделить всё

     momentum_x_residual = du_x_dt + dp_dx - nu * laplacian_u_x + advection_u_x
    momentum_y_residual = du_y_dt + dp_dy - nu * laplacian_u_y + advection_u_y
    tracer_residual     = ds_dt - D * laplacian_s + advection_s
    
  • Затем я вычисляю среднеквадратические остатки с помощью:

    Код: Выделить всё

     res_mom_x = ((momentum_x_residual)**2).mean().item()
    res_mom_y = ((momentum_y_residual)**2).mean().item()
    res_tracer = ((tracer_residual)**2).mean().item()
    
    (Да, это выражение представляет собой среднеквадратичный остаток / MSE.)
Наблюдаемый результат

Код: Выделить всё

The momentum equation residual norms: 0.18399687111377716, 0.1050143912434578
The tracer equation residual norm: 2.9967291355133057
Я ожидал, что значения будут близки к нулю, но получил значения ~0,1–3,0.
То, что я проверял на данный момент
  • формы данных и индексирование
  • производная реализация (центральная внутренняя разница + односторонняя граница)
Вопросы/запрошена помощь
  • Упускаю ли я какие-либо распространенные ошибки, которые могут привести к таким большим остаткам?
  • Может ли набор данных использовать другие соглашения (например, шахматную сетку, сдвиг давления в зависимости от скорости, единицы измерения/масштабирование, периодические BC, призрачные ячейки или преобразования координат), которые мне следует учитывать?
  • Есть ли ошибки в моей конечно-разностной дискретизации или соглашениях о знаках для терминов PDE?
  • Существуют ли рекомендуемые проверки работоспособности, которые мне следует выполнить, чтобы локализовать проблему?
Относительная информация

Код: Выделить всё

dt=0.09999999999999999, dx=0.003921568859368563, dy=0.001956947147846222, Reynolds=500000.0, Schmidt=0.20000000298023224
Заранее спасибо за любые подсказки!!!

Подробнее здесь: https://stackoverflow.com/questions/797 ... -residuals

Вернуться в «Python»