Problem 13.10#
Fundamentals of Solar Cells and Photovoltaic Systems Engineering
Solutions Manual - Chapter 13
Problem 13.10
In this problem, the economic viability of a household rooftop solar installation in Aarhus, Denmark is evaluated. To that end, hourly data will be used and can be accessed through the book repository. The file “Problem13.10_electricity_demand_and_price_data.csv” can be obtained at this book’s online repository. The data file includes:
1. hourly values of electricity demand for a household in Aarhus
2. electricity price in the wholesale electricity market for the power system DK1 [1]
3. capacity factors for a solar PV installation with optimal tilt angle and orientation in Aarhus. [2]
(a) As a first step, determine the capacity of the PV modules that must be installed so that the annual electricity generated by installation equals the household annual electricity demand.
Every hour in which the PV solar generation is lower than the demand, the energy deficit is imported from the utility power grid paying a price of 0.2924 EUR/kWh.3 Every hour in which the PV solar generation is higher than the demand, the excess energy is exported to the grid, and it is paid at the price of the wholesale market in the electricity market DK1. The installation cost for the rooftop PV system is 1243 EUR/kW. The cost of operation and maintenance (O&M) is neglected, and a discount rate of 4% is assumed.
(b) Calculate the net present value (NPV) of the installation in year 25.
(c) Calculate the year in which the initial investment will be recovered.
(d) Calculate the internal rate of return (IRR) of the investment.
(e) Aarhus municipality has decided to subsidize 20% of the cost of the installation. Repeat the sections (b)–(d) in this case.
(f) Aarhus municipality has decided to try a different strategy, and now, it does not subsidize rooftop PV installations, but it offers zero-interest loans to citizens, so it can be assumed that the discount rate is 0%. Repeat the sections (b)–(c) in this case and discuss the results.
[1] Data was obtained from Nordpoolgroup. It can be accessed at the Nordpoolgroup web by selecting “elspot-prices_2019_hourly_dkk”
[2] Data was obtained from PV-GIS, assuming a performance ratio of 86%. It can be retrieved from the webpage PVGIS selecting Aarhus on the map.
We start by importing the pandas package (useful to work with data tables) and importing the data
import pandas as pd
data=pd.read_csv('data/Problem13.10_electricity_demand_and_price_data.csv', sep=',', encoding='latin-1',
index_col=(0)) #, header=0)
data.head() #show the initial lines to check that import is working fine
Hours | Elspot Prices DK1 (EUR/MWh) | Household Demand (kWh) | Capacity factor solar | |
---|---|---|---|---|
Day | ||||
01/01/2019 | 00 - 01 | 28.39 | 0.18 | 0.0 |
01/01/2019 | 01 - 02 | 10.09 | 0.17 | 0.0 |
01/01/2019 | 02 - 03 | -4.09 | 0.20 | 0.0 |
01/01/2019 | 03 - 04 | -9.93 | 0.17 | 0.0 |
01/01/2019 | 04 - 05 | -7.43 | 0.18 | 0.0 |
(a) Determine the capacity of the PV modules that must be installed so that the annual electricity generated by them equals the annual electricity consumption.
We calculate the average capacity factor, the annual electricity consumption and the required PV capacity.
average_CF = data['Capacity factor solar'].mean()
annual_electricity_consumption = data['Household Demand (kWh)'].sum()
PV_capacity = annual_electricity_consumption / (average_CF*8760)
print('PV modules capacity = ' + str(PV_capacity.round(2)) + ' kW')
PV modules capacity = 2.85 kW
Every hour in which the PV solar generation is lower than the demand, the energy deficit is imported from the grid paying a price of 0.2924 €/kWh [3]. Every hour in which the PV solar generation is higher than the demand, the excess energy is exported to the grid and it is paid at the price of the wholesale market in the node DK1.
The installation cost for the rooftop PV system is 1,243 €/kW [4]. The cost of Operation and Maintenance (O&M) is neglected, and a discount rate of 4% is assumed.
(b) Calculate the Net Present Value (NPV) of the installation in year 25.
[3] This corresponds to the average price of electricity for consumes in Denmark in 2019 according to Eurostat
[4] This is the cost estimated for a rooftop PV installation in the report “Technology Data for Generation of Electricity and District Heating” by the Danish Energy Agency (DEA) and Energinet.dk
We start by calculating the mismatch in every hour, i.e., the difference between the PV electricity generation and demand.
mismatch = PV_capacity*data['Capacity factor solar'] - data['Household Demand (kWh)']
mismatch.tail()
Day
31/12/2019 -0.20
31/12/2019 -0.17
31/12/2019 -0.18
31/12/2019 -0.18
31/12/2019 -0.18
dtype: float64
We calculate the net cost of electricity with and without the PV installation.
market_price = data['Elspot Prices DK1 (EUR/MWh)']
electricity_cost_w_PV = -sum([mismatch_h*market_price_h/1000 if mismatch_h>0 else mismatch_h*0.2924
for mismatch_h, market_price_h in zip(mismatch, market_price)])
electricity_cost_wo_PV = annual_electricity_consumption*0.2924
print('Annual electricicy price with PV = ' + str(round(electricity_cost_w_PV, 2))+ ' €')
print('Annual electricicy price without PV = ' + str(round(electricity_cost_wo_PV, 2))+ ' €')
Annual electricicy price with PV = 464.84 €
Annual electricicy price without PV = 779.44 €
The annual savings can be calculated as
annual_savings = electricity_cost_wo_PV - electricity_cost_w_PV
print('Annual savings = ' + str(round(annual_savings, 2))+ ' €')
Annual savings = 314.6 €
We create the a series with the cash flow in every year and calculate the discounted values, assuming 25 years lifetime and discount rate \(r\)=4.0%
cash_flow=pd.Series(index=range(0,25), data=annual_savings)
cash_flow[0] -= PV_capacity*1243 # Investment cost 1243 EUR/kW
r=0.04
discounted_cash_flow = pd.Series(index=range(0,25), data=[cash_flow[y]/(1+r)**y for y in cash_flow.index])
The Net Present Value (NPV) is calculated as the sum of the discounted cash flow.
print('NPV = ' + str(round(sum(discounted_cash_flow),2))+ ' €')
NPV = 1568.47 €
(c) Calculate the year in which the initial investment will be recovered.
We calculate the cumulative discounted cash flow and see that at year 14 NPV>0, that is, the investment is recovered.
discounted_cash_flow.cumsum()
0 -3228.177113
1 -2925.680379
2 -2634.818134
3 -2355.142898
4 -2086.224402
5 -1827.648926
6 -1579.018660
7 -1339.951096
8 -1110.078439
9 -889.047038
10 -676.516845
11 -472.160889
12 -275.664779
13 -86.726211
14 94.945489
15 269.629816
16 437.595515
17 599.100995
18 754.394726
19 903.715621
20 1047.293404
21 1185.348965
22 1318.094697
23 1445.734823
24 1568.465714
dtype: float64
(d) Calculate the Internal Rate of Return (IRR) of the investment.
The IRR can be calculated at the discount rate that makes the NPV=0 at the end of the installation lifetime.
NPV = pd.Series(dtype=float)
for n in range(0, 100):
r=0.001*n
discounted_cash_flow = pd.Series(index=range(0,25), data=[cash_flow[y]/(1+r)**y for y in cash_flow.index])
NPV[r]=sum(discounted_cash_flow)
argmin=NPV.abs().argmin()
NPV.index[argmin]
print('IRR = ' + str(NPV.index[argmin]))
IRR = 0.083
(e) Aarhus municipality has decided to subsidize 20% of the cost of the installation. Repeat the sections (b)–(d) in this case.
Net Present value
cash_flow=pd.Series(index=range(0,25), data=annual_savings)
cash_flow[0] -= PV_capacity*1243*0.8 # Investment cost 1243 EUR/kW, 20% is subsidized
r=0.04
discounted_cash_flow = pd.Series(index=range(0,25), data=[cash_flow[y]/(1+r)**y for y in cash_flow.index])
print('NPV = ' + str(round(sum(discounted_cash_flow),2))+ ' €')
NPV = 2277.02 €
In this case, the investment is recoverd in 10 years.
discounted_cash_flow.cumsum()
0 -2519.622370
1 -2217.125635
2 -1926.263390
3 -1646.588155
4 -1377.669659
5 -1119.094182
6 -870.463916
7 -631.396353
8 -401.523696
9 -180.492294
10 32.037899
11 236.393854
12 432.889965
13 621.828533
14 803.500233
15 978.184560
16 1146.150259
17 1307.655739
18 1462.949469
19 1612.270364
20 1755.848147
21 1893.903708
22 2026.649440
23 2154.289567
24 2277.020458
dtype: float64
Internal Rate of Return (IRR)
NPV = pd.Series(dtype=float)
for n in range(0, 100):
r=0.001*n
discounted_cash_flow = pd.Series(index=range(0,25), data=[cash_flow[y]/(1+r)**y for y in cash_flow.index])
NPV[r]=sum(discounted_cash_flow)
argmin=NPV.abs().argmin()
NPV.index[argmin]
print('IRR = ' + str(NPV.index[argmin]))
IRR = 0.099
(f) Aarhus municipality has decided to try a different strategy, and now, it does not subsidize rooftop PV installations, but it offers zero-interest loans to citizens, so it can be assumed that the discount rate is 0%. Repeat the sections (b)–(c) in this case.
Net Present value
cash_flow=pd.Series(index=range(0,25), data=annual_savings)
cash_flow[0] -= PV_capacity*1243# Investment cost 1243 EUR/kW, 20% is subsidized
r=0
discounted_cash_flow = pd.Series(index=range(0,25), data=[cash_flow[y]/(1+r)**y for y in cash_flow.index])
print('NPV = ' + str(round(sum(discounted_cash_flow),2))+ ' €')
NPV = 4322.14 €
In this case, the investment is recoverd in 11 years.
discounted_cash_flow.cumsum()
0 -3228.177113
1 -2913.580509
2 -2598.983905
3 -2284.387301
4 -1969.790697
5 -1655.194093
6 -1340.597488
7 -1026.000884
8 -711.404280
9 -396.807676
10 -82.211072
11 232.385532
12 546.982136
13 861.578741
14 1176.175345
15 1490.771949
16 1805.368553
17 2119.965157
18 2434.561761
19 2749.158365
20 3063.754970
21 3378.351574
22 3692.948178
23 4007.544782
24 4322.141386
dtype: float64