Last active
June 8, 2026 14:52
-
-
Save raytroop/ba45a09dfa5abfe3560a355d5ba05d65 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| Inductive shunt peaking: bandwidth, peak frequency, and peaking gain | |
| as functions of m = R^2 * C / L. | |
| All frequencies are normalized to 1/RC (i.e. the plotted value is omega * RC). | |
| Smaller m <=> larger inductor L. | |
| Impedance: Z(s)/R = (1 + s L/R) / (1 + s R C + s^2 L C) | |
| With u = (omega * RC)^2 and m = R^2 C / L: | |
| |Z/R|^2 = (1 + u/m^2) / ((1 - u/m)^2 + u) | |
| """ | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| ONSET = 1 + np.sqrt(2) # m = 2.4142 : peaking switches on | |
| MAX_BW = np.sqrt(2) # m = 1.4142 : maximum bandwidth (approx) | |
| def bandwidth(m): | |
| """-3 dB bandwidth in units of 1/RC (i.e. omega_3dB * RC).""" | |
| B = 2 + 2 * m - m ** 2 | |
| u = (B + np.sqrt(B ** 2 + 4 * m ** 2)) / 2 | |
| return np.sqrt(u) | |
| def u_peak(m): | |
| """(omega_peak * RC)^2 at the magnitude peak; 0 where no peak exists.""" | |
| u = m * np.sqrt(1 + 2 * m) - m ** 2 | |
| return np.where((m < ONSET) & (u > 0), u, 0.0) | |
| def peak_freq(m): | |
| """Peak frequency in units of 1/RC.""" | |
| return np.sqrt(u_peak(m)) | |
| def peak_gain_db(m): | |
| """Peaking gain in dB (0 dB where the response is monotonic).""" | |
| u = u_peak(m) | |
| num = 1 + u / m ** 2 | |
| den = (1 - u / m) ** 2 + u | |
| with np.errstate(divide="ignore", invalid="ignore"): | |
| g = 10 * np.log10(num / den) | |
| return np.where(u > 0, g, 0.0) | |
| m = np.linspace(0.3, 5, 400) | |
| fig, ax1 = plt.subplots(figsize=(9, 5)) | |
| ax2 = ax1.twinx() | |
| l1, = ax1.plot(m, bandwidth(m), color="#0f6e56", lw=4, | |
| label="bandwidth (×1/RC)") | |
| l2, = ax1.plot(m, peak_freq(m), color="#d85a30", lw=4, ls="-", | |
| label="peak freq (×1/RC)") | |
| l3, = ax2.plot(m, peak_gain_db(m), color="#534ab7", lw=4, ls="-", | |
| label="peaking gain (dB)") | |
| for mv, txt in [(MAX_BW, "max BW (m≈1.41)"), (ONSET, "peaking onset (m≈2.41)")]: | |
| ax1.axvline(mv, color="0.6", ls="--", lw=1) | |
| ax1.text(mv - 0.04, 1.96, txt, rotation=90, va="top", ha="right", | |
| fontsize=9, color="0.4") | |
| ax1.set_xlabel("m = R²C / L (← larger L smaller L →)", fontsize=14) | |
| ax1.set_ylabel("frequency (×1/RC)", fontsize=14) | |
| ax2.set_ylabel("peaking gain (dB)", fontsize=14, color="#534ab7") | |
| ax2.tick_params(axis="y", colors="#534ab7") | |
| ax1.set_xlim(0.3, 5) | |
| ax1.set_ylim(0, 2) | |
| ax2.set_ylim(0, 12) | |
| ax1.set_title("Shunt peaking: bandwidth, peak frequency, peaking gain vs m", fontsize=16) | |
| ax1.grid(alpha=0.25) | |
| ax1.legend(handles=[l1, l2, l3], loc="upper right", framealpha=0.9) | |
| plt.tight_layout() | |
| plt.savefig("shunt_peaking_metrics.png", dpi=150) | |
| plt.show() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <h2 class="sr-only">Bandwidth, peak frequency, and peaking gain for inductive shunt peaking, all plotted against m equals R squared C over L. Frequencies are in units of 1 over RC. Bandwidth and peak frequency are humps peaking near m of 1.3 to 1.4; peaking gain decreases monotonically and reaches zero at m equals 2.41.</h2> | |
| <div style="display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 10px; font-size: 12px; color: var(--color-text-secondary);"> | |
| <span style="display:flex;align-items:center;gap:6px;"><span style="width:18px;height:0;border-top:2px solid #0f6e56;"></span>bandwidth (×1/RC) (left)</span> | |
| <span style="display:flex;align-items:center;gap:6px;"><span style="width:18px;height:0;border-top:2px dashed #d85a30;"></span>peak freq (×1/RC) (left)</span> | |
| <span style="display:flex;align-items:center;gap:6px;"><span style="width:18px;height:0;border-top:2px dotted #534ab7;"></span>peaking gain dB (right)</span> | |
| </div> | |
| <div style="position: relative; width: 100%; height: 340px;"> | |
| <canvas id="three2" role="img" aria-label="Three curves versus m equals R squared C over L from 0.3 to 5. Bandwidth, in units of 1 over RC, rises to about 1.85 near m of 1.4 then falls toward 1. Peak frequency, in units of 1 over RC, rises to about 0.88 near m of 1.3 then drops to zero at m of 2.41. Peaking gain falls monotonically from over 11 dB at small m to zero at m of 2.41 and stays zero.">Bandwidth and peak frequency (in units of 1/RC) are humps peaking near m of 1.3 to 1.4; peaking gain decreases monotonically to zero at m of 2.41.</canvas> | |
| </div> | |
| <p style="font-size:12px;color:var(--color-text-tertiary);margin:6px 0 0;text-align:center;">← larger L · m = R²C/L · smaller L → | dashed lines: m = 1.41 (max BW), m = 2.41 (peaking onset)</p> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js"></script> | |
| <script> | |
| (function(){ | |
| var ONSET = 2.414214; | |
| function bw(m){ var B=2+2*m-m*m; var u=(B+Math.sqrt(B*B+4*m*m))/2; return Math.sqrt(u); } | |
| function up(m){ if(m>=ONSET) return 0; var u=m*Math.sqrt(1+2*m)-m*m; return u>0?u:0; } | |
| function pf(m){ return Math.sqrt(up(m)); } | |
| function pg(m){ var u=up(m); if(u<=0) return 0; var num=1+u/(m*m); var den=Math.pow(1-u/m,2)+u; return 10*Math.log10(num/den); } | |
| var dBW=[], dPF=[], dPG=[]; | |
| for(var i=0;i<=200;i++){ | |
| var m=0.3+(i/200)*(5-0.3); | |
| dBW.push({x:m,y:bw(m)}); dPF.push({x:m,y:pf(m)}); dPG.push({x:m,y:pg(m)}); | |
| } | |
| var markers={ id:'mk', afterDraw:function(c){ | |
| var ctx=c.ctx, xs=c.scales.x, a=c.chartArea; | |
| [1.41,2.41].forEach(function(v){ | |
| var px=xs.getPixelForValue(v); ctx.save(); | |
| ctx.strokeStyle='rgba(136,135,128,0.55)'; ctx.setLineDash([4,3]); ctx.lineWidth=1; | |
| ctx.beginPath(); ctx.moveTo(px,a.top); ctx.lineTo(px,a.bottom); ctx.stroke(); ctx.restore(); | |
| }); | |
| }}; | |
| new Chart(document.getElementById('three2'), { | |
| type:'line', | |
| data:{ datasets:[ | |
| { label:'bandwidth', data:dBW, yAxisID:'y', borderColor:'#0f6e56', borderWidth:2.4, pointRadius:0, tension:0.25 }, | |
| { label:'peakfreq', data:dPF, yAxisID:'y', borderColor:'#d85a30', borderWidth:2.2, borderDash:[7,4], pointRadius:0, tension:0.25 }, | |
| { label:'peakgain', data:dPG, yAxisID:'y1', borderColor:'#534ab7', borderWidth:2.2, borderDash:[2,3], pointRadius:0, tension:0.25 } | |
| ]}, | |
| plugins:[markers], | |
| options:{ responsive:true, maintainAspectRatio:false, | |
| interaction:{ mode:'index', intersect:false }, | |
| plugins:{ legend:{display:false}, | |
| tooltip:{ callbacks:{ title:function(it){ return 'm = '+(+it[0].parsed.x).toFixed(2); }, | |
| label:function(it){ var n=it.datasetIndex; var v=it.parsed.y; | |
| return n===0?('bandwidth: '+v.toFixed(2)+' ×1/RC'):n===1?('peak freq: '+v.toFixed(2)+' ×1/RC'):('peaking gain: '+v.toFixed(2)+' dB'); } } } }, | |
| scales:{ | |
| x:{ type:'linear', min:0.3, max:5, | |
| title:{display:true, text:'m = R²C / L', color:'#888780', font:{size:12}}, | |
| ticks:{ color:'#888780', font:{size:11} }, grid:{ color:'rgba(136,135,128,0.15)' } }, | |
| y:{ position:'left', min:0, max:2, | |
| title:{display:true, text:'frequency (×1/RC)', color:'#888780', font:{size:12}}, | |
| ticks:{ color:'#888780', font:{size:11} }, grid:{ color:'rgba(136,135,128,0.15)' } }, | |
| y1:{ position:'right', min:0, max:12, | |
| title:{display:true, text:'peaking gain (dB)', color:'#534ab7', font:{size:12}}, | |
| ticks:{ color:'#534ab7', font:{size:11} }, grid:{ drawOnChartArea:false } } | |
| } | |
| } | |
| }); | |
| })(); | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment