Path: blob/main/latex-templates/templates/materials-science/diffusion.tex
51 views
unlisted
\documentclass[11pt,a4paper]{article}12% Document Setup3\usepackage[utf8]{inputenc}4\usepackage[T1]{fontenc}5\usepackage{lmodern}6\usepackage[margin=1in]{geometry}7\usepackage{amsmath,amssymb}8\usepackage{siunitx}9\usepackage{booktabs}10\usepackage{float}11\usepackage{caption}12\usepackage{subcaption}13\usepackage{hyperref}1415% PythonTeX Setup16\usepackage[makestderr]{pythontex}1718\title{Diffusion in Materials Science: Computational Analysis}19\author{Materials Engineering Laboratory}20\date{\today}2122\begin{document}23\maketitle2425\begin{abstract}26This report presents computational analysis of diffusion phenomena in materials science. We examine Fick's first and second laws, analytical solutions including error function profiles, numerical simulation of concentration evolution, and the Kirkendall effect in binary diffusion couples. Python-based computations provide quantitative analysis with dynamic visualization.27\end{abstract}2829\tableofcontents30\newpage3132\section{Introduction to Diffusion}3334Diffusion is the net movement of atoms or molecules from regions of high concentration to regions of low concentration. This fundamental transport phenomenon governs numerous materials processes including:35\begin{itemize}36\item Heat treatment and phase transformations37\item Oxidation and corrosion mechanisms38\item Semiconductor doping and device fabrication39\item Sintering and powder metallurgy40\end{itemize}4142% Initialize Python environment43\begin{pycode}44import numpy as np45import matplotlib.pyplot as plt46from scipy.special import erf, erfc47from scipy.integrate import odeint48from mpl_toolkits.mplot3d import Axes3D4950plt.rcParams['figure.figsize'] = (8, 5)51plt.rcParams['font.size'] = 1052plt.rcParams['text.usetex'] = True5354# Physical constants and parameters55k_B = 8.617e-5 # Boltzmann constant (eV/K)5657def save_fig(filename):58plt.savefig(filename, dpi=150, bbox_inches='tight')59plt.close()60\end{pycode}6162\section{Fick's Laws of Diffusion}6364\subsection{Fick's First Law}6566Fick's first law describes steady-state diffusion where the flux is proportional to the concentration gradient:67\begin{equation}68J = -D \frac{\partial C}{\partial x}69\end{equation}70where $J$ is the diffusion flux (\si{\mol\per\square\meter\per\second}), $D$ is the diffusion coefficient (\si{\square\meter\per\second}), and $C$ is concentration.7172\begin{pycode}73# Steady-state diffusion through a membrane74D = 1e-10 # m^2/s (typical for metals)75L = 0.01 # membrane thickness (m)76C1 = 100 # concentration at x=0 (mol/m^3)77C2 = 10 # concentration at x=L (mol/m^3)7879# Calculate steady-state flux80J_ss = -D * (C2 - C1) / L8182# Position array83x = np.linspace(0, L*1000, 100) # convert to mm84C_ss = C1 + (C2 - C1) * x / (L*1000)8586fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))8788# Concentration profile89ax1.plot(x, C_ss, 'b-', linewidth=2)90ax1.set_xlabel('Position (mm)')91ax1.set_ylabel('Concentration (mol/m$^3$)')92ax1.set_title("Steady-State Concentration Profile")93ax1.grid(True, alpha=0.3)94ax1.fill_between(x, 0, C_ss, alpha=0.3)9596# Flux visualization97x_flux = np.linspace(0, L*1000, 10)98ax2.quiver(x_flux, np.ones_like(x_flux)*50, np.ones_like(x_flux)*2,99np.zeros_like(x_flux), scale=30, color='red', width=0.01)100ax2.set_xlim(0, L*1000)101ax2.set_ylim(0, 100)102ax2.set_xlabel('Position (mm)')103ax2.set_ylabel('Concentration (mol/m$^3$)')104ax2.set_title(f'Diffusion Flux: J = {J_ss:.2e} mol/m$^2$/s')105ax2.grid(True, alpha=0.3)106107plt.tight_layout()108save_fig('ficks_first_law.pdf')109\end{pycode}110111\begin{figure}[H]112\centering113\includegraphics[width=\textwidth]{ficks_first_law.pdf}114\caption{Fick's first law: (a) steady-state concentration profile, (b) constant flux through membrane.}115\end{figure}116117The calculated steady-state flux is $J = \py{f"{J_ss:.3e}"}$ \si{\mol\per\square\meter\per\second}.118119\subsection{Fick's Second Law}120121For non-steady-state diffusion, Fick's second law describes the time evolution of concentration:122\begin{equation}123\frac{\partial C}{\partial t} = D \frac{\partial^2 C}{\partial x^2}124\end{equation}125126\section{Analytical Solutions}127128\subsection{Error Function Solutions}129130For semi-infinite solid with constant surface concentration:131\begin{equation}132\frac{C(x,t) - C_0}{C_s - C_0} = 1 - \text{erf}\left(\frac{x}{2\sqrt{Dt}}\right)133\end{equation}134135\begin{pycode}136# Error function solution parameters137D = 5e-11 # m^2/s138C0 = 0 # Initial concentration139Cs = 1 # Surface concentration (normalized)140141# Time points142times = [1, 10, 100, 1000] # hours143colors = plt.cm.viridis(np.linspace(0, 1, len(times)))144145x = np.linspace(0, 5e-3, 200) # depth in meters146147fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))148149# Concentration profiles at different times150for t_hr, color in zip(times, colors):151t = t_hr * 3600 # convert to seconds152C = Cs * erfc(x / (2 * np.sqrt(D * t)))153ax1.plot(x*1000, C, color=color, linewidth=2, label=f't = {t_hr} hr')154155ax1.set_xlabel('Depth (mm)')156ax1.set_ylabel('Normalized Concentration $C/C_s$')157ax1.set_title('Concentration Profiles (Error Function Solution)')158ax1.legend()159ax1.grid(True, alpha=0.3)160161# Diffusion penetration depth vs time162t_range = np.linspace(1, 1000, 100) * 3600163penetration = 2 * np.sqrt(D * t_range)164165ax2.plot(t_range/3600, penetration*1000, 'b-', linewidth=2)166ax2.set_xlabel('Time (hours)')167ax2.set_ylabel('Penetration Depth $2\\sqrt{Dt}$ (mm)')168ax2.set_title('Diffusion Penetration Depth')169ax2.grid(True, alpha=0.3)170171plt.tight_layout()172save_fig('error_function_solution.pdf')173\end{pycode}174175\begin{figure}[H]176\centering177\includegraphics[width=\textwidth]{error_function_solution.pdf}178\caption{Error function solution showing concentration profiles at different times and penetration depth evolution.}179\end{figure}180181\subsection{Thin-Film (Gaussian) Solution}182183For an instantaneous planar source at $x=0$:184\begin{equation}185C(x,t) = \frac{M}{\sqrt{4\pi Dt}} \exp\left(-\frac{x^2}{4Dt}\right)186\end{equation}187188\begin{pycode}189# Gaussian solution parameters190D = 1e-10 # m^2/s191M = 1e-6 # surface mass (mol/m^2)192193times = [10, 100, 1000, 10000] # seconds194x = np.linspace(-2e-3, 2e-3, 300)195196fig, ax = plt.subplots(figsize=(9, 6))197colors = plt.cm.plasma(np.linspace(0.2, 0.9, len(times)))198199for t, color in zip(times, colors):200C = (M / np.sqrt(4 * np.pi * D * t)) * np.exp(-x**2 / (4 * D * t))201ax.plot(x*1000, C*1e6, color=color, linewidth=2, label=f't = {t} s')202203ax.set_xlabel('Position (mm)')204ax.set_ylabel('Concentration ($\\mu$mol/m$^3$)')205ax.set_title('Gaussian Diffusion from Thin-Film Source')206ax.legend()207ax.grid(True, alpha=0.3)208209save_fig('gaussian_solution.pdf')210\end{pycode}211212\begin{figure}[H]213\centering214\includegraphics[width=0.8\textwidth]{gaussian_solution.pdf}215\caption{Gaussian diffusion profile evolution from an instantaneous thin-film source.}216\end{figure}217218\section{Temperature Dependence of Diffusion}219220The diffusion coefficient follows the Arrhenius relationship:221\begin{equation}222D = D_0 \exp\left(-\frac{Q}{RT}\right)223\end{equation}224225\begin{pycode}226# Arrhenius parameters for various systems227systems = {228'C in Fe-$\\alpha$': {'D0': 6.2e-7, 'Q': 80},229'C in Fe-$\\gamma$': {'D0': 2.3e-5, 'Q': 148},230'Fe in Fe-$\\alpha$': {'D0': 2.0e-4, 'Q': 251},231'Cu in Cu': {'D0': 7.8e-5, 'Q': 211},232'Al in Al': {'D0': 1.7e-4, 'Q': 142}233}234235R = 8.314 # J/(mol*K)236T = np.linspace(300, 1400, 200)237238fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))239240# Arrhenius plot241for name, params in systems.items():242D = params['D0'] * np.exp(-params['Q']*1000 / (R * T))243ax1.semilogy(1000/T, D, linewidth=2, label=name)244245ax1.set_xlabel('1000/T (K$^{-1}$)')246ax1.set_ylabel('D (m$^2$/s)')247ax1.set_title('Arrhenius Plot of Diffusion Coefficients')248ax1.legend(fontsize=8)249ax1.grid(True, alpha=0.3)250251# Q vs D0 comparison252D0_vals = [p['D0'] for p in systems.values()]253Q_vals = [p['Q'] for p in systems.values()]254names = list(systems.keys())255256ax2.scatter(D0_vals, Q_vals, s=100, c=range(len(systems)), cmap='viridis')257for i, name in enumerate(names):258ax2.annotate(name.replace('$\\alpha$', 'a').replace('$\\gamma$', 'g'),259(D0_vals[i], Q_vals[i]), xytext=(5, 5),260textcoords='offset points', fontsize=8)261ax2.set_xscale('log')262ax2.set_xlabel('$D_0$ (m$^2$/s)')263ax2.set_ylabel('Q (kJ/mol)')264ax2.set_title('Activation Energy vs Pre-exponential Factor')265ax2.grid(True, alpha=0.3)266267plt.tight_layout()268save_fig('arrhenius_diffusion.pdf')269270# Calculate specific values for table271T_test = 1000 # K272D_table = []273for name, params in systems.items():274D = params['D0'] * np.exp(-params['Q']*1000 / (R * T_test))275D_table.append((name.replace('$\\alpha$', 'alpha').replace('$\\gamma$', 'gamma'),276params['D0'], params['Q'], D))277\end{pycode}278279\begin{figure}[H]280\centering281\includegraphics[width=\textwidth]{arrhenius_diffusion.pdf}282\caption{Temperature dependence of diffusion: Arrhenius behavior for various material systems.}283\end{figure}284285\begin{table}[H]286\centering287\caption{Diffusion Parameters for Various Systems}288\begin{tabular}{lccc}289\toprule290System & $D_0$ (\si{\square\meter\per\second}) & Q (\si{\kilo\joule\per\mol}) & D at 1000 K \\291\midrule292\py{'C in Fe-alpha'} & \py{f"{6.2e-7:.2e}"} & 80 & \py{f"{6.2e-7 * np.exp(-80000/(8.314*1000)):.2e}"} \\293\py{'C in Fe-gamma'} & \py{f"{2.3e-5:.2e}"} & 148 & \py{f"{2.3e-5 * np.exp(-148000/(8.314*1000)):.2e}"} \\294\py{'Fe in Fe-alpha'} & \py{f"{2.0e-4:.2e}"} & 251 & \py{f"{2.0e-4 * np.exp(-251000/(8.314*1000)):.2e}"} \\295\py{'Cu in Cu'} & \py{f"{7.8e-5:.2e}"} & 211 & \py{f"{7.8e-5 * np.exp(-211000/(8.314*1000)):.2e}"} \\296\py{'Al in Al'} & \py{f"{1.7e-4:.2e}"} & 142 & \py{f"{1.7e-4 * np.exp(-142000/(8.314*1000)):.2e}"} \\297\bottomrule298\end{tabular}299\end{table}300301\section{Numerical Simulation of Diffusion}302303\subsection{Finite Difference Method}304305We solve Fick's second law numerically using explicit finite differences:306\begin{equation}307C_i^{n+1} = C_i^n + \frac{D \Delta t}{(\Delta x)^2}\left(C_{i+1}^n - 2C_i^n + C_{i-1}^n\right)308\end{equation}309310\begin{pycode}311# Numerical diffusion simulation312D = 1e-10 # m^2/s313L = 0.01 # domain length (m)314nx = 100 # spatial points315dx = L / (nx - 1)316dt = 0.5 * dx**2 / D # stability criterion317318# Initial condition: step function319x = np.linspace(0, L, nx)320C = np.zeros(nx)321C[x < L/2] = 1.0322323# Store profiles at different times324t_save = [0, 1000, 5000, 20000]325profiles = {0: C.copy()}326327# Time evolution328t = 0329for step in range(20001):330C_new = C.copy()331for i in range(1, nx-1):332C_new[i] = C[i] + D * dt / dx**2 * (C[i+1] - 2*C[i] + C[i-1])333C = C_new334t += dt335if step in t_save[1:]:336profiles[step] = C.copy()337338# Plot results339fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))340341colors = plt.cm.viridis(np.linspace(0, 1, len(t_save)))342for step, color in zip(t_save, colors):343t_actual = step * dt344ax1.plot(x*1000, profiles[step], color=color, linewidth=2,345label=f't = {t_actual:.0f} s')346347ax1.set_xlabel('Position (mm)')348ax1.set_ylabel('Concentration (normalized)')349ax1.set_title('Numerical Diffusion Simulation')350ax1.legend()351ax1.grid(True, alpha=0.3)352353# Conservation of mass check354mass = [np.trapz(profiles[step], x) for step in t_save]355steps_plot = [s * dt for s in t_save]356ax2.plot(steps_plot, mass, 'bo-', linewidth=2, markersize=8)357ax2.axhline(mass[0], color='r', linestyle='--', label='Initial mass')358ax2.set_xlabel('Time (s)')359ax2.set_ylabel('Total Mass (mol/m$^2$)')360ax2.set_title('Mass Conservation Check')361ax2.legend()362ax2.grid(True, alpha=0.3)363364plt.tight_layout()365save_fig('numerical_diffusion.pdf')366367# Stability parameter368Fo = D * dt / dx**2369\end{pycode}370371\begin{figure}[H]372\centering373\includegraphics[width=\textwidth]{numerical_diffusion.pdf}374\caption{Finite difference solution of Fick's second law with mass conservation verification.}375\end{figure}376377The Fourier number (stability criterion) is $Fo = \py{f"{Fo:.3f}"}$, which satisfies $Fo \leq 0.5$ for stability.378379\section{Kirkendall Effect}380381The Kirkendall effect demonstrates unequal diffusion rates in binary diffusion couples, resulting in marker movement and void formation.382383\begin{pycode}384# Kirkendall effect simulation385# Binary diffusion couple: A-B system386L = 0.02 # 20 mm total387nx = 200388x = np.linspace(0, L, nx)389dx = L / (nx - 1)390391# Diffusion coefficients (A diffuses faster than B)392D_A = 2e-10 # m^2/s393D_B = 5e-11 # m^2/s394395# Initial concentrations396C_A = np.zeros(nx)397C_B = np.zeros(nx)398C_A[x < L/2] = 1.0 # Pure A on left399C_B[x >= L/2] = 1.0 # Pure B on right400401# Time stepping402dt = 0.25 * dx**2 / max(D_A, D_B)403n_steps = 10000404405# Track marker position (initially at interface)406marker_pos = L/2407408# Store results409times = [0, 2500, 5000, 10000]410results = {0: {'C_A': C_A.copy(), 'C_B': C_B.copy(), 'marker': marker_pos}}411412for step in range(1, n_steps+1):413# Update A414C_A_new = C_A.copy()415for i in range(1, nx-1):416C_A_new[i] = C_A[i] + D_A * dt / dx**2 * (C_A[i+1] - 2*C_A[i] + C_A[i-1])417418# Update B419C_B_new = C_B.copy()420for i in range(1, nx-1):421C_B_new[i] = C_B[i] + D_B * dt / dx**2 * (C_B[i+1] - 2*C_B[i] + C_B[i-1])422423C_A = C_A_new424C_B = C_B_new425426# Calculate marker velocity (proportional to flux difference)427i_marker = int(marker_pos / dx)428if 0 < i_marker < nx-1:429J_A = -D_A * (C_A[i_marker+1] - C_A[i_marker-1]) / (2*dx)430J_B = -D_B * (C_B[i_marker+1] - C_B[i_marker-1]) / (2*dx)431v_marker = -(J_A - J_B) / (C_A[i_marker] + C_B[i_marker] + 1e-10)432marker_pos += v_marker * dt * 1000 # scale for visibility433434if step in times:435results[step] = {'C_A': C_A.copy(), 'C_B': C_B.copy(), 'marker': marker_pos}436437# Plot results438fig, axes = plt.subplots(2, 2, figsize=(12, 10))439440for idx, (step, ax) in enumerate(zip(times, axes.flat)):441data = results[step]442t = step * dt443ax.plot(x*1000, data['C_A'], 'b-', linewidth=2, label='Species A')444ax.plot(x*1000, data['C_B'], 'r-', linewidth=2, label='Species B')445ax.axvline(L*500, color='k', linestyle='--', alpha=0.5, label='Initial interface')446ax.axvline(data['marker']*1000, color='g', linestyle='-', linewidth=2, label='Marker')447ax.set_xlabel('Position (mm)')448ax.set_ylabel('Concentration')449ax.set_title(f't = {t:.0f} s')450ax.legend(fontsize=8)451ax.grid(True, alpha=0.3)452453plt.tight_layout()454save_fig('kirkendall_effect.pdf')455456marker_shift = (results[n_steps]['marker'] - L/2) * 1000457\end{pycode}458459\begin{figure}[H]460\centering461\includegraphics[width=\textwidth]{kirkendall_effect.pdf}462\caption{Kirkendall effect in a binary diffusion couple showing marker movement due to unequal diffusivities.}463\end{figure}464465The marker shifted by \py{f"{marker_shift:.3f}"} mm toward the faster-diffusing side, demonstrating the Kirkendall effect.466467\section{Interdiffusion Coefficient}468469The interdiffusion (chemical) coefficient can be determined using the Matano-Boltzmann analysis:470\begin{equation}471\tilde{D} = -\frac{1}{2t}\left(\frac{dx}{dC}\right)_{C^*} \int_0^{C^*} x \, dC472\end{equation}473474\begin{pycode}475# Matano-Boltzmann analysis476# Generate synthetic interdiffusion profile477x = np.linspace(-5, 5, 1000) # mm478t = 3600 # 1 hour479480# Interdiffusion profile (error function)481D_tilde = 1e-10 # m^2/s482C = 0.5 * erfc(x*1e-3 / (2*np.sqrt(D_tilde * t)))483484# Matano analysis at different concentrations485C_star = [0.2, 0.4, 0.6, 0.8]486D_calc = []487488fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))489490ax1.plot(x, C, 'b-', linewidth=2)491ax1.set_xlabel('Position (mm)')492ax1.set_ylabel('Concentration')493ax1.set_title('Interdiffusion Profile')494ax1.grid(True, alpha=0.3)495496for C_s in C_star:497# Find position at C*498idx = np.argmin(np.abs(C - C_s))499x_s = x[idx]500501# Calculate dx/dC502dCdx = np.gradient(C, x*1e-3)[idx]503dxdC = 1/dCdx if dCdx != 0 else 0504505# Integrate506integral = np.trapz(x[:idx]*1e-3, C[:idx])507508# Calculate D509D = -dxdC * integral / (2*t)510D_calc.append(D)511512ax1.axhline(C_s, color='r', linestyle='--', alpha=0.5)513ax1.plot(x_s, C_s, 'ro', markersize=8)514515ax2.plot(C_star, [d*1e10 for d in D_calc], 'bo-', linewidth=2, markersize=10)516ax2.axhline(D_tilde*1e10, color='r', linestyle='--', label=f'True D = {D_tilde:.0e}')517ax2.set_xlabel('Concentration')518ax2.set_ylabel('$\\tilde{D}$ ($\\times 10^{-10}$ m$^2$/s)')519ax2.set_title('Matano-Boltzmann Analysis')520ax2.legend()521ax2.grid(True, alpha=0.3)522523plt.tight_layout()524save_fig('matano_analysis.pdf')525\end{pycode}526527\begin{figure}[H]528\centering529\includegraphics[width=\textwidth]{matano_analysis.pdf}530\caption{Matano-Boltzmann analysis for determining concentration-dependent interdiffusion coefficient.}531\end{figure}532533\section{3D Diffusion Visualization}534535\begin{pycode}536# 3D visualization of diffusion evolution537D = 1e-10538x = np.linspace(0, 10, 100)539t = np.linspace(0.1, 100, 100)540X, T = np.meshgrid(x, t)541542# Concentration field C(x,t)543C = erfc(X*1e-3 / (2*np.sqrt(D * T * 3600)))544545fig = plt.figure(figsize=(10, 7))546ax = fig.add_subplot(111, projection='3d')547548surf = ax.plot_surface(X, T, C, cmap='viridis', alpha=0.8)549ax.set_xlabel('Position (mm)')550ax.set_ylabel('Time (hours)')551ax.set_zlabel('Concentration')552ax.set_title('3D Visualization of Diffusion Evolution')553554fig.colorbar(surf, shrink=0.5, aspect=10, label='Concentration')555556save_fig('diffusion_3d.pdf')557\end{pycode}558559\begin{figure}[H]560\centering561\includegraphics[width=0.8\textwidth]{diffusion_3d.pdf}562\caption{Three-dimensional visualization of concentration evolution during diffusion.}563\end{figure}564565\section{Conclusions}566567This analysis demonstrates key aspects of diffusion in materials science:568\begin{enumerate}569\item Fick's laws provide the mathematical framework for both steady-state and transient diffusion570\item Error function solutions enable analytical calculation of penetration profiles571\item Temperature dependence follows Arrhenius behavior with characteristic activation energies572\item Numerical methods allow simulation of complex boundary conditions573\item The Kirkendall effect demonstrates the physical consequences of unequal diffusivities574\item Matano-Boltzmann analysis enables experimental determination of diffusion coefficients575\end{enumerate}576577\end{document}578579580