paramrf 0.36.2__tar.gz → 0.36.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.
Files changed (249) hide show
  1. {paramrf-0.36.2/paramrf.egg-info → paramrf-0.36.3}/PKG-INFO +1 -1
  2. {paramrf-0.36.2 → paramrf-0.36.3/paramrf.egg-info}/PKG-INFO +1 -1
  3. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/utils/transforms.py +23 -4
  4. {paramrf-0.36.2 → paramrf-0.36.3}/pyproject.toml +1 -1
  5. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_edge_values.py +65 -3
  6. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_transforms.py +98 -0
  7. {paramrf-0.36.2 → paramrf-0.36.3}/.github/workflows/docs.yml +0 -0
  8. {paramrf-0.36.2 → paramrf-0.36.3}/.github/workflows/draft-pdf.yml +0 -0
  9. {paramrf-0.36.2 → paramrf-0.36.3}/.github/workflows/publish.yml +0 -0
  10. {paramrf-0.36.2 → paramrf-0.36.3}/.github/workflows/tests.yml +0 -0
  11. {paramrf-0.36.2 → paramrf-0.36.3}/.gitignore +0 -0
  12. {paramrf-0.36.2 → paramrf-0.36.3}/AGENTS.md +0 -0
  13. {paramrf-0.36.2 → paramrf-0.36.3}/CHANGELOG.md +0 -0
  14. {paramrf-0.36.2 → paramrf-0.36.3}/CITATION.cff +0 -0
  15. {paramrf-0.36.2 → paramrf-0.36.3}/CLAUDE.md +0 -0
  16. {paramrf-0.36.2 → paramrf-0.36.3}/CONTEXT.md +0 -0
  17. {paramrf-0.36.2 → paramrf-0.36.3}/CONTRIBUTING.md +0 -0
  18. {paramrf-0.36.2 → paramrf-0.36.3}/LICENSE +0 -0
  19. {paramrf-0.36.2 → paramrf-0.36.3}/NOTICE +0 -0
  20. {paramrf-0.36.2 → paramrf-0.36.3}/README.rst +0 -0
  21. {paramrf-0.36.2 → paramrf-0.36.3}/assets/logo.png +0 -0
  22. {paramrf-0.36.2 → paramrf-0.36.3}/docs/Makefile +0 -0
  23. {paramrf-0.36.2 → paramrf-0.36.3}/docs/_static/custom.css +0 -0
  24. {paramrf-0.36.2 → paramrf-0.36.3}/docs/_templates/autosummary/class.rst +0 -0
  25. {paramrf-0.36.2 → paramrf-0.36.3}/docs/_templates/autosummary/function.rst +0 -0
  26. {paramrf-0.36.2 → paramrf-0.36.3}/docs/_templates/autosummary/module.rst +0 -0
  27. {paramrf-0.36.2 → paramrf-0.36.3}/docs/adr/0001-line-modelling-architecture.md +0 -0
  28. {paramrf-0.36.2 → paramrf-0.36.3}/docs/adr/0002-parameter-api.md +0 -0
  29. {paramrf-0.36.2 → paramrf-0.36.3}/docs/adr/0003-derived-models.md +0 -0
  30. {paramrf-0.36.2 → paramrf-0.36.3}/docs/adr/0004-profiled-lines.md +0 -0
  31. {paramrf-0.36.2 → paramrf-0.36.3}/docs/adr/0005-priors-by-name.md +0 -0
  32. {paramrf-0.36.2 → paramrf-0.36.3}/docs/adr/0006-reference-impedance.md +0 -0
  33. {paramrf-0.36.2 → paramrf-0.36.3}/docs/adr/0007-edge-values.md +0 -0
  34. {paramrf-0.36.2 → paramrf-0.36.3}/docs/agents/domain.md +0 -0
  35. {paramrf-0.36.2 → paramrf-0.36.3}/docs/agents/issue-tracker.md +0 -0
  36. {paramrf-0.36.2 → paramrf-0.36.3}/docs/agents/triage-labels.md +0 -0
  37. {paramrf-0.36.2 → paramrf-0.36.3}/docs/api/index.rst +0 -0
  38. {paramrf-0.36.2 → paramrf-0.36.3}/docs/conf.py +0 -0
  39. {paramrf-0.36.2 → paramrf-0.36.3}/docs/core_concepts/core_primitives.rst +0 -0
  40. {paramrf-0.36.2 → paramrf-0.36.3}/docs/core_concepts/index.rst +0 -0
  41. {paramrf-0.36.2 → paramrf-0.36.3}/docs/core_concepts/jax_overview.rst +0 -0
  42. {paramrf-0.36.2 → paramrf-0.36.3}/docs/core_concepts/optimization_and_inference.rst +0 -0
  43. {paramrf-0.36.2 → paramrf-0.36.3}/docs/core_concepts/parameter_names.rst +0 -0
  44. {paramrf-0.36.2 → paramrf-0.36.3}/docs/examples/cascading_and_terminating.rst +0 -0
  45. {paramrf-0.36.2 → paramrf-0.36.3}/docs/examples/circuit_clc.png +0 -0
  46. {paramrf-0.36.2 → paramrf-0.36.3}/docs/examples/circuit_models.rst +0 -0
  47. {paramrf-0.36.2 → paramrf-0.36.3}/docs/examples/custom_models.rst +0 -0
  48. {paramrf-0.36.2 → paramrf-0.36.3}/docs/examples/derivatives_and_sweeps.rst +0 -0
  49. {paramrf-0.36.2 → paramrf-0.36.3}/docs/examples/index.rst +0 -0
  50. {paramrf-0.36.2 → paramrf-0.36.3}/docs/examples/model_optimization.rst +0 -0
  51. {paramrf-0.36.2 → paramrf-0.36.3}/docs/examples/multiple_models_one_parameter_set.rst +0 -0
  52. {paramrf-0.36.2 → paramrf-0.36.3}/docs/examples/parameter_naming_and_model_manipulation.rst +0 -0
  53. {paramrf-0.36.2 → paramrf-0.36.3}/docs/examples/shared_substrates.rst +0 -0
  54. {paramrf-0.36.2 → paramrf-0.36.3}/docs/index.rst +0 -0
  55. {paramrf-0.36.2 → paramrf-0.36.3}/docs/license.rst +0 -0
  56. {paramrf-0.36.2 → paramrf-0.36.3}/docs/make.bat +0 -0
  57. {paramrf-0.36.2 → paramrf-0.36.3}/docs/research/conductor-loss-alternatives.md +0 -0
  58. {paramrf-0.36.2 → paramrf-0.36.3}/docs/research/holloway1994.pdf +0 -0
  59. {paramrf-0.36.2 → paramrf-0.36.3}/docs/research/microstrip-loss-conventions.md +0 -0
  60. {paramrf-0.36.2 → paramrf-0.36.3}/docs/research/precision-coax-microstrip-10-500mhz.md +0 -0
  61. {paramrf-0.36.2 → paramrf-0.36.3}/docs/skrf_comparison/index.rst +0 -0
  62. {paramrf-0.36.2 → paramrf-0.36.3}/docs/skrf_comparison/overview.rst +0 -0
  63. {paramrf-0.36.2 → paramrf-0.36.3}/docs/skrf_comparison/performance.rst +0 -0
  64. {paramrf-0.36.2 → paramrf-0.36.3}/docs/tutorials/1_cable_fitting.ipynb +0 -0
  65. {paramrf-0.36.2 → paramrf-0.36.3}/docs/tutorials/2_chip_inductor_fitting.ipynb +0 -0
  66. {paramrf-0.36.2 → paramrf-0.36.3}/docs/tutorials/data/CBN-1.5FT-SMSM.s2p +0 -0
  67. {paramrf-0.36.2 → paramrf-0.36.3}/docs/tutorials/data/on-chip-inductor.s2p +0 -0
  68. {paramrf-0.36.2 → paramrf-0.36.3}/docs/tutorials/index.rst +0 -0
  69. {paramrf-0.36.2 → paramrf-0.36.3}/paper/paper.bib +0 -0
  70. {paramrf-0.36.2 → paramrf-0.36.3}/paper/paper.md +0 -0
  71. {paramrf-0.36.2 → paramrf-0.36.3}/paper/rlc.png +0 -0
  72. {paramrf-0.36.2 → paramrf-0.36.3}/paramrf.egg-info/SOURCES.txt +0 -0
  73. {paramrf-0.36.2 → paramrf-0.36.3}/paramrf.egg-info/dependency_links.txt +0 -0
  74. {paramrf-0.36.2 → paramrf-0.36.3}/paramrf.egg-info/requires.txt +0 -0
  75. {paramrf-0.36.2 → paramrf-0.36.3}/paramrf.egg-info/top_level.txt +0 -0
  76. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/__init__.py +0 -0
  77. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/_solver_view.py +0 -0
  78. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/bijectors.py +0 -0
  79. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/constraints.py +0 -0
  80. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/covariance_kernels.py +0 -0
  81. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/discrepancy_models.py +0 -0
  82. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/distributions.py +0 -0
  83. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/evaluators.py +0 -0
  84. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/fitting/__init__.py +0 -0
  85. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/fitting/minimize.py +0 -0
  86. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/fitting/result.py +0 -0
  87. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/fitting/routers.py +0 -0
  88. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/fitting/sample.py +0 -0
  89. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/fitting/targets.py +0 -0
  90. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/frequency.py +0 -0
  91. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/infer/__init__.py +0 -0
  92. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/infer/base.py +0 -0
  93. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/infer/result.py +0 -0
  94. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/infer/sample.py +0 -0
  95. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/infer/solvers/__init__.py +0 -0
  96. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/infer/solvers/blackjax.py +0 -0
  97. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/infer/solvers/polychord.py +0 -0
  98. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/likelihoods.py +0 -0
  99. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/losses.py +0 -0
  100. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/materials/__init__.py +0 -0
  101. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/materials/conductor.py +0 -0
  102. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/materials/dielectric.py +0 -0
  103. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/materials/properties.py +0 -0
  104. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/materials/roughness.py +0 -0
  105. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/materials/substrate.py +0 -0
  106. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/materials/surface_impedance.py +0 -0
  107. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/math/__init__.py +0 -0
  108. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/math/aggregations.py +0 -0
  109. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/math/bessel.py +0 -0
  110. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/math/conversions.py +0 -0
  111. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/math/losses.py +0 -0
  112. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/math/misc.py +0 -0
  113. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/__init__.py +0 -0
  114. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/adapters/__init__.py +0 -0
  115. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/adapters/base.py +0 -0
  116. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/adapters/bridge.py +0 -0
  117. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/adapters/callable.py +0 -0
  118. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/adapters/delegated.py +0 -0
  119. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/adapters/derived.py +0 -0
  120. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/adapters/static.py +0 -0
  121. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/adapters/wrapped.py +0 -0
  122. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/base.py +0 -0
  123. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/__init__.py +0 -0
  124. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/ideal.py +0 -0
  125. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/__init__.py +0 -0
  126. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/base.py +0 -0
  127. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/coaxial.py +0 -0
  128. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/empirical.py +0 -0
  129. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/ideal.py +0 -0
  130. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/microstrip.py +0 -0
  131. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/nodal.py +0 -0
  132. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/nonuniform.py +0 -0
  133. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/planar.py +0 -0
  134. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/profiles.py +0 -0
  135. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lines/stripline.py +0 -0
  136. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/lumped.py +0 -0
  137. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/components/sections.py +0 -0
  138. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/__init__.py +0 -0
  139. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/interconnected/__init__.py +0 -0
  140. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/interconnected/cascade.py +0 -0
  141. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/interconnected/circuit/__init__.py +0 -0
  142. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/interconnected/circuit/base.py +0 -0
  143. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/interconnected/circuit/circuit.py +0 -0
  144. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/interconnected/circuit/solvers/__init__.py +0 -0
  145. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/interconnected/circuit/solvers/nodal.py +0 -0
  146. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/interconnected/circuit/solvers/scattering.py +0 -0
  147. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/interconnected/terminated.py +0 -0
  148. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/nodal.py +0 -0
  149. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/topological.py +0 -0
  150. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/composite/transformed.py +0 -0
  151. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/surrogates/__init__.py +0 -0
  152. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/surrogates/expansion.py +0 -0
  153. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/models/surrogates/rational.py +0 -0
  154. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/modules/__init__.py +0 -0
  155. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/modules/base.py +0 -0
  156. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/modules/wrapped.py +0 -0
  157. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/network_collection.py +0 -0
  158. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/noise_models.py +0 -0
  159. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/optimize/__init__.py +0 -0
  160. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/optimize/base.py +0 -0
  161. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/optimize/minimize.py +0 -0
  162. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/optimize/result.py +0 -0
  163. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/optimize/solvers/__init__.py +0 -0
  164. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/optimize/solvers/jaxopt.py +0 -0
  165. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/optimize/solvers/optimistix.py +0 -0
  166. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/optimize/solvers/scipy.py +0 -0
  167. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/parameters.py +0 -0
  168. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/problems.py +0 -0
  169. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/rf/__init__.py +0 -0
  170. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/rf/cascade.py +0 -0
  171. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/rf/conversions.py +0 -0
  172. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/rf/mna.py +0 -0
  173. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/serialization.py +0 -0
  174. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/terms.py +0 -0
  175. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/types.py +0 -0
  176. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/utils/__init__.py +0 -0
  177. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/utils/array.py +0 -0
  178. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/utils/debug.py +0 -0
  179. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/utils/network.py +0 -0
  180. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/utils/random.py +0 -0
  181. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/utils/rf.py +0 -0
  182. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/utils/tree.py +0 -0
  183. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/utils/type.py +0 -0
  184. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/viz/__init__.py +0 -0
  185. {paramrf-0.36.2 → paramrf-0.36.3}/pmrf/viz/plots.py +0 -0
  186. {paramrf-0.36.2 → paramrf-0.36.3}/scripts/install-test-deps.sh +0 -0
  187. {paramrf-0.36.2 → paramrf-0.36.3}/setup.cfg +0 -0
  188. {paramrf-0.36.2 → paramrf-0.36.3}/tests/__init__.py +0 -0
  189. {paramrf-0.36.2 → paramrf-0.36.3}/tests/_jit.py +0 -0
  190. {paramrf-0.36.2 → paramrf-0.36.3}/tests/conftest.py +0 -0
  191. {paramrf-0.36.2 → paramrf-0.36.3}/tests/data/10m_cable.s2p +0 -0
  192. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_autodiff.py +0 -0
  193. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_box_space_solving.py +0 -0
  194. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_conversions.py +0 -0
  195. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_covariance_kernels.py +0 -0
  196. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_dc_limits.py +0 -0
  197. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_evaluators.py +0 -0
  198. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_fitting_minimize.py +0 -0
  199. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_fitting_routers.py +0 -0
  200. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_fitting_sample.py +0 -0
  201. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_fitting_targets.py +0 -0
  202. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_frequency.py +0 -0
  203. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_infer_base.py +0 -0
  204. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_infer_sample.py +0 -0
  205. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_map_priors.py +0 -0
  206. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_materials/test_conductor.py +0 -0
  207. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_materials/test_dielectric.py +0 -0
  208. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_materials/test_serialization.py +0 -0
  209. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_materials/test_substrate.py +0 -0
  210. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_materials/test_surface_impedance.py +0 -0
  211. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_math/test_bessel.py +0 -0
  212. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_model.py +0 -0
  213. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_adapters.py +0 -0
  214. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_cascade.py +0 -0
  215. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_circuit_native_z0.py +0 -0
  216. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_circuit_nodal.py +0 -0
  217. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_circuit_port_order.py +0 -0
  218. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_circuit_scattering.py +0 -0
  219. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_circuit_shorted_ports.py +0 -0
  220. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_circuit_skrf_port_names.py +0 -0
  221. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_circuit_z0.py +0 -0
  222. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_current_distribution.py +0 -0
  223. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_derived.py +0 -0
  224. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_interconnected.py +0 -0
  225. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_lines.py +0 -0
  226. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_lines_skrf_matrix.py +0 -0
  227. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_lumped.py +0 -0
  228. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_nodal.py +0 -0
  229. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_profiles.py +0 -0
  230. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_rational.py +0 -0
  231. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_repeated_cascade.py +0 -0
  232. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_sections.py +0 -0
  233. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_transformed.py +0 -0
  234. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_models/test_transformers.py +0 -0
  235. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_module.py +0 -0
  236. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_naming.py +0 -0
  237. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_optimize_base.py +0 -0
  238. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_optimize_minimize.py +0 -0
  239. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_parameters.py +0 -0
  240. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_parameters_by_name.py +0 -0
  241. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_parameters_joint_prior.py +0 -0
  242. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_parameters_prior.py +0 -0
  243. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_parameters_validity.py +0 -0
  244. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_raw_space_solving.py +0 -0
  245. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_serialization.py +0 -0
  246. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_structural_updates.py +0 -0
  247. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_terms.py +0 -0
  248. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_utils/test_compress.py +0 -0
  249. {paramrf-0.36.2 → paramrf-0.36.3}/tests/test_utils/test_tree.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paramrf
