Обновить README и PLAN до актуального состояния (физика v2, GPU, автономная эволюция)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
112
PLAN.md
112
PLAN.md
@@ -52,7 +52,7 @@ L(x, I)-модель с coenergy-выводом силы — в разделе "
|
|||||||
- [ ] **Не сделано**: отдельный "дешёвый квазистатический предфильтр" перед полным ODE не реализован (кроме уже встроенной в `sim/stage.py` дешёвой проверки порога индукционного датчика). Если миллионы прогонов на сервере окажутся слишком медленными, это первое место для ускорения.
|
- [ ] **Не сделано**: отдельный "дешёвый квазистатический предфильтр" перед полным ODE не реализован (кроме уже встроенной в `sim/stage.py` дешёвой проверки порога индукционного датчика). Если миллионы прогонов на сервере окажутся слишком медленными, это первое место для ускорения.
|
||||||
- [x] **Этап 7 — Отчётность**: `report/plots.py` (ток/поле/скорость по ступеням), `summary.py` (честная сводка + раздел "ограничения модели"), `bom.py` (спецификация деталей с ценами), `animate.py` (GIF: снаряд летит по трубе, катушки светятся пропорционально току — по запросу пользователя), `cli.py` (`gausse sweep/evolve/simulate/report`, все 4 команды реально вызывают соответствующие модули, не заглушки). Проверено сквозным прогоном через `docker compose run`: sweep → report с анимацией на реальной базе компонентов, лучший найденный результат — КПД 32.8% за 982₽ (не выдумано, из реального SQLite).
|
- [x] **Этап 7 — Отчётность**: `report/plots.py` (ток/поле/скорость по ступеням), `summary.py` (честная сводка + раздел "ограничения модели"), `bom.py` (спецификация деталей с ценами), `animate.py` (GIF: снаряд летит по трубе, катушки светятся пропорционально току — по запросу пользователя), `cli.py` (`gausse sweep/evolve/simulate/report`, все 4 команды реально вызывают соответствующие модули, не заглушки). Проверено сквозным прогоном через `docker compose run`: sweep → report с анимацией на реальной базе компонентов, лучший найденный результат — КПД 32.8% за 982₽ (не выдумано, из реального SQLite).
|
||||||
- [x] **Этап 8 — Сквозная проверка**: реальный прогон через `docker compose run` — sweep на 5000 конфигураций (16 воркеров, ~59с, 30.5% реализуемо), затем `evolve` (15 поколений x 40 особей = 600 оценок, ~18с) поверх той же базы, затем `report --top 3 --animate`.
|
- [x] **Этап 8 — Сквозная проверка**: реальный прогон через `docker compose run` — sweep на 5000 конфигураций (16 воркеров, ~59с, 30.5% реализуемо), затем `evolve` (15 поколений x 40 особей = 600 оценок, ~18с) поверх той же базы, затем `report --top 3 --animate`.
|
||||||
- **Найден и исправлен реальный баг именно на этом этапе**: КПД лучшего генома после `evolve` показал 387% — оказалось, `efficiency` считался как `exit_kinetic_energy / energy_in`, а `exit_kinetic_energy` включает фиксированный "бесплатный" толчок `initial_v_mps`, не учтённый в `energy_in`. Для лёгкого снаряда этот толчок доминировал и КПД пробивал 100%. Исправлено на `kinetic_energy_delta / energy_in` (энергия, реально добавленная катушками) — эта величина математически не может превысить 1 (следует из поэтапного энергобаланса). После исправления лучший честный результат: **1 ступень, КПД 80.97%, скорость 26.4 м/с, снаряд Ст3 ⌀4мм x 30мм, стоимость 1029₽** (провод cu-petv2-1.0mm, конденсатор 22мкФ/400В, ключ IRG4PC50F, оптический датчик).
|
- **Найден и исправлен реальный баг именно на этом этапе**: КПД лучшего генома после `evolve` показал 387% — оказалось, `efficiency` считался как `exit_kinetic_energy / energy_in`, а `exit_kinetic_energy` включает фиксированный "бесплатный" толчок `initial_v_mps`, не учтённый в `energy_in`. Для лёгкого снаряда этот толчок доминировал и КПД пробивал 100%. Исправлено на `kinetic_energy_delta / energy_in` (энергия, реально добавленная катушками) — эта величина математически не может превысить 1 (следует из поэтапного энергобаланса). После исправления лучший результат на тот момент: **1 ступень, КПД 80.97%, скорость 26.4 м/с, снаряд Ст3 ⌀4мм x 30мм, стоимость 1029₽** (провод cu-petv2-1.0mm, конденсатор 22мкФ/400В, ключ IRG4PC50F, оптический датчик). *(Историческая запись: это физика v1 БЕЗ потерь в железе, скина и трения — после их добавления такие КПД невозможны, см. «хронологию честности» ниже.)*
|
||||||
- **Честное сравнение датчиков** (запрос из первого обсуждения плана) — на 5000 прогонах: индукционный датчик (`inductive-pickup-lm393`) дал **0.2% реализуемых** конфигураций (6 из 2965, где он стоял хотя бы на одной ступени), тогда как оптический (TCST2103) и Холла (A3144E) — **~45-47%** реализуемых каждый. Это количественно подтверждает опасение, высказанное в самом начале обсуждения плана: индукционная катушка-датчик ненадёжна именно потому, что требует скорости выше её порога (здесь — фиксированный старт 3 м/с как раз ниже порога срабатывания реального компонента), тогда как оптика/Холл не зависят от скорости.
|
- **Честное сравнение датчиков** (запрос из первого обсуждения плана) — на 5000 прогонах: индукционный датчик (`inductive-pickup-lm393`) дал **0.2% реализуемых** конфигураций (6 из 2965, где он стоял хотя бы на одной ступени), тогда как оптический (TCST2103) и Холла (A3144E) — **~45-47%** реализуемых каждый. Это количественно подтверждает опасение, высказанное в самом начале обсуждения плана: индукционная катушка-датчик ненадёжна именно потому, что требует скорости выше её порога (здесь — фиксированный старт 3 м/с как раз ниже порога срабатывания реального компонента), тогда как оптика/Холл не зависят от скорости.
|
||||||
- Итог: сквозная цепочка (реальные компоненты → физика → поиск → SQLite → отчёт с графиками/BOM/анимацией) работает и произвела не выдуманный, а посчитанный и перепроверенный результат.
|
- Итог: сквозная цепочка (реальные компоненты → физика → поиск → SQLite → отчёт с графиками/BOM/анимацией) работает и произвела не выдуманный, а посчитанный и перепроверенный результат.
|
||||||
- [x] **Обогащённая БД + лог процесса + веб-морда** (по запросу пользователя при деплое): каждая запись `runs.decoded_summary_json` теперь содержит расстояния между катушками (`inter_stage_gaps_m`), абсолютные позиции катушек вдоль трубы, все номиналы деталей, геометрию намотки, вычисленную физику (индуктивность/сопротивление/пиковый ток/поле) и результат каждой ступени (вход/выход скорость, тайминги датчика, энергобаланс) — см. `optim/objective.py::build_detail`. Ход эксперимента пишется в `<db>.log` (`optim/progress_log.py`): прогресс, доля реализуемых, скорость, ETA, отметки нового лучшего КПД. Веб-дашборд `gausse serve` (`src/gausse/web/`, только stdlib `http.server`, self-contained HTML) — счётчики, гистограмма КПД, топ конфигураций с drill-down, причины отказа, хвост лога, автообновление 3с. В `docker-compose.yml` сервис `web` на порту 8000. 77 тестов, проверено в Docker.
|
- [x] **Обогащённая БД + лог процесса + веб-морда** (по запросу пользователя при деплое): каждая запись `runs.decoded_summary_json` теперь содержит расстояния между катушками (`inter_stage_gaps_m`), абсолютные позиции катушек вдоль трубы, все номиналы деталей, геометрию намотки, вычисленную физику (индуктивность/сопротивление/пиковый ток/поле) и результат каждой ступени (вход/выход скорость, тайминги датчика, энергобаланс) — см. `optim/objective.py::build_detail`. Ход эксперимента пишется в `<db>.log` (`optim/progress_log.py`): прогресс, доля реализуемых, скорость, ETA, отметки нового лучшего КПД. Веб-дашборд `gausse serve` (`src/gausse/web/`, только stdlib `http.server`, self-contained HTML) — счётчики, гистограмма КПД, топ конфигураций с drill-down, причины отказа, хвост лога, автообновление 3с. В `docker-compose.yml` сервис `web` на порту 8000. 77 тестов, проверено в Docker.
|
||||||
@@ -63,16 +63,108 @@ L(x, I)-модель с coenergy-выводом силы — в разделе "
|
|||||||
- **Уже было (тоже запрашивалось)**: разная толщина провода на разных катушках (`wire_idx` на ступень) и длина провода (`winding_geometry.total_wire_length_m` → сопротивление/цена/БД).
|
- **Уже было (тоже запрашивалось)**: разная толщина провода на разных катушках (`wire_idx` на ступень) и длина провода (`winding_geometry.total_wire_length_m` → сопротивление/цена/БД).
|
||||||
- **Графики в дашборде**: клик по прогону → графики скорость/поле/ток строятся на лету (`web/render.py`, `/api/run/<id>/plot/<kind>.png`) + GIF пролёта по кнопке (`/api/run/<id>/anim.gif`). Рендер matplotlib сериализован локом (Agg не потокобезопасен). 86 тестов.
|
- **Графики в дашборде**: клик по прогону → графики скорость/поле/ток строятся на лету (`web/render.py`, `/api/run/<id>/plot/<kind>.png`) + GIF пролёта по кнопке (`/api/run/<id>/anim.gif`). Рендер matplotlib сериализован локом (Agg не потокобезопасен). 86 тестов.
|
||||||
|
|
||||||
## Развёртывание на сервере (Proxmox 192.168.20.254 / VM 106 "test-math" = 192.168.20.45)
|
## Развёртывание на сервере (Proxmox 192.168.20.254 / VM 106 "test-math" = **192.168.20.47**)
|
||||||
|
|
||||||
**СТАТУС: развёрнуто и работает на CPU.** VM 106: RAM 2→6ГБ, Docker+git, клон с gitea, образ собран, 86 тестов проходят в контейнере на сервере. Веб-морда живёт на **http://192.168.20.45:8000** (сервис `web`, restart unless-stopped), sweep пишет в `~/gausse/results/gausse.sqlite3` (+ лог `.log`). Дашборд доступен снаружи (Proxmox firewall порт 8000 не блокирует). Обновление кода: на VM `cd ~/gausse && git pull && docker compose build && docker compose up -d web`.
|
**СТАТУС: развёрнуто, работает АВТОНОМНО (CPU-эволюция под systemd), GPU проброшен и рабочий.**
|
||||||
|
|
||||||
Обнаружено при осмотре: GTX 1070 (`10de:1b81`+аудио `10de:10f0`) стоит в Proxmox-хосте, **уже привязана к vfio-pci**, blacklist'ы nouveau/nvidia прописаны, IOMMU включён (`intel_iommu=on`), карта одна в IOMMU-группе 1. То есть хост заранее подготовлен под проброс — можно пробросить в VM **без перезагрузки хоста** (не заденет другие VM: nextcloud/minecraft/web-player). Целевая VM 106 = 5 ядер, 2ГБ RAM (мало для CUDA+Docker, поднять). GPU ей ещё не назначен.
|
- VM 106: Ubuntu 24.04, 5 ядер, 12ГБ RAM. После перевода на q35 (нужен для
|
||||||
|
PCIe-проброса) интерфейс переименовался и IP сменился **.45 → .47**
|
||||||
|
(netplan починен привязкой по MAC).
|
||||||
|
- [x] Пуш на gitea (`gitea.jze9.ru/jze9/gausse.git`) — рабочий процесс: пуш с
|
||||||
|
локальной машины → `git pull` на VM.
|
||||||
|
- [x] GPU: `qm set 106 --machine q35 --hostpci0 0000:01:00,pcie=1`; в VM
|
||||||
|
драйвер NVIDIA 580 + CUDA, `cupy-cuda12x[ctk]` в `~/gausse/.venv`.
|
||||||
|
`nvidia-smi` видит GTX 1070 без Code 43.
|
||||||
|
- [x] Веб-морда: **http://192.168.20.47:8000** (Docker-сервис `web`).
|
||||||
|
- [x] **Автономная эволюция — systemd-сервис `gausse-evolve`** (пользователь
|
||||||
|
явно потребовал: «алгоритм должен считать сам, годами, без тебя»):
|
||||||
|
`/etc/systemd/system/gausse-evolve.service` крутит `evolve_forever.sh` —
|
||||||
|
вечный цикл `run_evolution(80 поколений × 300 особей, polish=True)` с новым
|
||||||
|
случайным семенем на каждом заходе (свежая популяция = «революция» против
|
||||||
|
застревания в локальном оптимуме). `Restart=always` + `enabled` → переживает
|
||||||
|
и падение процесса, и перезагрузку VM. Всё пишет в одну базу
|
||||||
|
`~/gausse/results/gausse.sqlite3`; «запланировано N» на дашборде — план
|
||||||
|
ТЕКУЩЕГО цикла, сам поиск бесконечен. Управление: `sudo systemctl
|
||||||
|
status|stop|restart gausse-evolve`, лог `journalctl -u gausse-evolve`.
|
||||||
|
- Обновление кода на VM: `cd ~/gausse && git pull && docker compose build web
|
||||||
|
&& docker compose up -d web && sudo systemctl restart gausse-evolve`.
|
||||||
|
|
||||||
- [ ] Пуш на gitea (`gitea.jze9.ru/jze9/gausse.git`) или rsync прямо в VM.
|
- [x] **Этап 9 — GPU-ускорение массового sweep — СДЕЛАН**:
|
||||||
- [ ] `hostpci0: 0000:01:00,pcie=1` в конфиг VM 106, поднять RAM, перезагрузить VM 106.
|
`gpu/batch_integrator.py` — батч-RK4 фиксированного шага [Q,I,x,v] на N
|
||||||
- [ ] В VM: NVIDIA-драйвер + CUDA + Docker + nvidia-container-toolkit.
|
конфигураций одним тензором (numpy/cupy через `xp`), та же физика, что
|
||||||
- [ ] Развернуть проект, запустить sweep (пока CPU!), поднять `gausse serve` (порт 8000).
|
CPU-путь (общий `sim/stage.build_stage_physics` — один источник истины).
|
||||||
- [ ] Дать доступ: веб-морда http://192.168.20.45:8000, SQLite `results/gausse.sqlite3`, лог `results/gausse.sqlite3.log`.
|
Весь RK4-шаг слит в ОДНО `cupy.fuse`-ядро → **GTX 1070: 740 конф/с vs 193
|
||||||
|
на numpy = 3.8x** (наивный порт был 1.3x — упирался в запуск ядер);
|
||||||
|
SYNC_EVERY=256 убирает device→host синхронизацию на каждом шаге.
|
||||||
|
`gpu/batch_sweep.py` — МНОГОСТУПЕНЧАТЫЙ sweep раунд-за-раундом (подлёт
|
||||||
|
аналитически, состояние снаряда переносится между раундами), CLI
|
||||||
|
`gausse sweep --gpu`. Требование честности выполнено: GPU сверен с
|
||||||
|
CPU-эталоном — расхождение exit_v **0.084%** (tests/test_batch_sweep.py,
|
||||||
|
test_batch_integrator.py). Стиффные конфиги, переполняющие фикс-шаг,
|
||||||
|
честно бракуются (blew_up), а не записываются мусором.
|
||||||
|
- [ ] (опция) дослить cut-логику в ядро (>3.8x); GPU-батч внутрь эволюции.
|
||||||
|
|
||||||
- [ ] **Этап 9 — GPU-ускорение массового sweep (сервер с GTX 1070)**: после того как CPU/`scipy.solve_ivp`-модель провалидирована тестами (Этап 2-4) — батч-версия интегратора с ФИКСИРОВАННЫМ шагом (RK4/полу-неявная схема), считающая сразу N траекторий параллельно как один тензор (`cupy`, если доступна CUDA, иначе векторизованный `numpy`/`numba`), для прогона по-настоящему миллионов конфигураций на сервере. Важно: сначала корректность на CPU, потом скорость на GPU — численные результаты GPU-пути должны сверяться с CPU-эталоном на контрольной выборке, чтобы ускорение не подменило точность честными числами "для галочки".
|
## Физика: найденные завышения КПД и их исправления (хронология честности)
|
||||||
|
|
||||||
|
Пользователь ловил нереальные цифры; каждое исправление РОНЯЛО КПД к
|
||||||
|
реальности. Версия модели пишется в каждую запись БД (`model_version`),
|
||||||
|
прогоны разных версий не смешиваются.
|
||||||
|
|
||||||
|
1. **Поле 13 Тл** → насыщение железа через единое потокосцепление
|
||||||
|
λ(x,I)=L_air·I+L_iron·overlap(x)·g(I), g=I_sat·tanh(I/I_sat); сила и ЭДС
|
||||||
|
из одного λ (coenergy) → энергия сохраняется, поле упирается в B_sat.
|
||||||
|
2. **Ток сверх рейтинга ключа** → жёсткая отбраковка по импульсному пределу.
|
||||||
|
3. **КПД 83.9%: не было потерь в железе** → вихревые токи: снаряд =
|
||||||
|
короткозамкнутый виток, отражённое R_eddy=(ωM)²/R_e × overlap(x)
|
||||||
|
(physics/losses.py). Лучший упал 83.9% → ~47%, медиана ~0%.
|
||||||
|
4. **Три горба тока за выстрел** (физически невозможно — конденсатор не
|
||||||
|
перезарядить за мкс) → одиночный импульс: обрыв на первом нуле тока ИЛИ
|
||||||
|
первом локальном минимуме; остаточная энергия катушки → freewheel-диод,
|
||||||
|
считается точно через magnetic_energy (с насыщением). Энергобаланс сошёлся.
|
||||||
|
5. **gausse-physics-v2 (2026-07-08)**: скин-эффект + эффект близости обмотки
|
||||||
|
(метод Доуэлла на ω=1/√(LC), `physics/ac_resistance.py`) — для толстого
|
||||||
|
провода во многих слоях R_AC в разы выше DC; **трение о трубку**
|
||||||
|
(0.35·m·g) и **сопротивление воздуха** (½ρ·Cd·A·v²) во всей динамике
|
||||||
|
(разряд, подлёт с событием «снаряд остановлен трением», GPU-ядро,
|
||||||
|
аналитический межступенчатый пролёт — точная квадратура); паспортные
|
||||||
|
импульсные токи ключей из даташитов (`pulse_current_a`: ITSM/IDM/ICM)
|
||||||
|
вместо generic-множителей + починен вводивший в заблуждение флаг
|
||||||
|
(`switch_current_over_continuous_rating` — норма для импульса,
|
||||||
|
`switch_current_over_pulse_limit` — брак). КПД ступени теперь может быть
|
||||||
|
слегка отрицательным (трение съело больше слабой катушки) — это честно.
|
||||||
|
Для сравнения на одной и той же эволюции: v1 давал «38%» там, где v2 даёт
|
||||||
|
~8% — столько стоили неучтённые скин и трение.
|
||||||
|
|
||||||
|
## Требования пользователя, закрытые после Этапа 8
|
||||||
|
|
||||||
|
- **Снаряд до 200 г** (⌀ до 28мм, длина до 150мм, длина зажата по плотности).
|
||||||
|
- **Труба — часть поиска**: геном несёт внутренний диаметр (бор) + толщину
|
||||||
|
стенки; внешний диаметр трубы = внутренний диаметр катушки (влияет на
|
||||||
|
поле); снаряд обязан влезать в бор с зазором.
|
||||||
|
- **До 10 ступеней**; у каждой катушки СВОЙ датчик на своём расстоянии
|
||||||
|
(sensor_to_coil_distance_m на ступень; datчик не может попасть в предыдущую
|
||||||
|
катушку — repair()).
|
||||||
|
- **Ссылки на магазины** (`url`) у каждого компонента: в JSON-базе, BOM
|
||||||
|
(«Купить») и в детализации прогона.
|
||||||
|
- **Максимально детальная запись** в БД (`build_detail`): труба
|
||||||
|
внутр/стенка/внеш, масса снаряда в граммах и влезает-ли-в-бор,
|
||||||
|
внутр/внеш диаметры катушки, состав банки конденсаторов, DC/AC
|
||||||
|
сопротивление обмотки, все позиции датчиков и катушек вдоль трубы,
|
||||||
|
энергобаланс каждой ступени.
|
||||||
|
- **Анимация переделана** (была «время вырезается, результата не видно»):
|
||||||
|
кадры на равномерной сетке ФИЗИЧЕСКОГО времени (а не по индексам массива,
|
||||||
|
из-за чего плотные точки разряда съедали все кадры и подлёт выпадал),
|
||||||
|
множитель замедления в кадре; в кадре сам результат эксперимента — шапка
|
||||||
|
(выход м/с, КПД, ступени, энергия, масса), панель тока каждой катушки во
|
||||||
|
времени, панель скорости снаряда, бегущий курсор, датчики на трубе.
|
||||||
|
|
||||||
|
## Ограничения модели / следующие шаги по реализму (если потребуются)
|
||||||
|
|
||||||
|
- Поршневой эффект воздуха в трубе (учтено только лобовое сопротивление).
|
||||||
|
- Диффузия поля в снаряде (наш r_eddy — сосредоточенная оценка 1-го порядка).
|
||||||
|
- Спектр импульса для Доуэлла (взята одна характерная частота).
|
||||||
|
- Нагрев провода за импульс/серию; коэффициент трения не измерен (0.35).
|
||||||
|
- Гистерезис посчитан (losses.hysteresis_energy_j) и СОЗНАТЕЛЬНО не в
|
||||||
|
динамике: <0.1% энергии выстрела — включение изображало бы ложную точность.
|
||||||
|
- Индуктивность — Уилер+размагничивание, не МКЭ/FEA.
|
||||||
|
- Осторожно: не тюнить модель под «желаемую» цифру КПД — только физика.
|
||||||
|
|||||||
74
README.md
74
README.md
@@ -1,21 +1,58 @@
|
|||||||
# gausse
|
# gausse
|
||||||
|
|
||||||
Симулятор и оптимизатор многоступенчатого электромагнитного ускорителя
|
Симулятор и оптимизатор многоступенчатого электромагнитного ускорителя
|
||||||
(coilgun) на реальных, доступных в рознице компонентах.
|
(coilgun / пушка Гаусса) на реальных, доступных в рознице компонентах
|
||||||
|
(ChipDip, procontact74.ru, cable.ru — у каждой детали в базе ссылка на
|
||||||
|
магазин).
|
||||||
|
|
||||||
Полный план и чек-лист этапов — в [PLAN.md](PLAN.md).
|
Главный принцип — **честность**: все прогоны (включая нереализуемые, с
|
||||||
|
причиной отказа) пишутся в SQLite; физическая модель не приукрашивается ради
|
||||||
|
красивых цифр, а каждое известное упрощение задокументировано. История
|
||||||
|
проекта — это в том числе история найденных и исправленных завышений КПД
|
||||||
|
(80%+ → реалистичные единицы процентов), см. [PLAN.md](PLAN.md).
|
||||||
|
|
||||||
## Установка (Docker — основной способ)
|
## Что умеет
|
||||||
|
|
||||||
|
- **Физика** (`src/gausse/physics/`): RLC-разряд конденсаторной банки через
|
||||||
|
катушку с ферромагнитным снарядом; насыщение железа через единое
|
||||||
|
потокосцепление λ(x,I) (энергия сохраняется); вихревые потери в снаряде;
|
||||||
|
скин-эффект + эффект близости обмотки (метод Доуэлла); трение о трубку и
|
||||||
|
сопротивление воздуха; одиночный импульс (тиристор не перезапускается);
|
||||||
|
паспортные импульсные токи ключей (ITSM/IDM/ICM из даташитов).
|
||||||
|
- **Ступени** (`src/gausse/sim/`): у каждой катушки свой датчик
|
||||||
|
(оптика/Холл/индукционный) на своём расстоянии; подлёт → триггер →
|
||||||
|
задержки датчика и ключа → разряд → энергобаланс; цепочка до 10 ступеней.
|
||||||
|
- **Поиск** (`src/gausse/optim/`): геном переменной длины (число ступеней
|
||||||
|
эволюционирует), Monte-Carlo sweep и (μ+λ)-эволюция с Nelder-Mead
|
||||||
|
полировкой; всё в одну SQLite-базу (WAL, писатель поверх очереди).
|
||||||
|
- **GPU** (`src/gausse/gpu/`): батч-интегратор RK4 (numpy/cupy), весь шаг
|
||||||
|
слит в одно cupy.fuse-ядро — на GTX 1070 ~3.8x к CPU; многоступенчатый
|
||||||
|
GPU-sweep раунд-за-раундом; сверен с CPU-эталоном (<0.1%).
|
||||||
|
- **Отчёты** (`src/gausse/report/`, `src/gausse/web/`): веб-дашборд с
|
||||||
|
drill-down до каждой детали и энергобаланса ступени, графики ток/поле/
|
||||||
|
скорость, GIF-анимация выстрела (равномерное физическое время, результат
|
||||||
|
эксперимента в кадре), BOM с ценами и ссылками «купить».
|
||||||
|
|
||||||
|
## Запуск (Docker — основной способ)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose build
|
docker compose build
|
||||||
docker compose run --rm --entrypoint pytest gausse -q # тесты
|
docker compose run --rm --entrypoint pytest gausse -q # тесты
|
||||||
docker compose run --rm gausse sweep --n 1000 # CLI (после реализации Этапа 6)
|
docker compose up -d web # дашборд :8000
|
||||||
|
docker compose run --rm gausse sweep --n 100000 --db /app/results/gausse.sqlite3
|
||||||
|
docker compose run --rm gausse evolve --generations 80 --population 300 \
|
||||||
|
--db /app/results/gausse.sqlite3
|
||||||
|
docker compose run --rm gausse report --top 3 --animate --db /app/results/gausse.sqlite3
|
||||||
```
|
```
|
||||||
|
|
||||||
Результаты (SQLite, отчёты) должны сохраняться в `./results`, примонтированный
|
GPU-режим (нужны NVIDIA-драйвер и `pip install cupy-cuda12x[ctk]`, вне Docker):
|
||||||
в контейнер как `/app/results` (см. `docker-compose.yml`), чтобы переживать
|
|
||||||
пересборку образа.
|
```bash
|
||||||
|
gausse sweep --gpu --n 1000000 --db results/gausse.sqlite3
|
||||||
|
```
|
||||||
|
|
||||||
|
Результаты (SQLite + лог хода эксперимента `<db>.log`) живут в `./results`,
|
||||||
|
примонтированном в контейнер, и переживают пересборку образа.
|
||||||
|
|
||||||
## Установка без Docker (локальная разработка)
|
## Установка без Docker (локальная разработка)
|
||||||
|
|
||||||
@@ -25,3 +62,26 @@ source .venv/bin/activate
|
|||||||
pip install -e ".[dev]"
|
pip install -e ".[dev]"
|
||||||
pytest
|
pytest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Автономная работа на сервере
|
||||||
|
|
||||||
|
Эволюция оформлена как systemd-сервис `gausse-evolve` (вечный цикл: 80
|
||||||
|
поколений × 300 особей, по окончании — новый цикл со свежей случайной
|
||||||
|
популяцией; `Restart=always`, автозапуск при загрузке). Дашборд — Docker-
|
||||||
|
сервис `web` на :8000, читает ту же базу. Счётчик «запланировано» на
|
||||||
|
дашборде — план **текущего цикла**, а не всего поиска: поиск бесконечен.
|
||||||
|
|
||||||
|
## Ограничения модели (честно)
|
||||||
|
|
||||||
|
- Индуктивность — инженерная модель (Уилер + размагничивание сфероида +
|
||||||
|
tanh-перекрытие), не МКЭ; точная картина поля требует FEA.
|
||||||
|
- Вихревые потери снаряда — сосредоточенный виток на характерной частоте
|
||||||
|
импульса; диффузия поля (скин-эффект в самом снаряде) не решается.
|
||||||
|
- Доуэлл берёт одну характерную частоту ω=1/√(LC), без спектра импульса.
|
||||||
|
- Воздух — лобовое сопротивление; поршневой эффект столба воздуха в трубе
|
||||||
|
не учтён. Трение — константа 0.35 (сталь-пластик), не измерено.
|
||||||
|
- Гистерезис снаряда посчитан и сознательно не включён в динамику (<0.1%).
|
||||||
|
- Нагрев провода за импульс и от серии выстрелов не моделируется.
|
||||||
|
|
||||||
|
Версия физики пишется в каждую запись (`model_version`, сейчас
|
||||||
|
`gausse-physics-v2`) — прогоны разных моделей не смешиваются.
|
||||||
|
|||||||
Reference in New Issue
Block a user