• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GenXProject / GenX / #371

14 Sep 2023 02:22AM UTC coverage: 0.271%. First build
#371

Pull #546

travis-ci

Pull Request #546: Thermal+storage (fusion, maintenance)

630 of 630 new or added lines in 9 files covered. (100.0%)

12 of 4424 relevant lines covered (0.27%)

0.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/write_outputs/write_outputs.jl
1
################################################################################
2
## function output
3
##
4
## description: Writes results to multiple .csv output files in path directory
5
##
6
## returns: path directory
7
################################################################################
8
@doc raw"""
9
        write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)
10

11
Function for the entry-point for writing the different output files. From here, onward several other functions are called, each for writing specific output files, like costs, capacities, etc.
12
"""
13
function write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)
×
14
    if setup["OverwriteResults"] == 1
15
        # Overwrite existing results if dir exists
×
16
        # This is the default behaviour when there is no flag, to avoid breaking existing code
17
        if !(isdir(path))
18
            mkpath(path)
×
19
        end
×
20
    else
21
        # Find closest unused ouput directory name and create it
22
        path = choose_output_dir(path)
23
        mkpath(path)
×
24
    end
×
25

26
    if setup["OutputFullTimeSeries"] == 1
27
        mkpath(joinpath(path, setup["OutputFullTimeSeriesFolder"]))
28
    end
×
29

30
    # https://jump.dev/MathOptInterface.jl/v0.9.10/apireference/#MathOptInterface.TerminationStatusCode
31
    status = termination_status(EP)
×
32

×
33
    ## Check if solved sucessfully - time out is included
×
34
    if status != MOI.OPTIMAL && status != MOI.LOCALLY_SOLVED
×
35
        if status != MOI.TIME_LIMIT # Model failed to solve, so record solver status and exit
36
            write_status(path, inputs, setup, EP)
37
            return
×
38
            # Model reached timelimit but failed to find a feasible solution
39
            #### Aaron Schwartz - Not sure if the below condition is valid anymore. We should revisit ####
×
40
        elseif isnan(objective_value(EP)) == true
×
41
            # Model failed to solve, so record solver status and exit
42
            write_status(path, inputs, setup, EP)
43
            return
44
        end
×
45
    end
×
46

×
47
    # Dict containing the list of outputs to write
×
48
    output_settings_d = setup["WriteOutputsSettingsDict"]
×
49
    write_settings_file(path, setup)
×
50
    write_system_env_summary(path)
×
51

×
52
    output_settings_d["WriteStatus"] && write_status(path, inputs, setup, EP)
×
53

×
54
    # linearize and re-solve model if duals are not available but ShadowPrices are requested
×
55
    if !has_duals(EP) && setup["WriteShadowPrices"] == 1
×
56
        # function to fix integers and linearize problem
×
57
        fix_integers(EP)
×
58
        # re-solve statement for LP solution
×
59
        println("Solving LP solution for duals")
×
60
        set_silent(EP)
×
61
        optimize!(EP)
×
62
    end
×
63

×
64
    if output_settings_d["WriteCosts"]
×
65
        elapsed_time_costs = @elapsed write_costs(path, inputs, setup, EP)
×
66
        println("Time elapsed for writing costs is")
×
67
        println(elapsed_time_costs)
×
68
    end
×
69

×
70
    if output_settings_d["WriteCapacity"] || output_settings_d["WriteNetRevenue"]
×
71
        elapsed_time_capacity = @elapsed dfCap = write_capacity(path, inputs, setup, EP)
×
72
        println("Time elapsed for writing capacity is")
×
73
        println(elapsed_time_capacity)
×
74
    end
75

76
    if output_settings_d["WritePower"] || output_settings_d["WriteNetRevenue"]
×
77
        elapsed_time_power = @elapsed dfPower = write_power(path, inputs, setup, EP)
×
78
        println("Time elapsed for writing power is")
×
79
        println(elapsed_time_power)
×
80
    end
×
81

