Ejemplo n.º 1
0
def test_lrprop(setup_prop_to_test_lrprop, setup_expected_prop_to_test_lrprop):

    actual_prop = lrprop(0, setup_prop_to_test_lrprop)

    expected_prop = setup_expected_prop_to_test_lrprop

    assert actual_prop['hg'] == pytest.approx(expected_prop['hg'])
    assert actual_prop['kwx'] == pytest.approx(expected_prop['kwx'])
    assert actual_prop['ael'] == pytest.approx(expected_prop['ael'])
    assert actual_prop['aref'] == pytest.approx(expected_prop['aref'])
Ejemplo n.º 2
0
def test_lrprop(setup_prop_to_test_lrprop, setup_expected_prop_to_test_lrprop,
                setup_prop_to_test_lrprop_2, setup_prop_to_test_lrprop_uarea,
                setup_expected_prop_to_test_lrprop_uarea):
    """
    Test the basic Longley-Rice propagation program which returns the reference
    attenuation (aref) as in Eqn 4.1 of "The ITS Irregular Terrain Model,
    version 1.2.2: The Algorithm".

    The test variants are derived from the original test for Longley-Rice between
    for Crystal Palace (South London) to Mursley, England (See Stark, 1967).

    """
    actual_prop = lrprop(0, setup_prop_to_test_lrprop)

    expected_prop = setup_expected_prop_to_test_lrprop

    assert actual_prop['hg'] == pytest.approx(expected_prop['hg'])
    assert actual_prop['kwx'] == pytest.approx(expected_prop['kwx'])
    assert actual_prop['ael'] == pytest.approx(expected_prop['ael'])
    assert actual_prop['aref'] == pytest.approx(expected_prop['aref'])

    actual_prop = lrprop(0, setup_prop_to_test_lrprop_2)

    assert round(actual_prop['aref'], 2) == 35.42
    assert round(actual_prop['etq'], 2) == -0.14
    assert round(actual_prop['dx'], 2) == 162911.96
    assert round(actual_prop['aes'], 2) == 44.14

    actual_prop = lrprop(10000, setup_prop_to_test_lrprop_uarea)

    expected_prop = setup_expected_prop_to_test_lrprop_uarea

    assert actual_prop['hg'] == pytest.approx(expected_prop['hg'])
    assert actual_prop['kwx'] == pytest.approx(expected_prop['kwx'])
    assert actual_prop['ael'] == pytest.approx(expected_prop['ael'])
    assert actual_prop['aref'] == pytest.approx(expected_prop['aref'])
