# Бэкенд: ТОЛЬКО GPU/CuPy. CPU-фолбэка нет (по требованию). Если CuPy/GPU недоступны — жёсткая ошибка. # Здесь же — общие device-константы (DTYPE, скаляры 0/1/2) и помощник переноса на host для вывода. import os import cupy as cp try: _probe = (cp.zeros(2) + 1).sum(); cp.cuda.Device().synchronize() # реальная операция на device except Exception as e: raise RuntimeError("solver_2x_sdf требует рабочую GPU + CuPy (CPU-фолбэк удалён намеренно).") from e xp = cp # единый алиас вычислительного бэкенда DTYPE = cp.float64 if os.environ.get("AMR_FP64") else cp.float32 # Порог вырожденности знаменателя γ. ОТНОСИТЕЛЬНЫЙ (доля от ‖Δ‖² = ⟨Δ|Δ⟩), а НЕ абсолютный. # Почему: den = ⟨Δh|Δh⟩ — квадратичная по неравновесию величина, у развитого следа она # ~1e-7…1e-9 при вполне разрешённой физике. Прежний абсолютный порог 1e-6 (fp32) срабатывал # на 77–99% узлов и молча подменял γ на 2, т.е. гнал ЧИСТЫЙ LBGK вместо KBC (замерено: # энстрофия сдвигового слоя Re=3e4 уходила на +9%). den — сумма НЕотрицательных слагаемых, # её относительная точность ~eps типа, поэтому дробный порог одинаков для fp32/fp64. # 1e-8 на шесть порядков ниже наблюдаемого минимума den/‖Δ‖² (~5e-4) — срабатывает только на # истинном вырождении (Δh ≡ 0), где γ всё равно ни на что не влияет, т.к. умножается на Δh. GREL = 1e-8 BACKEND = f"CuPy/GPU dtype={'float64' if DTYPE == cp.float64 else 'float32'}" # device-скаляры — не создаём host→device на горячем пути (важно для CUDA-graph capture) ZERO = cp.zeros((), DTYPE) ONE = cp.asarray(1.0, DTYPE) TWO = cp.asarray(2.0, DTYPE) def to_cpu(a): """Перенос на host (numpy) — только для диагностики/визуализации, не в солвере.""" return cp.asnumpy(a) def pack(comps): """Собрать кортеж одинаковых по форме массивов в один (len,*shape) БЕЗ cupy.stack. cupy.stack/concatenate грузит на device host-массив указателей (H2D) → запрещено при CUDA-graph capture. Здесь: преаллокация + присваивание срезов — только device→device.""" out = xp.empty((len(comps),) + comps[0].shape, dtype=comps[0].dtype) for i, c in enumerate(comps): out[i] = c return out