Source code for hermespy.simulation.coupling.coupling

# -*- coding: utf-8 -*-
"""
===============
Mutual Coupling
===============

.. toctree::
   :glob:

   simulation.coupling.perfect
   simulation.coupling.impedance
"""

from __future__ import annotations
from typing import Optional, TYPE_CHECKING
from abc import ABC, abstractmethod

from hermespy.core import Signal, FloatingError

if TYPE_CHECKING:
    from ..simulated_device import SimulatedDevice  # pragma: no cover

__author__ = "Jan Adler"
__copyright__ = "Copyright 2023, Barkhausen Institut gGmbH"
__credits__ = ["Jan Adler"]
__license__ = "AGPLv3"
__version__ = "1.1.0"
__maintainer__ = "Jan Adler"
__email__ = "jan.adler@barkhauseninstitut.org"
__status__ = "Prototype"


[docs] class Coupling(ABC): """Base class for mutual coupling model implementations.""" __device: Optional[SimulatedDevice] def __init__(self, device: Optional[SimulatedDevice] = None) -> None: """ Args: device (SimulatedDevice, optional): Device the model is configured to. """ self.device = device @property def device(self) -> Optional[SimulatedDevice]: """Device the model is configured to. Returns: Handle to the device. `None`, if the model is considered floating. """ return self.__device @device.setter def device(self, value: Optional[SimulatedDevice]) -> None: self.__device = value
[docs] def transmit(self, signal: Signal) -> Signal: """Apply the mutual coupling model during signal transmission. Args: signal (Signal): The signal to be transmitted. Returns: The signal resulting from coupling modeling. Raises: FloatingError: If the device is not specified. ValueError: If the number of signal streams does not match the number of transmitting antennas. """ if self.device is None: raise FloatingError("Error trying to simulate coupling of a floating model") if self.device.num_transmit_antennas != signal.num_streams: raise ValueError( "Number of signal streams ({signal.num_streams}) does not match the number of transmitting antennas ({self.device.num_transmit_antennas})" ) return self._transmit(signal)
@abstractmethod def _transmit(self, signal: Signal) -> Signal: """Apply the mutual coupling model during signal transmission. Args: signal (Signal): The signal to be transmitted. Returns: The signal resulting from coupling modeling. """ ... # pragma: no cover
[docs] def receive(self, signal: Signal) -> Signal: """Apply the mutual coupling model during signal reception. Args: signal (Signal): The signal to be received. Returns: The signal resulting from coupling modeling. Raises: FloatingError: If the device is not specified. ValueError: If the number of signal streams does not match the number of transmitting antennas. """ if self.device is None: raise FloatingError("Error trying to simulate coupling of a floating model") if self.device.num_receive_antennas != signal.num_streams: raise ValueError( f"Number of signal streams ({signal.num_streams}) does not match the number of transmitting antennas ({self.device.num_transmit_antennas})" ) return self._receive(signal)
@abstractmethod def _receive(self, signal: Signal) -> Signal: """Apply the mutual coupling model during signal reception. Args: signal (Signal): The signal to be received. Returns: The signal resulting from coupling modeling. """ ... # pragma: no cover