codexpast-exam-of-the-chemistry-a-course-of-the-university-of-cambridge2023paper-2-semiconductor-regimes.py
past-exam-of-the-chemistry-a-course-of-the-university-of-cambridge/2023/paper-2-semiconductor-regimes.py
"""Original chosen donor-ionization model; Python 3.14, numpy, matplotlib.
This is not a fit to a silicon sample. The PNG is written to the working directory.
"""
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
KB=8.617333262145179e-5
EG=1.10
EB=0.050
ND=1.0
def populations(T):
nc=100*ND*(T/300)**1.5
ni=nc*np.exp(-EG/(2*KB*T))
# Solve charge neutrality with partial donor ionization, n*p=ni**2.
lo=max(ni,np.finfo(float).tiny)
hi=ND+ni
for _ in range(100):
n=(lo+hi)/2
donor=ND/(1+2*n/nc*np.exp(EB/(KB*T)))
if n-ni*ni/n-donor>0:
hi=n
else:
lo=n
n=(lo+hi)/2
return n,ni*ni/n,ni,nc
Ts=np.linspace(12,1450,700)
vals=np.array([populations(float(t)) for t in Ts])
n,p,ni,nc=vals.T
n300,_,_,nc300=populations(300)
mu_n=EG+KB*300*np.log(n300/nc300)
fig,axes=plt.subplots(1,2,figsize=(10,4.9),layout='constrained',gridspec_kw={'width_ratios':[1,1.4]})
fig.patch.set_facecolor('white')
ax=axes[0]
for x0,label,fermi in [(0,'Intrinsic',EG/2),(1.7,'Donor-doped',mu_n)]:
ax.fill_between([x0,x0+1.1],[-.12,-.12],[0,0],color='#dce7f2')
ax.fill_between([x0,x0+1.1],[EG,EG],[EG+.15,EG+.15],color='#e9e2f2')
ax.plot([x0,x0+1.1],[0,0],color='#3e5e7c')
ax.plot([x0,x0+1.1],[EG,EG],color='#3e5e7c')
ax.plot([x0,x0+1.1],[fermi,fermi],color='#af4f2f',ls='--',lw=1.7)
ax.text(x0+.55,-.22,label,ha='center',fontsize=10)
ax.text(x0+.1,fermi-.06,r'$\mu$',color='#af4f2f',fontsize=12)
ax.plot([1.7,2.8],[EG-EB,EG-EB],color='#2c7a64',lw=1.5)
ax.text(2.84,EG-EB,r'$E_D$',va='center',fontsize=11,color='#2c7a64')
ax.text(-.2,EG+.03,r'$E_c$',fontsize=12)
ax.text(-.2,.015,r'$E_v$',fontsize=12)
ax.set(xlim=(-.3,3.2),ylim=(-.3,1.3),ylabel='Energy above valence edge (eV)',title='Chosen model at 300 K',xticks=[])
ax.spines[['top','right','bottom']].set_visible(False)
ax=axes[1]
ax.semilogy(Ts,n+p,color='#285f80',lw=2,label='Donor-doped')
ax.semilogy(Ts,2*ni,color='#7f4389',ls='--',lw=1.6,label='Intrinsic')
ax.axhline(1,color='0.65',ls=':',lw=1)
ax.axvline(260,color='0.8',lw=.8)
ax.axvline(860,color='0.8',lw=.8)
for x,text in [(120,'Freeze-out'),(560,'Extrinsic'),(1150,'Intrinsic')]:
ax.text(x,45,text,ha='center',fontsize=10)
ax.set(xlim=(0,1450),ylim=(1e-8,1e2),xlabel='Temperature (K)',ylabel=r'Conductivity / $(eN_Du)$',title='Fixed equal mobilities: conductivity tracks n+p')
ax.legend(loc='lower right',fontsize=10)
ax.grid(alpha=.18)
ax.spines[['top','right']].set_visible(False)
fig.savefig('paper-2-semiconductor-regimes.png',dpi=160,facecolor='white')
plt.close(fig)