Ejemplo n.º 3
0
def test_itmlogic_area():
    """
    Test the model in area prediction mode.

    """
    prop = {}

    #Antenna height 1 (m), Antenna height 2 (m)
    prop['hg'] = [3.3, 1.3]

    #Frequency (MHz)
    prop['fmhz'] = 20

    #Terrain irregularity parameter dh (m)
    prop['dh'] = 102

    #Surface refractivity (N-units)
    prop['ens0'] = 301

    #Relative permittivity of ground
    prop['eps'] = 15

    #Conductivity (S/m) of ground
    prop['sgm'] = 0.001

    #Climate selection (1=equatorial, 2=continental subtropical,
    #3=maritime subtropical, 4=desert, 5=continental temperate,
    #6=maritime temperate overland, 7=maritime temperate,
    #oversea (5 is the default)
    prop['klimx'] = 5

    #0 = horizontal polarization, 1 = vertical
    prop['ipol'] = 1

    #Mode of variability: Single Message=0, Accidental=1,
    #Mobile=2, Broadcast=3
    prop['mdvarx'] = 3

    #Percent of time requested for computation
    QT = [50]

    #Percent of locations requested for computation
    QL = [50]

    #Confidence levels of computation
    QC = [50, 90, 10]

    #Initial distance (km) for loop over range
    D0 = 10

    #Max distance 1 (km) for loop over range
    D1 = 150

    #Increment 1 (km) for loop over range
    DS1 = 10

    #Max distance 2 (km) for coarser loop over range (starts beyond D1)
    D2 = 500

    #Increment 2 (km) for coarser loop over range
    DS2 = 50

    #Siting criterion for antenna 1, 0=random, 1= careful, 2= very careful
    KST = [2, 2]

    #Refractivity scaling ens=ens0*exp(-zsys/9460.);
    #(Average system elev above sea level)
    zsys = 0

    #Rescale requested percentages into their corresponding normal distribution arguments
    ZT = qerfi([x / 100 for x in QT])[0]
    ZL = qerfi([x / 100 for x in QL])[0]
    ZC = qerfi([x / 100 for x in QC])

    #The number of confidence intervals requested
    NC = len(QC)

    #Don't allow negative distances
    if (D0 <= 0):
        D0 = DS1

    #Set initial distance to 2 km if D0<=0
    if (D0 <= 0):
        D0 = 2

    #If final distance less than initial, only do one distance
    if (D1 <= D0) or (DS1 <= 0):
        ND = 1
        D1 = D0
    #Otherwise compute the number of distance points in the loop
    #and recompute the final distance using this grid
    else:
        DS = DS1
        ND = math.floor((D1 - D0) / DS + 1.75)
        D1 = D0 + (ND - 1) * DS

    #Repeat these corrections for the "coarse" grid in range that follows the fine grid
    if (D2 <= D1) or (DS2 <= 0):
        NDC = 0  #If input parameters are wrong, don't do a coarse grid
    #Otherwise set up appropriate coarse grid
    else:
        NDC = ND
        ND = math.floor((D2 - D1) / DS2 + 0.75)
        D2 = D1 + ND * DS2
        ND = NDC + ND

    #Standard Earth curvature parameter
    prop['gma'] = 157E-9
    #Scale factor for converting Np/km to dB/km
    DB = 8.685890
    #Scale factor to convert km to m
    AKM = 1000

    #Initialize error flag to 0
    prop['kwx'] = 0
    #Initialize the omega_n parameter
    prop['wn'] = prop['fmhz'] / 47.7
    #Initialize the surface refractivity
    prop['ens'] = prop['ens0']

    #Adjust surface refractivity parameter if zsys set by user
    if (zsys != 0):
        prop['ens'] = prop['ens'] * math.exp(-zsys / 9460)

    #Implement refractive effects on Earth curvature
    prop['gme'] = prop['gma'] * (1 - 0.04665 * math.exp(prop['ens'] / 179.3))

    #Initialize lvar parameter (this is used when updating AVAR with new input parameters)
    prop['lvar'] = 0

    #Compute ground effective impedance zq parameter
    zq = complex(prop['eps'], 376.62 * prop['sgm'] / prop['wn'])

    #Compute ground effective impedance z parameter (horizontal pol)
    prop['zgnd'] = math.sqrt(zq.real - 1)

    #Compute ground effective impedance z parameter (vertical pol)
    if (prop['ipol'] != 0):
        prop['zgnd'] = prop['zgnd'] / zq

    #Qlra initializes all the required parameters for area-prediction mode given
    #siting type and other params already set in "prop"
    prop = qlra(KST, prop)

    #Starting distances for loop over range
    D = D0
    #First range step is that of the fine grid
    DT = DS

    FS = []
    DD = []

    output = []

    for JD in range(0, ND):  #0-22

        #Ensure that AVAR routines adjust only for distance (not quantiles which are set)
        prop['lvar'] = max(1, prop['lvar'])

        #Compute baseline propagation loss at current range
        prop = lrprop(D * AKM, prop)

        #Compute and store baseline loss
        FS.append(DB * np.log(2 * prop['wn'] * prop['dist']))

        #Store distance at this increment
        DD.append(D)

        #Loop over confidence intervals requested by user
        for JC in range(0, NC):  #0-3

            #Get confidence interval
            confidence_level = QC[JC]

            #Compute adjustment for specified confidence levels
            avar1, prop = avar(ZT, ZL, ZC[JC], prop)

            #Store results
            output.append({
                'distance_km': D,
                'confidence_level_%': confidence_level,
                'propagation_loss_dB':
                FS[JD] + avar1  #Add in the adjustment for this level
            })

        #Switch to the coarse grid increment in range when we get there
        if JD + 1 == NDC:
            DT = DS2

        #Increment range
        D = D + DT

    for result in output:
        if result['distance_km'] == 10 and result['confidence_level_%'] == 50:
            assert result['propagation_loss_dB'] == 111.69200844812511
        if result['distance_km'] == 10 and result['confidence_level_%'] == 90:
            assert result['propagation_loss_dB'] == 121.59437954264777
        if result['distance_km'] == 10 and result['confidence_level_%'] == 10:
            assert result['propagation_loss_dB'] == 101.78963735360244
        if result['distance_km'] == 500 and result['confidence_level_%'] == 50:
            assert result['propagation_loss_dB'] == 215.27421197676375
        if result['distance_km'] == 500 and result['confidence_level_%'] == 90:
            assert result['propagation_loss_dB'] == 221.71014370503855
        if result['distance_km'] == 500 and result['confidence_level_%'] == 10:
            assert result['propagation_loss_dB'] == 208.83828024848896
