Files
NotBigGhostandClaude Opus 5 11ff7b79b4 Начальный коммит: Vulkan-редактор SimVulcan + исследование KBC-LBM
Состояние на момент заведения репозитория.

C++ приложение (src/, shaders/, tests/) — минимальный редактор 3D-моделей
на Vulkan 1.3: орбитальная камера, три опорные сетки через начало координат,
загрузка .obj с режимами отображения. Весь Vulkan изолирован в src/vk/.

Исследование (docs/) — оригинальные статьи по KBC (docs/origins) и
Python-решатель D2Q9 KBC-N1 с AMR 2x и SDF+Bouzidi (docs/theory).

В решателе перед коммитом исправлены дефекты, найденные сверкой с
первоисточниками: относительный порог знаменателя энтропийного стабилизатора
(абсолютный вырождал KBC в LBGK на 77-99% узлов), заворот вход/выход в углах
домена, диагностика средней плотности по фиктивным узлам тела, зашитый
refine=2. Подробности — docs/theory/solver_2x_sdf/README.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 16:37:38 +03:00

48 lines
2.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Геометрия: маски тела/стенок и знаковое поле расстояний (SDF) для L0 и патча L1.
# Чистый CuPy. Соглашение по SDF: phi>0 в жидкости, phi<0 в теле; |phi| ≈ расстоянию до границы.
import backend as B
import lattice as L
import amr
cp = B.cp; xp = B.xp; DTYPE = B.DTYPE
def _cmask(NX, NY, ccx, ccy, R):
"""Булева маска круга радиуса R (центр ccx,ccy) на сетке (NY,NX)."""
Y, X = cp.meshgrid(cp.arange(NY), cp.arange(NX), indexing="ij")
return (X - ccx)**2 + (Y - ccy)**2 <= R*R
def _csdf(NX, NY, ccx, ccy, R):
"""SDF круга: sqrt((x−ccx)²+(y−ccy)²) − R (отрицательно внутри)."""
Y, X = cp.meshgrid(cp.arange(NY), cp.arange(NX), indexing="ij")
return cp.sqrt((X - ccx).astype(DTYPE)**2 + (Y - ccy).astype(DTYPE)**2) - R
class Geometry:
"""Контейнер масок/SDF/патча. Поля *_np — host-копии для визуализации."""
pass
def build(cfg):
Nx, Ny, D, cx, cy = cfg.Nx, cfg.Ny, cfg.D, cfg.cx, cfg.cy
r = cfg.refine
ax1, bx1, ay1, by1 = cfg.ax1, cfg.bx1, cfg.ay1, cfg.by1
g = Geometry()
# --- L0: только цилиндр как твёрдое тело (стенки канала верх/низ — free-slip, не solid) ---
g.cyl0 = _cmask(Nx, Ny, cx, cy, D/2.0)
g.solid0 = g.cyl0 # стенки обрабатываются specular-отражением, см. boundary.free_slip_walls
g.phi0 = _csdf(Nx, Ny, cx, cy, D/2.0) # SDF только цилиндра (для Bouzidi тела)
# --- патч L1 (измельчение r) над областью [ax1,bx1]×[ay1,by1] ---
g.P1 = amr.patch(Nx, Ny, ax1, bx1, ay1, by1, r)
Nfx, Nfy = g.P1["Nfx"], g.P1["Nfy"]
# цилиндр на L1: центр и радиус масштабируются на r (диаметр r·D → радиус r·D/2)
R1 = r * D / 2.0
g.solid1 = _cmask(Nfx, Nfy, (cx - ax1)*r, (cy - ay1)*r, R1)
g.phi1 = _csdf(Nfx, Nfy, (cx - ax1)*r, (cy - ay1)*r, R1)
# маска жидких узлов для рестрикции L1→L0 (внутренняя часть патча на L0)
g.fl1 = ~g.solid0[ay1+1:by1, ax1+1:bx1]
# host-копии для визуализации
g.solid0_np = B.to_cpu(g.solid0); g.solid1_np = B.to_cpu(g.solid1)
return g