Exemplo n.º 1
0
def test_update_vertices():
    # TEST_UPDATE_VERTICES() - test method update_vertices(), which for this base class of LocalAsset does
    # practically nothing and must be redefined by child classes that represent flesible assets.
    print('Running LocalAsset.test_update_vertices()')

    #   Create a test Market.
    test_market = Market()

    #   Create and store a TimeInterval.
    dt = datetime.now(
    )  # datetime that may be used for most datetime arguments
    time_interval = TimeInterval(dt, timedelta(hours=1), test_market, dt, dt)
    test_market.timeIntervals = [time_interval]

    #   Create a test LocalAsset.
    test_model = LocalAsset()

    #   Create and store a scheduled power IntervalValue in the active time interval.
    test_model.scheduledPowers = [
        IntervalValue(test_model, time_interval, test_market,
                      MeasurementType.ScheduledPower, 50)
    ]

    #   Create maximum and minimum powers.
    test_model.maximumPower = 200
    test_model.minimumPower = 0

    # TEST 1
    print('- Test 1: Basic operation')

    try:
        test_model.update_vertices(test_market)
        print('  - the method ran without errors')
    except RuntimeWarning as cause:
        print('  - the method encountered errors', cause)

    assert len(test_model.activeVertices
               ) == 1, 'There were an unexpected number of active vertices'

    # Success.
    print('Method test_update_vertices ran to completion.\n')
Exemplo n.º 2
0
def test_prod_cost_from_vertices():
    from code.local_asset_model import LocalAsset
    from code.market import Market

    # TEST_PROD_COST_FROM_VERTICES - tests function prod_cost_from_vertices()
    print('Running test_prod_cost_from_vertices()')
    pf = 'pass'

    # Create a test object
    test_object = LocalAsset

    # Create a test market
    test_market = Market()

    # Create several active vertices av
    av = [Vertex(0.02, 5, 0),
          Vertex(0.02, 7, 100),
          Vertex(0.025, 9.25, 200)]

    # Create a time interval
    dt = datetime.now()
    at = dt
    #   NOTE: Function Hours() corrects behavior of Matlab function hours().
    dur = timedelta(hours=1)
    mkt = test_market
    mct = dt
    st = dt
    ti = TimeInterval(at, dur, mkt, mct, st)

    # Create and store the activeVertices, which are IntervalValues
    test_object.activeVertices = [IntervalValue(test_object, ti, test_market, MeasurementType.ActiveVertex, av[0]),
                                  IntervalValue(test_object, ti, test_market, MeasurementType.ActiveVertex, av[1]),
                                  IntervalValue(test_object, ti, test_market, MeasurementType.ActiveVertex, av[2])]

    # CASE: Various signed powers when there is more than one vertex
    test_powers = [-50, 0, 50, 150, 250]
    pc = []
    for p in test_powers:
        pc.append(prod_cost_from_vertices(test_object, ti, p))

    # pc(1) = 0: value is always 0 for power < 0
    # pc(2) = 5.0: assign cost from first vertex
    # pc(3) = 6.0: interpolate between vertices
    # pc(4) = 8.125: interpolate between vertices
    # pc(5) = 9.25: use last vertex cost if power > last vertex power

    # if ~all(pc == [0, 5.0, 6.0, 8.125, 9.25])
    expected = [0, 5.0, 6.0, 8.125, 9.25]
    if not all([pc[i] == expected[i] for i in range(len(pc))]):
        pf = 'fail'
        raise Exception('- the production cost was incorrectly calculated')
    else:
        print('- the production cost was correctly calculated')

    # CASE: One vertex (inelastic case, a constant)
    test_object.activeVertices = [
        IntervalValue(test_object, ti, test_market, MeasurementType.ActiveVertex, av[0])]

    # pc[i] = prod_cost_from_vertices(test_object, ti, test_powers[i])
    pc = []
    for p in test_powers:
        pc.append(prod_cost_from_vertices(test_object, ti, p))

    expected = [0.0, 5.0, 5.0, 5.0, 5.0]
    # if ~all(pc == [0.0, 5.0, 5.0, 5.0, 5.0])
    if not all([pc[i] == expected[i] for i in range(len(pc))]):
        pf = 'fail'
        raise Exception('- made an incorrect assignment when there is one vertex')
    else:
        print('- made a correct assignment when there is one vertex')

    # CASE: No active vertices (error case):
    test_object.activeVertices = []

    # print('off', 'all')
    try:
        pc = prod_cost_from_vertices(test_object, ti, test_powers[4])
        pf = 'fail'
        # print('on', 'all')
        raise Exception('- the function should have warned and continued when there were no active vertices')
    except:
        print('- the function returned gracefully when there were no active vertices')
        # print('on', 'all')

    #   Success
    print('- the test function ran to completion')
    print('Result: #s\n\n', pf)