3
- Version: 0.36.2
3
+ Version: 0.36.3
4
4
  Summary: Parametric radio frequency modeling
5
5
  Author-email: Gary Allen <gvcallen@gmail.com>
6
6
  Project-URL: homepage, https://github.com/gvcallen/paramrf
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paramrf
3
- Version: 0.36.2
3
+ Version: 0.36.3
4
4
  Summary: Parametric radio frequency modeling
5
5
  Author-email: Gary Allen <gvcallen@gmail.com>
6
6
  Project-URL: homepage, https://github.com/gvcallen/paramrf
@@ -1,6 +1,9 @@
1
+ import dataclasses
2
+
1
3
  import jax
2
4
  import jax.numpy as jnp
3
5
  import equinox as eqx
6
+ import parax as prx
4
7
  from typing import Callable, Any, Tuple, TypeVarTuple
5
8
 
6
9
  from pmrf.utils.tree import unwrap, batch_axes
@@ -35,6 +38,11 @@ def derivative(eval_fn: Callable[..., Any], *args: *Ts, space: str = 'declared')
35
38
  inside the differentiated function, so the source's derivative includes the
36
39
  path through the tie. Raw JAX arrays are differentiated as they are.
37
40
 
41
+ In declared and physical space a parameter on a closed bound, such as a
42
+ ``NonNegative`` loss at 0, has a finite derivative. In raw space it has none:
43
+ its raw value there is infinite, so a derivative with respect to it has no
44
+ finite meaning.
45
+
38
46
  Safely handles models as inputs by filtering out non-differentiable
