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 = Series(0, index=population_by_year.index) consumption_by_year = Series(0, index=population_by_year.index) estimated_household_connection_count_by_year = divide_safely( population_by_year, number_of_people_per_household, 0) 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})
def estimate_battery_cost( panel_actual_system_capacity_in_kw, battery_kwh_per_panel_kw, battery_raw_cost_per_battery_kwh, battery_installation_cost_as_percent_of_raw_cost, battery_maintenance_cost_per_year_as_percent_of_raw_cost, battery_lifetime_in_years): storage_in_kwh = panel_actual_system_capacity_in_kw * \ battery_kwh_per_panel_kw raw_cost = storage_in_kwh * \ battery_raw_cost_per_battery_kwh installation_cost = raw_cost * \ battery_installation_cost_as_percent_of_raw_cost / 100. maintenance_cost_per_year = raw_cost * \ battery_maintenance_cost_per_year_as_percent_of_raw_cost / 100. replacement_cost_per_year = divide_safely( raw_cost + installation_cost, battery_lifetime_in_years, ExpectedPositive('battery_lifetime_in_years')) return { 'storage_in_kwh': storage_in_kwh, 'raw_cost': raw_cost, 'installation_cost': installation_cost, 'maintenance_cost_per_year': maintenance_cost_per_year, 'replacement_cost_per_year': replacement_cost_per_year, }
def estimate_lv_line_cost( final_connection_count, line_length_adjustment_factor, average_distance_between_buildings_in_meters, lv_line_raw_cost_per_meter, lv_line_installation_cost_as_percent_of_raw_cost, lv_line_maintenance_cost_per_year_as_percent_of_raw_cost, lv_line_lifetime_in_years): # TODO: Compute lv line cost by year as connections come online line_length_in_meters = average_distance_between_buildings_in_meters * ( final_connection_count - 1) * line_length_adjustment_factor raw_cost = line_length_in_meters * \ lv_line_raw_cost_per_meter installation_cost = raw_cost * \ lv_line_installation_cost_as_percent_of_raw_cost / 100. maintenance_cost_per_year = raw_cost * \ lv_line_maintenance_cost_per_year_as_percent_of_raw_cost / 100. replacement_cost_per_year = divide_safely( raw_cost + installation_cost, lv_line_lifetime_in_years, ExpectedPositive('lv_line_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, }
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_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}
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, }
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_peak_demand( final_consumption_in_kwh_per_year, consumption_during_peak_hours_as_percent_of_total_consumption, peak_hours_of_consumption_per_year): final_consumption_during_peak_hours_in_kwh_per_year = \ final_consumption_in_kwh_per_year * \ consumption_during_peak_hours_as_percent_of_total_consumption / 100. # noqa # Choose to estimate peak demand by averaging kw over peak hours peak_demand_in_kw = divide_safely( final_consumption_during_peak_hours_in_kwh_per_year, peak_hours_of_consumption_per_year, ExpectedPositive('peak_hours_of_consumption_per_year')) return { 'peak_demand_in_kw': peak_demand_in_kw, }
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}
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_lv_connection_cost( final_connection_count, lv_connection_raw_cost, lv_connection_installation_cost_as_percent_of_raw_cost, lv_connection_maintenance_cost_per_year_as_percent_of_raw_cost, lv_connection_lifetime_in_years): # TODO: Compute lv connection cost by year as connections come online raw_cost = final_connection_count * \ lv_connection_raw_cost installation_cost = raw_cost * \ lv_connection_installation_cost_as_percent_of_raw_cost / 100. maintenance_cost_per_year = raw_cost * \ lv_connection_maintenance_cost_per_year_as_percent_of_raw_cost / 100. replacement_cost_per_year = divide_safely( raw_cost + installation_cost, lv_connection_lifetime_in_years, ExpectedPositive('lv_connection_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, }
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 xrange(min(graph), max(graph)): for node2_id in xrange(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), ]
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 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}