Skip to content

Commit 1390b60

Browse files
committed
Include two examples into respective folder.
1 parent 68bf445 commit 1390b60

File tree

4 files changed

+1079
-847
lines changed

4 files changed

+1079
-847
lines changed

examples/test_laser_cartledge_paper.ipynb

Lines changed: 181 additions & 69 deletions
Large diffs are not rendered by default.

examples/test_laser_modulation.ipynb

Lines changed: 666 additions & 0 deletions
Large diffs are not rendered by default.

optic/models/laser.py

Lines changed: 232 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@
66
from optic.utils import parameters
77

88
def laser_dfb(param, current):
9+
"""
10+
Simulates the behavior of a distributed feedback (DFB) laser.
11+
12+
Args:
13+
param: The parameters of the DFB laser.
14+
current: The current object.
15+
16+
Returns:
17+
A tuple containing the updated parameters, current object, and the solution of the DFB laser simulation.
18+
"""
919
param.noise_terms = getattr(param, "noise_terms", False)
1020
param.v = getattr(param, "v", 1.5e-10)
1121
param.tau_n = getattr(param, "tau_n", 1.0e-9)
@@ -23,31 +33,61 @@ def laser_dfb(param, current):
2333
param.eta_0 = getattr(param, 'eta_0', 0.4)
2434
param.lmbd = getattr(param, 'lmbd', 1300e-9)
2535
param.freq_0 = c/param.lmbd
36+
# Current Threshold
2637
param.ith = e/param.tau_n*param.v*(param.n_t + 1/(param.gamma * param.tau_p * param.vg * param.a0))
27-
38+
# Electrical current
2839
current = set_current(param, current)
2940

3041
return param, current, solve_laser_dfb(param, current)
3142

3243
def laser_dynamic_response(y, param):
44+
"""
45+
Calculates the dynamic response of the laser.
46+
47+
Args:
48+
y: The state of the laser.
49+
param: The parameters of the laser.
50+
51+
Returns:
52+
An object containing the calculated laser parameters including power, chirp, and output electric field.
53+
"""
3354
out = parameters()
34-
# get variables
55+
# get physical parameters
3556
out.N = y[0,:]
3657
out.S = y[1,: ]
3758
out.phase = y[2,:]
38-
# calculate others parameters
59+
# get signal parameters
3960
out.power = (out.S/2) * (param.v * h * param.freq_0 * param.eta_0)/(param.gamma * param.tau_p)
4061
out.chirp = 1/(2*np.pi) * (param.alpha / 2) * (param.gamma * param.vg * param.a0 * (out.N - param.n_t) - 1/param.tau_p) # np.diff(y[2,:],prepend=y[2,0])/self.t_step
4162
out.e_out = np.sqrt(np.real(out.power)) * np.exp(1j * out.phase)
4263
return out
4364

4465
def set_current(param, current):
45-
# set variables
66+
"""
67+
Sets the current signal and time step for the current object.
68+
69+
Args:
70+
param: The parameters for setting the current signal.
71+
current: The current object.
72+
73+
Returns:
74+
The updated current object with the modified signal and time step.
75+
"""
4676
current.signal = param.i_max * current.signal + param.i_bias
4777
current.t_step = current.t[1]-current.t[0]
4878
return current
4979

5080
def get_current(current, t):
81+
"""
82+
Returns the current value at a given time.
83+
84+
Args:
85+
current: The current object.
86+
t: The time value.
87+
88+
Returns:
89+
The real part of the current signal at the specified time.
90+
"""
5191
return np.real(current.signal[np.argwhere(t >= current.t)[-1]])
5292

5393
def solve_laser_dfb(param, current):
@@ -65,13 +105,42 @@ def solve_laser_dfb(param, current):
65105
)
66106

67107
def get_initial_conditions(param,current):
108+
"""
109+
Calculates the initial conditions for the laser rate equations.
110+
111+
Args:
112+
param: The parameters of the rate equations.
113+
current: The current value.
114+
115+
Returns:
116+
The array of initial conditions [y0[0], y0[1], y0[2]].
117+
"""
68118
y0 = np.zeros([3])
69119
y0[1] = param.gamma * param.tau_p/(param.v * e) * (get_current(current,0)-param.ith)
70120
y0[0] = param.n_t + (1 + param.epsilon * y0[1]) / (param.vg * param.a0 * param.gamma * param.tau_p)
71121
y0[2] = (param.alpha / 2) * (param.gamma * param.vg * param.a0 * (y0[0] - param.n_t) - 1 / param.tau_p)
72122
return y0
73123

