-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCreatePLEXOSImportFile.m
2969 lines (2778 loc) · 194 KB
/
CreatePLEXOSImportFile.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%Michael Craig
%1/18/15
%This script creates an Excel file formatted for importing into PLEXOS and
%calls a separate function that creates Excel files for PLEXOS of demand
%profiles in 2030. The Excel created by this script includes generator info
%as well as demand datafile info and spatial (zone, node, regional) info.
%% PARAMETERS
%WHICH PC RUNNING ON******************************************************
%Set whether running on work or personal PC.
pc='personal' %'work' or 'personal'
%*************************************************************************
%CARBON CAPTURE AND SEQUESTRATION TOGGLES**********************************
%Capacity of CCS retrofits to add to the fleet in MW
mwccstoadd=2000 %MW
%flexibleccs toggles whether to add flexible (1) or inflexible (0) CCS
%facilities.
flexibleccs=1
%Allow / disallow venting at flexible CCS unit. (Affects venting and
%venting when charging unit.)
allowventing=0
%If not including CCS, set flexbileccs to zero
if (mwccstoadd==0) flexibleccs=0; end;
%**************************************************************************
%SOLVENT STORAGE TANK SIZE*************************************************
%Solvent storage tank size for flexible CCS. Value given is # of hours at
%full output that can be enabled by discharging stored solvent.
solventstoragesize=1;
%Set SS tank size to 0 if inflexbile CCS (since no SS)
if flexibleccs==0
solventstoragesize=0;
end
%**************************************************************************
%WIND PARAMETERS*********************************************************** **********************************
%WIND CAPACITY ADDITION
%Capacity of wind to add to base fleet
mwwindtoadd=0
%GATHER WIND AND SOLAR GENERATION PROFILES
%Often turn off wind and solar generation profile gathering as it takes a
%long time. Set toggle to 1 if want generation profiles.
gatherwindandsolarprofiles=1
%**************************************************************************
%SET HIGHER EMISSIONS REDUCTION TARGET*************************************
%Use this parameter to achieve greater emissions reductions than would be
%achieved under the CPP. The parameter scales down the mass limit set by
%the CPP. The value of this scalar is calculated in the file
%StateFactSheetsData_3Dec2015 in the Databases\Final CPP\State Fact Sheets
%folder. The default value is 0.7182 - this achieves a 50% reduction from
%2012 levels in 2030 in our region of analysis. The Clean Power Plan, on
%the other hand, achieves a 30.4% reduction. Note that this is NOT sayign
%the CPP achieves all these reductions - other factors contribute to this
%reduction. I could not find state-specific baseline 2030 emissions to
%isolate the effect of the CPP.
testlowermasslimit=1 %set to 1 if want to reduce limit, 0 if not
masslimitscalar=.7182 %.7182 is default value - see above comment.
if (testlowermasslimit==0) masslimitscalar==1; end;
%**************************************************************************
%NATURAL GAS PRICE SCENARIOS***********************************************
%Alter natural gas prices in IPM in order to run high/low NGs. Do this w/ a
%scalar to manipulate NG prices up & down.
runnatgaspricescenario=0
if runnatgaspricescenario==1
%Set scenario to run (if running one)
ngpricescenario='High' %'Low' or 'High'
%If not running scenario, set scalar to 1 (so doesn't change NG prices);
%otherwise set scalar based on scenario. Calculated scalars in Excel using
%Goal Seek (databases -> Natural Gas Price Data -> NaturalGasUnits...csv)
%such that capacity-weighted natural gas price of fleet = $3.5 or $6.5
%per MMBtu for low & high gas price scenarios, respectively. (Just a mean
%natural gas price gives essentially the same scalars.)
if (strcmp(ngpricescenario,'High')) ngpricescalar=1.21; elseif (strcmp(ngpricescenario,'Low')) ngpricescalar=0.65; end;
else
ngpricescalar=1;
end
%**************************************************************************
%CLEAN POWER PLAN PARAMETERS***********************************************
%CPP COMPLIANCE SCENARIO
%Which CPP compliance scenario parsed file to import
compliancescenario='Mass'
% compliancescenario='Base'
%DEMAND SCENARIO
%Define demand scenario for analysis
%Scenarios: 0 = base case (no extra EE relative to base case), 1 (~1%/yr EE
%savings - EE rate assumed, after ramp up, in IPM runs for final CPP)
demandscenarioforanalysis=1 %options: 0,1
%scaleenergyefficiencysavings is used to scale energy efficiency savings up
%or down depending on desired amount. Basically, when using
%demandscenarioforanalysis=1, get some EE % savings for each state; this
%scalar is multiplied into that % savings to increase/reduce % savings.
%Resulting value is then used to scale 2030 pre-EE demand up/down. Only set
%this value to increments of tenths.
scaleenergyefficiencysavings=0.5
%**************************************************************************
%CARBON PRICE CALCULATIONS*************************************************
%WHETHER TO FORCE COMPLIANCE WITH CLEAN POWER PLAN
%Following toggle controls whether you determine and include in the UCED a
%CO2 price that enforces compliance with CPP. Set this to 1 in order to
%include CO2 price. Only turn this off when running base case, i.e. no CPP.
calculatecppco2price=1
%FORCE CO2 PRICE TO CERTAIN VALUE
%Want to run some scenarios in which we force CO2 price to a certain value.
%If do this, then don't want to calculate CPP-equivalent CO2 price, but
%rather just include imposed CO2 price.
setco2pricetoinputvalue=0
co2priceinput=10 %$/ton
%Ensure that if calculate CPP-equivalent CO2 price, don't want to force CO2
%price.
if (calculatecppco2price==1) setco2pricetoinputvalue=0; end;
%Zero out input co2 price if not setting co2 price based on that value
if (setco2pricetoinputvalue==0) co2priceinput=0; end;
%**************************************************************************
%RESERVE REQUIREMENTS******************************************************
%Indicate whether to use NREL or current (2015) MISO reserve requirements.
reserverequirements='nrel' %'nrel' or 'miso'
%**************************************************************************
%RAMP RATES****************************************************************
%Two sets of ramp rates available, PHORUM or scaled PHORUM such that coal
%plants ramp at roughly ~1.5-3%/min. in agreement w/ published values. If
%variable = 1, then use scaled values; if = 0, use unscaled values. Scaled
%values are 5x PHORUM values.
usescaledramprates=1 %default=1
%**************************************************************************
%FLEET COMPRESSION*********************************************************
%Following parameters are used to shrink the size of the optimization to
%improve computational tractability when adding flex CCS units.
%GROUP TOGETHER OIL, LFGAS AND NGCT PLANTS
%Indicates whether group together oil plants, LF Gas plants, and NGCTs to
%shrink fleet size.
groupplants=1
%WHETHER TO INCLUDE MIN STABLE LOAD FOR CTS, MSW, LFGAS, FWASTE
%Set whether to include min stable load on all CTs (NG & oil), MSW, LF Gas,
%& Fwaste plants (include min load if =1)
includeminloadCTmswLFGASfwaste=1
%WHETHER TO INCLUDE NLDC
%Set whether to use NLDC for demand (if =1, then use NLDC). Will subtract
%wind, solar & hydro generation from demand to create NLDC
usenldc=0
%WHETHER TO TAKE OUT HYDRO FROM DEMAND
%Toggles whether hydro is taken out of demand. Force to 1 if using NLDC.
removehydrofromdemand=1
%WHETHER TO COMPRESS ALL WIND GENERATORS INTO SINGLE GENERATOR
%When equal to 1, below parameter will group all wind generators into
%single generator. If using NLDC, this is obviated, since wind will be
%rmeoved from demand. The purpose of doing this is to avoid bouncing back &
%forth b/wn equally-zero-cost wind generators in solving MIP.
groupwindandsolarplants=1
%If using NLDC, set other parameters accordingly.
if usenldc==1
groupwindandsolarplants=0;
removehydrofromdemand=1;
end
%**************************************************************************
%OTHER PARAMETERS (RARELY CHANGED)*****************************************
%INPUT NOX AND SO2 PRICES
%Values taken from CSAPR final rule. So2 group: Table III-1. Emission
%Allowance Prices: RIA, Table 7-12. NOx price for annual program. Values
%given in $2007 - convert to $2011, which is what IPM costs are in.
tontokg=907.185;
cpi2007=207.342;
cpi2011=224.939;
noxandso2prices={'NOxCSAPR',600/tontokg;'SO2CSAPR1',1100/tontokg;'SO2CSAPR2',700/tontokg};
noxandso2prices(:,2)=num2cell(cell2mat(noxandso2prices(:,2))*cpi2011/cpi2007);
%REGION/ZONE/NODE
%Define region, zone and node name
regionname='MISO';
zonename='MISOZone';
nodename='MISONode';
%HOW TO MODEL MISO
%Two options for modeling MISO:
%1) As the IPM regions marked MIS_, which only includes areas in the upper Midwest in MISO, such that parts of MO, for
%instance, are not in MISO but parts are. Note that Entergy is not included
%in this. [modelmisowithfullstates=0]
%2) Including only complete states in MISO, such that the following states
%are completely included in MISO: ND, SD, MN, IA, MO, WI, MI, IL and IN.
%This area is equivalent to the EPA's North Central region in the regional
%compliance strategy with the Clean Power Plan. This option has the benefit
%of being able to model each state's emissions rate under the CPP, which
%is not possible to apportion between parts of states, and it also avoids
%the need to split up an emissions mass limit. [modelmisowithfullstates=1]
modelmisowithfullstates=1;
%HOW TO MODEL HYDRO
%Two options to model hydro: Monthly Max Energy w/ MT Schedule in PLEXOS,
%or monthly capacity factor, which essentially limits hydro to a flat
%amount of generation in each hour based on the CF.
modelhydrowithmonthlymaxenergy=0;
%PUMPED HYDRO
%Delete pumped hydro storage facilities (set to 1)
deletepumpedhydro=1;
%HEAT RATE IMPROVEMENT
%Define assumed level of heat rate improvement achievable at coal plants in
%system. For now, single unit input for all plants. Updated 8/6/15 for
%final CPP, which assumes HRI of 4.3% in Eastern Interconnect.
hrimprovement=.043;
hrimprovementassumedbyepa=.043;
%SUPPRESS MIP SOLVER OUTPUT
%MIP solver in PLEXOS, by default, outputs progress messages, task size,
%etc. If suppresssolveroutput=1, this information is not shown. (Controlled
%through Diagnostic object.)
suppresssolveroutput=0;
%**************************************************************************
%% FILE NAME
basefilename=strcat('CPPEEPt',num2str(10*scaleenergyefficiencysavings),...
'FlxCCS',num2str(flexibleccs),'MW',num2str(mwccstoadd),'WndMW',num2str(mwwindtoadd),...
'Rmp',num2str(usescaledramprates),'MSL',num2str(includeminloadCTmswLFGASfwaste),...
'Vnt',num2str(allowventing));
if calculatecppco2price==0
basefilename=strcat(basefilename,'CO2P0');
end
if runnatgaspricescenario==1
basefilename=strcat(basefilename,'NG',ngpricescenario);
end
if testlowermasslimit==1
basefilename=strcat(basefilename,'LwrLmt');
end
if strcmp(reserverequirements,'nrel')
basefilename=strcat(basefilename,'NRELRes');
end
if usenldc==1
basefilename=strcat(basefilename,'NLDC');
end
if groupplants==0
basefilename=strcat(basefilename,'Grp0');
end
if solventstoragesize==1
basefilename=strcat(basefilename,'SSH1');
end
%% GENERAL PLEXOS PARAMETERS
%Name of model object
nameofmodel='Base';
%% CREATE FLEET AND GATHER DATA
%% RUN FUNCTION THAT PARSES CPP PARSED FILE
%This function reads in the CPP parsed file from EPA, isolates the MISO
%plants, does some processing, and then outputs
%parseddataworetiredwadjustmentsmiso, which contains all the plants in the
%parsed file still operating in 2025.
[parseddataworetiredwadjustmentsiso] = CPPParsedFileImport...
(compliancescenario,hrimprovement,modelmisowithfullstates,pc);
'Imported parsed CPP file'
%Replace baghouse retrofit column name w/ somethign w/out commas - messes
%up when try to write fleet to CSV later.
bagcol=find(strcmp(parseddataworetiredwadjustmentsiso(1,:),'Baghouse Retrofit (in conjunction with either dry FGD, ACI+Toxecon, and/or DSI)'));
parseddataworetiredwadjustmentsiso{1,bagcol}='Baghouse Retrofit (in conjunction with either dry FGD or ACI+Toxecon andor DSI)';
clear bagcol
%This function reads in the output of the above function and isolates the
%new plants in the CPP from existing plants that are expected to still be
%operating in 2025. Then it adds on new plants to those existing plants
%depending on the input parameter.
[futurepowerfleetforplexos] = AddNewPlantsToFutureFleet(parseddataworetiredwadjustmentsiso,pc);
'Added new plants to fleet'
%futurepowerfleetforplexos has same format as parsed data file
%% DOWNSCALE OIL-FIRED GENERATORS TO PLANT LEVEL
%Lots of oil-fired generators in IPM; for MISO, there are over 1,100
%oil-fired generators, 932 of which are less than 5 MW in size. (526 are
%between 1 and 2 MW, and 218 are less than 1 MW.) To shrink the model size,
%I downscale oil-fired generators to the plant level, of which there are
%351. Heat rates of oil-fired generators do not significantly differ within
%a plant; for most oil-fired plants, generator heat rates are identical, or
%vary by ~1000 or less Btu/kWh. Additionally, unit commitment parameters
%for oil-fired generators don't vary by size (i.e., assume a linear
%relationship between parameters and plant size), and external values of fuel prices and
%emissions rates are used for oil-fired generators, so there is no worry
%about having to average these (although they should be nearly the same for
%generators within a plant anyways). For these reasons, aggregating
%oil-fired generators to the plant level should not affect model accuracy.
%Also note that some oil-fired generators do have NOx control techs
%installed; for those generators, I don't downscale them.
[futurepowerfleetforplexos] = DownscaleOilFiredGeneratorsToPlantLevel(futurepowerfleetforplexos);
'Downscaled oil-fired generators'
%% GET WIND AND SOLAR GENERATION PROFILES
%Toggle is used to turn off gathering of wind and solar generation profiles
%when debugging other parts of script; getting this data takes a while and
%so is often turned off.
if gatherwindandsolarprofiles==1
% GET WIND DATA FOR NEW WIND POWER PLANTS
%Gather hourly wind generation data from NREL Eastern Wind Dataset.
[csvfilenamewithwindgenprofiles,futurepowerfleetforplexos,~,windcapacityfactors]=...
GatherWindGenerationProfilesFromNRELDataForFutureFleet...
(futurepowerfleetforplexos, compliancescenario, mwwindtoadd, mwccstoadd, flexibleccs, usenldc, groupwindandsolarplants, pc);
'Gathered wind generation profiles'
% GET SOLAR DATA FOR NEW SOLAR POWER PLANTS
%Gather hourly solar generation data from EPA IPM.
[csvfilenamewithsolargenprofiles,futurepowerfleetforplexos,solarratingfactors] = ...
GatherSolarGenerationProfilesForFutureFleet...
(futurepowerfleetforplexos,compliancescenario,mwwindtoadd, mwccstoadd, flexibleccs, usenldc, groupwindandsolarplants, pc);
'Gathered solar generation profiles'
end
%% AGGREGATE HYDRO PLANTS AND GET MONTHLY MAX ENERGY VALUES
%Call function that combines hydro generators into a single plant and matches
%each plant to either monthly maximum energy value (calculated in
%AnalyzeEIA923HydroMonthlyGeneration script) or a monthly capacity factor
%value (determined w/ modelhydrowithmonthlymaxenergy switch).
%Monthly max energy is output in MWh here, whereas rating factors are in
%percents.
%NOTE: filling in empty monthly max energy for new plants is hardcoded in
%this function. Revisit if necessary.
%INPUTS: future fleet, compliance scenario indicator, whether model hydro
%w/ monthly max energy or capacity factors (monthly max energy if = 1).
[futurepowerfleetforplexos,hydromonthlymaxenergy,hydroratingfactors]=...
AggregateHydroPlantsAndGetMonthlyMaxEnergyValues...
(futurepowerfleetforplexos,compliancescenario,modelhydrowithmonthlymaxenergy,pc);
'Aggregated hydro plants'
%% ADD FUEL PRICE DATA TO FUTURE POWER FLEET
%As of May 26, 2015, fuel prices for each power plant in parsed files are
%claculated by dividing the total fuel cost by total fuel use for each
%plant (yielding a fuel price of $/GJ).
%The below function calculates this ratio and adds a column to the
%end of the fleet cell array with the fuel operational cost, in $/GJ (as
%needed by PLEXOS).
%The function relies on a hardcoded fuel price for oil generators, which
%needs to be updated once the final rule comes out (written 5/26/15).
[futurepowerfleetforplexos] = AddFuelPricesToFleet(futurepowerfleetforplexos);
'Added fuel prices'
%% ADD EMISSIONS RATE DATA TO FUTURE POWER FLEET
%As of April 1, 2015, emissions rates for CPP Parsed Files are calculated
%by dividing total power generation in the parsed files by the total
%emissions. The below function calculates these emissions rates and
%adds columns to the end of the cell array with the emissions rates.
%For generators without aggregate generation or emissions data (since they
%are not dispatched in IPM), I use a capacity-weighted average emissions
%factor for generator w/ the same fuel and generator type. The emissions
%factor is then converted to an emissions rate using each plant's
%individual heat rate.
%Emissions rate values are output in kg/MWh, as used in PLEXOS.
%Function has hardcoded emissions rates from PHORUM data for oil-fired
%generators.
[futurepowerfleetforplexos] = AddEmissionsRatesToFleet...
(futurepowerfleetforplexos,hrimprovement,hrimprovementassumedbyepa);
'Added emissions rates'
%% ASSIGN NOX AND SO2 EMISSION PRICES TO GENERATORS
%Following function assigns NOx and SO2 emissions prices, based on CSAPR
%projected values, to generators in model. The NOx and So2 emissions prices
%are set and assigned within the function. Outputs emissions prices in
%$/kg.
[futurepowerfleetforplexos] = AssignNOxAndSO2Prices(futurepowerfleetforplexos,noxandso2prices);
%% AGGREGATE OIL, LFGAS AND NGCT GENERATORS
%In addition to downscaling oil-fired generators to plant level, need to
%further reduce fleet size. Accomplish this by grouping together individual
%oil-fired generators, LF Gas generators, and NGCTs.
if groupplants==1
[futurepowerfleetforplexos] = GroupPlants(futurepowerfleetforplexos);
end
'Grouped plants'
%% SCALE NATURAL GAS PRICES IF RUNNING NG PRICE SCENARIO
%Scale natural gas prices if running a natural gas price scenario (high or
%low)
if runnatgaspricescenario==1
%INPUTS: fleet, scalar for NG prices.
%OUTPUTS: fleet
[futurepowerfleetforplexos] = AlterNaturalGasPrices(futurepowerfleetforplexos,ngpricescalar);
end
%% ADD UNIT COMMITMENT PARAMETERS TO FUTURE POWER FLEET
%UC parameters (min load, min down time, start cost, ramp limits) are derived
%from PHORUM. See research journal, March 19, 2015, for description of data.
%Below function takes in future power fleet, imports UC parameters from
%PHORUM, matches each row from futurepowerfleet to a set of UC parameters,
%and stores those values at the end of futurepowerfleet.
%INPUTS: future fleet, usescaledramprates (indicates whether to use scaled
%or unscaled PHORUM ramp rates), includeminloadCTmswLFGASfwaste (indicates
%whether include min stable load on CTs, MSW, lf gas, & f waste plants)
[futurepowerfleetforplexos] = AddUCParametersToFleet(futurepowerfleetforplexos,usescaledramprates,includeminloadCTmswLFGASfwaste,pc);
'Added UC parameters'
%% RETROFIT GENERATORS WITH CCS
%Below function retrofits generators with CCS. Run script even if no CCS
%added in order to add some column headers to futurepowerfleet (necessary
%for calculations below). If statement inside function skips rest of function if not
%actually adding any MW of CCS.
%INPUTS: futurepowerfleetforplexos, mwccstoadd (MW of CCS to retrofit),
%flexibleccs (if =1, add flexible CCS; if =0, add inflexible CCS).
%OUTPUTS: futurepowerfleetforplexos (includes venting and solvent storage
%generators if adding flexible CCS), regeneratoroversize (% by which regenerator is oversized/undersized; if
%not oversized, value = 0); solventstoragesize (hours of full load
%operation), ccscapacitypenalty (capacity penalty (%) from CCS retrofit),
%stminload (steam turbine min load, as %age ponits below boiler load, so if
%boiler min load is 30%, stminload=10 means st min load is 20%).
[futurepowerfleetforplexos,regeneratoroversize,ccscapacitypenalty,...
solventstoragecapacitypenaltyreduction,ventingcapacitypenaltyreduction,stminload] =...
RetrofitGeneratorsWithCCS(futurepowerfleetforplexos, ...
mwccstoadd, flexibleccs, pc, solventstoragesize);
'Retrofit CCS'
%% IDENTIFY UNITS AFFECTED BY CLEAN POWER PLAN
%This script adds a column to futurepowerfleetforplexos that marks whether
%the unit is an affected EGU under the final CPP.
[futurepowerfleetforplexos] = IdentifyAffectedEGUsUnderCPP(futurepowerfleetforplexos);
%% GET NECESSARY COLUMNS OF DATA FROM FUTURE FLEET DATASET
[fleetorisidcol, fleetunitidcol, fleetfueltypecol,...
fleetheatratecol, fleetcapacitycol,fleetplanttypecol,...
fleetretrofitcol, fleetregioncol, fleetstatecol, fleetfossilunitcol,...
fleetmindowntimecol, fleetstartcostcol, fleetminloadcol, fleetmaxrampupcol, ...
fleetmaxrampdowncol, fleetrunupratecol, fleetrundownratecol,...
fleetnoxemsratecol, fleetso2emsratecol, fleetco2emsratecol,...
fleetfuelpricecol, fleetpumpunitscol, fleetpumpeffcol, fleetpumploadcol,...
fleetccsretrofitcol,fleettruesscapacitycol,fleetaffectedegucol,fleethrpenaltycol,...
fleetcapacpenaltycol,fleetsshrpenaltycol,fleetsscapacpenaltycol,fleeteextraperestorecol,...
fleeteregenpereco2capcol,fleetegridpereco2capandregencol,fleetegriddischargeperestorecol,...
fleetnoxpricecol,fleetso2pricecol,fleetso2groupcol,fleetco2emsrateforedcol,...
fleetso2emsrateforedcol,fleetnoxemsrateforedcol,fleethrforedcol,fleetvomforedcol]=...
GetColumnNumbersFromCPPParsedFile(futurepowerfleetforplexos);
%% DELETE PUMPED STORAGE FACILITIES
if deletepumpedhydro==1
%Get rows of pumped hydro facilities
pumpedhydrorows=find(strcmp(futurepowerfleetforplexos(:,fleetplanttypecol),'Pumped Storage'));
%Delete rows
futurepowerfleetforplexos(pumpedhydrorows,:)=[];
'Deleted pumped storage facilities'
end
%Make sure no 'Pumps' units left - don't have UC parameters assigned to
%them, so don't want them staying in.
if find(strcmp(futurepowerfleetforplexos(:,fleetfueltypecol),'Pumps'))
'Pumps fuel type still in fleet!'
end
%%
%% CREATE FILES FOR PLEXOS
%% SLIM FLEET IF USING NLDC
%Save fleet. Do this even if not using NLDC, b/c futurepowerfleetfull is
%input to later functions.
futurepowerfleetfull=futurepowerfleetforplexos;
%If using NLDC, then need to remove wind, solar and hydro from the fleet
%that's input to PLEXOS.
if usenldc==1
windrows=find(strcmp(futurepowerfleetforplexos(:,fleetfueltypecol),'Wind'));
solarrows=find(strcmp(futurepowerfleetforplexos(:,fleetfueltypecol),'Solar'));
hydrorows=find(strcmp(futurepowerfleetforplexos(:,fleetfueltypecol),'Hydro'));
allrowstoremove=[windrows;solarrows;hydrorows];
futurepowerfleetforplexos(allrowstoremove,:)=[];
elseif removehydrofromdemand==1
%If just removing hydro from demand, not other units
hydrorows=find(strcmp(futurepowerfleetforplexos(:,fleetfueltypecol),'Hydro'));
allrowstoremove=hydrorows;
futurepowerfleetforplexos(allrowstoremove,:)=[];
end
%% CREATE FUNCTION FOR CREATING PLEXOS GENERATOR OBJECT NAME
%Name generators in PLEXOS as: ORISID-UNITID
createplexosobjname = @(arraywithdata,orisidcol,unitidcol,rowofinfo) strcat(arraywithdata{rowofinfo,orisidcol},...
'-',arraywithdata{rowofinfo,unitidcol});
%% SET UP GENERATOR DATA
%OBJECTS*******************************************************************
%Object - declare all objects in model.
objectheaders={'Class','Name'};
%Possible objects (basically class names): Data File, Generator, Fuel,
%Emission, Region, Zone, Node, Scenario, Line.
%Make generator names ORISCode+UnitID.
objectdata={};
for i=2:size(futurepowerfleetforplexos,1)
plexosgenname=createplexosobjname(futurepowerfleetforplexos,...
fleetorisidcol,fleetunitidcol,i);
objectdata=AddObjectToPLEXOSFile(objectdata,'Generator',plexosgenname);
end
%Categories - I haven't found a use for this sheet yet, so leave empty.
categoryheaders={'Category_ID','Class','Category','Rank','Class_ID','Name'};
categorydata={};
%MEMBERSHIPS***************************************************************
%Memberships - assign relationships between objects, e.g. emissions and
%node.
%6/15/15: Do NOT add a membership to fuel type - Price property of Fuel
%object will override Fuel Price property of Generator. There's really no
%reason as of today anyways to add Fuel memberships to PLEXOS.
%Memberships I care about: location (i.e., node), emission.
%Assign fuel type to each generator; SO2, NOx & CO2/CO2CPP emissions to each
%generator; region to each generator.
membershipsheaders={'Parent_Class','Child_Class','Collection','Parent_Object','Child_Object'};
membershipsdata={};
%CO2CPP emission object is for affected EGUs under CPP, whereas CO2 object
%is for rest of generators. Have two emission objects because only CO2CPP
%will have price attached to it to force compliance w/ CPP.
listofemissions={'NOx';'SO2';'CO2'};
listofallemissions={'NOx';'NOxCSAPR';'SO2';'SO2CSAPR1';'SO2CSAPR2';'CO2';'CO2CPP'};
for i=2:size(futurepowerfleetforplexos,1)
%Parent class: Generator
%Child classes: Fuel, Region (also emission)
%Collections: Fuels, Region (also emissions)
%Parent obj: generator name
%Child obj: varies
plexosgenname=createplexosobjname(futurepowerfleetforplexos,...
fleetorisidcol,fleetunitidcol,i);
%Add Generator-Node membership for all units.
membershipsdata=AddMembershipToPLEXOSFile(membershipsdata,'Generator','Node',plexosgenname,...
nodename);
%Add Generator-Emissions memberships
for j=1:size(listofemissions,1)
curremission=listofemissions{j};
if strcmp(curremission,'CO2')
%For CO2, if generator is affected EGU, add 'CO2EGU' membership
if futurepowerfleetforplexos{i,fleetaffectedegucol}==1
curremission='CO2CPP';
end
elseif strcmp(curremission,'NOx')
if futurepowerfleetforplexos{i,fleetnoxpricecol}>0
curremission='NOxCSAPR';
end
elseif strcmp(curremission,'SO2')
if futurepowerfleetforplexos{i,fleetso2groupcol}==1
curremission='SO2CSAPR1';
elseif futurepowerfleetforplexos{i,fleetso2groupcol}==2
curremission='SO2CSAPR2';
end
end
membershipsdata=AddMembershipToPLEXOSFile(membershipsdata,'Emission','Generator',curremission,...
plexosgenname);
end
end
%Attributes - I haven't found a use for this sheet, so skip.
attributeheaders={'Name','Class','Attribute','Value'};
attributedata={};
%PROPERTIES****************************************************************
%Generator properties of interest: Units (always 1), Max Capacity [MW], Min
%Stable Level [MW], Heat Rate [GJ/MWh], VO&M Charge [$/MWh], Rating Factor
%[%], Min Stable Level [MW], Start Cost [$], Max Ramp Up [MW/min.], Max
%Ramp Down [MW/min.], Min Down Time [hours], Production Rate [of NOx, SO2 & CO2
%emissions; kg/MWh], Fuel Price [$/GJ]
%Generator properties of interest for solvent storage (pump) facilities
%only: Pump Units, Pump Load, Pump Efficiency
%UC parameters (min stable level, start cost, max ramp up, max ramp down,
%min down time) are all derived from PHORUM values (imported above).
propertiesofinterest={'Units';'Max Capacity';'Heat Rate';'VO&M Charge';...
'Min Stable Level';'Start Cost';'Max Ramp Up';'Max Ramp Down';...
'Min Down Time';'Production Rate';'Fuel Price'};
propertiesofinterestsolventstorage={'Pump Units';'Pump Load';'Pump Efficiency'};
propertiesheader={'Parent_Class','Child_Class','Collection','Parent_Object',...
'Child_Object','Property','Band_ID','Value','Units','Date_From','Date_To',...
'Pattern','Action','Variable','Filename','Scenario','Memo','Period_Type_ID'};
propertiesdata={}; gjtobtu=1.055E-6;
for i=2:size(futurepowerfleetforplexos,1)
%Create PLEXOS gen name
plexosgenname=createplexosobjname(futurepowerfleetforplexos,...
fleetorisidcol,fleetunitidcol,i);
for j=1:size(propertiesofinterest,1)
%Get property value
if strcmp(propertiesofinterest{j,1},'Units')
propertyvalue=1; %value
elseif strcmp(propertiesofinterest{j,1},'Max Capacity')
propertyvalue=futurepowerfleetforplexos{i,fleetcapacitycol};
elseif strcmp(propertiesofinterest{j,1},'Heat Rate')
%If pump units, want HR=1 so don't do below conversion; otherwise, scale for gjtobtu
if strcmp(futurepowerfleetforplexos{i,fleetplanttypecol},'SSPump')==0
propertyvalue=futurepowerfleetforplexos{i,fleetheatratecol}*gjtobtu*1000; %Btu/kWh * 1000kWh/MWh * 1.055E-6GJ/Btu
else
propertyvalue=1;
end
elseif strcmp(propertiesofinterest{j,1},'VO&M Charge')
propertyvalue=futurepowerfleetforplexos{i,strcmp(futurepowerfleetforplexos(1,:),'VOMPerMWhCalculated')};
elseif strcmp(propertiesofinterest{j,1},'Min Stable Level')
%If flexible CCS generator, base CCS generator should be
%allowed to go down to 1, so input that value & ignore what's
%in cell, which is used in group constraints later.
if flexibleccs==1 && futurepowerfleetforplexos{i,fleetccsretrofitcol}==1
propertyvalue=1;
else
propertyvalue=futurepowerfleetforplexos{i,fleetminloadcol};
end
elseif strcmp(propertiesofinterest{j,1},'Start Cost')
propertyvalue=futurepowerfleetforplexos{i,fleetstartcostcol};
elseif strcmp(propertiesofinterest{j,1},'Max Ramp Up')
%If flexible CCS generator, ramp values enforced in group
%constraint, so input capacity of plant here to allow
%ramp over full output.
if flexibleccs==1 && futurepowerfleetforplexos{i,fleetccsretrofitcol}==1
propertyvalue=futurepowerfleetforplexos{i,fleetcapacitycol};
else
propertyvalue=futurepowerfleetforplexos{i,fleetmaxrampupcol};
end
elseif strcmp(propertiesofinterest{j,1},'Max Ramp Down')
%If flexible CCS generator, ramp values enforced in group
%constraint, so input capacity of plant here to allow
%ramp over full output.
if flexibleccs==1 && futurepowerfleetforplexos{i,fleetccsretrofitcol}==1
propertyvalue=futurepowerfleetforplexos{i,fleetcapacitycol};
else
propertyvalue=futurepowerfleetforplexos{i,fleetmaxrampdowncol};
end
elseif strcmp(propertiesofinterest{j,1},'Min Down Time')
propertyvalue=futurepowerfleetforplexos{i,fleetmindowntimecol};
elseif strcmp(propertiesofinterest{j,1},'Fuel Price')
propertyvalue=futurepowerfleetforplexos{i,fleetfuelpricecol};
elseif strcmp(propertiesofinterest{j,1},'Production Rate')
propertyvalue=[futurepowerfleetforplexos{i,fleetnoxemsratecol};
futurepowerfleetforplexos{i,fleetso2emsratecol};
futurepowerfleetforplexos{i,fleetco2emsratecol}];
end
%Add row to properties.
if strcmp(propertiesofinterest{j,1},'Production Rate')==0 %if not production (emission) rate
%AddPropertyToPLEXOSFile(propertiesdata,parentclass,childclass,parentobj,...
%childobj, propertyname, propertyvalue, filename, scenarioname, datefrom, dateto)
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'System','Generator','System',...
plexosgenname, propertiesofinterest{j,1}, propertyvalue,'','','','');
else
%If production (emission) rate, parent class is 'Emission', and
%the parent object is the name of the emission, so parent
%object is set within function. Instead, use parent class here
%to indicate whether the unit is an affected EGU under CPP and
%therefore should be assigned CO2CPP membership, or if gets
%regular CO2 membership.
if futurepowerfleetforplexos{i,fleetaffectedegucol}==1
emparentname='CO2CPP';
else
emparentname='CO2';
end
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'Emission','Generator',emparentname,...
plexosgenname, propertiesofinterest{j,1}, propertyvalue,'','','','');
end
end
%Add properties unique to pumped storage (solvent storage) facilities.
%Test if pumped storage by seeing if has any pump units
if futurepowerfleetforplexos{i,fleetpumpunitscol}==1
%Get property value
for j=1:size(propertiesofinterestsolventstorage,1)
if strcmp(propertiesofinterestsolventstorage{j,1},'Pump Units')
propertyvalue=futurepowerfleetforplexos{i,fleetpumpunitscol};
elseif strcmp(propertiesofinterestsolventstorage{j,1},'Pump Load')
propertyvalue=futurepowerfleetforplexos{i,fleetpumploadcol};
elseif strcmp(propertiesofinterestsolventstorage{j,1},'Pump Efficiency')
propertyvalue=futurepowerfleetforplexos{i,fleetpumpeffcol};
end
%Add row to property
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'System','Generator','System',...
plexosgenname, propertiesofinterestsolventstorage{j,1}, propertyvalue,'','','','');
end
end
end
%LOAD AND GENERATION PARTICIPATION FACTORS FOR FLEXIBLE CCS****************
%If running flexible CCS, need to set load and generation participation
%factors for some components - pump units, pump dummy units, and continuous
%solvent units - to zero. A value of 0 means that the unit is still
%included in the objective function but its generation and pump load are
%not included in the supply=demand constraint at the node.
if flexibleccs==1
if mwccstoadd>0
%Plant types for zero participation factors:
planttypesforzeroparticipationfactor={'SSPump';'SSPumpDummy';'ContinuousSolvent'};
for i=1:size(planttypesforzeroparticipationfactor,1)
currplanttype=planttypesforzeroparticipationfactor{i};
%Find units of that plant type
unitsofplanttyperows=find(strcmp(futurepowerfleetforplexos(:,fleetplanttypecol),currplanttype));
%For each unit, add property
for j=1:size(unitsofplanttyperows,1)
currfleetrow=unitsofplanttyperows(j);
plexosgenname=createplexosobjname(futurepowerfleetforplexos,...
fleetorisidcol,fleetunitidcol,currfleetrow);
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'Generator','Node',plexosgenname,...
nodename, 'Generation Participation Factor', 0,'','','','');
if strcmp(currplanttype,'SSPump')
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'Generator','Node',plexosgenname,...
nodename, 'Load Participation Factor', 0,'','','','');
end
end
end
end
end
'Added generator data to properties'
%% CREATE HEAD AND TAIL STORAGE FACILITIES FOR SOLVENT STORAGE
%Need to do this for both pump units
%Only add if adding flexible CCS
if mwccstoadd>0
if flexibleccs==1
%Storage properties for PLEXOS. Initial Volume uses Max Volume, so
%put it after Max Volume.
storageproperties={'Units';'Max Volume';'Initial Volume';'End Effects Method'}; %;'Internal Volume Scalar'}
%Iterate through each solvent storage facility being added. ID
%solvent storage generators by finding generators w/ Pump Units = 1.
sspumprows=find([futurepowerfleetforplexos{2:end,fleetpumpunitscol}]==1)+1; %add 1 to acct for header being skipped
for rownum=1:size(sspumprows,2) %solventstoragerows has columns, not rows
ssrow=sspumprows(rownum);
%Get SS generator PLEXOS name
plexosgenname=createplexosobjname(futurepowerfleetforplexos,...
fleetorisidcol,fleetunitidcol,ssrow);
%Create head and tail storage names by adding 'Lean' or 'Rich'
%to end of PLEXOS name
leanstoragename=strcat(plexosgenname,'Lean');
richstoragename=strcat(plexosgenname,'Rich');
%OBJECTS*******************************************************************
%Add rich and lean storage objects
objectdata=AddObjectToPLEXOSFile(objectdata,'Storage',leanstoragename);
objectdata=AddObjectToPLEXOSFile(objectdata,'Storage',richstoragename);
%MEMBERSHIPS***************************************************************
%Memberships to add: Generator,Storage,Head Storage,[Storage
%Name]. Also for Tail Storage. Lean = head, rich = tail.
%AddMembership function handles assignment to head/tail, which
%is in Collections field.
membershipsdata=AddMembershipToPLEXOSFile(membershipsdata,'Generator','Storage',plexosgenname,...
richstoragename);
membershipsdata=AddMembershipToPLEXOSFile(membershipsdata,'Generator','Storage',plexosgenname,...
leanstoragename);
%PROPERTIES****************************************************************
%Properties to add: Units=1, Max and Initial Volume, End Effects Method=1
%(value of 1 sets it to "Free", which means end volume of the optimization horizon does
%not have to equal the initial volume). Min Volume defaults to 0.
for currpropertyrow=1:size(storageproperties,1)
currproperty=storageproperties{currpropertyrow,1};
if strcmp(currproperty,'Units')
propertyvaluelean=1;
propertyvaluerich=1;
elseif strcmp(currproperty,'Max Volume')
%Volume is based on storage volume values used in other
%papers. Key storage size input parameter is # hours SS generator
%can generate at when operating at full load.
%Therefore, calculate max volume as:
%MaxVolume=HoursStorage*CapacitySSGen/1000.
%[GWh]=[Hr]*[MW]/(1000MW/GW)
%Pump 1 storage volume is set to combined storage
%volume of pumps 1 and 2, whereas pump 2 storage volume
%is set according to pump 2 capacity.
if strfind(futurepowerfleetforplexos{ssrow,fleetunitidcol},'Pump1')
%Find pump 2 row
pump1unitid=futurepowerfleetforplexos{ssrow,fleetunitidcol};
pump2unitid=strcat(pump1unitid(1:end-1),'2');
pump2row=find(strcmp(futurepowerfleetforplexos(:,fleetunitidcol),pump2unitid));
%Pump 2 row SHOULD be the next row in sspumprows
%array - check that.
if pump2row ~= (ssrow+1)
'Pump2RowDoesNotEqualPump1Row+1'
end
%Now get combined capacities of pump 1 & 2
sspump1capac=futurepowerfleetforplexos{ssrow,fleetcapacitycol};
sspump2capac=futurepowerfleetforplexos{pump2row,fleetcapacitycol};
combinedsscapac=sspump1capac+sspump2capac;
maxvolume=solventstoragesize*combinedsscapac/1000;
propertyvaluelean=maxvolume;
propertyvaluerich=maxvolume;
elseif strfind(futurepowerfleetforplexos{ssrow,fleetunitidcol},'Pump2')
ssgencapacity=futurepowerfleetforplexos{ssrow,fleetcapacitycol}; %convert from MWh to GWh
maxvolume=solventstoragesize*ssgencapacity/1000;
propertyvaluelean=maxvolume;
propertyvaluerich=maxvolume;
end
elseif strcmp(currproperty,'Initial Volume')
%This is what each storage will start with in terms of
%volume at the first period of the whole optimization;
%so if run daily steps for full year, initial volume
%determines volume in hour 1 of day 1. Set initial
%volume of pump 1 lean to half its max volume, and
%initial volume of pump 2 lean to 0. This results in
%half of the total solvent being initially stored as
%lean solvent (since the max volume of pump 1 is the
%combined capacity of stored solvent).
if strfind(futurepowerfleetforplexos{ssrow,fleetunitidcol},'Pump1')
propertyvaluelean=maxvolume/2;
propertyvaluerich=maxvolume/2;
elseif strfind(futurepowerfleetforplexos{ssrow,fleetunitidcol},'Pump2')
propertyvaluelean=0;
propertyvaluerich=maxvolume;
end
elseif strcmp(currproperty,'End Effects Method')
propertyvaluelean=1;
propertyvaluerich=1;
end
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'System','Storage','System',...
leanstoragename, currproperty, propertyvaluelean,'','','','');
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'System','Storage','System',...
richstoragename, currproperty, propertyvaluerich,'','','','');
end
end
end
end
%% ADD RATING FACTORS FOR WIND, HYDRO, SOLAR IF NOT USING NLDC
if usenldc==0
%% ADD MONTHLY MAX ENERGY OR RATING FACTOR PROPERTY TO HYDRO PLANTS
%Either add monthly max energy values or rating factors per month for each
%hydro facility, based on whether modelhydrowithmonthlymaxenergy = 0 (use
%rating factors) or 1 (use monthly max energy).
%Monthly max energy data in hydromonthlymaxenergy; rating factor data in
%hydroratingfactors. Both arrays are in the same format - across top is
%month #, across left is ORIS ID, and then values are in middle. Both are
%input as dynamic values into PLEXOS, so can just substitute values out.
%Only add hydro rating factors if not already removed hydro from
%demand.
if removehydrofromdemand==0
%Get hydro rows
hydrogenrows=find(strcmp(futurepowerfleetforplexos(:,fleetplanttypecol),'Hydro'));
%For each hydro row, get max monthly energy or rating factor
for i=1:size(hydrogenrows,1)
%Get ORIS ID
temprowinfuturefleet=hydrogenrows(i);
temporisid=futurepowerfleetforplexos{temprowinfuturefleet,fleetorisidcol};
temporisid=str2num(temporisid);
%Create generator name (for AddProperty call below)
plexosgenname=createplexosobjname(futurepowerfleetforplexos,...
fleetorisidcol,fleetunitidcol,temprowinfuturefleet);
%Now get row in monthly max energy or rating factor array. (Really
%would be the same either way as of 7/2/15, since set up identically.)
if modelhydrowithmonthlymaxenergy==1 %use monthly max energy
rowwithdata=find(hydromonthlymaxenergy(:,1)==temporisid);
elseif modelhydrowithmonthlymaxenergy==0 %use rating factors
rowwithdata=find(hydroratingfactors(:,1)==temporisid);
end
%For each month, fill in Date From as 1st of that month; PLEXOS
%auto-fills gaps (so if have Date From of 1/1/2012 and 2/1/2012, the
%value for 1/1/2012 will apply for all of January). Each plant only has
%1 entry, so rowwithmonthlyenergydata will have length of 1. Make sure
if size(rowwithdata,1)>1
'WARNING: rowwithmonthlyenergydata has more than 1 row!'
end
%Add property for each month
for j=2:size(hydromonthlymaxenergy,2)
%Get month
currmonth=j-1; %if j=2, really in January (month 1)
%Create Date From string
tempdatefrom=strcat(num2str(currmonth),'/1/2030');
%Get monthly max energy and convert to **GWh** (which is what Max
%Energy Month is in PLEXOS) or get rating factor (already in % so
%no further conversions needed), and then add to Properties list.
if modelhydrowithmonthlymaxenergy==1
temphydrodata=hydromonthlymaxenergy(rowwithdata,j)/1000;
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'System','Generator','System',...
plexosgenname, 'Max Energy Month', temphydrodata,'','',tempdatefrom,''); %don't include Date To
elseif modelhydrowithmonthlymaxenergy==0
temphydrodata=hydroratingfactors(rowwithdata,j);
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'System','Generator','System',...
plexosgenname, 'Rating Factor', temphydrodata,'','',tempdatefrom,''); %don't include Date To
end
end
end
clear temprowinfuturefleet temporisid tempdatefrom rowwithmonthlyenergydata;
end
%% ADD WIND RATING FACTOR FILE
%First create object for data file
nameofwindratingdatafile='NRELWindGenProfiles';
objectdata = AddObjectToPLEXOSFile(objectdata,'Data File',nameofwindratingdatafile);
%Create Data File Filename property
propertiesdata = AddPropertyToPLEXOSFile(propertiesdata,'System','Data File','System',...
nameofwindratingdatafile,'Filename',0,csvfilenamewithwindgenprofiles,'','1/1/2030','12/31/2030');
%Add data file to Rating Factor property of wind generators
windrows=find(strcmp(futurepowerfleetforplexos(:,fleetfueltypecol),'Wind'));
for i=1:size(windrows,1)
currrow=windrows(i,1);
%Get generator PLEXOS name
plexosgenname=createplexosobjname(futurepowerfleetforplexos,...
fleetorisidcol,fleetunitidcol,windrows(i)); %windrows has row of in futurepowerfleet... array which is what I want
%Add data
propertiesdata = AddPropertyToPLEXOSFile(propertiesdata,'System','Generator','System',...
plexosgenname,'Rating Factor',0,strcat('{Object}',nameofwindratingdatafile),'','1/1/2030','12/31/2030');
end
%Add attribute for wind capacity factor data file that sets datetime
%convention so that datetime is read as being at the end of the period
%(i.e., 11:00 is for hour 10:01-11:00). Do this by setting Datetime
%Convention attribute to 1.
attributedata = AddAttributeToPLEXOSFile(attributedata, nameofwindratingdatafile, 'Data File', 'Datetime Convention',...
1);
%% ADD SOLAR RATING FACTOR FILE
%First create object for data file
nameofsolarratingdatafile='NRELSolarGenProfiles';
objectdata = AddObjectToPLEXOSFile(objectdata,'Data File',nameofsolarratingdatafile);
%Create Data File Filename property
propertiesdata = AddPropertyToPLEXOSFile(propertiesdata,'System','Data File','System',...
nameofsolarratingdatafile,'Filename',0,csvfilenamewithsolargenprofiles,'','1/1/2030','12/31/2030');
%Add data file to Rating Factor property of wind generators
solarrows=find(strcmp(futurepowerfleetforplexos(:,fleetfueltypecol),'Solar'));
for i=1:size(solarrows,1)
currrow=solarrows(i,1);
%Get generator PLEXOS name
plexosgenname=createplexosobjname(futurepowerfleetforplexos,...
fleetorisidcol,fleetunitidcol,solarrows(i)); %solarrows has row of in futurepowerfleet... array which is what I want
%Add data
propertiesdata = AddPropertyToPLEXOSFile(propertiesdata,'System','Generator','System',...
plexosgenname,'Rating Factor',0,strcat('{Object}',nameofsolarratingdatafile),'','1/1/2030','12/31/2030');
end
%Add attribute for wind capacity factor data file that sets datetime
%convention so that datetime is read as being at the end of the period
%(i.e., 11:00 is for hour 10:01-11:00). Do this by setting Datetime
%Convention attribute to 1.
attributedata = AddAttributeToPLEXOSFile(attributedata, nameofsolarratingdatafile, 'Data File', 'Datetime Convention',...
1);
end
%% ADD FUEL OBJECTS TO PLEXOS FILE
%6/15/15: Price property of Fuel object will override Fuel Price property
%of Generators. As of today, there's no reason to add a fuel object to
%PLEXOS, so do not do it.
% %Don't need to add fuel prices - already included at generator level
% %Fuel objects - get unique fuels, and then create object for each
% listoffuels=unique(futurepowerfleetforplexos(2:end,fleetfueltypecol));
% for i=1:size(listoffuels,1)
% %Add fuel object
% objectdata=AddObjectToPLEXOSFile(objectdata,'Fuel',listoffuels{i,1});
% end
%% ADD EMISSION OBJECTS
%Memberships to generators are added above
for i=1:size(listofallemissions,1)
%Add emissions object
objectdata=AddObjectToPLEXOSFile(objectdata,'Emission',listofallemissions{i});
%Add prices for CSAPR emissions - these are marked as '...CSAPR'
if findstr(listofallemissions{i},'CSAPR')
currpricerow=find(strcmp(noxandso2prices(:,1),listofallemissions{i}));
currprice=noxandso2prices{currpricerow,2};
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'System','Emission','System',...
listofallemissions{i},'Shadow Price',currprice,'','','',''); %$/kg
propertiesdata=AddPropertyToPLEXOSFile(propertiesdata,'System','Emission','System',...
listofallemissions{i},'Price',currprice,'','','',''); %$/kg
end
end
%% CALL FUNCTION TO CREATE DEMAND PROFILE
%Call function to create demand profile for specified demand scenario
%specified above. Demand scenario assumes a certain penetration of energy
%efficiency (or no additional relative to base case (Scenario 0)).
%Also input states for analysis. This is the same regardless of value of modelmisowithfullstates
statesforanalysis={'Illinois';'Indiana';'Iowa';'Michigan';...
'Minnesota';'Missouri';'North Dakota';'South Dakota';'Wisconsin'}; %cell list of states, 1 per row; do not include 'State' as label at top
[demanddataobjnames, demandfilenames]=CreateDemandProfileForPLEXOS(demandscenarioforanalysis,statesforanalysis,...
modelmisowithfullstates,scaleenergyefficiencysavings,futurepowerfleetfull,usenldc,removehydrofromdemand,...
solarratingfactors,windcapacityfactors,hydroratingfactors,pc);
%Create scenario names (PLEXOS object) for demand scenarios
for i=1:size(demandscenarioforanalysis,1)
demandscenariosforanalysisscenarionames{i,1}=strcat('DemandScenario',num2str(demandscenarioforanalysis(i)));
end
%% ADD REGIONS/ZONES/NODES, DEMAND DATA, SCENARIOS FOR DEMAND DATA, AND ASSIGN SCENARIO TO MODEL
%First create region & zone objects
objectdata = AddObjectToPLEXOSFile(objectdata,'Region',regionname);
objectdata = AddObjectToPLEXOSFile(objectdata,'Zone',zonename);
objectdata = AddObjectToPLEXOSFile(objectdata,'Node',nodename);
%Then create scenario objects for each demand profile
for i=1:size(demandscenariosforanalysisscenarionames,1)
objectdata = AddObjectToPLEXOSFile(objectdata,'Scenario',demandscenariosforanalysisscenarionames{i});