Skip to content

Commit a74df56

Browse files
committed
fix overlap calculations
1 parent cf7d86f commit a74df56

File tree

1 file changed

+44
-41
lines changed

1 file changed

+44
-41
lines changed

femwell/examples/Aeff.py

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
"""Aeff analysis based on https://optics.ansys.com/hc/en-us/articles/15100783091731-Spontaneous-Four-wave-Mixing-SWFM-Microring-Resonator-Photon-Source."""
22
from collections import OrderedDict
3+
34
import numpy as np
5+
from scipy.constants import c, epsilon_0
46
from shapely.geometry import box
57
from shapely.ops import clip_by_rect
6-
from skfem import Basis, ElementTriP0
7-
from skfem import Functional
8+
from skfem import Basis, ElementTriP0, Functional
89
from skfem.helpers import dot
910
from skfem.io.meshio import from_meshio
11+
1012
from femwell.maxwell.waveguide import compute_modes
1113
from femwell.mesh import mesh_from_OrderedDict
12-
from scipy.constants import c, epsilon_0
1314

14-
def calculate_sfwm_Aeff(
15-
basis: Basis,
16-
mode_p,
17-
mode_s,
18-
mode_i
19-
) -> np.complex64:
20-
15+
16+
def calculate_sfwm_Aeff(basis: Basis, mode_p, mode_s, mode_i) -> np.complex64:
2117
"""
2218
Calculates the overlap integral for SFWM process by considering the interactions
2319
between pump, signal, and idler modes in the xy plane.
@@ -30,46 +26,43 @@ def calculate_sfwm_Aeff(
3026
np.complex64: The Aeff result for the SFWM process(1/overlap integral).
3127
"""
3228

33-
def normalize_mode(mode):
29+
def normalization_factor_mode(mode):
3430
@Functional
3531
def E2(w):
3632
return dot(w["E"][0], np.conj(w["E"][0]))
3733

38-
E_xy, _ = mode.basis.interpolate(mode.E) # [0]=xy [1]=z
39-
E_squared_integral = E2.assemble(mode.basis, E=E_xy)
34+
E = mode.basis.interpolate(mode.E) # [0]=xy [1]=z
35+
E_squared_integral = E2.assemble(mode.basis, E=E)
4036
normalization_factor = 1 / np.sqrt(E_squared_integral)
4137
return normalization_factor # Return the normalization factor instead of modifying the mode
4238

43-
# Calculate normalization factors for each mode
44-
norm_factor_p = normalize_mode(mode_p)
45-
norm_factor_s = normalize_mode(mode_s)
46-
norm_factor_i = normalize_mode(mode_i)
47-
4839
# Apply normalization factors to the electric fields for the overlap calculation
49-
E_p, _ = mode_p.basis.interpolate(mode_p.E * norm_factor_p)
50-
E_s, _ = mode_s.basis.interpolate(mode_s.E * norm_factor_s)
51-
E_i, _ = mode_i.basis.interpolate(mode_i.E * norm_factor_i)
52-
5340
@Functional(dtype=np.complex64)
5441
def sfwm_overlap(w):
55-
overlap_SFWM = w["E_p"][0] * w["E_p"][0] * np.conj(w["E_s"][0]) * np.conj(w["E_i"][0])
56-
return overlap_SFWM
42+
return dot(w["E_p"][0], w["E_p"][0]) * dot(np.conj(w["E_s"][0]), np.conj(w["E_i"][0]))
5743

58-
overlap_result = sfwm_overlap.assemble(basis, E_p=E_p, E_s=E_s, E_i=E_i)
44+
overlap_result = sfwm_overlap.assemble(
45+
basis,
46+
E_p=mode_p.basis.interpolate(mode_p.E * normalization_factor_mode(mode_p)),
47+
E_s=mode_s.basis.interpolate(mode_s.E * normalization_factor_mode(mode_s)),
48+
E_i=mode_i.basis.interpolate(mode_i.E * normalization_factor_mode(mode_i)),
49+
)
5950

6051
return 1 / overlap_result
6152

6253