Exemplo n.º 3
0
def test_prod_cost_from_formula():
    from code.local_asset_model import LocalAsset
    from code.market import Market

    print('Running test_prod_cost_from_formula()')
    pf = 'pass'

    #   Create a test object
    test_object = LocalAsset()

    #   Create a test market
    test_market = Market()

    #   Create and store the object's cost parameters
    test_object.costParameters = [4, 3, 2]

    #   Create and store three hourly TimeIntervals
    #   Modified to use the TimeInterval constructor.
    dt = datetime.now()
    at = dt
    dur = timedelta(hours=1)
    mkt = test_market
    mct = dt

    st = dt
    ti = [TimeInterval(at, dur, mkt, mct, st)]

    st = st + dur
    ti.append(TimeInterval(at, dur, mkt, mct, st))

    st = st + dur
    ti.append(TimeInterval(at, dur, mkt, mct, st))

    test_market.timeIntervals = ti

    # Create and store three corresponding scheduled powers
    iv = [IntervalValue(test_object, ti[0], test_market, MeasurementType.ScheduledPower, 100),
          IntervalValue(test_object, ti[1], test_market, MeasurementType.ScheduledPower, 200),
          IntervalValue(test_object, ti[2], test_market, MeasurementType.ScheduledPower, 300)]
    test_object.scheduledPowers = iv

    #   Run the test
    pc = [0] * 3
    for i in range(3):
        pc[i] = prod_cost_from_formula(test_object, ti[i])

    # pc(1) = 4 + 3 * 100 + 0.5 * 2 * 100^2 = 10304
    # pc(2) = 4 + 3 * 200 + 0.5 * 2 * 200^2 = 40604
    # pc(3) = 4 + 3 * 300 + 0.5 * 2 * 300^2 = 90904

    # if all(pc ~=[10304, 40604, 90904])
    expected = [10304, 40604, 90904]
    if all([pc[i] != expected[i] for i in range(len(pc))]):
        pf = 'fail'
        raise Exception('- production cost was incorrectly calculated')
    else:
        print('- production cost was correctly calculated')

    #   Success
    print('- the test ran to completion')
    print('Result: #s\n\n', pf)
Exemplo n.º 4
0
def test_production():
    from code.local_asset_model import LocalAsset
    from code.market import Market

    print('Running test_production()')
    pf = 'pass'

    #   Create a test object
    test_object = LocalAsset()

    #   Create a test market
    test_market = Market()

    #   Create several active vertices av
    av = [Vertex(0.0200, 5.00, 0.0),
          Vertex(0.0200, 7.00, 100.0),
          Vertex(0.0250, 9.25, 200.0)]

    # Create a time interval ti
    dt = datetime.now()
    at = dt
    #   NOTE: Function Hours() corrects the behavior of Matlab hours().
    dur = timedelta(hours=1)
    mkt = test_market
    mct = dt
    st = dt
    ti = TimeInterval(at, dur, mkt, mct, st)

    # Assign activeVertices, which are IntervalValues
    test_object.activeVertices = [
        IntervalValue(test_object, ti, test_market, MeasurementType.ActiveVertex, av[0]),
        IntervalValue(test_object, ti, test_market, MeasurementType.ActiveVertex, av[1]),
        IntervalValue(test_object, ti, test_market, MeasurementType.ActiveVertex, av[2])]

    # CASE: Various marginal prices when there is more than one vertex
    test_prices = [-0.010, 0.000, 0.020, 0.0225, 0.030]

    p = [0] * len(test_prices)  # zeros(1, length(test_prices))
    for i in range(len(test_prices)):  # for i = 1:length(test_prices)
        p[i] = production(test_object, test_prices[i], ti)

    print('- the function ran without errors')

    # p(1) = 0: below first vertex
    # p(2) = 0: below first vertex
    # p(3) = 100: at first vertex, which has identical marginal price as second
    # p(4) = 150: interpolate between vertices
    # p(5) = 200: exceeds last vertex

    # if ~all(abs(p - [0, 0, 100, 150, 200]) < 0.001):
    expected = [0, 0, 100, 150, 200]
    if not all([p[i] - expected[i] < 0.001 for i in range(len(p))]):
        pf = 'fail'
        raise Exception('- the production cost was incorrectly calculated')
    else:
        print('- the production cost was correctly calculated')

    # CASE: One vertex (inelastic case, a constant)
    test_object.activeVertices = [IntervalValue(test_object, ti, test_market, MeasurementType.ActiveVertex, av[2])]

    for i in range(5):
        p[i] = production(test_object, test_prices[i], ti)

    # if ~all(p == 200 * ones(1, length(p))):
    if not all(x == 200 for x in p):
        pf = 'fail'
        raise Exception('the vertex power should be assigned when there is one vertex')
    else:
        print('- the correct power was assigned when there is one vertex')

    # CASE: No active vertices (error case):
    test_object.activeVertices = []

    try:
        p = production(test_object, test_prices[4], ti)
        pf = 'fail'
        raise Exception('- an error should have occurred with no active vertices')
    except:
        print('- with no vertices, system returned with warnings, as expected')

    #   Success
    print('- the test function ran to completion')
    print('Result: #s\n\n', pf)
Exemplo n.º 5
0
# Add uncontrollable model
inelastive_load = LocalAsset()
inelastive_load.name = 'InelasticLoad'
inelastive_load.maximumPower = -50000  # Remember that a load is a negative power [kW]
inelastive_load.minimumPower = -200000  # Assume twice the average PNNL load [kW]
inelastive_load_model = OpenLoopRichlandLoadPredictor(weather_service)
inelastive_load_model.name = 'InelasticLoadModel'
inelastive_load_model.defaultPower = -100420  # [kW]
inelastive_load_model.defaultVertices = [Vertex(float("inf"), 0.0, -100420.0)]
inelastive_load_model.object = inelastive_load
inelastive_load.model = inelastive_load_model
city_market.localAssets.extend([inelastive_load])