×
82
    if output_settings_d["WriteCharge"]
×
83
        elapsed_time_charge = @elapsed write_charge(path, inputs, setup, EP)
×
84
        println("Time elapsed for writing charge is")
×
85
        println(elapsed_time_charge)
×
86
    end
×
87

88
    if output_settings_d["WriteCapacityFactor"]
89
        elapsed_time_capacityfactor = @elapsed write_capacityfactor(path, inputs, setup, EP)
90
        println("Time elapsed for writing capacity factor is")
×
91
        println(elapsed_time_capacityfactor)
×
92
    end
×
93

×
94
    if output_settings_d["WriteStorage"]
×
95
        elapsed_time_storage = @elapsed write_storage(path, inputs, setup, EP)
×
96
        println("Time elapsed for writing storage is")
×
97
        println(elapsed_time_storage)
×
98
    end
×
99

×
100
    if output_settings_d["WriteCurtailment"]
×
101
        elapsed_time_curtailment = @elapsed write_curtailment(path, inputs, setup, EP)
×
102
        println("Time elapsed for writing curtailment is")
×
103
        println(elapsed_time_curtailment)
×
104
    end
×
105

×
106
    if output_settings_d["WriteNSE"]
×
107
        elapsed_time_nse = @elapsed write_nse(path, inputs, setup, EP)
108
        println("Time elapsed for writing nse is")
109
        println(elapsed_time_nse)
110
    end
×
111

×
112
    if output_settings_d["WritePowerBalance"]
113
        elapsed_time_power_balance = @elapsed write_power_balance(path, inputs, setup, EP)
114
        println("Time elapsed for writing power balance is")
115
        println(elapsed_time_power_balance)
×
116
    end
×
117

×
118
    if inputs["Z"] > 1
×
119
        if output_settings_d["WriteTransmissionFlows"]
×
120
            elapsed_time_flows = @elapsed write_transmission_flows(path, inputs, setup, EP)
×
121
            println("Time elapsed for writing transmission flows is")
×
122
            println(elapsed_time_flows)
×
123
        end
124

125
        if output_settings_d["WriteTransmissionLosses"]
126
            elapsed_time_losses = @elapsed write_transmission_losses(path,
×
127
                inputs,
×
128
                setup,
×
129
                EP)
×
130
            println("Time elapsed for writing transmission losses is")
×
131
            println(elapsed_time_losses)
×
132
        end
×
133

×
134
        if setup["NetworkExpansion"] == 1 && output_settings_d["WriteNWExpansion"]
×
135
            elapsed_time_expansion = @elapsed write_nw_expansion(path, inputs, setup, EP)
×
136
            println("Time elapsed for writing network expansion is")
×
137
            println(elapsed_time_expansion)
138
        end
139
    end
×
140

×
141
    if output_settings_d["WriteEmissions"]
×
142
        elapsed_time_emissions = @elapsed write_emissions(path, inputs, setup, EP)
×
143
        println("Time elapsed for writing emissions is")
×
144
        println(elapsed_time_emissions)
×
145
    end
×
146

×
147
    dfVreStor = DataFrame()
148
    if !isempty(inputs["VRE_STOR"])
×
149
        if output_settings_d["WriteVREStor"] || output_settings_d["WriteNetRevenue"]
×
150
            elapsed_time_vrestor = @elapsed dfVreStor = write_vre_stor(path,
×
151
                inputs,
×
152
                setup,
×
153
                EP)
×
154
            println("Time elapsed for writing vre stor is")
×
155
            println(elapsed_time_vrestor)
×
156
        end
×
157
        VS_LDS = inputs["VS_LDS"]
×
158
        VS_STOR = inputs["VS_STOR"]
×
159
    else
×
160
        VS_LDS = []
×
161
        VS_STOR = []
162
    end
163

×
164
    if !isempty(inputs["ALLAM_CYCLE_LOX"])
×
165
        write_allam_capacity(path, inputs, setup, EP)