Ejemplo n.º 4
0
def qlrpfl(prop):
    """
    Preparatory subroutine for point-to-point mode, as in Section 43 by Hufford
    (see references/itm.pdf).

    Parameters
    ----------
    prop : dict
        Contains all input propagation parameters.

    Returns
    -------
    prop : dict
        Contains all input and output propagation parameters.

    """
    prop['dist'] = prop['pfl'][0] * prop['pfl'][1]

    np = prop['pfl'][0]

    prop['the'], prop['dl'] = (
        hzns(prop['pfl'], prop['dist'], prop['hg'], prop['gme'])
        )

    xl = {}
    for j in range(0,2):
        xl[j] = min(15 * prop['hg'][j], 0.1 * prop['dl'][j])

    xl[1] = prop['dist'] - xl[1]

    prop['dh'] = dlthx(prop['pfl'], xl[0], xl[1])

    if prop['dl'][0] + prop['dl'][1] >= 1.5 * prop['dist']:
        prop['he'] = []
        za, zb = zlsq1(prop['pfl'], xl[0], xl[1])
        prop['he'].append(prop['hg'][0] + max(prop['pfl'][2] - za, 0))
        prop['he'].append(prop['hg'][1] + max(prop['pfl'][np+1] - zb, 0))

        for j in range(1, 2):
            prop['dl'][j] = (
                math.sqrt(2 *prop['he'][j] / prop['gme']) *
                math.exp(-0.07 * math.sqrt(prop['dh'] / max(prop['he'][j], 5)))
                )

        q = prop['dl'][0] + prop['dl'][1]

        if q <= prop['dist']:
            q = (prop['dist'] / q)**2
            for j in range(1, 2):
                prop['he'][j] = prop['he'][j] * q
                prop['dl'][j] = (
                    math.sqrt(2 * prop['he'][j] / prop['gme']) *
                    math.exp(-0.07 * math.sqrt(prop['dh'] / max(prop['he'][j], 5)))
                )

        for j in range(0,2):
            q = math.sqrt(2 * prop['he'][j] / prop['gme'])
            prop['the'][j] = (
                (0.65 * prop['dh'] * (q / prop['dl'][j] - 1) - 2 *
                prop['he'][j]) / q
                )
    else:
        za, q = zlsq1(prop['pfl'], xl[0], 0.9 * prop['dl'][0])

        q, zb = zlsq1(prop['pfl'], prop['dist'] - 0.9 * prop['dl'][1], xl[1])

        prop['he'] = []
        prop['he'].append(prop['hg'][0] + max(prop['pfl'][2] - za, 0))
        prop['he'].append(prop['hg'][1] + max(prop['pfl'][np+2] - zb, 0))

    prop['mdp'] = -1
    prop['lvar'] = max(prop['lvar'], 3)

    if prop['mdvarx'] >= 0:
        prop['mdvar'] = prop['mdvarx']
        prop['lvar'] = max(prop['lvar'], 4)

    if prop['klimx'] > 0:
        prop['klim'] = prop['klimx']
        prop['lvar'] = 5

    prop = lrprop(0, prop)

    return prop
Ejemplo n.º 5
0
def qlrpfl(prop):
    """
    % Initialization routine for point-to-point mode

    """
    prop['dist'] = prop['pfl'][0] * prop['pfl'][1]

    np = prop['pfl'][0]

    prop['the'], prop['dl'] = (
        hzns(prop['pfl'], prop['dist'], prop['hg'], prop['gme'])
        )

    xl = {}
    for j in range(0,2):
        xl[j] = min(15 * prop['hg'][j], 0.1 * prop['dl'][j])

    xl[1]  = prop['dist'] - xl[1]

    prop['dh'] = dlthx(prop['pfl'], xl[0], xl[1])

    if prop['dl'][0] + prop['dl'][1] >= 1.5 * prop['dist']:
        prop['he'] = []
        za, zb = zlsq1(prop['pfl'], xl[0], xl[1])
        prop['he'].append(prop['hg'][0] + max(prop['pfl'][2] - za, 0))
        prop['he'].append(prop['hg'][1] + max(prop['pfl'][np+1] - zb, 0))

        for j in range(1, 2):
            prop['dl'][j] = (
                math.sqrt(2 *prop['he'][j] / prop['gme']) *
                math.exp(-0.07 * math.sqrt(prop['dh'] / max(prop['he'][j], 5)))
                )

        q = prop['dl'][0] + prop['dl'][1]

        if q <= prop['dist']:
            q = (prop['dist'] / q)**2
            for j in range(1, 2):
                prop['he'][j] = prop['he'][j] * q
                prop['dl'][j] = (
                    math.sqrt(2 * prop['he'][j] / prop['gme']) *
                    math.exp(-0.07 * math.sqrt(prop['dh'] / max(prop['he'][j], 5)))
                )

        for j in range(0,2):
            q = math.sqrt(2 * prop['he'][j] / prop['gme'])
            prop['the'][j] = (
                (0.65 * prop['dh'] * (q / prop['dl'][j] - 1) - 2 *
                prop['he'][j]) / q
                )
    else:
        za, q = zlsq1(prop['pfl'], xl[0], 0.9 * prop['dl'][0])

        q, zb = zlsq1(prop['pfl'], prop['dist'] - 0.9 * prop['dl'][1], xl[1])

        prop['he'] = []
        prop['he'].append(prop['hg'][0] + max(prop['pfl'][2] - za, 0))
        prop['he'].append(prop['hg'][1] + max(prop['pfl'][np+2] - zb, 0))

    prop['mdp'] = -1
    prop['lvar'] = max(prop['lvar'], 3)

    if prop['mdvarx'] >= 0:
        prop['mdvar'] = prop['mdvarx']
        prop['lvar'] = max(prop['lvar'], 4)

    if prop['klimx'] > 0:
        prop['klim'] = prop['klimx']
        prop['lvar'] = 5

    prop = lrprop(0, prop)

    return prop