修复循环信号与事件采样并接入 LSTP 接触定位,补充八路验证及复用实验
相较上一版 Jacobian 确定性复用更新,本次补齐事件边界一致性、结果两侧采样及接触事件定位;保留已有物性复用和组件力学公式。 - 统一 UD00 信号求值与下一事件查询的绝对时间边界,修复循环边界浮点舍入导致的阶段错位、重复或漏报,并覆盖零时长、多阶段及长周期场景。 - 引入原生输出语义 v2:保留规则网格真实时间,补充内部时间事件和状态事件的左邻及事件后采样,按保存时间、状态和离散模式重放结果。 - 两条代码生成路径均发出 LSTP 接触描述,默认定位间隙过零及非负力模式的力截断;仅在接受事件时更新防重复记录,增加 contactEvents 诊断计数。 - 补充 MASS/LSTP 独立事件实验、八路全曲线与驱动阶段配对评估,以及 Amesim 不连续点输出对照和力差定位报告;MASS 新增释放机制仍保留为独立实验。 - 保存局部 probe、context 访问与回退、shadow replay、R288 real skip/typed replay 及阀门数值尾部诊断工具和报告;未证明净收益的实验不启用为生产默认优化。 - 更新原生运行说明和元件建模规范,补充信号边界、输出语义、接触事件和实验依赖回归测试。 验证:五组专项回归共 34 项全部通过;37 个待提交 Python 文件语法检查通过;git diff --cached --check 通过。
This commit is contained in:
1 parent
1aac220084
commit
7611f13208
85 files changed
+11358
-33
No files matched your search
@@ -0,0 +1,63 @@
|
||||
"""Summarize accuracy, contact phases and repeated cost for isolated variants."""
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import statistics
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
def read(path):return json.loads(path.read_bytes())
|
||||
|
||||
|
||||
def main():
|
||||
parser=argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('directory',type=Path)
|
||||
args=parser.parse_args();out=args.directory
|
||||
runs=read(out/'summary.json');rows=[];branches=[];groups=[]
|
||||
for profile,variants in runs.items():
|
||||
baseline=variants['off']
|
||||
base_force=baseline['groups']['force']['worstAbsolute']['maxAbsoluteError']
|
||||
base_time=baseline['timing']['medianSeconds']
|
||||
base_curves=np.load(out/profile/'off/curves.npz')
|
||||
for mode,r in variants.items():
|
||||
data=np.load(out/profile/mode/'curves.npz')
|
||||
contacts=[]
|
||||
for key in data.files:
|
||||
if key.startswith('platform|') and key.endswith('.gap'):
|
||||
expected='amesim|'+key.split('|',1)[1]
|
||||
mismatch=data['phaseMatched'] & ((data[key]<0)!=(data[expected]<0))
|
||||
contacts.extend(dict(key=key.split('|',1)[1],time=float(data['time'][i])) for i in np.flatnonzero(mismatch))
|
||||
equal=all(np.array_equal(data[k],base_curves[k],equal_nan=True)
|
||||
for k in data.files if k.startswith('platform|'))
|
||||
worst=r['groups']['force']['worstAbsolute'];timing=r['timing'];native=r['nativeRun']
|
||||
report=read(out/profile/mode/'comparison.json')
|
||||
branches.extend(dict(profile=profile,mode=mode,**c) for c in report['curves'] if c['quantity']=='force')
|
||||
groups.extend(dict(profile=profile,mode=mode,quantity=q,**g) for q,g in r['groups'].items())
|
||||
counter_keys=('nfev','acceptedSteps','rejectedSteps','solverStarts','stateTransitions','njev','nlu','experimentalEvents')
|
||||
counters=[{k:t.get(k) for k in counter_keys} for t in timing['runs']]
|
||||
row=dict(profile=profile,mode=mode,medianSolveSeconds=timing['medianSeconds'],
|
||||
minimumSolveSeconds=timing['minimumSeconds'],maximumSolveSeconds=timing['maximumSeconds'],
|
||||
timingRepeats=timing['repeats'],repeatCountersStable=all(c==counters[0] for c in counters),
|
||||
medianCpuSeconds=statistics.median(t['solveCpuSeconds'] for t in timing['runs']),
|
||||
solveChangePercent=100*(timing['medianSeconds']/base_time-1),
|
||||
forceMaxError=worst['maxAbsoluteError'],forceWorstTime=worst['worstTime'],forceWorstKey=worst['key'],
|
||||
forceErrorChangePercent=100*(worst['maxAbsoluteError']/base_force-1),
|
||||
forceQuietMax=max(c['quietMaxAbsolute'] for c in report['curves'] if c['quantity']=='force'),
|
||||
pressureMaxError=r['groups']['pressure']['worstAbsolute']['maxAbsoluteError'],
|
||||
temperatureMaxError=r['groups']['temperature']['worstAbsolute']['maxAbsoluteError'],
|
||||
above5PercentCount=r['above5PercentCount'],phaseUnpairedCount=r['phaseUnpairedGridCount'],
|
||||
contactPhaseMismatches=contacts,gridTrajectoryEqualsOff=equal,
|
||||
rawPeakContactForce=r['extraEventPointMaxContactForce'],
|
||||
acceptedSteps=native['acceptedSteps'],rejectedSteps=native['rejectedSteps'],
|
||||
nfev=native['nfev'],solverStarts=native['solverStarts'],njev=native['njev'],nlu=native['nlu'],
|
||||
stateTransitions=native['stateTransitions'],
|
||||
experimentalEvents=native.get('experimentalEvents',{}),jacobianMode=native['jacobianMode'])
|
||||
rows.append(row)
|
||||
print(json.dumps(row,ensure_ascii=False))
|
||||
(out/'effect-summary.json').write_text(json.dumps(rows,ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
|
||||
(out/'branch-force-summary.json').write_text(json.dumps(branches,ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
|
||||
(out/'group-summary.json').write_text(json.dumps(groups,ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
|
||||
|
||||
|
||||
if __name__=='__main__':main()
|
||||
Reference in new issue
Block a user