def interpolate_values(source_table, source_column, target_value):
    t = source_table
    source_values = t[source_column]
    minimum_source_value = source_values.min()
    maximum_source_value = source_values.max()
    message_template = 'source_column (%s) values must be %%s' % source_column
    assert len(t) > 0, 'table must have at least one row'
    assert len(t) == len(set(source_values)), message_template % 'unique'
    assert minimum_source_value >= 0, message_template % 'positive'
    if len(t) == 1:
        return t.ix[t.index[0]]
    if target_value <= minimum_source_value:
        return t.ix[source_values.argmin()]
    if target_value >= maximum_source_value:
        return t.ix[source_values.argmax()]
    # Get two rows nearest to target value
    sorted_indices = (source_values - target_value).abs().argsort()
    row0 = t.ix[sorted_indices[0]]
    row1 = t.ix[sorted_indices[1]]
    # Compute fraction of interpolation
    fraction = divide_safely(
        target_value - row0[source_column],
        row1[source_column] - row0[source_column],
        ExpectedPositive(message_template % 'unique and positive'))
    # Interpolate
    return row0 + (row1 - row0) * fraction
def run(location_geotable):
    graph = Graph()
    for index, row in location_geotable.iterrows():
        graph.add_node(index, **{
            'lat': row['Latitude'],
            'lon': row['Longitude']
        })
    for node1_id in range(min(graph), max(graph)):
        for node2_id in range(node1_id + 1, max(graph) + 1):
            node1_d = graph.node[node1_id]
            node2_d = graph.node[node2_id]
            node1_ll = node1_d['lat'], node1_d['lon']
            node2_ll = node2_d['lat'], node2_d['lon']
            distance = get_distance(node1_ll, node2_ll).m
            graph.add_edge(node1_id, node2_id, weight=distance)
    tree = minimum_spanning_tree(graph)
    total_distance = sum(
        edge_d['weight']
        for node1_id, node2_id, edge_d in tree.edges(data=True))
    location_count = len(graph)
    average_distance = divide_safely(total_distance, location_count, 0)
    return [
        ('total_distance_between_locations_in_meters', total_distance),
        ('location_count', location_count),
        ('average_distance_between_locations_in_meters', average_distance),
    ]
Exemple #3
0
def prepare_cost_summary(cost_by_year, d, keywords, prefix):
    """
    Summarize costs using the values provided in *d*
    """
    discounted_cost = compute_discounted_cash_flow(
        cost_by_year, keywords['financing_year'],
        keywords['discount_rate_as_percent_of_cash_flow_per_year'])
    levelized_cost = divide_safely(discounted_cost, keywords[
        'discounted_consumption_in_kwh'], 0)
    return merge_dictionaries(d, {
        prefix + 'cost_by_year': cost_by_year,
        prefix + 'initial_cost': sum([
            sum_by_suffix(d, '_raw_cost'),
            sum_by_suffix(d, '_installation_cost'),
        ]),
        prefix + 'recurring_fixed_cost_per_year': sum([
            sum_by_suffix(d, '_maintenance_cost_per_year'),
            sum_by_suffix(d, '_replacement_cost_per_year'),
        ]),
        prefix + 'recurring_variable_cost_per_year': sum([
            d.get('final_electricity_production_cost_per_year', 0),
        ]),
        prefix + 'discounted_cost': discounted_cost,
        prefix + 'levelized_cost_per_kwh_consumed': levelized_cost,
    })
def estimate_consumption_from_connection_type(population_by_year,
                                              number_of_people_per_household,
                                              connection_type_table,
                                              **keywords):
    """
    Note that connection_count and consumption will be constant year over year
    if there is a local override for household_count.
    """
    d = {}
    connection_count_by_year = make_zero_by_year(population_by_year)
    consumption_by_year = make_zero_by_year(population_by_year)
    estimated_household_connection_count_by_year = divide_safely(
        population_by_year, number_of_people_per_household,
        make_zero_by_year(population_by_year))
    for row_index, row in connection_type_table.iterrows():
        connection_type = row['connection_type']
        count_by_year = _get_connection_count_by_year(
            keywords, connection_type,
            estimated_household_connection_count_by_year)
        consumption_per_connection = _get_consumption_per_connection(
            keywords, connection_type, row['consumption_in_kwh_per_year'])
        connection_count_by_year += count_by_year
        consumption_by_year += consumption_per_connection * count_by_year
        # Record
        connection_count_name = _name_connection_count(connection_type)
        consumption_per_connection_name = _name_consumption_per_connection(
            connection_type)
        d[connection_count_name + '_by_year'] = count_by_year
        d[connection_count_name] = get_final_value(count_by_year)
        d[consumption_per_connection_name] = consumption_per_connection
    return dict(
        d, **{
            'connection_count_by_year': connection_count_by_year,
            'consumption_in_kwh_by_year': consumption_by_year
        })
