pcb-analysis 0.9.2__tar.gz → 0.9.3__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.
- {pcb_analysis-0.9.2/src/pcb_analysis.egg-info → pcb_analysis-0.9.3}/PKG-INFO +1 -1
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/pyproject.toml +1 -1
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/__init__.py +2 -1
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/ports.py +42 -4
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/current_field_contract.py +1 -1
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/sheet_peec.py +53 -4
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/staggered_coupling/circuit_coupled.py +8 -1
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3/src/pcb_analysis.egg-info}/PKG-INFO +1 -1
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_dc_ports.py +24 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_sheet_peec.py +31 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/LICENSE +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/README.md +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/setup.cfg +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/backends.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/benchmark.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/cli/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/cli/calibrate.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/controller.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/cuda_delta.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/cupy_calibrator.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/delta_peec.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/layout_ops.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/lowmem_25d.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/lowmem_peec.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/multilayer_peec.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/dice_peec/stackup.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/cuda.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/frequency_domain.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/grid.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/native/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/native/build.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/native/layered_dc_q1.cpp +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/native/scalar_maxwell_q1.cpp +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/native_dc.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/native_q1.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/pcb.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/runtime.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/solver.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/two_level.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/py.typed +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/native/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/native/build.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/native/pfft_near.cpp +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/sheet_cuda.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/sheet_inductance.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/sheet_operator.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/sheet_pfft.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/sheet_results.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/skin_filaments.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/skin_screen.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/voxel_peec/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/voxel_peec/contract.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/voxel_peec/cuda_pypeec.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/voxel_peec/pypeec_memory.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/py.typed +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/far_field.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/fields.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/limits.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/moments.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/native/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/native/build.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/native/dipole_fields.cpp +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/native_dipole.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/sources.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/adapters.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/barrel.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/bodymap.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/conductors.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/contact.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/kicad.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/mesh.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/native/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/native/build.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/native/point_in_mesh.cpp +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/reader.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/refinement.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/section.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/skin.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/cad_import/voxelize.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/geometry/py.typed +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/py.typed +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/staggered_coupling/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/staggered_coupling/board_enclosure.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/staggered_coupling/electro_thermal.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/staggered_coupling/electro_thermal_enclosure.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/staggered_coupling/emission.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/staggered_coupling/scenarios.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/pcb_analysis.egg-info/SOURCES.txt +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/pcb_analysis.egg-info/dependency_links.txt +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/pcb_analysis.egg-info/entry_points.txt +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/pcb_analysis.egg-info/requires.txt +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/pcb_analysis.egg-info/top_level.txt +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/boundaries.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/contact.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/coupling.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/cuda.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/mesh.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/native/__init__.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/native/build.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/native/hex_q1.cpp +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/native_hex.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/operator.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/problem.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/radiation.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/solve.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/transient.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/two_level.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/voxel.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/py.typed +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_board_enclosure_coupling.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_circuit_coupled.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_controller.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_cuda.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_cuda_matrix_free_mpir_fem.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_cuda_thermal_conduction.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_current_field_contract.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_delta_peec.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_electro_thermal_enclosure.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_electrothermal_coupling.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_emc_dipole_superposition.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_emc_sources.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_fp32_accuracy.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_frequency_domain_fem.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_geometry_step.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_kicad_step.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_matrix_free_mpir_fem.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_multilayer_peec.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_native_dc.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_native_emc.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_native_geometry.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_native_q1.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_native_thermal.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_peec_fem_comparison.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_pypeec_memory.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_sheet_cuda_device.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_sheet_inductance.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_sheet_pfft.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_sheet_results.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_skin_filaments.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_staggered_coupling.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_tensor_grid.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_thermal_conduction.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_thermal_radiation.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_thermal_transient.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_thermal_voxel.py +0 -0
- {pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/tests/test_voxel_peec.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pcb-analysis
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.3
|
|
4
4
|
Summary: CUDA-accelerated PEEC, matrix-free FEM, and radiated-emission evaluation for electrical, thermal, and EMC PCB analysis
|
|
5
5
|
Author-email: Hiroyuki Yamada <H44bcda@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pcb-analysis"
|
|
7
|
-
version = "0.9.
|
|
7
|
+
version = "0.9.3"
|
|
8
8
|
description = "CUDA-accelerated PEEC, matrix-free FEM, and radiated-emission evaluation for electrical, thermal, and EMC PCB analysis"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -17,7 +17,7 @@ from .pcb import (
|
|
|
17
17
|
VoltageTerminal,
|
|
18
18
|
solve_pcb_dc,
|
|
19
19
|
)
|
|
20
|
-
from .ports import DCPortBasis, PortSet, dc_port_basis
|
|
20
|
+
from .ports import DCPortBasis, PortSet, dc_port_basis, port_basis_workers
|
|
21
21
|
from .frequency_domain import (
|
|
22
22
|
EPSILON_0_F_PER_M,
|
|
23
23
|
MU_0_H_PER_M,
|
|
@@ -80,6 +80,7 @@ __all__ = [
|
|
|
80
80
|
"refined_grid",
|
|
81
81
|
"cuda_available",
|
|
82
82
|
"dc_port_basis",
|
|
83
|
+
"port_basis_workers",
|
|
83
84
|
"graded_edges",
|
|
84
85
|
"make_complex64_runtime",
|
|
85
86
|
"make_float32_runtime",
|
|
@@ -28,10 +28,18 @@ The reduction is evaluated by diagonalising ``C`` restricted to the
|
|
|
28
28
|
non-reference ports: ``C_rr = Σ_m λ_m u_m u_mᵀ`` gives ``<P_e> = Σ_m λ_m
|
|
29
29
|
P_e(ψ_m)`` with ``ψ_m = Σ_k u_mk φ_k``, so the loss of every element and via
|
|
30
30
|
comes from the exact element quadratic forms of :class:`.pcb.MatrixFreePCBOperator`.
|
|
31
|
+
|
|
32
|
+
The ``n - 1`` unit solves are independent and share one read-only operator,
|
|
33
|
+
so :func:`dc_port_basis` can run them on a thread pool (``workers=``, or
|
|
34
|
+
``PCB_PORT_BASIS_WORKERS``). Threads multiply with the OpenMP team of the
|
|
35
|
+
native kernels (``PCB_NATIVE_THREADS``); their product is the core budget.
|
|
36
|
+
A CUDA runtime solves serially, since its stream is shared.
|
|
31
37
|
"""
|
|
32
38
|
|
|
33
39
|
from __future__ import annotations
|
|
34
40
|
|
|
41
|
+
import os
|
|
42
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
35
43
|
from dataclasses import dataclass
|
|
36
44
|
from typing import Sequence
|
|
37
45
|
|
|
@@ -49,6 +57,15 @@ from .runtime import LowPrecisionRuntime, RuntimeBackend
|
|
|
49
57
|
from .solver import MPIRConfig, MPIRResult, solve_mpir
|
|
50
58
|
|
|
51
59
|
|
|
60
|
+
def port_basis_workers() -> int:
|
|
61
|
+
"""Threads for the unit solves of a basis; ``PCB_PORT_BASIS_WORKERS`` overrides (default 1)."""
|
|
62
|
+
|
|
63
|
+
value = os.environ.get("PCB_PORT_BASIS_WORKERS")
|
|
64
|
+
if value:
|
|
65
|
+
return max(1, int(value))
|
|
66
|
+
return 1
|
|
67
|
+
|
|
68
|
+
|
|
52
69
|
@dataclass(frozen=True)
|
|
53
70
|
class PortSet:
|
|
54
71
|
"""The pads of one conductor role, one node set per port.
|
|
@@ -111,6 +128,7 @@ class DCPortBasis:
|
|
|
111
128
|
port ``k`` is held at 1 V and every other port at 0 V.
|
|
112
129
|
``unit_current_potential_v[m]`` is the potential field (``mesh.node_shape``)
|
|
113
130
|
for 1 A into port ``ports.driven[m]`` and out of the reference port.
|
|
131
|
+
``workers`` is the number of threads the unit solves actually ran on.
|
|
114
132
|
"""
|
|
115
133
|
|
|
116
134
|
mesh: LayeredPCBMesh
|
|
@@ -120,6 +138,7 @@ class DCPortBasis:
|
|
|
120
138
|
unit_voltage_potential_v: np.ndarray
|
|
121
139
|
unit_current_potential_v: np.ndarray
|
|
122
140
|
solves: tuple[MPIRResult, ...]
|
|
141
|
+
workers: int = 1
|
|
123
142
|
|
|
124
143
|
@property
|
|
125
144
|
def converged(self) -> bool:
|
|
@@ -228,13 +247,17 @@ def dc_port_basis(
|
|
|
228
247
|
native: bool | None = None,
|
|
229
248
|
native_threads: int | None = None,
|
|
230
249
|
initial: DCPortBasis | None = None,
|
|
250
|
+
workers: int | None = None,
|
|
231
251
|
) -> DCPortBasis:
|
|
232
252
|
"""Measure the N-port of ``mesh`` at ``ports`` with ``n - 1`` unit voltage solves.
|
|
233
253
|
|
|
234
254
|
One operator with every port node fixed serves all solves. ``initial``
|
|
235
255
|
warm-starts each unit solve from the same port's field of an earlier
|
|
236
256
|
basis (for example the previous iterate of a coupled analysis on the
|
|
237
|
-
same mesh with other conductivities).
|
|
257
|
+
same mesh with other conductivities). ``workers`` threads run the unit
|
|
258
|
+
solves concurrently (``None``: :func:`port_basis_workers`); the operator
|
|
259
|
+
is read-only once built and every solve owns its vectors, so the result
|
|
260
|
+
does not depend on the thread count. A CUDA runtime solves serially.
|
|
238
261
|
"""
|
|
239
262
|
|
|
240
263
|
operator = MatrixFreePCBOperator(
|
|
@@ -256,8 +279,8 @@ def dc_port_basis(
|
|
|
256
279
|
n = ports.count
|
|
257
280
|
conductance = np.zeros((n, n), dtype=np.float64)
|
|
258
281
|
unit_voltage = np.zeros((n - 1,) + mesh.node_shape, dtype=np.float64)
|
|
259
|
-
|
|
260
|
-
|
|
282
|
+
|
|
283
|
+
def unit_solve(column: int, port: int) -> tuple[np.ndarray, np.ndarray, MPIRResult]:
|
|
261
284
|
excitation = np.zeros(n)
|
|
262
285
|
excitation[port] = 1.0
|
|
263
286
|
terminals = ports.voltage_terminals(excitation)
|
|
@@ -268,8 +291,22 @@ def dc_port_basis(
|
|
|
268
291
|
guess = np.where(operator.free_nodes.reshape(-1), previous, guess)
|
|
269
292
|
result = solve_mpir(operator, rhs, config=config, initial_guess=guess)
|
|
270
293
|
potential = result.solution.reshape(mesh.node_shape)
|
|
294
|
+
return potential, operator.terminal_currents(potential, terminals), result
|
|
295
|
+
|
|
296
|
+
threads = port_basis_workers() if workers is None else max(1, int(workers))
|
|
297
|
+
threads = min(threads, n - 1)
|
|
298
|
+
if getattr(operator.runtime, "is_cuda", False):
|
|
299
|
+
threads = 1
|
|
300
|
+
if threads > 1:
|
|
301
|
+
with ThreadPoolExecutor(max_workers=threads, thread_name_prefix="port-basis") as pool:
|
|
302
|
+
outcomes = list(pool.map(unit_solve, range(n - 1), ports.driven))
|
|
303
|
+
else:
|
|
304
|
+
outcomes = [unit_solve(column, port) for column, port in enumerate(ports.driven)]
|
|
305
|
+
solves = []
|
|
306
|
+
for column, port in enumerate(ports.driven):
|
|
307
|
+
potential, currents, result = outcomes[column]
|
|
271
308
|
unit_voltage[column] = potential
|
|
272
|
-
conductance[:, port] =
|
|
309
|
+
conductance[:, port] = currents
|
|
273
310
|
solves.append(result)
|
|
274
311
|
# The driven block is what the solves measured; it is symmetrised against
|
|
275
312
|
# solver round-off. The reference row and column follow from KCL exactly
|
|
@@ -295,4 +332,5 @@ def dc_port_basis(
|
|
|
295
332
|
unit_voltage_potential_v=unit_voltage,
|
|
296
333
|
unit_current_potential_v=unit_current,
|
|
297
334
|
solves=tuple(solves),
|
|
335
|
+
workers=threads,
|
|
298
336
|
)
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/sheet_peec/current_field_contract.py
RENAMED
|
@@ -518,7 +518,7 @@ def solve_current_field_problem(
|
|
|
518
518
|
"tolerance": float(settings.get("relative_tolerance", 1e-9)),
|
|
519
519
|
"max_iterations": int(settings.get("maximum_iterations", 200)),
|
|
520
520
|
"restart": int(settings.get("restart", 120)),
|
|
521
|
-
"preconditioner": str(settings.get("preconditioner", "
|
|
521
|
+
"preconditioner": str(settings.get("preconditioner", "auto")),
|
|
522
522
|
}
|
|
523
523
|
if execution_backend == "cuda":
|
|
524
524
|
from .sheet_cuda import solve_sheet_case_cuda
|
|
@@ -466,7 +466,7 @@ def solve_sheet_case(
|
|
|
466
466
|
tolerance: float = 1e-10,
|
|
467
467
|
max_iterations: int = 400,
|
|
468
468
|
restart: int = 60,
|
|
469
|
-
preconditioner: str = "
|
|
469
|
+
preconditioner: str = "auto",
|
|
470
470
|
) -> SheetSolution:
|
|
471
471
|
"""Solve one excitation of the mesh.
|
|
472
472
|
|
|
@@ -477,7 +477,11 @@ def solve_sheet_case(
|
|
|
477
477
|
it, ``Z`` couples every branch to every other and is applied through the
|
|
478
478
|
operator's transforms, so the reduction is carried out by a Krylov method.
|
|
479
479
|
|
|
480
|
-
``preconditioner="
|
|
480
|
+
``preconditioner="auto"`` (default) picks ``near`` below :data:`AUTO_BLOCK_FROM_UNKNOWNS`
|
|
481
|
+
saddle-point unknowns and ``block`` above. ``preconditioner="block"`` keeps the near-field impedance but factors it
|
|
482
|
+
on its own and approximates the Schur complement by the diagonal
|
|
483
|
+
variant's nodal admittance: block elimination at a fraction of the
|
|
484
|
+
saddle LU's memory. ``preconditioner="near"`` factors the saddle-point matrix with
|
|
481
485
|
``Z`` replaced by ``R + j omega L_near``, the exact partial inductance of
|
|
482
486
|
each branch with itself and its neighbours within the operator's
|
|
483
487
|
preconditioner radius (``operator.near_inductance(mesh)``), by sparse LU;
|
|
@@ -485,8 +489,8 @@ def solve_sheet_case(
|
|
|
485
489
|
through a Schur complement but leaves every mutual term to the Krylov
|
|
486
490
|
iterations.
|
|
487
491
|
"""
|
|
488
|
-
if preconditioner not in ("near", "diagonal"):
|
|
489
|
-
raise ValueError("preconditioner must be 'near' or 'diagonal'")
|
|
492
|
+
if preconditioner not in ("auto", "near", "block", "diagonal"):
|
|
493
|
+
raise ValueError("preconditioner must be 'auto', 'near', 'block' or 'diagonal'")
|
|
490
494
|
if operator.shape != mesh.shape:
|
|
491
495
|
raise ValueError("the operator and the mesh must share a shape")
|
|
492
496
|
if len(operator.stackup) != len(mesh.stackup):
|
|
@@ -629,6 +633,8 @@ def solve_sheet_case(
|
|
|
629
633
|
[impedance(currents) - reduced @ voltages, reduced.T @ currents]
|
|
630
634
|
)
|
|
631
635
|
|
|
636
|
+
if preconditioner == "auto":
|
|
637
|
+
preconditioner = choose_preconditioner(size)
|
|
632
638
|
precondition = _build_preconditioner(
|
|
633
639
|
mesh, operator, preconditioner, omega, resistance, active_branches, reduced, branches
|
|
634
640
|
)
|
|
@@ -686,6 +692,21 @@ def _near_impedance(
|
|
|
686
692
|
return (sp.diags(resistance[active_branches]) + 1j * omega * near).tocsr()
|
|
687
693
|
|
|
688
694
|
|
|
695
|
+
# Above this many saddle-point unknowns (branches + nodes) the whole-matrix LU
|
|
696
|
+
# of the near preconditioner costs more memory than the block elimination
|
|
697
|
+
# saves in iterations: on a 33 x 30 mm two-layer plane at 800 kHz the near
|
|
698
|
+
# variant needed 2.2 GB and 27 s at 64k branches where block needed 0.5 GB
|
|
699
|
+
# and 21 s, while at 20k branches near was faster (2.1 s against 4.0 s) at
|
|
700
|
+
# 0.3 GB (docs/SHEET_PRECONDITIONER_RESULTS.json).
|
|
701
|
+
AUTO_BLOCK_FROM_UNKNOWNS = 60_000
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
def choose_preconditioner(unknowns: int) -> str:
|
|
705
|
+
"""``near`` for a small saddle-point system, ``block`` for a large one."""
|
|
706
|
+
|
|
707
|
+
return "block" if unknowns >= AUTO_BLOCK_FROM_UNKNOWNS else "near"
|
|
708
|
+
|
|
709
|
+
|
|
689
710
|
def _build_preconditioner(
|
|
690
711
|
mesh: SheetMesh,
|
|
691
712
|
operator: Any,
|
|
@@ -703,6 +724,34 @@ def _build_preconditioner(
|
|
|
703
724
|
saddle = sp.bmat([[impedance, -reduced], [reduced.T, None]], format="csc")
|
|
704
725
|
factored = spla.splu(saddle)
|
|
705
726
|
return factored.solve
|
|
727
|
+
if kind == "block" and hasattr(operator, "near_inductance"):
|
|
728
|
+
# The same near-field impedance, applied by block elimination instead
|
|
729
|
+
# of one LU of the whole saddle-point matrix. Z_near is factored on
|
|
730
|
+
# its own (a local stencil, so the fill stays small), and the Schur
|
|
731
|
+
# complement A^T Z_near^-1 A, which is dense, is approximated by
|
|
732
|
+
# A^T diag(Z)^-1 A, the nodal admittance of the diagonal variant.
|
|
733
|
+
# The saddle LU needs about 13x the memory of these two factors and
|
|
734
|
+
# is what runs a board at the acceptance grid out of memory.
|
|
735
|
+
impedance = _near_impedance(mesh, operator, omega, resistance, active_branches).tocsc()
|
|
736
|
+
factored_z = spla.splu(impedance, permc_spec="MMD_AT_PLUS_A")
|
|
737
|
+
full_diagonal = resistance + 1j * omega * np.concatenate(
|
|
738
|
+
[_inline_self_inductance(mesh, operator), _vertical_self_inductance(mesh, operator)]
|
|
739
|
+
)
|
|
740
|
+
diagonal = full_diagonal[active_branches]
|
|
741
|
+
schur = (reduced.T @ sp.diags(1.0 / diagonal) @ reduced).tocsc()
|
|
742
|
+
factored_s = spla.splu(schur, permc_spec="MMD_AT_PLUS_A")
|
|
743
|
+
|
|
744
|
+
def precondition_block(vector: np.ndarray) -> np.ndarray:
|
|
745
|
+
rhs_current = vector[:branches]
|
|
746
|
+
rhs_node = vector[branches:]
|
|
747
|
+
# [[Z, -A], [A^T, 0]] [x; y] = [r1; r2]:
|
|
748
|
+
# x = Z^-1 (r1 + A y), A^T Z^-1 A y = r2 - A^T Z^-1 r1.
|
|
749
|
+
z = factored_z.solve(rhs_current)
|
|
750
|
+
node = factored_s.solve(rhs_node - reduced.T @ z)
|
|
751
|
+
current = factored_z.solve(rhs_current + reduced @ node)
|
|
752
|
+
return np.concatenate([current, node])
|
|
753
|
+
|
|
754
|
+
return precondition_block
|
|
706
755
|
# The same system with Z replaced by its diagonal, which is exactly
|
|
707
756
|
# solvable: its Schur complement is the sparse nodal admittance matrix,
|
|
708
757
|
# factored once and reused for every iteration.
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/staggered_coupling/circuit_coupled.py
RENAMED
|
@@ -360,8 +360,14 @@ def run_circuit_coupled(
|
|
|
360
360
|
device_id: int = 0,
|
|
361
361
|
native: bool | None = None,
|
|
362
362
|
native_threads: int | None = None,
|
|
363
|
+
port_basis_workers: int | None = None,
|
|
363
364
|
) -> CircuitCoupledResult:
|
|
364
|
-
"""Iterate N-port, circuit and thermal solves to a self-consistent ρ(T) state.
|
|
365
|
+
"""Iterate N-port, circuit and thermal solves to a self-consistent ρ(T) state.
|
|
366
|
+
|
|
367
|
+
``port_basis_workers`` threads run the unit solves of every N-port basis
|
|
368
|
+
concurrently (see :func:`electrical.matrix_free_mpir_fem.dc_port_basis`);
|
|
369
|
+
``None`` reads ``PCB_PORT_BASIS_WORKERS``.
|
|
370
|
+
"""
|
|
365
371
|
|
|
366
372
|
config = config or CouplingConfig()
|
|
367
373
|
fixed_point = TemperatureFixedPoint(scenario, config)
|
|
@@ -393,6 +399,7 @@ def run_circuit_coupled(
|
|
|
393
399
|
native=native,
|
|
394
400
|
native_threads=native_threads,
|
|
395
401
|
initial=bases[conductor.name],
|
|
402
|
+
workers=port_basis_workers,
|
|
396
403
|
)
|
|
397
404
|
bases[conductor.name] = basis
|
|
398
405
|
heated[conductor.name] = (mesh, vias)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pcb-analysis
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.3
|
|
4
4
|
Summary: CUDA-accelerated PEEC, matrix-free FEM, and radiated-emission evaluation for electrical, thermal, and EMC PCB analysis
|
|
5
5
|
Author-email: Hiroyuki Yamada <H44bcda@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -227,3 +227,27 @@ def test_invalid_ports_and_correlations_are_rejected() -> None:
|
|
|
227
227
|
basis.mean_loss_w(-np.array([[2.0, -1.0, -1.0], [-1.0, 2.0, -1.0], [-1.0, -1.0, 2.0]]))
|
|
228
228
|
with pytest.raises(ValueError, match="share the ports"):
|
|
229
229
|
dc_port_basis(mesh, PortSet(pads=ports.pads, reference=0), vias=vias, initial=basis)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def test_threaded_unit_solves_give_the_serial_basis(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
233
|
+
mesh, ports, vias = _three_port_board()
|
|
234
|
+
serial = dc_port_basis(mesh, ports, vias=vias, config=TIGHT, workers=1)
|
|
235
|
+
threaded = dc_port_basis(mesh, ports, vias=vias, config=TIGHT, workers=4)
|
|
236
|
+
assert serial.workers == 1
|
|
237
|
+
assert threaded.workers == 2 # capped at n - 1 unit solves
|
|
238
|
+
assert threaded.converged
|
|
239
|
+
np.testing.assert_array_equal(threaded.conductance_s, serial.conductance_s)
|
|
240
|
+
np.testing.assert_array_equal(threaded.unit_voltage_potential_v, serial.unit_voltage_potential_v)
|
|
241
|
+
np.testing.assert_array_equal(threaded.unit_current_potential_v, serial.unit_current_potential_v)
|
|
242
|
+
assert [r.inner_iterations for r in threaded.solves] == [r.inner_iterations for r in serial.solves]
|
|
243
|
+
|
|
244
|
+
# The default comes from the environment; the warm start works on the pool too.
|
|
245
|
+
monkeypatch.setenv("PCB_PORT_BASIS_WORKERS", "3")
|
|
246
|
+
from electrical.matrix_free_mpir_fem import port_basis_workers
|
|
247
|
+
|
|
248
|
+
assert port_basis_workers() == 3
|
|
249
|
+
warm = dc_port_basis(mesh, ports, vias=vias, config=TIGHT, initial=serial)
|
|
250
|
+
assert warm.workers == 2
|
|
251
|
+
np.testing.assert_allclose(warm.conductance_s, serial.conductance_s, rtol=1.0e-9)
|
|
252
|
+
monkeypatch.delenv("PCB_PORT_BASIS_WORKERS")
|
|
253
|
+
assert port_basis_workers() == 1
|
|
@@ -239,6 +239,37 @@ class AlternatingCurrentTests(unittest.TestCase):
|
|
|
239
239
|
for smaller, larger in zip(departures, departures[1:]):
|
|
240
240
|
self.assertAlmostEqual(larger / smaller, 10.0, places=3)
|
|
241
241
|
|
|
242
|
+
def test_the_block_preconditioner_reaches_the_near_preconditioner_solution(self):
|
|
243
|
+
# Block elimination with Z_near factored alone and the Schur complement
|
|
244
|
+
# approximated by the diagonal variant's nodal admittance: the same
|
|
245
|
+
# fixed point as the saddle LU, at a fraction of its memory.
|
|
246
|
+
near = solve_sheet_case(
|
|
247
|
+
self.mesh, self.operator, self.terminals, frequency_hz=3e5, preconditioner="near"
|
|
248
|
+
)
|
|
249
|
+
block = solve_sheet_case(
|
|
250
|
+
self.mesh, self.operator, self.terminals, frequency_hz=3e5, preconditioner="block"
|
|
251
|
+
)
|
|
252
|
+
self.assertTrue(near.converged and block.converged)
|
|
253
|
+
scale = float(np.abs(near.node_voltage).max())
|
|
254
|
+
self.assertLess(float(np.abs(block.node_voltage - near.node_voltage).max()) / scale, 1e-7)
|
|
255
|
+
self.assertLess(
|
|
256
|
+
float(np.abs(block.branch_current - near.branch_current).max())
|
|
257
|
+
/ float(np.abs(near.branch_current).max()),
|
|
258
|
+
1e-7,
|
|
259
|
+
)
|
|
260
|
+
self.assertLessEqual(block.iterations, 10 * max(near.iterations, 1))
|
|
261
|
+
with self.assertRaises(ValueError):
|
|
262
|
+
solve_sheet_case(self.mesh, self.operator, self.terminals, frequency_hz=3e5, preconditioner="exact")
|
|
263
|
+
# auto: the small fixture takes the near path and reproduces it exactly.
|
|
264
|
+
auto = solve_sheet_case(
|
|
265
|
+
self.mesh, self.operator, self.terminals, frequency_hz=3e5, preconditioner="auto"
|
|
266
|
+
)
|
|
267
|
+
self.assertEqual(auto.iterations, near.iterations)
|
|
268
|
+
np.testing.assert_allclose(auto.node_voltage, near.node_voltage, rtol=0.0, atol=1e-12 * scale)
|
|
269
|
+
from electrical.sheet_peec.sheet_peec import AUTO_BLOCK_FROM_UNKNOWNS, choose_preconditioner
|
|
270
|
+
self.assertEqual(choose_preconditioner(AUTO_BLOCK_FROM_UNKNOWNS - 1), "near")
|
|
271
|
+
self.assertEqual(choose_preconditioner(AUTO_BLOCK_FROM_UNKNOWNS), "block")
|
|
272
|
+
|
|
242
273
|
def test_the_two_span_definitions_are_named(self):
|
|
243
274
|
direct = solve_sheet_case(
|
|
244
275
|
self.mesh, self.operator, self.terminals, frequency_hz=0.0
|
|
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
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/frequency_domain.py
RENAMED
|
File without changes
|
|
File without changes
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/native/__init__.py
RENAMED
|
File without changes
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/electrical/matrix_free_mpir_fem/native/build.py
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/native/__init__.py
RENAMED
|
File without changes
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/native/build.py
RENAMED
|
File without changes
|
|
File without changes
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/emc/tiled_dipole_superposition/native_dipole.py
RENAMED
|
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
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/staggered_coupling/board_enclosure.py
RENAMED
|
File without changes
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/multiphysics/staggered_coupling/electro_thermal.py
RENAMED
|
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
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/native/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{pcb_analysis-0.9.2 → pcb_analysis-0.9.3}/src/thermal/matrix_free_mpir_fem/native/hex_q1.cpp
RENAMED
|
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
|
|
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
|