装药模板套用与适配
全局配置库里的装药结构模板(explosivemodel.dmt,如 连续装药 /
间隔装药)以某个标定孔深描述炮孔自孔口 → 孔底的分段结构——第 0 段固定是孔口填塞物。
真实炮孔孔深几乎不可能正好等于标定总长,因此需要把模板按「装药模式 × 调整规则」适配到
每根孔:填塞保规范下限、炸药 / 间隔按策略取舍或压缩、富余空间补到孔口填塞或末段间隔,
保证分段总长精确 = 孔深。
适用场景:工地有成熟的装药结构经验模板(一段一段怎么装已标定好),希望按模板结构去装药, 而不是让 SDK 用单耗公式凭空生成结构。若没有固定模板、更想「按单耗算药量」,用直算入口
design_charge(见 爆破设计流程 / 装药)。
本模块算法移植自 Dimine CDesignExplosiveOperator(修正版)。数值口径:长度 m、重量 kg、
延时 ms;重量按炸药段逐段 × 线装药密度累加。
from dimine_python_sdk.lib.blasting import (
ChargeParams, Explosive, Hole, ChargeMode, AdjustRule,
design_charge_from_template, adapt_charge_template, TemplateAdaptation,
)
from dimine_python_sdk.lib.blasting.charge_design import min_stemming_length
一、底层适配 adapt_charge_template
单孔(几何层,不绑定孔对象)把模板适配到给定孔深:
result: TemplateAdaptation = adapt_charge_template(
hole_length=16.0, # 真实孔深 m
segments=template_segments, # 模板分段(ChargeSegment / dict),第 0 段=孔口填塞
mode=ChargeMode.MIN_STEMMING, # 装药模式
adjust=AdjustRule.PROPORTIONAL, # 调整规则
min_block_length=4.5, # 最小填塞规范下限(用 min_stemming_length 算)
line_density={"2#岩石炸药": 6.0}, # 炸药名 → 线装药密度 kg/m
# 仅模式1(按单耗)需要:
# consumption=0.4, hole_space=5.0, row_space=4.0,
# primary_density_default=6.0, # 模板炸药名查不到密度时的兜底
)
min_block_length 请用公式装药与模板适配共用的权威口径:
# = max(min_stemming, 0.7·W, 20·直径m, 4.5m)
min_block_length = min_stemming_length(ChargeParams(), burden=4.0, diameter_m=220.0 / 1000.0)
返回 TemplateAdaptation(frozen dataclass):
| 字段 | 说明 |
|---|---|
ok |
是否适配成功 |
fail_code / fail_reason |
失败原因 A/B/C(见下) |
segments |
适配后的分段(自孔口→孔底),总长精确 = 孔深 |
charge_length / charge_weight |
装药总长度 m / 装药总量 kg |
stemming_length / spacer_length |
填塞长度 m / 间隔总长度 m(间隔器+空气) |
三种失败(不抛异常,ok=False + fail_code)
| code | 含义 |
|---|---|
A |
孔深 ≤ 最小填塞规范下限 |
B |
孔深 < 按单耗所需装药长度(仅模式1) |
C |
孔深 < 最小填塞 + 间隔总长(仅模式2) |
结构 / 参数本身的错误(模板为空、无有效长度、模式1 缺参数或无炸药段、炸药名既查不到密度又无兜底)
则抛 ValueError。
三种装药模式 × 三种调整规则
装药模式 ChargeMode(决定「优先级」):
| 模式 | 优先级 | 行为 |
|---|---|---|
MIN_STEMMING 优先最小填塞和炸药 |
填塞保最小 → 炸药尽量保 → 间隔尽量保 | 富余全给孔口填塞;空间不足先放弃间隔再压缩炸药 |
BY_SPECIFIC_CHARGE 优先按单耗 |
按单耗定药量 → 填塞保最小 | 目标药量 = consumption × 孔距×排距 × 孔深,按模板炸药段「长度×密度」比例反解各段实装长度,使实装药量恰好等于目标 |
STEMMING_SPACER 优先填塞和间隔器 |
间隔全保 → 填塞保最小 → 剩余给炸药 | 保留模板全部间隔,其余空间给炸药 |
调整规则 AdjustRule(决定炸药段被压缩 / 有多余时「保哪一侧」):
| 规则 | 语义 |
|---|---|
PROPORTIONAL 按比例 |
各炸药段按模板长度比例等比缩放 |
MOUTH_FIRST 优先孔口装药 |
自孔口段起逐段保证(模板长度),装完即止 |
BOTTOM_FIRST 优先孔底装药 |
自孔底段倒序保证;仍有富余则补到孔口侧第一段 |
直观效果(对同一根 10 m 孔、同一模板,见
test_template_adapt_strategy.py): 模式0 药量 ≥ 模式1 ≥ 模式2;模式2 保留间隔、余量喂炸药;MOUTH_FIRST保孔口段、BOTTOM_FIRST保孔底段。孔深恰好等于模板总长时,任何模式/规则都逐段还原模板。
二、批量入口 design_charge_from_template
对一整批炮孔套模板,直接产出 .dmo 可用的装药结果:
from dimine_python_sdk.lib.blasting import ChargeTemplateDB
# 1) 从模板库取出一个模板(自孔口→孔底;模板不存在 → [])
db = ChargeTemplateDB()
template_segments = db.segments("间隔装药")
# 2) 炸药库(主炸药 = 模板炸药段命中的名字,否则取列表首个;其线密度兼作未知段名的兜底)
explosives = [Explosive(name="2#岩石炸药", line_density=6.0, unit_price=5.0),
Explosive(name="乳化炸药", line_density=6.0, unit_price=8.0)]
# 3) 逐孔套模板(mode / adjust 由 ChargeParams 决定)
results = design_charge_from_template(
holes, # 布孔结果 list[Hole]
template_segments,
explosives,
burden=4.0, # 最小抵抗线 W m
params=ChargeParams(
charge_mode=ChargeMode.MIN_STEMMING, # 或 BY_SPECIFIC_CHARGE / STEMMING_SPACER
adjust_rule=AdjustRule.PROPORTIONAL,
specific_charge=0.4, # 模式1 使用
),
) # -> list[ChargeResult](每孔一个,顺序同 holes)
每个炮孔内部先算 min_block = min_stemming_length(params, W, 孔径m),再交给 adapt_charge_template。
失败孔不抛异常:返回 segments == []、charge_weight == 0,并把原因写进该孔 warnings
(如 "[装药结构适配失败:原因A] 孔深小于最小填塞长度");模板不含炸药段时给黄/红提示且药量为 0。
for r in results:
if not r.segments:
print(r.hole_number, "适配失败:", r.warnings) # 原因 A/B/C,需人工处理(如并入深孔或降台阶)
ChargeResult 各字段与直算口径一致(specific_charge_area 记录每孔负担面积:前排 a×W、
后排 a×b),可直接交给 起爆网络与 DMO 的后续步骤。
三、完整示例(含校验)
from dimine_python_sdk.lib.blasting import (
BlastRegion, HoleLayoutParams, Hole, ChargeParams, ChargeMode, AdjustRule,
ChargeTemplateDB, layout_holes, design_charge_from_template, build_network,
)
# 布孔
region = BlastRegion(
name="M01",
polygon=[(0, 0), (30, 0), (30, 25), (0, 25)],
mouth={"mode": "z", "value": 765.0},
bottom={"mode": "depth", "value": 15.0},
)
holes = layout_holes(region, HoleLayoutParams(hole_spacing=5.0, row_spacing=4.0))
# 取模板 + 装药
template = ChargeTemplateDB().segments("间隔装药") # 需 DIMINE_HOME
results = design_charge_from_template(
holes, template,
[Explosive(name="2#岩石炸药", line_density=6.0)],
burden=4.0,
params=ChargeParams(charge_mode=ChargeMode.MIN_STEMMING,
adjust_rule=AdjustRule.PROPORTIONAL),
)
# 校验不变式(与公式装药引擎一致)
assert len(results) == len(holes)
for r in results:
if r.segments:
assert abs(sum(s.length for s in r.segments) - r.depth) < 1e-6 # 总长=孔深
assert r.segments[0].fill_type == template[0].fill_type # 首段=孔口填塞
assert r.stemming_length >= 4.5 # 填塞 ≥ 规范下限
for s in r.segments:
assert s.delay >= 0 or s.fill_type in ("填塞物", "间隔器", "空气") # 惰性段 delay=-1
记忆要点:模板第 0 段固定为孔口填塞物,其长度由算法重算,模板里写多少不影响; 适配后的炸药段雷管延时沿用模板设定(如 350 → 380 → 410 ms),惰性段恒为
-1; 起爆药包 / 空气参与结构与起爆,但起爆药包重量计 0。
参考链接
- 全局配置库与参数来源 —
ChargeTemplateDB的模板增删改查 - 爆破设计流程 — 布孔与装药之后:起爆网络 / 分析 / DMO 落盘
- 模块总览与数据模型 —
ChargeMode/AdjustRule/ChargeResult字段