По требованию пользователя «не сохранять всё подряд, а только то, что нужно для эволюции»: рядовые геномы поколения больше НЕ пишутся строками в runs — писатель получает лёгкие StatsOnly-инкременты (счётчики, гистограмма, причины отказов на дашборде остаются честными по ВСЕМ оценкам), а полная строка пишется только когда лучший геном острова улучшился (+ полировка). Вставка миллионов строк в HDD-базу с 6 индексами была узким местом конвейера: GPU считал цикл ~23 мин, дозапись хвоста очереди шла часами (~150 строк/с), реальная скорость была ~165 оценок/с вместо ~1300/с. gpu_record_worker стал не нужен — удалён. Выборка эволюции уменьшена до 10000 на поколение (8 островов x 1250, было 8x4000=32000) — по просьбе пользователя, чтобы поколения сменялись быстрее; поколений за цикл теперь 120 (было 60) — при освобождённом писателе цикл углубляется вдвое дальше за то же время.
gausse
Симулятор и оптимизатор многоступенчатого электромагнитного ускорителя (coilgun / пушка Гаусса) на реальных, доступных в рознице компонентах (ChipDip, procontact74.ru, cable.ru — у каждой детали в базе ссылка на магазин).
Главный принцип — честность: все прогоны (включая нереализуемые, с причиной отказа) пишутся в SQLite; физическая модель не приукрашивается ради красивых цифр, а каждое известное упрощение задокументировано. История проекта — это в том числе история найденных и исправленных завышений КПД (80%+ → реалистичные единицы процентов), см. PLAN.md.
Что умеет
- Физика (
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 раунд-за-раундом И GPU-эволюция (use_gpu=True: всё поколение — один батч, ~150 геномов/с на 1070); сверено с CPU-эталоном (<0.1%). - Отчёты (
src/gausse/report/,src/gausse/web/): веб-дашборд с drill-down до каждой детали и энергобаланса ступени, графики ток/поле/ скорость, GIF-анимация выстрела (равномерное физическое время, результат эксперимента в кадре), BOM с ценами и ссылками «купить».
Запуск (Docker — основной способ)
docker compose build
docker compose run --rm --entrypoint pytest gausse -q # тесты
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
GPU-режим (нужны NVIDIA-драйвер и pip install cupy-cuda12x[ctk], вне Docker):
gausse sweep --gpu --n 1000000 --db results/gausse.sqlite3
Результаты (SQLite + лог хода эксперимента <db>.log) живут в ./results,
примонтированном в контейнер, и переживают пересборку образа.
Установка без Docker (локальная разработка)
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
Автономная работа на сервере
Эволюция оформлена как systemd-сервис gausse-evolve (вечный цикл: 120
поколений × 1000 особей на GPU, по окончании — новый цикл со свежей
случайной популяцией; Restart=always, автозапуск при загрузке). Дашборд — Docker-
сервис web на :8000, читает ту же базу. Счётчик «запланировано» на
дашборде — план текущего цикла, а не всего поиска: поиск бесконечен.
Ограничения модели (честно)
- Индуктивность — инженерная модель (Уилер + размагничивание сфероида + tanh-перекрытие), не МКЭ; точная картина поля требует FEA.
- Вихревые потери снаряда — сосредоточенный виток; диффузия поля в снаряд — одночастотная оценка скин-кольца, а не решение уравнения диффузии.
- Доуэлл берёт одну характерную частоту ω=1/√(LC), без спектра импульса.
- Воздух — лобовое сопротивление; поршневой эффект столба воздуха в трубе не учтён. Трение — константа 0.35 (сталь-пластик), не измерено.
- Гистерезис снаряда посчитан и сознательно не включён в динамику (<0.1%).
- Нагрев провода за импульс и от серии выстрелов не моделируется.
Версия физики пишется в каждую запись (model_version, сейчас gausse-physics-v4) — прогоны разных моделей не смешиваются.