# Add Market
market = Market()
market.name = 'dayAhead'
market.commitment = False
market.converged = False
market.defaultPrice = 0.0428  # [$/kWh]
market.dualityGapThreshold = duality_gap_threshold  # [0.02 = 2#]
market.initialMarketState = MarketState.Inactive
market.marketOrder = 1  # This is first and only market
market.intervalsToClear = 1  # Only one interval at a time
market.futureHorizon = timedelta(
    hours=24)  # Projects 24 hourly future intervals
market.intervalDuration = timedelta(hours=1)  # [h] Intervals are 1 h long
market.marketClearingInterval = timedelta(hours=1)  # [h]
market.marketClearingTime = Timer.get_cur_time().replace(
    hour=0, minute=0, second=0, microsecond=0)  # Aligns with top of hour
market.nextMarketClearingTime = market.marketClearingTime + timedelta(hours=1)
Exemplo n.º 6
0
def test_schedule():
    print('Running AbstractModel.test_schedule()')

    test_mtn = TransactiveNode()

    #   Create a test market test_mkt
    test_mkt = Market()

    #   Create a sample time interval ti
    dt = datetime.now()
    at = dt
    # NOTE: Function Hours() corrects behavior of Matlab hours().
    dur = timedelta(hours=1)
    mkt = test_mkt
    mct = dt
    # NOTE: Function Hours() corrects behavior of Matlab hours().
    st = datetime.combine(date.today(), time()) + timedelta(hours=20)
    ti = TimeInterval(at, dur, mkt, mct, st)

    print(ti)

    #   Save the time interval
    test_mkt.timeIntervals = [ti]

    #   Assign a marginal price in the time interval
    test_mkt.check_marginal_prices(test_mtn)

    #   Create a Neighbor test object and give it a default maximum power value
    # test_obj = Neighbor()

    #   Create a corresponding Neighbor.
    test_mdl = Neighbor()
    test_mdl.maximumPower = 100

    #   Make sure that the model and object cross-reference one another
    # test_obj.model = test_mdl
    # test_mdl.object = test_obj

    #   Run a test with a Neighbor object
    print('- running test with a Neighbor:')

    try:
        test_mdl.schedule(test_mkt)
        print('  - the method encountered no errors')
    except RuntimeWarning:
        print('  - ERRORS ENCOUNTERED')

    assert len(test_mdl.scheduledPowers
               ) == 1, '  - the method did not store a scheduled power'
    assert len(test_mdl.reserveMargins
               ) == 1, '  - the method did not store a reserve margin'
    assert len(test_mdl.activeVertices
               ) == 1, '  - the method did not store an active vertex'

    # Run a test again with a LocalAsset.
    # test_obj = LocalAsset()

    test_mdl = LocalAsset()
    # test_obj.model = test_mdl
    # test_mdl.object = test_obj
    test_mdl.maximumPower = 100
    test_mdl.scheduleCalculated = True

    print('- running test with a LocalAsset:')

    try:
        test_mdl.schedule(test_mkt)
        print('  - the method encountered no errors')
    except RuntimeWarning:
        print('  - ERRORS ENCOUNTERED')

    assert len(test_mdl.scheduledPowers
               ) == 1, '  - the method did not store a scheduled power'
    assert len(test_mdl.reserveMargins
               ) == 1, '  - the method did not store a reserve margin'
    assert len(test_mdl.activeVertices
               ) == 1, '  - the method did not store an active vertex'

    # Success
    print('test_schedule() ran to completion.\n')
Exemplo n.º 7
0
def test_update_costs():
    print('Running AbstractModel.test_update_costs()')

    test_mtn = TransactiveNode()

    #   Create a test market test_mkt
    test_mkt = Market()

    #   Create a sample time interval ti
    dt = datetime.now()
    at = dt
    #   NOTE: Function Hours() corrects behavior of Matlab hours().
    dur = timedelta(hours=1)
    mkt = test_mkt
    mct = dt
    st = datetime.combine(date.today(), time()) + timedelta(hours=20)
    ti = TimeInterval(at, dur, mkt, mct, st)

    #   Save the time interval
    test_mkt.timeIntervals = [ti]

    #   Assign a marginal price in the time interval
    test_mkt.check_marginal_prices(test_mtn)

    #   Create a Neighbor test object and give it a default maximum power value
    # test_obj = Neighbor()
    #     test_obj.maximumPower = 100

    #   Create a corresponding Neighbor.
    test_mdl = Neighbor()

    #   Make sure that the model and object cross-reference one another
    # test_obj.model = test_mdl
    # test_mdl.object = test_obj

    test_mdl.scheduledPowers = [
        IntervalValue(test_mdl, ti, test_mkt, MeasurementType.ScheduledPower,
                      100)
    ]
    test_mdl.activeVertices = [
        IntervalValue(test_mdl, ti, test_mkt, MeasurementType.ActiveVertex,
                      Vertex(0.05, 0, 100))
    ]

    #   Run a test with a Neighbor object
    print('- running test with a Neighbor:')
    try:
        test_mdl.update_costs(test_mkt)
        print('  - the method encountered no errors')
    except RuntimeWarning:
        print('  - ERRORS ENCOUNTERED')

    assert len(test_mdl.productionCosts
               ) == 1, '  - the method did not store a production cost'
    assert len(
        test_mdl.dualCosts) == 1, '  - the method did not store a dual cost'
    assert test_mdl.totalProductionCost == sum([x.value for x in test_mdl.productionCosts]), \
            '  - the method did not store a total production cost'
    assert test_mdl.totalDualCost == sum([x.value for x in test_mdl.dualCosts]), \
            '  - the method did not store a total dual cost'

    # Run a test again with a LocalAsset.
    # test_obj = LocalAsset()
    test_mdl = LocalAsset()
    # test_obj.model = test_mdl
    # test_mdl.object = test_obj
    test_mdl.maximumPower = 100

    test_mdl.scheduledPowers = [
        IntervalValue(test_mdl, ti, test_mkt, MeasurementType.ScheduledPower,
                      100)
    ]
    test_mdl.activeVertices = [
        IntervalValue(test_mdl, ti, test_mkt, MeasurementType.ActiveVertex,
                      Vertex(0.05, 0, 100))
    ]

    print('- running test with a LocalAsset:')

    try:
        test_mdl.update_costs(test_mkt)
        print('  - the method encountered no errors')
    except RuntimeWarning:
        print('  - ERRORS ENCOUNTERED')

    assert len(test_mdl.productionCosts
               ) == 1, '  - the method did not store a production cost'
    assert len(
        test_mdl.dualCosts) == 1, '  - the method did not store a dual cost'
    assert test_mdl.totalProductionCost == sum([x.value for x in test_mdl.productionCosts]), \
            '  - the method did not store a total production cost'
    assert test_mdl.totalDualCost == sum([x.value for x in test_mdl.dualCosts]), \
            '  - the method did not store a total dual cost'

    # Success
    print('test_update_costs() ran to completion.\n')
