Source code for pytwinnet.physics.ris_beam

from __future__ import annotations
from dataclasses import dataclass
from typing import Optional, Tuple
import math
from ..core.node import WirelessNode
from .environment import Environment
from .propagation import PropagationModel

[docs] @dataclass class SmartRISPanel: """ Toy RIS with a steerable mainlobe. Approximates array gain: mainlobe_gain_db ~= 20*log10(N) sidelobe_gain_db ~= mainlobe - 13 dB (typical) """ position: Tuple[float, float, float] element_count: int = 64 mainlobe_gain_db: Optional[float] = None sidelobe_gain_db: Optional[float] = None def __post_init__(self): if self.mainlobe_gain_db is None: self.mainlobe_gain_db = 20.0 * math.log10(max(self.element_count, 1)) if self.sidelobe_gain_db is None: self.sidelobe_gain_db = self.mainlobe_gain_db - 13.0
[docs] class RISBeamModel(PropagationModel): """ Wraps a base PropagationModel. For a configured target UE (by id), the RIS contributes mainlobe gain on the two-hop path; others see sidelobe gain. Effective path loss = min( direct, (tx->RIS + RIS->rx - gain + extra_loss_db) ). """ def __init__(self, base: PropagationModel, ris: SmartRISPanel, extra_loss_db: float = 3.0) -> None: self.base = base self.ris = ris self.extra_loss_db = extra_loss_db self._beam_target_id: Optional[str] = None
[docs] def set_beam(self, rx_node_id: Optional[str]) -> None: """Point mainlobe toward rx_node_id (or None for no specific target).""" self._beam_target_id = rx_node_id
[docs] def calculate_path_loss(self, tx: WirelessNode, rx: WirelessNode, environment: Environment) -> float: direct = self.base.calculate_path_loss(tx, rx, environment) tmp1 = WirelessNode("__tmp_tx2ris__", position=self.ris.position) tmp2 = WirelessNode("__tmp_ris2rx__", position=self.ris.position) pl1 = self.base.calculate_path_loss(tx, tmp1, environment) pl2 = self.base.calculate_path_loss(tmp2, rx, environment) gain = self.ris.mainlobe_gain_db if (self._beam_target_id == rx.node_id) else self.ris.sidelobe_gain_db via = pl1 + pl2 - gain + self.extra_loss_db return min(direct, via)