修复循环信号与事件采样并接入 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:
ljz committed 2026-09-17 23:50:13 +08:00
1 parent 1aac220084
commit 7611f13208
85 files changed
+11358 -33

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
/* 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);
}