<jupyter_start><jupyter_text>Wilkinson Power Divider In this notebook we create a [Wilkinson power divider](https://www.microwaves101.com/encyclopedias/wilkinson-power-splitters), which splits an input signal into two equals phase output signals. Theoritecal results about this circuit are exposed in reference [1]. Here we will reproduce the ideal circuit illustrated below and discussed in reference [2]. In this example, the circuit is designed to operate at 1 GHz. - [1] <NAME>, Microw. Opt. Technol. Lett. 38, 99 (2003). - [2] Microwaves 101: "Wilkinson Power Splitters"<jupyter_code># standard imports
import numpy as np
import matplotlib.pyplot as plt
import skrf as rf
rf.stylely()
# frequency band
freq = rf.Frequency(start=0, stop=2, npoints=501, unit='GHz')

# characteristic impedance of the ports
Z0_ports = 50

# resistor
R = 100
line_resistor = rf.media.DefinedGammaZ0(frequency=freq, Z0=R)
resistor = line_resistor.resistor(R, name='resistor')

# branches
Z0_branches = np.sqrt(2)*Z0_ports
beta = freq.w/rf.c
line_branches = rf.media.DefinedGammaZ0(frequency=freq, Z0=Z0_branches, gamma=0+beta*1j)

d = line_branches.theta_2_d(90, deg=True)  # @ 90°(lambda/4)@ 1 GHz is ~ 75 mm
branch1 = line_branches.line(d, unit='m', name='branch1')
branch2 = line_branches.line(d, unit='m', name='branch2')

# ports
port1 = rf.Circuit.Port(freq, name='port1', z0=50)
port2 = rf.Circuit.Port(freq, name='port2', z0=50)
port3 = rf.Circuit.Port(freq, name='port3', z0=50)

# Connection setup
#┬Note that the order of appearance of the port in the setup is important 
connections = [
           [(port1, 0), (branch1, 0), (branch2, 0)],
           [(port2, 0), (branch1, 1), (resistor, 0)],
           [(port3, 0), (branch2, 1), (resistor, 1)]
        ]

# Building the circuit
C = rf.Circuit(connections)<jupyter_output><empty_output><jupyter_text>The circuit setup can be checked by visualising the circuit graph (this requires the python package `networkx` to be available).<jupyter_code>C.plot_graph(network_labels=True, edge_labels=True, port_labels=True, port_fontize=2)<jupyter_output><empty_output><jupyter_text>Let's look to the scattering parameters of the circuit:<jupyter_code>fig, (ax1,ax2) = plt.subplots(2, 1, sharex=True)
C.network.plot_s_db(ax=ax1, m=0, n=0,  lw=2)  # S11
C.network.plot_s_db(ax=ax1, m=1, n=1,  lw=2)  # S22
ax1.set_ylim(-90, 0)
C.network.plot_s_db(ax=ax2, m=1, n=0,  lw=2)  # S21
C.network.plot_s_db(ax=ax2, m=2, n=0,  ls='--', lw=2)  # S31
ax2.set_ylim(-4, 0)
fig.suptitle('Ideal Wilkinson Divider @ 1 GHz')<jupyter_output><empty_output><jupyter_text>Currents and VoltagesIs is possible to calculate currents and voltages at the Circuit's internals ports. However, if you try with this specific example, one obtains:<jupyter_code>power = [1,0,0]
phase = [0,0,0]
C.voltages(power, phase)  # or C2.currents(power, phase)<jupyter_output><empty_output><jupyter_text>This situation is "normal", in the sense that the voltages and currents calculation methods does not support the case of more than 2 ports are connected together, which is the case in this example, as we have defined the connection list:```connections = [           [(port1, 0), (branch1, 0), (branch2, 0)],           [(port2, 0), (branch1, 1), (resistor, 0)],           [(port3, 0), (branch2, 1), (resistor, 1)]        ]```However, note that the voltages and currents calculations at external ports works:<jupyter_code>C.voltages_external(power, phase)  # or C.currents_external(power, phase)<jupyter_output><empty_output><jupyter_text>But there is hope! It is possible to calculate the internal voltages and currents of the circuit using intermediate splitting Networks. In our case, one needs three "T" Networks and to make only pair of connections:<jupyter_code>tee1 = line_branches.tee(name='tee1')
tee2 = line_branches.tee(name='tee2')
tee3 = line_branches.tee(name='tee3')

cnx = [
    [(port1, 0), (tee1, 0)],
    [(tee1, 1), (branch1, 0)],
    [(tee1, 2), (branch2, 0)],
    [(branch1, 1), (tee2, 0)],
    [(branch2, 1), (tee3, 0)],
    [(tee2, 2), (resistor, 0)],
    [(tee3, 2), (resistor, 1)],
    [(tee3, 1), (port3, 0)],
    [(tee2, 1), (port2, 0)],   
]
C2 = rf.Circuit(cnx)<jupyter_output><empty_output><jupyter_text>The resulting graph is a bit more stuffed:<jupyter_code>C2.plot_graph(network_labels=True, edge_labels=True, port_labels=True, port_fontize=2)<jupyter_output><empty_output><jupyter_text>But the results are the same:<jupyter_code>C.network == C2.network
fig, (ax1,ax2) = plt.subplots(2, 1, sharex=True)
C2.network.plot_s_db(ax=ax1, m=0, n=0,  lw=2)  # S11
C2.network.plot_s_db(ax=ax1, m=1, n=1,  lw=2)  # S22
ax1.set_ylim(-90, 0)
C2.network.plot_s_db(ax=ax2, m=1, n=0,  lw=2)  # S21
C2.network.plot_s_db(ax=ax2, m=2, n=0,  ls='--', lw=2)  # S31
ax2.set_ylim(-4, 0)
fig.suptitle('Ideal Wilkinson Divider (2nd way) @ 1 GHz')<jupyter_output><empty_output><jupyter_text>And this time one can calculate internal voltages and currents:<jupyter_code>C2.voltages(power, phase)  # or C2.currents(power, phase)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1431112868155762, 'fraction_numerical': 0.045858865388416686, 'mean_word_length': 5.325, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 38, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '282287', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2076, 'n_tokens_neox': 1895, 'n_words': 506, 'path': 'doc/source/examples/circuit/Wilkinson Power Splitter.ipynb', 'repo_name': 'hohe/scikit-rf', 'size': '5067'}