Возникли проблемы с вычислением остатков 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}. $$

    Трейсер
    $$ \partial_t s - D\Delta s = -\mathbf{u}\cdot\nabla s, $$

    где ν = 1/Рейнольдс и D = ν/Шмидт.
    и члены 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.)
Наблюдаемый результат:
  • Нормы остатка уравнения импульса: 0,18399687111377716, 0,1050143912434578
  • Норма остатка уравнения трассировки: 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»