1
1
"""Aeff analysis based on https://optics.ansys.com/hc/en-us/articles/15100783091731-Spontaneous-Four-wave-Mixing-SWFM-Microring-Resonator-Photon-Source."""
2
2
from collections import OrderedDict
3
+
3
4
import numpy as np
5
+ from scipy .constants import c , epsilon_0
4
6
from shapely .geometry import box
5
7
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
8
9
from skfem .helpers import dot
9
10
from skfem .io .meshio import from_meshio
11
+
10
12
from femwell .maxwell .waveguide import compute_modes
11
13
from femwell .mesh import mesh_from_OrderedDict
12
- from scipy .constants import c , epsilon_0
13
14
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 :
21
17
"""
22
18
Calculates the overlap integral for SFWM process by considering the interactions
23
19
between pump, signal, and idler modes in the xy plane.
@@ -30,46 +26,43 @@ def calculate_sfwm_Aeff(
30
26
np.complex64: The Aeff result for the SFWM process(1/overlap integral).
31
27
"""
32
28
33
- def normalize_mode (mode ):
29
+ def normalization_factor_mode (mode ):
34
30
@Functional
35
31
def E2 (w ):
36
32
return dot (w ["E" ][0 ], np .conj (w ["E" ][0 ]))
37
33
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 )
40
36
normalization_factor = 1 / np .sqrt (E_squared_integral )
41
37
return normalization_factor # Return the normalization factor instead of modifying the mode
42
38
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
-
48
39
# 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
-
53
40
@Functional (dtype = np .complex64 )
54
41
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 ]))
57
43
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
+ )
59
50
60
51
return 1 / overlap_result
61
52
62
53
63
- #Dispersion relations of materials
64
- #Core
54
+ # Dispersion relations of materials
55
+ # Core
65
56
def n_X (wavelength ):
66
57
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 )
71
63
) ** 0.5
72
64
65
+
73
66
# Box
74
67
def n_silicon_dioxide (wavelength ):
75
68
x = wavelength
@@ -80,35 +73,43 @@ def n_silicon_dioxide(wavelength):
80
73
+ 0.8974794 / (1 - (9.896161 / x ) ** 2 )
81
74
) ** 0.5
82
75
83
- Clad = 1
76
+
77
+ Clad = 1
84
78
85
79
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
87
82
polygons = OrderedDict (
88
83
core = core ,
89
84
box = clip_by_rect (core .buffer (1.5 , resolution = 4 ), - np .inf , - np .inf , np .inf , 0 ),
90
85
clad = clip_by_rect (core .buffer (1.5 , resolution = 4 ), - np .inf , 0 , np .inf , np .inf ),
91
86
)
92
87
93
- resolutions = {"core" : {"resolution" : 0.025 , "distance" : 2. }}
88
+ resolutions = {"core" : {"resolution" : 0.025 , "distance" : 2.0 }}
94
89
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 ))
96
91
97
92
num_modes = 2
98
93
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
100
95
lambda_p0 = 1.4
101
96
lambda_s0 = 1.097
102
97
lambda_i0 = 1.686
103
98
99
+ # lambda_p0 = 1.55
100
+ # lambda_s0 = 1.55
101
+ # lambda_i0 = 1.55
102
+
104
103
basis0 = Basis (mesh , ElementTriP0 ())
105
104
106
105
epsilon_p = basis0 .zeros ()
107
106
epsilon_s = basis0 .zeros ()
108
107
epsilon_i = basis0 .zeros ()
109
108
110
109
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
+ ):
112
113
for subdomain , n_func in {
113
114
"core" : n_X ,
114
115
"box" : n_silicon_dioxide ,
@@ -122,6 +123,7 @@ def n_silicon_dioxide(wavelength):
122
123
modes_s = compute_modes (basis0 , epsilon_s , wavelength = lambda_s0 , num_modes = num_modes , order = 1 )
123
124
modes_i = compute_modes (basis0 , epsilon_i , wavelength = lambda_i0 , num_modes = num_modes , order = 1 )
124
125
126
+ # modes_p[0].show(modes_p[0].E.real)
125
127
126
128
mode_p = max (modes_p , key = lambda mode : mode .te_fraction )
127
129
mode_s = max (modes_s , key = lambda mode : mode .te_fraction )
@@ -130,14 +132,15 @@ def n_silicon_dioxide(wavelength):
130
132
A_eff = calculate_sfwm_Aeff (basis0 , mode_p , mode_s , mode_i )
131
133
print ("Aeff in um2:" , A_eff )
132
134
133
- #Calculation for non-linear coef
135
+ # Calculation for non-linear coef
134
136
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
136
139
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
138
141
139
142
omega_p0 = 2 * np .pi * c / lambda_p0_m
140
143
141
144
gamma = (3 * chi_3 * omega_p0 ) / (4 * epsilon_0 * c ** 2 * n_p0 ** 2 * A_eff_m2 )
142
145
143
- print ("gamma:" ,gamma )
146
+ print ("gamma:" , gamma )
0 commit comments