← Commit history
docs/cooling-volume/chipset40-section.png
⋯ 1 unchanged line ⋯
docs/cooling-volume/pi5-section.png
⋯ 1 unchanged line ⋯
docs/cooling-volume/power-comparison.png
⋯ 1 unchanged line ⋯
docs/cooling-volume/preferred50-section.png
⋯ 1 unchanged line ⋯
docs/cooling-volume/viewer.html+4−3
@@ -1,7 +1,7 @@ <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Electronic load — 3D thermal comparison</title><style>-html,body{margin:0;height:100%;background:#14212c;color:#e4edf4;font:15px system-ui}header{padding:12px 18px;background:#20303e}select,button{font:inherit;background:#30495b;color:white;border:1px solid #76929f;border-radius:5px;padding:5px}small{display:block;color:#c9d5de;margin-top:6px}#host{height:calc(100vh - 185px)}a{color:#7bd7ce}label{margin-left:12px}.legend{display:inline-block;width:150px;height:10px;background:linear-gradient(90deg,cyan,#ffff80,red)}#numbers{font-size:17px;margin-top:8px;color:#9be5d9}#warning{color:#ffd18a}</style><script>window.process={env:{NODE_ENV:'production'}};window.global=window;</script></head><body><header><b>Q1 → interface → heatsink fins</b> <select id="choice"><option value="preferred50">50 mm low-profile</option><option value="chipset40">40 mm tall-fin</option><option value="pi5">Pi 5 blower concept</option></select> <select id="air"><option value="100">Fan-on assumption · h=100</option><option value="5">Fan-off assumption · h=5</option></select><label><input id="sink" type="checkbox" checked>Heatsink</label><label><input id="layers" type="checkbox" checked>Interface layers</label> <button id="home">Home</button>+html,body{margin:0;height:100%;background:#14212c;color:#e4edf4;font:15px system-ui}body{display:flex;flex-direction:column}header{padding:12px 18px;background:#20303e}select,button{font:inherit;background:#30495b;color:white;border:1px solid #76929f;border-radius:5px;padding:5px}small{display:block;color:#c9d5de;margin-top:6px}#host{flex:1;min-height:0}a{color:#7bd7ce}label{margin-left:12px}.legend{display:inline-block;width:150px;height:10px;background:linear-gradient(90deg,cyan,#ffff80,red)}#numbers{font-size:17px;margin-top:8px;color:#9be5d9}#warning{color:#ffd18a}</style><script>window.process={env:{NODE_ENV:'production'}};window.global=window;</script></head><body><header><b>Q1 → interface → heatsink fins</b> <select id="choice"><option value="preferred50">50 mm low-profile</option><option value="chipset40">40 mm tall-fin</option><option value="pi5">Pi 5 blower concept</option></select> <select id="air"><option value="100">Fan-on assumption · h=100</option><option value="5">Fan-off assumption · h=5</option></select><label><input id="sink" type="checkbox" checked>Heatsink</label><label><input id="layers" type="checkbox" checked>Interface layers</label> <button id="home">Home</button> <button id="section">Heat-flow section</button> <small>Steady 3D solid-conduction simulation • 5.5 W Q1 heat input • 40°C ambient • approximate geometry • h in W/m²K, not measured fan performance</small>-<div id="numbers">Loading…</div><small><span class="legend"></span> <span id="legendText">40–150°C</span> <button id="scale">Magnify 40–60°C</button> · <a href="https://wiki.adom.inc/adom/adom-custom-electronic-load/files/docs/cooling-volume/README.md">Results, heat-flow sections and limitations</a></small><small id="warning">Calculated limits are conditional, not board power ratings. Fan-off views assume shutdown failed; they are not an authorized operating state.</small><small id="status">Loading canonical Adom viewer…</small></header><main id="host"></main>+<div id="numbers">Loading…</div><small><span class="legend"></span> <span id="legendText">40–150°C</span> <button id="scale">Magnify 40–60°C</button> · <a href="https://wiki.adom.inc/adom/adom-custom-electronic-load/files/docs/cooling-volume/README.md">Results, heat-flow sections and limitations</a></small><small id="warning">Calculated limits are conditional, not board power ratings. Fan-off views assume shutdown failed; they are not an authorized operating state.</small><small id="status">Loading canonical Adom viewer…</small></header><main id="host"></main><img id="sectionImage" style="display:none;flex:1;min-height:0;object-fit:contain;max-width:100%" alt="Solved h=100 heat-flow cross-section"> <script type="module"> const $=id=>document.getElementById(id),status=$('status'); try {@@ -10,7 +10,8 @@ const v=window.Adom3DViewerBabylon9.init($('host'),{zUp:true,showViewCube:true}) const data=await(await fetch('./summary.json')).json();let loading=false,magnify=false; function recolor(){for(const m of v.getScene().meshes){const a=m.getVerticesData?.('color');if(!a)continue;if(!m.thermalOriginal)m.thermalOriginal=Array.from(a);const src=m.thermalOriginal,out=src.slice(),stride=src.length/m.getTotalVertices();for(let i=0;i<src.length;i+=stride){const temp=40+110*(1-src[i+2]),t=Math.max(0,Math.min(1,(temp-40)/(magnify?20:110)));out[i]=Math.min(1,2*t);out[i+1]=Math.min(1,2*(1-t));out[i+2]=1-t;}m.setVerticesData('color',out,false,stride);} $('legendText').textContent=magnify?'40–60°C (above 60°C saturated)':'40–150°C';$('scale').textContent=magnify?'Show 40–150°C':'Magnify 40–60°C';} function visibility(){for(const m of v.getScene().meshes){if(m.name==='heatsink')m.setEnabled($('sink').checked);if(['AlN','spreader'].includes(m.name))m.setEnabled($('layers').checked);}}-window.selectThermal=async function(id,h){if(loading)return {busy:true};loading=true;$('choice').disabled=$('air').disabled=true;$('choice').value=id;$('air').value=String(h);status.textContent='Loading solved surfaces…';try{v.clearScene();await v.loadModel(new URL(id+'-h'+h+'.glb',location.href).href);v.frameModel();recolor();visibility();const r=data.results.find(r=>r.id===id&&r.h===Number(h)&&r.pitchMm===1);$('numbers').textContent=`Case ${r.caseC.toFixed(1)}°C · estimated junction ${r.junctionC.toFixed(1)}°C · sink ${r.sinkMinC.toFixed(1)}–${r.sinkMaxC.toFixed(1)}°C · conditional ceiling ${r.conditionalLoadW.toFixed(2)} W`;status.textContent='Ready · drag to orbit; hide heatsink and interface layers to inspect Q1. Cell colours come from the solve.';window.thermalState={id,h:Number(h),...r};return window.thermalState;}finally{loading=false;$('choice').disabled=$('air').disabled=false;}};+window.selectThermal=async function(id,h){if(loading)return {busy:true};loading=true;$('choice').disabled=$('air').disabled=true;$('choice').value=id;$('air').value=String(h);status.textContent='Loading solved surfaces…';$('host').style.display='block';$('sectionImage').style.display='none';$('section').textContent='Heat-flow section';$('section').disabled=Number(h)!==100;try{v.clearScene();await v.loadModel(new URL(id+'-h'+h+'.glb',location.href).href);v.frameModel();const camera=v.getCamera();camera.alpha=0.8;camera.beta=0.55;camera.radius*=1.15;recolor();visibility();const r=data.results.find(r=>r.id===id&&r.h===Number(h)&&r.pitchMm===1);$('numbers').textContent=`Case ${r.caseC.toFixed(1)}°C · estimated junction ${r.junctionC.toFixed(1)}°C · sink ${r.sinkMinC.toFixed(1)}–${r.sinkMaxC.toFixed(1)}°C · conditional ceiling ${r.conditionalLoadW.toFixed(2)} W`;status.textContent='Ready · drag to orbit; hide heatsink and interface layers to inspect Q1. Cell colours come from the solve.';window.thermalState={id,h:Number(h),...r};return window.thermalState;}finally{loading=false;$('choice').disabled=$('air').disabled=false;}};+$('section').onclick=()=>{const show=$('sectionImage').style.display==='none';$('sectionImage').src='./'+$('choice').value+'-section.png';$('sectionImage').style.display=show?'block':'none';$('host').style.display=show?'none':'block';$('section').textContent=show?'Return to 3D':'Heat-flow section';}; $('choice').onchange=()=>selectThermal($('choice').value,$('air').value);$('air').onchange=()=>selectThermal($('choice').value,$('air').value);$('sink').onchange=visibility;$('layers').onchange=visibility;$('home').onclick=()=>v.goHome();$('scale').onclick=()=>{magnify=!magnify;recolor();};await selectThermal('chipset40',100); }catch(e){status.textContent='Viewer error: '+e.message;window.viewerError=e.message;} </script></body></html>
tools/plot_volume_study.py+2−2
@@ -10,7 +10,7 @@ plt.style.use('dark_background') fig,ax=plt.subplots(figsize=(9,4.6)) for name,title in [('preferred50','50 mm low-profile'),('chipset40','40 mm tall-fin'),('pi5','Pi 5 blower concept')]:  r=[x for x in s if x['id']==name and x['pitchMm']==2];ax.plot([x['h'] for x in r],[x['conditionalLoadW'] for x in r],'-o',label=title)-ax.axhline(5,color='white',linestyle=':',label='Existing 5 W target');ax.set(xlabel='Assumed convection h (W/m²K); not measured fan airflow',ylabel='Conditional load ceiling (W)',title='3D conduction model • 40°C ambient / retained 55°C screen');ax.legend();ax.grid(alpha=.2);fig.tight_layout();fig.savefig(O/'power-comparison.png',dpi=170);plt.close(fig)+ax.axhline(5,color='white',linestyle=':',label='Existing 5 W target');ax.set(xlabel='Assumed convection h (W/m²K); not measured fan airflow',ylabel='Conditional load ceiling (W)',title='3D conduction model • 40°C ambient / retained 55°C screen');ax.legend();ax.grid(alpha=.2);fig.tight_layout();fig.savefig(O/'power-comparison.png',dpi=170,bbox_inches='tight');plt.close(fig) for name in ['preferred50','chipset40','pi5']:  p=json.loads((A/f'{name}-h100-p1/thermal3d.json').read_text());cells=p['cells'];bb=np.array([c['boundsMm'] for c in cells]);cent=(bb[:,:3]+bb[:,3:])/2;t=np.array([c['temperatureC'] for c in cells]);q1=next(c['boundsMm'] for c in cells if c['body']==0);ymid=(min(b[1] for b,c in zip(bb,cells) if c['body']==0)+max(b[4] for b,c in zip(bb,cells) if c['body']==0))/2  yvals=sorted(set(cent[:,1]));ys=min(yvals,key=lambda x:abs(x-ymid));mask=np.isclose(cent[:,1],ys);indices=np.where(mask)[0]@@ -23,4 +23,4 @@ for name in ['preferred50','chipset40','pi5']:  pc2=PolyCollection(verts,array=np.log10(np.maximum(mag[indices],1)),cmap='magma',edgecolors='none');axes[1].add_collection(pc2);axes[1].autoscale();axes[1].set_aspect('equal');fig.colorbar(pc2,ax=axes[1],label='log₁₀ heat flux magnitude (W/m²)')  sample=indices[::max(1,len(indices)//90)];norm=np.maximum(np.linalg.norm(flux[sample][:,[0,2]],axis=1),1e-9);axes[1].quiver(cent[sample,0],cent[sample,2],flux[sample,0]/norm,flux[sample,2]/norm,color='#83fff1',scale=25,width=.004);axes[1].set_title('Solved heat flow • arrows show direction')  for ax in axes:ax.set(xlabel='X (mm)',ylabel='Z (mm)')- fig.suptitle(f'{name} • 5.5 W Q1 • assumed h=100 • section Y={ys:.2f} mm\nEquivalent Q1 case at bottom; no die-level heat-density claim',fontsize=11);fig.tight_layout();fig.savefig(O/f'{name}-section.png',dpi=170);plt.close(fig)+ fig.suptitle(f'{name} • 5.5 W Q1 • assumed h=100 • section Y={ys:.2f} mm\nEquivalent Q1 case at bottom; no die-level heat-density claim',fontsize=11);fig.tight_layout();fig.savefig(O/f'{name}-section.png',dpi=170,bbox_inches='tight');plt.close(fig)