166
        write_allam_output(path, inputs, setup, EP)
×
167
    end
×
168

169
    if has_duals(EP) == 1
×
170
        if output_settings_d["WriteReliability"]
×
171
            elapsed_time_reliability = @elapsed write_reliability(path, inputs, setup, EP)
172
            println("Time elapsed for writing reliability is")
173
            println(elapsed_time_reliability)
174
        end
×
175
        if !isempty(inputs["STOR_ALL"]) || !isempty(VS_STOR)
176
            if output_settings_d["WriteStorageDual"]
177
                elapsed_time_stordual = @elapsed write_storagedual(path, inputs, setup, EP)
178
                println("Time elapsed for writing storage duals is")
179
                println(elapsed_time_stordual)
×
180
            end
181
        end
182
    end
183

184
    if setup["UCommit"] >= 1
185
        if output_settings_d["WriteCommit"]
186
            elapsed_time_commit = @elapsed write_commit(path, inputs, setup, EP)
187
            println("Time elapsed for writing commitment is")
188
            println(elapsed_time_commit)
189
        end
190

191
        if output_settings_d["WriteStart"]
192
            elapsed_time_start = @elapsed write_start(path, inputs, setup, EP)
193
            println("Time elapsed for writing startup is")
194
            println(elapsed_time_start)
195
        end
196

197
        if output_settings_d["WriteShutdown"]
198
            elapsed_time_shutdown = @elapsed write_shutdown(path, inputs, setup, EP)
199
            println("Time elapsed for writing shutdown is")
200
            println(elapsed_time_shutdown)
201
        end
202

203
        if setup["OperationalReserves"] == 1
204
            if output_settings_d["WriteReg"]
205
                elapsed_time_reg = @elapsed write_reg(path, inputs, setup, EP)
206
                println("Time elapsed for writing regulation is")
207
                println(elapsed_time_reg)
208
            end
209

210
            if output_settings_d["WriteRsv"]
211
                elapsed_time_rsv = @elapsed write_rsv(path, inputs, setup, EP)
212
                println("Time elapsed for writing reserves is")
213
                println(elapsed_time_rsv)
214
            end
215
        end
216

217
        # fusion is only applicable to UCommit=1 resources
218
        if output_settings_d["WriteFusion"] && has_fusion(inputs)
219
            write_fusion_net_capacity_factor(path, inputs, setup, EP)
220
            write_fusion_pulse_starts(path, inputs, setup, EP)
221
        end
222
    end
223

224
    # Output additional variables related inter-period energy transfer via storage
225
    representative_periods = inputs["REP_PERIOD"]
226
    if representative_periods > 1 &&
227
       (!isempty(inputs["STOR_LONG_DURATION"]) || !isempty(VS_LDS))
228
        if output_settings_d["WriteOpWrapLDSStorInit"]
229
            elapsed_time_lds_init = @elapsed write_opwrap_lds_stor_init(path,
230
                inputs,
231
                setup,
232
                EP)
233
            println("Time elapsed for writing lds init is")
234
            println(elapsed_time_lds_init)
235
        end
236

237
        if output_settings_d["WriteOpWrapLDSdStor"]
238
            elapsed_time_lds_dstor = @elapsed write_opwrap_lds_dstor(path,
239
                inputs,
240
                setup,
241
                EP)
242
            println("Time elapsed for writing lds dstor is")
243
            println(elapsed_time_lds_dstor)
244
        end
245
    end
246

247
    if output_settings_d["WriteFuelConsumption"]
248
        elapsed_time_fuel_consumption = @elapsed write_fuel_consumption(path,
249
            inputs,
250
            setup,
251
            EP)
252
        println("Time elapsed for writing fuel consumption is")
253
        println(elapsed_time_fuel_consumption)
254
    end
255

256
    if output_settings_d["WriteCO2"]
257
        elapsed_time_emissions = @elapsed write_co2(path, inputs, setup, EP)
258
        println("Time elapsed for writing co2 is")