63-
#Dispersion relations of materials
64-
#Core
54+
# Dispersion relations of materials
55+
# Core
6556
def n_X(wavelength):
6657
x = wavelength
67-
return (1
68-
+ 2.19244563 / (1 - (0.20746607 / x) ** 2)
69-
+ 0.13435116 / (1 - (0.3985835 / x) ** 2)
70-
+ 2.20997784 / (1 - (0.20747044 / x) ** 2)
58+
return (
59+
1
60+
+ 2.19244563 / (1 - (0.20746607 / x) ** 2)
61+
+ 0.13435116 / (1 - (0.3985835 / x) ** 2)
62+
+ 2.20997784 / (1 - (0.20747044 / x) ** 2)
7163
) ** 0.5
7264

65+
7366
# Box
7467
def n_silicon_dioxide(wavelength):
7568
x = wavelength
@@ -80,35 +73,43 @@ def n_silicon_dioxide(wavelength):
8073
+ 0.8974794 / (1 - (9.896161 / x) ** 2)
8174
) ** 0.5
8275

83-
Clad=1
76+
77+
Clad = 1
8478

8579

86-
core = box(0, 0, 0.5, 0.39) #500x390nm
80+
core = box(0, 0, 1.05, 0.5) # 1050x500nm
81+
# core = box(0, 0, .5, 0.39) # 500x390nm
8782
polygons = OrderedDict(
8883
core=core,
8984
box=clip_by_rect(core.buffer(1.5, resolution=4), -np.inf, -np.inf, np.inf, 0),
9085
clad=clip_by_rect(core.buffer(1.5, resolution=4), -np.inf, 0, np.inf, np.inf),
9186
)
9287

93-
resolutions = {"core": {"resolution": 0.025, "distance": 2.}}
88+
resolutions = {"core": {"resolution": 0.025, "distance": 2.0}}
9489

95-
mesh = from_meshio(mesh_from_OrderedDict(polygons, resolutions, default_resolution_max=0.6))
90+
mesh = from_meshio(mesh_from_OrderedDict(polygons, resolutions, default_resolution_max=0.2))
9691

9792
num_modes = 2
9893

99-
#For SFWM we have energy conservation and momemtum(k) conservation for 2pumps and signal+idler
94+
# For SFWM we have energy conservation and momemtum(k) conservation for 2pumps and signal+idler
10095
lambda_p0 = 1.4
10196
lambda_s0 = 1.097
10297
lambda_i0 = 1.686
10398

99+
# lambda_p0 = 1.55
100+
# lambda_s0 = 1.55
101+
# lambda_i0 = 1.55
102+
104103
basis0 = Basis(mesh, ElementTriP0())
105104

106105
epsilon_p = basis0.zeros()
107106
epsilon_s = basis0.zeros()
108107
epsilon_i = basis0.zeros()
109108

110109

111-
for wavelength, epsilon in zip([lambda_p0, lambda_s0, lambda_i0], [epsilon_p, epsilon_s, epsilon_i]):
110+
for wavelength, epsilon in zip(
111+
[lambda_p0, lambda_s0, lambda_i0], [epsilon_p, epsilon_s, epsilon_i]
112+
):
112113
for subdomain, n_func in {
113114
"core": n_X,
114115
"box": n_silicon_dioxide,
@@ -122,6 +123,7 @@ def n_silicon_dioxide(wavelength):
122123
modes_s = compute_modes(basis0, epsilon_s, wavelength=lambda_s0, num_modes=num_modes, order=1)
123124
modes_i = compute_modes(basis0, epsilon_i, wavelength=lambda_i0, num_modes=num_modes, order=1)
124125

126+
# modes_p[0].show(modes_p[0].E.real)
125127

126128
mode_p = max(modes_p, key=lambda mode: mode.te_fraction)
127129
mode_s = max(modes_s, key=lambda mode: mode.te_fraction)
@@ -130,14 +132,15 @@ def n_silicon_dioxide(wavelength):
130132
A_eff = calculate_sfwm_Aeff(basis0, mode_p, mode_s, mode_i)
131133
print("Aeff in um2:", A_eff)
132134

133-
#Calculation for non-linear coef
135+
# Calculation for non-linear coef
134136
chi_3 = 5e-21 # m^2/V^2 #7e-20?
135-
lambda_p0_m = lambda_p0 * 1e-6 #to m
137+
chi_3 = 7e-20 # ?
138+
lambda_p0_m = lambda_p0 * 1e-6 # to m
136139
n_p0 = np.real(mode_p.n_eff)
137-
A_eff_m2 = A_eff * 1e-12 #to m^2
140+
A_eff_m2 = A_eff * 1e-12 # to m^2
138141

139142
omega_p0 = 2 * np.pi * c / lambda_p0_m
140143

141144
gamma = (3 * chi_3 * omega_p0) / (4 * epsilon_0 * c**2 * n_p0**2 * A_eff_m2)
142145

143-
print("gamma:",gamma)
146+
print("gamma:", gamma)

0 commit comments

Comments
 (0)