Skip to content

Commit

Permalink
matching tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jhillairet committed Mar 25, 2024
1 parent f838391 commit 16fbfc9
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 49 deletions.
62 changes: 28 additions & 34 deletions west_ic_antenna/antenna.py
Expand Up @@ -271,10 +271,8 @@ def capa(

capa = pre ** cap ** post

# should we renormalize of not z0 to the Network's z0 they will be connected to?
# ANSYS Designer seems not doing it and leaves to 50 ohm
# renormalizing the z0 will lead to decrease the matched capacitances by ~10pF @55MHz
# In reality, values are closer to 50 pF at 55 MHz
# Renormalize z0s' to match left and right Network connected to
# If not renormalized, the match point would differ by ~1.4 pF at 55 MHz
capa.renormalize(z_new=np.array([z0_bridge, z0_antenna]).T)

return capa
Expand Down Expand Up @@ -322,7 +320,6 @@ def _antenna_circuit(self, Cs: NumberLike) -> 'Circuit':
# while for capa and voltage it is:
# C1 C3
# C2 C4
# service stub 3rd ports are left open
connections = [
[(self.antenna, 0), (capa_C1, 1)],
[(self.antenna, 1), (capa_C3, 1)],
Expand All @@ -334,14 +331,9 @@ def _antenna_circuit(self, Cs: NumberLike) -> 'Circuit':
[(capa_C4, 0), (self.bridge_right, 2)],
[(self.bridge_left, 0), (self.windows_impedance_transformer_left, 1)],
[(self.bridge_right, 0), (self.windows_impedance_transformer_right, 1)],
# [(self.windows_impedance_transformer_left, 0), (self.port_left, 0)], # no stub
# [(self.windows_impedance_transformer_right, 0), (self.port_right, 0)], # no stub
[(self.windows_impedance_transformer_left, 0), (self.service_stub_left, 1)],
[(self.windows_impedance_transformer_right, 0), (self.service_stub_right, 1)],
[(self.service_stub_left, 0), (self.port_left, 0)],
[
(self.windows_impedance_transformer_right, 0),
(self.service_stub_right, 1),
],
[(self.service_stub_right, 0), (self.port_right, 0)],
[(self.service_stub_left, 2), (self.short_left, 0)],
[(self.service_stub_right, 2), (self.short_right, 0)],
Expand Down Expand Up @@ -1683,45 +1675,47 @@ def match_both_sides_iterative(
f_match: float = 55e6,
power: NumberLike = [1, 1],
phase: NumberLike = [0, np.pi],
Cs: Union[None, list] = None,
solution_number: int = 1,
K: float = 0.7,
z_T_target: float = Z_T_OPT,
C0: Union[None, list] = None,
K: float = 0.7,
) -> NumberLike:
"""
Match both sides using the automatic matching alg. (iterative).
Parameters
----------
f_match : float, optional
DESCRIPTION. The default is 55e6.
power : NumberLike, optional
DESCRIPTION. The default is [1, 1].
phase : NumberLike, optional
DESCRIPTION. The default is [0, np.pi].
solution_number : int, optional
DESCRIPTION. The default is 1.
power : list or array
Input power at external ports in Watts [W]
phase : list or array
Input phase at external ports in radian [rad]
Cs : list or array
antenna 4 capacitances [C1, C2, C3, C4] in [pF].
Default is None (use internal Cs)
z_T_target : complex, optional
Desired target (Set Point) for the input impedance at T-junction.
The default is 2.89-0.17j.
solution_number : int
Desired solution. 1 for C_top > C_bot and 2 for the opposite.
K : float, optional
DESCRIPTION. The default is 0.7.
z_T_target : float, optional
DESCRIPTION. The default is Z_T_OPT.
C0 : Union[None, list], optional
DESCRIPTION. The default is None.
: TYPE
DESCRIPTION.
Gain. Default value: 0.7.
Smaller value leads to higher number of iterations.
Returns
-------
NumberLike
DESCRIPTION.
Cs_match : list or array
antenna 4 capacitances [C1, C2, C3, C4] in [pF].
"""
C0 = Cs or self.Cs

if C0 is not None:
if solution_number == 1:
C0 = [60, 40, 60, 40] # note that the start point matches solution 1 (Ctop>Cbot)
elif solution_number == 2:
C0 = [40, 60, 40, 60]
# if C0 is not None:
# if solution_number == 1:
# C0 = [60, 40, 60, 40] # note that the start point matches solution 1 (Ctop>Cbot)
# elif solution_number == 2:
# C0 = [40, 60, 40, 60]

# creates an antenna circuit for a single frequency only to speed-up calculations
freq_match = rf.Frequency(f_match, f_match, npoints=1, unit="Hz")
Expand Down
84 changes: 69 additions & 15 deletions west_ic_antenna/test/test_antenna.py
Expand Up @@ -106,9 +106,9 @@ def test_capa_model_bridge_antenna_ports(antenna_default_arg):
# ANSYS Equivalent circuit with complex bridge and antenna ports' Z0
ANSYS_model = "ANSYS_benchmarks/WEST_capacitor_equivalent_circuit_bridge_antenna_ports.s2p"
cap_ANSYS = rf.Network(os.path.join(TEST_DIR, ANSYS_model))

assert cap == cap_ANSYS


def test_capa_model_bridge_antenna_ports_renorm50ohm(antenna_default_arg):
"""
Expand All @@ -129,21 +129,18 @@ def test_capa_model_bridge_antenna_ports_renorm50ohm(antenna_default_arg):
def test_capa_model_connection(antenna_default_arg):
"""
Benchmark dummy circuit model of a antenna-capa-bridge vs ANSYS Circuit.
In ANSYS, a single capacitor electrical circuit is connected to one bridge
output and to an antenne front face input (using HFSS model).
Bridge input is connected to input port and all other ports are shorted.
Benchmark is performed when the Touchtone file is exported without and with
50 Ohm renormalization.
"""
# NB: importing S-matrix in ANSYS Circuit as a N-port component
# requires the user to know in advance the port char impedance
# ant = antenna_default_arg
ant = antenna_default_arg
cap = ant.capa(C=50)

# Creating the dummy circuit using scikit-rf
cap.name = 'capa'
port = rf.Circuit.Port(frequency=ant.frequency, name='port1', z0=ant.bridge.z0[:,0].real)
Expand All @@ -157,20 +154,77 @@ def test_capa_model_connection(antenna_default_arg):
]
cir = rf.Circuit(cnx)
ntw = cir.network

# ANSYS Model Export without renormalization
ANSYS_model = "ANSYS_benchmarks/WEST_capacitor_test_connection.s1p"
ANSYS_connection_test = rf.Network(os.path.join(TEST_DIR, ANSYS_model))
assert ntw == ANSYS_connection_test

assert ntw == ANSYS_connection_test

# ANSYS Model Export Renomalized to 50 Ohm
ANSYS_model_50 = "ANSYS_benchmarks/WEST_capacitor_test_connection_renorm50ohm.s1p"
ANSYS_connection_test_50 = rf.Network(os.path.join(TEST_DIR, ANSYS_model_50))
ntw.renormalize(50)

assert ntw == ANSYS_connection_test_50


assert ntw == ANSYS_connection_test_50

# Various return value tests
def test_antenna_circuit(antenna_default_arg):
"""Test the internal circuit."""
ant = antenna_default_arg
assert isinstance(ant.circuit(), rf.Circuit)
assert isinstance(ant.circuit(Cs=[50,50,50,50]), rf.Circuit)

# TODO benchmark against ANSYS for a specific case of capa set

def test_Cs(antenna_default_arg):
ant = antenna_default_arg
assert isinstance(ant.Cs, list)


# Matching Tests (longer...)
def test_match_one_side_left(antenna_default_arg):
# Test the return values of left side matching
Cs = antenna_default_arg.match_one_side(
f_match=55e6,
solution_number=1,
side="left",
z_match=29.89 + 0j
)
# reference values 25/03/2024
np.testing.assert_allclose(Cs, [51.44282751806046, 49.325275021316564, 150, 150], rtol=1e-5)

def test_match_one_side_right(antenna_default_arg):
# Test the return values of right side matching
Cs = antenna_default_arg.match_one_side(
f_match=55e6,
solution_number=1,
side="right",
z_match=29.89 + 0j
)
# reference values 25/03/2024
np.testing.assert_allclose(Cs, [150, 150, 51.20960703555699, 49.489644871023714], rtol=1e-5)

def test_match_both_sides_separately(antenna_default_arg):
# Test the return values of both sides matching (separately)
Cs = antenna_default_arg.match_both_sides_separately(
f_match=55e6,
solution_number=1,
z_match=[29.89 + 0j, 29.87 + 0j],
)
# reference values 25/03/2024
np.testing.assert_allclose(Cs, [51.44282792582701, 49.32527088864287, 51.20987339854108, 49.48946981138618], rtol=1e-1)

def test_match_both_sides(antenna_default_arg):
# Test the return values of both sides matching
Cs = antenna_default_arg.match_both_sides(
f_match=55e6,
solution_number=1,
z_match=[29.89 + 0j, 29.87 + 0j],
)
# reference values 25/03/2024
np.testing.assert_allclose(Cs, [52.09695694, 50.08075395, 51.62129529, 50.25710599], rtol=1e-1)


if __name__ == "__main__":
pytest.main([__file__])

0 comments on commit 16fbfc9

Please sign in to comment.