259
        println(elapsed_time_emissions)
260
    end
261

262
    if has_maintenance(inputs) && output_settings_d["WriteMaintenance"]
263
        write_maintenance(path, inputs, setup, EP)
264
    end
265

266
    #Write angles when DC_OPF is activated
267
    if setup["DC_OPF"] == 1 && output_settings_d["WriteAngles"]
268
        elapsed_time_angles = @elapsed write_angles(path, inputs, setup, EP)
269
        println("Time elapsed for writing angles is")
270
        println(elapsed_time_angles)
271
    end
272

273
    # Temporary! Suppress these outputs until we know that they are compatable with multi-stage modeling
274
    if setup["MultiStage"] == 0
275
        dfEnergyRevenue = DataFrame()
276
        dfChargingcost = DataFrame()
277
        dfSubRevenue = DataFrame()
278
        dfRegSubRevenue = DataFrame()
279
        if has_duals(EP) == 1
280
            if output_settings_d["WritePrice"]
281
                elapsed_time_price = @elapsed write_price(path, inputs, setup, EP)
282
                println("Time elapsed for writing price is")
283
                println(elapsed_time_price)
284
            end
285

286
            if output_settings_d["WriteEnergyRevenue"] ||
287
               output_settings_d["WriteNetRevenue"]
288
                elapsed_time_energy_rev = @elapsed dfEnergyRevenue = write_energy_revenue(
289
                    path,
290
                    inputs,
291
                    setup,
292
                    EP)
293
                println("Time elapsed for writing energy revenue is")
294
                println(elapsed_time_energy_rev)
295
            end
296

297
            if output_settings_d["WriteChargingCost"] ||
298
               output_settings_d["WriteNetRevenue"]
299
                elapsed_time_charging_cost = @elapsed dfChargingcost = write_charging_cost(
300
                    path,
301
                    inputs,
302
                    setup,
303
                    EP)
304
                println("Time elapsed for writing charging cost is")
305
                println(elapsed_time_charging_cost)
306
            end
307

308
            if output_settings_d["WriteSubsidyRevenue"] ||
309
               output_settings_d["WriteNetRevenue"]
310
                elapsed_time_subsidy = @elapsed dfSubRevenue, dfRegSubRevenue = write_subsidy_revenue(
311
                    path,
312
                    inputs,
313
                    setup,
314
                    EP)
315
                println("Time elapsed for writing subsidy is")
316
                println(elapsed_time_subsidy)
317
            end
318
        end
319

320
        if output_settings_d["WriteTimeWeights"]
321
            elapsed_time_time_weights = @elapsed write_time_weights(path, inputs)
322
            println("Time elapsed for writing time weights is")
323
            println(elapsed_time_time_weights)
324
        end
325

326
        dfESRRev = DataFrame()
327
        if setup["EnergyShareRequirement"] == 1 && has_duals(EP)
328
            dfESR = DataFrame()
329
            if output_settings_d["WriteESRPrices"] ||
330
               output_settings_d["WriteESRRevenue"] || output_settings_d["WriteNetRevenue"]
331
                elapsed_time_esr_prices = @elapsed dfESR = write_esr_prices(path,
332
                    inputs,
333
                    setup,
334
                    EP)
335
                println("Time elapsed for writing esr prices is")
336
                println(elapsed_time_esr_prices)
337
            end
338

339
            if output_settings_d["WriteESRRevenue"] || output_settings_d["WriteNetRevenue"]
340
                elapsed_time_esr_revenue = @elapsed dfESRRev = write_esr_revenue(path,
341
                    inputs,
342
                    setup,
343
                    dfPower,
344
                    dfESR,
345
                    EP)
346
                println("Time elapsed for writing esr revenue is")
347
                println(elapsed_time_esr_revenue)
348
            end
349
        end
350

351
        dfResRevenue = DataFrame()
352
        if setup["CapacityReserveMargin"] == 1 && has_duals(EP)
