优化 Jacobian 确定性复用并补充性能剖析与平台依赖文档
在单次 Jacobian 构建内按完整输入精确复用储气物性、PH 反算、密度和管路求根结果,保持原有求值副作用、差分政策与失败回退。八路模型求解 CPU 中位数减少 19.27%,循环和不循环的完整原始采样均与恢复基线一致。 增加独立的跨平台时间剖析工具,记录互斥阶段耗时、Newton/LU 统计、矩阵复用与内核复用,保存 UD00 两种工况的调查报告和机器可读汇总。 补充 Windows/Linux 运行、测试、原生编译和剖析所需依赖文档及索引,不修改依赖清单、版本锁或安装环境。 验证:8 项新增专项回归通过;2270 次完整 Jacobian 核对零差异;16 次剖析配对及预热运行保持完整数值一致。既有固定样本哈希失败和 Linux 实机验收限制见报告。
This commit is contained in:
1 parent
2b07d996cf
commit
1aac220084
26 files changed
+2293
-13
No files matched your search
@@ -340,7 +340,9 @@ def compile_extended_program(network):
|
||||
else:
|
||||
gas_initializers.append(f'if(!native_medium_init({medium(c)},{num(p0)},{num(T0)},{num(initial_volume)},{int(kind in ("cylinder","tank"))},&y[{states[c.name,"m"+suffix]}])) return 0;')
|
||||
gas_function = 'native_medium_gas_context'
|
||||
lines.append(f'if(!{gas_function}(gas_properties,{medium(c)}, {y(c,"m"+suffix)}, {y(c,thermal)}, {V}, &{gas})) return 0;')
|
||||
gas_arguments = f'{medium(c)}, {y(c,"m"+suffix)}, {y(c,thermal)}, {V}, &{gas}'
|
||||
lines.append(f'if(!(jacobian ? native_jacobian_gas(&jacobian->gases[{gas_count-1}],{gas_function},{gas_arguments},&jacobian->stats) : '
|
||||
f'{gas_function}(gas_properties,{gas_arguments}))) return 0;')
|
||||
gas_inputs = expression_inputs(f'{y(c,"m"+suffix)}+{y(c,thermal)}+({V})')
|
||||
for field in ('p','T','rho','u','h'):
|
||||
dependencies.assign(gas+'.'+field, gas_inputs)
|
||||
@@ -711,10 +713,19 @@ def compile_extended_program(network):
|
||||
if missing: raise NativeCapabilityError(f'Native output mapping incomplete: {sorted(missing)}')
|
||||
if not state_keys: lines.append('dy[0]=0;')
|
||||
jacobian = dependencies.build()
|
||||
memo_kernels = ('native_temperature_ph_context(', 'native_density_context(',
|
||||
'native_pipe_flow_context(', 'native_pipe_flow_cached_context(')
|
||||
has_memo_work = gas_count > 0 or any(name in '\n'.join([*lines,*schedule_helpers]) for name in memo_kernels)
|
||||
reuse_enabled = jacobian.enabled and 0 < jacobian.color_count < nstates and has_memo_work
|
||||
jacobian_info = jacobian.manifest(canonical_rhs=True)
|
||||
jacobian_info['reuse'] = dict(enabled=reuse_enabled,gasSlots=gas_count,scalarSlots=1024,
|
||||
scope='one Jacobian construction',key='kernel and bit-exact complete physical inputs',
|
||||
policy='immutable canonical baseline for gas, PH inversion, density and pipe roots; changed inputs recomputed',
|
||||
verification='uncached canonical dense differences')
|
||||
np,ng,nq=max(1,len(pgroups)),max(1,gas_count),max(1,len(pneu))
|
||||
# Advanced-friction reference runs at 5 N and 7 N confirm Amesim 2404's
|
||||
# 0.1% breakaway hysteresis. Simple friction uses the exact static threshold.
|
||||
source='\n'.join(['#include "model.h"','#include <math.h>',*declarations,
|
||||
source='\n'.join(['#include "model.h"','#include <math.h>','#include <string.h>',*declarations,
|
||||
f'const NativeFriction model_frictions[{max(1,len(friction_groups))}] = {{'+(','.join(
|
||||
'{'+str(states[group[0].name,'v'])+','+str(states[group[0].name,'_friction_mode'])+','+num(threshold)+','+
|
||||
num(sum(c.fstick*(1.001 if int(c.frictionType)==2 else 1) for c in dry))+'}'
|
||||
@@ -725,12 +736,13 @@ def compile_extended_program(network):
|
||||
*jacobian.source_lines(),
|
||||
*schedule_helpers,
|
||||
'int model_init(double *y) {',*[f'y[{i}]={num(v)};' for i,v in enumerate(initial)],*gas_initializers,'return 1;}',
|
||||
'static int model_eval_internal(double t,const double *y,double *dy,double *w,int canonical,double *friction_drives,NativePropertyTemperatures *temperatures) {',
|
||||
'(void)friction_drives;',
|
||||
'static int model_eval_internal(double t,const double *y,double *dy,double *w,int canonical,double *friction_drives,NativePropertyTemperatures *temperatures,ModelJacobianWorkspace *jacobian) {',
|
||||
'(void)friction_drives;(void)jacobian;',
|
||||
f'NativePropertyState property_states[{min(256,max(16,4*gas_count+2*len(components)))}];',
|
||||
'NativePropertyCache property_cache, *properties=&property_cache;',
|
||||
'native_properties_init(properties,property_states,sizeof(property_states)/sizeof(property_states[0]));',
|
||||
'properties->temperatures=temperatures;',
|
||||
'properties->jacobian=jacobian?&jacobian->scalars:NULL;',
|
||||
'NativePropertyCache *gas_properties=canonical?NULL:properties;(void)gas_properties;',
|
||||
*(['double projected[NSTATES];for(int i=0;i<NSTATES;i++) projected[i]=y[i];',*project,'y=projected;'] if project else []),
|
||||
f'double p[{np}]={{0}},h[{nq}]={{0}},q[{nq}]={{0}};NativeGas g[{ng}];',
|
||||
@@ -739,14 +751,23 @@ def compile_extended_program(network):
|
||||
'(void)t;(void)y;(void)w;(void)p;(void)h;(void)q;(void)g;',*lines,
|
||||
'for(int i=0;i<NSTATES;i++) if(!isfinite(dy[i])) return 0;',
|
||||
'for(int i=0;i<NOUTPUTS;i++) if(!isfinite(w[i])) return 0;','return 1;}',
|
||||
'int model_eval(double t,const double *y,double *dy,double *w) {return model_eval_internal(t,y,dy,w,0,NULL,NULL);}',
|
||||
'int model_eval_jacobian(double t,const double *y,double *dy,double *w) {return model_eval_internal(t,y,dy,w,1,NULL,NULL);}',
|
||||
'int model_friction_drives(double t,const double *y,double *drives) {double dy[NSTATES],w[NOUTPUTS];return model_eval_internal(t,y,dy,w,0,drives,NULL);}',
|
||||
'int model_property_temperatures(double t,const double *y,NativePropertyTemperatures *temperatures) {double dy[NSTATES],w[NOUTPUTS];return model_eval_internal(t,y,dy,w,0,NULL,temperatures);}',
|
||||
'int model_eval(double t,const double *y,double *dy,double *w) {return model_eval_internal(t,y,dy,w,0,NULL,NULL,NULL);}',
|
||||
'int model_eval_jacobian(double t,const double *y,double *dy,double *w) {return model_eval_internal(t,y,dy,w,1,NULL,NULL,NULL);}',
|
||||
'void model_jacobian_begin(ModelJacobianWorkspace *workspace) {memset(workspace,0,sizeof(*workspace));workspace->scalars.entries=workspace->scalar_entries;workspace->scalars.capacity=MODEL_JACOBIAN_SCALAR_COUNT;workspace->scalars.recording=1;}',
|
||||
'int model_eval_jacobian_reuse(double t,const double *y,double *dy,double *w,ModelJacobianWorkspace *workspace) {int ok=model_eval_internal(t,y,dy,w,1,NULL,NULL,workspace);if(workspace)workspace->scalars.recording=0;return ok;}',
|
||||
'int model_friction_drives(double t,const double *y,double *drives) {double dy[NSTATES],w[NOUTPUTS];return model_eval_internal(t,y,dy,w,0,drives,NULL,NULL);}',
|
||||
'int model_property_temperatures(double t,const double *y,NativePropertyTemperatures *temperatures) {double dy[NSTATES],w[NOUTPUTS];return model_eval_internal(t,y,dy,w,0,NULL,temperatures,NULL);}',
|
||||
'double model_next_break(double t,double end) { double result=end;(void)t;',*breaks,'return result;}',''])
|
||||
header=f'''#ifndef GENERATED_NATIVE_MODEL_H
|
||||
#define GENERATED_NATIVE_MODEL_H
|
||||
#include "kernels.h"
|
||||
#define MODEL_JACOBIAN_GAS_REUSE {int(reuse_enabled)}
|
||||
#define MODEL_JACOBIAN_GAS_COUNT {gas_count}
|
||||
#define MODEL_JACOBIAN_SCALAR_COUNT 1024
|
||||
typedef struct {{ NativeJacobianGasMemo gases[{ng}]; NativeJacobianGasStats stats;
|
||||
NativeJacobianScalars scalars; NativeJacobianScalarEntry scalar_entries[MODEL_JACOBIAN_SCALAR_COUNT]; }} ModelJacobianWorkspace;
|
||||
void model_jacobian_begin(ModelJacobianWorkspace *workspace);
|
||||
int model_eval_jacobian_reuse(double t,const double *y,double *dy,double *w,ModelJacobianWorkspace *workspace);
|
||||
#define MODEL_PROPERTY_TEMPERATURES {int(any(key[1] == 'peng_robinson' for key in media))}
|
||||
int model_property_temperatures(double t,const double *y,NativePropertyTemperatures *temperatures);
|
||||
#define NSTATES {nstates}
|
||||
@@ -764,4 +785,4 @@ int model_eval(double t,const double *y,double *dy,double *w);
|
||||
double model_next_break(double t,double end);
|
||||
#endif
|
||||
'''
|
||||
return NativeProgram(source,header,tuple(state_keys),variables,tuple(sorted({c.model_type for c in components})),schedule.report(),jacobian.manifest(canonical_rhs=True))
|
||||
return NativeProgram(source,header,tuple(state_keys),variables,tuple(sorted({c.model_type for c in components})),schedule.report(),jacobian_info)
|
||||
Reference in new issue
Block a user