Exemplo n.º 8
0
def test_calculate_reserve_margin():
    # TEST_LAM_CALCULATE_RESERVE_MARGIN() - a LocalAsset ("LAM") class
    # method NOTE: Reserve margins are introduced but not fully integrated into
    # code in early template versions.
    # CASES:
    # 1. uses hard maximum if no active vertices exist
    # 2. vertices exist
    # 2.1 uses maximum vertex power if it is less than hard power constraint
    # 2.2 uses hard constraint if it is less than maximum vertex power
    # 2.3 upper flex power is greater than scheduled power assigns correct
    # positive reserve margin
    # 2.4 upperflex power less than scheduled power assigns zero value to
    # reserve margin.
    print('Running LocalAsset.test_calculate_reserve_margin()')

    # Establish test market
    test_mkt = Market()

    # Establish test market with an active time interval
    # Note: modified 1/29/18 due to new TimeInterval constructor
    dt = datetime.now()
    at = dt
    # NOTE: def Hours() corrects behavior of Matlab hours().
    dur = timedelta(hours=1)
    mkt = test_mkt
    mct = dt
    # st = datetime(date)
    st = datetime.combine(date.today(), time())

    ti = TimeInterval(at, dur, mkt, mct, st)

    # Store time interval
    test_mkt.timeIntervals = [ti]

    # Establish test object that is a LocalAsset.
    test_model = LocalAsset()
    test_model.scheduledPowers = [
        IntervalValue(test_model, ti, test_mkt, MeasurementType.ScheduledPower,
                      0.0)
    ]
    test_model.maximumPower = 100

    # Run the first test case.
    print("  Case 1:")
    try:
        test_model.calculate_reserve_margin(test_mkt)
        print('  The test ran without errors')
    except RuntimeWarning as cause:
        print('  The test encountered errors', cause)

    print(test_model.reserveMargins[0].value)

    assert len(test_model.reserveMargins
               ) == 1, 'An unexpected number of results were stored'

    assert test_model.reserveMargins[0].value == test_model.maximumPower, \
                                                                'The method did not use the available maximum power'

    # create some vertices and store them
    iv = [
        IntervalValue(test_model, ti, test_mkt, MeasurementType.Vertex,
                      Vertex(0, 0, -10)),
        IntervalValue(test_model, ti, test_mkt, MeasurementType.Vertex,
                      Vertex(0, 0, 10))
    ]
    test_model.activeVertices = iv

    print("  Case 2: test with maximum power greater than maximum vertex")
    test_model.maximumPower = 100
    try:
        test_model.calculate_reserve_margin(test_mkt)
        print('  The test ran without errors')
    except RuntimeWarning as cause:
        print('  The test encountered errors', cause)

    assert test_model.reserveMargins[
        0].value == 10, 'The method should have used vertex for comparison'

    print("  Case 3: test with maximum power less than maximum vertex")
    test_model.maximumPower = 5
    try:
        test_model.calculate_reserve_margin(test_mkt)
        print('  The test ran without errors')
    except RuntimeWarning as cause:
        print('  The test encountered errors', cause)

    assert test_model.reserveMargins[
        0].value == 5, 'The method should have used maximum power for comparison'

    print("  Case 4: test with scheduled power greater than maximum vertex")
    test_model.scheduledPowers[0].value = 20
    test_model.maximumPower = 500
    try:
        test_model.calculate_reserve_margin(test_mkt)
        print('  The test ran without errors')
    except RuntimeWarning as cause:
        print('  The test encountered errors', cause)
    print(test_model.reserveMargins[0].value)
    assert test_model.reserveMargins[
        0].value == 0, 'The method should have assigned zero for a neg. result'

    # Success.
    print('Method test_calculate_reserve_margin() ran to completion.\n')