353
            if output_settings_d["WriteReserveMargin"]
354
                elapsed_time_reserve_margin = @elapsed write_reserve_margin(path, setup, EP)
355
                println("Time elapsed for writing reserve margin is")
356
                println(elapsed_time_reserve_margin)
357
            end
358

359
            if output_settings_d["WriteReserveMarginWithWeights"]
360
                elapsed_time_rsv_margin_w = @elapsed write_reserve_margin_w(path,
361
                    inputs,
362
                    setup,
363
                    EP)
364
                println("Time elapsed for writing reserve margin with weights is")
365
                println(elapsed_time_rsv_margin_w)
366
            end
367

368
            if output_settings_d["WriteVirtualDischarge"]
369
                elapsed_time_virtual_discharge = @elapsed write_virtual_discharge(path,
370
                    inputs,
371
                    setup,
372
                    EP)
373
                println("Time elapsed for writing virtual discharge is")
374
                println(elapsed_time_virtual_discharge)
375
            end
376

377
            if output_settings_d["WriteReserveMarginRevenue"] ||
378
               output_settings_d["WriteNetRevenue"]
379
                elapsed_time_res_rev = @elapsed dfResRevenue = write_reserve_margin_revenue(
380
                    path,
381
                    inputs,
382
                    setup,
383
                    EP)
384
                println("Time elapsed for writing reserve revenue is")
385
                println(elapsed_time_res_rev)
386
            end
387

388
            if haskey(inputs, "dfCapRes_slack") &&
389
               output_settings_d["WriteReserveMarginSlack"]
390
                elapsed_time_rsv_slack = @elapsed write_reserve_margin_slack(path,
391
                    inputs,
392
                    setup,
393
                    EP)
394
                println("Time elapsed for writing reserve margin slack is")
395
                println(elapsed_time_rsv_slack)
396
            end
397

398
            if output_settings_d["WriteCapacityValue"]
399
                elapsed_time_cap_value = @elapsed write_capacity_value(path,
400
                    inputs,
401
                    setup,
402
                    EP)
403
                println("Time elapsed for writing capacity value is")
404
                println(elapsed_time_cap_value)
405
            end
406
        end
407

408
        dfOpRegRevenue = DataFrame()
409
        dfOpRsvRevenue = DataFrame()
410
        if setup["OperationalReserves"] == 1 && has_duals(EP)
411
            elapsed_time_op_res_rev = @elapsed dfOpRegRevenue, dfOpRsvRevenue = write_operating_reserve_regulation_revenue(
412
                path,
413
                inputs,
414
                setup,
415
                EP)
416
            println("Time elapsed for writing oerating reserve and regulation revenue is")
417
            println(elapsed_time_op_res_rev)
418
        end
419

420
        if setup["CO2Cap"] > 0 && has_duals(EP) == 1 && output_settings_d["WriteCO2Cap"]
421
            elapsed_time_co2_cap = @elapsed write_co2_cap(path, inputs, setup, EP)
422
            println("Time elapsed for writing co2 cap is")
423
            println(elapsed_time_co2_cap)
424
        end
425
        if setup["MinCapReq"] == 1 && has_duals(EP) == 1 &&
426
           output_settings_d["WriteMinCapReq"]
427
            elapsed_time_min_cap_req = @elapsed write_minimum_capacity_requirement(path,
428
                inputs,
429
                setup,
430
                EP)
431
            println("Time elapsed for writing minimum capacity requirement is")
432
            println(elapsed_time_min_cap_req)
433
        end
434

435
        if setup["MaxCapReq"] == 1 && has_duals(EP) == 1 &&
436
           output_settings_d["WriteMaxCapReq"]
437
            elapsed_time_max_cap_req = @elapsed write_maximum_capacity_requirement(path,
438
                inputs,
439
                setup,
440
                EP)
441
            println("Time elapsed for writing maximum capacity requirement is")
442
            println(elapsed_time_max_cap_req)
443
        end
444