Exemple #5
0
def estimate_grid_mv_line_budget(internal_discounted_cost_by_technology,
                                 grid_mv_line_discounted_cost_per_meter,
                                 line_length_adjustment_factor):
    standalone_cost = min(
        v for k, v in internal_discounted_cost_by_technology.items()
        if k != 'grid')
    grid_mv_line_budget_in_money = \
        standalone_cost - internal_discounted_cost_by_technology['grid']
    grid_mv_line_raw_budget_in_meters = divide_safely(
        grid_mv_line_budget_in_money, grid_mv_line_discounted_cost_per_meter,
        ExpectedPositive('grid_mv_line_discounted_cost_per_meter'))
    # Divide line distance by factor here, which should be equivalent to
    # multiplying line distance by factor when computing the network
    grid_mv_line_adjusted_budget_in_meters = divide_safely(
        grid_mv_line_raw_budget_in_meters, line_length_adjustment_factor,
        ExpectedPositive('line_length_adjustment_factor'))
    return {
        'grid_mv_line_adjusted_budget_in_meters':
        grid_mv_line_adjusted_budget_in_meters,
    }
Exemple #6
0
def estimate_panel_cost(final_consumption_in_kwh_per_year,
                        peak_hours_of_sun_per_year,
                        system_loss_as_percent_of_total_production,
                        panel_table):
    final_production_in_kwh_per_year = adjust_for_losses(
        final_consumption_in_kwh_per_year,
        system_loss_as_percent_of_total_production)
    desired_system_capacity_in_kw = divide_safely(
        final_production_in_kwh_per_year, peak_hours_of_sun_per_year,
        float('inf'))
    return prepare_system_capacity_cost(panel_table, 'capacity_in_kw',
                                        desired_system_capacity_in_kw)
def estimate_consumption_from_connection_count(
        population_by_year, number_of_people_per_connection,
        consumption_in_kwh_per_year_per_connection):
    connection_count_by_year = divide_safely(population_by_year,
                                             number_of_people_per_connection,
                                             0)
    consumption_by_year = consumption_in_kwh_per_year_per_connection * \
        connection_count_by_year
    return {
        'connection_count_by_year': connection_count_by_year,
        'consumption_in_kwh_by_year': consumption_by_year
    }
Exemple #8
0
def estimate_total_levelized_cost_by_technology(infrastructure_graph,
                                                selected_technologies,
                                                discounted_cost_by_technology):
    discounted_consumption_by_technology = OrderedDefaultDict(int)
    for node_id, node_d in infrastructure_graph.cycle_nodes():
        technology = node_d['proposed_technology']
        if technology not in selected_technologies:
            continue
        discounted_consumption_by_technology[technology] += node_d[
            'discounted_consumption_in_kwh']
    levelized_cost_by_technology = OrderedDict()
    for technology in selected_technologies:
        discounted_cost = discounted_cost_by_technology[technology]
        discounted_consumption = discounted_consumption_by_technology[
            technology]
        levelized_cost_by_technology[technology] = divide_safely(
            discounted_cost, discounted_consumption, 0)
    return {'levelized_cost_by_technology': levelized_cost_by_technology}
Exemple #9
0
def estimate_balance_cost(
        panel_actual_system_capacity_in_kw, balance_raw_cost_per_panel_kw,
        balance_installation_cost_as_percent_of_raw_cost,
        balance_maintenance_cost_per_year_as_percent_of_raw_cost,
        balance_lifetime_in_years):
    raw_cost = panel_actual_system_capacity_in_kw * \
        balance_raw_cost_per_panel_kw
    installation_cost = raw_cost * \
        balance_installation_cost_as_percent_of_raw_cost / 100.
    maintenance_cost_per_year = raw_cost * \
        balance_maintenance_cost_per_year_as_percent_of_raw_cost / 100.
    replacement_cost_per_year = divide_safely(
        raw_cost + installation_cost, balance_lifetime_in_years,
        ExpectedPositive('balance_lifetime_in_years'))
    return {
        'raw_cost': raw_cost,
        'installation_cost': installation_cost,
        'maintenance_cost_per_year': maintenance_cost_per_year,
        'replacement_cost_per_year': replacement_cost_per_year,
    }
