ElectroMagneticPython 2.1.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ """Collection of different algorithms to find modes of optical waveguides.
2
+
3
+ Modesolvers:
4
+
5
+ 1. FD.
6
+ 2. FMM.
7
+
8
+
9
+ """
10
+ __all__ = ["FD", "FMM", "geometries"]
11
+ __author__ = "Lorenzo Bolla"
12
+
13
+ from . import FD, FMM, geometries
@@ -0,0 +1,231 @@
1
+ """Geometries.
2
+
3
+ """
4
+ import numpy
5
+ import pylab
6
+
7
+ from EMpy.modesolvers.interface import interface_matrix
8
+
9
+
10
+ def S2T(S):
11
+ dim = S.shape[0] / 2.0
12
+ s11 = S[:dim, :dim]
13
+ s22 = S[dim:, dim:]
14
+ s12 = S[:dim, dim:]
15
+ s21 = S[dim:, :dim]
16
+ T = numpy.zeros_like(S)
17
+ s12_1 = numpy.linalg.inv(s12)
18
+ T[:dim, :dim] = s21 - numpy.dot(numpy.dot(s22, s12_1), s11)
19
+ T[dim:, dim:] = s12_1
20
+ T[:dim, dim:] = numpy.dot(s22, s12_1)
21
+ T[dim:, :dim] = -numpy.dot(s12_1, s11)
22
+ return T
23
+
24
+
25
+ def T2S(T):
26
+ dim = T.shape[0] / 2.0
27
+ t11 = T[:dim, :dim]
28
+ t22 = T[dim:, dim:]
29
+ t12 = T[:dim, dim:]
30
+ t21 = T[dim:, :dim]
31
+ S = numpy.zeros_like(T)
32
+ t22_1 = numpy.linalg.inv(t22)
33
+ S[:dim, :dim] = -numpy.dot(t22_1, t21)
34
+ S[dim:, dim:] = numpy.dot(t12, t22_1)
35
+ S[:dim, dim:] = t22_1
36
+ S[dim:, :dim] = t11 - numpy.dot(numpy.dot(t12, t22_1), t21)
37
+ return S
38
+
39
+
40
+ class SWG:
41
+
42
+ # def __init__(self, cs, solver, length, inputLHS=None, inputRHS=None):
43
+ def __init__(self, solver, length, inputLHS=None, inputRHS=None):
44
+ # self.cs = cs
45
+ self.solver = solver
46
+ self.length = length
47
+ self.build_matrix()
48
+ self.compute_output(inputLHS, inputRHS)
49
+
50
+ def compute_output(self, inputLHS=None, inputRHS=None):
51
+ if inputLHS is None:
52
+ self.inputLHS = numpy.zeros(self.solver.nmodes)
53
+ self.inputLHS[0] = 1.0
54
+ else:
55
+ self.inputLHS = inputLHS
56
+ if inputRHS is None:
57
+ self.inputRHS = numpy.zeros(self.solver.nmodes)
58
+ else:
59
+ self.inputRHS = inputRHS
60
+ input = numpy.r_[self.inputLHS, self.inputRHS]
61
+ output = numpy.dot(self.S, input)
62
+ self.outputLHS = output[: self.solver.nmodes]
63
+ self.outputRHS = output[self.solver.nmodes :]
64
+
65
+ def build_matrix(self):
66
+ neffs = numpy.array([m.neff for m in self.solver.modes])
67
+ betas = 2 * numpy.pi / self.solver.wl * neffs
68
+ neigs = self.solver.nmodes
69
+ T = numpy.zeros((2 * neigs, 2 * neigs), dtype=complex)
70
+ T[:neigs, :neigs] = numpy.diag(numpy.exp(1j * betas * self.length))
71
+ T[neigs:, neigs:] = numpy.diag(numpy.exp(-1j * numpy.conj(betas) * self.length))
72
+ self.T = T
73
+ self.S = T2S(self.T)
74
+
75
+ def plot(self, sumx=1, nxy=100, nz=100, z0=0):
76
+ if sumx is None: # sum in y
77
+ x = self.solver.modes[0].get_y(nxy)
78
+ axis = 0
79
+ else: # sum in x
80
+ x = self.solver.modes[0].get_x(nxy)
81
+ axis = 1
82
+ z = numpy.linspace(0, self.length, nz)
83
+ const_z = numpy.ones_like(z)
84
+ f = numpy.zeros((len(x), len(z)), dtype=complex)
85
+ for im, (coeffLHS, coeffRHS) in enumerate(zip(self.inputLHS, self.inputRHS)):
86
+ m = self.solver.modes[im]
87
+ # beta = 2 * numpy.pi / self.solver.wl * m.neff
88
+ tmp = numpy.sum(m.intensity(x, x), axis=axis)
89
+ f += (
90
+ numpy.abs(coeffLHS) ** 2 * tmp[:, numpy.newaxis] * const_z
91
+ + numpy.abs(coeffRHS) ** 2 * tmp[:, numpy.newaxis] * const_z
92
+ )
93
+ pylab.hot()
94
+ pylab.contourf(x, z0 + z, numpy.abs(f).T, 16)
95
+
96
+
97
+ class SimpleJoint:
98
+
99
+ # def __init__(self, cs1, cs2, solver1, solver2, inputLHS=None, inputRHS=None):
100
+ def __init__(self, solver1, solver2, inputLHS=None, inputRHS=None):
101
+ # self.cs1 = cs1
102
+ self.solver1 = solver1
103
+ # self.cs2 = cs2
104
+ self.solver2 = solver2
105
+ self.length = 0.0
106
+ self.build_matrix()
107
+ self.compute_output(inputLHS, inputRHS)
108
+
109
+ def compute_output(self, inputLHS=None, inputRHS=None):
110
+ if inputLHS is None:
111
+ self.inputLHS = numpy.zeros(self.solver1.nmodes)
112
+ self.inputLHS[0] = 1.0
113
+ else:
114
+ self.inputLHS = inputLHS
115
+ if inputRHS is None:
116
+ self.inputRHS = numpy.zeros(self.solver1.nmodes)
117
+ else:
118
+ self.inputRHS = inputRHS
119
+ input = numpy.r_[self.inputLHS, self.inputRHS]
120
+ output = numpy.dot(self.S, input)
121
+ self.outputLHS = output[: self.solver1.nmodes]
122
+ self.outputRHS = output[self.solver1.nmodes :]
123
+
124
+ def build_matrix(self):
125
+ O11, O22, O12, O21 = interface_matrix(self.solver1, self.solver2)
126
+ neffA = numpy.array([m.neff for m in self.solver1.modes])
127
+ neffB = numpy.array([m.neff for m in self.solver2.modes])
128
+ betaA = 2 * numpy.pi / self.solver1.wl * neffA
129
+ betaB = 2 * numpy.pi / self.solver1.wl * neffB
130
+
131
+ BetaA = numpy.diag(betaA)
132
+ BetaB = numpy.diag(betaB)
133
+
134
+ # MRA1 = numpy.dot(O12, BetaA + BetaB)
135
+ # MRA2 = numpy.dot(O12, BetaA - BetaB)
136
+ # MRA = numpy.dot(numpy.linalg.inv(MRA1), MRA2)
137
+ # S11 = MRA
138
+ #
139
+ # MRB1 = numpy.dot(O21, BetaA + BetaB)
140
+ # MRB2 = numpy.dot(O21, BetaB - BetaA)
141
+ # MRB = numpy.dot(numpy.linalg.inv(MRB1), MRB2)
142
+ # S22 = MRB
143
+ #
144
+ # MTAB1 = numpy.dot(O22, BetaA + BetaB)
145
+ # MTAB2 = numpy.dot(O12, 2. * BetaA)
146
+ # MTAB = numpy.dot(numpy.linalg.inv(MTAB1), MTAB2)
147
+ # S12 = MTAB
148
+ #
149
+ # MTBA1 = numpy.dot(O11, BetaA + BetaB)
150
+ # MTBA2 = numpy.dot(O21, 2. * BetaB)
151
+ # MTBA = numpy.dot(numpy.linalg.inv(MTBA1), MTBA2)
152
+ # S21 = MTBA
153
+
154
+ SUM = numpy.dot(BetaA, O21) + numpy.dot(O21, BetaB)
155
+ DIF = numpy.dot(BetaA, O21) - numpy.dot(O21, BetaB)
156
+ A = 0.5 * numpy.dot(numpy.linalg.inv(BetaA), SUM)
157
+ B = 0.5 * numpy.dot(numpy.linalg.inv(BetaA), DIF)
158
+ A_1 = numpy.linalg.inv(A)
159
+ S11 = numpy.dot(B, A_1)
160
+ S12 = A - numpy.dot(numpy.dot(B, A_1), B)
161
+ S21 = A_1
162
+ S22 = -numpy.dot(A_1, B)
163
+
164
+ dim = O11.shape[0]
165
+
166
+ S = numpy.zeros((2 * dim, 2 * dim), dtype=complex)
167
+ S[:dim, :dim] = S11
168
+ S[dim:, dim:] = S22
169
+ S[:dim, dim:] = S12
170
+ S[dim:, :dim] = S21
171
+
172
+ self.S = S
173
+ self.T = S2T(self.S)
174
+
175
+ def plot(self, sumx=1, nxy=100, nz=100, z0=0):
176
+ pass
177
+
178
+
179
+ class GenericDevice:
180
+ def __init__(self, devlist, inputLHS=None, inputRHS=None):
181
+ self.devlist = devlist
182
+ self.build_matrix()
183
+ self.compute_output(inputLHS, inputRHS)
184
+
185
+ def compute_output(self, inputLHS=None, inputRHS=None):
186
+ if inputLHS is None:
187
+ self.inputLHS = numpy.zeros_like(self.devlist[0].inputLHS)
188
+ self.inputLHS[0] = 1.0
189
+ else:
190
+ self.inputLHS = inputLHS
191
+ if inputRHS is None:
192
+ self.inputRHS = numpy.zeros_like(self.devlist[0].inputRHS)
193
+ else:
194
+ self.inputRHS = inputRHS
195
+ input = numpy.r_[self.inputLHS, self.inputRHS]
196
+ output = numpy.dot(self.S, input)
197
+ self.outputLHS = output[: len(self.inputLHS)]
198
+ self.outputRHS = output[len(self.inputLHS) :]
199
+ # compute for each device
200
+ inputLHS = self.inputLHS
201
+ outputLHS = self.outputLHS
202
+ dim = len(inputLHS)
203
+ for d in self.devlist:
204
+ d.inputLHS = inputLHS
205
+ d.outputLHS = outputLHS
206
+ LHS = numpy.r_[inputLHS, outputLHS]
207
+ RHS = numpy.dot(d.T, LHS)
208
+ d.outputRHS = RHS[:dim]
209
+ d.inputRHS = RHS[dim:]
210
+ inputLHS = d.outputRHS
211
+ outputLHS = d.inputRHS
212
+
213
+ def build_matrix(self):
214
+ dim = self.devlist[0].solver.nmodes
215
+ T = numpy.eye(2 * dim, dtype=complex)
216
+ for d in self.devlist:
217
+ T = numpy.dot(d.T, T)
218
+ self.T = T
219
+ self.S = T2S(self.T)
220
+
221
+ def plot(self, sumx=1, nxy=100, nz=100, z0=0):
222
+ z = z0
223
+ for d in self.devlist:
224
+ d.plot(sumx, nxy, nz, z0=z)
225
+ z += d.length
226
+ pylab.ylabel("z")
227
+ if sumx is None:
228
+ pylab.xlabel("y")
229
+ else:
230
+ pylab.xlabel("x")
231
+ pylab.axis("tight")
@@ -0,0 +1,71 @@
1
+ import numpy
2
+
3
+
4
+ class ModeSolver:
5
+ def solve(self, *argv):
6
+ raise NotImplementedError()
7
+
8
+
9
+ class Mode:
10
+ def get_x(self, x=None, y=None):
11
+ raise NotImplementedError()
12
+
13
+ def get_y(self, x=None, y=None):
14
+ raise NotImplementedError()
15
+
16
+ def intensity(self, x=None, y=None):
17
+ raise NotImplementedError()
18
+
19
+ def TEfrac(self, x=None, y=None):
20
+ raise NotImplementedError()
21
+
22
+ def overlap(self, x=None, y=None):
23
+ raise NotImplementedError()
24
+
25
+ def get_fields_for_FDTD(self, x, y):
26
+ raise NotImplementedError()
27
+
28
+ def save_for_FDTD(self, mode_id="", x=None, y=None):
29
+ """Save mode's fields on a staggered grid."""
30
+ Ex_FDTD, Ey_FDTD, Ez_FDTD, Hx_FDTD, Hy_FDTD, Hz_FDTD = self.get_fields_for_FDTD(
31
+ x, y
32
+ )
33
+ Ex_FDTD.real.T.tofile("ex" + mode_id + ".dat", sep=" ")
34
+ Ex_FDTD.imag.T.tofile("iex" + mode_id + ".dat", sep=" ")
35
+ Ey_FDTD.real.T.tofile("ey" + mode_id + ".dat", sep=" ")
36
+ Ey_FDTD.imag.T.tofile("iey" + mode_id + ".dat", sep=" ")
37
+ Ez_FDTD.real.T.tofile("ez" + mode_id + ".dat", sep=" ")
38
+ Ez_FDTD.imag.T.tofile("iez" + mode_id + ".dat", sep=" ")
39
+ Hx_FDTD.real.T.tofile("hx" + mode_id + ".dat", sep=" ")
40
+ Hx_FDTD.imag.T.tofile("ihx" + mode_id + ".dat", sep=" ")
41
+ Hy_FDTD.real.T.tofile("hy" + mode_id + ".dat", sep=" ")
42
+ Hy_FDTD.imag.T.tofile("ihy" + mode_id + ".dat", sep=" ")
43
+ Hz_FDTD.real.T.tofile("hz" + mode_id + ".dat", sep=" ")
44
+ Hz_FDTD.imag.T.tofile("ihz" + mode_id + ".dat", sep=" ")
45
+
46
+ def plot(self, x=None, y=None):
47
+ raise NotImplementedError()
48
+
49
+
50
+ def overlap(m1, m2, x=None, y=None):
51
+ return m1.overlap(m2, x, y)
52
+
53
+
54
+ def interface_matrix(solver1, solver2, x=None, y=None):
55
+
56
+ neigs = solver1.nmodes
57
+
58
+ O11 = numpy.zeros((neigs, neigs), dtype=complex)
59
+ O22 = numpy.zeros((neigs, neigs), dtype=complex)
60
+ O12 = numpy.zeros((neigs, neigs), dtype=complex)
61
+ O21 = numpy.zeros((neigs, neigs), dtype=complex)
62
+
63
+ for i in range(neigs):
64
+ for j in range(neigs):
65
+
66
+ O11[i, j] = overlap(solver1.modes[i], solver1.modes[j], x, y)
67
+ O22[i, j] = overlap(solver2.modes[i], solver2.modes[j], x, y)
68
+ O12[i, j] = overlap(solver1.modes[i], solver2.modes[j], x, y)
69
+ O21[i, j] = overlap(solver2.modes[i], solver1.modes[j], x, y)
70
+
71
+ return (O11, O22, O12, O21)
EMpy/scattering.py ADDED
@@ -0,0 +1,236 @@
1
+ import numpy
2
+ import EMpy
3
+
4
+ __author__ = "Julien Hillairet"
5
+
6
+
7
+ class Field:
8
+ """Class to describe an electromagnetic field.
9
+
10
+ A EM field is a vector field which is the combination of an electric field E and a magnetic field H.
11
+ These fields are defined on some space point r
12
+
13
+ @ivar E: Electric vector on point M{r} in the cartesian coordinate system M{(Ex,Ey,Ez)}
14
+ @type E: 2d numpy.ndarray of shape (3,N)
15
+ @ivar H: Magnetic vector on point M{r} in the cartesian coordinate system M{(Mx,My,Mz)}
16
+ @type H: 2d numpy.ndarray of shape (3,N)
17
+ @ivar r: Position vector in cartesian coordinates M{(x,y,z)}
18
+ @type r: 2d numpy.ndarray of shape (3,N)
19
+
20
+ """
21
+
22
+ def __init__(
23
+ self, E=numpy.zeros((3, 1)), H=numpy.zeros((3, 1)), r=numpy.zeros((3, 1))
24
+ ):
25
+ """Initialize the Field object with an Electric, Magnetic and Position vectors."""
26
+ self.E = E
27
+ self.H = H
28
+ self.r = r
29
+
30
+
31
+ """
32
+ ##############################################################
33
+ utils functions for field manipulations
34
+ ##############################################################
35
+ """
36
+
37
+
38
+ def stack(X, Y, Z):
39
+ """Stack 3 vectors of different lengths into one vector.
40
+
41
+ stack 3 vectors of different length to one vector of type
42
+ M{P(n) = [x(n); y(n); z(n)]} with M{n=[1:Nx*Ny*Nz]}
43
+
44
+ Examples
45
+ ========
46
+ >>> import numpy
47
+ >>> X = numpy.arange(4); Y = numpy.arange(3); Z = numpy.arange(2)
48
+ >>> S = field.stack(X,Y,Z)
49
+ >>> print S
50
+ [[ 0. 0. 0. 0. 0. 0. 1. 1. 1. 1. 1. 1. 2. 2. 2. 2. 2. 2. 3. 3. 3. 3. 3. 3.]
51
+ [ 0. 0. 1. 1. 2. 2. 0. 0. 1. 1. 2. 2. 0. 0. 1. 1. 2. 2. 0. 0. 1. 1. 2. 2.]
52
+ [ 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1.]]
53
+
54
+ Checking the size of the returned array
55
+ >>> numpy.size(S,axis=1) == numpy.size(X,axis=0)*numpy.size(Y,axis=0)*numpy.size(Z,axis=0)
56
+ True
57
+
58
+ @param X: first vector.of length Nx
59
+ @type X: numpy.ndarray of shape (1, Nx).
60
+ @param Y: second vector.of length Ny
61
+ @type Y: numpy.ndarray of shape (1, Ny).
62
+ @param Z: third vector.of length Nz
63
+ @type Z: numpy.ndarray of shape (1, Nz).
64
+
65
+ @return: stacked array.
66
+ @rtype: numpy.ndarray of shape (3, Nx*Ny*Nz)
67
+
68
+ """
69
+ Nx = numpy.size(X, axis=0)
70
+ Ny = numpy.size(Y, axis=0)
71
+ Nz = numpy.size(Z, axis=0)
72
+
73
+ XX = numpy.reshape(numpy.transpose(numpy.ones((Ny * Nz, 1)) * X), (1, Ny * Nz * Nx))
74
+ YY = numpy.tile(
75
+ numpy.reshape(numpy.transpose(numpy.ones((Nz, 1)) * Y), (1, Ny * Nz)), (1, Nx)
76
+ )
77
+ ZZ = numpy.tile(Z, (1, Nx * Ny))
78
+
79
+ return numpy.vstack((XX, YY, ZZ))
80
+
81
+
82
+ def matlab_dot(a, b):
83
+ """
84
+ "classical" dot product (as defined in octave or matlab)
85
+
86
+ Example
87
+ =======
88
+ >>> a=numpy.array([1,2,3]).repeat(6).reshape((3,6))
89
+ >>> print a
90
+ [[1 1 1 1 1 1]
91
+ [2 2 2 2 2 2]
92
+ [3 3 3 3 3 3]]
93
+ >>> field.matlab_dot(a,a)
94
+ array([14, 14, 14, 14, 14, 14])
95
+
96
+ where M{14=1*1+2*2+3*3}
97
+
98
+ @param a: first vector of length N
99
+ @type a: numpy.ndarray of shape (M,N)
100
+ @param b: second vector of length N
101
+ @type b: numpy.ndarray of shape (M,N)
102
+
103
+ @return: "classical" dot product between M{a} and M{b}
104
+ @rtype: numpy.ndarray of shape (1,N)
105
+
106
+ """
107
+ return numpy.sum(a * b, axis=0)
108
+
109
+
110
+ """
111
+ ##########################################
112
+ Common functions for calculating EM fields
113
+ ##########################################
114
+ """
115
+
116
+
117
+ def currentsScatteringKottler(P, J, M, Q, dS, f, epsr=1):
118
+ """
119
+ Compute the scattered fields on some point M{P} in cartesian coordinates M{P(Px,Py,Pz)}
120
+ by electric (and even magnetic) currents densities M{J}, M{M}
121
+ defined on a surface M{Q(Qx,Qy,Qz)}.
122
+ M{dS} corresponds to the surface element M{dS} of surface M{Q}
123
+
124
+ TODO:
125
+ - Maybe an option to compute only main expression in farfield
126
+ - Optimisation ? (At the present time, python version is slower than the matlab code)
127
+
128
+ @param P: observation points M{P(Px,Py,Pz)}.
129
+ @type P: numpy.ndarray of shape (3,NbP)
130
+ @param J: electric current density on M{Q}
131
+ @type J: numpy.ndarray of shape (3,NbQ)
132
+ @param M: magnetic current density on M{Q}
133
+ @type M: numpy.ndarray of shape (3,NbQ)
134
+ @param Q: radiating (surface) points M{Q(Qx,Qy,Qz)}.
135
+ @type Q: numpy.ndarray of shape (3,NbQ)
136
+ @param dS: surface elements of the radiating surface
137
+ @type dS: numpy.ndarray of shape (1,NbQ)
138
+ @param f: frequency
139
+ @type f: float
140
+ @param epsr: relative permittivity (dielectric constant) (defaut : 1, vacuum)
141
+ @type epsr: float
142
+
143
+ @return: EM Field on M{P}
144
+ @rtype: L{Field}
145
+
146
+
147
+ """
148
+ # test if the parameters size are correct
149
+ if (
150
+ numpy.size(P, axis=0) != 3
151
+ or numpy.size(Q, axis=0) != 3
152
+ or numpy.size(J, axis=0) != 3
153
+ or numpy.size(M, axis=0) != 3
154
+ ):
155
+ EMpy.utils.warning(
156
+ "Bad parameters size : number of rows must be 3 for vectors P,Q,J,M"
157
+ )
158
+
159
+ if (
160
+ not numpy.size(Q, axis=1)
161
+ == numpy.size(J, axis=1)
162
+ == numpy.size(M, axis=1)
163
+ == numpy.size(dS, axis=1)
164
+ ):
165
+ EMpy.utils.warning(
166
+ "Bad parameters size : number of columns between Q,J,M and dS must be equal"
167
+ )
168
+
169
+ lambda0 = EMpy.constants.c / f
170
+ lambdam = lambda0 / numpy.sqrt(epsr)
171
+ # k0 = 2*numpy.pi/lambda0
172
+ km = 2 * numpy.pi / lambdam
173
+ Z0 = 120 * numpy.pi
174
+ NbP = numpy.size(P, axis=1)
175
+ NbQ = numpy.size(Q, axis=1)
176
+
177
+ # preallocation
178
+ EMF_P = Field(
179
+ numpy.zeros((3, NbP), dtype=complex), numpy.zeros((3, NbP), dtype=complex), P
180
+ )
181
+
182
+ # for all observation point
183
+ # PB = EMpy.utils.ProgressBar()
184
+ for ind in numpy.arange(NbP):
185
+ # distance between scattering and observation point
186
+ QP = P[:, ind].reshape((3, 1)) * numpy.ones((1, NbQ)) - Q
187
+ r = numpy.sqrt(numpy.sum(QP**2, axis=0))
188
+ # unit vector
189
+ r1 = QP / r
190
+ # integrand expression shorcuts
191
+ kmr = km * r
192
+ kmr_1 = 1 / kmr
193
+ kmr_2 = kmr_1**2
194
+ aa = 1 - 1j * kmr_1 - kmr_2
195
+ bb = -1 + 3 * 1j * kmr_1 + 3 * kmr_2
196
+ cc = 1 - 1j * kmr_1
197
+ # scalar product
198
+ r1dotJ = matlab_dot(r1, J)
199
+ r1dotM = matlab_dot(r1, -M)
200
+ # Kottler EM fields
201
+ EMF_P.E[:, ind] = (
202
+ km
203
+ / (4 * numpy.pi * 1j)
204
+ * numpy.sum(
205
+ (
206
+ Z0
207
+ / numpy.sqrt(epsr)
208
+ * (aa * J + bb * (r1dotJ * numpy.ones((3, 1))) * r1)
209
+ + cc * numpy.cross(r1, -M, axis=0)
210
+ )
211
+ * numpy.exp(-1j * km * r)
212
+ / r
213
+ * dS,
214
+ axis=1,
215
+ )
216
+ )
217
+ EMF_P.H[:, ind] = (
218
+ -km
219
+ / (4 * numpy.pi * 1j)
220
+ * numpy.sum(
221
+ (
222
+ numpy.sqrt(epsr)
223
+ / Z0
224
+ * (-aa * M + bb * (r1dotM * numpy.ones((3, 1))) * r1)
225
+ - cc * numpy.cross(r1, J, axis=0)
226
+ )
227
+ * numpy.exp(-1j * km * r)
228
+ / r
229
+ * dS,
230
+ axis=1,
231
+ )
232
+ )
233
+ # waitbar update
234
+ # PB.update((ind+1)*100.0/NbP)
235
+
236
+ return EMF_P