39
47
  static fields (like strings, booleans, integers, AND NumPy arrays).
40
48
 
@@ -82,15 +90,15 @@ def derivative(eval_fn: Callable[..., Any], *args: *Ts, space: str = 'declared')
82
90
  -1.164e-01
83
91
  """
84
92
  # Imported here: pmrf.parameters imports pmrf.utils.
85
- from pmrf.parameters import _check_space, _read, _set_paths, _with_fixed, _write, tree_param_paths
93
+ from pmrf.parameters import _check_space, _read, _set_paths, _with_fixed, _write, is_param, tree_param_paths
86
94
  from pmrf.utils.tree import Pathgetter
87
95
 
88
96
  _check_space(space)
89
97
 
90
98
  # Each parameter is replaced by its value in `space`, and rebuilt from it inside
91
99
  # the differentiated function, so the derivative is taken with respect to that
92
- # value and the chain rule carries it through scale, constraint and ties. Fixed
93
- # is an optimisation state, not a zero sensitivity, so parameters are rebuilt free.
100
+ # value and the chain rule carries it through scale and ties. Fixed is an
101
+ # optimisation state, not a zero sensitivity, so parameters are rebuilt free.
94
102
  rebuilds = []
95
103
  surrogates = []
96
104
  for arg in args:
@@ -103,12 +111,23 @@ def derivative(eval_fn: Callable[..., Any], *args: *Ts, space: str = 'declared')
103
111
  rebuilds.append((paths, nodes))
104
112
  surrogates.append(_set_paths(arg, paths, [_read(node, space) for node in nodes]))
105
113
 
114
+ def _rebuild_node(node, value):
115
+ # In declared and physical space a parameter holds its declared value directly,
116
+ # as in box space (#226), not through its raw value: on a closed bound that is
117
+ # infinite, the constraint's bijector gives 0 * inf = NaN, and forward mode
118
+ # spreads the NaN to every parameter. The value is the one the parameter was
119
+ # built with, so its bounds need no checking again. A `Real` is free.
120
+ if not is_param(node) or space == 'raw':
121
+ return _with_fixed(_write(node, value, space), False)
122
+ declared = value / node._scale if space == 'physical' and node._scale != 1.0 else value
123
+ return dataclasses.replace(node, variable=prx.Real(declared))
124
+
106
125
  def _rebuild(surrogate_args):
107
126
  rebuilt = []
108
127
  for surrogate, (paths, nodes) in zip(surrogate_args, rebuilds):
109
128
  values = [Pathgetter(path)(surrogate) for path in paths]
110
129
  rebuilt.append(_set_paths(
111
- surrogate, paths, [_with_fixed(_write(node, value, space), False) for node, value in zip(nodes, values)]
130
+ surrogate, paths, [_rebuild_node(node, value) for node, value in zip(nodes, values)]
112
131
  ))
113
132
  return unwrap(tuple(rebuilt))
114
133
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "paramrf"
3
- version = "0.36.2"
3
+ version = "0.36.3"
4
4
  description = "Parametric radio frequency modeling"
5
5
  readme = "README.rst"
6
6
  authors = [
@@ -7,6 +7,12 @@ parameter in turn is set to zero, where its validity constraint allows it, and t
7
7
  finite closed bound of that constraint. S and its derivative with respect to that
8
8
  parameter must be finite, and the MNA and scattering solvers must agree on both.
9
9
 
10
+ dS is taken with a `jax.jvp` through the component's constructor, which never goes
11
+ through `prf.derivative`; that is how #238 shipped, NaN from `derivative` on closed
12
+ bounds where every component passed. So each case also takes `prf.derivative` of S with
13
+ respect to every parameter of the component, the swept one on its edge value, and checks
14
+ it is finite and agrees with dS (#239).
15
+
10
16
  Infinite bounds are closed too (Parax ADR 0001: `Positive()` is (0, inf]), but a
11
17
  consumer that treats a closed bound as an evaluable point must skip non-finite ones, so
12
18
  the sweep does.
@@ -31,6 +37,7 @@ What the sweep found, and what was done (#224):
31
37
  negative winding inductance, so negative values never worked.
32
38
  - `Load.z0 = 0`, `Port.z0 = 0`: not evaluated; see `NOT_EVALUATED`.
33
39
  """