Exemplo n.º 9
0
def test_get_extended_prices():
    print("Running test_get_extended_prices()")
    """
    This base method uses the following prioritization to populate the price horizon needed by this local asset:
        1. Actual marginal prices offered by the market.
        2. Actual marginal prices in prior sequential markets that are similar to the market.
        3. Actual marginal prices in prior markets that are being corrected by the market.
        4. Modeled prices using the market's price model
        5. The market's default price value.
        6. Nothing
    """
    # ******************************************************************************************************************
    print("  Case 1. Actual marginal prices offered by the market."
          )  # *****************************************
    # The test setup is such that the local asset should use Methods 1 to find an existing marginal price in its market.
    now = datetime.now()
    # test_asset = LocalAsset()
    test_asset_model = LocalAsset()
    # test_asset = test_asset_model
    # test_asset_model.object = test_asset
    test_asset_model.schedulingHorizon = timedelta(hours=0.5)
    test_market = Market()
    test_interval = TimeInterval(now, timedelta(hours=1), test_market, now,
                                 now)
    price = 3.14159
    test_price = IntervalValue(None, test_interval, test_market, 'test', price)
    test_market.timeIntervals = [test_interval]
    test_market.marginalPrices = [test_price]
    test_mtn = TransactiveNode()
    test_mtn.markets = [test_market]
    test_mtn.localAssets = [test_asset_model]

    assert len(test_market.marginalPrices
               ) == 1, 'The market was supposed to have a marginal price'
    assert datetime.now() + test_asset_model.schedulingHorizon \
           < test_market.timeIntervals[0].startTime + test_market.intervalDuration, \
        'For this test, the existing marginal price intervals should not extend beyond the scheduling horizon.'

    try:
        price_set = test_asset_model.get_extended_prices(test_market)
        print("  The case ran without errors.")
    except RuntimeWarning as cause:
        print("  The case encountered errors.", cause)
        price_set = []

    assert len(price_set) == 1, 'An unexpected number of prices was found'
    assert price_set[0].value == price, 'The price was no correct'

    # ******************************************************************************************************************
    print(
        "  Case 2. Actual marginal prices in prior sequential market that is similar to the market."
    )  # ****
    # The test setup is such that the local asset should sequentially use Methods 1, & 2 to find two marginal prices.
    now = datetime.now()

    test_asset_model = LocalAsset()

    test_asset_model.schedulingHorizon = timedelta(
        hours=1.5)  # Should cause asset to use prior market

    test_market = Market()

    test_interval0 = TimeInterval(now, timedelta(hours=1), test_market, now,
                                  now)
    price0 = 3.14159
    test_price0 = IntervalValue(None, test_interval0, test_market, 'test',
                                price0)
    test_market.timeIntervals = [test_interval0]
    test_market.marginalPrices = [test_price0]
    test_market.marketSeriesName = "Test Market"
    test_market.marketClearingTime = now

    prior_market = Market()
    test_interval1 = TimeInterval(now, timedelta(hours=1), prior_market, now,
                                  now)
    test_interval2 = TimeInterval(now, timedelta(hours=1), prior_market, now,
                                  now + timedelta(hours=1))
    price1 = 10
    test_price1 = IntervalValue(None, test_interval1, prior_market, 'test',
                                price1)
    test_price2 = IntervalValue(None, test_interval2, prior_market, 'test',
                                price1)
    prior_market.timeIntervals = [test_interval1, test_interval2]
    prior_market.marginalPrices = [test_price1, test_price2]
    prior_market.marketSeriesName = test_market.marketSeriesName
    prior_market.marketClearingTime = test_market.marketClearingTime - timedelta(
        hours=1)

    test_market.priorMarketInSeries = prior_market  # Important pointer to preceding market interval in market series.

    test_mtn = TransactiveNode()
    test_mtn.markets = [prior_market, test_market]
    test_mtn.localAssets = [test_asset_model]

    assert len(test_market.marginalPrices
               ) == 1, 'The market was supposed to have a marginal price'
    assert len(prior_market.marginalPrices
               ) == 2, "The prior market should have had two prices"
    assert test_market.marketSeriesName == prior_market.marketSeriesName, 'The market names must be the same'
    assert test_market.priorMarketInSeries == prior_market, "The market must point to its predecessor in market series"

    try:
        price_set = test_asset_model.get_extended_prices(test_market)
        print("  The case ran without errors.")
    except RuntimeWarning as result:
        print("  The case encountered errors.", result)

    assert len(price_set) == 2, 'An unexpected number of prices was found'
    assert price_set[0].value == price0, 'The first price was not correct'
    assert price_set[1].value == price1, 'The second price was not correct'

    # ******************************************************************************************************************
    print(
        "  Case 3. Actual marginal prices in prior markets that are being corrected by the market."
    )  # *******
    # The test setup is such that the local asset should sequentially use Methods 1, 2, & 3 to find three marginal
    # prices.
    now = datetime.now()
    # test_asset = LocalAsset()
    test_asset_model = LocalAsset()
    # test_asset.model = test_asset_model
    # test_asset_model.object = test_asset
    test_asset_model.schedulingHorizon = timedelta(
        hours=2.5)  # Should cause asset to use prior market

    test_market = Market()

    test_interval0 = TimeInterval(now, timedelta(hours=1), test_market, now,
                                  now)
    price0 = 3.14159
    test_price0 = IntervalValue(None, test_interval0, test_market, 'test',
                                price0)
    test_market.timeIntervals = [test_interval0]
    test_market.marginalPrices = [test_price0]
    test_market.marketSeriesName = "Test Market"
    test_market.marketClearingTime = now

    prior_market = Market()
    test_interval1 = TimeInterval(now, timedelta(hours=1), prior_market, now,
                                  now)
    test_interval2 = TimeInterval(now, timedelta(hours=1), prior_market, now,
                                  now + timedelta(hours=1))
    price1 = 10
    test_price1 = IntervalValue(None, test_interval1, prior_market, 'test',
                                price1)
    test_price2 = IntervalValue(None, test_interval2, prior_market, 'test',
                                price1)
    prior_market.timeIntervals = [test_interval1, test_interval2]
    prior_market.marginalPrices = [test_price1, test_price2]
    prior_market.marketSeriesName = test_market.marketSeriesName
    prior_market.marketClearingTime = test_market.marketClearingTime - timedelta(
        hours=1)

    test_market.priorMarketInSeries = prior_market

    corrected_market = Market()
    price2 = 20
    test_interval3 = TimeInterval(now, timedelta(hours=1), corrected_market,
                                  now, now + timedelta(hours=2))
    test_price3 = IntervalValue(None, test_interval1, corrected_market, 'test',
                                price2)
    test_price4 = IntervalValue(None, test_interval2, corrected_market, 'test',
                                price2)
    test_price5 = IntervalValue(None, test_interval3, corrected_market, 'test',
                                price2)
    corrected_market.timeIntervals = [
        test_interval1, test_interval2, test_interval3
    ]
    corrected_market.marginalPrices = [test_price3, test_price4, test_price5]
    corrected_market.marketSeriesName = "Corrected Market"
    corrected_market.marketClearingTime = test_market.marketClearingTime - timedelta(
        hours=2)
    corrected_market.intervalDuration = timedelta(hours=1)

    test_market.priorRefinedMarket = corrected_market

    test_mtn = TransactiveNode()
    test_mtn.markets = [corrected_market, prior_market, test_market]
    test_mtn.localAssets = [test_asset_model]

    assert len(test_market.marginalPrices
               ) == 1, 'The market was supposed to have a marginal price'
    assert len(prior_market.marginalPrices
               ) == 2, "The prior market should have had two prices"
    assert len(corrected_market.marginalPrices
               ) == 3, 'The corrected market should have three prices'
    assert test_market.marketSeriesName == prior_market.marketSeriesName, 'The market names must be the same'

    try:
        price_set = test_asset_model.get_extended_prices(test_market)
        print("  The case ran without errors.")
    except RuntimeWarning as result:
        print("  The case encountered errors.", result)
        price_set = []

    assert len(price_set) == 3, 'An unexpected number of prices was found'
    assert price_set[0].value == price0, 'The first price was not correct'
    assert price_set[1].value == price1, 'The second price was not correct'
    assert price_set[2].value == price2, 'The third price was not correct'

    # ******************************************************************************************************************
    print("  Case 4. Modeled prices using the market's price model."
          )  # ***********************************************
    # The test setup is such that the local asset should use Methods 1 & 4 to find four marginal prices.
    now = datetime.now()
    test_asset_model = LocalAsset()
    test_asset_model.schedulingHorizon = timedelta(
        hours=3.5)  # Should cause asset to use prior market

    test_market = Market()

    test_interval0 = TimeInterval(now, timedelta(hours=1), test_market, now,
                                  now)
    price0 = 3.14159
    test_price0 = IntervalValue(None, test_interval0, test_market, 'test',
                                price0)
    test_market.timeIntervals = [test_interval0]
    test_market.marginalPrices = [test_price0]
    test_market.marketSeriesName = "Test Market"
    test_market.marketClearingTime = now
    test_market.priorMarketInSeries = None
    test_market.priorRefinedMarket = None
    avg_price = 30
    std_price = 0.1
    test_market.priceModel = [avg_price, std_price
                              ] * 24  # Critical to this test
    test_mtn = TransactiveNode()
    test_mtn.markets = [test_market]
    test_mtn.localAssets = [test_asset_model]

    assert len(test_market.marginalPrices
               ) == 1, 'The market was supposed to have a marginal price'
    assert len(test_market.priceModel
               ) == 48, 'A price model must exist for all 2 * 24 hours'

    try:
        price_set = test_asset_model.get_extended_prices(test_market)
        print("  The case ran without errors.")
    except RuntimeWarning as result:
        print("  The case encountered errors.", result)
        price_set = []

    # 200207DJH: The assignment of modeled prices now completes the prior successful method to the top of the next hour.
    #            Thereafter, modeled prices are assigned through the top of the hour that exceeds the scheduling
    #            horizon. Therefore, there is some variability in the count of
    assert len(price_set) == 4 or len(price_set) == 5, \
        ('An unexpected number', len(price_set), ' of prices was found')
    assert price_set[0].value == price0, 'The first price was not correct'
    assert all([price_set[x].value == avg_price for x in range(1, len(price_set))]), \
        'Prices 1 - 4 were not correct'

    # ******************************************************************************************************************
    print("  Case 5. The market's default price value."
          )  # ************************************************************

    test_asset_model = LocalAsset()

    test_asset_model.schedulingHorizon = timedelta(hours=4.5)

    test_market = Market()
    default_price = 1.2345
    test_market.defaultPrice = default_price
    test_market.priceModel = None
    test_market.intervalsToClear = 24
    test_market.intervalDuration = timedelta(hours=1)
    test_market.activationLeadTime = timedelta(days=2)
    test_market.priorRefinedMarket = None

    test_mtn = TransactiveNode()
    test_mtn.markets = [test_market]

    assert type(test_market.defaultPrice
                ) == float, 'A valid default price must be defined'

    try:
        price_set = test_asset_model.get_extended_prices(test_market)
        print("  The case ran without errors.")
    except RuntimeWarning:
        print("  The case encountered errors.")

    assert len(price_set) == 5, 'The number of horizon prices was unexpected'
    assert all([price_set[x].value == default_price for x in range(1, len(price_set))]), \
        'The default prices were not used'

    print("Method test_get_extended_prices() ran to completion.\n")
