Climate impact of a gas furnace vs. heat pump
I am investigating the potential climate impact of switching from a gas furnace to an electric heat pump in my home in Bozeman, Montana. Heat pumps are one of the climate solutions heavily subsided by the Inflation Reduction Act, with a tax credit of up to $2,000 for any installation in 2023 or later, as well as an upfront discount of up to $8,000 depending on your income level, which will be available once the program is up and running at the state level. More info can be found at Rewiring America.
How a gas furnace warms the planet
A gas furnace delivers heat by combusting methane gas, a process which releases carbon dioxide into the atmosphere. In addition, there are methane leaks throughout the lifecycle of extraction, transporation, and use. The EPA estimates the leak percentages at 1.4%, but a newer study in Science puts the number at 2.3%. This is particularly significant because methane is over 80 times more impactful at warming the planet over 20 years than CO2. More info available in this PBS article.
Emissions impact from heat pumps
Heat pumps rely on electricity to transfer heat from outdoors into your home. It's possible to do this even if it is colder outside than inside, although they fail at low temperatures, which vary signficantly by model. Since they are transferring rather than generating heat, they are able to be up to about 4 times more efficient than resistive electric heat.
If your electricity is completely renewable on a 24/7 basis, then marginal carbon emissions are minimal. However, that is not currently the state on the grid anywhere in the United States.
So, given the current carbon emissions from electricity in Montana, is there an immediate climate benefit to switching to a heat pump now? (Or alternatively, does the climate benefit only appear in a future scenario with greater renewable energy powering the grid?)
Exploratory Analysis
To investigate this question, I will first do some exploratory analysis to see:
- How is electricity generated in Montana?
- How much CO2 is emitted through electricity generation?
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import requests
import datetime as dt# Create functions for later use
# Get first date of the month
def get_first_date_of_month(year, month):
"""Return the first date of the month.
Args:
year (int): Year
month (int): Month
Returns:
date (datetime): First date of the current month
"""
first_date = dt.datetime(year, month, 1)
return first_date.strftime("%Y-%m-%d")
# Get last date of the month
def get_last_date_of_month(year, month):
"""Return the last date of the month.
Args:
year (int): Year, i.e. 2022
month (int): Month, i.e. 1 for January
Returns:
date (datetime): Last date of the current month
"""
if month == 12:
last_date = dt.datetime(year, month, 31)
else:
last_date = dt.datetime(year, month + 1, 1) + dt.timedelta(days=-1)
return last_date.strftime("%Y-%m-%d")# Instantiate Dataframe
fuels = pd.DataFrame()
# Set base_url for API
base_url = 'https://api.eia.gov/v2/electricity/rto/fuel-type-data/data/?api_key=7GJ2r5mQsp8zCMzZRUdgX16Vi03YCoJhIDLu4pIN&frequency=hourly&data[0]=value&sort[0][column]=period&sort[0][direction]=desc&offset=0&length=5000&facets[respondent][]=NWMT'
# Get data from each month and compile into DataFrame
for i in range(1,13):
first_day = get_first_date_of_month(2022, i)
last_day = get_last_date_of_month(2022, i)
timeline = '&start=' + first_day + '&end=' + last_day + 'T23'
full_url = base_url + timeline
r = requests.get(full_url)
fuel_json_data = r.json()
temp_fuels = pd.DataFrame.from_dict(fuel_json_data)
temp_fuels = pd.DataFrame(temp_fuels.loc['data', 'response'])
fuels = pd.concat([fuels,temp_fuels], axis=0)
# Fix datatypes
fuels['value'] = fuels['value'].astype('int64')
fuels['period'] = pd.to_datetime(fuels['period'])# Plot electricity produced by fuel type
fig, ax = plt.subplots()
sns.lineplot(data=fuels, y='value', x='period', hue='type-name')
plt.xticks(rotation=90)
ax.set(ylabel="Megawatthours", xlabel='Time', title = "Electricity Produced by Fuel Type by NWMT")
plt.show()fuel_pct = fuels.groupby('type-name')['value'].sum()/fuels.value.sum()
plt.pie(fuel_pct, labels=fuel_pct.index, autopct='%.0f%%')
plt.title('Fuel Type Breakdown')
plt.show()Electricity production in NWMT Balancing Authority
Looking at the data in the graph above for 2022, Coal produced 64% of the electricity in total, with only ~29% from renewable sources.
Variability of production
Hydro power was relatively stable, with wind extremely variable ranging from about 0 to about 400 MWh. Coal varied between two levels, usually producing around 800 MWh or 1600 MWh. Presumably a plant is selectively activated depending on the electricity demand. Natural gas production varied in a smaller range, presumably due to controlled variation to meet demand. Solar production was minimal.
# Store constant values for use in calculating CO2 emissions
# Pounds of CO2 emitted per kWh produced for various fuel types
# Source: https://www.eia.gov/tools/faqs/faq.php?id=74&t=11
CO2_by_fuel_type = {}
CO2_by_fuel_type['Solar'] = 0
CO2_by_fuel_type['Petroleum'] = 2.44
CO2_by_fuel_type['Hydro'] = 0
CO2_by_fuel_type['Natural gas'] = .97
CO2_by_fuel_type['Coal'] = 2.26
CO2_by_fuel_type['Wind'] = 0
# Line losses in NWPP subregion
# Source: 5.3% line losses: https://www.epa.gov/egrid/power-profiler#/NWPP
line_loss = .053
# Cost for electricity, in dollars
# Source: personal bill
cost_per_kwh = 0.12
# Cost per Therm of methane gas, in dollars
# Source: personal bill
cost_per_therm = 1.00
# Conversions
# Source for pounds conversions: https://www.rapidtables.com/convert/weight/ton-to-pound.html
# Source for btus: https://www.eia.gov/energyexplained/units-and-calculators/british-thermal-units.php
# Source for CO2_from_gas: https://www.epa.gov/energy/greenhouse-gases-equivalencies-calculator-calculations-and-references
pounds_per_metric_ton = 2204.6226218
pounds_per_kg = 2.204623
btus_per_kwh = 3412
btus_per_therm = 100000
btus_per_cord_wood = 20000000
CO2_per_cord_kg = 116.15*20 # Source: 116.15 kg/MMBTU, 20 MMBTU/cord
CO2_per_cord_lbs = CO2_per_cord_kg * pounds_per_kg
btus_per_gallon_propane = 91452
btus_per_gallon_heating_oil = 138500
btus_per_barrel_oil = 5800000
CO2_from_barrel_oil_metric_tons = .43
CO2_from_barrel_oil_lbs = CO2_from_barrel_oil_metric_tons * pounds_per_metric_ton
CO2_from_gas_metric_tons = 0.0053
CO2_from_gas_lbs = CO2_from_gas_metric_tons * pounds_per_metric_ton
CO2_from_gallon_gasoline_metric_tons = .008887
CO2_from_gallon_gasoline_lbs = CO2_from_gallon_gasoline_metric_tons * pounds_per_metric_ton
# Set furnace efficiency
# Source: Estimate of current efficiency from HVAC technician of my particular furnace model
# Wood stove source: https://www.fs.usda.gov/Internet/FSE_DOCUMENTS/fsbdev3_035113.pdf
furnace_efficiency = .90
wood_stove_efficiency = .50
oil_furnace_efficiency = .80
# Social cost of carbon
# According to middle value in EPA proposal 2022
# Source: https://www.americanenergyalliance.org/2022/11/bidens-epa-reveals-astronomical-social-cost-of-carbon-proposal/
social_cost_CO2_metric_ton = 190.00
social_cost_CO2_lbs = social_cost_CO2_metric_ton/pounds_per_metric_ton# Pull in average CO2 emissions per MWh produced
fuels['CO2_factor'] = fuels['type-name'].map(CO2_by_fuel_type)
# Calculate CO2 emissions
fuels['CO2_emissions'] = fuels['value']*1000 * fuels['CO2_factor']
# Adjust due to line loss
fuels['CO2_emissions'] = fuels['CO2_emissions']/(1 - line_loss)
# Calculate hourly values
hourly_emissions = pd.DataFrame()
hourly_emissions['CO2_emissions'] = fuels.groupby('period')['CO2_emissions'].sum()
hourly_emissions['MWh_produced'] = fuels.groupby('period')['value'].sum()
hourly_emissions['emissions_per_MWh'] = hourly_emissions['CO2_emissions']/hourly_emissions['MWh_produced']
hourly_emissionsRelation of CO2 emissions and electricity production
As you can see in the graph above, emissions (in blue) rise and fall similarly with overall electricity generation (in grey). This is generally to be expected, as the bulk of production is from non-renewable sources. However, there is not an exact match because the renewable percentage of production varies over time.
As you can see in the graph below, CO2 emissions per MWh produced varies throughout the period, typically falling between 1000 pounds and 1800 pounds. The emissions from relying solely on coal, methane gas, or renewables are shown as comparison points. The emissions for this period were typically above that from relying solely on methane gas, and much lower than pure coal and much higher than pure renewables.
# Calculate percentage of power that was renewable
gen_pct = pd.DataFrame()
gen_pct['total'] = fuels.groupby('type-name')['value'].sum()
gen_pct['pct'] = gen_pct['total']/fuels['value'].sum()*100
renewables = ['Hydro', 'Solar', 'Wind']
gen_pct['renewable'] = 0
for x in renewables:
gen_pct.loc[x,'renewable'] = 1
print(f'Total MWh generated: {gen_pct.total.sum()}')
pct_renewable = gen_pct.groupby('renewable').pct.sum()[1]
print(f'Percentage of electricity that was renewable: {np.round(pct_renewable*100)/100}%')