Kernels
CPU
CPU kernels in the NLSE
package are responsible for solving the nonlinear Schrödinger equation using CPU resources.
We use the popular Numba library to just-in-time compile array functions.
These functions are not meant to be called directly and instead work as the backend specific implementations for the main classes methods.
Due to the manual indexing involved in the implementations, these kernels do not support broadcasting (for now).
CPU kernels are suitable for small to medium-sized problems or when GPU resources are not available. As it uses multithreading internally, they will benefit from higher core counts.
nl_prop(A, A_sq, dz, alpha, V, g, Isat)
A compiled parallel implementation to apply real space terms
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A |
ndarray
|
The field to propagate |
required |
A_sq |
ndarray
|
The field modulus squared |
required |
dz |
float
|
Propagation step in m |
required |
alpha |
float
|
Losses |
required |
V |
ndarray
|
Potential |
required |
g |
float
|
Interactions |
required |
Isat |
float
|
Saturation |
required |
Source code in NLSE/kernels_cpu.py
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 |
|
nl_prop_c(A1, A_sq_1, A_sq_2, dz, alpha, V, g11, g12, Isat1, Isat2)
A fused kernel to apply real space terms Args: A1 (cp.ndarray): The field to propagate (1st component) A_sq_1 (cp.ndarray): The field modulus squared (1st component) A_sq_2 (cp.ndarray): The field modulus squared (2nd component) dz (float): Propagation step in m alpha (float): Losses V (cp.ndarray): Potential g11 (float): Intra-component interactions g12 (float): Inter-component interactions Isat1 (float): Saturation parameter of first component Isat2 (float): Saturation parameter of second component
Source code in NLSE/kernels_cpu.py
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 |
|
nl_prop_without_V(A, A_sq, dz, alpha, g, Isat)
A fused kernel to apply real space terms
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A |
ndarray
|
The field to propagate |
required |
A_sq |
ndarray
|
The field modulus squared |
required |
dz |
float
|
Propagation step in m |
required |
alpha |
float
|
Losses |
required |
g |
float
|
Interactions |
required |
Isat |
float
|
Saturation |
required |
Source code in NLSE/kernels_cpu.py
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 |
|
nl_prop_without_V_c(A1, A_sq_1, A_sq_2, dz, alpha, g11, g12, Isat1, Isat2)
A fused kernel to apply real space terms Args: A1 (cp.ndarray): The field to propagate (1st component) A_sq_1 (cp.ndarray): The field modulus squared (1st component) A_sq_2 (cp.ndarray): The field modulus squared (2nd component) dz (float): Propagation step in m alpha (float): Losses g11 (float): Intra-component interactions g12 (float): Inter-component interactions Isat1 (float): Saturation parameter of first component Isat2 (float): Saturation parameter of second component
Source code in NLSE/kernels_cpu.py
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 |
|
rabi_coupling(A1, A2, dz, omega)
Apply a Rabi coupling term. This function implements the Rabi hopping term. It exchanges density between the two components.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A1 |
ndarray
|
First field / component |
required |
A2 |
ndarray
|
Second field / component |
required |
dz |
float
|
Solver step |
required |
omega |
float
|
Rabi coupling strength |
required |
Source code in NLSE/kernels_cpu.py
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
|
square_mod(A, A_sq)
Compute the square modulus of the field
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A |
ndarray
|
The field |
required |
A_sq |
ndarray
|
The modulus squared of the field |
required |
Returns:
Type | Description |
---|---|
None
|
None |
Source code in NLSE/kernels_cpu.py
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
|
vortex(im, i, j, ii, jj, ll)
Generates a vortex of charge l at a position (i,j) on the image im.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
im |
ndarray
|
Image |
required |
i |
int
|
position row of the vortex |
required |
j |
int
|
position column of the vortex |
required |
ii |
int
|
meshgrid position row (coordinates of the image) |
required |
jj |
int
|
meshgrid position column (coordinates of the image) |
required |
ll |
int
|
vortex charge |
required |
Returns:
Type | Description |
---|---|
None
|
None |
Source code in NLSE/kernels_cpu.py
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
|
GPU (CUDA)
GPU kernels in the NLSE
package are responsible for solving the nonlinear Schrödinger equation using GPU resources.
They utilize the computational power of the graphics processing unit (GPU) to perform the necessary calculations.
These kernels use the cupy.fuse
API to just-in-time compile the array operations to
a single kernel.
The strategy here is to maximize GPU occupancy by grouping operations to a complex enough task such that we are not limited by memory bandwidth. As with the CPU kernels, the paradigm is to try and mutate arrays in place as much as possible to avoid costly memory transfers.
To this end, most of these kernels have the following signature:
@cp.fuse
def kernel(A: cp.ndarray, *args):
# do something to A
A += args[0]
A *= args[1]
nl_prop(A, A_sq, dz, alpha, V, g, Isat)
A fused kernel to apply real space terms
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A |
ndarray
|
The field to propagate |
required |
A_sq |
ndarray
|
The field modulus squared |
required |
dz |
float
|
Propagation step in m |
required |
alpha |
float
|
Losses |
required |
V |
ndarray
|
Potential |
required |
g |
float
|
Interactions |
required |
Isat |
float
|
Saturation |
required |
Source code in NLSE/kernels_gpu.py
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 |
|
nl_prop_c(A1, A_sq_1, A_sq_2, dz, alpha, V, g11, g12, Isat1, Isat2)
A fused kernel to apply real space terms Args: A1 (cp.ndarray): The field to propagate (1st component) A_sq_1 (cp.ndarray): The field modulus squared (1st component) A_sq_2 (cp.ndarray): The field modulus squared (2nd component) dz (float): Propagation step in m alpha (float): Losses V (cp.ndarray): Potential g11 (float): Intra-component interactions g12 (float): Inter-component interactions Isat1 (float): Saturation parameter of first component Isat2 (float): Saturation parameter of second component
Source code in NLSE/kernels_gpu.py
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 |
|
nl_prop_without_V(A, A_sq, dz, alpha, g, Isat)
A fused kernel to apply real space terms
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A |
ndarray
|
The field to propagate |
required |
A_sq |
ndarray
|
The field modulus squared |
required |
dz |
float
|
Propagation step in m |
required |
alpha |
float
|
Losses |
required |
g |
float
|
Interactions |
required |
Isat |
float
|
Saturation |
required |
Source code in NLSE/kernels_gpu.py
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 |
|
nl_prop_without_V_c(A1, A_sq_1, A_sq_2, dz, alpha, g11, g12, Isat1, Isat2)
A fused kernel to apply real space terms Args: A1 (cp.ndarray): The field to propagate (1st component) A_sq_1 (cp.ndarray): The field modulus squared (1st component) A_sq_2 (cp.ndarray): The field modulus squared (2nd component) dz (float): Propagation step in m alpha (float): Losses g11 (float): Intra-component interactions g12 (float): Inter-component interactions Isat1 (float): Saturation parameter of first component Isat2 (float): Saturation parameter of second component
Source code in NLSE/kernels_gpu.py
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 |
|
rabi_coupling(A1, A2, dz, omega)
Apply a Rabi coupling term. This function implements the Rabi hopping term. It exchanges density between the two components.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A1 |
ndarray
|
First field / component |
required |
A2 |
ndarray
|
Second field / component |
required |
dz |
float
|
Solver step |
required |
omega |
float
|
Rabi coupling strength |
required |
Source code in NLSE/kernels_gpu.py
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
|
square_mod(A, A_sq)
Compute the square modulus of the field
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A |
ndarray
|
The field |
required |
A_sq |
ndarray
|
The modulus squared of the field |
required |
Returns:
Type | Description |
---|---|
None
|
None |
Source code in NLSE/kernels_gpu.py
179 180 181 182 183 184 185 186 187 188 189 190 |
|
vortex_cp(im, i, j, ii, jj, ll)
Generates a vortex of charge l at a position (i,j) on the image im.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
im |
ndarray
|
Image |
required |
i |
int
|
position row of the vortex |
required |
j |
int
|
position column of the vortex |
required |
ii |
int
|
meshgrid position row (coordinates of the image) |
required |
jj |
int
|
meshgrid position column (coordinates of the image) |
required |
ll |
int
|
vortex charge |
required |
Returns:
Type | Description |
---|---|
None
|
None |
Source code in NLSE/kernels_gpu.py
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
|
OpenCL (GPU or CPU)
In order to take advantage of the modern hardware, there is experimental support for OpenCL for the NLSE
class.
The long-term goal is to use a unified interface for GPU and CPU (which is what OpenCL already does).
This uses PyOpenCL
and its array
interface to follow the same approach as the other two implementations.
Due to the limited support for OpenCL on newer hardware (mostly Macs), this might not be the winning strategy so use at your own risk ! 😇
nl_prop(A, A_sq, dz, alpha, V, g, Isat)
A fused kernel to apply real space terms
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A |
Array
|
The field to propagate |
required |
A_sq |
Array
|
The field modulus squared |
required |
dz |
float
|
Propagation step in m |
required |
alpha |
float
|
Losses |
required |
V |
Array
|
Potential |
required |
g |
float
|
Interactions |
required |
Isat |
float
|
Saturation |
required |
Source code in NLSE/kernels_cl.py
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 |
|
nl_prop_c(A1, A_sq_1, A_sq_2, dz, alpha, V, g11, g12, Isat)
A fused kernel to apply real space terms Args: A1 (cla.Array): The field to propagate (1st component) A_sq_1 (cla.Array): The field modulus squared (1st component) A_sq_2 (cla.Array): The field modulus squared (2nd component) dz (float): Propagation step in m alpha (float): Losses V (cla.Array): Potential g11 (float): Intra-component interactions g12 (float): Inter-component interactions Isat1 (float): Saturation parameter of first component Isat2 (float): Saturation parameter of second component
Source code in NLSE/kernels_cl.py
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 |
|
nl_prop_without_V(A, A_sq, dz, alpha, g, Isat)
A fused kernel to apply real space terms
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A |
Array
|
The field to propagate |
required |
A_sq |
Array
|
The field modulus squared |
required |
dz |
float
|
Propagation step in m |
required |
alpha |
float
|
Losses |
required |
g |
float
|
Interactions |
required |
Isat |
float
|
Saturation |
required |
Source code in NLSE/kernels_cl.py
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 |
|
nl_prop_without_V_c(A1, A_sq_1, A_sq_2, dz, alpha, g11, g12, Isat)
A fused kernel to apply real space terms Args: A1 (cla.Array): The field to propagate (1st component) A_sq_1 (cla.Array): The field modulus squared (1st component) A_sq_2 (cla.Array): The field modulus squared (2nd component) dz (float): Propagation step in m alpha (float): Losses g11 (float): Intra-component interactions g12 (float): Inter-component interactions Isat1 (float): Saturation parameter of first component Isat2 (float): Saturation parameter of second component
Source code in NLSE/kernels_cl.py
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 |
|
rabi_coupling(A, dz, omega)
Apply a Rabi coupling term. This function implements the Rabi hopping term. It exchanges density between the two components.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A |
Array
|
First field / component |
required |
dz |
float
|
Solver step |
required |
omega |
float
|
Rabi coupling strength |
required |
Source code in NLSE/kernels_cl.py
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
|
square_mod(A, A_sq)
Compute the square modulus of the field
Parameters:
Name | Type | Description | Default |
---|---|---|---|
A |
Array
|
The field |
required |
A_sq |
Array
|
The modulus squared of the field |
required |
Returns:
Type | Description |
---|---|
None
|
None |
Source code in NLSE/kernels_cl.py
173 174 175 176 177 178 179 180 181 182 183 |
|
vortex_cp(im, i, j, ii, jj, ll)
Generates a vortex of charge l at a position (i,j) on the image im.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
im |
ndarray
|
Image |
required |
i |
int
|
position row of the vortex |
required |
j |
int
|
position column of the vortex |
required |
ii |
int
|
meshgrid position row (coordinates of the image) |
required |
jj |
int
|
meshgrid position column (coordinates of the image) |
required |
ll |
int
|
vortex charge |
required |
Returns:
Type | Description |
---|---|
None
|
None |
Source code in NLSE/kernels_cl.py
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
|