Exemplo n.º 10
0
def test_update_production_costs():
    # TEST_UPDATE_PRODUCTION_COSTS() - test method update_production_costs() that calculates production costs from
    # active vertices and scheduled powers.
    # NOTE: This test is virtually identical to the Neighbor test of the same name.
    print('Running LocalAsset.test_update_production_costs()')

    #   Create a test Market.
    test_market = Market()

    #   Create and store a TimeInterval.
    dt = datetime.now(
    )  # datetime that may be used for most datetime arguments
    time_interval = TimeInterval(dt, timedelta(hours=1), test_market, dt, dt)
    test_market.timeIntervals = [time_interval]

    #   Create a test LocalAsset.
    test_model = LocalAsset()

    #   Create and store a scheduled power IntervalValue in the active time interval.
    test_model.scheduledPowers = [
        IntervalValue(test_model, time_interval, test_market,
                      MeasurementType.ScheduledPower, 50)
    ]

    #   Create and store some active vertices IntervalValues in the active time interval.
    vertices = [Vertex(0.1, 1000, 0), Vertex(0.2, 1015, 100)]
    interval_values = [
        IntervalValue(test_model, time_interval, test_market,
                      MeasurementType.ActiveVertex, vertices[0]),
        IntervalValue(test_model, time_interval, test_market,
                      MeasurementType.ActiveVertex, vertices[1])
    ]
    test_model.activeVertices = interval_values

    # TEST 1
    print('- Test 1: First calculation of a production cost')

    try:
        test_model.update_production_costs(test_market)
        print('  - the method ran without errors')
    except RuntimeWarning as cause:
        print('  - the method encountered errors', cause)

    assert len(test_model.productionCosts
               ) == 1, 'The wrong number of production costs was created'

    production_cost = test_model.productionCosts[0].value
    assert production_cost == 1007.5, 'An unexpected production cost value was found'

    # TEST 2
    print('- Test 2: Reassignment of an existing production cost')

    #   Configure the test by modifying the scheduled power value.
    test_model.scheduledPowers[0].value = 150

    try:
        test_model.update_production_costs(test_market)
        print('  - the method ran without errors')
    except RuntimeWarning as cause:
        print('  - the method encountered errors', cause)

    assert len(test_model.productionCosts
               ) == 1, 'The wrong number of productions was created'

    production_cost = test_model.productionCosts[0].value

    assert production_cost == 1015, 'An unexpected dual cost value was found'

    # Success.
    print('Method test_update_production_costs() ran to completion.\n')
