Wire (Cu/Al ПЭТВ-2), capacitors (350-450V electrolytic bank), switches (КУ202Н/BT151 SCR, IRFP250/IRFP4468 MOSFET, IRG4PC50F IGBT), sensors (A3144E Hall, TCST2103 optical, LM393-based inductive pickup), and projectile materials (Ст3, Сталь 10, армко-железо) sourced from procontact74.ru/chipdip.ru/cable.ru research. Every entry's `source` field states plainly whether the number is a REAL scraped retail price/spec (with URL) or an ОЦЕНКА (estimate) with its basis (e.g. aluminum magnet wire has no self-service retail price in RU stores, so it's priced as a fraction of equivalent copper) — no value is presented as real when it isn't. Added a smoke test proving the real database runs end-to-end through the full physics + chaining pipeline, not just against synthetic test fixtures. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
71 lines
3.1 KiB
Python
71 lines
3.1 KiB
Python
"""Дымовой тест: реальная база компонентов (Этап 1) действительно прогоняется.
|
||
|
||
Не проверяет конкретные числа (это будет делать sweep/оптимизатор) — только
|
||
то, что хотя бы одна разумная комбинация реальных деталей из
|
||
components/data/*.json физически прогоняется через полную цепочку без
|
||
исключений, и что честная отбраковка (feasible=False) тоже доступна и не
|
||
падает, если комбинация неудачная.
|
||
"""
|
||
|
||
from gausse.components.database import ComponentDatabase
|
||
from gausse.sim.coilgun import CoilgunConfig, run_coilgun
|
||
from gausse.sim.stage import ProjectileConfig, StageConfig
|
||
|
||
|
||
def _find(items, **kwargs):
|
||
for item in items:
|
||
if all(getattr(item, k) == v for k, v in kwargs.items()):
|
||
return item
|
||
raise AssertionError(f"не найден компонент с {kwargs} среди {len(items)} записей")
|
||
|
||
|
||
def test_real_component_database_loads_and_is_nonempty():
|
||
db = ComponentDatabase.load()
|
||
assert len(db.wires) > 0
|
||
assert len(db.capacitors) > 0
|
||
assert len(db.switches) > 0
|
||
assert len(db.sensors) > 0
|
||
assert len(db.projectile_materials) > 0
|
||
|
||
|
||
def test_real_component_combination_runs_end_to_end():
|
||
db = ComponentDatabase.load()
|
||
wire = _find(db.wires, part_id="cu-petv2-1.0mm")
|
||
capacitor = _find(db.capacitors, part_number="cap-470uf-400v")
|
||
switch = _find(db.switches, part_number="IRFP250PBF")
|
||
sensor = _find(db.sensors, part_number="TCST2103")
|
||
steel = _find(db.projectile_materials, name="Ст3 (конструкционная сталь)")
|
||
|
||
projectile = ProjectileConfig(material=steel, diameter_m=0.008, length_m=0.02)
|
||
stage = StageConfig(
|
||
wire=wire,
|
||
capacitor=capacitor,
|
||
switch=switch,
|
||
sensor=sensor,
|
||
tube_od_m=0.01,
|
||
turns_per_layer=20,
|
||
layers=4,
|
||
sensor_to_coil_distance_m=0.02,
|
||
charge_voltage_v=350.0,
|
||
)
|
||
config = CoilgunConfig(
|
||
stages=[stage, stage],
|
||
inter_stage_gaps_m=[0.05],
|
||
projectile=projectile,
|
||
initial_x_m=-0.05,
|
||
initial_v_mps=5.0,
|
||
)
|
||
|
||
result = run_coilgun(config)
|
||
|
||
# Реальные детали могут дать как удачную, так и провальную (feasible=False)
|
||
# конфигурацию — это тоже честный результат. Тест лишь гарантирует, что
|
||
# весь путь (реальные JSON -> физика -> цепочка) не падает с исключением
|
||
# и возвращает осмысленный, самосогласованный результат в любом случае.
|
||
if result.feasible:
|
||
assert result.exit_v_mps is not None
|
||
assert 0.0 <= result.efficiency <= 1.0
|
||
else:
|
||
assert result.reason is not None
|
||
assert result.failed_stage_index is not None
|