1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
"""Test the module that performs harmonic balance
(qmix.harmonic_balance.harmonic_balance).
This module is relatively easy to test. Assuming that harmonic balance was
performed correctly, the circuit should be 'balanced', meaning that the
voltage drop across the junction should match the Thevenin equivalent circuit.
See Section 4.3 in Garrett (2018) to understand what this means.
"""
import numpy as np
import pytest
import qmix
from qmix.harmonic_balance import check_hb_error, harmonic_balance, _qtcurrent_all_freq
from qmix.qtcurrent import qtcurrent
from qmix.respfn import RespFnPolynomial
# Response function and voltage sweep to use for all tests
RESP = RespFnPolynomial(50)
NPTS = 101
VBIAS = np.linspace(0, 2, NPTS)
def test_relative_error_in_hb_solution():
""" The harmonic_balance module can be tested by running the harmonic
balance process and then checking that the optimized voltage from the
harmonic_balance function does actually lead to a balanced circuit."""
# Input parameters ------------------------------------------------------
NF = 2 # number of tones
NP = 2 # number of harmonics
N = NF * NP # total number of signals
NB = (15, 9) # number of Bessel functions to use
# Generate embedding circuit
circuit = qmix.circuit.EmbeddingCircuit(NF, NP)
# Photon voltage
circuit.freq[1] = 0.30
circuit.freq[2] = 0.32
# Embedding voltage
circuit.vt[1, 1] = circuit.freq[1] * 1.5
circuit.vt[1, 2] = circuit.freq[1] * 0.1
circuit.vt[2, 1] = circuit.freq[2] * 0.1
circuit.vt[2, 2] = circuit.freq[2] * 0.01
# Embedding impedance
circuit.zt[1, 1] = 0.3 - 1j*0.3
circuit.zt[1, 2] = 0.3 - 1j*0.3
circuit.zt[2, 1] = 0.3 - 1j*0.3
circuit.zt[2, 2] = 0.3 - 1j*0.3
# Run test ---------------------------------------------------------------
# Perform harmonic balance to calculate voltage across junction (vj)
vj, _, solution_found = harmonic_balance(circuit, RESP, NB,
stop_rerror=0.001, mode='x')
assert solution_found, "No solution found. Max iterations was reached!"
# This function will raise an exception if the error function exceeds
# the 'stop_error' value. Here we will set this value to maximum
# error of 0.001. This is a relative error: error / vj. This is checked
# for every tone, harmonic and bias voltage.
check_hb_error(vj, circuit, RESP, NB, stop_rerror= 0.001)
def test_error_handling():
"""The harmonic_balance function will tell you if it did not reach the
`stop_rerror` value. Make sure that this works by only running 1
iteration (i.e., don't give harmonic_balance enough time to find the
solution) and then make sure that the error flag is working."""
# Input parameters ------------------------------------------------------
NB = 15
NF = 1
NP = 1
N = NF * NP
# Embedding circuit
circuit = qmix.circuit.EmbeddingCircuit(NF, NP)
circuit.freq[1] = 0.30
circuit.vt[1, 1] = circuit.freq[1] * 1.5
circuit.zt[1, 1] = 0.3 - 1j*0.3
# Run test ---------------------------------------------------------------
# Perform harmonic balance (with impossible settings)
vj, _, got_solution = harmonic_balance(circuit, RESP, NB,
max_it=1,
stop_rerror=0.0001,
mode='x')
# Make sure that no solution was found
assert not got_solution, "A solution was found with only one iteration."
def test_when_zthev_is_zero():
""" Harmonic balance is not needed when all of the embedding impedances
are set to zero. In this test, set all thevenin impedances to zero, and
make sure that the harmonic balance function just returns the embedding
voltage."""
NB = 15
NF = 2
NP = 2
# Embedding circuit
circuit = qmix.circuit.EmbeddingCircuit(NF, NP)
circuit.freq[1] = 0.30
circuit.freq[2] = 0.32
circuit.vt[1, 1] = circuit.freq[1] * 1.5
# Calculate junction voltage (should be equal to Thevenin voltage)
vj = harmonic_balance(circuit, RESP, NB)
for i in range(NPTS):
assert (vj[:,:,i] == circuit.vt).all()
|