74124
def laser_rate_equations(t, y, param, current):
125+
"""
126+
Calculate the derivatives of the laser state variables based on the laser rate equations.
127+
128+
Parameters
129+
----------
130+
t : scalar
131+
Time value.
132+
y : np.array
133+
Array of laser state variables.
134+
param : parameter object (struct)
135+
Object with laser parameters.
136+
current : parameter object (struct)
137+
Object with current input signal.
138+
139+
Returns
140+
-------
141+
np.array
142+
Array of derivatives of the laser state variables.
143+
"""
75144
#param, current = args
76145
dy = np.zeros(3)
77146
# Carrier density
@@ -83,37 +152,121 @@ def laser_rate_equations(t, y, param, current):
83152
return add_noise_rate_equations(y,dy,param,current)
84153

85154
def carrier_density(t,y,param,current):
155+
"""
156+
Calculate the rate of change of the carrier density.
157+
158+
Parameters
159+
----------
160+
t : scalar
161+
Time value.
162+
y : np.array
163+
Array of laser state variables.
164+
param : parameter object (struct)
165+
Object with laser parameters.
166+
current : parameter object (struct)
167+
Object with current input signal.
168+
169+
Returns
170+
-------
171+
scalar
172+
Rate of change of the carrier density.
173+
"""
86174
current = get_current(current, t)
87175
return current/(e*param.v)-y[0]/param.tau_n-param.vg*param.a0*y[1]*(y[0]-param.n_t)/(1+param.epsilon*y[1])
88176

89177
def photon_density(y,param):
178+
"""
179+
Calculate the rate of change of the photon density.
180+
181+
Parameters
182+
----------
183+
y : np.array
184+
Array of laser state variables.
185+
param : parameter object (struct)
186+
Object with laser parameters.
187+
188+
Returns
189+
-------
190+
scalar
191+
Rate of change of the photon density.
192+
"""
90193
return (param.gamma * param.a0 * param.vg * ((y[0]-param.n_t)/(1+param.epsilon*y[1]))-1/param.tau_p)*y[1]+param.beta*param.gamma*y[0]/param.tau_n
91194

92195
def optical_phase(y,param):
196+
"""
197+
Calculate the rate of change of the optical phase.
198+
199+
Parameters
200+
----------
201+
y : np.array
202+
Array of laser state variables.
203+
param : parameter object (struct)
204+
Object with laser parameters.
205+
206+
Returns
207+
-------
208+
scalar
209+
Rate of change of the optical phase.
210+
"""
93211
return param.alpha/2 * (param.gamma*param.vg*param.a0*(y[0]-param.n_t)-1/param.tau_p)
94212

95213
def add_noise_rate_equations(y, dy, param, current):
214+
"""
215+
Adds noise terms to the rate equations.
216+
217+
Args:
218+
y: The current state of the rate equations.
219+
dy: The rate of change of the rate equations.
220+
param: The parameters of the rate equations.
221+
current: The current value.
222+
223+
Returns:
224+
The updated rate of change of the rate equations.
225+
"""
96226
# Calculate noise terms
97227
dn = laser_noise_sources(y,param,current) if param.noise_terms else np.zeros(3)
98228
# Add noise terms to dy
99229
dy += dn
100230
return dy
101231

102232
def laser_noise_sources(y,param,current):
103-
# noise term
233+
"""
234+
Calculates the noise terms for the laser rate equations.
235+
236+
Args:
237+
y: The current state of the rate equations.
238+
param: The parameters of the rate equations.
239+
current: The current value.
240+
241+
Returns:
242+
A list of noise terms [fn, fs, fp].
243+
"""
104244
# diffusion coefficient - see ref. [2]
105245
dss = (param.beta*y[0]*y[1]/param.tau_n)
106246
#dnn = (y[0]/self.tau_n)*(1+self.beta*y[1])
107247
dpp = (param.beta*y[0])/(4*param.tau_n*y[1])
108248
dzz = y[0]/param.tau_n
109249
# noise sources
110-
fs = np.random.randn()*np.sqrt(2*dss/current.t_step)
111-
fz = np.random.randn()*np.sqrt(2*dzz/current.t_step)
112-
fp = np.random.randn()*np.sqrt(2*dpp/current.t_step)
250+
t_step_sqrt = np.sqrt(2 / current.t_step)
251+
fs = np.random.randn() * np.sqrt(dss) * t_step_sqrt
252+
fz = np.random.randn() * np.sqrt(dzz) * t_step_sqrt
253+
fp = np.random.randn() * np.sqrt(dpp) * t_step_sqrt
113254
fn = fz - fs
114255
return [fn, fs, fp]
115256

