1
0
Files
LCRConnector/legacy/common.py

252 lines
7.6 KiB
Python
Raw Normal View History

2026-06-02 21:08:48 +08:00
import enum
2026-06-15 13:47:31 +08:00
2026-06-02 21:08:48 +08:00
class LcrConnException(Exception):
"""The exception thrown by LCR Connector"""
2026-06-15 13:47:31 +08:00
2026-06-02 21:08:48 +08:00
pass
class DeviceKind(enum.IntEnum):
"""The kind of device"""
2026-06-15 13:47:31 +08:00
2026-06-02 21:08:48 +08:00
RESISTOR = enum.auto()
"""Resistor device"""
CAPACITOR = enum.auto()
"""Capacitor device"""
INDUCTOR = enum.auto()
"""Inductor device"""
class JointKind(enum.IntEnum):
"""The joint type between 2 devices"""
2026-06-15 13:47:31 +08:00
2026-06-02 21:08:48 +08:00
SERIES = enum.auto()
"""Series connection"""
PARALLEL = enum.auto()
"""Parallel connection"""
2026-06-15 13:47:31 +08:00
def flip(self) -> "JointKind":
2026-06-02 21:08:48 +08:00
"""
Flip the joint kind
2026-06-15 13:47:31 +08:00
2026-06-02 21:08:48 +08:00
Flip the joint kind from series to parallel or vice versa
:return: The flipped joint kind
"""
match self:
case JointKind.SERIES:
return JointKind.PARALLEL
case JointKind.PARALLEL:
return JointKind.SERIES
2026-06-15 13:47:31 +08:00
class SubCircuit:
2026-06-02 21:08:48 +08:00
"""The part of circuit composed of two devices and the joint kind"""
2026-06-15 13:47:31 +08:00
__device_value: float
2026-06-02 21:08:48 +08:00
"""The value of the device"""
2026-06-15 13:47:31 +08:00
__joint_kind: JointKind
2026-06-02 21:08:48 +08:00
"""The joint kind between this device and the next device"""
2026-06-15 13:47:31 +08:00
def __init__(self, device_value: float, joint_kind: JointKind):
self.__device_value = device_value
self.__joint_kind = joint_kind
def compute(self, value: float, device_kind: DeviceKind) -> float:
2026-06-02 21:08:48 +08:00
"""
Compute the joint value
:param value: The value computed from previous devices
:param device_kind: The kind of the device
:return: The joint value computed
"""
2026-06-15 13:47:31 +08:00
if self.__device_value <= 0 or value <= 0:
2026-06-02 21:08:48 +08:00
raise LcrConnException("Device value must be greater than 0")
2026-06-15 13:47:31 +08:00
2026-06-02 21:08:48 +08:00
# We perform series connect for: series resistor, series inductor and parallel capacitor.
# We perform parallel connect for: parallel resistor, parallel inductor and series capacitor.
2026-06-15 13:47:31 +08:00
joint_kind = self.__joint_kind
2026-06-02 21:08:48 +08:00
if device_kind == DeviceKind.CAPACITOR:
joint_kind = joint_kind.flip()
match joint_kind:
case JointKind.SERIES:
2026-06-15 13:47:31 +08:00
return self.__device_value + value
2026-06-02 21:08:48 +08:00
case JointKind.PARALLEL:
2026-06-15 13:47:31 +08:00
return (self.__device_value * value) / (self.__device_value + value)
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
def get_device_value(self) -> float:
"""
Get the device value
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
:return: The device value
"""
return self.__device_value
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
def get_joint_kind(self) -> JointKind:
2026-06-02 21:08:48 +08:00
"""
2026-06-15 13:47:31 +08:00
Get the joint kind
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
:return: The joint kind
2026-06-02 21:08:48 +08:00
"""
2026-06-15 13:47:31 +08:00
return self.__joint_kind
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
class CircuitDeviceCount(enum.IntEnum):
"""The number of devices in the circuit"""
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
ONE = enum.auto()
"""One device"""
TWO = enum.auto()
"""Two devices"""
THREE = enum.auto()
"""Three devices"""
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
def to_device_count(self) -> int:
match self:
case CircuitDeviceCount.ONE:
return 1
case CircuitDeviceCount.TWO:
return 2
case CircuitDeviceCount.THREE:
return 3
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
class Circuit:
"""The circuit composed of multiple joints"""
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
__first_device_value: float
"""The value of the first device"""
__second_device_subckt: SubCircuit | None
"""The second device and its joint property"""
__third_device_subckt: SubCircuit | None
"""The third device and its joint property"""
def __init__(
self,
first_device_value: float,
second_device_subckt: SubCircuit | None,
third_device_subckt: SubCircuit | None,
):
"""
Initialize the circuit
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
:param first_device_value: The value of the first device
:param second_device_subckt: The second device and its joint property
:param third_device_subckt: The third device and its joint property
"""
if second_device_subckt is None and third_device_subckt is not None:
raise LcrConnException("Third device cannot exist without second device")
self.__first_device_value = first_device_value
self.__second_device_subckt = second_device_subckt
self.__third_device_subckt = third_device_subckt
@staticmethod
def from_one_device(device1_value: float) -> "Circuit":
return Circuit(device1_value, None, None)
@staticmethod
def from_two_devices(
device1_value: float, device2_value: float, device2_joint: JointKind
) -> "Circuit":
return Circuit(device1_value, SubCircuit(device2_value, device2_joint), None)
@staticmethod
def from_three_devices(
device1_value: float,
device2_value: float,
device2_joint: JointKind,
device3_value: float,
device3_joint: JointKind,
) -> "Circuit":
return Circuit(
device1_value,
SubCircuit(device2_value, device2_joint),
SubCircuit(device3_value, device3_joint),
)
def get_device_count(self) -> CircuitDeviceCount:
if self.__third_device_subckt is not None:
return CircuitDeviceCount.THREE
elif self.__second_device_subckt is not None:
return CircuitDeviceCount.TWO
else:
return CircuitDeviceCount.ONE
def get_first_device_value(self) -> float:
"""
Get the value of the first device
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
:return: The value of the first device
"""
return self.__first_device_value
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
def get_second_device_joint(self) -> JointKind:
"""
Get the joint kind of the second device
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
:return: The joint kind of the second device
:raises LcrConnException: If there is no second device
"""
if self.__second_device_subckt is not None:
return self.__second_device_subckt.get_joint_kind()
else:
raise LcrConnException("No second device")
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
def get_second_device_value(self) -> float:
"""
Get the value of the second device
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
:return: The value of the second device
:raises LcrConnException: If there is no second device
"""
if self.__second_device_subckt is not None:
return self.__second_device_subckt.get_device_value()
else:
raise LcrConnException("No second device")
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
def get_third_device_joint(self) -> JointKind:
"""
Get the joint kind of the third device
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
:return: The joint kind of the third device
:raises LcrConnException: If there is no third device
"""
if self.__third_device_subckt is not None:
return self.__third_device_subckt.get_joint_kind()
else:
raise LcrConnException("No third device")
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
def get_third_device_value(self) -> float:
"""
Get the value of the third device
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
:return: The value of the third device
:raises LcrConnException: If there is no third device
"""
if self.__third_device_subckt is not None:
return self.__third_device_subckt.get_device_value()
else:
raise LcrConnException("No third device")
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
def compute(self, device_kind: DeviceKind) -> float:
"""
Compute the circuit value
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
:param device_kind: The kind of the device
:return: The circuit value
"""
if self.__first_device_value <= 0:
raise LcrConnException("Device value must be greater than 0")
2026-06-02 21:08:48 +08:00
2026-06-15 13:47:31 +08:00
value = self.__first_device_value
if self.__second_device_subckt is None:
return value
value = self.__second_device_subckt.compute(value, device_kind)
if self.__third_device_subckt is None:
return value
value = self.__third_device_subckt.compute(value, device_kind)
return value