Introduction The transition to a green economy is accelerating globally, with a significant focus on expanding solar photovoltaic (PV) installations to meet the rising demand for renewable energy. This memo presents an analysis of the projected global supply and demand for solar PVs up to the year 2050, based on different policy and utilization scenarios. These include the Current Stated Policies Scenario, Net Zero Emission by 2050 Scenario, and 100% Solar Power Utilization Scenario.
Supply and Demand Dynamics Data analysis from various sources indicates a potential oversupply of solar PVs in the short term due to rapid advancements in technology and manufacturing capacity. However, as global electricity demand grows, driven by policies aimed at reducing carbon emissions and increasing the use of renewable energy, the demand for solar PVs is expected to rise sharply. Our projections show that by 2050, under all scenarios, the demand for solar PVs will significantly outstrip current supply capabilities, particularly in the Net Zero Emission scenario.
Scenario-Specific Demand
Current Stated Policies Scenario: This scenario projects a moderate increase in solar PV demand, aligned with current government policies and commitments. It suggests a steady growth in solar PV installations, sufficient to meet the rising electricity demands without drastic changes in policy.
Net Zero Emission by 2050 Scenario: Under this scenario, there is a substantial increase in demand for solar PVs, as it aims for a rapid and significant reduction in carbon emissions. This scenario requires aggressive policy shifts towards renewable energy, dramatically increasing solar PV installations.
100% Solar Power Utilization Scenario: This is the most ambitious scenario, assuming a complete shift to solar energy for electricity generation by 2050. It would require an unprecedented scale of solar PV production and installation, far beyond current capacities and planned expansions.
Supply Challenges and Opportunities The projected increase in demand highlights significant challenges in the supply chain for solar PVs. These include raw material sourcing, manufacturing capacity, technological advancements, and logistics. To address these challenges, strategic investments are needed in technology research, capacity building, and global supply chain optimization. Additionally, policies facilitating international cooperation and trade in renewable energy technologies will be crucial.
Policy Recommendations
Enhance Support for Solar PV Manufacturing: Governments should consider subsidies, grants, and tax incentives to encourage the establishment and expansion of solar PV manufacturing facilities.
Invest in Research and Development: Increasing the efficiency of solar PVs and reducing their production costs through continuous technological innovation is essential.
Develop International Supply Chains: Strengthening international cooperation on renewable energy resources can mitigate supply risks and stabilize prices.
Implement Progressive Energy Policies: Policies that progressively increase the adoption of solar power, such as feed-in tariffs and renewable portfolio standards, should be expanded to support the scenarios where higher solar PV demand is projected.
Conclusion Our analysis underscores the critical role of policy frameworks in shaping the future landscape of solar PV supply and demand. By aligning policies with the ambitious goals of the Net Zero Emission and 100% Solar Power Utilization Scenarios, we can ensure a sustainable and resilient energy future. It is imperative for policymakers to consider these findings and act accordingly to meet the challenges and capitalize on the opportunities presented by the global shift to renewable energy.
library("esquisse")
Warning: package 'esquisse' was built under R version 4.2.3
library(tidyverse)
Warning: package 'tidyr' was built under R version 4.2.3
Warning: package 'readr' was built under R version 4.2.3
Warning: package 'dplyr' was built under R version 4.2.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ ggplot2 3.4.4 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.1
✔ purrr 1.0.1
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(scales)
Warning: package 'scales' was built under R version 4.2.3
Attaching package: 'scales'
The following object is masked from 'package:purrr':
discard
The following object is masked from 'package:readr':
col_factor
Warning: package 'fmsb' was built under R version 4.2.3
library(shiny)
Warning: package 'shiny' was built under R version 4.2.3
library(plotly)
Warning: package 'plotly' was built under R version 4.2.3
Attaching package: 'plotly'
The following object is masked from 'package:ggplot2':
last_plot
The following object is masked from 'package:stats':
filter
The following object is masked from 'package:graphics':
layout
library(sf)
Warning: package 'sf' was built under R version 4.2.3
Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
setwd("~/Desktop/Sus Fin App & Meth/Sus Fin Final/00_data_raw")global_PV_production_2000_2022 <-read_excel("statistic_id668764_global-module-manufacturing-production-2000-2022.xlsx",sheet ="Data", col_names =FALSE)
New names:
• `` -> `...1`
• `` -> `...2`
global_PV_production_2000_2022 <- global_PV_production_2000_2022%>%rename(year =1, production =2)global_PV_production_2000_2022$year <-as.numeric(as.character(global_PV_production_2000_2022$year))global_PV_production_2000_2022$production <- global_PV_production_2000_2022$production /1000# Convert to gigawattsglobal_PV_production_2000_2022$year <-as.numeric(global_PV_production_2000_2022$year) # Ensure year is numeric
############# SOLAR PV LINEAR ############### Fit a linear model to the adjusted datalinear_model <-lm(production ~ year, data = global_PV_production_2000_2022)# Create a dataframe for predictions, from the year after the last year in the dataset to 2050future_years <-data.frame(year =seq(from =max(global_PV_production_2000_2022$year) +1, to =2050, by =1))# Predict future production values using the linear model and add them to the dataframefuture_years$production <-predict(linear_model, newdata = future_years)# Combine the original and predicted datacombined_data <-rbind(global_PV_production_2000_2022, future_years)# Create a continuous line data from 2000 to 2050 based on the linear model for the trend linetrend_data <-data.frame(year =seq(min(global_PV_production_2000_2022$year), to =2050, by =1))trend_data$production <-predict(linear_model, newdata = trend_data)# Find the production value for 2022value_2022_gw <- global_PV_production_2000_2022 %>%filter(year ==2022) %>%pull(production) # This should already be in gigawatts due to the previous conversion# Plot the data and the projectionggplot(combined_data, aes(x = year, y = production)) +geom_col(data = global_PV_production_2000_2022, fill ="darkgreen", show.legend =FALSE) +geom_col(data = future_years, fill ="lightgreen", show.legend =FALSE) +geom_line(data = trend_data, aes(group =1), color ="red", linetype ="dashed") +geom_text(data =subset(combined_data, year ==2022), aes(label = scales::comma(production)), vjust =-0.5, hjust =0.5, color ="black") +labs(title ="Global PV Production from 2000 to 2050",subtitle ="Total production measured annually with linear projection to 2050",x ="Year",y ="Production (in gigawatts)" ) +theme_minimal(base_size =14) +theme(plot.title =element_text(face ="bold", hjust =0.5),plot.subtitle =element_text(hjust =0.5),axis.title =element_text(face ="bold"),axis.text =element_text(color ="#112446"),axis.text.x =element_text(angle =45, hjust =1),axis.title.x =element_text(vjust =-0.2),axis.title.y =element_text(vjust =2),panel.grid.major.x =element_blank(),panel.grid.minor.x =element_blank() )
####### SOLAR PV POLYNOMIAL PRODUCTION ##########3model <-lm(production ~poly(year, 3), data = global_PV_production_2000_2022)# Create a dataframe for predictions, from the year after the last year in the dataset to 2050future_years <-data.frame(year =seq(from =max(global_PV_production_2000_2022$year) +1, to =2050, by =1))# Predict future production values using the polynomial model and add them to the dataframefuture_years$production <-predict(model, newdata = future_years) # Convert predictions to gigawatts# Combine the original and predicted datacombined_data <-rbind(global_PV_production_2000_2022, future_years)# Create a continuous line data from 2000 to 2050 based on the model for the trend linetrend_data <-data.frame(year =seq(min(global_PV_production_2000_2022$year), to =2050, by =1))trend_data$production <-predict(model, newdata = trend_data) # Convert trend predictions to gigawatts# Find the production value for 2022 and convert it to gigawattsvalue_2022_gw <- global_PV_production_2000_2022 %>%filter(year ==2022) %>%pull(production) # This should already be in gigawatts due to the previous conversion# Plot the data and the projectionsolar_poly <-ggplot(combined_data, aes(x = year, y = production)) +geom_col(data = global_PV_production_2000_2022, fill ="darkgreen", show.legend =FALSE) +geom_col(data = future_years, fill ="lightgreen", show.legend =FALSE) +geom_line(data = trend_data, aes(group =1), color ="red", linetype ="dashed") +geom_text(data =subset(combined_data, year ==2022), aes(label = scales::comma(production)), vjust =-0.5, hjust =0.5, color ="black") +labs(title ="Global PV Production from 2000 to 2050",subtitle ="Total production measured annually with projection to 2050",x ="Year",y ="Production (in gigawatts)" ) +theme_minimal(base_size =14) +theme(plot.title =element_text(face ="bold", hjust =0.5),plot.subtitle =element_text(hjust =0.5),axis.title =element_text(face ="bold"),axis.text =element_text(color ="#112446"),axis.text.x =element_text(angle =45, hjust =1),axis.title.x =element_text(vjust =-0.2),axis.title.y =element_text(vjust =2),panel.grid.major.x =element_blank(),panel.grid.minor.x =element_blank() )print(solar_poly)
wind_capacity <-read_csv("~/Desktop/Sus Fin App & Meth/Sus Fin Final/00_data_raw/cumulative-installed-wind-energy-capacity-gigawatts.csv")
Rows: 3059 Columns: 4
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (2): Entity, Code
dbl (2): Year, Wind energy capacity - GW
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Rename the fourth column to "Capacity"colnames(wind_capacity)[4] <-"Capacity"# Load necessary librarieslibrary(ggplot2)library(dplyr)# Rename the fourth column to "Capacity"colnames(wind_capacity)[4] <-"Capacity"# Prepare the datawind_capacity <- wind_capacity %>%filter(Entity =="World") %>%mutate(year =as.numeric(Year),capacity =as.numeric(Capacity) )# Create linear modellinear_model <-lm(capacity ~ year, data = wind_capacity)# Create polynomial modelpolynomial_model <-lm(capacity ~poly(year, 2), data = wind_capacity)# Predict future valuesfuture_years <-data.frame(year =seq(from =max(wind_capacity$year) +1, to =2050, by =1))future_years$capacity_linear <-predict(linear_model, newdata = future_years)future_years$capacity_polynomial <-predict(polynomial_model, newdata = future_years)# Combine original and predicted datacombined_data <-bind_rows( wind_capacity %>%select(year, capacity), future_years %>%select(year, capacity_linear, capacity_polynomial))# Create trend datatrend_data_linear <-data.frame(year =seq(min(wind_capacity$year), to =2050, by =1))trend_data_linear$Capacity <-predict(linear_model, newdata = trend_data_linear)trend_data_polynomial <-data.frame(year =seq(min(wind_capacity$year), to =2050, by =1))trend_data_polynomial$Capacity <-predict(polynomial_model, newdata = trend_data_polynomial)# Find the capacity value for 2022value_2022_gw <- wind_capacity %>%filter(year ==2022) %>%pull(capacity) # This should already be in gigawatts due to the previous conversion# Plot linear trendp1 <-ggplot(combined_data, aes(x = year, y = capacity)) +geom_col(data = wind_capacity, fill ="darkblue", show.legend =FALSE) +geom_col(data = future_years, aes(y = capacity_linear), fill ="lightblue", show.legend =FALSE) +geom_line(data = trend_data_linear, aes(y = Capacity, group =1), color ="red", linetype ="dashed") +geom_text(data =subset(combined_data, year ==2022), aes(label = scales::comma(capacity)), vjust =-0.5, hjust =0.5, color ="black") +labs(title ="Global Wind Capacity from 2000 to 2050",subtitle ="Total capacity measured annually with linear projection to 2050",x ="Year",y ="Capacity (in gigawatts)" ) +theme_minimal(base_size =14) +theme(plot.title =element_text(face ="bold", hjust =0.5),plot.subtitle =element_text(hjust =0.5),axis.title =element_text(face ="bold"),axis.text =element_text(color ="#112446"),axis.text.x =element_text(angle =45, hjust =1),axis.title.x =element_text(vjust =-0.2),axis.title.y =element_text(vjust =2),panel.grid.major.x =element_blank(),panel.grid.minor.x =element_blank() )# Plot polynomial trendp2 <-ggplot(combined_data, aes(x = year, y = capacity)) +geom_col(data = wind_capacity, fill ="darkblue", show.legend =FALSE) +geom_col(data = future_years, aes(y = capacity_polynomial), fill ="lightblue", show.legend =FALSE) +geom_line(data = trend_data_polynomial, aes(y = Capacity, group =1), color ="blue", linetype ="dashed") +geom_text(data =subset(combined_data, year ==2022), aes(label = scales::comma(capacity)), vjust =-0.5, hjust =0.5, color ="black") +labs(title ="Global Wind Capacity from 2000 to 2050",subtitle ="Total capacity measured annually with polynomial projection to 2050",x ="Year",y ="Capacity (in gigawatts)" ) +theme_minimal(base_size =14) +theme(plot.title =element_text(face ="bold", hjust =0.5),plot.subtitle =element_text(hjust =0.5),axis.title =element_text(face ="bold"),axis.text =element_text(color ="#112446"),axis.text.x =element_text(angle =45, hjust =1),axis.title.x =element_text(vjust =-0.2),axis.title.y =element_text(vjust =2),panel.grid.major.x =element_blank(),panel.grid.minor.x =element_blank() )# Print the plotsprint(p1)
print(p2)
WEO_Values_long <-read_excel("/Users/annaliceticha/WEO_Values_long")total_capacity <- WEO_Values_long %>%filter(Type =="Total", Description =="Electrical capacity", Scenario !="APS") %>%mutate(Values =as.numeric(as.character(Values)),Year =as.numeric(Year))ggplot(total_capacity, aes(x = Year, y = Values, colour = Scenario)) +geom_line() +scale_color_manual(values =c("NZE"="darkgreen", "STEPS"="red"),name ="Scenario" ) +labs(title ="Total Electrical Capacity 2000-2050",subtitle ="Comparing different scenarios until 2050",x ="Year",y ="Electrical Capacity (GW)" ) +theme_minimal() +theme(plot.title =element_text(hjust =0.5, face ="bold"),plot.subtitle =element_text(hjust =0.5),legend.title =element_text(face ="bold"),legend.position ="bottom",axis.text.x =element_text(angle =45, hjust =1),axis.title.x =element_text(vjust =-0.2),axis.title.y =element_text(vjust =2),legend.text =element_text(size =8) # Set size of legend text if necessary ) +scale_y_continuous(labels = comma) +# Format y-axis labels with commas for thousandsscale_x_continuous(breaks =seq(2000, 2050, 5)) # Ensure all years up to 2050 are covered
WEO_Values_long <-read_excel("/Users/annaliceticha/WEO_Values_long")WEO_Values_long <- WEO_Values_long %>%mutate(Year =as.numeric(Year),Values =as.numeric(Values))NZE_PV_scenario <- WEO_Values_long %>%filter(Description =="Electrical capacity") %>%filter(Scenario =="NZE") %>%filter(Type =="Solar PV")pv_values_before_2023 <- WEO_Values_long %>%filter(Year <2023& Scenario =="NZE"& Type =="Solar PV"& Description =="Electrical capacity")# Filter for year 2050 with "Total" Typetotal_value_2050 <- WEO_Values_long %>%filter(Year ==2050& Scenario =="NZE"& Type =="Total"& Description =="Electrical capacity")# Combine the two dataframesfull_PV_scenario <-bind_rows(pv_values_before_2023, total_value_2050) %>%mutate(Scenario ="Full Solar")STEPS_PV_scenario <- WEO_Values_long %>%filter(Description =="Electrical capacity") %>%filter(Scenario =="STEPS") %>%filter(Type =="Solar PV")all_solar_scenarios <-bind_rows( full_PV_scenario, NZE_PV_scenario, STEPS_PV_scenario)pv_values_before_2023 <- WEO_Values_long %>%filter(Year <2023& Scenario =="NZE"& Type =="Wind"& Description =="Electrical capacity")# Combine the two dataframesfull_Wind_scenario <-bind_rows(pv_values_before_2023, total_value_2050) %>%mutate(Scenario ="Full Wind")NZE_Wind_scenario <- WEO_Values_long %>%filter(Description =="Electrical capacity") %>%filter(Scenario =="NZE") %>%filter(Type =="Wind")STEPS_Wind_scenario <- WEO_Values_long %>%filter(Description =="Electrical capacity") %>%filter(Scenario =="STEPS") %>%filter(Type =="Wind")all_Wind_scenarios <-bind_rows( full_Wind_scenario, NZE_Wind_scenario, STEPS_Wind_scenario)space_format <-function() {function(x) {format(x, big.mark =" ", scientific =FALSE, trim =TRUE) }}solar_scenarios_plot <-ggplot(all_solar_scenarios, aes(x = Year, y = Values, color = Scenario)) +geom_line() +scale_color_manual(values =c("Full Solar"="orange", "NZE"="darkgreen", "STEPS"="red")) +labs(title ="Solar Capacity by Scenario 2010-2050",x ="Year",y ="Electrical Capacity in GW" ) +theme_minimal() +scale_y_continuous(labels =space_format())wind_scenarios_plot <-ggplot(all_Wind_scenarios, aes(x = Year, y = Values, color = Scenario)) +geom_line() +scale_color_manual(values =c("Full Wind"="blue", "NZE"="darkgreen", "STEPS"="red")) +labs(title ="Wind Capacity by Scenario 2010-2050",x ="Year",y ="Electrical Capacity in GW" ) +theme_minimal() +scale_y_continuous(labels =space_format())print(solar_scenarios_plot)
print(wind_scenarios_plot)
Crossover between Supply and Demand
avg_solar_scenarios <- all_solar_scenarios %>%arrange(Scenario, Year) %>%group_by(Scenario) %>%summarize(Value_2022 =sum(Values[Year ==2022]),Value_2050 =sum(Values[Year ==2050]),AverageYearlyIncrease = (Value_2050 - Value_2022) / (2050-2022) ) %>%ungroup()avg_Wind_scenarios <- all_Wind_scenarios %>%arrange(Scenario, Year) %>%group_by(Scenario) %>%summarize(Value_2022 =sum(Values[Year ==2022]),Value_2050 =sum(Values[Year ==2050]),AverageYearlyIncrease = (Value_2050 - Value_2022) / (2050-2022) ) %>%ungroup()avg_increase_plot <-ggplot(avg_solar_scenarios, aes(x = Scenario, y = AverageYearlyIncrease, fill = Scenario)) +geom_col() +# geom_col is used for plotting the bar plot for pre-summarised datalabs(title ="Average Yearly Increase in Capacity by Scenario",x ="Scenario",y ="Average Yearly Increase (GW)" ) +theme_minimal() +scale_fill_manual(values =c("Full Solar"="orange", "NZE"="darkgreen", "STEPS"="red")) # Manually setting the fill colorprint(avg_increase_plot)
scenario_summary <-data.frame(Scenario =c("Full Solar", "NZE", "STEPS"),Value_2022 =c(1144.88, 1144.88, 1144.88),Value_2050 =c(36956.46, 18753.48, 12639.19))# Calculate the exponential annual growth ratescenario_summary <- scenario_summary %>%mutate(GrowthRate = (Value_2050 / Value_2022)^(1/ (2050-2022)) -1 )# Now create a new dataframe to hold the yearly values for each scenarioyears <-2022:2050yearly_values <-expand.grid(Year = years, Scenario = scenario_summary$Scenario) %>%mutate(Value_2022 =rep(scenario_summary$Value_2022, each =length(years)),GrowthRate =rep(scenario_summary$GrowthRate, each =length(years)),Values = Value_2022 * ((1+ GrowthRate)^(Year -2022)) )# Select only the columns you needyearly_values <-select(yearly_values, Scenario, Year, Values)ggplot(yearly_values, aes(x = Year, y = Values, color = Scenario)) +geom_line() +labs(title ="Projected Electrical Capacity with Exponential Growth",x ="Year", y ="Electrical Capacity (GW)") +theme_minimal()
all_solar_scenarios <- all_solar_scenarios %>%arrange(Scenario, Year) %>%group_by(Scenario) %>%mutate(YearlyIncrease =c(NA, diff(Values)))# Plot the yearly increase for each scenarioggplot(data = all_solar_scenarios, aes(x = Year, y = YearlyIncrease, color = Scenario, group = Scenario)) +geom_line() +# Add lines to connect pointsgeom_point() +# Add points for each yearlabs(title ="Yearly Increase in Solar PV Capacity for Different Scenarios",x ="Year",y ="Yearly Increase (GW)",color ="Scenario") +theme_minimal() # Use a minimal theme
library(broom)# Calculate the linear models for each scenariomodels <- all_solar_scenarios %>%group_by(Scenario) %>%do(model =lm(Values ~ Year, data = .))# Create a data frame with all the years we want to predictyears_to_predict <-data.frame(Year =min(all_solar_scenarios$Year):max(all_solar_scenarios$Year))# Predict the values using the models for each scenariopredictions <-bind_rows(lapply(1:nrow(models), function(i) {data.frame(Scenario = models$Scenario[i],augment(models$model[[i]], newdata = years_to_predict))})) %>%select(Scenario, Year, .fitted) %>%rename(Values = .fitted)# Plot the predicted valuesggplot(predictions, aes(x = Year, y = Values, color = Scenario)) +geom_line() +# Lines for the trendsgeom_point(data = all_solar_scenarios, aes(x = Year, y = Values)) +# Actual data pointslabs(title ="Interpolated Yearly Solar PV Capacity Growth",x ="Year",y ="Predicted Electrical Capacity (GW)",color ="Scenario") +theme_minimal() # Minimal theme for the plot
scenario_summary <-data.frame(Scenario =c("Full Solar", "NZE", "STEPS"),Value_2022 =c(1144.88, 1144.88, 1144.88),Value_2050 =c(36956.46, 18753.48, 12639.19))# Calculate the exponential annual growth ratescenario_summary <- scenario_summary %>%mutate(GrowthRate = (Value_2050 / Value_2022)^(1/ (2050-2022)) -1 )# Now create a new dataframe to hold the yearly values for each scenarioyears <-2022:2050yearly_values <-expand.grid(Year = years, Scenario = scenario_summary$Scenario)# Join the data with the growth rates and base valueyearly_values <-left_join(yearly_values, scenario_summary, by ="Scenario")# Calculate the yearly values with exponential growthyearly_values <- yearly_values %>%mutate(TotalCapacity = Value_2022 * ((1+ GrowthRate)^(Year -2022)),PreviousYearCapacity =if_else(Year ==min(years), Value_2022, Value_2022 * ((1+ GrowthRate)^((Year -1) -2022))) ) %>%mutate(YearlyIncrease = TotalCapacity - PreviousYearCapacity )# Select only the columns you needyearly_values <-select(yearly_values, Scenario, Year, YearlyIncrease)# Plot the yearly increasesggplot(yearly_values, aes(x = Year, y = YearlyIncrease, color = Scenario)) +geom_line() +labs(title ="Yearly Increases in Electrical Capacity with Exponential Growth",x ="Year", y ="Yearly Increase in Electrical Capacity (GW)") +theme_minimal()