116257
def get_im_response(param, out, f, type='exact'):
258+
"""
259+
Calculates the impulse response of an intensity modulator (IM).
260+
261+
Args:
262+
param: The parameters of the IM.
263+
out: The output of the IM.
264+
f: The frequency values.
265+
type: The type of response to calculate ('exact' or 'approx.').
266+
267+
Returns:
268+
The calculated Y, Z, and response values based on the specified type.
269+
"""
117270
Y, Z = im_response_yz(param,out)
118271
if type=='exact':
119272
return Y, Z, im_response_hf(f,Y,Z)
@@ -124,21 +277,88 @@ def get_im_response(param, out, f, type='exact'):
124277
return -1
125278

126279
def im_response_hf(f,Y,Z):
280+
"""
281+
Calculates the high-frequency response of an intensity modulator (IM) - Eq. [6] ref. [1].
282+
283+
Args:
284+
f: The frequency values.
285+
Y: The Y parameter of the IM.
286+
Z: The Z parameter of the IM.
287+
288+
Returns:
289+
The calculated high-frequency response of the IM.
290+
"""
127291
return Z/((1j*2*np.pi*f)**2+1j*2*np.pi*f*Y+Z)
128292

129293
def im_response_haf(f,Y,Z):
294+
"""
295+
Calculates the high-frequency approximation response of an intensity modulator (IM) - Eq. [12] ref. [1]
296+
297+
Args:
298+
f: The frequency values.
299+
Y: The Y parameter of the IM.
300+
Z: The Z parameter of the IM.
301+
302+
Returns:
303+
The calculated high-frequency approximation response of the IM.
304+
"""
130305
fr = np.sqrt(Z)/(2*np.pi)
131306
return fr**2/((fr**2-f**2)+1j*f*Y/(2*np.pi))
132307

133308
def im_response_yz(param,out):
134-
# Intensity modulation frequency response - see ref. [1]
309+
"""
310+
Calculates the Y and Z parameters for the intensity modulation frequency response - see ref. [1]
311+
312+
Args:
313+
param: The parameters of the intensity modulator.
314+
out: The output of the intensity modulator.
315+
316+
Returns:
317+
A tuple containing the calculated Y and Z parameters for the intensity modulation frequency response.
318+
"""
319+
return im_response_y(param,out),im_response_z(param,out)
320+
321+
def im_response_y(param,out):
322+
"""
323+
Calculates the Y parameter for the intensity modulation frequency response - Eq. [7] ref. [1].
324+
325+
Args:
326+
param: The parameters of the intensity modulator.
327+
out: The output of the intensity modulator.
328+
329+
Returns:
330+
The calculated Y parameter for the intensity modulation frequency response.
331+
"""
135332
Y = param.vg*param.a0*out.S[-1]/(1+param.epsilon*out.S[-1]) + 1/param.tau_n + 1/param.tau_p
136-
Y = Y - param.gamma*param.a0*param.vg*(out.N[-1]-param.n_t)/(1+param.epsilon*out.S[-1])**2
333+
Y -= param.gamma*param.a0*param.vg*(out.N[-1]-param.n_t)/(1+param.epsilon*out.S[-1])**2
334+
return Y
335+
336+
def im_response_z(param,out):
337+
"""
338+
Calculates the Z parameter for the intensity modulation frequency response - Eq. [8] ref. [1].
339+
340+
Args:
341+
param: The parameters of the intensity modulator.
342+
out: The output of the intensity modulator.
343+
344+
Returns:
345+
The calculated Z parameter for the intensity modulation frequency response.
346+
"""
137347
Z = param.vg*param.a0*out.S[-1]/(1+param.epsilon*out.S[-1]) * 1/param.tau_p + 1/(param.tau_p*param.tau_n)
138-
Z = Z + (param.beta-1)*param.gamma*param.a0*param.vg/param.tau_n*(out.N[-1]-param.n_t)/(1+param.epsilon*out.S[-1])**2
139-
return Y,Z
348+
Z += (param.beta-1)*param.gamma*param.a0*param.vg/param.tau_n*(out.N[-1]-param.n_t)/(1+param.epsilon*out.S[-1])**2
349+
return Z
140350

141351
def plot(t,y):
352+
"""
353+
Plots the optical power, chirp, carrier density, and photon density.
354+
355+
Args:
356+
t: The time values.
357+
y: The values to be plotted.
358+
359+
Returns:
360+
The matplotlib axes object containing the plot.
361+
"""
142362
fig,ax=plt.subplots(2,2,figsize=(12,6))
143363
ax[0,0].plot(1e9*t, 1e3*y.power)
144364
_extracted_from_plot_4(t, ax, 0, 0, 'Optical Power [mW]')

0 commit comments

Comments
 (0)