相较上一版 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 通过。
64 lines
4.2 KiB
C
64 lines
4.2 KiB
C
/* Diagnostic worker only: original tail executes on every visit. */
|
|
#include "valve_tail_diag.h"
|
|
#include <windows.h>
|
|
#include <cpuid.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <fenv.h>
|
|
#include <math.h>
|
|
#include <stddef.h>
|
|
int kd_scope;
|
|
uint64_t kd_jac;
|
|
KdMemo kd_memo;
|
|
static KdRecord records[26000];
|
|
static size_t count;
|
|
static uint64_t entries,hits,executions,lookup_ticks,capture_ticks,reset_ticks,tail_ticks;
|
|
static uint64_t base_lookup_ticks,miss_lookup_ticks,hit_lookup_ticks;
|
|
static uint64_t qpc_frequency,tsc_start,qpc_start;
|
|
static FILE *matrix_file;
|
|
static int disabled;
|
|
static void fatal(const char *s){fprintf(stderr,"valve tail: %s\n",s);abort();}
|
|
void kd_eval_exit(double t,const double*y,const double*dy,const double*w,int r,NativePropertyCache*p,NativePipeCache*c,ModelJacobianWorkspace*m){(void)t;(void)y;(void)dy;(void)w;(void)r;(void)p;(void)c;(void)m;}
|
|
void kd_start(void){
|
|
unsigned a,b,c,d;if(!__get_cpuid(0x80000007,&a,&b,&c,&d) || !(d&(1u<<8)))fatal("invariant TSC required");
|
|
LARGE_INTEGER f;QueryPerformanceFrequency(&f);qpc_frequency=(uint64_t)f.QuadPart;
|
|
qpc_start=lp_tick();tsc_start=kd_clock();disabled=getenv("KD_DISABLED")!=NULL;
|
|
if(getenv("KD_MATRICES")){matrix_file=fopen("jacobians.bin","wb");if(!matrix_file)fatal("matrix file");setvbuf(matrix_file,NULL,_IOFBF,1024*1024);}
|
|
}
|
|
void kd_new_jac(void){uint64_t t=kd_clock();kd_memo.ready=0;reset_ticks+=kd_clock()-t;kd_jac++;}
|
|
void kd_before(KdRecord *r,double p,double T,double pd,double g,double rho){
|
|
double key[5]={p,T,pd,g,rho};memcpy(r->key,key,40);r->before=kd_env();
|
|
r->hit=lp_color>=0 && !disabled && kd_lookup(r->key,r->before,&r->cm,&r->vel);
|
|
r->jac=kd_jac;r->group=lp_color;
|
|
}
|
|
void kd_after(KdRecord *r,double cm,double vel,uint64_t elapsed,int executed){
|
|
uint64_t capture_start=lp_color<0?kd_clock():0;
|
|
r->after=kd_env();r->cm=cm;r->vel=vel;r->tail=elapsed;r->executed=executed;r->capture=0;r->pad=0;
|
|
if(lp_color<0){
|
|
memcpy(kd_memo.key,r->key,40);kd_memo.cm=cm;kd_memo.vel=vel;kd_memo.env=r->before;
|
|
kd_memo.ready=kd_finite(r->key) && isfinite(cm) && isfinite(vel) && kd_env_equal(r->before,r->after) && (r->before.cw&63)==63 && (r->before.mxcsr&0x1f80)==0x1f80;
|
|
r->capture=kd_clock()-capture_start;capture_ticks+=r->capture;
|
|
}
|
|
entries++;lookup_ticks+=r->lookup;if(lp_color<0)base_lookup_ticks+=r->lookup;else if(r->hit)hit_lookup_ticks+=r->lookup;else miss_lookup_ticks+=r->lookup;
|
|
hits+=r->hit;executions+=executed;tail_ticks+=elapsed;
|
|
#if KD_TRACE
|
|
if(count>=sizeof(records)/sizeof(*records)){fatal("record capacity");}
|
|
records[count++]=*r;
|
|
#endif
|
|
}
|
|
void kd_matrix(double t,const double*y,const double*m){
|
|
if(!matrix_file){return;}
|
|
int saved=errno;fenv_t env;fegetenv(&env);unsigned sse=_mm_getcsr();
|
|
fwrite(&t,8,1,matrix_file);fwrite(y,8,NSTATES,matrix_file);fwrite(m,8,NSTATES*NSTATES,matrix_file);
|
|
fesetenv(&env);_mm_setcsr(sse);errno=saved;
|
|
}
|
|
void kd_finish(void){
|
|
uint64_t t=kd_clock(),q=lp_tick();double frequency=(double)(t-tsc_start)/(q-qpc_start)*qpc_frequency;
|
|
uint64_t empty[10001];for(int i=0;i<10001;i++){uint64_t a=kd_clock();empty[i]=kd_clock()-a;}
|
|
FILE *f=fopen("tail-records.bin","wb");if(!f)fatal("records");fwrite(records,sizeof(KdRecord),count,f);fclose(f);
|
|
f=fopen("empty-clock.bin","wb");fwrite(empty,8,10001,f);fclose(f);
|
|
f=fopen("tail.json","wb");if(!f)fatal("summary");
|
|
fprintf(f,"{\"frequency\":%.9f,\"recordBytes\":%llu,\"memoBytes\":%llu,\"jacobians\":%llu,\"entries\":%llu,\"hits\":%llu,\"executions\":%llu,\"lookupTicks\":%llu,\"hitLookupTicks\":%llu,\"missLookupTicks\":%llu,\"baseLookupTicks\":%llu,\"captureTicks\":%llu,\"resetTicks\":%llu,\"tailTicks\":%llu,\"skipEnabled\":%d,\"disabled\":%d}\n",frequency,(unsigned long long)sizeof(KdRecord),(unsigned long long)sizeof(KdMemo),(unsigned long long)kd_jac,(unsigned long long)entries,(unsigned long long)hits,(unsigned long long)executions,(unsigned long long)lookup_ticks,(unsigned long long)hit_lookup_ticks,(unsigned long long)miss_lookup_ticks,(unsigned long long)base_lookup_ticks,(unsigned long long)capture_ticks,(unsigned long long)reset_ticks,(unsigned long long)tail_ticks,0,disabled);fclose(f);
|
|
if(matrix_file)fclose(matrix_file);
|
|
}
|