paramrf 0.35.0__tar.gz → 0.35.2__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.
- {paramrf-0.35.0 → paramrf-0.35.2}/PKG-INFO +1 -1
- {paramrf-0.35.0 → paramrf-0.35.2}/paramrf.egg-info/PKG-INFO +1 -1
- {paramrf-0.35.0 → paramrf-0.35.2}/paramrf.egg-info/SOURCES.txt +1 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/interconnected/circuit/circuit.py +53 -9
- {paramrf-0.35.0 → paramrf-0.35.2}/pyproject.toml +1 -1
- paramrf-0.35.2/tests/test_models/test_circuit_port_order.py +168 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/.github/workflows/docs.yml +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/.github/workflows/draft-pdf.yml +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/.github/workflows/publish.yml +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/.github/workflows/tests.yml +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/.gitignore +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/AGENTS.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/CHANGELOG.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/CITATION.cff +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/CLAUDE.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/CONTEXT.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/CONTRIBUTING.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/LICENSE +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/NOTICE +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/README.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/assets/logo.png +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/Makefile +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/_static/custom.css +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/_templates/autosummary/class.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/_templates/autosummary/function.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/_templates/autosummary/module.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/adr/0001-line-modelling-architecture.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/adr/0002-parameter-api.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/agents/domain.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/agents/issue-tracker.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/agents/triage-labels.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/api/index.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/conf.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/core_concepts/core_primitives.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/core_concepts/index.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/core_concepts/jax_overview.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/core_concepts/optimization_and_inference.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/core_concepts/parameter_names.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/examples/cascading_and_terminating.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/examples/circuit_clc.png +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/examples/circuit_models.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/examples/custom_models.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/examples/derivatives_and_sweeps.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/examples/index.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/examples/model_optimization.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/examples/multiple_models_one_parameter_set.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/examples/parameter_naming_and_model_manipulation.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/examples/shared_substrates.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/index.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/license.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/make.bat +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/research/conductor-loss-alternatives.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/research/holloway1994.pdf +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/research/microstrip-loss-conventions.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/research/precision-coax-microstrip-10-500mhz.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/skrf_comparison/index.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/skrf_comparison/overview.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/skrf_comparison/performance.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/tutorials/1_cable_fitting.ipynb +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/tutorials/2_chip_inductor_fitting.ipynb +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/tutorials/data/CBN-1.5FT-SMSM.s2p +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/tutorials/data/on-chip-inductor.s2p +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/docs/tutorials/index.rst +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/paper/paper.bib +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/paper/paper.md +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/paper/rlc.png +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/paramrf.egg-info/dependency_links.txt +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/paramrf.egg-info/requires.txt +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/paramrf.egg-info/top_level.txt +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/_solver_view.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/bijectors.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/constraints.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/covariance_kernels.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/discrepancy_models.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/distributions.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/evaluators.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/fitting/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/fitting/minimize.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/fitting/result.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/fitting/routers.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/fitting/sample.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/fitting/targets.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/frequency.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/infer/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/infer/base.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/infer/result.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/infer/sample.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/infer/solvers/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/infer/solvers/blackjax.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/infer/solvers/polychord.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/likelihoods.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/losses.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/materials/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/materials/conductor.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/materials/dielectric.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/materials/properties.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/materials/roughness.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/materials/substrate.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/materials/surface_impedance.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/math/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/math/aggregations.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/math/bessel.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/math/conversions.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/math/losses.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/math/misc.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/adapters/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/adapters/base.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/adapters/bridge.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/adapters/callable.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/adapters/delegated.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/adapters/static.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/adapters/wrapped.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/base.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/ideal.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lines/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lines/base.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lines/coaxial.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lines/empirical.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lines/ideal.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lines/microstrip.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lines/nodal.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lines/nonuniform.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lines/planar.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lines/stripline.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/lumped.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/components/sections.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/interconnected/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/interconnected/cascade.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/interconnected/circuit/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/interconnected/circuit/base.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/interconnected/circuit/solvers/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/interconnected/circuit/solvers/nodal.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/interconnected/circuit/solvers/scattering.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/interconnected/terminated.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/nodal.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/topological.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/composite/transformed.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/surrogates/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/surrogates/expansion.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/models/surrogates/rational.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/modules/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/modules/base.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/modules/wrapped.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/network_collection.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/noise_models.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/optimize/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/optimize/base.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/optimize/minimize.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/optimize/result.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/optimize/solvers/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/optimize/solvers/jaxopt.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/optimize/solvers/optimistix.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/optimize/solvers/scipy.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/parameters.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/problems.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/rf/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/rf/conversions.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/rf/mna.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/serialization.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/terms.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/types.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/utils/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/utils/array.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/utils/debug.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/utils/network.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/utils/random.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/utils/rf.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/utils/transforms.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/utils/tree.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/utils/type.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/viz/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/pmrf/viz/plots.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/scripts/install-test-deps.sh +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/setup.cfg +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/__init__.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/_dependency_checks.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/_jit.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/conftest.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/data/10m_cable.s2p +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_autodiff.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_conversions.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_covariance_kernels.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_dc_limits.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_evaluators.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_fitting_minimize.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_fitting_routers.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_fitting_sample.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_fitting_targets.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_frequency.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_infer_base.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_infer_sample.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_map_priors.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_materials/test_conductor.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_materials/test_dielectric.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_materials/test_serialization.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_materials/test_substrate.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_materials/test_surface_impedance.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_math/test_bessel.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_model.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_adapters.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_circuit_nodal.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_circuit_scattering.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_current_distribution.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_interconnected.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_lines.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_lines_skrf_matrix.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_lumped.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_nodal.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_sections.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_transformed.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_models/test_transformers.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_module.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_naming.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_optimize_base.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_optimize_minimize.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_parameters.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_parameters_by_name.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_raw_space_solving.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_serialization.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_structural_updates.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_terms.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_transforms.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_utils/test_compress.py +0 -0
- {paramrf-0.35.0 → paramrf-0.35.2}/tests/test_utils/test_tree.py +0 -0
|
@@ -211,6 +211,7 @@ tests/test_materials/test_surface_impedance.py
|
|
|
211
211
|
tests/test_math/test_bessel.py
|
|
212
212
|
tests/test_models/test_adapters.py
|
|
213
213
|
tests/test_models/test_circuit_nodal.py
|
|
214
|
+
tests/test_models/test_circuit_port_order.py
|
|
214
215
|
tests/test_models/test_circuit_scattering.py
|
|
215
216
|
tests/test_models/test_current_distribution.py
|
|
216
217
|
tests/test_models/test_interconnected.py
|
|
@@ -48,18 +48,26 @@ class Circuit(Model):
|
|
|
48
48
|
of nodes. Each node connects one or more ports of the constituent models
|
|
49
49
|
to form a composite network.
|
|
50
50
|
|
|
51
|
+
The external ports follow `Port` declaration order: scanning `connections`
|
|
52
|
+
node by node, left to right, the first `Port` found is port 0. This holds for
|
|
53
|
+
every solver, nested or flattened.
|
|
54
|
+
|
|
51
55
|
Parameters
|
|
52
56
|
----------
|
|
53
57
|
connections : list[list[tuple[Model, int]]]
|
|
54
58
|
A list representing the nodes of the circuit. Each node is a list of
|
|
55
59
|
tuples, where each tuple contains a model and the integer
|
|
56
60
|
index of the port to connect to that node.
|
|
57
|
-
flatten: bool, default=
|
|
61
|
+
flatten: bool, default=False
|
|
58
62
|
Flattens sub-circuits and sub-cascades to perform a single solve.
|
|
59
|
-
|
|
60
|
-
solver : AbstractCircuitSolver, default=GlobalScatteringCircuitSolver()
|
|
63
|
+
solver : AbstractCircuitSolver, default=GlobalMNACircuitSolver()
|
|
61
64
|
The circuit solver to use. Available solvers can be found in :mod:`pmrf.models`.
|
|
62
65
|
|
|
66
|
+
Raises
|
|
67
|
+
------
|
|
68
|
+
ValueError
|
|
69
|
+
If two `Port`\\ s share a net, or a `Port` shares a net with a `Ground`.
|
|
70
|
+
|
|
63
71
|
Examples
|
|
64
72
|
--------
|
|
65
73
|
Create a two-port PI-CLC network. External nodes are defined using `Port`,
|
|
@@ -75,8 +83,8 @@ class Circuit(Model):
|
|
|
75
83
|
>>>
|
|
76
84
|
>>> # Create the connections list
|
|
77
85
|
>>> connections = [
|
|
78
|
-
... [(p0, 0), (C1, 1), (L, 1)], # Node 0 -> Port
|
|
79
|
-
... [(p1, 0), (C2, 1), (L, 0)], # Node 1 -> Port
|
|
86
|
+
... [(p0, 0), (C1, 1), (L, 1)], # Node 0 -> Port 0
|
|
87
|
+
... [(p1, 0), (C2, 1), (L, 0)], # Node 1 -> Port 1
|
|
80
88
|
... [(ground, 0), (C1, 0), (C2, 0)], # Node 2 -> Ground
|
|
81
89
|
... ]
|
|
82
90
|
>>>
|
|
@@ -149,6 +157,34 @@ class Circuit(Model):
|
|
|
149
157
|
|
|
150
158
|
self.circuit = models
|
|
151
159
|
self.indexed_connections = indexed_connections
|
|
160
|
+
self._validate_port_nets()
|
|
161
|
+
|
|
162
|
+
def _validate_port_nets(self):
|
|
163
|
+
"""Ensures every `Port` has a net to itself that is not grounded."""
|
|
164
|
+
global_net_map = compute_unique_nets(self.circuit, self.indexed_connections)
|
|
165
|
+
|
|
166
|
+
net_to_port = {}
|
|
167
|
+
ground_nets = set()
|
|
168
|
+
offset = 0
|
|
169
|
+
port_idx = 0
|
|
170
|
+
for model in self.circuit:
|
|
171
|
+
if isinstance(model, Ground):
|
|
172
|
+
ground_nets.update(global_net_map[offset : offset + model.nports].tolist())
|
|
173
|
+
elif isinstance(model, Port):
|
|
174
|
+
net = int(global_net_map[offset])
|
|
175
|
+
label = f"Port {port_idx} ('{getattr(model, 'name', None) or 'unnamed'}')"
|
|
176
|
+
if net in net_to_port:
|
|
177
|
+
raise ValueError(
|
|
178
|
+
f"{net_to_port[net]} and {label} are connected to the same net. "
|
|
179
|
+
"Each Port must be on its own net."
|
|
180
|
+
)
|
|
181
|
+
net_to_port[net] = label
|
|
182
|
+
port_idx += 1
|
|
183
|
+
offset += model.nports
|
|
184
|
+
|
|
185
|
+
for net, label in net_to_port.items():
|
|
186
|
+
if net in ground_nets:
|
|
187
|
+
raise ValueError(f"{label} is connected to a Ground net. A Port cannot be grounded.")
|
|
152
188
|
|
|
153
189
|
def expand(self):
|
|
154
190
|
internal_ports = [comp for comp in self.circuit if isinstance(comp, Port)]
|
|
@@ -209,14 +245,14 @@ class Circuit(Model):
|
|
|
209
245
|
global_net_map = compute_unique_nets(self.circuit, self.indexed_connections)
|
|
210
246
|
|
|
211
247
|
ground_nets = set()
|
|
212
|
-
ext_nets =
|
|
248
|
+
ext_nets = [] # In `Port` declaration order, which fixes the external port order
|
|
213
249
|
offset = 0
|
|
214
250
|
for model in self.circuit:
|
|
215
251
|
nets = global_net_map[offset : offset + model.nports]
|
|
216
252
|
if isinstance(model, Ground):
|
|
217
253
|
ground_nets.update(nets)
|
|
218
254
|
elif isinstance(model, Port):
|
|
219
|
-
ext_nets.
|
|
255
|
+
ext_nets.extend(nets)
|
|
220
256
|
offset += model.nports
|
|
221
257
|
|
|
222
258
|
unique_all_nets = np.unique(global_net_map)
|
|
@@ -243,7 +279,7 @@ class Circuit(Model):
|
|
|
243
279
|
r_idx_mapped = mapping[_safe_cat(r_idx)]
|
|
244
280
|
c_idx_mapped = mapping[_safe_cat(c_idx)]
|
|
245
281
|
|
|
246
|
-
ext_active = np.array(
|
|
282
|
+
ext_active = np.array(ext_nets, dtype=int)
|
|
247
283
|
int_active = np.setdiff1d(active_nets, ext_active)
|
|
248
284
|
|
|
249
285
|
return NodalRepresentation(
|
|
@@ -723,6 +759,14 @@ def flatten_hierarchy(connections: list[list[tuple[Model, int]]]) -> list[list[t
|
|
|
723
759
|
group.sort(key=lambda x: (model_discovery_order[id(x[0])], x[1]))
|
|
724
760
|
valid_groups.append(group)
|
|
725
761
|
|
|
726
|
-
|
|
762
|
+
# Nets holding a top-level `Port` come first, in `Port` declaration order, since
|
|
763
|
+
# the flat circuit's external port order is the order its `Port`s first appear.
|
|
764
|
+
def group_order(group):
|
|
765
|
+
port_orders = [model_discovery_order[id(m)] for m, _ in group if isinstance(m, Port)]
|
|
766
|
+
if port_orders:
|
|
767
|
+
return (0, min(port_orders), 0)
|
|
768
|
+
return (1, model_discovery_order[id(group[0][0])], group[0][1])
|
|
769
|
+
|
|
770
|
+
valid_groups.sort(key=group_order)
|
|
727
771
|
|
|
728
772
|
return valid_groups
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# tests/test_models/test_circuit_port_order.py
|
|
2
|
+
"""
|
|
3
|
+
A `Circuit` orders its external ports by `Port` declaration: the first `Port` found
|
|
4
|
+
scanning `connections` node by node, left to right, is port 0. This must hold for
|
|
5
|
+
every solver and must not depend on how internal components are wired.
|
|
6
|
+
"""
|
|
7
|
+
import pytest
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from pmrf.frequency import Frequency
|
|
11
|
+
from pmrf.models import (
|
|
12
|
+
Circuit, Port, Ground, Resistor, Capacitor, Inductor,
|
|
13
|
+
GlobalScatteringCircuitSolver,
|
|
14
|
+
HierarchicalScatteringCircuitSolver,
|
|
15
|
+
SequentialScatteringCircuitSolver,
|
|
16
|
+
GlobalNodalCircuitSolver,
|
|
17
|
+
GlobalMNACircuitSolver,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
SOLVERS = [
|
|
21
|
+
GlobalScatteringCircuitSolver,
|
|
22
|
+
HierarchicalScatteringCircuitSolver,
|
|
23
|
+
SequentialScatteringCircuitSolver,
|
|
24
|
+
GlobalNodalCircuitSolver,
|
|
25
|
+
GlobalMNACircuitSolver,
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
Z0 = 50.0
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.fixture
|
|
32
|
+
def freq():
|
|
33
|
+
return Frequency(start=1.0, stop=10.0, npoints=3, unit='GHz')
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _y_to_s(Y, z0=Z0):
|
|
37
|
+
"""Independent reference: S = (I - z0 Y)(I + z0 Y)^-1 for a real, uniform z0."""
|
|
38
|
+
eye = np.eye(Y.shape[0])
|
|
39
|
+
return (eye - z0 * Y) @ np.linalg.inv(eye + z0 * Y)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Asymmetric two-port: node A has a 10 Ω shunt, node B a 1000 Ω shunt, with a 5 Ω
|
|
43
|
+
# series resistor between them. Nodal Y written down by hand, ordered (A, B).
|
|
44
|
+
R_A, R_B, R_SERIES = 10.0, 1000.0, 5.0
|
|
45
|
+
Y_AB = np.array([
|
|
46
|
+
[1 / R_A + 1 / R_SERIES, -1 / R_SERIES],
|
|
47
|
+
[-1 / R_SERIES, 1 / R_B + 1 / R_SERIES],
|
|
48
|
+
])
|
|
49
|
+
S_AB = _y_to_s(Y_AB)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _asymmetric_two_port(solver, a_first: bool, series_flipped: bool, **kwargs):
|
|
53
|
+
shunt_a, shunt_b, series = Resistor(R=R_A), Resistor(R=R_B), Resistor(R=R_SERIES)
|
|
54
|
+
port_a, port_b, ground = Port(), Port(), Ground()
|
|
55
|
+
|
|
56
|
+
series_a, series_b = ((series, 1), (series, 0)) if series_flipped else ((series, 0), (series, 1))
|
|
57
|
+
node_a = [(port_a, 0), (shunt_a, 0), series_a]
|
|
58
|
+
node_b = [(port_b, 0), (shunt_b, 0), series_b]
|
|
59
|
+
nodes = [node_a, node_b] if a_first else [node_b, node_a]
|
|
60
|
+
|
|
61
|
+
return Circuit(
|
|
62
|
+
nodes + [[(ground, 0), (shunt_a, 1), (shunt_b, 1)]],
|
|
63
|
+
solver=solver,
|
|
64
|
+
**kwargs,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_asymmetric_two_port_reference_values():
|
|
69
|
+
# Values quoted in issue #165, as a guard on the hand-written reference.
|
|
70
|
+
assert np.isclose(S_AB[0, 0], -0.7122, atol=1e-4)
|
|
71
|
+
assert np.isclose(S_AB[1, 1], -0.5833, atol=1e-4)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@pytest.mark.parametrize("series_flipped", [False, True])
|
|
75
|
+
@pytest.mark.parametrize("a_first", [True, False])
|
|
76
|
+
@pytest.mark.parametrize("solver_cls", SOLVERS)
|
|
77
|
+
def test_ports_follow_declaration_order(solver_cls, a_first, series_flipped, freq):
|
|
78
|
+
circuit = _asymmetric_two_port(solver_cls(), a_first, series_flipped)
|
|
79
|
+
expected = S_AB if a_first else S_AB[::-1, ::-1]
|
|
80
|
+
|
|
81
|
+
s = circuit.s(freq, z0=Z0)
|
|
82
|
+
|
|
83
|
+
np.testing.assert_allclose(s, np.broadcast_to(expected, s.shape), atol=1e-8)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _kron_reduce(Y, keep):
|
|
87
|
+
"""Independent reference: eliminate every node not in `keep` by Schur complement."""
|
|
88
|
+
keep = np.asarray(keep)
|
|
89
|
+
drop = np.setdiff1d(np.arange(Y.shape[0]), keep)
|
|
90
|
+
return Y[np.ix_(keep, keep)] - Y[np.ix_(keep, drop)] @ np.linalg.solve(
|
|
91
|
+
Y[np.ix_(drop, drop)], Y[np.ix_(drop, keep)]
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@pytest.mark.parametrize("flatten", [False, True])
|
|
96
|
+
@pytest.mark.parametrize("solver_cls", SOLVERS)
|
|
97
|
+
def test_nested_circuit_ports_follow_declaration_order(solver_cls, flatten, freq):
|
|
98
|
+
# The inner circuit has its series element's port indices swapped.
|
|
99
|
+
inner = _asymmetric_two_port(solver_cls(), a_first=True, series_flipped=True)
|
|
100
|
+
|
|
101
|
+
# The outer circuit adds a 3 Ω series resistor on A and a 2 Ω one on B. The
|
|
102
|
+
# resistor on B is declared first, so it is discovered before either `Port`,
|
|
103
|
+
# but port A is still the first `Port` declared.
|
|
104
|
+
r_ta, r_tb = 3.0, 2.0
|
|
105
|
+
t_a, t_b = Resistor(R=r_ta), Resistor(R=r_tb)
|
|
106
|
+
port_a, port_b = Port(), Port()
|
|
107
|
+
outer = Circuit([
|
|
108
|
+
[(t_b, 0), (inner, 1)],
|
|
109
|
+
[(t_a, 0), (inner, 0)],
|
|
110
|
+
[(port_a, 0), (t_a, 1)],
|
|
111
|
+
[(port_b, 0), (t_b, 1)],
|
|
112
|
+
], solver=solver_cls(), flatten=flatten)
|
|
113
|
+
|
|
114
|
+
# Nodes (A, B, port A, port B), by hand.
|
|
115
|
+
Y = np.zeros((4, 4))
|
|
116
|
+
Y[:2, :2] = Y_AB
|
|
117
|
+
for i, j, R in [(0, 2, r_ta), (1, 3, r_tb)]:
|
|
118
|
+
Y[np.ix_([i, j], [i, j])] += np.array([[1, -1], [-1, 1]]) / R
|
|
119
|
+
expected = _y_to_s(_kron_reduce(Y, keep=[2, 3]))
|
|
120
|
+
|
|
121
|
+
s = outer.s(freq, z0=Z0)
|
|
122
|
+
|
|
123
|
+
np.testing.assert_allclose(s, np.broadcast_to(expected, s.shape), atol=1e-8)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_ports_sharing_a_net_raise():
|
|
127
|
+
shunt, ground = Resistor(R=R_A), Ground()
|
|
128
|
+
port_a, port_b = Port(name="port_a"), Port(name="port_b")
|
|
129
|
+
|
|
130
|
+
with pytest.raises(ValueError, match="port_a.*port_b"):
|
|
131
|
+
Circuit([
|
|
132
|
+
[(port_a, 0), (port_b, 0), (shunt, 0)],
|
|
133
|
+
[(ground, 0), (shunt, 1)],
|
|
134
|
+
])
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def test_port_sharing_a_net_with_ground_raises():
|
|
138
|
+
shunt, ground = Resistor(R=R_A), Ground()
|
|
139
|
+
port_a, port_b = Port(name="port_a"), Port(name="port_b")
|
|
140
|
+
|
|
141
|
+
with pytest.raises(ValueError, match="port_b.*Ground"):
|
|
142
|
+
Circuit([
|
|
143
|
+
[(port_a, 0), (shunt, 0)],
|
|
144
|
+
[(ground, 0), (shunt, 1), (port_b, 0)],
|
|
145
|
+
])
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@pytest.mark.parametrize("solver_cls", SOLVERS)
|
|
149
|
+
def test_pi_clc_docstring_example_matches_skrf(solver_cls, freq):
|
|
150
|
+
skrf = pytest.importorskip("skrf")
|
|
151
|
+
|
|
152
|
+
# Exactly the `Circuit` docstring example: `(L, 1)` on the first node.
|
|
153
|
+
C1, C2 = Capacitor(C=2e-12), Capacitor(C=1.5e-12)
|
|
154
|
+
L = Inductor(L=3e-9)
|
|
155
|
+
p0, p1, ground = Port(), Port(), Ground()
|
|
156
|
+
pi_clc = Circuit([
|
|
157
|
+
[(p0, 0), (C1, 1), (L, 1)],
|
|
158
|
+
[(p1, 0), (C2, 1), (L, 0)],
|
|
159
|
+
[(ground, 0), (C1, 0), (C2, 0)],
|
|
160
|
+
], solver=solver_cls())
|
|
161
|
+
|
|
162
|
+
# Port 1 is the C1 side.
|
|
163
|
+
media = skrf.media.DefinedGammaZ0(frequency=freq.to_skrf(), z0_port=Z0)
|
|
164
|
+
expected = (
|
|
165
|
+
media.shunt_capacitor(2e-12) ** media.inductor(3e-9) ** media.shunt_capacitor(1.5e-12)
|
|
166
|
+
).s
|
|
167
|
+
|
|
168
|
+
np.testing.assert_allclose(pi_clc.s(freq, z0=Z0), expected, atol=1e-8)
|
|
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
|
|
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
|
|
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
|