cfsem 2.0.4__tar.gz → 2.1.0__tar.gz
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.
- {cfsem-2.0.4 → cfsem-2.1.0}/CHANGELOG.md +11 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/Cargo.lock +2 -2
- {cfsem-2.0.4 → cfsem-2.1.0}/Cargo.toml +1 -1
- {cfsem-2.0.4 → cfsem-2.1.0}/PKG-INFO +4 -4
- {cfsem-2.0.4 → cfsem-2.1.0}/README.md +1 -1
- {cfsem-2.0.4 → cfsem-2.1.0}/cfsem/__init__.py +16 -4
- {cfsem-2.0.4 → cfsem-2.1.0}/cfsem/bindings.py +107 -21
- cfsem-2.1.0/docs/assets/logo.svg +1 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/python/flux_density.md +1 -3
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/python/inductance.md +2 -0
- cfsem-2.1.0/docs/python/vector_potential.md +5 -0
- cfsem-2.1.0/docs/stylesheets/extra.css +4 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/mkdocs.yml +9 -1
- {cfsem-2.0.4 → cfsem-2.1.0}/pyproject.toml +3 -3
- {cfsem-2.0.4 → cfsem-2.1.0}/src/lib.rs +159 -9
- {cfsem-2.0.4 → cfsem-2.1.0}/test/test_electromagnetics.py +104 -21
- {cfsem-2.0.4 → cfsem-2.1.0}/.cargo/config.toml +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/.github/workflows/CI.yml +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/.github/workflows/actions.yml +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/.gitignore +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/.readthedocs.yml +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/CONTRIBUTING.md +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/LICENSE +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/build_docs.sh +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/cfsem/py.typed +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/cfsem/types.py +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/index.md +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/javascripts/mathjax.js +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/python/example_outputs/.placeholder +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/python/examples.md +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/python/filament.md +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/python/grad_shafranov.md +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/python/math.md +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/python/types.md +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/docs/requirements.txt +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/examples/helmholtz.py +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/examples/inductance.py +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/test/__init__.py +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/test/test_examples.py +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/test/test_filaments.py +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/test/test_funcs.py +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/test/test_gradshafranov.py +0 -0
- {cfsem-2.0.4 → cfsem-2.1.0}/test/test_math.py +0 -0
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.1.0 2024-08-27
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
* Add vector potential calcs for linear and circular filaments
|
|
8
|
+
* Add parallel options for circular-filament calcs
|
|
9
|
+
* Add parametrization of unit tests over parallel and serial variants
|
|
10
|
+
* Add optional parallel flags to functions that use functions with new parallel options
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
3
14
|
## 2.0.4 2024-07-10
|
|
4
15
|
|
|
5
16
|
### Changed
|
|
@@ -46,9 +46,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
|
46
46
|
|
|
47
47
|
[[package]]
|
|
48
48
|
name = "cfsem"
|
|
49
|
-
version = "1.
|
|
49
|
+
version = "1.1.0"
|
|
50
50
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
51
|
-
checksum = "
|
|
51
|
+
checksum = "2b3e27e61569347c86debb5a8032a62c7acb3b6da51d14f68dd948cf7625dd79"
|
|
52
52
|
dependencies = [
|
|
53
53
|
"nalgebra",
|
|
54
54
|
"rayon",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: cfsem
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
7
7
|
Requires-Dist: numpy >=2
|
|
8
|
-
Requires-Dist: interpn >=0.2.
|
|
8
|
+
Requires-Dist: interpn >=0.2.3
|
|
9
9
|
Requires-Dist: pytest >=7.1.3 ; extra == 'dev'
|
|
10
10
|
Requires-Dist: coverage >=6.5.0 ; extra == 'dev'
|
|
11
|
-
Requires-Dist: ruff >=0.
|
|
11
|
+
Requires-Dist: ruff >=0.6.2 ; extra == 'dev'
|
|
12
12
|
Requires-Dist: pyright >=1.1.331 ; extra == 'dev'
|
|
13
13
|
Requires-Dist: scipy >=1.8 ; extra == 'dev'
|
|
14
14
|
Requires-Dist: mkdocs >=1.6.0 ; extra == 'dev'
|
|
@@ -25,7 +25,7 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
|
25
25
|
|
|
26
26
|
# cfsem
|
|
27
27
|
|
|
28
|
-
[Docs - Rust](https://docs.rs/cfsem) | [Docs - Python](https://cfsem.readthedocs.io/)
|
|
28
|
+
[Docs - Rust](https://docs.rs/cfsem) | [Docs - Python](https://cfsem-py.readthedocs.io/)
|
|
29
29
|
|
|
30
30
|
Quasi-steady electromagnetics including filamentized approximations, Biot-Savart, and Grad-Shafranov.
|
|
31
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# cfsem
|
|
2
2
|
|
|
3
|
-
[Docs - Rust](https://docs.rs/cfsem) | [Docs - Python](https://cfsem.readthedocs.io/)
|
|
3
|
+
[Docs - Rust](https://docs.rs/cfsem) | [Docs - Python](https://cfsem-py.readthedocs.io/)
|
|
4
4
|
|
|
5
5
|
Quasi-steady electromagnetics including filamentized approximations, Biot-Savart, and Grad-Shafranov.
|
|
6
6
|
|
|
@@ -9,6 +9,7 @@ from cfsem.types import Array3xN
|
|
|
9
9
|
|
|
10
10
|
from cfsem.bindings import (
|
|
11
11
|
flux_circular_filament,
|
|
12
|
+
flux_density_linear_filament,
|
|
12
13
|
flux_density_biot_savart,
|
|
13
14
|
flux_density_circular_filament,
|
|
14
15
|
gs_operator_order2,
|
|
@@ -16,6 +17,8 @@ from cfsem.bindings import (
|
|
|
16
17
|
inductance_piecewise_linear_filaments,
|
|
17
18
|
filament_helix_path,
|
|
18
19
|
rotate_filaments_about_path,
|
|
20
|
+
vector_potential_linear_filament,
|
|
21
|
+
vector_potential_circular_filament,
|
|
19
22
|
)
|
|
20
23
|
|
|
21
24
|
from ._cfsem import ellipe, ellipk
|
|
@@ -29,6 +32,7 @@ https://www.physics.nist.gov/cuu/pdf/wall_2018.pdf .
|
|
|
29
32
|
__all__ = [
|
|
30
33
|
"flux_circular_filament",
|
|
31
34
|
"flux_density_biot_savart",
|
|
35
|
+
"flux_density_linear_filament",
|
|
32
36
|
"flux_density_circular_filament",
|
|
33
37
|
"gs_operator_order2",
|
|
34
38
|
"gs_operator_order4",
|
|
@@ -47,6 +51,8 @@ __all__ = [
|
|
|
47
51
|
"ellipe",
|
|
48
52
|
"ellipk",
|
|
49
53
|
"rotate_filaments_about_path",
|
|
54
|
+
"vector_potential_linear_filament",
|
|
55
|
+
"vector_potential_circular_filament",
|
|
50
56
|
]
|
|
51
57
|
|
|
52
58
|
|
|
@@ -240,7 +246,9 @@ def self_inductance_lyle6(r: float, dr: float, dz: float, n: float) -> float:
|
|
|
240
246
|
return self_inductance # [H]
|
|
241
247
|
|
|
242
248
|
|
|
243
|
-
def mutual_inductance_of_circular_filaments(
|
|
249
|
+
def mutual_inductance_of_circular_filaments(
|
|
250
|
+
rzn1: NDArray, rzn2: NDArray, par: bool = True
|
|
251
|
+
) -> float:
|
|
244
252
|
"""
|
|
245
253
|
Analytic mutual inductance between a pair of ideal cylindrically-symmetric coaxial filaments.
|
|
246
254
|
|
|
@@ -251,19 +259,22 @@ def mutual_inductance_of_circular_filaments(rzn1: NDArray, rzn2: NDArray) -> flo
|
|
|
251
259
|
Args:
|
|
252
260
|
rzn1 (array): 3x1 array (r [m], z [m], n []) coordinates and number of turns
|
|
253
261
|
rzn2 (array): 3x1 array (r [m], z [m], n []) coordinates and number of turns
|
|
262
|
+
par: Whether to use CPU parallelism
|
|
254
263
|
|
|
255
264
|
Returns:
|
|
256
265
|
float: [H] mutual inductance
|
|
257
266
|
"""
|
|
258
267
|
|
|
259
268
|
m = mutual_inductance_of_cylindrical_coils(
|
|
260
|
-
rzn1.reshape((3, 1)), rzn2.reshape((3, 1))
|
|
269
|
+
rzn1.reshape((3, 1)), rzn2.reshape((3, 1)), par
|
|
261
270
|
)
|
|
262
271
|
|
|
263
272
|
return m # [H]
|
|
264
273
|
|
|
265
274
|
|
|
266
|
-
def mutual_inductance_of_cylindrical_coils(
|
|
275
|
+
def mutual_inductance_of_cylindrical_coils(
|
|
276
|
+
f1: NDArray, f2: NDArray, par: bool = True
|
|
277
|
+
) -> float:
|
|
267
278
|
"""
|
|
268
279
|
Analytical mutual inductance between two coaxial collections of ideal filaments.
|
|
269
280
|
|
|
@@ -274,6 +285,7 @@ def mutual_inductance_of_cylindrical_coils(f1: NDArray, f2: NDArray) -> float:
|
|
|
274
285
|
Args:
|
|
275
286
|
f1: 3 x N array of filament definitions like (r [m], z [m], n [])
|
|
276
287
|
f2: 3 x N array of filament definitions like (r [m], z [m], n [])
|
|
288
|
+
par: Whether to use CPU parallelism
|
|
277
289
|
|
|
278
290
|
Returns:
|
|
279
291
|
[H] mutual inductance of the two discretized coils
|
|
@@ -284,7 +296,7 @@ def mutual_inductance_of_cylindrical_coils(f1: NDArray, f2: NDArray) -> float:
|
|
|
284
296
|
# Using n2 as the current per filament is equivalent to examining a 1A reference current,
|
|
285
297
|
# which gives us the flux per amp (inductance)
|
|
286
298
|
m = np.sum(
|
|
287
|
-
n1 * flux_circular_filament(n2, r2, z2, r1, z1)
|
|
299
|
+
n1 * flux_circular_filament(n2, r2, z2, r1, z1, par)
|
|
288
300
|
) # [H] total mutual inductance
|
|
289
301
|
|
|
290
302
|
return m # [H]
|
|
@@ -11,7 +11,7 @@ from numpy import ascontiguousarray, float64, zeros_like
|
|
|
11
11
|
from numpy.typing import NDArray
|
|
12
12
|
|
|
13
13
|
from ._cfsem import flux_circular_filament as em_flux_circular_filament
|
|
14
|
-
from ._cfsem import
|
|
14
|
+
from ._cfsem import flux_density_linear_filament as em_flux_density_linear_filament
|
|
15
15
|
from ._cfsem import flux_density_circular_filament as em_flux_density_circular_filament
|
|
16
16
|
from ._cfsem import gs_operator_order2 as em_gs_operator_order2
|
|
17
17
|
from ._cfsem import gs_operator_order4 as em_gs_operator_order4
|
|
@@ -20,6 +20,12 @@ from ._cfsem import (
|
|
|
20
20
|
)
|
|
21
21
|
from ._cfsem import filament_helix_path as em_filament_helix_path
|
|
22
22
|
from ._cfsem import rotate_filaments_about_path as em_rotate_filaments_about_path
|
|
23
|
+
from ._cfsem import (
|
|
24
|
+
vector_potential_circular_filament as em_vector_potential_circular_filament,
|
|
25
|
+
)
|
|
26
|
+
from ._cfsem import (
|
|
27
|
+
vector_potential_linear_filament as em_vector_potential_linear_filament,
|
|
28
|
+
)
|
|
23
29
|
|
|
24
30
|
|
|
25
31
|
def flux_circular_filament(
|
|
@@ -28,6 +34,7 @@ def flux_circular_filament(
|
|
|
28
34
|
zfil: NDArray[float64],
|
|
29
35
|
rprime: NDArray[float64],
|
|
30
36
|
zprime: NDArray[float64],
|
|
37
|
+
par: bool = True,
|
|
31
38
|
) -> NDArray[float64]:
|
|
32
39
|
"""
|
|
33
40
|
Flux contributions from some circular filaments to some observation points,
|
|
@@ -37,17 +44,55 @@ def flux_circular_filament(
|
|
|
37
44
|
(`rprime`, `zprime`) observation location with $\\hat{n}$ oriented parallel to the z-axis.
|
|
38
45
|
|
|
39
46
|
A convenient interpretation of the flux is as the mutual inductance
|
|
40
|
-
|
|
47
|
+
between a circular filament at (`rfil`, `zfil`) and a second circular
|
|
41
48
|
filament at (`rprime`, `zprime`); this can be used to get the mutual inductance
|
|
42
|
-
between two filamentized coils as the sum of
|
|
49
|
+
between two filamentized coils as the sum of flux contributions between each coil's filaments.
|
|
43
50
|
Because mutual inductance is reflexive, the order of the coils can be reversed and
|
|
44
51
|
the same result is obtained.
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
Args:
|
|
54
|
+
ifil: [A] filament current
|
|
55
|
+
rfil: [m] filament R-coord
|
|
56
|
+
zfil: [m] filament Z-coord
|
|
57
|
+
rprime: [m] Observation point R-coord
|
|
58
|
+
zprime: [m] Observation point Z-coord
|
|
59
|
+
par: Whether to use CPU parallelism
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
[Wb] or [T-m^2] or [V-s] psi, poloidal flux at each observation point
|
|
63
|
+
"""
|
|
64
|
+
ifil = ascontiguousarray(ifil)
|
|
65
|
+
rfil = ascontiguousarray(rfil)
|
|
66
|
+
zfil = ascontiguousarray(zfil)
|
|
67
|
+
rprime = ascontiguousarray(rprime)
|
|
68
|
+
zprime = ascontiguousarray(zprime)
|
|
69
|
+
psi = em_flux_circular_filament(ifil, rfil, zfil, rprime, zprime, par)
|
|
70
|
+
return psi # [Wb] or [T-m^2] or [V-s]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def vector_potential_circular_filament(
|
|
74
|
+
ifil: NDArray[float64],
|
|
75
|
+
rfil: NDArray[float64],
|
|
76
|
+
zfil: NDArray[float64],
|
|
77
|
+
rprime: NDArray[float64],
|
|
78
|
+
zprime: NDArray[float64],
|
|
79
|
+
par: bool = True,
|
|
80
|
+
) -> NDArray[float64]:
|
|
81
|
+
"""
|
|
82
|
+
Vector potential contributions from some circular filaments to some observation points.
|
|
83
|
+
Off-axis A_phi component for a circular current filament in vacuum.
|
|
84
|
+
|
|
85
|
+
The vector potential of a loop has zero r- and z- components due to symmetry,
|
|
86
|
+
and does not vary in the phi-direction.
|
|
87
|
+
|
|
88
|
+
Note that to recover the B-field as the curl of A, the curl operator for cylindrical
|
|
89
|
+
coordinates must be used with the output of this function incorporated into a full
|
|
90
|
+
3D A-field like [A_r, A_phi, A_z].
|
|
91
|
+
|
|
92
|
+
References:
|
|
93
|
+
[1] J. C. Simpson, J. E. Lane, C. D. Immer, R. C. Youngquist, and T. Steinrock,
|
|
94
|
+
“Simple Analytic Expressions for the Magnetic Field of a Circular Current Loop,”
|
|
95
|
+
Jan. 01, 2001. Accessed: Sep. 06, 2022. [Online]. Available: <https://ntrs.nasa.gov/citations/20010038494>
|
|
51
96
|
|
|
52
97
|
Args:
|
|
53
98
|
ifil: [A] filament current
|
|
@@ -55,17 +100,18 @@ def flux_circular_filament(
|
|
|
55
100
|
zfil: [m] filament Z-coord
|
|
56
101
|
rprime: [m] Observation point R-coord
|
|
57
102
|
zprime: [m] Observation point Z-coord
|
|
103
|
+
par: Whether to use CPU parallelism
|
|
58
104
|
|
|
59
105
|
Returns:
|
|
60
|
-
[
|
|
106
|
+
[Wb/m] or [V-s/m] a_phi, vector potential in the toroidal direction
|
|
61
107
|
"""
|
|
62
108
|
ifil = ascontiguousarray(ifil)
|
|
63
109
|
rfil = ascontiguousarray(rfil)
|
|
64
110
|
zfil = ascontiguousarray(zfil)
|
|
65
111
|
rprime = ascontiguousarray(rprime)
|
|
66
112
|
zprime = ascontiguousarray(zprime)
|
|
67
|
-
|
|
68
|
-
return
|
|
113
|
+
a_phi = em_vector_potential_circular_filament(ifil, rfil, zfil, rprime, zprime, par)
|
|
114
|
+
return a_phi # [Wb/m] or [V-s/m]
|
|
69
115
|
|
|
70
116
|
|
|
71
117
|
def flux_density_circular_filament(
|
|
@@ -74,6 +120,7 @@ def flux_density_circular_filament(
|
|
|
74
120
|
zfil: NDArray[float64],
|
|
75
121
|
rprime: NDArray[float64],
|
|
76
122
|
zprime: NDArray[float64],
|
|
123
|
+
par: bool = True,
|
|
77
124
|
) -> tuple[NDArray[float64], NDArray[float64]]:
|
|
78
125
|
"""
|
|
79
126
|
Off-axis Br,Bz components for a circular current filament in vacuum.
|
|
@@ -105,6 +152,7 @@ def flux_density_circular_filament(
|
|
|
105
152
|
zfil: [m] filament Z-coord
|
|
106
153
|
rprime: [m] Observation point R-coord
|
|
107
154
|
zprime: [m] Observation point Z-coord
|
|
155
|
+
par: Whether to use CPU parallelism
|
|
108
156
|
|
|
109
157
|
Returns:
|
|
110
158
|
[T] (Br, Bz) flux density components
|
|
@@ -114,11 +162,11 @@ def flux_density_circular_filament(
|
|
|
114
162
|
zfil = ascontiguousarray(zfil)
|
|
115
163
|
rprime = ascontiguousarray(rprime)
|
|
116
164
|
zprime = ascontiguousarray(zprime)
|
|
117
|
-
Br, Bz = em_flux_density_circular_filament(ifil, rfil, zfil, rprime, zprime)
|
|
165
|
+
Br, Bz = em_flux_density_circular_filament(ifil, rfil, zfil, rprime, zprime, par)
|
|
118
166
|
return Br, Bz # [T]
|
|
119
167
|
|
|
120
168
|
|
|
121
|
-
def
|
|
169
|
+
def flux_density_linear_filament(
|
|
122
170
|
xyzp: Array3xN,
|
|
123
171
|
xyzfil: Array3xN,
|
|
124
172
|
dlxyzfil: Array3xN,
|
|
@@ -129,11 +177,6 @@ def flux_density_biot_savart(
|
|
|
129
177
|
Biot-Savart law calculation for B-field contributions from many filament segments
|
|
130
178
|
to many observation points.
|
|
131
179
|
|
|
132
|
-
This calc is fairly well-optimized under the constraint to keep peak RAM usage to
|
|
133
|
-
O(n) in n observation points, which precludes tiling. It comes out about 20% faster
|
|
134
|
-
than an equivalent implementation in numba, which is about 4x faster than an
|
|
135
|
-
equivalent implementation in numpy.
|
|
136
|
-
|
|
137
180
|
Args:
|
|
138
181
|
xyzp: [m] x,y,z coords of observation points
|
|
139
182
|
xyzfil: [m] x,y,z coords of current filament origins (start of segment)
|
|
@@ -160,7 +203,50 @@ def flux_density_biot_savart(
|
|
|
160
203
|
ascontiguousarray(dlxyzfil[2]),
|
|
161
204
|
)
|
|
162
205
|
ifil = ascontiguousarray(ifil)
|
|
163
|
-
return
|
|
206
|
+
return em_flux_density_linear_filament(xyzp, xyzfil, dlxyzfil, ifil, par)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
flux_density_biot_savart = flux_density_linear_filament # For backwards-compatibility
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def vector_potential_linear_filament(
|
|
213
|
+
xyzp: Array3xN,
|
|
214
|
+
xyzfil: Array3xN,
|
|
215
|
+
dlxyzfil: Array3xN,
|
|
216
|
+
ifil: NDArray[float64],
|
|
217
|
+
par: bool = True,
|
|
218
|
+
) -> Array3xN:
|
|
219
|
+
"""
|
|
220
|
+
Vector potential calculation for A-field contribution from many current filament
|
|
221
|
+
segments to many observation points.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
xyzp: [m] x,y,z coords of observation points
|
|
225
|
+
xyzfil: [m] x,y,z coords of current filament origins (start of segment)
|
|
226
|
+
dlxyzfil: [m] x,y,z length delta of current filaments
|
|
227
|
+
ifil: [A] current in each filament segment
|
|
228
|
+
par: Whether to use CPU parallelism
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
[Wb/m] or [V-s/m] (Ax, Ay, Az) magnetic vector potential at observation points
|
|
232
|
+
"""
|
|
233
|
+
xyzp = (
|
|
234
|
+
ascontiguousarray(xyzp[0]),
|
|
235
|
+
ascontiguousarray(xyzp[1]),
|
|
236
|
+
ascontiguousarray(xyzp[2]),
|
|
237
|
+
)
|
|
238
|
+
xyzfil = (
|
|
239
|
+
ascontiguousarray(xyzfil[0]),
|
|
240
|
+
ascontiguousarray(xyzfil[1]),
|
|
241
|
+
ascontiguousarray(xyzfil[2]),
|
|
242
|
+
)
|
|
243
|
+
dlxyzfil = (
|
|
244
|
+
ascontiguousarray(dlxyzfil[0]),
|
|
245
|
+
ascontiguousarray(dlxyzfil[1]),
|
|
246
|
+
ascontiguousarray(dlxyzfil[2]),
|
|
247
|
+
)
|
|
248
|
+
ifil = ascontiguousarray(ifil)
|
|
249
|
+
return em_vector_potential_linear_filament(xyzp, xyzfil, dlxyzfil, ifil, par)
|
|
164
250
|
|
|
165
251
|
|
|
166
252
|
def inductance_piecewise_linear_filaments(
|
|
@@ -200,10 +286,10 @@ def inductance_piecewise_linear_filaments(
|
|
|
200
286
|
References:
|
|
201
287
|
[1] “Inductance,” Wikipedia. Dec. 12, 2022. Accessed: Jan. 23, 2023. [Online].
|
|
202
288
|
Available: <https://en.wikipedia.org/w/index.php?title=Inductance>
|
|
203
|
-
|
|
289
|
+
|
|
204
290
|
[2] F. E. Neumann, “Allgemeine Gesetze der inducirten elektrischen Ströme,”
|
|
205
291
|
Jan. 1846, doi: [10.1002/andp.18461430103](https://doi.org/10.1002/andp.18461430103)
|
|
206
|
-
|
|
292
|
+
|
|
207
293
|
[3] R. Dengler, “Self inductance of a wire loop as a curve integral,”
|
|
208
294
|
AEM, vol. 5, no. 1, p. 1, Jan. 2016, doi: [10.7716/aem.v5i1.331](https://doi.org/10.7716/aem.v5i1.331)
|
|
209
295
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="183" height="44" viewBox="0 0 183 44" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22.591.294h-.83l-1.218 5.72 1.218 5.715h.83l1.218-5.714L22.591.294z" fill="#CCC8C3"/><path d="M22.591 32.25h-.83l-1.218 5.721 1.218 5.721h.83l1.218-5.72-1.218-5.722z" fill="#CCC8C3"/><path d="M15.148 1.463l-.78.283.811 5.788 3.1 4.958.782-.283-.818-5.788-3.095-4.958z" fill="#CCC8C3"/><path d="M26.084 31.488l-.787.289.818 5.788 3.094 4.958.781-.283-.811-5.788-3.095-4.964z" fill="#CCC8C3"/><path d="M8.55 5.104l-.64.535 2.75 5.161 4.607 3.6.634-.536-2.744-5.161L8.55 5.104z" fill="#CCC8C3"/><path d="M29.09 29.58l-.633.536 2.744 5.167 4.607 3.599.64-.535-2.75-5.161-4.607-3.605z" fill="#CCC8C3"/><path d="M3.598 10.782l-.418.72 4.343 3.912 5.56 1.809.419-.72-4.35-3.912-5.554-1.809z" fill="#CCC8C3"/><path d="M31.278 26.763l-.419.72 4.343 3.912 5.561 1.803.419-.72-4.343-3.906-5.561-1.809z" fill="#CCC8C3"/><path d="M.88 17.813l-.142.818 5.42 2.19 5.844-.203.147-.818-5.425-2.19-5.844.203z" fill="#CCC8C3"/><path d="M32.359 23.362l-.148.824 5.425 2.184 5.838-.203.148-.818-5.42-2.19-5.843.203z" fill="#CCC8C3"/><path d="M.738 25.349l.142.818 5.844.203 5.425-2.184-.147-.824-5.844-.203-5.42 2.19z" fill="#CCC8C3"/><path d="M32.21 19.8l.149.818 5.843.203 5.42-2.19-.148-.818-5.837-.203-5.426 2.19z" fill="#CCC8C3"/><path d="M3.18 32.478l.412.72 5.56-1.803 4.35-3.912-.418-.72-5.561 1.809-4.343 3.906z" fill="#CCC8C3"/><path d="M30.86 16.503l.418.72 5.56-1.809 4.343-3.912-.418-.72-5.56 1.809-4.344 3.912z" fill="#CCC8C3"/><path d="M7.91 38.347l.64.535 4.607-3.599 2.744-5.167-.64-.535-4.601 3.605-2.75 5.16z" fill="#CCC8C3"/><path d="M28.457 13.864l.634.535 4.607-3.598 2.75-5.162-.64-.535-4.607 3.599-2.744 5.16z" fill="#CCC8C3"/><path d="M14.363 42.24l.788.283 3.094-4.958.818-5.788-.787-.29-3.095 4.965-.818 5.788z" fill="#CCC8C3"/><path d="M25.297 12.21l.781.282 3.1-4.958.812-5.788-.78-.283-3.095 4.958-.818 5.788z" fill="#CCC8C3"/><path d="M72.669 10.93a4.072 4.072 0 00-1.477-1.015 5.629 5.629 0 00-3.937 0 3.984 3.984 0 00-1.457 1.009 4.36 4.36 0 00-.91 1.556 5.96 5.96 0 00-.32 2.024c-.012.682.096 1.36.32 2.005a4.54 4.54 0 00.91 1.563 3.9 3.9 0 001.457 1.015 5.629 5.629 0 003.937 0 4.072 4.072 0 001.477-1.015c.407-.452.718-.982.916-1.557a5.91 5.91 0 00.32-2.011c.008-.682-.1-1.36-.32-2.006a4.576 4.576 0 00-.916-1.568zm-1.63 5.678a2.172 2.172 0 01-1.846.768 2.147 2.147 0 01-1.79-.768 3.918 3.918 0 010-4.214 2.147 2.147 0 011.79-.77 2.171 2.171 0 011.846.77 3.918 3.918 0 010 4.214z" fill="#CCC8C3"/><path d="M85.06 9.558a3.02 3.02 0 00-1.5.338 3.923 3.923 0 00-1.009.75c-.05.08-.105.08-.154 0a2.952 2.952 0 00-.984-.799 3.223 3.223 0 00-1.458-.307c-.222 0-.443.03-.658.086-.21.057-.415.13-.615.215-.197.08-.386.177-.566.29-.146.09-.282.195-.406.313-.062.061-.117.05-.166-.037l-.191-.566a.184.184 0 00-.184-.11h-1.784a.086.086 0 00-.099.067v9.344a.086.086 0 00.074.099h2.091a.086.086 0 00.093-.074v-5.23a4.682 4.682 0 01.086-.922c.046-.26.14-.511.277-.738.127-.205.305-.375.516-.492.25-.13.53-.19.812-.178.287-.009.57.064.819.209.215.133.394.317.522.535.137.232.233.486.283.75.057.276.086.556.087.837v5.204a.086.086 0 00.067.099h2.092a.086.086 0 00.092-.074v-5.205c.001-.309.03-.618.086-.922a2.16 2.16 0 01.283-.738c.127-.206.305-.375.517-.492a1.61 1.61 0 01.806-.179c.287-.009.57.064.818.21.217.132.398.316.529.534.136.233.232.486.283.75.054.276.08.557.08.838v5.204a.087.087 0 00.041.087c.01.006.021.01.032.011h2.092a.086.086 0 00.092-.074v-5.345c0-1.47-.332-2.547-1.002-3.242a3.691 3.691 0 00-2.793-1.046z" fill="#CCC8C3"/><path d="M100.333 9.558a3.02 3.02 0 00-1.5.338c-.372.201-.709.46-.997.769-.056.08-.105.08-.154 0a2.952 2.952 0 00-.984-.8 3.223 3.223 0 00-1.458-.307c-.222 0-.444.03-.658.086a4.68 4.68 0 00-.646.215c-.197.08-.386.177-.566.29-.146.09-.282.195-.406.313-.062.061-.117.05-.166-.037l-.191-.566a.185.185 0 00-.185-.11h-1.784a.086.086 0 00-.098.067v9.344a.087.087 0 00.042.087c.01.006.02.01.032.012h2.091a.086.086 0 00.093-.074v-5.23a4.682 4.682 0 01.086-.922c.046-.26.14-.511.277-.738.127-.205.305-.375.516-.492.25-.13.53-.19.812-.179.287-.008.57.065.818.21.216.133.395.317.523.535.137.232.232.486.283.75.057.276.085.556.086.837v5.204a.086.086 0 00.068.099h2.092a.086.086 0 00.092-.074V13.98c.001-.31.03-.619.086-.923a2.16 2.16 0 01.283-.738c.127-.206.305-.375.517-.492a1.61 1.61 0 01.806-.179c.287-.009.57.064.818.21.217.132.398.316.529.534.136.233.232.486.283.751.054.275.081.556.08.837v5.204a.09.09 0 00.018.063.09.09 0 00.055.035h2.092a.086.086 0 00.092-.074v-5.364c0-1.47-.332-2.546-1.002-3.242a3.707 3.707 0 00-2.775-1.045z" fill="#CCC8C3"/><path d="M113.487 10.93a4.007 4.007 0 00-1.47-1.015 5.629 5.629 0 00-3.937 0 3.981 3.981 0 00-1.458 1.009 4.36 4.36 0 00-.911 1.556 5.976 5.976 0 00-.32 2.024 5.87 5.87 0 00.32 2.005 4.55 4.55 0 00.911 1.563c.401.446.9.793 1.458 1.015a5.629 5.629 0 003.937 0 4.006 4.006 0 001.47-1.015c.411-.45.725-.98.922-1.557a5.882 5.882 0 00.32-2.011c.008-.682-.1-1.36-.32-2.006a4.492 4.492 0 00-.922-1.568zm-1.624 5.678a2.177 2.177 0 01-1.846.768 2.145 2.145 0 01-1.79-.768 3.921 3.921 0 010-4.214 2.152 2.152 0 011.79-.77 2.172 2.172 0 011.846.77 3.921 3.921 0 010 4.214z" fill="#CCC8C3"/><path d="M123.952 10.911a3.214 3.214 0 00-1.23-.984 4.267 4.267 0 00-1.845-.37 2.47 2.47 0 00-.616.087 5.965 5.965 0 00-.615.203c-.193.08-.381.174-.56.283a2.6 2.6 0 00-.406.313c-.036.05-.073.068-.11.056a.164.164 0 01-.093-.074l-.209-.584c0-.062-.067-.093-.172-.093h-1.784a.077.077 0 00-.031.002.084.084 0 00-.051.037.079.079 0 00-.01.03v9.343a.083.083 0 00.014.063.087.087 0 00.054.036h2.091a.091.091 0 00.063-.018.087.087 0 00.035-.056v-5.34c0-.276.038-.551.111-.818.07-.26.193-.504.363-.713.176-.215.399-.386.652-.499.296-.133.617-.198.941-.19a1.902 1.902 0 011.606.78c.172.234.296.5.363.782.072.275.112.558.117.843v5.13a.083.083 0 00.014.063.085.085 0 00.053.036h2.092a.086.086 0 00.092-.074V14.03a6.84 6.84 0 00-.203-1.692 4.157 4.157 0 00-.726-1.427z" fill="#CCC8C3"/><path d="M140.375 9.749h-2.104c-.055 0-.092.036-.117.11l-1.501 7.253a.08.08 0 01-.014.036.088.088 0 01-.064.04.088.088 0 01-.038-.002.097.097 0 01-.074-.074l-1.729-7.253c-.024-.074-.067-.11-.129-.11h-3.008c-.062 0-.105.036-.129.11l-1.729 7.253c0 .068-.043.098-.098.098-.056 0-.08 0-.092-.098l-1.477-7.253a.144.144 0 00-.048-.079.142.142 0 00-.087-.031h-2.104c-.074 0-.098.036-.074.11l2.178 9.301c0 .062.061.099.117.099h3.211c.049 0 .086-.037.111-.099l1.617-7.283c0-.062.031-.092.093-.092.055 0 .086 0 .098.092l1.655 7.283c0 .062.061.099.111.099h3.211c.055 0 .092-.037.116-.099l2.178-9.3c.016-.075-.01-.111-.08-.111z" fill="#CCC8C3"/><path d="M145.742 9.589a4.71 4.71 0 00-1.845.35 4.143 4.143 0 00-1.433.997 4.423 4.423 0 00-.923 1.55 6.308 6.308 0 000 4.005c.203.57.516 1.095.923 1.544a4.04 4.04 0 001.433 1.008 4.82 4.82 0 001.845.351 4.92 4.92 0 002.762-.763 3.381 3.381 0 001.464-2.116v-.037h-2.257a.117.117 0 00-.117.068 1.341 1.341 0 01-.744.689c-.357.128-.735.19-1.114.184a2.771 2.771 0 01-.923-.153 2.394 2.394 0 01-.719-.419 1.939 1.939 0 01-.468-.615 1.813 1.813 0 01-.166-.756.112.112 0 01.005-.049.116.116 0 01.06-.073.12.12 0 01.046-.014h6.563s.037 0 .056-.067c.024-.106.043-.213.055-.32 0-.105 0-.253.037-.437a5.892 5.892 0 00-.326-1.987 4.581 4.581 0 00-.923-1.556 4.04 4.04 0 00-1.433-1.01 4.709 4.709 0 00-1.858-.374zm2.104 3.924h-4.263a.104.104 0 01-.104-.053.109.109 0 01-.013-.04c.004-.211.05-.42.136-.614a1.66 1.66 0 01.424-.615 2.33 2.33 0 01.714-.45 2.544 2.544 0 011.002-.184 2.68 2.68 0 011.009.172c.258.104.492.259.689.455.175.174.31.384.394.616.08.195.124.404.129.615a.11.11 0 01-.098.11l-.019-.012z" fill="#CCC8C3"/><path d="M162.299 6.027h2.067c.025 0 .049.01.068.026a.1.1 0 01.031.066V19.16a.1.1 0 01-.029.07.1.1 0 01-.07.028h-2.067a.1.1 0 01-.092-.098V6.119a.092.092 0 01.092-.092z" fill="#CCC8C3"/><path d="M171.835 9.748h-1.932a.08.08 0 01-.062-.016.074.074 0 01-.021-.026.06.06 0 01-.009-.031v-2.56a.112.112 0 00-.001-.031.079.079 0 00-.014-.029.077.077 0 00-.053-.032h-2.092a.08.08 0 00-.092.068v2.534a.092.092 0 01-.074.098h-1.562a.085.085 0 00-.098.068V11.6a.083.083 0 00.018.06.089.089 0 00.055.032h1.563a.085.085 0 01.087.042c.006.01.01.02.011.032v4.817a2.67 2.67 0 00.658 2.03 3.077 3.077 0 002.141.615h1.464a.086.086 0 00.092-.074v-1.9a.083.083 0 00-.014-.064.082.082 0 00-.053-.035h-1.329a.721.721 0 01-.48-.16.54.54 0 01-.197-.437v-4.743a.088.088 0 01.074-.098h1.938a.075.075 0 00.06-.014.085.085 0 00.022-.024.079.079 0 00.01-.03V9.841a.068.068 0 00-.001-.032.077.077 0 00-.037-.05.079.079 0 00-.029-.01h-.043z" fill="#CCC8C3"/><path d="M181.527 10.911a3.424 3.424 0 00-1.23-.984 3.922 3.922 0 00-1.772-.37c-.274 0-.548.038-.812.111a4.78 4.78 0 00-.677.259 2.91 2.91 0 00-.498.289c-.094.07-.185.147-.27.228-.05.049-.093.067-.13.055-.037-.013-.055-.05-.055-.11v-4.27a.084.084 0 00-.019-.06.083.083 0 00-.055-.032h-2.091a.081.081 0 00-.061.014.08.08 0 00-.021.024.08.08 0 00-.011.03V19.16a.093.093 0 00.014.063.087.087 0 00.054.036h2.092a.092.092 0 00.098-.074v-5.34a2.789 2.789 0 01.111-.812c.069-.251.193-.484.363-.683.182-.2.404-.362.652-.473a2.33 2.33 0 01.941-.179c.33-.008.657.064.953.21a1.94 1.94 0 011.015 1.285c.073.273.112.554.117.837v5.13a.093.093 0 00.014.063.087.087 0 00.054.036h2.091a.087.087 0 00.093-.074V14.03a5.867 5.867 0 00-.234-1.692 4.18 4.18 0 00-.726-1.427z" fill="#CCC8C3"/><path d="M155.601 13.39a6.148 6.148 0 00-1.802.246c-.465.138-.9.364-1.28.665a2.676 2.676 0 00-1.015 2.116c-.004.406.071.81.222 1.187.15.364.379.69.67.954.339.28.73.488 1.15.615a5.21 5.21 0 001.655.233 4.311 4.311 0 001.846-.356c.228-.11.447-.235.658-.376.055-.043.104-.08.154-.067a.24.24 0 01.104.086l.142.424a.165.165 0 00.166.099h1.79c.049 0 .074 0 .074-.074v-6.035a3.195 3.195 0 00-1.132-2.657 4.862 4.862 0 00-3.076-.898 5.888 5.888 0 00-1.575.209 3.942 3.942 0 00-1.31.615 3.134 3.134 0 00-.898 1.027 3 3 0 00-.332 1.44c0 .049 0 .074.073.074h2.049a.067.067 0 00.054-.02.064.064 0 00.016-.025 1.451 1.451 0 01.127-.51 1.03 1.03 0 01.326-.399 1.67 1.67 0 01.572-.277c.293-.075.595-.11.898-.104.371-.014.742.038 1.095.153.232.072.443.199.615.37.122.124.209.28.252.449.026.125.042.253.049.381a.419.419 0 01-.147.295.616.616 0 01-.437.136l-1.753.024zm-.4 4.023a2.389 2.389 0 01-.72-.092 1.412 1.412 0 01-.455-.24.783.783 0 01-.24-.32.795.795 0 01-.067-.326c.001-.136.023-.27.067-.4a.819.819 0 01.289-.387 1.85 1.85 0 01.616-.283 3.48 3.48 0 011.008-.11h2.141a.105.105 0 01.117.085 1.937 1.937 0 01-.154.72 1.852 1.852 0 01-.486.658 2.59 2.59 0 01-.849.48 3.65 3.65 0 01-1.267.215z" fill="#CCC8C3"/><path d="M55.046 9.275a3.396 3.396 0 014.127-1.052c.356.178.676.418.948.708.225.234.406.507.535.806.117.27.197.473.246.615.05.141.061.098.11.098h2.166c.01.002.022.001.033-.002a.08.08 0 00.06-.072 2.986 2.986 0 00-.124-.732 4.405 4.405 0 00-.393-.947 6.331 6.331 0 00-.708-1.009 4.811 4.811 0 00-1.052-.91 5.825 5.825 0 00-1.433-.659 6.44 6.44 0 00-1.846-.252 5.967 5.967 0 00-2.596.53 5.137 5.137 0 00-1.845 1.451 6.354 6.354 0 00-1.107 2.202 9.925 9.925 0 00-.37 2.756c-.012.922.113 1.84.37 2.725.221.77.598 1.486 1.107 2.104a4.922 4.922 0 001.846 1.36c.823.336 1.706.5 2.596.48.66.011 1.317-.08 1.95-.271a5.493 5.493 0 001.47-.708 4.78 4.78 0 001.033-.96 6.4 6.4 0 00.665-1.02c.154-.293.274-.603.356-.923.056-.201.09-.407.105-.615a.078.078 0 00-.015-.06.08.08 0 00-.053-.033H61.02c-.05 0-.086.031-.11.093-.038.11-.118.301-.235.572a3.34 3.34 0 01-.547.818 3.377 3.377 0 01-.954.683 3.2 3.2 0 01-1.488.307 3.132 3.132 0 01-2.645-1.23 5.469 5.469 0 01-.93-3.371 7.318 7.318 0 01.247-1.969 4.86 4.86 0 01.689-1.513z" fill="#CCC8C3"/><path d="M62.133 24.795h-9.19a.087.087 0 00-.098.068v13.065a.087.087 0 00.074.099h2.091a.074.074 0 00.033-.002.08.08 0 00.06-.072v-5.536a.063.063 0 01.01-.05.061.061 0 01.045-.024h5.247a.086.086 0 00.098-.068v-1.944a.086.086 0 00-.074-.092h-5.253a.063.063 0 01-.05-.01.064.064 0 01-.024-.045v-3.291a.063.063 0 01.011-.05.061.061 0 01.045-.024h6.975a.078.078 0 00.06-.015.08.08 0 00.033-.053v-1.907a.08.08 0 00-.074-.092l-.018.043z" fill="#CCC8C3"/><path d="M71.146 28.486h-2.085a.086.086 0 00-.099.067V33.9a2.7 2.7 0 01-.11.824 2.037 2.037 0 01-.363.708 1.926 1.926 0 01-.652.498 2.148 2.148 0 01-.942.185 1.882 1.882 0 01-1.605-.782 2.21 2.21 0 01-.363-.769 3.074 3.074 0 01-.117-.855v-5.13a.082.082 0 00-.014-.06.081.081 0 00-.053-.032H62.65a.079.079 0 00-.06.014.08.08 0 00-.032.053v5.13a6.79 6.79 0 00.203 1.692c.129.52.366 1.006.695 1.428.344.424.782.763 1.28.99a4.712 4.712 0 001.974.363 2.6 2.6 0 001.175-.283c.325-.153.62-.36.873-.615.037-.056.074-.074.111-.062a.2.2 0 01.092.08l.191.56a.203.203 0 00.19.117h1.785a.082.082 0 00.062-.017.08.08 0 00.03-.057v-9.295c0-.065-.025-.098-.074-.098z" fill="#CCC8C3"/><path d="M83.94 24.05a1.353 1.353 0 00-1.354 1.348v.012a1.354 1.354 0 002.7 0 1.347 1.347 0 00-1.347-1.347v-.012z" fill="#CCC8C3"/><path d="M82.901 28.486h2.073a.092.092 0 01.092.092v9.32a.099.099 0 01-.092.098h-2.073a.099.099 0 01-.092-.098v-9.314a.092.092 0 01.092-.098z" fill="#CCC8C3"/><path d="M94.853 29.673a4.04 4.04 0 00-1.476-1.015 5.629 5.629 0 00-3.937 0 3.913 3.913 0 00-1.452 1.009c-.409.45-.721.98-.916 1.556a6.644 6.644 0 000 4.036 4.68 4.68 0 00.916 1.556c.4.444.897.791 1.452 1.015a5.629 5.629 0 003.937 0 3.967 3.967 0 001.476-1.015c.411-.45.725-.98.923-1.556a6.496 6.496 0 000-4.017 4.495 4.495 0 00-.923-1.569zm-1.624 5.678a2.504 2.504 0 01-3.61 0 3.937 3.937 0 010-4.208 2.46 2.46 0 013.61 0 3.937 3.937 0 010 4.208z" fill="#CCC8C3"/><path d="M105.343 29.654a3.214 3.214 0 00-1.23-.984 4.27 4.27 0 00-1.846-.369 2.464 2.464 0 00-.615.086 4.867 4.867 0 00-.615.21 3.39 3.39 0 00-.56.276 2.56 2.56 0 00-.406.314c-.037.05-.074.068-.11.055a.16.16 0 01-.093-.073l-.209-.616c0-.061-.068-.092-.172-.092h-1.784a.078.078 0 00-.06.015.08.08 0 00-.032.053v9.344a.087.087 0 00.067.098h2.092a.085.085 0 00.064-.016.086.086 0 00.034-.058v-5.34c0-.276.037-.55.11-.817.07-.261.194-.504.364-.714.177-.213.4-.383.652-.498a2.15 2.15 0 01.941-.19 1.908 1.908 0 011.606.78c.169.235.292.5.362.782.073.275.112.558.117.843v5.13a.093.093 0 00.014.063.087.087 0 00.054.035h2.092a.083.083 0 00.062-.017.075.075 0 00.021-.025.088.088 0 00.009-.032v-5.105a6.841 6.841 0 00-.203-1.692 4.163 4.163 0 00-.726-1.446z" fill="#CCC8C3"/><path d="M120.793 31.605a3.417 3.417 0 00-.922-.702 5.737 5.737 0 00-1.083-.443 7.934 7.934 0 00-1.132-.252 23.454 23.454 0 00-1.064-.141 6.62 6.62 0 01-.781-.111 4.218 4.218 0 01-.862-.258 1.744 1.744 0 01-.615-.456 1.03 1.03 0 01-.24-.713c-.003-.25.061-.497.185-.714.125-.235.295-.444.498-.615.218-.175.466-.308.732-.394.293-.099.601-.146.911-.141a3.17 3.17 0 011.045.16c.278.097.537.242.763.43.196.153.358.346.474.566a1.39 1.39 0 01.161.647.077.077 0 00.037.05c.009.006.019.01.029.01h2.178c.049 0 .074-.03.074-.091a3.251 3.251 0 00-.394-1.625 3.65 3.65 0 00-1.058-1.193 4.978 4.978 0 00-1.532-.744 6.2 6.2 0 00-1.808-.252 5.615 5.615 0 00-1.716.264 4.82 4.82 0 00-1.495.757c-.437.331-.799.75-1.064 1.23a3.385 3.385 0 00-.4 1.655 3.61 3.61 0 00.357 1.685c.235.457.585.845 1.015 1.126a5.099 5.099 0 001.587.677 11.81 11.81 0 001.907.301 3.925 3.925 0 012.085.658 1.414 1.414 0 01.431 1.926 1.946 1.946 0 01-.573.615 3.01 3.01 0 01-.861.418c-.35.112-.715.166-1.082.16a3.733 3.733 0 01-1.108-.148 3.347 3.347 0 01-.885-.387 1.887 1.887 0 01-.616-.554 1.144 1.144 0 01-.217-.69.067.067 0 00-.014-.03.08.08 0 00-.058-.03h-2.183a.08.08 0 00-.082.038.08.08 0 00-.011.03c.004.463.101.92.283 1.347.199.473.504.894.892 1.23a4.66 4.66 0 001.587.892 6.97 6.97 0 002.387.344 7.26 7.26 0 002.122-.276 4.59 4.59 0 001.6-.819 3.571 3.571 0 001.027-1.236c.241-.527.361-1.1.351-1.68.012-.5-.068-.998-.234-1.47a3.256 3.256 0 00-.628-1.051z" fill="#CCC8C3"/><path d="M131.615 28.486h-2.183c-.05 0-.087.03-.111.092l-2.276 7.29a.093.093 0 01-.111.067.093.093 0 01-.058-.018.088.088 0 01-.034-.05l-2.276-7.277c-.025-.061-.062-.092-.111-.092h-2.202c-.086 0-.117.03-.092.092l3.137 9.326c.08.246.141.48.19.701a1.36 1.36 0 010 .616.634.634 0 01-.27.418 1.232 1.232 0 01-.671.147h-2.257a.08.08 0 00-.082.038.103.103 0 00-.011.03v1.796a.082.082 0 00.042.083c.01.006.021.009.032.01h2.787a2.936 2.936 0 001.913-.585 3.807 3.807 0 001.126-1.784l.492-1.445 3.119-9.326c.037-.086.006-.13-.093-.13z" fill="#CCC8C3"/><path d="M147.198 28.486h-1.907a.075.075 0 01-.06-.014.085.085 0 01-.022-.024.079.079 0 01-.01-.03v-2.565a.082.082 0 00-.042-.083.08.08 0 00-.032-.01h-2.092a.08.08 0 00-.092.068v2.565a.085.085 0 01-.001.032.077.077 0 01-.037.05.077.077 0 01-.03.01h-1.581a.08.08 0 00-.092.068v1.809a.078.078 0 00.002.034.107.107 0 00.014.03.088.088 0 00.058.034h1.556a.083.083 0 01.061.015.081.081 0 01.021.023.08.08 0 01.011.03v4.817a2.677 2.677 0 00.658 2.03 3.075 3.075 0 002.141.615h1.47a.078.078 0 00.062-.017.076.076 0 00.021-.025.088.088 0 00.009-.032v-1.9a.082.082 0 00-.042-.083.082.082 0 00-.032-.01h-1.353a.751.751 0 01-.48-.16.519.519 0 01-.197-.443v-4.774a.084.084 0 01.001-.031.078.078 0 01.014-.029.077.077 0 01.053-.032h1.944a.082.082 0 00.033-.002.087.087 0 00.029-.014.074.074 0 00.021-.026.087.087 0 00.009-.032v-1.808a.082.082 0 00-.042-.083.082.082 0 00-.032-.01l-.012.007z" fill="#CCC8C3"/><path d="M168.767 28.295a3.074 3.074 0 00-1.507.338 4.06 4.06 0 00-.997.775c-.049.074-.098.074-.147 0a2.812 2.812 0 00-.985-.8 3.145 3.145 0 00-2.116-.227 5.05 5.05 0 00-.652.215 4.098 4.098 0 00-.56.296 2.23 2.23 0 00-.406.307c-.061.062-.116.05-.166-.037l-.19-.566a.192.192 0 00-.191-.11h-1.784a.075.075 0 00-.06.014.085.085 0 00-.022.023.079.079 0 00-.01.03v9.35a.068.068 0 00.001.032.077.077 0 00.037.05c.009.006.019.01.029.01h2.092a.087.087 0 00.065-.015.09.09 0 00.033-.058v-5.229a4.618 4.618 0 01.08-.916 2.15 2.15 0 01.283-.745c.129-.204.307-.373.517-.492a1.77 1.77 0 01.812-.178 1.57 1.57 0 01.812.21c.216.134.397.317.529.534.136.232.232.486.283.75.053.277.082.556.086.837v5.21a.085.085 0 00.001.032c.003.01.007.02.013.029a.093.093 0 00.024.021c.009.006.019.01.03.01h2.122a.08.08 0 00.092-.073v-5.229a5.12 5.12 0 01.086-.916 2.15 2.15 0 01.283-.745c.129-.204.307-.373.517-.492.25-.123.527-.184.806-.178.287-.006.57.066.818.21.214.136.395.318.529.534.135.233.228.487.277.75.056.276.085.556.086.837v5.21a.082.082 0 00.042.083.08.08 0 00.032.01h2.091a.083.083 0 00.063-.017.09.09 0 00.021-.025.088.088 0 00.009-.032v-5.34c0-1.463-.337-2.544-1.009-3.241a3.693 3.693 0 00-2.799-1.046z" fill="#CCC8C3"/><path d="M79.555 32.669a5.269 5.269 0 00-1.41-.394l-1.377-.178c-.21 0-.418-.056-.615-.093a4.11 4.11 0 01-.542-.141 1.04 1.04 0 01-.387-.234.524.524 0 01-.154-.393.75.75 0 01.43-.652 3.217 3.217 0 012.154-.123c.223.057.432.16.615.3.14.111.25.255.32.42a1.084 1.084 0 01.093.424.08.08 0 00.067.061h2.023a.075.075 0 00.059-.015.073.073 0 00.028-.052 3.194 3.194 0 00-.302-1.385 2.958 2.958 0 00-.843-1.027 3.586 3.586 0 00-1.28-.615 6.152 6.152 0 00-1.641-.21 5.14 5.14 0 00-1.588.235 3.99 3.99 0 00-1.23.615 2.768 2.768 0 00-.787.916 2.64 2.64 0 00.086 2.516c.242.353.567.64.947.837.413.21.855.356 1.31.437.492.086.985.153 1.465.203.19.03.4.049.615.067.208.019.414.058.615.117.181.048.35.136.492.258a.615.615 0 01.203.499.861.861 0 01-.197.578 1.23 1.23 0 01-.486.338c-.197.078-.404.13-.615.154-1.015.11-1.74 0-2.14-.363a1.157 1.157 0 01-.468-.836.104.104 0 000-.062.104.104 0 00-.062 0h-2.085a.098.098 0 00-.055 0 .08.08 0 000 .05 2.935 2.935 0 001.076 2.226c.396.323.846.573 1.329.738.595.196 1.219.29 1.845.277 1.07.06 2.132-.22 3.033-.8a2.669 2.669 0 001.107-2.3 2.461 2.461 0 00-.443-1.538 2.965 2.965 0 00-1.206-.855z" fill="#CCC8C3"/><path d="M181.899 33.512a2.966 2.966 0 00-1.101-.843 5.274 5.274 0 00-1.409-.394l-1.378-.178c-.209 0-.418-.056-.615-.093a3.862 3.862 0 01-.541-.14 1.044 1.044 0 01-.388-.235.524.524 0 01-.154-.393.75.75 0 01.431-.652 3.217 3.217 0 012.153-.123c.213.061.411.164.584.3.141.111.251.255.32.42a1.072 1.072 0 01.094.425c.002.01.007.02.013.028a.077.077 0 00.053.032h2.024a.073.073 0 00.06-.017.073.073 0 00.02-.025.084.084 0 00.006-.032 3.182 3.182 0 00-.301-1.384 2.968 2.968 0 00-.843-1.027 3.584 3.584 0 00-1.279-.615 6.161 6.161 0 00-1.643-.21 5.142 5.142 0 00-1.587.234 4.003 4.003 0 00-1.23.616 2.694 2.694 0 00-.788.916 2.643 2.643 0 00.086 2.516c.246.35.573.636.954.83.415.21.859.356 1.316.437.492.087.978.154 1.464.203.191.031.4.05.616.068.208.019.414.058.615.117.181.047.35.136.492.258a.62.62 0 01.203.498.863.863 0 01-.197.579 1.341 1.341 0 01-.486.338 2.46 2.46 0 01-.615.154c-1.015.11-1.741 0-2.141-.363a1.188 1.188 0 01-.474-.837.093.093 0 000-.061.104.104 0 00-.061 0h-2.085a.1.1 0 00-.056 0 .083.083 0 000 .049 2.887 2.887 0 001.077 2.227c.395.323.845.573 1.328.738a5.54 5.54 0 001.846.277 5.08 5.08 0 003.033-.8 2.69 2.69 0 001.107-2.3 2.46 2.46 0 00-.523-1.538z" fill="#CCC8C3"/><path d="M152.969 28.338a4.715 4.715 0 00-1.846.351 4.152 4.152 0 00-1.433.997c-.406.45-.72.977-.923 1.55a6.321 6.321 0 000 4.004c.203.571.517 1.096.923 1.544.4.436.889.78 1.433 1.01a4.83 4.83 0 001.846.35 4.922 4.922 0 002.762-.763 3.396 3.396 0 001.47-2.116v-.012h-2.264a.117.117 0 00-.117.067 1.307 1.307 0 01-.744.69 3.112 3.112 0 01-1.113.184 2.774 2.774 0 01-.923-.154 2.47 2.47 0 01-.72-.418 1.797 1.797 0 01-.633-1.372.13.13 0 01.004-.048.136.136 0 01.023-.043.121.121 0 01.083-.044h6.564s.043 0 .062-.068c.018-.068.036-.215.049-.32.012-.104 0-.252.037-.436a5.892 5.892 0 00-.326-1.987 4.408 4.408 0 00-.923-1.557 4.05 4.05 0 00-1.433-1.009 4.715 4.715 0 00-1.858-.4zm2.104 3.925h-4.239a.111.111 0 01-.117-.092 1.59 1.59 0 01.136-.615c.099-.223.243-.422.424-.585.21-.19.451-.342.714-.449.318-.128.659-.19 1.003-.184.346-.008.69.05 1.014.172.258.104.493.259.689.455a1.723 1.723 0 01.517 1.23.104.104 0 01-.092.111l-.049-.043z" fill="#CCC8C3"/><path d="M139.001 32.669a5.347 5.347 0 00-1.409-.394l-1.384-.178c-.209 0-.418-.056-.615-.093a4.136 4.136 0 01-.542-.141 1.04 1.04 0 01-.387-.234.517.517 0 01-.154-.394.75.75 0 01.431-.652 3.217 3.217 0 012.153-.122c.223.057.432.16.615.3.14.111.25.255.32.42a1.245 1.245 0 01.1.426.082.082 0 00.04.05.12.12 0 00.032.01h2.018c.01 0 .02 0 .03-.002a.077.077 0 00.028-.014.064.064 0 00.019-.023.076.076 0 00.009-.03 3.081 3.081 0 00-.302-1.384 2.954 2.954 0 00-.842-1.027 3.597 3.597 0 00-1.28-.615 6.149 6.149 0 00-1.642-.21 5.138 5.138 0 00-1.587.235 4.094 4.094 0 00-1.231.615 2.778 2.778 0 00-.787.916c-.18.346-.275.73-.277 1.12a2.46 2.46 0 00.363 1.396c.226.341.53.624.886.825.413.209.854.356 1.31.436.492.086.984.154 1.464.203.191.031.4.05.615.068.209.019.415.058.616.117.183.048.353.136.498.258a.616.616 0 01.197.498.863.863 0 01-.197.579 1.23 1.23 0 01-.486.338 2.41 2.41 0 01-.615.154c-1.015.11-1.741 0-2.141-.363a1.165 1.165 0 01-.468-.837.093.093 0 000-.061.097.097 0 00-.055 0h-2.091a.1.1 0 00-.056 0 2.94 2.94 0 001.077 2.276 4.23 4.23 0 001.335.738 5.452 5.452 0 001.845.277c1.07.06 2.132-.22 3.033-.8a2.665 2.665 0 001.107-2.3 2.46 2.46 0 00-.443-1.538 3 3 0 00-1.15-.843z" fill="#CCC8C3"/></svg>
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
site_name: cfsem
|
|
2
|
-
site_url: https://cfsem.readthedocs.io
|
|
2
|
+
site_url: https://cfsem-py.readthedocs.io
|
|
3
3
|
theme:
|
|
4
4
|
name: material
|
|
5
|
+
logo: assets/logo.svg
|
|
6
|
+
palette:
|
|
7
|
+
primary: custom
|
|
8
|
+
accent: custom
|
|
5
9
|
|
|
6
10
|
plugins:
|
|
7
11
|
- search
|
|
@@ -20,6 +24,7 @@ nav:
|
|
|
20
24
|
- "Python API":
|
|
21
25
|
- "python/filament.md"
|
|
22
26
|
- "python/flux_density.md"
|
|
27
|
+
- "python/vector_potential.md"
|
|
23
28
|
- "python/inductance.md"
|
|
24
29
|
- "python/grad_shafranov.md"
|
|
25
30
|
- "python/math.md"
|
|
@@ -46,6 +51,9 @@ extra_javascript:
|
|
|
46
51
|
- https://polyfill.io/v3/polyfill.min.js?features=es6
|
|
47
52
|
- https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js
|
|
48
53
|
|
|
54
|
+
extra_css:
|
|
55
|
+
- stylesheets/extra.css
|
|
56
|
+
|
|
49
57
|
watch:
|
|
50
58
|
- cfsem
|
|
51
59
|
|
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cfsem"
|
|
7
|
-
version = "2.0
|
|
7
|
+
version = "2.1.0"
|
|
8
8
|
description = "Quasi-steady electromagnetics including filamentized approximations, Biot-Savart, and Grad-Shafranov."
|
|
9
9
|
authors = [{author = "Commonwealth Fusion Systems", email = "jlogan@cfs.energy"}]
|
|
10
10
|
requires-python = ">=3.9, <3.13"
|
|
@@ -16,7 +16,7 @@ classifiers = [
|
|
|
16
16
|
dynamic = ["version"]
|
|
17
17
|
dependencies = [
|
|
18
18
|
"numpy >= 2",
|
|
19
|
-
"interpn >= 0.2.
|
|
19
|
+
"interpn >= 0.2.3",
|
|
20
20
|
]
|
|
21
21
|
license = "MIT"
|
|
22
22
|
|
|
@@ -25,7 +25,7 @@ dev = [
|
|
|
25
25
|
# Tests
|
|
26
26
|
"pytest >= 7.1.3",
|
|
27
27
|
"coverage >= 6.5.0",
|
|
28
|
-
"ruff >= 0.
|
|
28
|
+
"ruff >= 0.6.2",
|
|
29
29
|
"pyright >= 1.1.331",
|
|
30
30
|
"scipy >= 1.8",
|
|
31
31
|
# Docs
|
|
@@ -128,6 +128,7 @@ fn flux_circular_filament<'py>(
|
|
|
128
128
|
z: Bound<'py, PyArray1<f64>>,
|
|
129
129
|
rprime: Bound<'py, PyArray1<f64>>,
|
|
130
130
|
zprime: Bound<'py, PyArray1<f64>>,
|
|
131
|
+
par: bool,
|
|
131
132
|
) -> PyResult<Py<PyArray1<f64>>> {
|
|
132
133
|
// Get references to contiguous data as slice
|
|
133
134
|
// or error if data is not contiguous
|
|
@@ -148,8 +149,14 @@ fn flux_circular_filament<'py>(
|
|
|
148
149
|
// Initialize output
|
|
149
150
|
let mut psi = vec![0.0; m];
|
|
150
151
|
|
|
152
|
+
// Select variant
|
|
153
|
+
let func = match par {
|
|
154
|
+
true => physics::circular_filament::flux_circular_filament_par,
|
|
155
|
+
false => physics::circular_filament::flux_circular_filament,
|
|
156
|
+
};
|
|
157
|
+
|
|
151
158
|
// Do calculations
|
|
152
|
-
match
|
|
159
|
+
match func(current, r, z, rprime, zprime, &mut psi[..]) {
|
|
153
160
|
Ok(_) => {}
|
|
154
161
|
Err(x) => {
|
|
155
162
|
let err: PyErr = PyInteropError::DimensionalityError { msg: x.to_string() }.into();
|
|
@@ -163,6 +170,56 @@ fn flux_circular_filament<'py>(
|
|
|
163
170
|
})
|
|
164
171
|
}
|
|
165
172
|
|
|
173
|
+
/// Python bindings for cfsemrs::physics::circular_filament::vector_potential_circular_filament
|
|
174
|
+
#[pyfunction]
|
|
175
|
+
fn vector_potential_circular_filament<'py>(
|
|
176
|
+
current: Bound<'py, PyArray1<f64>>,
|
|
177
|
+
r: Bound<'py, PyArray1<f64>>,
|
|
178
|
+
z: Bound<'py, PyArray1<f64>>,
|
|
179
|
+
rprime: Bound<'py, PyArray1<f64>>,
|
|
180
|
+
zprime: Bound<'py, PyArray1<f64>>,
|
|
181
|
+
par: bool,
|
|
182
|
+
) -> PyResult<Py<PyArray1<f64>>> {
|
|
183
|
+
// Get references to contiguous data as slice
|
|
184
|
+
// or error if data is not contiguous
|
|
185
|
+
let current_readonly = current.readonly();
|
|
186
|
+
let current = current_readonly.as_slice()?;
|
|
187
|
+
let r_readonly = r.readonly();
|
|
188
|
+
let r = r_readonly.as_slice()?;
|
|
189
|
+
let z_readonly = z.readonly();
|
|
190
|
+
let z = z_readonly.as_slice()?;
|
|
191
|
+
let rprime_readonly = rprime.readonly();
|
|
192
|
+
let rprime = rprime_readonly.as_slice()?;
|
|
193
|
+
let zprime_readonly = zprime.readonly();
|
|
194
|
+
let zprime = zprime_readonly.as_slice()?;
|
|
195
|
+
|
|
196
|
+
// Get array shapes, make sure they make sense
|
|
197
|
+
let m = rprime.len();
|
|
198
|
+
|
|
199
|
+
// Initialize output
|
|
200
|
+
let mut out = vec![0.0; m];
|
|
201
|
+
|
|
202
|
+
// Select variant
|
|
203
|
+
let func = match par {
|
|
204
|
+
true => physics::circular_filament::vector_potential_circular_filament_par,
|
|
205
|
+
false => physics::circular_filament::vector_potential_circular_filament,
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// Do calculations
|
|
209
|
+
match func(current, r, z, rprime, zprime, &mut out[..]) {
|
|
210
|
+
Ok(_) => {}
|
|
211
|
+
Err(x) => {
|
|
212
|
+
let err: PyErr = PyInteropError::DimensionalityError { msg: x.to_string() }.into();
|
|
213
|
+
return Err(err);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Acquire global interpreter lock, which will be released when it goes out of scope
|
|
218
|
+
Python::with_gil(|py| {
|
|
219
|
+
Ok(PyArray1::from_vec_bound(py, out).unbind()) // Make PyObject
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
|
|
166
223
|
/// Python bindings for cfsemrs::physics::flux_density_circular_filament
|
|
167
224
|
#[pyfunction]
|
|
168
225
|
fn flux_density_circular_filament<'py>(
|
|
@@ -171,6 +228,7 @@ fn flux_density_circular_filament<'py>(
|
|
|
171
228
|
zfil: Bound<'py, PyArray1<f64>>,
|
|
172
229
|
rprime: Bound<'py, PyArray1<f64>>,
|
|
173
230
|
zprime: Bound<'py, PyArray1<f64>>,
|
|
231
|
+
par: bool,
|
|
174
232
|
) -> PyResult<(Py<PyArray1<f64>>, Py<PyArray1<f64>>)> {
|
|
175
233
|
// Get references to contiguous data as slice
|
|
176
234
|
// or error if data is not contiguous
|
|
@@ -190,10 +248,14 @@ fn flux_density_circular_filament<'py>(
|
|
|
190
248
|
let mut br = vec![0.0; n];
|
|
191
249
|
let mut bz = vec![0.0; n];
|
|
192
250
|
|
|
251
|
+
// Select variant
|
|
252
|
+
let func = match par {
|
|
253
|
+
true => physics::circular_filament::flux_density_circular_filament_par,
|
|
254
|
+
false => physics::circular_filament::flux_density_circular_filament,
|
|
255
|
+
};
|
|
256
|
+
|
|
193
257
|
// Do calculations
|
|
194
|
-
match
|
|
195
|
-
¤t, &rfil, &zfil, &rprime, &zprime, &mut br, &mut bz,
|
|
196
|
-
) {
|
|
258
|
+
match func(¤t, &rfil, &zfil, &rprime, &zprime, &mut br, &mut bz) {
|
|
197
259
|
Ok(_) => {}
|
|
198
260
|
Err(x) => {
|
|
199
261
|
let err: PyErr = PyInteropError::DimensionalityError { msg: x.to_string() }.into();
|
|
@@ -210,9 +272,9 @@ fn flux_density_circular_filament<'py>(
|
|
|
210
272
|
})
|
|
211
273
|
}
|
|
212
274
|
|
|
213
|
-
/// Python bindings for cfsemrs::physics::
|
|
275
|
+
/// Python bindings for cfsemrs::physics::linear_filament::flux_density_linear_filament
|
|
214
276
|
#[pyfunction]
|
|
215
|
-
fn
|
|
277
|
+
fn flux_density_linear_filament<'py>(
|
|
216
278
|
xyzp: (
|
|
217
279
|
Bound<'py, PyArray1<f64>>,
|
|
218
280
|
Bound<'py, PyArray1<f64>>,
|
|
@@ -259,8 +321,8 @@ fn flux_density_biot_savart<'py>(
|
|
|
259
321
|
let (mut bx, mut by, mut bz) = (vec![0.0; n], vec![0.0; n], vec![0.0; n]);
|
|
260
322
|
|
|
261
323
|
let func = match par {
|
|
262
|
-
true => physics::
|
|
263
|
-
false => physics::
|
|
324
|
+
true => physics::linear_filament::flux_density_linear_filament_par,
|
|
325
|
+
false => physics::linear_filament::flux_density_linear_filament,
|
|
264
326
|
};
|
|
265
327
|
match func(xyzp, xyzfil, dlxyzfil, ifil, (&mut bx, &mut by, &mut bz)) {
|
|
266
328
|
Ok(x) => x,
|
|
@@ -280,6 +342,82 @@ fn flux_density_biot_savart<'py>(
|
|
|
280
342
|
})
|
|
281
343
|
}
|
|
282
344
|
|
|
345
|
+
/// Python bindings for cfsemrs::physics::linear_filament::vector_potential_linear_filament
|
|
346
|
+
#[pyfunction]
|
|
347
|
+
fn vector_potential_linear_filament<'py>(
|
|
348
|
+
xyzp: (
|
|
349
|
+
Bound<'py, PyArray1<f64>>,
|
|
350
|
+
Bound<'py, PyArray1<f64>>,
|
|
351
|
+
Bound<'py, PyArray1<f64>>,
|
|
352
|
+
), // [m] Test point coords
|
|
353
|
+
xyzfil: (
|
|
354
|
+
Bound<'py, PyArray1<f64>>,
|
|
355
|
+
Bound<'py, PyArray1<f64>>,
|
|
356
|
+
Bound<'py, PyArray1<f64>>,
|
|
357
|
+
), // [m] Filament origin coords (start of segment)
|
|
358
|
+
dlxyzfil: (
|
|
359
|
+
Bound<'py, PyArray1<f64>>,
|
|
360
|
+
Bound<'py, PyArray1<f64>>,
|
|
361
|
+
Bound<'py, PyArray1<f64>>,
|
|
362
|
+
), // [m] Filament length delta
|
|
363
|
+
ifil: Bound<'py, PyArray1<f64>>, // [A] filament current
|
|
364
|
+
par: bool,
|
|
365
|
+
) -> PyResult<(Py<PyArray1<f64>>, Py<PyArray1<f64>>, Py<PyArray1<f64>>)> {
|
|
366
|
+
// Get references to contiguous data as slice
|
|
367
|
+
// or error if data is not contiguous
|
|
368
|
+
let xpro = xyzp.0.readonly();
|
|
369
|
+
let ypro = xyzp.1.readonly();
|
|
370
|
+
let zpro = xyzp.2.readonly();
|
|
371
|
+
let xyzp = (xpro.as_slice()?, ypro.as_slice()?, zpro.as_slice()?);
|
|
372
|
+
|
|
373
|
+
let xfilro = xyzfil.0.readonly();
|
|
374
|
+
let yfilro = xyzfil.1.readonly();
|
|
375
|
+
let zfilro = xyzfil.2.readonly();
|
|
376
|
+
let xyzfil = (xfilro.as_slice()?, yfilro.as_slice()?, zfilro.as_slice()?);
|
|
377
|
+
|
|
378
|
+
let dlxfilro = dlxyzfil.0.readonly();
|
|
379
|
+
let dlyfilro = dlxyzfil.1.readonly();
|
|
380
|
+
let dlzfilro = dlxyzfil.2.readonly();
|
|
381
|
+
let dlxyzfil = (
|
|
382
|
+
dlxfilro.as_slice()?,
|
|
383
|
+
dlyfilro.as_slice()?,
|
|
384
|
+
dlzfilro.as_slice()?,
|
|
385
|
+
);
|
|
386
|
+
let ifilro = ifil.readonly();
|
|
387
|
+
let ifil = ifilro.as_slice()?;
|
|
388
|
+
|
|
389
|
+
// Do calculations
|
|
390
|
+
let n = xyzp.0.len();
|
|
391
|
+
let (mut outx, mut outy, mut outz) = (vec![0.0; n], vec![0.0; n], vec![0.0; n]);
|
|
392
|
+
|
|
393
|
+
let func = match par {
|
|
394
|
+
true => physics::linear_filament::vector_potential_linear_filament_par,
|
|
395
|
+
false => physics::linear_filament::vector_potential_linear_filament,
|
|
396
|
+
};
|
|
397
|
+
match func(
|
|
398
|
+
xyzp,
|
|
399
|
+
xyzfil,
|
|
400
|
+
dlxyzfil,
|
|
401
|
+
ifil,
|
|
402
|
+
(&mut outx, &mut outy, &mut outz),
|
|
403
|
+
) {
|
|
404
|
+
Ok(x) => x,
|
|
405
|
+
Err(x) => {
|
|
406
|
+
let err: PyErr = PyInteropError::DimensionalityError { msg: x.to_string() }.into();
|
|
407
|
+
return Err(err);
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
// Acquire global interpreter lock, which will be released when it goes out of scope
|
|
412
|
+
Python::with_gil(|py| {
|
|
413
|
+
let bx: Py<PyArray1<f64>> = PyArray1::from_vec_bound(py, outx).unbind();
|
|
414
|
+
let by: Py<PyArray1<f64>> = PyArray1::from_vec_bound(py, outy).unbind();
|
|
415
|
+
let bz: Py<PyArray1<f64>> = PyArray1::from_vec_bound(py, outz).unbind();
|
|
416
|
+
|
|
417
|
+
Ok((bx, by, bz))
|
|
418
|
+
})
|
|
419
|
+
}
|
|
420
|
+
|
|
283
421
|
#[pyfunction]
|
|
284
422
|
fn inductance_piecewise_linear_filaments<'py>(
|
|
285
423
|
xyzfil0: (
|
|
@@ -430,15 +568,27 @@ fn ellipk(x: f64) -> f64 {
|
|
|
430
568
|
fn _cfsem<'py>(_py: Python, m: Bound<'py, PyModule>) -> PyResult<()> {
|
|
431
569
|
m.add_function(wrap_pyfunction!(flux_circular_filament, m.clone())?)?;
|
|
432
570
|
m.add_function(wrap_pyfunction!(flux_density_circular_filament, m.clone())?)?;
|
|
433
|
-
m.add_function(wrap_pyfunction!(
|
|
571
|
+
m.add_function(wrap_pyfunction!(
|
|
572
|
+
vector_potential_circular_filament,
|
|
573
|
+
m.clone()
|
|
574
|
+
)?)?;
|
|
575
|
+
|
|
576
|
+
m.add_function(wrap_pyfunction!(flux_density_linear_filament, m.clone())?)?;
|
|
577
|
+
m.add_function(wrap_pyfunction!(
|
|
578
|
+
vector_potential_linear_filament,
|
|
579
|
+
m.clone()
|
|
580
|
+
)?)?;
|
|
434
581
|
m.add_function(wrap_pyfunction!(
|
|
435
582
|
inductance_piecewise_linear_filaments,
|
|
436
583
|
m.clone()
|
|
437
584
|
)?)?;
|
|
585
|
+
|
|
438
586
|
m.add_function(wrap_pyfunction!(gs_operator_order2, m.clone())?)?;
|
|
439
587
|
m.add_function(wrap_pyfunction!(gs_operator_order4, m.clone())?)?;
|
|
588
|
+
|
|
440
589
|
m.add_function(wrap_pyfunction!(ellipe, m.clone())?)?;
|
|
441
590
|
m.add_function(wrap_pyfunction!(ellipk, m.clone())?)?;
|
|
591
|
+
|
|
442
592
|
m.add_function(wrap_pyfunction!(filament_helix_path, m.clone())?)?;
|
|
443
593
|
m.add_function(wrap_pyfunction!(rotate_filaments_about_path, m.clone())?)?;
|
|
444
594
|
Ok(())
|
|
@@ -39,12 +39,13 @@ def test_self_inductance_piecewise_linear_filaments(r, z, h):
|
|
|
39
39
|
@mark.parametrize("r1", [0.5, np.pi])
|
|
40
40
|
@mark.parametrize("r2", [0.1, np.pi / 10.0])
|
|
41
41
|
@mark.parametrize("z", [0.0, np.e / 2, -np.e / 2])
|
|
42
|
-
|
|
42
|
+
@mark.parametrize("par", [True, False])
|
|
43
|
+
def test_mutual_inductance_piecewise_linear_filaments(r1, r2, z, par):
|
|
43
44
|
# Test against calc for mutual inductance of circular filaments
|
|
44
45
|
rzn1 = np.array([[r1], [z], [1.0]])
|
|
45
46
|
rzn2 = np.array([[r2], [-z / np.e], [1.0]])
|
|
46
47
|
|
|
47
|
-
m_circular = cfsem.mutual_inductance_of_circular_filaments(rzn1, rzn2)
|
|
48
|
+
m_circular = cfsem.mutual_inductance_of_circular_filaments(rzn1, rzn2, par)
|
|
48
49
|
|
|
49
50
|
n = 100
|
|
50
51
|
|
|
@@ -126,7 +127,7 @@ def test_biot_savart_against_flux_density_circular_filament(r, z, par):
|
|
|
126
127
|
# Circular filament calc
|
|
127
128
|
# [T]
|
|
128
129
|
Br_circular, Bz_circular = cfsem.flux_density_circular_filament(
|
|
129
|
-
np.ones(1), np.array([r]), np.array([z]), rprime, zprime
|
|
130
|
+
np.ones(1), np.array([r]), np.array([z]), rprime, zprime, par
|
|
130
131
|
)
|
|
131
132
|
|
|
132
133
|
# Biot-Savart calc
|
|
@@ -149,7 +150,10 @@ def test_biot_savart_against_flux_density_circular_filament(r, z, par):
|
|
|
149
150
|
|
|
150
151
|
@mark.parametrize("r", [0.775, np.pi])
|
|
151
152
|
@mark.parametrize("z", [0.0, np.e / 2, -np.e / 2])
|
|
152
|
-
|
|
153
|
+
@mark.parametrize("par", [True, False])
|
|
154
|
+
def test_flux_circular_filament_against_mutual_inductance_of_cylindrical_coils(
|
|
155
|
+
r, z, par
|
|
156
|
+
):
|
|
153
157
|
# Two single-turn coils with irrelevant cross-section,
|
|
154
158
|
# each discretized into a single filament
|
|
155
159
|
rc1 = r # Coil center radii
|
|
@@ -165,7 +169,7 @@ def test_flux_circular_filament_against_mutual_inductance_of_cylindrical_coils(r
|
|
|
165
169
|
# Calculate mutual inductance between these two filaments
|
|
166
170
|
f1 = np.array((r1, z1, n1))
|
|
167
171
|
f2 = np.array((r2, z2, n2))
|
|
168
|
-
m_filaments = cfsem.mutual_inductance_of_cylindrical_coils(f1, f2)
|
|
172
|
+
m_filaments = cfsem.mutual_inductance_of_cylindrical_coils(f1, f2, par)
|
|
169
173
|
|
|
170
174
|
# Calculate mutual inductance via python test calc
|
|
171
175
|
# and test the mutual inductance of coils calc.
|
|
@@ -175,8 +179,8 @@ def test_flux_circular_filament_against_mutual_inductance_of_cylindrical_coils(r
|
|
|
175
179
|
assert abs(1 - m_filaments / m_filaments_test) < 1e-6
|
|
176
180
|
|
|
177
181
|
# Do flux calcs
|
|
178
|
-
psi_2to1 = np.sum(n1 * cfsem.flux_circular_filament(n2, r2, z2, r1, z1))
|
|
179
|
-
psi_1to2 = np.sum(n2 * cfsem.flux_circular_filament(n1, r1, z1, r2, z2))
|
|
182
|
+
psi_2to1 = np.sum(n1 * cfsem.flux_circular_filament(n2, r2, z2, r1, z1, par))
|
|
183
|
+
psi_1to2 = np.sum(n2 * cfsem.flux_circular_filament(n1, r1, z1, r2, z2, par))
|
|
180
184
|
|
|
181
185
|
# Because the integrated poloidal flux at a given location is the same as mutual inductance,
|
|
182
186
|
# we should get the same number using our mutual inductance calc
|
|
@@ -191,7 +195,8 @@ def test_flux_circular_filament_against_mutual_inductance_of_cylindrical_coils(r
|
|
|
191
195
|
|
|
192
196
|
@mark.parametrize("r", [0.775, np.pi])
|
|
193
197
|
@mark.parametrize("z", [0.0, np.e / 2, -np.e / 2])
|
|
194
|
-
|
|
198
|
+
@mark.parametrize("par", [True, False])
|
|
199
|
+
def test_flux_density_circular_filament_against_flux_circular_filament(r, z, par):
|
|
195
200
|
rzn1 = cfsem.filament_coil(r, z, 0.05, 0.05, 1.0, 4, 4)
|
|
196
201
|
rfil, zfil, _ = rzn1.T
|
|
197
202
|
ifil = np.ones_like(rfil)
|
|
@@ -204,7 +209,7 @@ def test_flux_density_circular_filament_against_flux_circular_filament(r, z):
|
|
|
204
209
|
zprime = Z.flatten()
|
|
205
210
|
|
|
206
211
|
Br, Bz = cfsem.flux_density_circular_filament(
|
|
207
|
-
ifil, rfil, zfil, rprime, zprime
|
|
212
|
+
ifil, rfil, zfil, rprime, zprime, par
|
|
208
213
|
) # [T]
|
|
209
214
|
|
|
210
215
|
# We can also get B from the derivative of the flux function (Wesson eqn 3.2.2),
|
|
@@ -216,12 +221,12 @@ def test_flux_density_circular_filament_against_flux_circular_filament(r, z):
|
|
|
216
221
|
|
|
217
222
|
dr = 1e-4
|
|
218
223
|
dz = 1e-4
|
|
219
|
-
psi = cfsem.flux_circular_filament(ifil, rfil, zfil, rprime, zprime)
|
|
224
|
+
psi = cfsem.flux_circular_filament(ifil, rfil, zfil, rprime, zprime, par)
|
|
220
225
|
dpsidz = (
|
|
221
|
-
cfsem.flux_circular_filament(ifil, rfil, zfil, rprime, zprime + dz) - psi
|
|
226
|
+
cfsem.flux_circular_filament(ifil, rfil, zfil, rprime, zprime + dz, par) - psi
|
|
222
227
|
) / dz
|
|
223
228
|
dpsidr = (
|
|
224
|
-
cfsem.flux_circular_filament(ifil, rfil, zfil, rprime + dr, zprime) - psi
|
|
229
|
+
cfsem.flux_circular_filament(ifil, rfil, zfil, rprime + dr, zprime, par) - psi
|
|
225
230
|
) / dr
|
|
226
231
|
|
|
227
232
|
Br_from_psi = -dpsidz / rprime / (2.0 * np.pi) # [T]
|
|
@@ -232,7 +237,8 @@ def test_flux_density_circular_filament_against_flux_circular_filament(r, z):
|
|
|
232
237
|
|
|
233
238
|
|
|
234
239
|
@mark.parametrize("r", [np.e / 100, 0.775, np.pi])
|
|
235
|
-
|
|
240
|
+
@mark.parametrize("par", [True, False])
|
|
241
|
+
def test_flux_density_circular_filament_against_ideal_solenoid(r, par):
|
|
236
242
|
# We can also check against the ideal solenoid calc to make sure we don't have a systematic
|
|
237
243
|
# offset or scaling error
|
|
238
244
|
|
|
@@ -245,14 +251,15 @@ def test_flux_density_circular_filament_against_ideal_solenoid(r):
|
|
|
245
251
|
current=1.0, num_turns=ifil.size, length=length
|
|
246
252
|
) # [T] ideal solenoid Bz at origin
|
|
247
253
|
_, bz_origin = cfsem.flux_density_circular_filament(
|
|
248
|
-
ifil, rfil, zfil, np.zeros(1), np.zeros(1)
|
|
254
|
+
ifil, rfil, zfil, np.zeros(1), np.zeros(1), par
|
|
249
255
|
)
|
|
250
256
|
|
|
251
257
|
assert np.allclose(np.array([b_ideal]), bz_origin, rtol=1e-2)
|
|
252
258
|
|
|
253
259
|
|
|
254
260
|
@mark.parametrize("r", [np.e / 100, 0.775, np.pi])
|
|
255
|
-
|
|
261
|
+
@mark.parametrize("par", [True, False])
|
|
262
|
+
def test_flux_density_circular_filament_against_ideal_loop(r, par):
|
|
256
263
|
# We can also check against an ideal current loop calc
|
|
257
264
|
# http://hyperphysics.phy-astr.gsu.edu/hbase/magnetic/curloo.html
|
|
258
265
|
|
|
@@ -263,7 +270,7 @@ def test_flux_density_circular_filament_against_ideal_loop(r):
|
|
|
263
270
|
|
|
264
271
|
b_ideal = cfsem.MU_0 * current / (2.0 * r) # [T] ideal loop Bz at origin
|
|
265
272
|
_, bz_origin = cfsem.flux_density_circular_filament(
|
|
266
|
-
ifil, rfil, zfil, np.zeros(1), np.zeros(1)
|
|
273
|
+
ifil, rfil, zfil, np.zeros(1), np.zeros(1), par
|
|
267
274
|
)
|
|
268
275
|
|
|
269
276
|
assert np.allclose(np.array([b_ideal]), bz_origin, rtol=1e-6)
|
|
@@ -271,7 +278,8 @@ def test_flux_density_circular_filament_against_ideal_loop(r):
|
|
|
271
278
|
|
|
272
279
|
@mark.parametrize("a", [0.775, np.pi])
|
|
273
280
|
@mark.parametrize("z", [0.0, np.e / 2, -np.e / 2])
|
|
274
|
-
|
|
281
|
+
@mark.parametrize("par", [True, False])
|
|
282
|
+
def test_flux_density_circular_filament_against_numerical(a, z, par):
|
|
275
283
|
# Test the elliptic-integral calc for B-field of a loop against numerical integration
|
|
276
284
|
|
|
277
285
|
n = 10
|
|
@@ -286,7 +294,7 @@ def test_flux_density_circular_filament_against_numerical(a, z):
|
|
|
286
294
|
|
|
287
295
|
# Calc using elliptic integral fits
|
|
288
296
|
Br, Bz = cfsem.flux_density_circular_filament(
|
|
289
|
-
np.array([I]), np.array([a]), np.array([z]), rprime, zprime
|
|
297
|
+
np.array([I]), np.array([a]), np.array([z]), rprime, zprime, par
|
|
290
298
|
) # [T]
|
|
291
299
|
|
|
292
300
|
# Calc using numerical integration around the loop
|
|
@@ -302,7 +310,8 @@ def test_flux_density_circular_filament_against_numerical(a, z):
|
|
|
302
310
|
assert np.allclose(Bz, Bz_num)
|
|
303
311
|
|
|
304
312
|
|
|
305
|
-
|
|
313
|
+
@mark.parametrize("par", [True, False])
|
|
314
|
+
def test_self_inductance_lyle6_against_filamentization_and_distributed(par):
|
|
306
315
|
# Test that the Lyle approximation gives a similar result to
|
|
307
316
|
# a case done by brute-force filamentization w/ a heuristic for self-inductance of a loop
|
|
308
317
|
r, z, dr, dz, nt, nr, nz = (0.8, 0.0, 0.5, 2.0, 3.0, 20, 20)
|
|
@@ -323,11 +332,11 @@ def test_self_inductance_lyle6_against_filamentization_and_distributed():
|
|
|
323
332
|
# Do filamentized psi and B calcs for convenience,
|
|
324
333
|
# although ideally we'd do a grad-shafranov solve here for a smoother field
|
|
325
334
|
psi = cfsem.flux_circular_filament(
|
|
326
|
-
current, rfil, zfil, rmesh.flatten(), zmesh.flatten()
|
|
335
|
+
current, rfil, zfil, rmesh.flatten(), zmesh.flatten(), par
|
|
327
336
|
)
|
|
328
337
|
psi = psi.reshape(rmesh.shape)
|
|
329
338
|
br, bz = cfsem.flux_density_circular_filament(
|
|
330
|
-
current, rfil, zfil, rmesh.flatten(), zmesh.flatten()
|
|
339
|
+
current, rfil, zfil, rmesh.flatten(), zmesh.flatten(), par
|
|
331
340
|
)
|
|
332
341
|
br = br.reshape(rmesh.shape)
|
|
333
342
|
bz = bz.reshape(rmesh.shape)
|
|
@@ -505,3 +514,77 @@ def test_self_inductance_annular_ring(major_radius, a, b):
|
|
|
505
514
|
with raises(ValueError):
|
|
506
515
|
# Larger outer than major
|
|
507
516
|
cfsem.self_inductance_annular_ring(0.1, 0.01, 0.11)
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
@mark.parametrize("r", [0.775, 1.51])
|
|
520
|
+
@mark.parametrize("z", [0.0, np.pi])
|
|
521
|
+
@mark.parametrize("par", [True, False])
|
|
522
|
+
def test_vector_potential_axisymmetric(r, z, par):
|
|
523
|
+
# Spot-check vector potential against inductance calcs.
|
|
524
|
+
# More detailed three-way tests against both B-field and inductance
|
|
525
|
+
# are done in the Rust library.
|
|
526
|
+
|
|
527
|
+
# Filament
|
|
528
|
+
ifil = np.atleast_1d([1.0]) # [A] 1A total reference current
|
|
529
|
+
rfil = np.atleast_1d([r])
|
|
530
|
+
zfil = np.atleast_1d([z])
|
|
531
|
+
|
|
532
|
+
# Observation points
|
|
533
|
+
rgrid = np.arange(0.5, 2.0, 0.05)
|
|
534
|
+
zgrid = np.arange(-3.0, 3.0, 0.05)
|
|
535
|
+
rmesh, zmesh = np.meshgrid(rgrid, zgrid, indexing="ij")
|
|
536
|
+
|
|
537
|
+
psi = cfsem.flux_circular_filament(
|
|
538
|
+
ifil, rfil, zfil, rmesh.flatten(), zmesh.flatten(), par
|
|
539
|
+
)
|
|
540
|
+
a_phi = cfsem.vector_potential_circular_filament(
|
|
541
|
+
ifil, rfil, zfil, rmesh.flatten(), zmesh.flatten(), par
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
# Integrate vector potential around a loop to get the flux
|
|
545
|
+
psi_from_a = 2.0 * np.pi * rmesh.flatten() * a_phi # [Wb]
|
|
546
|
+
|
|
547
|
+
# We should not be able to tell the difference above a single roundoff
|
|
548
|
+
assert np.allclose(psi, psi_from_a, rtol=1e-16, atol=1e-16)
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
@mark.parametrize("r", [0.775, np.pi])
|
|
552
|
+
@mark.parametrize("z", [0.0, np.e / 2, -np.e / 2])
|
|
553
|
+
@mark.parametrize("par", [True, False])
|
|
554
|
+
def test_vector_potential_linear_against_circular_filament(r, z, par):
|
|
555
|
+
# Note we are mapping between (x, y, z) and (r, phi, z) coordinates here
|
|
556
|
+
|
|
557
|
+
# Biot-Savart filaments in cartesian coords
|
|
558
|
+
n_filaments = int(1e4)
|
|
559
|
+
phi = np.linspace(0.0, 2.0 * np.pi, n_filaments)
|
|
560
|
+
xfils = r * np.cos(phi)
|
|
561
|
+
yfils = r * np.sin(phi)
|
|
562
|
+
zfils = np.ones_like(xfils) * z
|
|
563
|
+
|
|
564
|
+
# Observation grid
|
|
565
|
+
rs = np.linspace(0.01, r - 0.1, 10)
|
|
566
|
+
zs = np.linspace(-1.0, 1.0, 10)
|
|
567
|
+
|
|
568
|
+
rmesh, zmesh = np.meshgrid(rs, zs, indexing="ij")
|
|
569
|
+
rprime = rmesh.flatten()
|
|
570
|
+
zprime = zmesh.flatten()
|
|
571
|
+
|
|
572
|
+
# Circular filament calc
|
|
573
|
+
a_phi = cfsem.vector_potential_circular_filament(
|
|
574
|
+
np.ones(1), np.array([r]), np.array([z]), rprime, zprime, par
|
|
575
|
+
) # [V-s/m]
|
|
576
|
+
|
|
577
|
+
# Biot-Savart calc
|
|
578
|
+
xyzp = (rprime, np.zeros_like(zprime), zprime)
|
|
579
|
+
xyzfil = (xfils[1:], yfils[1:], zfils[1:])
|
|
580
|
+
dlxyzfil = (xfils[1:] - xfils[:-1], yfils[1:] - yfils[:-1], zfils[1:] - zfils[:-1])
|
|
581
|
+
ifil = np.ones_like(xfils[1:])
|
|
582
|
+
ax, ay, az = cfsem.vector_potential_linear_filament(
|
|
583
|
+
xyzp, xyzfil, dlxyzfil, ifil, par
|
|
584
|
+
) # [V-s/m]
|
|
585
|
+
|
|
586
|
+
assert np.allclose(a_phi, ay, rtol=1e-12, atol=1e-12) # Should match circular calc
|
|
587
|
+
assert np.allclose(
|
|
588
|
+
az, np.zeros_like(az), atol=1e-9
|
|
589
|
+
) # Should sum to zero everywhere
|
|
590
|
+
assert np.allclose(ax, np.zeros_like(ax), atol=1e-9) # ...
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|