library(tidyverse) library(scales) library(fixest) #### OUTPUT_DIR <- './Results/Tables_and_Figures/' dir.create(OUTPUT_DIR,recursive=TRUE,showWarnings=FALSE) ##########################Direct cost estimates TOTAL_COMPUTER_CAPITAL_INVEST <- 1156875000/10^6 #Total "Computer" capital cost in terms of millions of dollars #Split of spending at data centers https://jlarc.virginia.gov/pdfs/reports/Rpt598.pdf BUILDING <- 0.196 COMPUTERS <- 0.682 OTHER <- 0.061 LAND <- 0.061 TOTAL <- (BUILDING+COMPUTERS+OTHER) #Adjust assuming that land is not included in the total capital costs BUILDING <- BUILDING/TOTAL COMPUTERS <- COMPUTERS/TOTAL OTHER <- OTHER/TOTAL #Cost in each category BUILDING <- BUILDING*TOTAL_COMPUTER_CAPITAL_INVEST COMPUTERS <- COMPUTERS*TOTAL_COMPUTER_CAPITAL_INVEST OTHER <- OTHER*TOTAL_COMPUTER_CAPITAL_INVEST SCHEDULE <- c(250,500,250,500)#Data Center capacity schedule #Assume half of all capital is spent a year before opening CAPITAL_SCHEDULE_EST <- c(250,500,250,500,0)/2 + c(0,250,500,250,500)/2 CAPITAL_SCHEDULE_EST<- CAPITAL_SCHEDULE_EST/sum(SCHEDULE) BUILDING <- BUILDING*CAPITAL_SCHEDULE_EST #Output of construction industry COMPUTERS <- COMPUTERS*CAPITAL_SCHEDULE_EST #Purchases of Computers sum(COMPUTERS ) OTHER <- OTHER*CAPITAL_SCHEDULE_EST #Other purchases DOLLAR_VALUES <- cbind(2029:2033,BUILDING,COMPUTERS,OTHER) %>% as_tibble colnames(DOLLAR_VALUES )[1] <- "Year" #Include Batteries BESS_COST <- 719027250/10^6 BESS_SCHEDULE <- c(0,250,500,250,500) BESS_SCHEDULE <- BESS_SCHEDULE / sum(BESS_SCHEDULE ) BESS <- BESS_SCHEDULE*BESS_COST DOLLAR_VALUES$BESS <- BESS DOLLAR_VALUES #Include gas generator costs #Reciprocation Engine costs (No construction assumed) CCG_COST <- 6165257143/10^6 RECIP_COST <- 50000000/10^6 RECIP_SCHEDULE <- c(0,640,640,0,0) RECIP_SCHEDULE <- RECIP_SCHEDULE/sum(RECIP_SCHEDULE) RECIP <- RECIP_COST*RECIP_SCHEDULE #Combined cycle costs CCG_SCHEDULE <- c(0,0,0,0,2400) DOLLARS_PER_KW <- 782 #See https://www.eia.gov/electricity/generatorcosts/index.php for the 7820 number converted from cents per kw DOLLARS_PER_MW <- DOLLARS_PER_KW*1000 MILL_DOLLARS_PER_MW <- DOLLARS_PER_MW/10^6 CCG_CONSTRUCTION_COSTS <- CCG_SCHEDULE*MILL_DOLLARS_PER_MW #DOLLAR_VALUES$CCG_COST <- CCG_CONSTRUCTION_COSTS CCG_CAPITAL_COST <- CCG_COST-CCG_CONSTRUCTION_COSTS[5] #Remove the construction cost to estimate final capital costs CCG <- CCG_CAPITAL_COST *(CCG_SCHEDULE/sum(CCG_SCHEDULE)) TURBINE <- CCG +RECIP DOLLAR_VALUES$TURBINE <- TURBINE #######################Employment estimates NAMES <- c("Trumbull Energy Center","Orange County Advanced Power Station","Shady Hills Combined Cycle Facility","Cumberland (TN)","Kingston","Lincoln Land Energy Center","Delta Blues Advanced Power Station","Homer","Vicksburg","Cheyenne Prairie","Legend and Lone Star","Wolf Summit Energy","Franklin Farms","Viola Generating Station","CPV Basin Ranch Energy Center","Smarr Combined Cycle Energy Facility","Waterford 5 & 6","Lake Charles","Jefferson Power Station") CAP <- c(308.7*2+360, 453*2+400, 612, 454.8+323, 323, 638.4*2, 477+341.7, 4678, 819.4, 132, 754+453, 600, 1560, 705, 1490, 1425, 1640, 994, 754 ) DETAILED_REPORT <- c(1,1,1,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0) EMP <- c(25,27,12.5,30,NA,34,21,250,21,12,73,30,44,30,45,30,30,30,22) PEAK_CONST <- c(920,NA,600,NA,300,500,300,2500,560,400,NA,400,(1500+1800)/2,500,1000,1200,700,1100,NA) DATE <- c(2017,2018,2018,2022,2015,2020,2024,2025,2025,2012,2024,2025,2024,2024,2026,2026,2025,2020,2025) DATA <- cbind(CAP,EMP,PEAK_CONST,DETAILED_REPORT,DATE) %>% as.matrix %>% as_tibble DATA$NAMES <- NAMES colnames(DATA ) <- c("Capacity","Emp","Peak_Const","Report_Quality","Report_Year","Plant") REG_DATA <-DATA %>% select(Emp,Capacity,Report_Quality,Report_Year) REG_DATA_TRIMMED <-DATA %>% filter(Plant!='Homer') %>% select(Emp,Capacity,Report_Quality,Report_Year) MOD1 <- feols(log(Emp)~Capacity+Report_Quality+Report_Year,REG_DATA,vcov='hetero') MOD1 feols(log(Emp)~Capacity+Report_Quality+Report_Year,REG_DATA,vcov='hetero') PRED_DATA <- DATA[1:4,] PRED_DATA$Capacity <- c(640,1280,1280,3680) PRED_DATA$Report_Year <- 2026 PRED_DATA$Plant <- 'Enyo' PRED_DATA$Emp<- NA round(exp(predict(MOD1,newdata=PRED_DATA))) #PRED_DATA$Capacity<- c(640,1280,1280,3680) #Larger number includes the single cyle turbines that look to be turned off most of the time PRED_DATA PRED_OPERATING <- round(exp(predict(MOD1,newdata=PRED_DATA))) POWER_OPERATORS <- c(0,PRED_OPERATING ) ALL_VALUES <- DOLLAR_VALUES ALL_VALUES$POWER_OPERATORS <- POWER_OPERATORS OP_PLOT <- ggplot(REG_DATA,aes(x=Capacity,y=log(Emp)))+geom_point()+geom_smooth(method='lm',color="orange")+theme_bw()+ylab("Operating Employment (Natural Log)" )+scale_x_continuous(breaks=seq(0,5000,by=200),labels = scales::comma)+scale_y_continuous(breaks=seq(0,7,by=0.25))+theme(text=element_text(size=16)) CONST_PLOT <- ggplot(DATA,aes(x=Capacity,y=Peak_Const))+geom_point()+geom_smooth(method='lm')+theme_bw()+ylab("Peak Construction Employment" )+scale_x_continuous(breaks=seq(0,5000,by=200),labels = scales::comma)+scale_y_continuous(breaks=seq(0,20000,by=200),labels = scales::comma)+theme(text=element_text(size=16)) png(paste0(OUTPUT_DIR,"Operating_Employment_Fit.png" ) , units = "in", width = 1.25*12, height = 1.25*8, res = 600) OP_PLOT dev.off() png(paste0(OUTPUT_DIR,"Peak_Construction_Employment_Fit.png" ) , units = "in", width = 1.25*12, height = 1.25*8, res = 600) CONST_PLOT dev.off() MOD2 <- feols(Peak_Const~Capacity+Report_Year+Report_Quality,DATA,vcov='hetero') #ggplot(DATA,aes(x=Capacity,y=Peak_Const))+geom_point()+geom_smooth(method='lm') DICT <- c("log(Emp)"="Operating Employment (ln)",Peak_Const="Peak Construction Employment",Report_Quality='Government Source',Report_Year='Data Year',Capacity='Capacity (MW)' ) NOTES <- c("Data found for natural gas power plants listed in EIA860 fillings as planned.","Data Year: is the date a report was released","Government Source: is a dummy variable that is one if the source of data came from a government filing and not a company report.") etable(MOD1,MOD2,style.tex=style.tex(yesNo="$\\checkmark$"),dict=DICT,notes=NOTES,file=paste0(OUTPUT_DIR,"Reg.tex") ,export=paste0(OUTPUT_DIR,"Reg.png"),replace=TRUE,tpt=TRUE,adjustbox=TRUE,order="!Constant") ###Construction Data CONST_SCHEDULE_HISTORIC <- c(45,75,90,115,175,235,285,350,400,350,255,175,95,65) #Employment by month in the most recent 2011 Wyoming application for a generator (See one drive data) PEAK_CONST_EMP_HISTORIC <- 400 #Historic peak employment rate PEAK_RATIO <- (sum(CONST_SCHEDULE_HISTORIC )/12)/PEAK_CONST_EMP_HISTORIC PEAK_RATIO #Also aligns with the 60% estimate used in the data center report on expenses PRED_DATA_CONST <- PRED_DATA PRED_DATA_CONST$Capacity <- c(640,640,0,2400) #Capacity Added in a given year CONST_EMPLOYMENT_PRED <- round(predict(MOD2,PRED_DATA_CONST)*PEAK_RATIO) CONST_EMPLOYMENT_PRED EMP_2029 <- CONST_EMPLOYMENT_PRED[1]/4 #Shift based on starting in Q4 of 2029 CONST_EMPLOYMENT_PRED CONST_EMPLOYMENT_PRED[1] <- CONST_EMPLOYMENT_PRED[1]-EMP_2029 CONST_EMPLOYMENT_PRED <- c(EMP_2029,CONST_EMPLOYMENT_PRED) CONST_EMPLOYMENT_PRED <- CONST_EMPLOYMENT_PRED[c(1:3,5,4)] #Assume the CCG is built mostly in the previous year, but single cycles are same year, based on Enyo data sheet ALL_VALUES$TURBINE_CONST_WORKERS <- CONST_EMPLOYMENT_PRED ###Data center values OPERATIONAL_EMP_COEF <- (0.15+0.2)/2 DATA_CENTER_EMP <- round(OPERATIONAL_EMP_COEF* c(0,cumsum(SCHEDULE ))) ##MW of active data center capacity times emplotyment intesity coefcient ###see(https://hamminstitute.org/site-files/documents/data_center_workforce.pdf)0/see DOLLAR_VALUES*0.8603 #Deflate dollar values to 2022 for fixed local inputs in REMI which only offers 2017 or 2022 #0.000 0.000 0.000 0.000 0.000 +67.451 +263.014 +382.987 +377.990 +304.176 +104.521 ALL_VALUES$DATA_CENTER_EMP <- DATA_CENTER_EMP TAX_EXEMPTIONS <- -1*rowSums(ALL_VALUES[,c(3,4)]*0.04/2) TAX_EXEMPTIONS ALL_VALUES %>% select(POWER_OPERATORS,TURBINE_CONST_WORKERS,DATA_CENTER_EMP) ALL_VALUES %>% select(-BUILDING,-COMPUTERS,-BESS,-DATA_CENTER_EMP,-POWER_OPERATORS,-TURBINE_CONST_WORKERS,-OTHER)