Example #1
0
    def test(CostExpression):
        from testfixtures import compare

        (coefficients_sympify, var_names_sympify) = coef_via_sympify(CostExpression) 
        (coefficients_pyomo, var_names_pyomo) = coef_via_pyomo(CostExpression)

        compare(var_names_sympify, var_names_pyomo)
        # I have to use sorted because keys come out as randomly orderd tuples
        # and compare got hung up on inconsequential differences their ordering.
        compare(sorted(coefficients_sympify.keys()), sorted(coefficients_pyomo.keys()))

        # I rolled my own compare tool for cost_coefficients because compare
        # insists on numeric equality, and the sympify's round-trip of
        # binary->text->binary results in slight rounding errors.
        from switch_model.utilities import approx_equal
        for vid in coefficients_pyomo.keys():
            assert(approx_equal(coefficients_sympify[vid], coefficients_pyomo[vid],
                                tolerance=.000001))
Example #2
0
    def test(CostExpression):
        from testfixtures import compare

        (coefficients_sympify, var_names_sympify) = coef_via_sympify(CostExpression) 
        (coefficients_pyomo, var_names_pyomo) = coef_via_pyomo(CostExpression)

        compare(var_names_sympify, var_names_pyomo)
        # I have to use sorted because keys come out as randomly orderd tuples
        # and compare got hung up on inconsequential differences their ordering.
        compare(sorted(coefficients_sympify.keys()), sorted(coefficients_pyomo.keys()))

        # I rolled my own compare tool for cost_coefficients because compare
        # insists on numeric equality, and the sympify's round-trip of
        # binary->text->binary results in slight rounding errors.
        from switch_model.utilities import approx_equal
        for vid in coefficients_pyomo.keys():
            assert(approx_equal(coefficients_sympify[vid], coefficients_pyomo[vid],
                                tolerance=.000001))
Example #3
0
 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)
Example #4
0
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 heat22 rate. If no specific data is provided for a project, it
    will default to its generation technology.

    gen_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_PROJECT")
        # Check implied minimum loading level for consistency with
        # gen_min_load_fraction if gen_min_load_fraction was provided. If
        # gen_min_load_fraction wasn't provided, set it to implied minimum
        # loading level.
        for g in min_load:
            if 'gen_min_load_fraction' not in switch_data.data():
                switch_data.data()['gen_min_load_fraction'] = {}
            dp_dict = switch_data.data(name='gen_min_load_fraction')
            if g in dp_dict:
                min_load_dat = dp_dict[g]
                if not approx_equal(min_load[g], min_load_dat):
                    raise ValueError(
                        ("gen_min_load_fraction is inconsistant with " +
                         "incremental heat rate data for project " +
                         "{}.").format(g))
            else:
                dp_dict[g] = min_load[g]
        # Same thing, but for full load heat rate.
        for g in full_hr:
            if 'gen_full_load_heat_rate' not in switch_data.data():
                switch_data.data()['gen_full_load_heat_rate'] = {}
            dp_dict = switch_data.data(name='gen_full_load_heat_rate')
            if g in dp_dict:
                full_hr_dat = dp_dict[g]
                if abs((full_hr[g] - full_hr_dat) / full_hr_dat) > 0.01:
                    raise ValueError(
                        ("gen_full_load_heat_rate is inconsistant with " +
                         "incremental heat rate data for project " +
                         "{}.").format(g))
            else:
                dp_dict[g] = full_hr[g]
        # Copy parsed data into the data portal.
        switch_data.data()['FUEL_USE_SEGMENTS_FOR_GEN'] = fuel_rate_segments
Example #5
0
 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)
Example #6
0
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 heat22 rate. If no specific data is provided for a project, it
    will default to its generation technology.

    gen_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="project")
        # Check implied minimum loading level for consistency with
        # gen_min_load_fraction if gen_min_load_fraction was provided. If
        # gen_min_load_fraction wasn't provided, set it to implied minimum
        # loading level.
        for g in min_load:
            if 'gen_min_load_fraction' not in switch_data.data():
                switch_data.data()['gen_min_load_fraction'] = {}
            dp_dict = switch_data.data(name='gen_min_load_fraction')
            if g in dp_dict:
                min_load_dat = dp_dict[g]
                if not approx_equal(min_load[g], min_load_dat):
                    raise ValueError((
                        "gen_min_load_fraction is inconsistant with " +
                        "incremental heat rate data for project " +
                        "{}.").format(g))
            else:
                dp_dict[g] = min_load[g]
        # Same thing, but for full load heat rate.
        for g in full_hr:
            if 'gen_full_load_heat_rate' not in switch_data.data():
                switch_data.data()['gen_full_load_heat_rate'] = {}
            dp_dict = switch_data.data(name='gen_full_load_heat_rate')
            if g in dp_dict:
                full_hr_dat = dp_dict[g]
                if abs((full_hr[g] - full_hr_dat) / full_hr_dat) > 0.01:
                    raise ValueError((
                        "gen_full_load_heat_rate is inconsistant with " +
                        "incremental heat rate data for project " +
                        "{}.").format(g))
            else:
                dp_dict[g] = full_hr[g]
        # Copy parsed data into the data portal.
        switch_data.data()['FUEL_USE_SEGMENTS_FOR_GEN'] = fuel_rate_segments