-
Notifications
You must be signed in to change notification settings - Fork 1
/
worker.py
129 lines (93 loc) · 4.8 KB
/
worker.py
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
## Copyright 2021-2 Tom Brown
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU Affero General Public License as
## published by the Free Software Foundation; either version 3 of the
## License, or (at your option) any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Affero General Public License for more details.
## License and more information at:
## https://github.com/PyPSA/pypsa-server
import os, snakemake, yaml, datetime
from rq import get_current_job
import pandas as pd
resolution_limit_eu = 25
resolution_limit_ct = 3
def solve(assumptions):
print(assumptions)
job = get_current_job()
jobid = job.get_id()
job.meta['status'] = "Reading in data"
job.save_meta()
run_name = jobid
dir_name = "static/results"
if not os.path.isdir(dir_name):
os.mkdir(dir_name)
dir_name = f"static/results/{run_name}"
if not os.path.isdir(dir_name):
os.mkdir(dir_name)
with open("config.yaml", "r") as default_file:
default = yaml.safe_load(default_file)
original_assumptions = default["scenario"].copy()
default["run"] = run_name
default["scenario"]["datetime"] = str(datetime.datetime.now())
for item in ["scenario_name","co2_limit","region","frequency","line_volume","linemax_extension",
"land_transport_electric_share","land_transport_fuel_cell_share",
"bev_dsm","v2g",
"central","tes",
"space_heat_demand", "water_heat_demand", "electricity_demand","land_transport_demand",
"shipping_demand","aviation_demand","industry_demand",
"co2_sequestration_potential",
"co2_sequestration_cost",
"hashid"]:
default["scenario"][item] = assumptions[item]
for tech in ["solar","onwind","offwind"]:
default["scenario"][tech + "_potential"] = assumptions[tech + "_potential"]
for tech in ["solar","onwind","offwind","nuclear","electrolysis","h2_pipeline","land_transmission"]:
#scenario cost is ratio to default cost
default["scenario"][tech + "_cost"] = assumptions[tech + "_cost"]
#check assumptions are clean
for forbidden in [",","\n"]:
if forbidden in default["scenario"]["scenario_name"]:
return {"error" : "Scenario name cannot contain commas or whitespace"}
if (default["scenario"]["region"] == "EU") and (default["scenario"]["frequency"] < resolution_limit_eu):
return {"error" : f"Frequency must be {resolution_limit_eu}-hourly or greater for Europe for computational reasons"}
if (default["scenario"]["region"] != "EU") and (default["scenario"]["frequency"] < resolution_limit_ct):
return {"error" : f"Frequency must be {resolution_limit_ct}-hourly or greater for single countries for computational reasons"}
if default["scenario"]["line_volume"] < 1.0:
return {"error" : "Line volume limit must be greater than 1.0"}
if default["scenario"]["linemax_extension"] < 0:
return {"error" : "Maximum line extension must be greater than 0"}
config_name = os.path.join(dir_name,"config.yaml")
with open(config_name, "w") as output_file:
yaml.dump(default, output_file)
diff = {}
for key in original_assumptions:
if original_assumptions[key] != default["scenario"][key]:
diff[key] = [original_assumptions[key],default["scenario"][key]]
diff_name = os.path.join(dir_name,"diff.yaml")
with open(diff_name, "w") as output_file:
yaml.dump(diff, output_file)
diff_string = ""
for key in diff:
diff_string += f"{key}: {diff[key][0]} -> {diff[key][1]}; "
diff_string = diff_string[:-2]
job.meta['status'] = "Running snakemake workflow"
job.save_meta()
success = snakemake.snakemake("Snakefile",configfiles=[config_name])
if not success:
return {"error" : "Snakemake failed"}
summary = pd.read_csv(f"static/results/{jobid}/csvs/metrics.csv",
names=["item","value"],
index_col=0,
squeeze=True)
with open("static/scenarios.csv","a") as f:
f.write("{},{},{},{},{},{},{}\n".format(jobid,
default["scenario"]["scenario_name"],
default["scenario"]["datetime"],
summary["co2_shadow"],
summary["total costs"],
diff_string,
default["scenario"]["hashid"]))
return {}