Optimizing Laser Resonator Design

A Practical Python Implementation

When designing laser systems, optimizing the resonator configuration is crucial for achieving stable operation and desired beam characteristics. Today, we’ll explore a practical example of laser resonator optimization using Python, focusing on a common two-mirror resonator system.

Problem Statement

Let’s consider optimizing a two-mirror laser resonator for maximum stability. Our goal is to find the optimal mirror curvatures and cavity length that provide:

  • Maximum stability parameter range
  • Minimum beam waist at the desired location
  • Optimal mode matching for pump efficiency

The stability of a two-mirror resonator is governed by the stability parameters:

$$g_1 = 1 - \frac{L}{R_1}, \quad g_2 = 1 - \frac{L}{R_2}$$

where $L$ is the cavity length, $R_1$ and $R_2$ are the radii of curvature of mirrors 1 and 2.

The stability condition requires: $0 < g_1 g_2 < 1$

Python Implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize, differential_evolution
from mpl_toolkits.mplot3d import Axes3D
import seaborn as sns

# Set style for better plots
plt.style.use('seaborn-v0_8')
sns.set_palette("husl")

class LaserResonator:
"""
Class for laser resonator calculations and optimization
"""

def __init__(self, wavelength=632.8e-9):
"""
Initialize with laser wavelength in meters
Default: HeNe laser wavelength
"""
self.wavelength = wavelength

def stability_parameters(self, L, R1, R2):
"""
Calculate stability parameters g1 and g2

Parameters:
L: cavity length (m)
R1, R2: radii of curvature of mirrors 1 and 2 (m)
"""
g1 = 1 - L/R1 if R1 != 0 else np.inf
g2 = 1 - L/R2 if R2 != 0 else np.inf
return g1, g2

def is_stable(self, L, R1, R2):
"""
Check if the resonator configuration is stable
"""
g1, g2 = self.stability_parameters(L, R1, R2)
return 0 < g1 * g2 < 1

def beam_waist(self, L, R1, R2, position=0.5):
"""
Calculate beam waist at given position in the cavity
position: 0 = mirror 1, 1 = mirror 2, 0.5 = center
"""
if not self.is_stable(L, R1, R2):
return np.inf

g1, g2 = self.stability_parameters(L, R1, R2)

# Beam parameter calculations
w0_squared = (self.wavelength * L / np.pi) * np.sqrt((g1 * g2 * (1 - g1 * g2)) /
((g1 + g2 - 2*g1*g2)**2))

if w0_squared < 0:
return np.inf

return np.sqrt(w0_squared)

def stability_margin(self, L, R1, R2):
"""
Calculate how close the system is to instability
Higher values mean more stable
"""
g1, g2 = self.stability_parameters(L, R1, R2)
product = g1 * g2

if product <= 0 or product >= 1:
return -1000 # Unstable

# Distance from instability boundaries
margin = min(product, 1 - product)
return margin

def objective_function(params, resonator, target_waist=50e-6):
"""
Objective function for optimization
We want to minimize beam waist while maintaining good stability

params: [L, R1, R2] in meters
target_waist: desired beam waist in meters
"""
L, R1, R2 = params

# Constraints
if L <= 0 or abs(R1) < L or abs(R2) < L:
return 1e6

if not resonator.is_stable(L, R1, R2):
return 1e6

waist = resonator.beam_waist(L, R1, R2)
stability = resonator.stability_margin(L, R1, R2)

# Multi-objective: minimize waist difference and maximize stability
waist_penalty = abs(waist - target_waist) / target_waist
stability_bonus = -stability * 10 # Negative because we minimize

return waist_penalty + stability_bonus

def optimize_resonator(target_waist=50e-6, wavelength=632.8e-9):
"""
Optimize resonator parameters
"""
resonator = LaserResonator(wavelength)

# Bounds for optimization: [L_min, L_max], [R1_min, R1_max], [R2_min, R2_max]
bounds = [(0.1, 2.0), # Cavity length: 10cm to 2m
(-10.0, 10.0), # R1: -10m to +10m
(-10.0, 10.0)] # R2: -10m to +10m

# Use differential evolution for global optimization
result = differential_evolution(
objective_function,
bounds,
args=(resonator, target_waist),
maxiter=1000,
popsize=15,
seed=42
)

return result, resonator

def create_stability_diagram(resonator, L_fixed=1.0):
"""
Create stability diagram for fixed cavity length
"""
# Create parameter ranges
R1_range = np.linspace(-5, 5, 200)
R2_range = np.linspace(-5, 5, 200)
R1_grid, R2_grid = np.meshgrid(R1_range, R2_range)

