Model Comparison to Qucs-S¶
This notebook compares the S-parameter models from qpdk (using sax) against reference results from Qucs-S simulations. Each test suite validates a different component model.
The comparisons include:
- Polar plots showing S-parameters in the complex plane
- Magnitude and phase plots versus frequency
- Visual validation of model accuracy against reference data
import inspect
import numpy as np
from IPython.display import Markdown, display
from qpdk import PDK
from _qucs_comparison import BaseCompareToQucs
PDK.activate()
Discover Test Suites¶
Dynamically discover all test suite classes that compare qpdk models to Qucs-S results.
We find all classes that:
1. Are subclasses of BaseCompareToQucs
2. Are not the base class itself
3. Are concrete classes (not abstract)
def discover_test_suites() -> list[type[BaseCompareToQucs]]:
"""Discover all test suite classes for Qucs-S comparison.
Returns:
List of test suite classes that inherit from :class:`~BaseCompareToQucs`.
"""
import _qucs_comparison # noqa: PLC0415
test_suites = []
# Get all members of the module
for _name, obj in inspect.getmembers(_qucs_comparison):
# Check if it's a class
if not inspect.isclass(obj):
continue
# Check if it's a subclass of BaseCompareToQucs but not the base class itself
if not issubclass(obj, BaseCompareToQucs) or obj is BaseCompareToQucs:
continue
# Check if it's a concrete class (not abstract)
if inspect.isabstract(obj):
continue
test_suites.append(obj)
return test_suites
# Discover all available test suites
test_suites = discover_test_suites()
print(f"Found {len(test_suites)} test suite(s):")
for suite in test_suites:
print(f"\t· {suite.__name__}")
Model Comparison¶
Compare the S-parameter models against Qucs-S reference data.
# Find and plot all test suites
for suite in test_suites:
test_instance = suite()
display(Markdown(f"### {test_instance.component_name}"))
display(Markdown(f"**Test Suite:** `{suite.__name__}`"))
param_strs = [
f"{p.name} = {p.value / p.unit:.2f} × 10^{int(np.log10(p.unit))}"
for p in sorted(test_instance.parameters, key=lambda x: x.name)
]
param_text = "**Parameters:**\n" + "\n".join(f"- {p}" for p in param_strs)
display(Markdown(param_text))
display(Markdown(f"**CSV:** `{test_instance.csv_filename}`"))
test_instance.plot_comparison()
Summary¶
The plots above show comparisons between qpdk models (dashed lines) and Qucs-S reference simulations (solid lines) for various passive components:
- Left plot: Polar representation showing S-parameters in the complex plane
- Right plot: Magnitude (in dB) and phase (in radians) versus frequency
Good agreement between the models validates the accuracy of the qpdk implementations for use in circuit simulations and design optimization.