C内核流量计算方法优化,前端文件名称读取优化
This commit is contained in:
1 parent
5d5a2e1843
commit
808c484f5b
94 files changed
+20163
-4418
No files matched your search
@@ -0,0 +1,92 @@
|
||||
"""Compare real native/browser results to the frozen 72-curve Amesim reference.
|
||||
|
||||
Run with Python + NumPy. --plot additionally requires Matplotlib, available in
|
||||
this workstation's system Python. Outputs stay in the requested artifact folder.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import argparse
|
||||
import csv
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
LIMITS = {'pressure': 250., 'temperature': .015, 'displacement': 2e-6,
|
||||
'velocity': 1e-5, 'mass_flow': 3e-5}
|
||||
UNITS = {'pressure': 'Pa', 'temperature': 'K', 'displacement': 'm',
|
||||
'velocity': 'm/s', 'mass_flow': 'kg/s'}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('result', type=Path)
|
||||
parser.add_argument('--reference', type=Path, default=ROOT/'tests/baselines/simulation/test_mql_4/test-mql-4-amesim-reference.json')
|
||||
parser.add_argument('--output-dir', type=Path, required=True)
|
||||
parser.add_argument('--plot', action='store_true')
|
||||
args = parser.parse_args()
|
||||
ref = json.loads(args.reference.read_text())
|
||||
data = json.loads(args.result.read_text())
|
||||
if 'snapshot' in data:
|
||||
data = data['snapshot']['result']
|
||||
series = data['series']; times = np.array(series['time']); ref_times = np.array(ref['times'])
|
||||
if not data['success'] or times[-1] < ref_times[-1] or times[0] > ref_times[0]:
|
||||
raise ValueError('A completed result covering all reference times is required.')
|
||||
if np.any(np.diff(times) < 0):
|
||||
raise ValueError('Native sample times are not ordered.')
|
||||
finite = all(np.all(np.isfinite(values)) for values in series.values())
|
||||
rows = []; grouped = {}
|
||||
for key, curve in ref['series'].items():
|
||||
actual = np.interp(ref_times, times, series[key]); error = actual - curve['values']
|
||||
worst = int(np.argmax(abs(error))); quantity = curve['quantity']
|
||||
row = {'key': key, 'quantity': quantity, 'unit': UNITS[quantity],
|
||||
'maxAbsoluteError': float(abs(error[worst])), 'rmsError': float(np.sqrt(np.mean(error**2))),
|
||||
'worstTime': float(ref_times[worst]), 'limit': LIMITS[quantity],
|
||||
'passed': bool(np.max(abs(error)) <= LIMITS[quantity])}
|
||||
rows.append(row)
|
||||
if quantity not in grouped or row['maxAbsoluteError'] > grouped[quantity]['maxAbsoluteError']:
|
||||
grouped[quantity] = row
|
||||
masses = np.array([v for k, v in series.items() if k.rsplit('.', 1)[-1] in ('m', 'm1', 'm2')])
|
||||
total = np.sum(masses, axis=0)
|
||||
mass_drift = float(np.max(abs(total-total[0])))
|
||||
force_peaks = sorted(({'key': k, 'peakAbsolute': max(map(abs, v))} for k, v in series.items()
|
||||
if k.startswith('amesim_lstp00a_') and k.endswith('.f')),
|
||||
key=lambda row: row['peakAbsolute'], reverse=True)
|
||||
summary = {'resultPath': str(args.result.resolve()),
|
||||
'resultSha256': hashlib.sha256(args.result.read_bytes()).hexdigest(),
|
||||
'referencePath': str(args.reference.resolve()),
|
||||
'referenceSha256': hashlib.sha256(args.reference.read_bytes()).hexdigest(),
|
||||
'referenceSource': ref['source'], 'freshAmesimRun': False,
|
||||
'referenceCurveCount': len(rows), 'referenceTimeCount': len(ref_times),
|
||||
'nativeSampleCount': len(times), 'allSamplesFinite': bool(finite),
|
||||
'massStateCount': len(masses), 'maxTotalMassDriftKg': mass_drift,
|
||||
'groupedWorstErrors': grouped, 'curves': rows, 'contactForcePeaksOutsideReferenceScope': force_peaks,
|
||||
'passed': bool(finite and mass_drift <= 1e-10 and all(row['passed'] for row in rows))}
|
||||
args.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
(args.output_dir/'comparison.json').write_text(json.dumps(summary, ensure_ascii=False, indent=2)+'\n')
|
||||
with (args.output_dir/'curve-errors.csv').open('w', newline='') as output:
|
||||
writer = csv.DictWriter(output, fieldnames=list(rows[0])); writer.writeheader(); writer.writerows(rows)
|
||||
if args.plot:
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
fig, axes = plt.subplots(5, 2, figsize=(13, 15), constrained_layout=True)
|
||||
for (quantity, row), (left, right) in zip(grouped.items(), axes):
|
||||
key = row['key']; values = ref['series'][key]['values']
|
||||
actual = np.interp(ref_times, times, series[key])
|
||||
left.plot(times, series[key], linewidth=1, label='Native, rtol=1e-8')
|
||||
left.plot(ref_times, values, '.', markersize=3, label='Saved Amesim reference')
|
||||
left.set_title(key, fontsize=9); left.set_ylabel(UNITS[quantity]); left.legend(fontsize=7)
|
||||
right.plot(ref_times, actual-values, '.-', linewidth=.8, markersize=3)
|
||||
right.axhline(row['limit'], color='gray', linestyle='--', linewidth=.6)
|
||||
right.axhline(-row['limit'], color='gray', linestyle='--', linewidth=.6)
|
||||
right.set_title(f'{quantity}: sampled difference and acceptance limits', fontsize=9)
|
||||
right.set_ylabel(UNITS[quantity])
|
||||
for ax in (left, right): ax.grid(alpha=.2); ax.set_xlabel('Time [s]')
|
||||
fig.suptitle('Four-branch model: 72 curves checked at 57 stored Amesim times\nWorst curve per quantity; contact force is outside this reference', fontsize=12)
|
||||
fig.savefig(args.output_dir/'comparison.svg'); fig.savefig(args.output_dir/'comparison.png', dpi=140)
|
||||
print(json.dumps({k: summary[k] for k in ('passed', 'nativeSampleCount', 'maxTotalMassDriftKg', 'groupedWorstErrors')}, indent=2))
|
||||
if not summary['passed']: raise SystemExit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
Reference in new issue
Block a user