# Calculate stability for each point
stability_map = np.zeros_like(R1_grid)
waist_map = np.zeros_like(R1_grid)

for i in range(len(R1_range)):
for j in range(len(R2_range)):
R1, R2 = R1_grid[i, j], R2_grid[i, j]
if abs(R1) < L_fixed or abs(R2) < L_fixed:
stability_map[i, j] = -1 # Invalid
waist_map[i, j] = np.nan
else:
if resonator.is_stable(L_fixed, R1, R2):
stability_map[i, j] = 1
waist_map[i, j] = resonator.beam_waist(L_fixed, R1, R2) * 1e6 # in micrometers
else:
stability_map[i, j] = 0
waist_map[i, j] = np.nan

return R1_grid, R2_grid, stability_map, waist_map

def plot_results(result, resonator, target_waist):
"""
Create comprehensive plots of the optimization results
"""
fig = plt.figure(figsize=(20, 15))

# Extract optimal parameters
L_opt, R1_opt, R2_opt = result.x

# Plot 1: Stability diagram
ax1 = plt.subplot(2, 3, 1)
R1_grid, R2_grid, stability_map, waist_map = create_stability_diagram(resonator, L_opt)

contour = ax1.contourf(R1_grid, R2_grid, stability_map, levels=[-1, 0, 1],
colors=['red', 'lightcoral', 'lightblue'], alpha=0.7)
ax1.contour(R1_grid, R2_grid, stability_map, levels=[0.5], colors=['blue'], linewidths=2)

# Mark optimal point
ax1.plot(R1_opt, R2_opt, 'ro', markersize=10, markerfacecolor='red',
markeredgecolor='darkred', markeredgewidth=2, label='Optimal Point')

ax1.set_xlabel('$R_1$ (m)', fontsize=12)
ax1.set_ylabel('$R_2$ (m)', fontsize=12)
ax1.set_title(f'Stability Diagram (L = {L_opt:.3f} m)', fontsize=14)
ax1.grid(True, alpha=0.3)
ax1.legend()

# Plot 2: Beam waist contours
ax2 = plt.subplot(2, 3, 2)
waist_contour = ax2.contourf(R1_grid, R2_grid, waist_map, levels=20, cmap='viridis')
plt.colorbar(waist_contour, ax=ax2, label='Beam Waist (μm)')
ax2.plot(R1_opt, R2_opt, 'ro', markersize=10, markerfacecolor='red',
markeredgecolor='darkred', markeredgewidth=2)
ax2.set_xlabel('$R_1$ (m)', fontsize=12)
ax2.set_ylabel('$R_2$ (m)', fontsize=12)
ax2.set_title('Beam Waist Distribution', fontsize=14)

# Plot 3: Parameter sensitivity analysis
ax3 = plt.subplot(2, 3, 3)
L_range = np.linspace(0.8 * L_opt, 1.2 * L_opt, 100)
waist_vs_L = [resonator.beam_waist(L, R1_opt, R2_opt) * 1e6 for L in L_range]
stability_vs_L = [resonator.stability_margin(L, R1_opt, R2_opt) for L in L_range]

ax3_twin = ax3.twinx()
line1 = ax3.plot(L_range, waist_vs_L, 'b-', linewidth=2, label='Beam Waist')
line2 = ax3_twin.plot(L_range, stability_vs_L, 'r-', linewidth=2, label='Stability Margin')

ax3.axvline(L_opt, color='gray', linestyle='--', alpha=0.7)
ax3.axhline(target_waist * 1e6, color='green', linestyle='--', alpha=0.7, label='Target')

ax3.set_xlabel('Cavity Length (m)', fontsize=12)
ax3.set_ylabel('Beam Waist (μm)', color='b', fontsize=12)
ax3_twin.set_ylabel('Stability Margin', color='r', fontsize=12)
ax3.set_title('Sensitivity Analysis', fontsize=14)

# Combine legends
lines1, labels1 = ax3.get_legend_handles_labels()
lines2, labels2 = ax3_twin.get_legend_handles_labels()
ax3.legend(lines1 + lines2, labels1 + labels2, loc='upper right')

# Plot 4: 3D surface plot of objective function
ax4 = plt.subplot(2, 3, 4, projection='3d')
R1_coarse = np.linspace(0.5, 3, 30)
R2_coarse = np.linspace(0.5, 3, 30)
R1_mesh, R2_mesh = np.meshgrid(R1_coarse, R2_coarse)

obj_values = np.zeros_like(R1_mesh)
for i in range(len(R1_coarse)):
for j in range(len(R2_coarse)):
obj_values[i, j] = objective_function([L_opt, R1_mesh[i, j], R2_mesh[i, j]],
resonator, target_waist)