Exemplo n.º 11
0
def test_update_dual_costs():
    # TEST_UPDATE_DUAL_COSTS() - test method update_dual_costs() that creates or revises the dual costs in active time
    # intervals using active vertices, scheduled powers, and marginal prices.
    # NOTE: This test is virtually identical to the Neighbor test of the same name.
    print('Running LocalAsset.test_update_dual_costs()')

    #   Create a test Market object.
    test_market = Market()

    #   Create and store a TimeInterval object.
    dt = datetime.now(
    )  # datetime that may be used for most datetime arguments
    time_interval = TimeInterval(dt, timedelta(hours=1), test_market, dt, dt)
    test_market.timeIntervals = [time_interval]

    #   Create and store a marginal price IntervalValue object.
    test_market.marginalPrices = [
        IntervalValue(test_market, time_interval, test_market,
                      MeasurementType.MarginalPrice, 0.1)
    ]

    #   Create a test LocalAsset.
    test_model = LocalAsset()

    #   Create and store a scheduled power IntervalValue in the active time interval.
    test_model.scheduledPowers = [
        IntervalValue(test_model, time_interval, test_market,
                      MeasurementType.ScheduledPower, 100)
    ]

    #   Create and store a production cost IntervalValue in the active time interval.
    test_model.productionCosts = [
        IntervalValue(test_model, time_interval, test_market,
                      MeasurementType.ProductionCost, 1000)
    ]

    # TEST 1
    print('- Test 1: First calculation of a dual cost')

    try:
        test_model.update_dual_costs(test_market)
        print('  The test ran without errors')
    except RuntimeWarning as cause:
        print('  The test encountered errors', cause)

    assert len(test_model.dualCosts
               ) == 1, 'The wrong number of dual cost values was created'

    dual_cost = test_model.dualCosts[0].value

    assert dual_cost == (1000 -
                         100 * 0.1), 'An unexpected dual cost value was found'

    # TEST 2
    print('- Test 2: Reassignment of an existing dual cost')

    #   Configure the test by modifying the marginal price value.
    test_market.marginalPrices[0].value = 0.2

    try:
        test_model.update_dual_costs(test_market)
        print('  The test ran without errors')
    except RuntimeWarning as cause:
        print('  The test encountered errors', cause)

    assert len(test_model.dualCosts
               ) == 1, 'The wrong number of dual cost values was created'

    dual_cost = test_model.dualCosts[0].value

    assert dual_cost == (1000 -
                         100 * 0.2), 'An unexpected dual cost value was found'

    # Success.
    print('Method test_update_dual_costs() ran to completion.\n')