40
+ import dataclasses
34
41
  import inspect
35
42
 
36
43
  import equinox as eqx
@@ -40,8 +47,10 @@ import numpy as np
40
47
  import parax as prx
41
48
  import pytest
42
49
 
50
+ import pmrf as prf
43
51
  import pmrf.models
44
52
  from pmrf.frequency import Frequency
53
+ from pmrf.materials import ColeColeDielectric, MultipoleDebyeDielectric, RoughConductor
45
54
  from pmrf.parameters import Param
46
55
  from pmrf.models import (
47
56
  Model, Circuit, Port,
@@ -88,9 +97,17 @@ EXAMPLES = {
88
97
  RLGCLine: lambda: RLGCLine(R=0.1, L=250e-9, G=1e-6, C=100e-12, length=0.07),
89
98
  PhysicalLine: lambda: PhysicalLine(zn=50.0, ep_r=2.2, A=0.01, f_A=1e9, tand=0.001, length=1.0),
90
99
  DatasheetLine: lambda: DatasheetLine(zn=50.0, vf=0.69, k1=0.2, k2=0.01, length=1.0),
91
- CoaxialLine: lambda: CoaxialLine(length=0.5),
100
+ # Dispersive and rough materials, so their loss parameters (dep_r, alpha, rms) are
101
+ # swept too; MicrostripLine keeps the default ConstantDielectric and BulkConductor.
102
+ CoaxialLine: lambda: CoaxialLine(
103
+ length=0.5,
104
+ dielectric=ColeColeDielectric(ep_inf=2.0, dep_r=0.3, f_relax=1e9, alpha=0.2, sigma=1e-4),
105
+ conductor=RoughConductor(sigma=5.8e7, roughness=1e-6),
106
+ ),
92
107
  MicrostripLine: lambda: MicrostripLine(length=0.1),
93
- StriplineLine: lambda: StriplineLine(length=0.1),
108
+ StriplineLine: lambda: StriplineLine(
109
+ length=0.1, dielectric=MultipoleDebyeDielectric(ep_inf=2.0, poles=[(0.3, 1e9)]),
110
+ ),
94
111
  FloatingLine: lambda: FloatingLine(floating=PhaseLine(z0=50.0, theta=90.0, f0=0.5e9)),
95
112
  Resistor: lambda: Resistor(R=10.0),
96
113
  Capacitor: lambda: Capacitor(C=1e-12),
@@ -226,12 +243,46 @@ def _s_and_ds(cls, path, value, solver):
226
243
  return jax.jvp(s_of, (jnp.asarray(value),), (jnp.asarray(1.0),))
227
244
 
228
245
 
246
+ def _with_param(model, path, x):
247
+ """`model` with the parameter at `path` kept a parameter, holding the declared value `x`.
248
+
249
+ Unlike `_at`, which puts a plain array there, so `prf.derivative` meets the parameter
250
+ on its bound, constraint and all.
251
+ """
252
+ get = _getter(path)
253
+ param = get(model)
254
+ declared = jnp.broadcast_to(jnp.asarray(x), jnp.shape(param.value))
255
+ return eqx.tree_at(get, model, dataclasses.replace(param, value=declared))
256
+
257
+
258
+ def _derivative(cls, path, value, solver):
259
+ """dS with respect to every parameter of the component, by `prf.derivative`.
260
+
261
+ Returns the swept parameter's derivative, and every parameter's derivative.
262
+ """
263
+ model = _with_param(EXAMPLES[cls](), path, value)
264
+ s_of = lambda m: _in_circuit(m, solver).s(FREQ)
265
+ # Forward mode is where a NaN from one parameter reaches every other (#238), so the
266
+ # derivative must be taken in forward mode. S is complex, which `derivative` always
267
+ # takes forward, and it has more entries than the component has parameters, so it
268
+ # would be wide, and taken forward, if it were real.
269
+ n_params = sum(jnp.size(param.value) for _, param in _params(model))
270
+ assert jax.eval_shape(s_of, model).size > n_params, "the derivative is not wide"
271
+ (d_model,) = prf.derivative(s_of, model)
272
+ param_derivatives = [_getter(p)(d_model) for p, _ in _params(model)]
273
+ return _getter(path)(d_model), param_derivatives
274
+
275
+
229
276
  # The scattering solver regularises its own system with eps = 1e-12, which moves S, and
230
277
  # dS relative to its size, by about 2e-12 (see test_lumped.py). dS is compared relative
231
278
  # to its largest entry, which reaches 6e6 for an inductor at zero.
232
279
  SCATTERING_TOL = 1e-11
233
280
 
234
281
 
282
+ def _ds_atol(ref_ds):
283
+ return SCATTERING_TOL * max(1.0, np.max(np.abs(ref_ds)))
284
+
285
+
235
286
  @pytest.mark.parametrize("cls, path, value", _cases())
236
287
  def test_component_at_edge_value(cls, path, value):
237
288
  s, ds = _s_and_ds(cls, path, value, GlobalMNACircuitSolver())
@@ -242,7 +293,18 @@ def test_component_at_edge_value(cls, path, value):
242
293
  assert np.all(np.isfinite(ref_s)), "non-finite S under scattering"
243
294
  assert np.all(np.isfinite(ref_ds)), "non-finite dS under scattering"
244
295
  np.testing.assert_allclose(s, ref_s, rtol=0, atol=SCATTERING_TOL)
245
- np.testing.assert_allclose(ds, ref_ds, rtol=0, atol=SCATTERING_TOL * max(1.0, np.max(np.abs(ref_ds))))
296
+ np.testing.assert_allclose(ds, ref_ds, rtol=0, atol=_ds_atol(ref_ds))
297
+
298
+ # `prf.derivative` against the jvp under the same solver: both differentiate the same
299
+ # computation, so they differ only by rounding, well inside the sweep's dS tolerance.
300
+ for solver, sweep_ds in [(GlobalMNACircuitSolver(), ds), (GlobalScatteringCircuitSolver(), ref_ds)]:
301
+ name = type(solver).__name__
302
+ swept, param_derivatives = _derivative(cls, path, value, solver)
303
+ assert all(np.all(np.isfinite(d)) for d in param_derivatives), f"non-finite prf.derivative under {name}"
304
+ np.testing.assert_allclose(
305
+ np.reshape(swept, np.shape(sweep_ds)), sweep_ds, rtol=0, atol=_ds_atol(sweep_ds),
306
+ err_msg=f"prf.derivative disagrees with dS under {name}",
307
+ )
246
308
 
247
309
 
248
310
  @pytest.mark.parametrize("cls, field", [
@@ -245,6 +245,104 @@ def test_derivative_rejects_an_unknown_space():
245
245
  prf.derivative(lambda x: x ** 2, jnp.array(1.0), space='unscaled')
246
246
 
247
247
 
248
+ @pytest.mark.parametrize("space", ["declared", "physical"])
249
+ @pytest.mark.parametrize("k2", [0.0, 1e-6])
250
+ def test_derivative_on_and_near_a_closed_bound(space, k2):
251
+ """`k2` is NonNegative: at 0 its raw value is -inf, which must not reach the derivative."""
252
+ from pmrf.models import DatasheetLine
253
+
254
+ line = DatasheetLine(length=1.0, zn=50.0, vf=0.8, k1=0.1, k2=k2)
255
+
256
+ (d_line,) = prf.derivative(lambda m: 2.0 * m.k2, line, space=space)
257
+
258
+ assert prf.values(d_line)['k2'] == 2.0
259
+
260
+
261
+ def test_a_closed_bound_is_still_a_valid_value():
262
+ from pmrf.models import DatasheetLine
263
+
264
+ line = DatasheetLine(length=1.0, zn=50.0, vf=0.8, k1=0.1, k2=0.5)
265
+
266
+ assert prf.values(prf.update(line, {'k2': 0.0}))['k2'] == 0.0
267
+ with pytest.raises(Exception, match="outside the constraint"):
268
+ prf.update(line, {'k2': -1.0})
269
+
270
+
271
+ _CLOSED_BOUNDS = {
272
+ 'non_negative': (0.0, prf.constraints.NonNegative()),
273
+ 'greater_than': (2.0, prf.constraints.GreaterThan(2.0)),
274
+ 'interval_upper': (3.0, prf.constraints.Interval(1.0, 3.0)),
275
+ 'less_than': (3.0, prf.constraints.LessThan(3.0)),
276
+ }
277
+
278
+
279
+ @pytest.mark.parametrize("n", [1, 50], ids=['tall', 'wide'])
280
+ @pytest.mark.parametrize("space", ["declared", "physical"])
281
+ @pytest.mark.parametrize("bound", list(_CLOSED_BOUNDS))
282
+ def test_derivative_on_a_closed_bound_is_exact_and_confined(bound, space, n):
283
+ """On a closed bound the derivative is finite and exact, and does not reach the
284
+ other parameters, whether taken by reverse mode (tall) or forward mode (wide)."""
285
+ value, constraint = _CLOSED_BOUNDS[bound]
286
+ scale = 1e-3
287
+ tree = {
288
+ 'a': prf.Param(value=value, constraint=constraint, scale=scale),
289
+ 'b': prf.Unconstrained(1.5),
290
+ }
291
+ x = jnp.linspace(0.0, 1.0, n)
292
+
293
+ (d_tree,) = prf.derivative(lambda t: 2.0 * t['a'] + t['b'] * x, tree, space=space)
294
+
295
+ per_unit = 1.0 if space == 'physical' else scale
296
+ assert jnp.array_equal(d_tree['a'], jnp.full(n, 2.0 * per_unit))
297
+ assert jnp.array_equal(d_tree['b'], x)
298
+
299
+
300
+ def test_derivative_in_physical_space_on_a_closed_bound_is_declared_over_scale():
301
+ tree = {'a': prf.Param(value=0.0, constraint=prf.constraints.NonNegative(), scale=1e-3)}
302
+ fn = lambda t: jnp.sin(t['a'] + 0.3)
303
+
304
+ (declared,) = prf.derivative(fn, tree)
305
+ (physical,) = prf.derivative(fn, tree, space='physical')
306
+
307
+ assert jnp.isfinite(declared['a'])
308
+ assert jnp.allclose(physical['a'], declared['a'] / 1e-3, rtol=1e-12, atol=0)
309
+
310
+
311
+ def _coax_on_a_closed_bound():
312
+ from pmrf.models import CoaxialLine, SchelkunoffCoaxialFormulation
313
+ from pmrf.materials import DjordjevicSarkarDielectric, BulkConductor
314
+
315
+ # The dielectric's conductivity defaults to 0, the closed bound of NonNegative.
316
+ return CoaxialLine(
317
+ length=1.0, d_in=3.124e-3, d_out=8.328e-3,
318
+ dielectric=DjordjevicSarkarDielectric(ep_r=1.33, tand=1e-4, f_low=1.5e4, f_high=1e11, f_ref=1e8),
319
+ conductor=BulkConductor(sigma=5.8e7), formulation=SchelkunoffCoaxialFormulation(),
320
+ )
321
+
322
+
323
+ @pytest.mark.parametrize("n", [5, 50], ids=['tall', 'wide'])
324
+ def test_derivative_of_a_line_with_a_parameter_on_a_closed_bound(n):
325
+ """A parameter on a closed bound gives every parameter a finite derivative, and the
326
+ others match a reference taken through free parameters inside their bounds."""
327
+ line = _coax_on_a_closed_bound()
328
+ freq = prf.Frequency(50, 130, n, 'MHz')
329
+ fn = lambda m: jnp.abs(m.s(freq)[:, 1, 1])
330
+
331
+ (d_line,) = prf.derivative(fn, line)
332
+ actual = prf.values(d_line)
333
+
334
+ assert prf.values(line)['dielectric.sigma'] == 0.0
335
+ assert all(jnp.isfinite(v).all() for v in actual.values()), actual
336
+
337
+ # Fixed parameters stop the gradient through `prf.update`, so the reference frees them.
338
+ names = ['length', 'd_in', 'd_out', 'dielectric.ep_r', 'dielectric.tand']
339
+ free = prf.update(line, names, fixed=False)
340
+ values = prf.values(free, names)
341
+ expected = jax.jacfwd(lambda v: fn(prf.unwrap(prf.update(free, v))))(values)
342
+ for name in names:
343
+ assert jnp.allclose(actual[name], expected[name], rtol=1e-12, atol=0), name
344
+
345
+
248
346
  def test_sweep_parallel():
249
347
  """
250
348
  Verifies that a standard sweep correctly vectorizes across the leading
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