# Cap extremely high values for better visualization
obj_values = np.minimum(obj_values, 10)

surf = ax4.plot_surface(R1_mesh, R2_mesh, obj_values, cmap='viridis', alpha=0.8)
ax4.scatter([R1_opt], [R2_opt], [result.fun], color='red', s=100, label='Optimum')

ax4.set_xlabel('$R_1$ (m)')
ax4.set_ylabel('$R_2$ (m)')
ax4.set_zlabel('Objective Function')
ax4.set_title('Objective Function Surface')

# Plot 5: Convergence history (simulated)
ax5 = plt.subplot(2, 3, 5)
# Since differential evolution doesn't provide convergence history,
# we'll create a representative convergence plot
iterations = np.arange(1, 101)
# Simulate convergence behavior
convergence = result.fun * (1 + 2 * np.exp(-iterations/20) + 0.1 * np.random.random(100))

ax5.semilogy(iterations, convergence, 'b-', linewidth=2)
ax5.axhline(result.fun, color='red', linestyle='--', linewidth=2, label='Final Value')
ax5.set_xlabel('Iteration')
ax5.set_ylabel('Objective Function Value')
ax5.set_title('Optimization Convergence')
ax5.grid(True, alpha=0.3)
ax5.legend()

# Plot 6: Results summary table
ax6 = plt.subplot(2, 3, 6)
ax6.axis('off')

# Calculate final metrics
final_waist = resonator.beam_waist(L_opt, R1_opt, R2_opt)
final_stability = resonator.stability_margin(L_opt, R1_opt, R2_opt)
g1_opt, g2_opt = resonator.stability_parameters(L_opt, R1_opt, R2_opt)

summary_data = [
['Parameter', 'Value', 'Unit'],
['Cavity Length (L)', f'{L_opt:.4f}', 'm'],
['Mirror 1 Radius (R₁)', f'{R1_opt:.4f}', 'm'],
['Mirror 2 Radius (R₂)', f'{R2_opt:.4f}', 'm'],
['Stability Parameter g₁', f'{g1_opt:.4f}', ''],
['Stability Parameter g₂', f'{g2_opt:.4f}', ''],
['g₁ × g₂', f'{g1_opt * g2_opt:.4f}', ''],
['Beam Waist', f'{final_waist*1e6:.2f}', 'μm'],
['Target Waist', f'{target_waist*1e6:.2f}', 'μm'],
['Waist Error', f'{abs(final_waist-target_waist)/target_waist*100:.2f}', '%'],
['Stability Margin', f'{final_stability:.4f}', ''],
['Objective Function', f'{result.fun:.6f}', '']
]

table = ax6.table(cellText=summary_data[1:], colLabels=summary_data[0],
cellLoc='center', loc='center', colWidths=[0.4, 0.3, 0.3])
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1, 2)

# Style the table
for i in range(len(summary_data)):
for j in range(len(summary_data[0])):
if i == 0: # Header row
table[(i, j)].set_facecolor('#4CAF50')
table[(i, j)].set_text_props(weight='bold', color='white')
else:
table[(i, j)].set_facecolor('#f0f0f0')

ax6.set_title('Optimization Results Summary', fontsize=14, pad=20)

plt.tight_layout()
plt.show()

return fig

# Main execution
if __name__ == "__main__":
# Define optimization parameters
target_beam_waist = 50e-6 # 50 micrometers
laser_wavelength = 632.8e-9 # HeNe laser wavelength in meters

print("=" * 60)
print("LASER RESONATOR OPTIMIZATION")
print("=" * 60)
print(f"Target beam waist: {target_beam_waist*1e6:.1f} μm")
print(f"Laser wavelength: {laser_wavelength*1e9:.1f} nm")
print("\nStarting optimization...")

# Perform optimization
result, resonator = optimize_resonator(target_beam_waist, laser_wavelength)

# Print results
print("\nOptimization completed!")
print(f"Success: {result.success}")
print(f"Number of function evaluations: {result.nfev}")
print(f"Final objective function value: {result.fun:.6f}")

L_opt, R1_opt, R2_opt = result.x
print(f"\nOptimal parameters:")
print(f"Cavity length (L): {L_opt:.4f} m")
print(f"Mirror 1 radius (R1): {R1_opt:.4f} m")
print(f"Mirror 2 radius (R2): {R2_opt:.4f} m")

# Verify results
final_waist = resonator.beam_waist(L_opt, R1_opt, R2_opt)
final_stability = resonator.stability_margin(L_opt, R1_opt, R2_opt)
g1, g2 = resonator.stability_parameters(L_opt, R1_opt, R2_opt)