Exemplo n.º 12
0
def test_schedule_power():
    # TEST_SCHEDULE_POWER() - tests a LocalAsset method called
    # schedule_power().

    print('Running LocalAsset.test_schedule_power()')

    #   Establish test market
    test_mkt = Market()

    #   Establish test market with two distinct active time intervals
    # Note: This changed 1/29/19 due to new TimeInterval constructor
    dt = datetime.now()
    at = dt
    #   NOTE: def Hours() corrects behavior of Matlab hours().
    dur = timedelta(hours=1)
    mkt = test_mkt
    mct = dt
    st = datetime.combine(date.today(), time())  # datetime(date)

    ti = [TimeInterval(at, dur, mkt, mct, st)]
    st = ti[0].startTime + dur
    ti.append(TimeInterval(at, dur, mkt, mct, st))

    #   Store time intervals
    test_mkt.timeIntervals = ti

    #   Establish test model that is a LocalAsset with a default power
    #   property.
    test_model = LocalAsset()
    test_model.defaultPower = 3.14159

    #   Run the first test case.
    print("  Case 1: Power is scheduled for two time intervals.")
    try:
        test_model.schedule_power(test_mkt)
        print("  The method ran without errors")
    except RuntimeWarning as cause:
        print("  The method encountered errors", cause)

    #   Were the right number of scheduled power values created?
    assert len(test_model.scheduledPowers
               ) == 2, 'The method did not store the right number of results'

    # Where the correct scheduled power values stored?
    # if any([test_model.scheduledPowers.value] != test_model.defaultPower * ones(1, 2))
    assert all([x.value == test_model.defaultPower for x in test_model.scheduledPowers]), \
        'The stored scheduled powers were not as expected'

    # Change the default power.
    test_model.defaultPower = 6

    #   Create and store another active time interval.
    st = ti[1].startTime + dur
    ti.append(TimeInterval(at, dur, mkt, mct, st))

    #   Re-store time intervals
    test_mkt.timeIntervals = ti

    #   Run next test case.
    print("  Case 2: Power is scheduled for three time intervals.")
    try:
        test_model.schedule_power(test_mkt)
        print("  The method ran without errors")
    except RuntimeWarning as cause:
        print("  The method encountered errors", cause)

    #   Was the new time interval used?
    assert len(test_model.scheduledPowers
               ) == 3, 'The method failed to create a new scheduled power'

    # Were the existing time intervals reassigned properly?
    assert all([x.value == test_model.defaultPower for x in test_model.scheduledPowers]), \
        '- existing scheduled powers were not reassigned properly'

    # Success.
    print('Method test_schedule_power() ran to completion.\n')
Exemplo n.º 13
0
def test_schedule_engagement():
    # TEST_SCHEDULE_ENGAGEMENT() - tests a LocalAsset method called schedule_engagment()

    print('Running LocalAsset.test_schedule_engagement()')

    #   Establish test market
    test_mkt = Market()

    #   Establish test market with two distinct active time intervals
    # Note: This changed 1/29/18 due to new TimeInterval constructor
    dt = datetime.now()
    at = dt
    #   NOTE: def Hours() corrects behavior of Matlab hours().
    dur = timedelta(hours=1)
    mkt = test_mkt
    mct = dt
    st = datetime.combine(date.today(), time())  # datetime(date)

    ti = [TimeInterval(at, dur, mkt, mct, st)]

    st = ti[0].startTime + dur
    ti.append(TimeInterval(at, dur, mkt, mct, st))

    #   store time intervals
    test_mkt.timeIntervals = ti

    #   Establish test model that is a LocalAsset.
    test_model = LocalAsset()

    #   Run the first test case.
    print("  Case 1: Generate engagement schedule for two time intervals.")
    try:
        test_model.schedule_engagement(test_mkt)
        print("  The case ran without errors.")
    except RuntimeWarning as cause:
        print("  The case encountered errors.", cause)

    #   Were the right number of engagement schedule values created?
    assert len(test_model.engagementSchedule
               ) == 2, 'The method did not store the engagement schedule'

    # Where the correct scheduled engagement values stored?
    assert len([x.value for x in test_model.engagementSchedule if x.value != 1]) == 0, \
        'The stored engagement schedule was not as expected'
    """
    if len([x.value for x in test_model.engagementSchedule if x.value != 1]) > 0:
        pf = 'fail'
        raise Exception('- the stored engagement schedule was not as expected')
    else:
        print('- the result values were as expected')
        """

    # Create and store another active time interval.
    st = ti[1].startTime + dur
    ti.append(TimeInterval(at, dur, mkt, mct, st))

    #   Re-store time intervals
    test_mkt.timeIntervals = ti

    #   Run next test case.
    print("  Case 2: Adding a third time interval.")
    try:
        test_model.schedule_engagement(test_mkt)
        print("  The method ran without errors.")
    except RuntimeWarning as cause:
        print("  The method encountered errors.", cause)

    #   Was the new time interval used?
    assert len(
        test_model.engagementSchedule
    ) == 3, 'The method apparently failed to create a new engagement'

    # Were the existing time interval values reassigned properly?
    # if any([test_model.engagementSchedule.value] != true * ones(1, 3)):
    assert all([x.value == 1 for x in test_model.engagementSchedule]), \
        'The existing list was not augmented as expected'

    # Success.
    print('Method test_schedule_engagement() ran to completion.\n')