Exemple #10
0
def estimate_grid_mv_line_cost_per_meter(
        grid_mv_line_raw_cost_per_meter,
        grid_mv_line_installation_cost_as_percent_of_raw_cost,
        grid_mv_line_maintenance_cost_per_year_as_percent_of_raw_cost,
        grid_mv_line_lifetime_in_years):
    raw_cost_per_meter = grid_mv_line_raw_cost_per_meter
    installation_cost_per_meter = raw_cost_per_meter * \
        grid_mv_line_installation_cost_as_percent_of_raw_cost / 100.
    return {
        'raw_cost_per_meter':
        raw_cost_per_meter,
        'installation_cost_per_meter':
        installation_cost_per_meter,
        'maintenance_cost_per_meter_per_year':
        raw_cost_per_meter *
        grid_mv_line_maintenance_cost_per_year_as_percent_of_raw_cost /
        100.,  # noqa
        'replacement_cost_per_meter_per_year':
        divide_safely(raw_cost_per_meter + installation_cost_per_meter,
                      grid_mv_line_lifetime_in_years,
                      ExpectedPositive('grid_mv_line_lifetime_in_years')),
    }
def estimate_fuel_cost(consumption_in_kwh_by_year,
                       system_loss_as_percent_of_total_production,
                       generator_actual_system_capacity_in_kw,
                       generator_minimum_hours_of_production_per_year,
                       generator_fuel_liters_consumed_per_kwh,
                       fuel_cost_per_liter):
    production_in_kwh_by_year = adjust_for_losses(
        consumption_in_kwh_by_year, system_loss_as_percent_of_total_production)
    desired_hours_of_production_by_year = divide_safely(
        production_in_kwh_by_year, generator_actual_system_capacity_in_kw,
        float('inf'))
    years = production_in_kwh_by_year.index
    minimum_hours_of_production_by_year = Series([
        generator_minimum_hours_of_production_per_year,
    ] * len(years),
                                                 index=years)
    hours_of_production_by_year = DataFrame({
        'desired':
        desired_hours_of_production_by_year,
        'minimum':
        minimum_hours_of_production_by_year,
    }).max(axis=1)
    fuel_cost_by_year = fuel_cost_per_liter * \
        generator_fuel_liters_consumed_per_kwh * \
        generator_actual_system_capacity_in_kw * \
        hours_of_production_by_year
    d = {}
    # Add yearly values
    d['hours_of_production_by_year'] = hours_of_production_by_year
    d['fuel_cost_by_year'] = fuel_cost_by_year
    d['electricity_production_in_kwh_by_year'] = production_in_kwh_by_year
    # Add final values
    d['final_hours_of_production_per_year'] = get_final_value(
        hours_of_production_by_year)
    d['final_fuel_cost_per_year'] = get_final_value(fuel_cost_by_year)
    d['final_electricity_production_in_kwh_per_year'] = get_final_value(
        production_in_kwh_by_year)
    return d
def prepare_system_capacity_cost(
        option_table, capacity_column, desired_system_capacity):
    t = option_table.copy()
    t['raw_cost_per_unit_capacity'] = t['raw_cost'] / t[capacity_column]
    x = interpolate_values(t, capacity_column, desired_system_capacity)

    minimum_system_capacity = t[capacity_column].min()
    actual_system_capacity = max(
        desired_system_capacity, minimum_system_capacity)

    # Extrapolate
    raw_cost = actual_system_capacity * x['raw_cost_per_unit_capacity']
    installation_cost = raw_cost * x[
        'installation_cost_as_percent_of_raw_cost'] / 100.
    return {
        'actual_system_' + capacity_column: actual_system_capacity,
        'raw_cost': raw_cost,
        'installation_cost': installation_cost,
        'maintenance_cost_per_year': raw_cost * x[
            'maintenance_cost_per_year_as_percent_of_raw_cost'] / 100.,
        'replacement_cost_per_year': divide_safely(
            raw_cost + installation_cost, x['lifetime_in_years'],
            ExpectedPositive('lifetime_in_years')),
    }
def adjust_for_losses(x, *loss_percents):
    y = x
    for loss_percent in loss_percents:
        loss_fraction = loss_percent / 100.
        y = divide_safely(y, 1 - loss_fraction, 0)
    return y
Exemple #14
0
def estimate_proposed_cost_per_connection(proposed_technology,
                                          final_connection_count, **keywords):
    proposed_cost_per_connection = divide_safely(
        keywords.get(proposed_technology + '_local_discounted_cost', 0),
        final_connection_count, 0)
    return {'proposed_cost_per_connection': proposed_cost_per_connection}