def test_approx_equal(self): assert not utilities.approx_equal(1, 2) assert not utilities.approx_equal(1, 1.02) assert utilities.approx_equal(1, 1.01) assert utilities.approx_equal(1, 1)
def load_inputs(mod, switch_data, inputs_dir): """ Import data to support modeling fuel use under partial loading conditions with piecewise linear incremental heat rates. These files are formatted differently than most to match the standard format of incremental heat rates. This format is peculiar because it formats data records that describes a fuel use curve in two disticnt ways. The first record is the first point on the curve, but all subsequent records are slopes and x-domain for each line segment. For a given generation technology or project, the relevant data should be formatted like so: power_start_mw power_end_mw ihr fuel_use_rate min_load . . value min_load mid_load1 value . mid_load1 max_load value . The first row provides the first point on the input/output curve. Literal dots should be included to indicate blanks. The column fuel_use_rate is in units of MMBTU/h. Subsequent rows provide the domain and slope of each line segement. The column ihr indicates incremental heat rate in MMBTU/MWh. Any number of line segments will be accepted. All text should be replaced with actual numerical values. I chose this format to a) be relatively consistent with standard data that is easiest to find, b) make it difficult to misinterpret the meaning of the data, and c) allow all of the standard data to be included in a single file. The following files are optional. If no representative data is provided for a generation technology, it will default to a single line segment with an intercept of 0 and a slope equal to the full load heat rate. If no specific data is provided for a project, it will default to its generation technology. gen_inc_heat_rates.tab generation_technology, power_start_mw, power_end_mw, incremental_heat_rate_mbtu_per_mwhr, fuel_use_rate_mmbtu_per_h proj_inc_heat_rates.tab project, power_start_mw, power_end_mw, incremental_heat_rate_mbtu_per_mwhr, fuel_use_rate_mmbtu_per_h """ path = os.path.join(inputs_dir, 'gen_inc_heat_rates.tab') if os.path.isfile(path): (fuel_rate_segments, min_load, full_hr) = _parse_inc_heat_rate_file( path, id_column="generation_technology") # Check implied minimum loading level for consistency with # g_min_load_fraction if g_min_load_fraction was provided. If # g_min_load_fraction wasn't provided, set it to implied minimum # loading level. for g in min_load: if 'g_min_load_fraction' not in switch_data.data(): switch_data.data()['g_min_load_fraction'] = {} if g in switch_data.data(name='g_min_load_fraction'): min_load_dat = switch_data.data(name='g_min_load_fraction')[g] if not approx_equal(min_load[g], min_load_dat): raise ValueError(( "g_min_load_fraction is inconsistant with " + "incremental heat rate data for generation " + "technology {}.").format(g)) else: switch_data.data(name='g_min_load_fraction')[g] = min_load[g] # Same thing, but for full load heat rate. for g in full_hr: if 'g_full_load_heat_rate' not in switch_data.data(): switch_data.data()['g_full_load_heat_rate'] = {} if g in switch_data.data(name='g_full_load_heat_rate'): full_hr_dat = switch_data.data(name='g_full_load_heat_rate')[g] if abs((full_hr[g] - full_hr_dat) / full_hr_dat) > 0.01: raise ValueError(( "g_full_load_heat_rate is inconsistant with " + "incremental heat rate data for generation " + "technology {}.").format(g)) else: switch_data.data(name='g_full_load_heat_rate')[g] = full_hr[g] # Copy parsed data into the data portal. switch_data.data()['GEN_FUEL_USE_SEGMENTS'] = fuel_rate_segments path = os.path.join(inputs_dir, 'proj_inc_heat_rates.tab') if os.path.isfile(path): (fuel_rate_segments, min_load, full_hr) = _parse_inc_heat_rate_file( path, id_column="project") # Check implied minimum loading level for consistency with # proj_min_load_fraction if proj_min_load_fraction was provided. If # proj_min_load_fraction wasn't provided, set it to implied minimum # loading level. for pr in min_load: if 'proj_min_load_fraction' not in switch_data.data(): switch_data.data()['proj_min_load_fraction'] = {} dp_dict = switch_data.data(name='proj_min_load_fraction') if pr in dp_dict: min_load_dat = dp_dict[pr] if abs((min_load[pr] - min_load_dat) / min_load_dat) > 0.01: raise ValueError(( "proj_min_load_fraction is inconsistant with " + "incremental heat rate data for project " + "{}.").format(pr)) else: dp_dict[pr] = min_load[pr] # Same thing, but for full load heat rate. for pr in full_hr: if 'proj_full_load_heat_rate' not in switch_data.data(): switch_data.data()['proj_full_load_heat_rate'] = {} dp_dict = switch_data.data(name='proj_full_load_heat_rate') if pr in dp_dict: full_hr_dat = dp_dict[pr] if abs((full_hr[pr] - full_hr_dat) / full_hr_dat) > 0.01: raise ValueError(( "proj_full_load_heat_rate is inconsistant with " + "incremental heat rate data for project " + "{}.").format(pr)) else: dp_dict[pr] = full_hr[pr] # Copy parsed data into the data portal. switch_data.data()['PROJ_FUEL_USE_SEGMENTS'] = fuel_rate_segments
def load_inputs(mod, switch_data, inputs_dir): """ Import data to support modeling fuel use under partial loading conditions with piecewise linear incremental heat rates. These files are formatted differently than most to match the standard format of incremental heat rates. This format is peculiar because it formats data records that describes a fuel use curve in two disticnt ways. The first record is the first point on the curve, but all subsequent records are slopes and x-domain for each line segment. For a given generation technology or project, the relevant data should be formatted like so: power_start_mw power_end_mw ihr fuel_use_rate min_load . . value min_load mid_load1 value . mid_load1 max_load value . The first row provides the first point on the input/output curve. Literal dots should be included to indicate blanks. The column fuel_use_rate is in units of MMBTU/h. Subsequent rows provide the domain and slope of each line segement. The column ihr indicates incremental heat rate in MMBTU/MWh. Any number of line segments will be accepted. All text should be replaced with actual numerical values. I chose this format to a) be relatively consistent with standard data that is easiest to find, b) make it difficult to misinterpret the meaning of the data, and c) allow all of the standard data to be included in a single file. The following files are optional. If no representative data is provided for a generation technology, it will default to a single line segment with an intercept of 0 and a slope equal to the full load heat rate. If no specific data is provided for a project, it will default to its generation technology. gen_inc_heat_rates.tab generation_technology, power_start_mw, power_end_mw, incremental_heat_rate_mbtu_per_mwhr, fuel_use_rate_mmbtu_per_h proj_inc_heat_rates.tab project, power_start_mw, power_end_mw, incremental_heat_rate_mbtu_per_mwhr, fuel_use_rate_mmbtu_per_h """ path = os.path.join(inputs_dir, 'gen_inc_heat_rates.tab') if os.path.isfile(path): (fuel_rate_segments, min_load, full_hr) = _parse_inc_heat_rate_file( path, id_column="generation_technology") # Check implied minimum loading level for consistency with # g_min_load_fraction if g_min_load_fraction was provided. If # g_min_load_fraction wasn't provided, set it to implied minimum # loading level. for g in min_load: if 'g_min_load_fraction' not in switch_data.data(): switch_data.data()['g_min_load_fraction'] = {} if g in switch_data.data(name='g_min_load_fraction'): min_load_dat = switch_data.data(name='g_min_load_fraction')[g] if not approx_equal(min_load[g], min_load_dat): raise ValueError( ("g_min_load_fraction is inconsistant with " + "incremental heat rate data for generation " + "technology {}.").format(g)) else: switch_data.data(name='g_min_load_fraction')[g] = min_load[g] # Same thing, but for full load heat rate. for g in full_hr: if 'g_full_load_heat_rate' not in switch_data.data(): switch_data.data()['g_full_load_heat_rate'] = {} if g in switch_data.data(name='g_full_load_heat_rate'): full_hr_dat = switch_data.data(name='g_full_load_heat_rate')[g] if abs((full_hr[g] - full_hr_dat) / full_hr_dat) > 0.01: raise ValueError( ("g_full_load_heat_rate is inconsistant with " + "incremental heat rate data for generation " + "technology {}.").format(g)) else: switch_data.data(name='g_full_load_heat_rate')[g] = full_hr[g] # Copy parsed data into the data portal. switch_data.data()['GEN_FUEL_USE_SEGMENTS'] = fuel_rate_segments path = os.path.join(inputs_dir, 'proj_inc_heat_rates.tab') if os.path.isfile(path): (fuel_rate_segments, min_load, full_hr) = _parse_inc_heat_rate_file(path, id_column="project") # Check implied minimum loading level for consistency with # proj_min_load_fraction if proj_min_load_fraction was provided. If # proj_min_load_fraction wasn't provided, set it to implied minimum # loading level. for pr in min_load: if 'proj_min_load_fraction' not in switch_data.data(): switch_data.data()['proj_min_load_fraction'] = {} dp_dict = switch_data.data(name='proj_min_load_fraction') if pr in dp_dict: min_load_dat = dp_dict[pr] if abs((min_load[pr] - min_load_dat) / min_load_dat) > 0.01: raise ValueError( ("proj_min_load_fraction is inconsistant with " + "incremental heat rate data for project " + "{}.").format(pr)) else: dp_dict[pr] = min_load[pr] # Same thing, but for full load heat rate. for pr in full_hr: if 'proj_full_load_heat_rate' not in switch_data.data(): switch_data.data()['proj_full_load_heat_rate'] = {} dp_dict = switch_data.data(name='proj_full_load_heat_rate') if pr in dp_dict: full_hr_dat = dp_dict[pr] if abs((full_hr[pr] - full_hr_dat) / full_hr_dat) > 0.01: raise ValueError( ("proj_full_load_heat_rate is inconsistant with " + "incremental heat rate data for project " + "{}.").format(pr)) else: dp_dict[pr] = full_hr[pr] # Copy parsed data into the data portal. switch_data.data()['PROJ_FUEL_USE_SEGMENTS'] = fuel_rate_segments