def test_update_vertices(): # TEST_UPDATE_VERTICES() - test method update_vertices(), which for this # base class of LocalAssetModel does practically nothing and must be # redefined by child classes that represent flesible assets. print('Running LocalAssetModel.test_update_vertices()') pf = 'pass' # 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 a test LocalAssetModel object. test_model = LocalAssetModel() # 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 a LocalAsset object and its maximum and minimum powers. test_object = LocalAsset() test_object.maximumPower = 200 test_object.minimumPower = 0 # Have the LocalAsset model and object cross reference one another. test_object.model = test_model test_model.object = test_object ## TEST 1 print('- Test 1: Basic operation') test_model.update_vertices(test_market) print(' - the method ran without errors') if len(test_model.activeVertices) != 1: pf = 'fail' print(' - there is an unexpected number of active vertices') else: print(' - the expected number of active vertices was found') # Success. print('- the test ran to completion') print('\nResult: #s\n\n', pf)
def test_calculate_reserve_margin(): # TEST_LAM_CALCULATE_RESERVE_MARGIN() - a LocalAssetModel ("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 LocalAssetModel.test_calculate_reserve_margin()') pf = 'pass' # 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 a test object that is a LocalAsset with assigned maximum power test_object = LocalAsset() test_object.maximumPower = 100 # Establish test object that is a LocalAssetModel test_model = LocalAssetModel() test_model.scheduledPowers = [ IntervalValue(test_model, ti, test_mkt, MeasurementType.ScheduledPower, 0.0)] # Allow object and model to cross-reference one another. test_object.model = test_model test_model.object = test_object # Run the first test case. test_model.calculate_reserve_margin(test_mkt) print('- method ran without errors') if len(test_model.reserveMargins) != 1: raise Exception('- an unexpected number of results were stored') else: print('- one reserve margin was stored, as expected') if test_model.reserveMargins[0].value != test_object.maximumPower: pf = 'fail' raise Exception('- the method did not use the available maximum power') else: print('- the method used maximum power value, as expected') # 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 # run test with maximum power greater than maximum vertex test_object.maximumPower = 100 test_model.calculate_reserve_margin(test_mkt) if test_model.reserveMargins[0].value != 10: pf = 'fail' raise Exception('- the method should have used vertex for comparison') else: print('- the method correctly chose to use the vertex power') # run test with maximum power less than maximum vertex test_object.maximumPower = 5 test_model.calculate_reserve_margin(test_mkt) if test_model.reserveMargins[0].value != 5: pf = 'fail' raise Exception('- method should have used maximum power for comparison') else: print('- the method properly chose to use the maximum power') # run test with scheduled power greater than maximum vertex test_model.scheduledPowers[0].value = 20 test_object.maximumPower = 500 test_model.calculate_reserve_margin(test_mkt) if test_model.reserveMargins[0].value != 0: pf = 'fail' raise Exception('- method should have assigned zero for a neg. result') else: print('- the method properly assigned 0 for a negative result') # Success. print('- the test ran to completion') print('\nResult: #s\n\n', pf)
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 NeighborModel test of the # same name. print('Running LocalAssetModel.test_update_dual_costs()') pf = 'pass' # 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 LocalAssetModel object. test_model = LocalAssetModel() # 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 object 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') test_model.update_dual_costs(test_market) print(' - the method ran without errors') if len(test_model.dualCosts) != 1: pf = 'fail' print(' - the wrong number of dual cost values was created') else: print(' - the right number of dual cost values was created') dual_cost = test_model.dualCosts[0].value if dual_cost != (1000 - 100 * 0.1): pf = 'fail' print(' - an unexpected dual cost value was found') else: print(' - the expected 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 test_model.update_dual_costs(test_market) print(' - the method ran without errors') if len(test_model.dualCosts) != 1: pf = 'fail' print(' - the wrong number of dual cost values was created') else: print(' - the right number of dual cost values was created') dual_cost = test_model.dualCosts[0].value if dual_cost != (1000 - 100 * 0.2): pf = 'fail' print(' - an unexpected dual cost value was found') else: print(' - the expected dual cost value was found') # Success. print('- the test ran to completion') print('\nResult: #s\n\n', pf)
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 NeighborModel test of the # same name. print('Running LocalAssetModel.test_update_production_costs()') pf = 'pass' # 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 a test LocalAssetModel object. test_model = LocalAssetModel() # 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 IntervalValue objects 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') test_model.update_production_costs(test_market) print(' - the method ran without errors') if len(test_model.productionCosts) != 1: pf = 'fail' print(' - the wrong number of production costs was created') else: print(' - the right number of production cost values was created') production_cost = test_model.productionCosts[0].value if float(production_cost) != float(1007.5): pf = 'fail' print(' - an unexpected production cost value was found') else: print(' - the expected 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 test_model.update_production_costs(test_market) print(' - the method ran without errors') if len(test_model.productionCosts) != 1: pf = 'fail' print(' - the wrong number of productions was created') else: print(' - the right number of production cost values was created') production_cost = test_model.productionCosts[0].value if float(production_cost) != float(1015): pf = 'fail' print(' - an unexpected dual cost value was found') else: print(' - the expected dual cost value was found') # Success. print('- the test ran to completion') print('\nResult: #s\n\n', pf)
def test_schedule_engagement(): # TEST_SCHEDULE_ENGAGEMENT() - tests a LocalAssetModel method called # schedule_engagment() print('Running LocalAssetModel.test_schedule_engagement()') pf = 'pass' # 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 object that is a LocalAssetModel test_object = LocalAssetModel() # Run the first test case. test_object.schedule_engagement(test_mkt) # Were the right number of engagement schedule values created? if len(test_object.engagementSchedule) != 2: pf = 'fail' raise Exception('- the method did not store the engagement schedule') else: print('- the method stored the right number of results') # Where the correct scheduled engagement values stored? if len([x.value for x in test_object.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. test_object.schedule_engagement(test_mkt) # Was the new time interval used? if len(test_object.engagementSchedule) != 3: pf = 'fail' raise Exception('- the method apparently failed to create a new engagement') else: print('- the method created and stored new values') # Were the existing time interval values reassigned properly? # if any([test_object.engagementSchedule.value] != true * ones(1, 3)): if any([x.value != 1 for x in test_object.engagementSchedule]): pf = 'fail' raise Exception('- the existing list was not augmented as expected') # Success. print('- the test ran to completion') print('\nResult: #s\n\n', pf)
def test_schedule_power(): # TEST_SCHEDULE_POWER() - tests a LocalAssetModel method called # schedule_power(). print('Running LocalAssetModel.test_schedule_power()') pf = 'pass' # 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 object that is a LocalAssetModel with a default power # property. test_object = LocalAssetModel() test_object.defaultPower = 3.14159 # Run the first test case. test_object.schedule_power(test_mkt) # Were the right number of schduled power values created? if len(test_object.scheduledPowers) != 2: pf = 'fail' raise Exception('- the method did not store the right number of results') else: print('- the method stored the right number of results') # Where the correct scheduled power valules stored? # if any([test_object.scheduledPowers.value] != test_object.defaultPower * ones(1, 2)) if any([x.value != test_object.defaultPower for x in test_object.scheduledPowers]): pf = 'fail' raise Exception('- the stored scheduled powers were not as expected') else: print('- the result value was as expected') # Change the default power. test_object.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. test_object.schedule_power(test_mkt) # Was the new time interval used? if len(test_object.scheduledPowers) != 3: pf = 'fail' raise Exception('- the method failed to create a new scheduled power') # Were the existing time intervals reassigned properly? # if any([test_object.scheduledPowers.value] != test_object.defaultPower * ones(1, 3)) if any([x.value != test_object.defaultPower for x in test_object.scheduledPowers]): pf = 'fail' raise Exception('- existing scheduled powers were not reassigned properly') # Success. print('- the test ran to completion') print('\nResult: #s\n\n', pf)
def test_schedule(): print('Running AbstractModel.test_schedule()') pf = 'pass' # 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) # Save the time interval test_mkt.timeIntervals = [ti] # Assign a marginal price in the time interval test_mkt.check_marginal_prices() # Create a Neighbor test object and give it a default maximum power value test_obj = Neighbor() test_obj.maximumPower = 100 # Create a corresponding NeighborModel test_mdl = NeighborModel() # 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 NeighborModel object print('- running test with a NeighborModel:') test_mdl.schedule(test_mkt) print(' - the method encountered no errors') if len(test_mdl.scheduledPowers) != 1: pf = 'fail' raise ' - the method did not store a scheduled power' else: print(' - the method calculated and stored a scheduled power') if len(test_mdl.reserveMargins) != 1: pf = 'fail' raise ' - the method did not store a reserve margin' else: print(' - the method stored a reserve margin') if len(test_mdl.activeVertices) != 1: pf = 'fail' raise ' - the method did not store an active vertex' else: print(' - the method stored an active vertex') # Run a test again with a LocalAssetModel object test_obj = LocalAsset() test_obj.maximumPower = 100 test_mdl = LocalAssetModel() test_obj.model = test_mdl test_mdl.object = test_obj print('- running test with a LocalAssetModel:') test_mdl.schedule(test_mkt) print(' - the method encountered no errors') if len(test_mdl.scheduledPowers) != 1: pf = 'fail' raise ' - the method did not store a scheduled power' else: print(' - the method calculated and stored a scheduled power') if len(test_mdl.reserveMargins) != 1: pf = 'fail' raise ' - the method did not store a reserve margin' else: print(' - the method stored a reserve margin') if len(test_mdl.activeVertices) != 1: pf = 'fail' raise ' - the method did not store an active vertex' else: print(' - the method stored an active vertex') # Success print('- the test ran to completion') print('Result: %s', pf)
def test_engagement_cost(): print('Running LocalAssetModel.test_engagement_cost()') pf = 'pass' # Create a test LocalAssetModel object. test_model = LocalAssetModel() # Assign engagement costs for [dissengagement, hold, engagement] test_model.engagementCost = [1, 2, 3] ## TEST 1 print('- Test 1: Normal transition input arguments [-1,0,1]') transition = 0 # false - false # a hold transition, unchanged cost = test_model.engagement_cost(transition) print(' - the method ran without errors') if cost != 2: pf = 'fail' print(' - the method miscalculated the cost of a hold') else: print(' - the method correctly calculated the cost of a hold') transition = -1 # false - true # an disengagement transition cost = test_model.engagement_cost(transition) if cost != 1: pf = 'fail' print(' - the method miscalculated the cost of a disengagement') else: print(' - the method correctly calculated the cost of a disengagement') transition = 1 # true - false # an disengagement transition cost = test_model.engagement_cost(transition) if cost != 3: pf = 'fail' print(' - the method miscalculated the cost of an engagement') else: print(' - the method correctly calculated the cost of an engagement') ## TEST 2 print('- Test 2: Unexpected, dissallowed input argument') transition = 7 # a disallowed transition cost = test_model.engagement_cost(transition) print(' - method warned and returned gracefully') if cost != 0: pf = 'fail' print(' - the method assigned a cost value other than zero') else: print(' - the method correctly assigned zero to the cost') # Success. print('- the test ran to completion') print('\nResult: #s\n\n', pf)
def test_update_costs(): print('Running AbstractModel.test_update_costs()') pf = 'pass' # 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() # Create a Neighbor test object and give it a default maximum power value test_obj = Neighbor() # test_obj.maximumPower = 100 # Create a corresponding NeighborModel test_mdl = NeighborModel() # 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 NeighborModel object print('- running test with a NeighborModel:') try: test_mdl.update_costs(test_mkt) print(' - the method encountered no errors') except: pf = 'fail' raise ' - the method did not run without errors' if len(test_mdl.productionCosts) != 1: pf = 'fail' raise ' - the method did not store a production cost' else: print(' - the method calculated and stored a production cost') if len(test_mdl.dualCosts) != 1: pf = 'fail' raise ' - the method did not store a dual cost' else: print(' - the method stored a dual cost') if test_mdl.totalProductionCost != sum( [x.value for x in test_mdl.productionCosts]): pf = 'fail' raise ' - the method did not store a total production cost' else: print(' - the method stored an total production cost') if test_mdl.totalDualCost != sum([x.value for x in test_mdl.dualCosts]): pf = 'fail' raise ' - the method did not store a total dual cost' else: print(' - the method stored an total dual cost') # Run a test again with a LocalAssetModel object test_obj = LocalAsset() # test_obj.maximumPower = 100 test_mdl = LocalAssetModel() 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)) ] print('- running test with a LocalAssetModel:') try: test_mdl.update_costs(test_mkt) print(' - the method encountered no errors') except: pf = 'fail' raise ' - the method did not run without errors' if len(test_mdl.productionCosts) != 1: pf = 'fail' raise ' - the method did not store a production cost' else: print(' - the method calculated and stored a production cost') if len(test_mdl.dualCosts) != 1: pf = 'fail' raise ' - the method did not store a dual cost' else: print(' - the method stored a dual cost') if test_mdl.totalProductionCost != sum( [x.value for x in test_mdl.productionCosts]): pf = 'fail' raise ' - the method did not store a total production cost' else: print(' - the method stored an total production cost') if test_mdl.totalDualCost != sum([x.value for x in test_mdl.dualCosts]): pf = 'fail' raise ' - the method did not store a total dual cost' else: print(' - the method stored an total dual cost') # Success print('- the test ran to completion') print('Result: %s', pf)
def test_prod_cost_from_formula(): from local_asset_model import LocalAssetModel from market import Market print('Running test_prod_cost_from_formula()') pf = 'pass' # Create a test object test_object = LocalAssetModel() # 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)
def test_production(): from local_asset_model import LocalAssetModel from market import Market print('Running test_production()') pf = 'pass' # Create a test object test_object = LocalAssetModel() # 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)
def test_sum_vertices(): print('Running Market.test_sum_vertices()') pf = 'pass' # Create a test myTransactiveNode object. test_node = myTransactiveNode() # Create a test Market object. test_market = Market() # List the test market with the test_node. test_node.markets = test_market # Create and store a time interval to work with. dt = datetime.now() at = dt dur = timedelta(hours=1) mkt = test_market mct = dt st = dt time_interval = TimeInterval(at, dur, mkt, mct, st) test_market.timeIntervals = [time_interval] # Create test LocalAsset and LocalAssetModel objects test_asset = LocalAsset() test_asset_model = LocalAssetModel() # Add the test_asset to the test node list. test_node.localAssets = [test_asset] # Have the test asset and its model cross reference one another. test_asset.model = test_asset_model test_asset_model.object = test_asset # Create and store an active Vertex or two for the test asset test_vertex = [Vertex(0.2, 0, -110), Vertex(0.2, 0, -90)] interval_values = [ IntervalValue(test_node, time_interval, test_market, MeasurementType.ActiveVertex, test_vertex[0]), IntervalValue(test_node, time_interval, test_market, MeasurementType.ActiveVertex, test_vertex[1]) ] test_asset_model.activeVertices = [interval_values[0], interval_values[1] ] # interval_value(1:2) # Create test Neighbor and NeighborModel objects. test_neighbor = Neighbor() test_neighbor_model = NeighborModel() # Add the test neighbor to the test node list. test_node.neighbors = [test_neighbor] # Have the test neighbor and its model cross reference one another. test_neighbor.model = test_neighbor_model test_neighbor.model.object = test_neighbor # Create and store an active Vertex or two for the test neighbor test_vertex.append(Vertex(0.1, 0, 0)) test_vertex.append(Vertex(0.3, 0, 200)) interval_values.append( IntervalValue(test_node, time_interval, test_market, MeasurementType.ActiveVertex, test_vertex[2])) interval_values.append( IntervalValue(test_node, time_interval, test_market, MeasurementType.ActiveVertex, test_vertex[3])) test_neighbor_model.activeVertices = [ interval_values[2], interval_values[3] ] ## Case 1 print('- Case 1: Basic case with interleaved vertices') # Run the test. try: vertices = test_market.sum_vertices(test_node, time_interval) print(' - the method ran without errors') except: pf = 'fail' print(' - the method had errors when called and stopped') if len(vertices) != 4: pf = 'fail' print(' - an unexpected number of vertices was returned') else: print(' - the expected number of vertices was returned') powers = [x.power for x in vertices] # if any(~ismember(single(powers), single([-110.0000, -10.0000, 10.0000, 110.0000]))) if len([ x for x in powers if round(x, 4) not in [-110.0000, -10.0000, 10.0000, 110.0000] ]) > 0: pf = 'fail' print(' - the vertex powers were not as expected') else: print(' - the vertex powers were as expected') marginal_prices = [round(x.marginalPrice, 4) for x in vertices] # if any(~ismember(single(marginal_prices), single([0.1000, 0.2000, 0.3000]))) if len([ x for x in marginal_prices if round(x, 4) not in [0.1000, 0.2000, 0.3000] ]) > 0: pf = 'fail' print(' - the vertex powers were not as expected') else: print(' - the vertex marginal prices were as expected') ## CASE 2: NEIGHBOR MODEL TO BE EXCLUDED # This case is needed when a demand or supply curve must be created for a # transactive Neighbor object. The active vertices of the target Neighbor # must be excluded, leaving a residual supply or demand curve against which # the Neighbor may plan. print('- Case 2: Exclude test Neighbor model') # Run the test. try: # [vertices] = test_market.sum_vertices(test_node, time_interval, test_neighbor_model) vertices = test_market.sum_vertices(test_node, time_interval, test_neighbor_model) print(' - the method ran without errors') except: pf = 'fail' print(' - the method encountered errors and stopped') if len(vertices) != 2: pf = 'fail' print(' - an unexpected number of vertices was returned') else: print(' - the expected number of vertices was returned') powers = [round(x.power, 4) for x in vertices] # if any(~ismember(single(powers), single([-110.0000, -90.0000]))) if len([x for x in powers if x not in [-110.0000, -90.0000]]) > 0: pf = 'fail' print(' - the vertex powers were not as expected') else: print(' - the vertex powers were as expected') marginal_prices = [x.marginalPrice for x in vertices] # if any(~ismember(single(marginal_prices), single([0.2000]))) if len([x for x in marginal_prices if round(x, 4) not in [0.2000]]) > 0: pf = 'fail' print(' - the vertex powers were not as expected') else: print(' - the vertex marginal prices were as expected') ## CASE 3: CONSTANT SHOULD NOT CREATE NEW NET VERTEX print('- Case 3: Include a constant vertex. No net vertex should be added') # Change the test asset to NOT have any flexibility. A constant should # not introduce a net vertex at a constant's marginal price. Marginal # price is NOT meaningful for an inelastic device. test_asset_model.activeVertices = [interval_values[0]] # Run the test. try: # [vertices] = test_market.sum_vertices(test_node, time_interval) vertices = test_market.sum_vertices(test_node, time_interval) print(' - the method ran without errors') except: pf = 'fail' print(' - the method encountered errors and stopped') #%[180907DJH: THIS TEST IS CORRECTED. THE NEIGHBOR HAS TWO VERTICES. ADDING #AN ASSET WITH ONE VERTEX (NO FLEXIBILITY) SHOULD NOT CHANGE THE NUMBER OF #ACTIVE VERTICES, SO THE CORRECTED TEST CONFIRMS TWO VERTICES. THE CODE HAS #BEEN CORRECTED ACCORDINGLY.] if len(vertices) != 2: pf = 'fail' print(' - an unexpected number of vertices was returned') else: print(' - the expected number of vertices was returned') powers = [x.power for x in vertices] # if any(~ismember(single(powers), single([-110.0000, 90]))) if len([x for x in powers if round(x, 4) not in [-110.0000, 90]]) > 0: pf = 'fail' print(' - the vertex powers were not as expected') else: print(' - the vertex powers were as expected') marginal_prices = [x.marginalPrice for x in vertices] # if any(~ismember(single(marginal_prices), single([0.1000, 0.3000, Inf]))) if len([ x for x in marginal_prices if round(x, 4) not in [0.1000, 0.3000, float("inf")] ]) > 0: pf = 'fail' print(' - the vertex powers were not as expected') else: print(' - the vertex marginal prices were as expected') # CASE 4: More than two vertices at any marginal price print('- Case 4: More than two vertices at same marginal price') # Move the two active vertices of the test asset to be at the same # marginal price as one of the neighbor active vertices. test_vertex = [Vertex(0.1, 0, -110), Vertex(0.1, 0, -90)] interval_values = [ IntervalValue(test_node, time_interval, test_market, MeasurementType.ActiveVertex, test_vertex[0]), IntervalValue(test_node, time_interval, test_market, MeasurementType.ActiveVertex, test_vertex[1]) ] test_asset_model.activeVertices = [interval_values[0], interval_values[1] ] # interval_value(1:2) # Run the test. try: vertices = test_market.sum_vertices(test_node, time_interval) print(' - the method ran without errors') except: pf = 'fail' print(' - the method encountered errors and stopped') if len(vertices) != 3: pf = 'fail' print(' - an unexpected number of vertices was returned') else: print(' - the expected number of vertices was returned') powers = [x.power for x in vertices] # if any(~ismember(single(powers), single([-110.0000, -90.0000, 110.0000]))) if len([ x for x in powers if round(x, 4) not in [-110.0000, -90.0000, 110.0000] ]) > 0: pf = 'fail' print(' - the vertex powers were not as expected') else: print(' - the vertex powers were as expected') marginal_prices = [x.marginalPrice for x in vertices] # if any(~ismember(single(marginal_prices), single([0.1000, 0.3000]))) if len([x for x in marginal_prices if round(x, 4) not in [0.1000, 0.3000] ]) > 0: pf = 'fail' print(' - the vertex powers were not as expected') else: print(' - the vertex marginal prices were as expected') # Success print('- the test ran to completion') print('Result: #s\n\n', pf)
def test_schedule(): print('Running Market.test_schedule()') print('WARNING: This test may be affected by NeighborModel.schedule()') print('WARNING: This test may be affected by NeighborModel.schedule()') pf = 'pass' # Establish a myTransactiveNode object mtn = myTransactiveNode() # Establish a test market test_mkt = Market() # Create and store one TimeInterval dt = datetime(2018, 1, 1, 12, 0, 0) # Noon Jan 1, 2018 at = dt dur = timedelta(hours=1) mkt = test_mkt mct = dt st = dt ti = TimeInterval(at, dur, mkt, mct, st) test_mkt.timeIntervals = [ti] # Create and store a marginal price in the active interval. test_mkt.marginalPrices = [ IntervalValue(test_mkt, ti, test_mkt, MeasurementType.MarginalPrice, 0.01) ] print('- configuring a test Neighbor and its NeighborModel') # Create a test object that is a Neighbor test_obj1 = Neighbor() test_obj1.maximumPower = 100 # Create the corresponding model that is a NeighborModel test_mdl1 = NeighborModel() test_mdl1.defaultPower = 10 test_obj1.model = test_mdl1 test_mdl1.object = test_obj1 mtn.neighbors = [test_obj1] print('- configuring a test LocalAsset and its LocalAssetModel') # Create a test object that is a Local Asset test_obj2 = LocalAsset test_obj2.maximumPower = 100 # Create the corresponding model that is a LocalAssetModel test_mdl2 = LocalAssetModel() test_mdl2.defaultPower = 10 test_obj2.model = test_mdl2 test_mdl2.object = test_obj2 mtn.localAssets = [test_obj2] try: test_mkt.schedule(mtn) print('- method ran without errors') except: raise ('- method did not run due to errors') if len(test_mdl1.scheduledPowers) != 1: raise ( '- the wrong numbers of scheduled powers were stored for the Neighbor' ) else: print( '- the right number of scheduled powers were stored for the Neighbor' ) if len(test_mdl2.scheduledPowers) != 1: raise ( '- the wrong numbers of scheduled powers were stored for the LocalAsset' ) else: print( '- the right number of scheduled powers were stored for the LocalAsset' ) # Success print('- the test ran to completion') print('Result: #s\n\n', pf)