export const MODEL_VERSION='1.0.0',DEFAULTS=Object.freeze({a_cm:1.05,b_cm:6.94,voltage:10,fraction:.5,angle:0}); export function validateParameters(p){for(const[k,a,b]of[['a_cm',.5,2],['b_cm',5,10],['voltage',5,15],['fraction',0,1],['angle',0,360]])if(!Number.isFinite(p[k])||p[k]b)throw new RangeError(k);if(p.a_cm>=p.b_cm)throw new RangeError('a < b');return{...p};} export function potentialAt(p,r){validateParameters(p);if(rp.b_cm*.01+1e-12)throw new RangeError('radius');return p.voltage*Math.log(p.b_cm*.01/r)/Math.log(p.b_cm/p.a_cm);} export function response(p){validateParameters(p);const radius_cm=p.a_cm+(p.b_cm-p.a_cm)*p.fraction;return{radius_cm,potential:potentialAt(p,radius_cm*.01),field:p.voltage/(radius_cm*.01*Math.log(p.b_cm/p.a_cm)),angle:p.angle};} export function plots(p){const qs=Array.from({length:201},(_,i)=>i/200);return['potential','field'].map(key=>({caption:key==='potential'?'径向电势与探针位置':'径向电场与探针位置',xLabel:'半径 r / cm',yLabel:key==='potential'?'电势 φ / V':'径向场 Er / (V/m)',curves:[{points:qs.map(fraction=>{const r=response({...p,fraction});return[r.radius_cm,r[key]];})}],selected:[response(p).radius_cm,response(p)[key]]}));} export function analyzeRecords(rows,p){const s=rows.filter(r=>['a_cm','b_cm','voltage'].every(k=>r.parameters[k]===p[k]));if(s.length<3)return'固定几何和电压,沿半径取至少三个位置,拟合电势对 ln(r/1cm) 的关系。';const xs=s.map(r=>Math.log(r.readings.radius_cm)),ys=s.map(r=>r.readings.potential),xm=xs.reduce((a,b)=>a+b,0)/xs.length,ym=ys.reduce((a,b)=>a+b,0)/ys.length,den=xs.reduce((a,b)=>a+(b-xm)**2,0);if(!den)return'需要不同半径的记录。';const slope=xs.reduce((a,x,i)=>a+(x-xm)*(ys[i]-ym),0)/den;return'电势对 ln(r/1cm) 斜率 '+slope.toFixed(8)+' V;理论斜率 '+(-p.voltage/Math.log(p.b_cm/p.a_cm)).toFixed(8)+' V。';}