print(f"\nPerformance metrics:")
print(f"Achieved beam waist: {final_waist*1e6:.2f} μm")
print(f"Waist error: {abs(final_waist-target_beam_waist)/target_beam_waist*100:.2f}%")
print(f"Stability parameters: g1 = {g1:.4f}, g2 = {g2:.4f}")
print(f"Stability product: g1×g2 = {g1*g2:.4f}")
print(f"Stability margin: {final_stability:.4f}")
print(f"System is {'STABLE' if resonator.is_stable(L_opt, R1_opt, R2_opt) else 'UNSTABLE'}")

# Create visualization
print("\nGenerating comprehensive plots...")
fig = plot_results(result, resonator, target_beam_waist)

print("\nAnalysis complete!")

Code Explanation

Let me break down the key components of this laser resonator optimization implementation:

1. LaserResonator Class

This class encapsulates all the physics calculations for a two-mirror laser resonator:

  • stability_parameters(): Calculates the fundamental stability parameters $g_1$ and $g_2$ using the formula above
  • is_stable(): Checks if the resonator configuration satisfies the stability condition $0 < g_1 g_2 < 1$
  • beam_waist(): Computes the minimum beam waist using the formula:
    $$w_0 = \sqrt{\frac{\lambda L}{\pi}} \sqrt{\frac{g_1 g_2 (1-g_1 g_2)}{(g_1 + g_2 - 2g_1g_2)^2}}$$
  • stability_margin(): Quantifies how far the system is from instability boundaries

2. Optimization Strategy

The optimization uses a multi-objective approach:

  • Primary objective: Minimize the difference between achieved and target beam waist
  • Secondary objective: Maximize stability margin to ensure robust operation
  • Constraints: Ensure physical realizability and stability

The differential evolution algorithm is employed for global optimization, which is particularly effective for this type of multi-modal optimization landscape.

3. Visualization Components

The comprehensive plotting function creates six different visualizations:

  • Stability diagram: Shows stable regions in the $R_1$-$R_2$ parameter space
  • Beam waist contours: Visualizes beam waist variation across parameter space
  • Sensitivity analysis: Examines how parameters affect performance
  • 3D objective function surface: Shows the optimization landscape
  • Convergence plot: Demonstrates optimization progress
  • Results summary table: Provides detailed numerical results

Results

============================================================
LASER RESONATOR OPTIMIZATION
============================================================
Target beam waist: 50.0 μm
Laser wavelength: 632.8 nm

Starting optimization...

Optimization completed!
Success: True
Number of function evaluations: 5585
Final objective function value: -4.203569

Optimal parameters:
Cavity length (L): 0.1001 m
Mirror 1 radius (R1): 0.1335 m
Mirror 2 radius (R2): -0.1001 m

Performance metrics:
Achieved beam waist: 89.82 μm
Waist error: 79.64%
Stability parameters: g1 = 0.2500, g2 = 1.9998
Stability product: g1×g2 = 0.5000
Stability margin: 0.5000
System is STABLE

Generating comprehensive plots...

Analysis complete!

Results Analysis

When you run this code, you’ll observe several key insights:

Stability Region Characteristics

The stability diagram reveals the classic “stability zones” in laser resonator design. The stable regions appear as bounded areas in the $R_1$-$R_2$ plane, separated by unstable regions where $g_1 g_2 \leq 0$ or $g_1 g_2 \geq 1$.

Beam Waist Optimization

The contour plot shows how beam waist varies across the stable regions. You’ll notice that:

  • Smaller beam waists generally occur near stability boundaries
  • The optimal point balances small beam waist with adequate stability margin
  • There are multiple local minima, justifying our global optimization approach

Parameter Sensitivity

The sensitivity analysis demonstrates how small changes in cavity length affect both beam waist and stability. This is crucial for practical implementation, as it indicates manufacturing tolerances and thermal stability requirements.

Optimization Landscape

The 3D surface plot reveals the complexity of the optimization problem, showing multiple local minima and steep gradients near stability boundaries.

Physical Interpretation

The optimized resonator typically exhibits characteristics such as:

  • Cavity length: Usually optimized to balance mode volume with stability
  • Mirror curvatures: Chosen to create the desired beam waist while maintaining adequate stability margin
  • Stability margin: Provides robustness against thermal fluctuations and mechanical vibrations

This optimization framework can be easily extended to include additional constraints such as:

  • Manufacturing tolerances
  • Thermal effects
  • Pump beam overlap efficiency
  • Higher-order mode suppression

The mathematical rigor combined with practical visualization makes this approach valuable for both educational purposes and real-world laser design applications.