445
        if setup["HydrogenMinimumProduction"] == 1 && has_duals(EP)
446
            if output_settings_d["WriteHydrogenPrices"]
447
                elapsed_time_hydrogen_prices = @elapsed write_hydrogen_prices(path,
448
                    inputs,
449
                    setup,
450
                    EP)
451
                println("Time elapsed for writing hydrogen prices is")
452
                println(elapsed_time_hydrogen_prices)
453
            end
454
            if setup["HourlyMatching"] == 1 &&
455
               output_settings_d["WriteHourlyMatchingPrices"]
456
                elapsed_time_hourly_matching_prices = @elapsed write_hourly_matching_prices(
457
                    path,
458
                    inputs,
459
                    setup,
460
                    EP)
461
                println("Time elapsed for writing hourly matching prices is")
462
                println(elapsed_time_hourly_matching_prices)
463
            end
464
        end
465

466
        if output_settings_d["WriteNetRevenue"]
467
            elapsed_time_net_rev = @elapsed write_net_revenue(path,
468
                inputs,
469
                setup,
470
                EP,
471
                dfCap,
472
                dfESRRev,
473
                dfResRevenue,
474
                dfChargingcost,
475
                dfPower,
476
                dfEnergyRevenue,
477
                dfSubRevenue,
478
                dfRegSubRevenue,
479
                dfVreStor,
480
                dfOpRegRevenue,
481
                dfOpRsvRevenue)
482
            println("Time elapsed for writing net revenue is")
483
            println(elapsed_time_net_rev)
484
        end
485
    end
486
    ## Print confirmation
487
    println("Wrote outputs to $path")
488

489
    return path
490
end # END output()
491

492
"""
493
        write_annual(fullpath::AbstractString, dfOut::DataFrame)
494

495
Internal function for writing annual outputs. 
496
"""
497
function write_annual(fullpath::AbstractString, dfOut::DataFrame)
498
    push!(dfOut, ["Total" 0 sum(dfOut[!, :AnnualSum], init = 0.0)])
499
    CSV.write(fullpath, dfOut)
500
    return nothing
501
end
502

503
"""
504
        write_fulltimeseries(fullpath::AbstractString, dataOut::Matrix{Float64}, dfOut::DataFrame)
505

506
Internal function for writing full time series outputs. This function wraps the instructions for creating the full time series output files. 
507
"""
508
function write_fulltimeseries(fullpath::AbstractString,
509
        dataOut::Matrix{Float64},
510
        dfOut::DataFrame)
511
    T = size(dataOut, 2)
512
    dfOut = hcat(dfOut, DataFrame(dataOut, :auto))
513
    auxNew_Names = [Symbol("Resource");
514
                    Symbol("Zone");
515
                    Symbol("AnnualSum");
516
                    [Symbol("t$t") for t in 1:T]]
517
    rename!(dfOut, auxNew_Names)
518
    total = DataFrame(
519
        ["Total" 0 sum(dfOut[!, :AnnualSum], init = 0.0) fill(0.0, (1, T))], auxNew_Names)
520
    total[!, 4:(T + 3)] .= sum(dataOut, dims = 1, init = 0.0)
521
    dfOut = vcat(dfOut, total)
522

523
    CSV.write(fullpath, dftranspose(dfOut, false), writeheader = false)
524
    return dfOut
525
end
526

527
"""
528
    write_settings_file(path, setup)
529

530
Internal function for writing settings files
531
"""
532
function write_settings_file(path, setup)
533
    YAML.write_file(joinpath(path, "run_settings.yml"), setup)
534
end
535

536
"""
537
    write_system_env_summary(path::AbstractString)
538

539
Write a summary of the current testing environment to a YAML file. The summary 
540
includes information like the CPU name and architecture, number of CPU threads, 
541
JIT status, operating system kernel, machine name, Julia standard library path, 
542
Julia version and GenX version.
543

544
# Arguments
545
- `path::AbstractString`: The directory path where the YAML file will be written.
546

547
# Output
548
Writes a file named `env_summary.yml` in the specified directory.
549

550
"""
551
function write_system_env_summary(path::AbstractString)
552
    v = pkgversion(GenX)
