https://www.circuitlab.com/circuit/62vd4a/whitening-non-inverting/ Sean Leavey """ import numpy as np from zero import Circuit from zero.analysis import AcSignalAnalysis if __name__ == "__main__": # 1000 frequencies between 1 Hz to 1 MHz. frequencies = np.logspace(0, 6, 1000) # Create circuit object. circuit = Circuit() # Add components. circuit.add_capacitor(value="10u", node1="gnd", node2="n1") circuit.add_resistor(value="430", node1="n1", node2="nm") circuit.add_resistor(value="43k", node1="nm", node2="nout") circuit.add_capacitor(value="47p", node1="nm", node2="nout") circuit.add_library_opamp(model="LT1124", node1="gnd", node2="nm", node3="nout") # Solve circuit. analysis = AcSignalAnalysis(circuit=circuit) solution = analysis.calculate(frequencies=frequencies, input_type="current",
class CircuitTestCase(TestCase): """Circuit tests""" def setUp(self): self.reset() def reset(self): """Reset circuit""" self.circuit = Circuit() def test_add_component(self): """Test add component to circuit""" r = Resistor(name="r1", value=10e3, node1="n1", node2="n2") c = Capacitor(name="c1", value="10u", node1="n1", node2="n2") l = Inductor(name="l1", value="1u", node1="n1", node2="n2") self.circuit.add_component(r) self.assertCountEqual(self.circuit.components, [r]) self.assertCountEqual(self.circuit.non_gnd_nodes, [Node("n1"), Node("n2")]) self.assertEqual(self.circuit.n_components, 1) self.assertEqual(self.circuit.n_nodes, 2) self.circuit.add_component(c) self.assertCountEqual(self.circuit.components, [r, c]) self.assertCountEqual(self.circuit.non_gnd_nodes, [Node("n1"), Node("n2")]) self.assertEqual(self.circuit.n_components, 2) self.assertEqual(self.circuit.n_nodes, 2) self.circuit.add_component(l) self.assertCountEqual(self.circuit.components, [r, c, l]) self.assertCountEqual(self.circuit.non_gnd_nodes, [Node("n1"), Node("n2")]) self.assertEqual(self.circuit.n_components, 3) self.assertEqual(self.circuit.n_nodes, 2) def test_add_component_without_name(self): """Test add component without name to circuit""" r = Resistor(value=10e3, node1="n1", node2="n2") c = Capacitor(value="10u", node1="n1", node2="n2") l = Inductor(value="1u", node1="n1", node2="n2") op = OpAmp(model="OP00", node1="n1", node2="n2", node3="n3") self.assertEqual(r.name, None) self.circuit.add_component(r) self.assertEqual(r.name, "r1") self.assertEqual(c.name, None) self.circuit.add_component(c) self.assertEqual(c.name, "c1") self.assertEqual(l.name, None) self.circuit.add_component(l) self.assertEqual(l.name, "l1") self.assertEqual(op.name, None) self.circuit.add_component(op) self.assertEqual(op.name, "op1") def test_remove_component(self): """Test remove component from circuit""" r = Resistor(name="r1", value=10e3, node1="n1", node2="n2") c = Capacitor(name="c1", value="10u", node1="n1", node2="n2") self.circuit.add_component(r) self.circuit.add_component(c) self.assertCountEqual(self.circuit.components, [r, c]) self.assertCountEqual(self.circuit.non_gnd_nodes, [Node("n1"), Node("n2")]) self.assertEqual(self.circuit.n_components, 2) self.assertEqual(self.circuit.n_nodes, 2) self.circuit.remove_component(r) self.assertEqual(self.circuit.components, [c]) self.assertCountEqual(self.circuit.non_gnd_nodes, [Node("n1"), Node("n2")]) self.assertEqual(self.circuit.n_components, 1) self.assertEqual(self.circuit.n_nodes, 2) self.circuit.remove_component(c) self.assertEqual(self.circuit.components, []) self.assertEqual(self.circuit.non_gnd_nodes, []) self.assertEqual(self.circuit.n_components, 0) self.assertEqual(self.circuit.n_nodes, 0) def test_remove_component_by_name(self): """Test remove component from circuit by name""" r = Resistor(name="r1", value=10e3, node1="n1", node2="n2") c = Capacitor(name="c1", value="10u", node1="n1", node2="n2") self.circuit.add_component(r) self.circuit.add_component(c) self.circuit.remove_component("r1") self.circuit.remove_component("c1") self.assertEqual(self.circuit.components, []) self.assertCountEqual(self.circuit.non_gnd_nodes, []) self.assertEqual(self.circuit.n_components, 0) self.assertEqual(self.circuit.n_nodes, 0) def test_cannot_add_component_with_invalid_name(self): """Test components with invalid names cannot be added to circuit""" # name "all" is invalid r = Resistor(name="all", value=1e3, node1="n1", node2="n2") self.assertRaisesRegex(ValueError, r"component name 'all' is reserved", self.circuit.add_component, r) # name "sum" is invalid c = Capacitor(name="sum", value=1e3, node1="n1", node2="n2") self.assertRaisesRegex(ValueError, r"component name 'sum' is reserved", self.circuit.add_component, c) def test_cannot_add_duplicate_component(self): """Test component already present in circuit cannot be added again""" # duplicate component r1 = Resistor(name="r1", value=1e3, node1="n1", node2="n2") r2 = Resistor(name="r1", value=2e5, node1="n3", node2="n4") self.circuit.add_component(r1) self.assertRaisesRegex(ValueError, r"element with name 'r1' already in circuit", self.circuit.add_component, r2) self.reset() # different component with same name r1 = Resistor(name="r1", value=1e3, node1="n1", node2="n2") op1 = OpAmp(name="r1", model="OP00", node1="n3", node2="n4", node3="n5") self.circuit.add_component(r1) self.assertRaisesRegex(ValueError, r"element with name 'r1' already in circuit", self.circuit.add_component, op1) def test_cannot_add_component_with_same_name_as_node(self): """Test component with same name as existing node cannot be added""" # first component r1 = Resistor(name="r1", value=1e3, node1="n1", node2="n2") # second component, with same name as one of first component's nodes r2 = Resistor(name="n1", value=2e5, node1="n3", node2="r4") self.circuit.add_component(r1) self.assertRaisesRegex(ValueError, r"element with name 'n1' already in circuit", self.circuit.add_component, r2) self.reset() # different component with same name r1 = Resistor(name="r1", value=1e3, node1="n1", node2="n2") op1 = OpAmp(name="n1", model="OP00", node1="n2", node2="n4", node3="n5") self.circuit.add_component(r1) self.assertRaisesRegex(ValueError, r"element with name 'n1' already in circuit", self.circuit.add_component, op1) def test_cannot_add_node_with_same_name_as_component(self): """Test node with same name as existing component cannot be added""" # first component r1 = Resistor(name="r1", value=1e3, node1="n1", node2="n2") # second component, with node with same name as first component r2 = Resistor(name="r2", value=2e5, node1="n3", node2="r1") self.circuit.add_component(r1) self.assertRaisesRegex( ValueError, r"node 'r1' is the same as existing circuit component", self.circuit.add_component, r2) self.reset() # different component with same name r1 = Resistor(name="r1", value=1e3, node1="n1", node2="n2") op1 = OpAmp(name="op1", model="OP00", node1="r1", node2="n4", node3="n5") self.circuit.add_component(r1) self.assertRaisesRegex( ValueError, r"node 'r1' is the same as existing circuit component", self.circuit.add_component, op1)
class MutualInductanceTestCase(TestCase): """Mutual inductance tests""" def setUp(self): # Triple transformer, winding ratio 1:3:3. self.circuit = Circuit() self.circuit.add_resistor(value="1k", node1="n1", node2="n2") self.circuit.add_inductor(value="1m", node1="n2", node2="gnd", name="l1") self.circuit.add_inductor(value="9m", node1="n3", node2="gnd", name="l2") self.circuit.add_inductor(value="9m", node1="n4", node2="gnd", name="l3") self.circuit.add_resistor(value="1k", node1="n3", node2="gnd") self.circuit.add_resistor(value="1k", node1="n4", node2="gnd") def test_matrix_impedance_elements(self): """Test impedance matrix elements are the same for both inductors""" # Add mutual inductance between all three coils. self.circuit.set_inductor_coupling("l1", "l2") self.circuit.set_inductor_coupling("l2", "l3") self.circuit.set_inductor_coupling("l1", "l3") # Get circuit matrix, with prescaling switched off so we can directly compare values. analysis = MockMutualInductanceAcSignalAnalysis(circuit=self.circuit) # Add circuit input. analysis.set_input(input_type="voltage", node="n1") # Get inductors. l1 = analysis.get_component_from_current_circuit("l1") l2 = analysis.get_component_from_current_circuit("l2") l3 = analysis.get_component_from_current_circuit("l3") # Get inductor current indices. l1_index = analysis.component_matrix_index(l1) l2_index = analysis.component_matrix_index(l2) l3_index = analysis.component_matrix_index(l3) # Check at various frequency decades. for frequency in np.logspace(-3, 6, 10): with self.subTest( msg="Test impedance matrix elements for coupled inductors", frequency=frequency): # Get matrix for this frequency. matrix = analysis.circuit_matrix(frequency) # There should be a term proportional to the current of each paired inductor on the # opposite inductor's equation. self.assertEqual(matrix[l1_index, l2_index], l1.impedance_from(l2, frequency)) self.assertEqual(matrix[l1_index, l2_index], matrix[l2_index, l1_index]) self.assertEqual(matrix[l1_index, l3_index], l1.impedance_from(l3, frequency)) self.assertEqual(matrix[l1_index, l3_index], matrix[l3_index, l1_index]) self.assertEqual(matrix[l2_index, l3_index], l2.impedance_from(l3, frequency)) self.assertEqual(matrix[l2_index, l3_index], matrix[l3_index, l2_index])