cfsem 2.4.3__tar.gz → 2.6.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.4.3 → cfsem-2.6.0}/.github/workflows/test_python.yml +4 -1
- cfsem-2.6.0/CHANGELOG.md +32 -0
- cfsem-2.4.3/CHANGELOG_PYTHON.md → cfsem-2.6.0/CHANGELOG_PYTHON_ARCHIVE.md +11 -0
- cfsem-2.4.3/CHANGELOG_RUST.md → cfsem-2.6.0/CHANGELOG_RUST_ARCHIVE.md +1 -1
- {cfsem-2.4.3 → cfsem-2.6.0}/Cargo.lock +133 -22
- {cfsem-2.4.3 → cfsem-2.6.0}/Cargo.toml +5 -5
- cfsem-2.6.0/PKG-INFO +27 -0
- cfsem-2.6.0/cfsem/solenoid_stress/solenoid_1d.py +317 -0
- cfsem-2.6.0/cfsem/solenoid_stress/solenoid_handcalc.py +91 -0
- cfsem-2.6.0/cfsem/solenoid_stress/thick_wall_cylinder_handcalc.py +69 -0
- cfsem-2.6.0/docs/python/solenoid_stress.md +5 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/examples/helmholtz.py +3 -1
- {cfsem-2.4.3 → cfsem-2.6.0}/examples/inductance.py +1 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/mkdocs.yml +2 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/pyproject.toml +5 -2
- {cfsem-2.4.3 → cfsem-2.6.0}/src/lib.rs +1 -1
- {cfsem-2.4.3 → cfsem-2.6.0}/src/math.rs +29 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/src/physics/circular_filament.rs +1 -1
- {cfsem-2.4.3 → cfsem-2.6.0}/src/physics/linear_filament.rs +20 -9
- cfsem-2.6.0/test/__init__.py +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/test/test_electromagnetics.py +2 -2
- {cfsem-2.4.3 → cfsem-2.6.0}/test/test_funcs.py +2 -1
- cfsem-2.6.0/test/test_solenoid_stress.py +290 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/uv.lock +240 -110
- cfsem-2.4.3/PKG-INFO +0 -124
- {cfsem-2.4.3 → cfsem-2.6.0}/.cargo/config.toml +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/.github/workflows/release_python.yml +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/.github/workflows/release_rust.yml +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/.github/workflows/test_rust.yml +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/.gitignore +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/.readthedocs.yml +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/CONTRIBUTING.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/LICENSE +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/README.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/benches/circular_filament.rs +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/benches/linear_filament.rs +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/build_docs.sh +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/cfsem/__init__.py +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/cfsem/bindings.py +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/cfsem/py.typed +0 -0
- {cfsem-2.4.3/test → cfsem-2.6.0/cfsem/solenoid_stress}/__init__.py +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/cfsem/types.py +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/assets/logo.svg +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/index.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/javascripts/mathjax.js +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/python/example_outputs/.placeholder +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/python/examples.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/python/filament.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/python/flux_density.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/python/force.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/python/grad_shafranov.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/python/inductance.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/python/math.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/python/types.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/python/vector_potential.md +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/requirements.txt +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/docs/stylesheets/extra.css +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/katex-header.html +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/src/mesh.rs +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/src/physics/biotsavart.rs +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/src/physics/gradshafranov.rs +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/src/physics/mesh_filament.rs +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/src/physics/mod.rs +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/src/physics/point_source.rs +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/src/python.rs +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/src/testing.rs +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/test/test_examples.py +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/test/test_filaments.py +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/test/test_gradshafranov.py +0 -0
- {cfsem-2.4.3 → cfsem-2.6.0}/test/test_math.py +0 -0
cfsem-2.6.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
See archived changelogs for versions prior to 2.6.0.
|
|
4
|
+
|
|
5
|
+
## 2.6.0 2025-10-15
|
|
6
|
+
|
|
7
|
+
Substantial performance improvement for `flux_density_linear_filament` Biot-Savart methods.
|
|
8
|
+
This also improves performance in calculations that use these methods, such as linear filament
|
|
9
|
+
body force density calcs.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
* Rust
|
|
14
|
+
* Add `dot3f` and `cross3f` 32-bit float variants
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
* Rust
|
|
19
|
+
* Use mixed-precision method for `flux_density_linear_filament_scalar`
|
|
20
|
+
* High-dynamic-range part of the calc is still done using 64-bit floats
|
|
21
|
+
* Low-dynamic-range part of the calc is now done using 32-bit floats
|
|
22
|
+
* _All_ addition operations in 32-bit section are done using
|
|
23
|
+
fused multiply-add operations, usually chained to defer
|
|
24
|
+
roundoff to final operation. As a result, total roundoff error
|
|
25
|
+
accumulated in this section is minimal.
|
|
26
|
+
* Return is upcast back to 64-bit float to support precise summation downstream
|
|
27
|
+
* 1.4-2x speedup without any meaningful loss of precision
|
|
28
|
+
* No change to unit test tolerances needed; unlike an all-32-bit implementation,
|
|
29
|
+
this mixed-precision method passes all the same tests as the 64-bit-only method
|
|
30
|
+
* Python
|
|
31
|
+
* Update dep versions
|
|
32
|
+
* Use latest rust backend version, which includes 1.4-2x speedup for flux_density_linear_filament Biot-Savart calcs
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.5.0 2025-08-05
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
* Add `solenoid_stress` module
|
|
8
|
+
* 1D finite-difference solver for solenoid stress given arbitrary B-field, current density, and surface load
|
|
9
|
+
* Generalizes over both long-solenoid stress and ideal thick-walled pressure vessel stress
|
|
10
|
+
* Tested against handcalcs for both ideal solenoid & thick-walled pressure vessel
|
|
11
|
+
* 1D handcalc for solenoid stress under uniform current density and linear B-field profile
|
|
12
|
+
* 1D handcalc for thick-walled pressure vessel
|
|
13
|
+
|
|
3
14
|
## 2.4.3 2025-07-07
|
|
4
15
|
|
|
5
16
|
### Changed
|
|
@@ -64,7 +64,7 @@ checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
|
|
64
64
|
|
|
65
65
|
[[package]]
|
|
66
66
|
name = "cfsem"
|
|
67
|
-
version = "2.
|
|
67
|
+
version = "2.6.0"
|
|
68
68
|
dependencies = [
|
|
69
69
|
"criterion",
|
|
70
70
|
"itertools 0.14.0",
|
|
@@ -201,6 +201,102 @@ version = "1.15.0"
|
|
|
201
201
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
202
202
|
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
|
203
203
|
|
|
204
|
+
[[package]]
|
|
205
|
+
name = "glam"
|
|
206
|
+
version = "0.14.0"
|
|
207
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
208
|
+
checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da"
|
|
209
|
+
|
|
210
|
+
[[package]]
|
|
211
|
+
name = "glam"
|
|
212
|
+
version = "0.15.2"
|
|
213
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
214
|
+
checksum = "3abb554f8ee44336b72d522e0a7fe86a29e09f839a36022fa869a7dfe941a54b"
|
|
215
|
+
|
|
216
|
+
[[package]]
|
|
217
|
+
name = "glam"
|
|
218
|
+
version = "0.16.0"
|
|
219
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
220
|
+
checksum = "4126c0479ccf7e8664c36a2d719f5f2c140fbb4f9090008098d2c291fa5b3f16"
|
|
221
|
+
|
|
222
|
+
[[package]]
|
|
223
|
+
name = "glam"
|
|
224
|
+
version = "0.17.3"
|
|
225
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
226
|
+
checksum = "e01732b97afd8508eee3333a541b9f7610f454bb818669e66e90f5f57c93a776"
|
|
227
|
+
|
|
228
|
+
[[package]]
|
|
229
|
+
name = "glam"
|
|
230
|
+
version = "0.18.0"
|
|
231
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
232
|
+
checksum = "525a3e490ba77b8e326fb67d4b44b4bd2f920f44d4cc73ccec50adc68e3bee34"
|
|
233
|
+
|
|
234
|
+
[[package]]
|
|
235
|
+
name = "glam"
|
|
236
|
+
version = "0.19.0"
|
|
237
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
238
|
+
checksum = "2b8509e6791516e81c1a630d0bd7fbac36d2fa8712a9da8662e716b52d5051ca"
|
|
239
|
+
|
|
240
|
+
[[package]]
|
|
241
|
+
name = "glam"
|
|
242
|
+
version = "0.20.5"
|
|
243
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
244
|
+
checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f"
|
|
245
|
+
|
|
246
|
+
[[package]]
|
|
247
|
+
name = "glam"
|
|
248
|
+
version = "0.21.3"
|
|
249
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
250
|
+
checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815"
|
|
251
|
+
|
|
252
|
+
[[package]]
|
|
253
|
+
name = "glam"
|
|
254
|
+
version = "0.22.0"
|
|
255
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
256
|
+
checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774"
|
|
257
|
+
|
|
258
|
+
[[package]]
|
|
259
|
+
name = "glam"
|
|
260
|
+
version = "0.23.0"
|
|
261
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
262
|
+
checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c"
|
|
263
|
+
|
|
264
|
+
[[package]]
|
|
265
|
+
name = "glam"
|
|
266
|
+
version = "0.24.2"
|
|
267
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
268
|
+
checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945"
|
|
269
|
+
|
|
270
|
+
[[package]]
|
|
271
|
+
name = "glam"
|
|
272
|
+
version = "0.25.0"
|
|
273
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
274
|
+
checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
|
|
275
|
+
|
|
276
|
+
[[package]]
|
|
277
|
+
name = "glam"
|
|
278
|
+
version = "0.27.0"
|
|
279
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
280
|
+
checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9"
|
|
281
|
+
|
|
282
|
+
[[package]]
|
|
283
|
+
name = "glam"
|
|
284
|
+
version = "0.28.0"
|
|
285
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
286
|
+
checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
|
|
287
|
+
|
|
288
|
+
[[package]]
|
|
289
|
+
name = "glam"
|
|
290
|
+
version = "0.29.3"
|
|
291
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
292
|
+
checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee"
|
|
293
|
+
|
|
294
|
+
[[package]]
|
|
295
|
+
name = "glam"
|
|
296
|
+
version = "0.30.8"
|
|
297
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
298
|
+
checksum = "e12d847aeb25f41be4c0ec9587d624e9cd631bc007a8fd7ce3f5851e064c6460"
|
|
299
|
+
|
|
204
300
|
[[package]]
|
|
205
301
|
name = "half"
|
|
206
302
|
version = "2.6.0"
|
|
@@ -319,11 +415,27 @@ dependencies = [
|
|
|
319
415
|
|
|
320
416
|
[[package]]
|
|
321
417
|
name = "nalgebra"
|
|
322
|
-
version = "0.
|
|
418
|
+
version = "0.34.1"
|
|
323
419
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
324
|
-
checksum = "
|
|
420
|
+
checksum = "c4d5b3eff5cd580f93da45e64715e8c20a3996342f1e466599cf7a267a0c2f5f"
|
|
325
421
|
dependencies = [
|
|
326
422
|
"approx",
|
|
423
|
+
"glam 0.14.0",
|
|
424
|
+
"glam 0.15.2",
|
|
425
|
+
"glam 0.16.0",
|
|
426
|
+
"glam 0.17.3",
|
|
427
|
+
"glam 0.18.0",
|
|
428
|
+
"glam 0.19.0",
|
|
429
|
+
"glam 0.20.5",
|
|
430
|
+
"glam 0.21.3",
|
|
431
|
+
"glam 0.22.0",
|
|
432
|
+
"glam 0.23.0",
|
|
433
|
+
"glam 0.24.2",
|
|
434
|
+
"glam 0.25.0",
|
|
435
|
+
"glam 0.27.0",
|
|
436
|
+
"glam 0.28.0",
|
|
437
|
+
"glam 0.29.3",
|
|
438
|
+
"glam 0.30.8",
|
|
327
439
|
"matrixmultiply",
|
|
328
440
|
"nalgebra-macros",
|
|
329
441
|
"num-complex",
|
|
@@ -335,9 +447,9 @@ dependencies = [
|
|
|
335
447
|
|
|
336
448
|
[[package]]
|
|
337
449
|
name = "nalgebra-macros"
|
|
338
|
-
version = "0.
|
|
450
|
+
version = "0.3.0"
|
|
339
451
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
340
|
-
checksum = "
|
|
452
|
+
checksum = "973e7178a678cfd059ccec50887658d482ce16b0aa9da3888ddeab5cd5eb4889"
|
|
341
453
|
dependencies = [
|
|
342
454
|
"proc-macro2",
|
|
343
455
|
"quote",
|
|
@@ -410,9 +522,9 @@ dependencies = [
|
|
|
410
522
|
|
|
411
523
|
[[package]]
|
|
412
524
|
name = "numpy"
|
|
413
|
-
version = "0.
|
|
525
|
+
version = "0.26.0"
|
|
414
526
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
415
|
-
checksum = "
|
|
527
|
+
checksum = "9b2dba356160b54f5371b550575b78130a54718b4c6e46b3f33a6da74a27e78b"
|
|
416
528
|
dependencies = [
|
|
417
529
|
"libc",
|
|
418
530
|
"ndarray",
|
|
@@ -496,9 +608,9 @@ dependencies = [
|
|
|
496
608
|
|
|
497
609
|
[[package]]
|
|
498
610
|
name = "pyo3"
|
|
499
|
-
version = "0.
|
|
611
|
+
version = "0.26.0"
|
|
500
612
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
501
|
-
checksum = "
|
|
613
|
+
checksum = "7ba0117f4212101ee6544044dae45abe1083d30ce7b29c4b5cbdfa2354e07383"
|
|
502
614
|
dependencies = [
|
|
503
615
|
"indoc",
|
|
504
616
|
"libc",
|
|
@@ -513,19 +625,18 @@ dependencies = [
|
|
|
513
625
|
|
|
514
626
|
[[package]]
|
|
515
627
|
name = "pyo3-build-config"
|
|
516
|
-
version = "0.
|
|
628
|
+
version = "0.26.0"
|
|
517
629
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
518
|
-
checksum = "
|
|
630
|
+
checksum = "4fc6ddaf24947d12a9aa31ac65431fb1b851b8f4365426e182901eabfb87df5f"
|
|
519
631
|
dependencies = [
|
|
520
|
-
"once_cell",
|
|
521
632
|
"target-lexicon",
|
|
522
633
|
]
|
|
523
634
|
|
|
524
635
|
[[package]]
|
|
525
636
|
name = "pyo3-ffi"
|
|
526
|
-
version = "0.
|
|
637
|
+
version = "0.26.0"
|
|
527
638
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
528
|
-
checksum = "
|
|
639
|
+
checksum = "025474d3928738efb38ac36d4744a74a400c901c7596199e20e45d98eb194105"
|
|
529
640
|
dependencies = [
|
|
530
641
|
"libc",
|
|
531
642
|
"pyo3-build-config",
|
|
@@ -533,9 +644,9 @@ dependencies = [
|
|
|
533
644
|
|
|
534
645
|
[[package]]
|
|
535
646
|
name = "pyo3-macros"
|
|
536
|
-
version = "0.
|
|
647
|
+
version = "0.26.0"
|
|
537
648
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
538
|
-
checksum = "
|
|
649
|
+
checksum = "2e64eb489f22fe1c95911b77c44cc41e7c19f3082fc81cce90f657cdc42ffded"
|
|
539
650
|
dependencies = [
|
|
540
651
|
"proc-macro2",
|
|
541
652
|
"pyo3-macros-backend",
|
|
@@ -545,9 +656,9 @@ dependencies = [
|
|
|
545
656
|
|
|
546
657
|
[[package]]
|
|
547
658
|
name = "pyo3-macros-backend"
|
|
548
|
-
version = "0.
|
|
659
|
+
version = "0.26.0"
|
|
549
660
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
550
|
-
checksum = "
|
|
661
|
+
checksum = "100246c0ecf400b475341b8455a9213344569af29a3c841d29270e53102e0fcf"
|
|
551
662
|
dependencies = [
|
|
552
663
|
"heck",
|
|
553
664
|
"proc-macro2",
|
|
@@ -573,9 +684,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
|
|
573
684
|
|
|
574
685
|
[[package]]
|
|
575
686
|
name = "rayon"
|
|
576
|
-
version = "1.
|
|
687
|
+
version = "1.11.0"
|
|
577
688
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
578
|
-
checksum = "
|
|
689
|
+
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
|
|
579
690
|
dependencies = [
|
|
580
691
|
"either",
|
|
581
692
|
"rayon-core",
|
|
@@ -583,9 +694,9 @@ dependencies = [
|
|
|
583
694
|
|
|
584
695
|
[[package]]
|
|
585
696
|
name = "rayon-core"
|
|
586
|
-
version = "1.
|
|
697
|
+
version = "1.13.0"
|
|
587
698
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
588
|
-
checksum = "
|
|
699
|
+
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
|
589
700
|
dependencies = [
|
|
590
701
|
"crossbeam-deque",
|
|
591
702
|
"crossbeam-utils",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "cfsem"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.6.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
authors = ["Commonwealth Fusion Systems <jlogan@cfs.energy>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -15,11 +15,11 @@ name = "cfsem"
|
|
|
15
15
|
crate-type = ["cdylib", "rlib"]
|
|
16
16
|
|
|
17
17
|
[dependencies]
|
|
18
|
-
pyo3 = { version="0.
|
|
19
|
-
numpy = { version="0.
|
|
18
|
+
pyo3 = { version="0.26.0", features=["extension-module"], optional=true }
|
|
19
|
+
numpy = { version="0.26.0", optional=true } # This must match pyo3 version!
|
|
20
20
|
|
|
21
|
-
nalgebra = "^0.
|
|
22
|
-
rayon = "^1.
|
|
21
|
+
nalgebra = "^0.34.1"
|
|
22
|
+
rayon = "^1.11.0"
|
|
23
23
|
libm = "^0.2"
|
|
24
24
|
num-traits = { version = "0.2.19", features = ["libm"] }
|
|
25
25
|
|
cfsem-2.6.0/PKG-INFO
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cfsem
|
|
3
|
+
Version: 2.6.0
|
|
4
|
+
Classifier: Programming Language :: Rust
|
|
5
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
7
|
+
Requires-Dist: numpy>=2
|
|
8
|
+
Requires-Dist: interpn>=0.6.1
|
|
9
|
+
Requires-Dist: findiff>=0.12.1
|
|
10
|
+
Requires-Dist: pydantic>=2
|
|
11
|
+
Requires-Dist: pydantic-numpy>=6
|
|
12
|
+
Requires-Dist: pytest>=7.1.3 ; extra == 'dev'
|
|
13
|
+
Requires-Dist: coverage>=6.5.0 ; extra == 'dev'
|
|
14
|
+
Requires-Dist: ruff>=0.6.2 ; extra == 'dev'
|
|
15
|
+
Requires-Dist: pyright==1.1.402 ; extra == 'dev'
|
|
16
|
+
Requires-Dist: scipy>=1.8 ; extra == 'dev'
|
|
17
|
+
Requires-Dist: mkdocs>=1.6.0 ; extra == 'dev'
|
|
18
|
+
Requires-Dist: mkdocs-material>=9.5.25 ; extra == 'dev'
|
|
19
|
+
Requires-Dist: mkdocstrings[python]>=0.25.1 ; extra == 'dev'
|
|
20
|
+
Requires-Dist: matplotlib>=3.9 ; extra == 'dev'
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Summary: Quasi-steady electromagnetics including filamentized approximations, Biot-Savart, and Grad-Shafranov.
|
|
24
|
+
Home-Page: https://github.com/cfs-energy/cfsem-py
|
|
25
|
+
Author-email: Commonwealth Fusion Systems <jlogan@cfs.energy>
|
|
26
|
+
License-Expression: MIT
|
|
27
|
+
Requires-Python: >=3.9, <3.14
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Finite-difference solution to structural PDE for pancake or
|
|
3
|
+
infinite-length solenoid coil, following Iwasa 2e section 3.6.
|
|
4
|
+
|
|
5
|
+
Assumes
|
|
6
|
+
* Uniform current density within each r-section
|
|
7
|
+
* Zero R-Z shear (deck-of-cards structure)
|
|
8
|
+
* Zero Z-force,stress,strain (no axial compression accounted here; can be evaluated separately;
|
|
9
|
+
usually relatively small)
|
|
10
|
+
* Isotropic material
|
|
11
|
+
* This method could be extended to handle orthotropic material, with some effort
|
|
12
|
+
* Single material region
|
|
13
|
+
* This method could be extended to handle multiple regions of isotropic materials
|
|
14
|
+
|
|
15
|
+
Supports
|
|
16
|
+
* Non-uniform r-grid
|
|
17
|
+
* Arbitrary current density and B-field defined on r-grid
|
|
18
|
+
* Nonzero pressure on inner/outer wall (fluid pressure, bucking load, etc)
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from dataclasses import dataclass
|
|
24
|
+
from functools import cached_property
|
|
25
|
+
from logging import getLogger
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from typing import Callable, Literal
|
|
28
|
+
|
|
29
|
+
import findiff
|
|
30
|
+
import numpy as np
|
|
31
|
+
from numpy.typing import NDArray
|
|
32
|
+
from pydantic import ConfigDict
|
|
33
|
+
from pydantic_numpy.model import NumpyModel
|
|
34
|
+
from pydantic_numpy.typing import NpNDArray # Array of any type or dimensionality
|
|
35
|
+
from scipy import io, sparse
|
|
36
|
+
from scipy.sparse import csc_matrix as CSC
|
|
37
|
+
from scipy.sparse import csr_matrix as CSR
|
|
38
|
+
from scipy.sparse.linalg import factorized
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def solenoid_1d_structural_factor(elasticity_modulus: float, poisson_ratio: float) -> float:
|
|
42
|
+
"""Structural factor applied to RHS of solenoid stress solve"""
|
|
43
|
+
c = (1.0 - poisson_ratio**2) / elasticity_modulus # [m/N]
|
|
44
|
+
return c
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def solenoid_1d_structural_rhs(
|
|
48
|
+
c: float,
|
|
49
|
+
j: NDArray | list[float],
|
|
50
|
+
bz: NDArray | list[float],
|
|
51
|
+
pi: float = 0.0,
|
|
52
|
+
po: float = 0.0,
|
|
53
|
+
) -> NDArray:
|
|
54
|
+
"""
|
|
55
|
+
Right-hand-side for solenoid stress solve,
|
|
56
|
+
including zero values at the BCs.
|
|
57
|
+
|
|
58
|
+
From Iwasa 2e eqn. 3.64a
|
|
59
|
+
|
|
60
|
+
Recommend padding the grid with a dummy value at either end
|
|
61
|
+
to make room for the BCs without losing accounting of nonzero
|
|
62
|
+
current density at the inner/outer radius.
|
|
63
|
+
|
|
64
|
+
Padding for BCs can be done like:
|
|
65
|
+
`rgrid = np.array([r0 - 1e-6] + rgrid.tolist() + [r1 + 1e-6])`
|
|
66
|
+
|
|
67
|
+
Padding region is ultimately treated as structural material,
|
|
68
|
+
so the padded region should be small to avoid introducing error,
|
|
69
|
+
but not so small that it causes numerical error in the finite difference scheme.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
c: [m/N] scalar structural factor; see `solenoid_1d_structural_factor()`
|
|
73
|
+
j: [A/m^2] with shape (n x 1), current density at each point in the r-grid
|
|
74
|
+
bz: [T] with shape (n x 1), Z-axis B-field at each point in the r-grid
|
|
75
|
+
pi: [Pa] scalar pressure on inner wall, defined in +r direction
|
|
76
|
+
po: [Pa] scalar pressure on outer wall, defined in -r direction
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
-c * j * bz, [1/m^2] with shape (n x 1), the right-hand side of the solenoid stress PDE
|
|
80
|
+
"""
|
|
81
|
+
# Guarantee arrays
|
|
82
|
+
j = np.array(j)
|
|
83
|
+
bz = np.array(bz)
|
|
84
|
+
|
|
85
|
+
# RHS without BCs
|
|
86
|
+
rhs = -c * j * bz
|
|
87
|
+
|
|
88
|
+
# BC for r-stress at inner and outer radius
|
|
89
|
+
# is the fluid or mechanical pressure, which is usually going to be set to zero
|
|
90
|
+
# to represent an unsupported system, but could be set to a nonzero value
|
|
91
|
+
# to represent a surface load.
|
|
92
|
+
rhs[0] = -pi # Sign convention: compression is negative stress
|
|
93
|
+
rhs[-1] = -po
|
|
94
|
+
|
|
95
|
+
return rhs
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class SolenoidStress1D(NumpyModel):
|
|
99
|
+
model_config = ConfigDict(validate_assignment=True, frozen=True, extra="forbid")
|
|
100
|
+
|
|
101
|
+
rgrid: NpNDArray
|
|
102
|
+
"""[m] 1D grid of r-coordinates"""
|
|
103
|
+
elasticity_modulus: float
|
|
104
|
+
"""[Pa] diagonal terms in material property matrix"""
|
|
105
|
+
poisson_ratio: float
|
|
106
|
+
"""[dimensionless] factor determining off-diagonal terms in material property matrix"""
|
|
107
|
+
order: Literal[2, 4] = 4
|
|
108
|
+
"""Finite-difference stencil polynomial order.
|
|
109
|
+
Higher order operators produce excessive numerical error under typical use."""
|
|
110
|
+
direct_inverse: bool = False
|
|
111
|
+
"""Whether to generate fully-dense direct inverse of the system, which
|
|
112
|
+
can be useful as a linear operator. Alternatively, the system can be solved
|
|
113
|
+
using an LU solver with reduced memory usage and better numerical conditioning."""
|
|
114
|
+
|
|
115
|
+
@cached_property
|
|
116
|
+
def operators(self) -> SolenoidStress1DOperators:
|
|
117
|
+
"""
|
|
118
|
+
Linear operators for solving stress and strain in a pancake coil
|
|
119
|
+
following Iwasa 2e section 3.6.
|
|
120
|
+
"""
|
|
121
|
+
return solenoid_1d_structural_operators(
|
|
122
|
+
np.array(self.rgrid), self.elasticity_modulus, self.poisson_ratio, self.order, self.direct_inverse
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
@cached_property
|
|
126
|
+
def displacement_solver(self) -> Callable[[NDArray], NDArray]:
|
|
127
|
+
"""LU solver for load-displacement relation (A_ub)
|
|
128
|
+
as an alternative to taking a direct inverse of A_bu"""
|
|
129
|
+
return factorized(self.operators.a_bu)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@dataclass(frozen=True)
|
|
133
|
+
class SolenoidStress1DOperators:
|
|
134
|
+
"""
|
|
135
|
+
Linear operators for solving stress and strain in a pancake coil
|
|
136
|
+
following Iwasa 2e section 3.6.
|
|
137
|
+
|
|
138
|
+
A_bu, (n x n) sparse operator mapping displacement to the RHS like A @ u_r = -c * j * bz
|
|
139
|
+
A_ub, (n x n) fully-dense direct inverse of A_bu mapping RHS to displacement
|
|
140
|
+
A_eu (2n x n), A_eu_radial (n x n), A_eu_hoop (n x n), sparse operators mapping displacement to strain
|
|
141
|
+
* First entry is combined operator producing both strain components
|
|
142
|
+
* Second and third entries are split operators, which are equivalent because they are fully decoupled
|
|
143
|
+
A_se (2n x 2n), sparse operator mapping strain to stress
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
a_bu: CSC
|
|
147
|
+
"""(n x n) sparse operator mapping displacement to the RHS like A @ u_r = -c * j * bz"""
|
|
148
|
+
a_ub: NDArray | None
|
|
149
|
+
"""(n x n) fully-dense direct inverse of A_bu mapping RHS to displacement.
|
|
150
|
+
Only generated if `direct_inverse` flag is set."""
|
|
151
|
+
a_eu: CSR
|
|
152
|
+
"""(2n x n), sparse operator mapping displacement to strain; contains both radial and hoop components"""
|
|
153
|
+
a_eu_radial: CSR
|
|
154
|
+
"""(n x n), sparse operators mapping displacement to strain; radial component only"""
|
|
155
|
+
a_eu_hoop: CSR
|
|
156
|
+
"""(n x n), sparse operators mapping displacement to strain; hoop component only"""
|
|
157
|
+
a_se: CSR
|
|
158
|
+
"""(2n x 2n), sparse operator mapping strain to stress"""
|
|
159
|
+
|
|
160
|
+
def write_mat(self, dst: str | Path) -> str:
|
|
161
|
+
"""Write the collection of operators in .mat format.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
dst: Target directory to place the file named "stress_operators.mat"
|
|
165
|
+
|
|
166
|
+
Raises:
|
|
167
|
+
IOError: If the directory does not exist
|
|
168
|
+
"""
|
|
169
|
+
# Check directory
|
|
170
|
+
dst = Path(dst).absolute()
|
|
171
|
+
fpath = dst / "stress_operators.mat"
|
|
172
|
+
getLogger("cfsem").info(f"Saving stress operator data to {fpath}")
|
|
173
|
+
|
|
174
|
+
to_save = {
|
|
175
|
+
"A_bu": self.a_bu,
|
|
176
|
+
"A_ub": self.a_ub,
|
|
177
|
+
"A_eu": self.a_eu,
|
|
178
|
+
"A_eu_radial": self.a_eu_radial,
|
|
179
|
+
"A_eu_hoop": self.a_eu_hoop,
|
|
180
|
+
"A_se": self.a_se,
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if self.a_ub is None: # savemat fails on None value
|
|
184
|
+
to_save.pop("A_ub")
|
|
185
|
+
|
|
186
|
+
# Note this will implicitly convert all CSR matrices to CSC, which is .mat's preferred I/O
|
|
187
|
+
io.savemat(fpath, to_save)
|
|
188
|
+
|
|
189
|
+
return f"{fpath}"
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def solenoid_1d_structural_operators(
|
|
193
|
+
rgrid: NDArray | list,
|
|
194
|
+
elasticity_modulus: float,
|
|
195
|
+
poisson_ratio: float,
|
|
196
|
+
order: Literal[2, 4],
|
|
197
|
+
direct_inverse: bool = False,
|
|
198
|
+
) -> SolenoidStress1DOperators:
|
|
199
|
+
"""
|
|
200
|
+
Linear operators for solving stress and strain in a pancake coil
|
|
201
|
+
following Iwasa 2e section 3.6.
|
|
202
|
+
|
|
203
|
+
Assumes
|
|
204
|
+
* Uniform current density within each r-section
|
|
205
|
+
* Zero R-Z shear (deck-of-cards structure)
|
|
206
|
+
* Zero Z-force,stress,strain (no axial compression accounted here; can be evaluated separately;
|
|
207
|
+
usually relatively small)
|
|
208
|
+
* Isotropic material
|
|
209
|
+
* This method could be extended to handle orthotropic material, with some effort
|
|
210
|
+
* Single material region
|
|
211
|
+
* This method could be extended to handle multiple regions of isotropic materials
|
|
212
|
+
|
|
213
|
+
Supports
|
|
214
|
+
* Non-uniform r-grid
|
|
215
|
+
* Arbitrary current density and B-field defined on r-grid
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
rgrid: [m] with shape (n x 1), Grid of r-coordinates. Must be sorted ascending.
|
|
219
|
+
elasticity_modulus: [N/m] Material property; Young's modulus
|
|
220
|
+
poisson_ratio: [dimensionless] Material property; off-axis stress coupling term
|
|
221
|
+
order: Finite-difference stencil polynomial order
|
|
222
|
+
direct_inverse: Whether to generate fully-dense direct inverse of the system, which
|
|
223
|
+
can be useful as a linear operator.
|
|
224
|
+
Alternatively, the system can be solved using an LU solver with
|
|
225
|
+
reduced memory usage and better numerical conditioning.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
object containing linear operators
|
|
229
|
+
"""
|
|
230
|
+
# Guarantee arrays
|
|
231
|
+
rgrid = np.array(rgrid)
|
|
232
|
+
nr = len(rgrid)
|
|
233
|
+
|
|
234
|
+
#
|
|
235
|
+
# Stencils / differential operators
|
|
236
|
+
#
|
|
237
|
+
|
|
238
|
+
# Note these will include the 1/dr and 1/dr^2 scalings,
|
|
239
|
+
# not just the normalized stencil
|
|
240
|
+
ddr = findiff.Diff(0, rgrid, acc=order)
|
|
241
|
+
d2dr2 = ddr**2
|
|
242
|
+
|
|
243
|
+
ddr = ddr.matrix((nr,))
|
|
244
|
+
d2dr2 = d2dr2.matrix((nr,))
|
|
245
|
+
|
|
246
|
+
rinv = CSR(np.diag(1.0 / rgrid))
|
|
247
|
+
rinv2 = CSR(np.diag(1.0 / rgrid**2))
|
|
248
|
+
|
|
249
|
+
#
|
|
250
|
+
# Displacement-load relation
|
|
251
|
+
#
|
|
252
|
+
|
|
253
|
+
# The first and last row of the u-b relation will be modified later
|
|
254
|
+
# to include the boundary conditions
|
|
255
|
+
#
|
|
256
|
+
# Iwasa 2e eqn. 3.64a left hand side
|
|
257
|
+
#
|
|
258
|
+
# This one is converted to CSC because, while it's easiest to build it as CSR,
|
|
259
|
+
# it is more useful for solving a system as CSC
|
|
260
|
+
a_bu = CSC(d2dr2 + (rinv @ ddr) - rinv2) # Operator maps displacement TO rhs (-c*j*B)
|
|
261
|
+
|
|
262
|
+
# Stress-strain relation components
|
|
263
|
+
# that are needed for BCs
|
|
264
|
+
# Iwasa 2e eqns. 3.63g
|
|
265
|
+
a_stress_strain = np.array(
|
|
266
|
+
[
|
|
267
|
+
[1.0 / elasticity_modulus, -poisson_ratio / elasticity_modulus],
|
|
268
|
+
[-poisson_ratio / elasticity_modulus, 1.0 / elasticity_modulus],
|
|
269
|
+
]
|
|
270
|
+
)
|
|
271
|
+
a_strain_stress = np.linalg.inv(a_stress_strain)
|
|
272
|
+
diag_term = a_strain_stress[0, 0]
|
|
273
|
+
off_diag_term = a_strain_stress[1, 0]
|
|
274
|
+
|
|
275
|
+
# We only need the first and last row of this matrix.
|
|
276
|
+
# Actualizing the whole thing is easy but unnecessary
|
|
277
|
+
# This is extracted by hand-calc starting from
|
|
278
|
+
# Iwasa 2e eqns. 3.63a-d
|
|
279
|
+
bcmat = diag_term * ddr + off_diag_term * rinv
|
|
280
|
+
|
|
281
|
+
# Apply BC to displacement operator
|
|
282
|
+
a_bu[0, :] = bcmat[0, :]
|
|
283
|
+
a_bu[-1, :] = bcmat[-1, :]
|
|
284
|
+
|
|
285
|
+
# Invert A_bu directly to get A_ub
|
|
286
|
+
# This is fully dense, which may be prohibitive in some situations
|
|
287
|
+
a_ub = (
|
|
288
|
+
None if not direct_inverse else np.linalg.inv(a_bu.todense())
|
|
289
|
+
) # Operator maps RHS=-c*j*bz to displacement
|
|
290
|
+
|
|
291
|
+
#
|
|
292
|
+
# Strain-displacement operator(s)
|
|
293
|
+
#
|
|
294
|
+
# Iwasa 2e eqns. 3.63a-d
|
|
295
|
+
a_eu_hoop = rinv # Just the hoop part
|
|
296
|
+
a_eu_radial = ddr # Just the radial part
|
|
297
|
+
# fmt: off
|
|
298
|
+
a_eu = CSR(sparse.block_array(
|
|
299
|
+
[[a_eu_radial],
|
|
300
|
+
[a_eu_hoop]]
|
|
301
|
+
)) # Operator for getting strain from displacement
|
|
302
|
+
# fmt: on
|
|
303
|
+
|
|
304
|
+
#
|
|
305
|
+
# Stress-strain operators
|
|
306
|
+
#
|
|
307
|
+
# In this case, we're manually assembling the inverse of the A_es matrix
|
|
308
|
+
# because we know all the components from handcalc arithmetic
|
|
309
|
+
eye = sparse.eye(nr, nr)
|
|
310
|
+
# fmt: off
|
|
311
|
+
a_se = CSR(sparse.block_array(
|
|
312
|
+
[[ diag_term * eye, off_diag_term * eye],
|
|
313
|
+
[off_diag_term * eye, diag_term * eye]]
|
|
314
|
+
)) # Operator maps strain to stress
|
|
315
|
+
# fmt: on
|
|
316
|
+
|
|
317
|
+
return SolenoidStress1DOperators(a_bu, a_ub, a_eu, a_eu_radial, a_eu_hoop, a_se)
|