553
    env_summary = Dict(
554
        :ARCH => getproperty(Sys, :ARCH),
555
        :CPU_NAME => getproperty(Sys, :CPU_NAME),
556
        :CPU_THREADS => getproperty(Sys, :CPU_THREADS),
557
        :JIT => getproperty(Sys, :JIT),
558
        :KERNEL => getproperty(Sys, :KERNEL),
559
        :MACHINE => getproperty(Sys, :MACHINE),
560
        :JULIA_STDLIB => getproperty(Sys, :STDLIB),
561
        :JULIA_VERSION => VERSION,
562
        :GENX_VERSION => v
563
    )
564

565
    YAML.write_file(joinpath(path, "system_summary.yml"), env_summary)
566
end
567

568
# used by ucommit. Could be used by more functions as well.
569
function _create_annualsum_df(inputs::Dict, set::Vector{Int64}, data::Matrix{Float64})
570
    resources = inputs["RESOURCE_NAMES"][set]
571
    zones = inputs["R_ZONES"][set]
572
    weight = inputs["omega"]
573
    df_annual = DataFrame(Resource = resources, Zone = zones)
574
    df_annual.AnnualSum = data * weight
575
    return df_annual
576
end
577

578
function write_temporal_data(
579
        df_annual, data, path::AbstractString, setup::Dict, filename::AbstractString)
580
    filepath = joinpath(path, filename * ".csv")
581
    if setup["WriteOutputs"] == "annual"
582
        # df_annual is expected to have an AnnualSum column.
583
        write_annual(filepath, df_annual)
584
    else # setup["WriteOutputs"] == "full"
585
        df_full = write_fulltimeseries(filepath, data, df_annual)
586
        if setup["OutputFullTimeSeries"] == 1 && setup["TimeDomainReduction"] == 1
587
            write_full_time_series_reconstruction(path, setup, df_full, filename)
588
            @info("Writing Full Time Series for "*filename)
589
        end
590
    end
591
    return nothing
592
end
593

594
@doc raw"""write_full_time_series_reconstruction(path::AbstractString,
595
                            setup::Dict,
596
                            DF::DataFrame,
597
                            name::String)
598
Create a DataFrame with all 8,760 hours of the year from the reduced output.
599

600
This function calls `full_time_series_reconstruction()``, which uses Period_map.csv to create a new DataFrame with 8,760 time steps, as well as other pre-existing rows such as "Zone".
601
For each 52 weeks of the year, the corresponding representative week is taken from the input DataFrame and copied into the new DataFrame. Representative periods that 
602
represent more than one week will appear multiple times in the output. 
603

604
Note: Currently, TDR only gives the representative periods in Period_map for 52 weeks, when a (non-leap) year is 52 weeks + 24 hours. This function takes the last 24 hours of 
605
the time series and copies them to get up to all 8,760 hours in a year.
606

607
This function is called when output files with time series data (e.g. power.csv, emissions.csv) are created, if the setup key "OutputFullTimeSeries" is set to "1".
608

609
# Arguments
610
- `path` (AbstractString): Path input to the results folder
611
- `setup` (Dict): Case setup
612
- `DF` (DataFrame): DataFrame to be reconstructed
613
- `name` (String): Name desired for the .csv file
614

615
"""
616
function write_full_time_series_reconstruction(
617
        path::AbstractString, setup::Dict, DF::DataFrame, name::String)
618
    FullTimeSeriesFolder = setup["OutputFullTimeSeriesFolder"]
619
    output_path = joinpath(path, FullTimeSeriesFolder)
620
    dfOut_full = full_time_series_reconstruction(path, setup, dftranspose(DF, false))
621
    CSV.write(joinpath(output_path, "$name.csv"), dfOut_full, header = false)
622
    return nothing
623
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc