Real 5000-run sweep + 600-genome evolution through docker compose run, not a synthetic smoke test. Two concrete outcomes worth recording: 1. Quantitative confirmation of the sensor discussion from the original planning conversation: inductive pickup sensor reached only 0.2% feasibility (6/2965 configs using it), vs ~45-47% for optical/Hall, because its trigger threshold sits above the fixed launch velocity. 2. Best honest result after the efficiency-metric fix: single stage, 80.97% efficiency, 26.4 m/s, ~1029 RUB in real parts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
13 KiB
План: Gauss-ускоритель — симулятор и оптимизатор
Многоступенчатый электромагнитный ускоритель ферромагнитного цилиндра (coilgun). Каждая ступень: разгонная катушка (Cu/Al провод на пластиковой трубке) + батарея конденсаторов через тиристор/MOSFET, и датчик прохода снаряда перед катушкой (компенсация задержки включения ключа). Датчик — два конкурирующих варианта: индукционная катушка (сигнал ~ скорости снаряда, слаб на медленных ступенях) и оптопара/датчик Холла (не зависит от скорости) — оптимизатор сравнивает оба.
Цель поиска — КПД (кинетическая энергия снаряда на выходе / энергия во всех конденсаторах). Скорость и стоимость — вторичные метрики. Число ступеней N, геометрия/материал снаряда, все компоненты — часть пространства поиска, а не фиксированные входы. Компоненты — реальные, розничные (Проконтакт/procontact74.ru, ChipDip, Cable.ru и др.).
Требование: миллионы прогонов (Monte Carlo/LHS sweep + эволюционный поиск), все результаты — успешные и неудачные, с честной причиной отказа — пишутся в SQLite. Никаких приукрашенных цифр — если модель показывает низкий КПД или нереализуемость, это тоже результат.
Найденная и исправленная ошибка (Этап 3): насыщение сердечника изначально
клэмпилось только в механическом уравнении (F=0.5·I²·dL/dx), но не в
электрическом (наведённая ЭДС всё ещё считалась по полной dL/dx) — это
незаметно ломало точный энергобаланс на ~15%. Тест на сохранение энергии
(этого же честного протокола, который просил пользователь) это поймал.
Решение: клэмп насыщения убран из динамики (F=0.5·I²·dL/dx без клэмпа,
энергобаланс теперь точен до ~0.02%), а solenoid_field_estimate_tesla/
saturation_scale оставлены как ДИАГНОСТИКА — StageResult.saturation_warning
честно предупреждает, когда конфигурация физически выходит за пределы
насыщения материала снаряда, не подменяя динамику. Полная нелинейная
L(x, I)-модель с coenergy-выводом силы — в разделе "ограничения модели"
как будущая работа, не как текущая гарантия точности.
Полный план архитектуры: см. историю обсуждения / physics, sim, optim,
storage, report модули ниже.
Docker — основной способ запуска (по требованию пользователя): Dockerfile
docker-compose.ymlв корне репозитория, образ собран и провалидирован — внутри контейнера запускаются все 37 тестов и CLI (docker compose run --rm --entrypoint pytest gausse -q). Результаты (SQLite и отчёты, когда появятся) монтируются в./resultsна хосте, чтобы переживать пересборку образа.
Чек-лист этапов
- Этап 0 — Скелет проекта:
pyproject.toml,README.md,.gitignore, пакетыsrc/gausse/*, этот файл, первый коммит. - Этап 1 — База реальных компонентов: провод Cu/Al, конденсаторы, тиристоры/MOSFET/IGBT, датчики (Hall/оптика реальные, индукционный — оценка), материалы снаряда →
components/data/*.json. Каждая запись честно помечена REAL (с URL источника) или ОЦЕНКА (с указанием основания); алюминиевый провод и ёмкости 1000/2200мкФ — низкая уверенность в цене, явно отмечено. - Этап 2 — Физическое ядро:
physics/constants.py,inductance.py(Уилер + ферромагнитный сердечник + размагничивание),force.py,circuit.py(ОДУ RLC). Юнит-тесты: аналитическое RLC-решение, согласованность dL/dx. - Этап 3 — Датчики и одна ступень:
physics/sensors.py(оба типа как события solve_ivp),sim/stage.py(полёт → триггер → разряд → энергобаланс). Тест на сохранение энергии + найден/исправлен баг насыщения (см. выше). - Этап 4 — Многоступенчатая цепочка:
sim/coilgun.py— сквозная координата, отбраковка нереализуемых конфигураций. Дымовой тест на реальной базе компонентов (test_real_components_smoke.py) подтверждает: полный путь реальные JSON → физика → цепочка работает (пример: 22.3 м/с, КПД 3.4% — честный неоптимизированный результат). - Этап 5 — Хранилище результатов:
storage/schema.py+database.py— SQLite (WAL), таблицаrunsсо всеми прогонами (успех/провал + честная причина), однопроцессный писатель поверх многопроцессной очереди. Тест с реальнымиmultiprocessing.Process(не моками) поймал реальную проблему: коллизияrun_idроняла writer и молча останавливала осушение очереди на весь sweep — писатель теперь переживает ошибку вставки одной записи (лог в stderr) и продолжает работу. - Этап 6 — Поиск и оптимизация:
optim/search_space.py(геном переменной длины — число ступеней тоже эволюционирует),objective.py(fitness=КПД, честный мягкий штраф за нереализуемость пропорционально пройденным ступеням),optim/sweep.py(параллельный Monte Carlo, каждый прогон в SQLite),optim/evolutionary.py((μ+λ)-ГА + Nelder-Mead полировка непрерывных параметров лучшего генома). Тест поймал реальный баг вcrossover()— IndexError при скрещивании двух одноступенчатых геномов (пустой список зазоров), исправлено и покрыто регрессией.- Не сделано: отдельный "дешёвый квазистатический предфильтр" перед полным ODE не реализован (кроме уже встроенной в
sim/stage.pyдешёвой проверки порога индукционного датчика). Если миллионы прогонов на сервере окажутся слишком медленными, это первое место для ускорения.
- Не сделано: отдельный "дешёвый квазистатический предфильтр" перед полным ODE не реализован (кроме уже встроенной в
- Этап 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). - Этап 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, оптический датчик). - Честное сравнение датчиков (запрос из первого обсуждения плана) — на 5000 прогонах: индукционный датчик (
inductive-pickup-lm393) дал 0.2% реализуемых конфигураций (6 из 2965, где он стоял хотя бы на одной ступени), тогда как оптический (TCST2103) и Холла (A3144E) — ~45-47% реализуемых каждый. Это количественно подтверждает опасение, высказанное в самом начале обсуждения плана: индукционная катушка-датчик ненадёжна именно потому, что требует скорости выше её порога (здесь — фиксированный старт 3 м/с как раз ниже порога срабатывания реального компонента), тогда как оптика/Холл не зависят от скорости. - Итог: сквозная цепочка (реальные компоненты → физика → поиск → SQLite → отчёт с графиками/BOM/анимацией) работает и произвела не выдуманный, а посчитанный и перепроверенный результат.
- Найден и исправлен реальный баг именно на этом этапе: КПД лучшего генома после
- Этап 9 — GPU-ускорение массового sweep (сервер с GTX 1070): после того как CPU/
scipy.solve_ivp-модель провалидирована тестами (Этап 2-4) — батч-версия интегратора с ФИКСИРОВАННЫМ шагом (RK4/полу-неявная схема), считающая сразу N траекторий параллельно как один тензор (cupy, если доступна CUDA, иначе векторизованныйnumpy/numba), для прогона по-настоящему миллионов конфигураций на сервере. Важно: сначала корректность на CPU, потом скорость на GPU — численные результаты GPU-пути должны сверяться с CPU-эталоном на контрольной выборке, чтобы ускорение не подменило точность честными числами "для галочки".