import numpy as np from scipy.constants import speed_of_light class AntennaPattern: def __init__(self, A_m=30, theta_3=65): self._A_m = A_m self._theta_3 = theta_3 def __call__(self, theta): pattern = 12 * (theta / self._theta_3) ** 2 return -np.minimum(pattern, self._A_m) class PathlossModel: @staticmethod def getLOSpathloss(d3d, d2d, dbp, fc, h_b, h_t): PL1 = 28 + 22 * np.log10(d3d) + 20 * np.log10(fc) PL2 = ( 28 + 40 * np.log10(d3d) + 20 * np.log10(fc) - 9 * np.log10(dbp ** 2 + (h_b - h_t) ** 2) ) PL = np.zeros((d3d.shape)) PL = PL2 # Default pathloss PL[(np.greater_equal(d2d, 10) & np.less_equal(d2d, dbp))] = PL1[ (np.greater_equal(d2d, 10) & np.less_equal(d2d, dbp)) ] # Overwrite if distance is greater than 10 meters or smaller than dbp return PL @staticmethod def getNLOSpathloss( street_width, average_building_height, bs_height, ue_height, d3d, f_ghz ): pathlossdB = ( 161.04 - 7.1 * np.log10(street_width) + 7.5 * np.log10(average_building_height) - (24.37 - 3.7 * (average_building_height / bs_height) ** 2) * np.log10(bs_height) + (43.42 - 3.1 * np.log10(bs_height)) * (np.log10(d3d) - 3) + 20 * np.log10(f_ghz) - (3.2 * (np.log10(17.625)) ** 2 - 4.97) - 0.6 * (ue_height - 1.5) ) return pathlossdB @staticmethod def pathlos_36873(h_b, h_ue, f_ghz, street_w, building_h, d2d): h_e = h_b - h_ue d3d = np.sqrt(d2d ** 2 + h_e ** 2) dbp = 4 * h_b * h_ue * f_ghz * 10e8 / speed_of_light nlos_pathloss = PathlossModel.getNLOSpathloss( street_w, building_h, h_b, h_ue, d3d, f_ghz ) los_pathloss = PathlossModel.getLOSpathloss(d3d, d2d, dbp, f_ghz, h_b, h_ue) return np.maximum(nlos_pathloss, los_pathloss) @staticmethod def pathlos_36873(h_b, h_ue, f_ghz, street_w, building_h, d2d, use_los=False): h_e = h_b - h_ue d3d = np.sqrt(d2d ** 2 + h_e ** 2) dbp = 4 * h_b * h_ue * f_ghz * 10e8 / speed_of_light nlos_pathloss = PathlossModel.getNLOSpathloss( street_w, building_h, h_b, h_ue, d3d, f_ghz ) los_pathloss = PathlossModel.getLOSpathloss(d3d, d2d, dbp, f_ghz, h_b, h_ue) if use_los: return los_pathloss return np.maximum(nlos_pathloss, los_pathloss) def __call__( self, distance_2D, h_bs, use_los=False, street_width=10, building_height=25, frequency=None, ): return self.pathlos_36873( h_bs, 2, frequency, street_width, building_height, distance_2D, use_los=use_los, )