Source code for NetworkSim.architecture.setup.model

__all__ = ["Model"]
__author__ = ["Hongyi Yang"]

import numpy as np

from NetworkSim.architecture.base.network import Network
from NetworkSim.architecture.base.node import Node
from NetworkSim.architecture.base.ring import Ring
from NetworkSim.architecture.signal.control import ControlSignal
from NetworkSim.architecture.signal.data import DataSignal


[docs]class Model: """ Constructor for model. The model includes network, node and signal definitions. Parameters ---------- control_signal : ControlSignal, optional The control signal definition. Default is ``ControlSignal()``. data_signal : DataSignal, optional The data signal definition. Default is ``DataSignal()``. network : Network, optional The network definition. Default is ``Network()``. abstract : bool Abstract representation of control and data packets. Default is ``True``. bidirectional : bool, optional The type of network architecture, either bidirectional or unidirectional. \ Default is ``False``, which is unidirectional. Attributes ---------- nodes : list A list containing the nodes in the model data_rings : list A list containing the data rings in the model control_ring : Ring The control ring in the network. The `ring_id` of this ring is ``-1``. constants : dict A dictionary containing: - `speed` : speed of light in the fibre, in m/s - `maximum_bit_rate` : maximum bit rate of each channel, in Gbit/s - `average_bit_rate` : average bit rate of each channel, in Gbit/s - `data_guard_interval` : guard interval of data packets, in ns - `control_guard_interval` : guard interval of control packets, in ns - `tuning_time` : tuning time of the receiver, in ns data_packet_duration : float The total duration of the data packet, including the guard interval. circulation_time : float The time for one complete circulation around the ring. max_data_packet_num_on_ring : int The maximum number of data packets a ring can contain. """ def __init__( self, control_signal=None, data_signal=None, network=None, abstract=True, bidirectional=False ): if control_signal is None: control_signal = ControlSignal(abstract=abstract) self.control_signal = control_signal if data_signal is None: data_signal = DataSignal(abstract=abstract) self.data_signal = data_signal if network is None: network = Network() self.network = network self.abstract = abstract self.bidirectional = bidirectional self.nodes = self.generate_nodes() self.data_rings = self.generate_data_rings() if self.bidirectional: self.reversed_data_rings = self.generate_reversed_data_rings() self.control_ring = self.generate_control_ring() self.constants = { 'speed': 2e8, # speed of light in fibre, in m/s 'maximum_bit_rate': 100, # system burst rate (maximum bit rate), in Gbit/s 'average_bit_rate': 30, # system average bit rate, in Gbit/s 'data_guard_interval': 20, # guard interval of data packets in ns 'control_guard_interval': 0.14, # guard interval of control packets in ns 'tuning_time': 20 # tuning time of the receiver in ns } self.data_packet_duration = self.get_data_packet_total_duration() self.circulation_time = self.get_circulation_time() self.max_data_packet_num_on_ring = self.get_max_data_packet_num_on_ring()
[docs] def get_circulation_time(self): """ Calculate time for a signal to circulate around the ring once. Returns ------- circulation_time : float The time taken for one circulation, in ns. """ return self.network.length / self.constants.get('speed') * 1e9
[docs] def get_data_packet_duration(self): """ Calculation of the duration of a data packet excluding guard interval Returns ------- packet_duration : float Duration of the data packet, in ns """ # Calculate total time taken by one packet excluding guard interval _bit_duration = 1 / self.constants.get('maximum_bit_rate') packet_duration = _bit_duration * self.data_signal.size * 8 return packet_duration
[docs] def get_data_packet_total_duration(self): """ Calculation of the duration of a data packet including guard interval Returns ------- total_duration : float Duration of the data packet with guard interval, in ns """ # Calculate total time taken by one packet including guard interval _bit_duration = 1 / self.constants.get('maximum_bit_rate') _packet_duration = _bit_duration * self.data_signal.size * 8 total_duration = _packet_duration + self.constants.get('data_guard_interval') return total_duration
[docs] def get_max_data_packet_num_on_ring(self): """ Obtain the maximum number of data packets that can be fitted in the ring. Returns ------- max_packet_num : int The maximum number of packets allowed. """ # Calculate total time taken by one packet including guard interval _total_duration = self.get_data_packet_total_duration() # Calculate total length of one transmission _transmission_length = _total_duration * self.constants.get('speed') * 1e-9 # Calculate maximum number of packets that could be fitted on the ring max_packet_num = self.network.length // np.round(_transmission_length, decimals=2) # Type cast at the end to avoid TypeError: 'numpy.float64' object cannot be interpreted as an integer return max_packet_num
[docs] def get_max_control_packet_num_on_ring(self): """ Obtain the maximum number of control packets that can be fitted in the ring. Returns ------- max_packet_num : int The maximum number of packets allowed. """ return self.get_max_control_packet_num_between_nodes() * self.network.num_nodes
[docs] def get_max_control_packet_num_between_nodes(self): """ Obtain the maximum number of control packets that can be fitted between two nodes. Returns ------- max_packet_num_between_node : int The maximum number of packets allowed between two nodes. """ # Calculate total time taken by one packet including guard interval _bit_duration = 1 / self.constants.get('maximum_bit_rate') _packet_duration = _bit_duration * (2 * self.control_signal.id_length + self.control_signal.control_length) _total_duration = _packet_duration + self.constants.get('control_guard_interval') # Calculate total length of one transmission _transmission_length = _total_duration * self.constants.get('speed') * 1e-9 # Calculate the distance between two node _node_interval = self.network.get_interval() if _node_interval < _transmission_length: raise ValueError("This configuration would result in control packet larger than the node interval.") # Calculate maximum number of packets that could be fitted between two node max_packet_num_between_node = _node_interval // np.round(_transmission_length, decimals=2) # Type cast at the end to avoid TypeError: 'numpy.float64' object cannot be interpreted as an integer return max_packet_num_between_node
[docs] def generate_nodes(self): """ Generate a list of nodes based on the network configuration. Returns ------- nodes : list List of `Node` objects. """ return [Node( control_signal=self.control_signal, data_signal=self.data_signal, network=self.network, node_id=i ) for i in range(self.network.num_nodes)]
[docs] def generate_data_rings(self): """ Generate a list of data rings based on the network configuration. Returns ------- data_rings : list List of `Ring` objects. """ return [Ring(model=self, ring_id=i) for i in range(self.network.num_nodes)]
[docs] def generate_reversed_data_rings(self): """ Generate a list of data rings in the reversed transmission direction based on the network configuration. Returns ------- data_rings : list List of `Ring` objects with `reversed=True`. """ return [Ring(model=self, ring_id=i, reversed=True) for i in range(self.network.num_nodes)]
[docs] def generate_control_ring(self): """ Generate a control ring based on the network configuration. Returns ------- control_ring : Ring List of `Ring` objects. """ return Ring(model=self, ring_id=-1)