Skip to content

Commit 2698801

Browse files
committed
first pass at migration to pyenergyplus
1 parent 0f58837 commit 2698801

File tree

24 files changed

+628
-1069
lines changed

24 files changed

+628
-1069
lines changed

alfalfa_worker/jobs/modelica/step_run.py

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -99,31 +99,6 @@ def update_sim_status(self):
9999
def get_sim_time(self) -> datetime:
100100
return datetime(self.start_datetime.year, 1, 1, 0, 0, 0) + timedelta(seconds=float(self.tc.final_time))
101101

102-
def step(self):
103-
# u represents simulation input values
104-
u = self.default_input.copy()
105-
# look in redis for current writearrays which has an array of controller
106-
# input values, the first element in the array with a value
107-
# is what should be applied to the simulation according to Project Haystack
108-
# convention. If there is no value in the array, then it will not be passed to the
109-
# simulation.
110-
for point in self.run.input_points:
111-
value = point.value
112-
if value is not None:
113-
u[point.name] = value
114-
u[point.name.replace('_u', '_activate')] = 1
115-
116-
y_output = self.tc.advance(u)
117-
self.logger.debug(f"FMU output is {y_output}")
118-
self.update_sim_status()
119-
120-
# get each of the simulation output values and feed to the database
121-
for point in self.run.output_points:
122-
point.value = y_output[point.name]
123-
124-
if self.historian_enabled:
125-
self.write_outputs_to_influx(y_output)
126-
127102
def write_outputs_to_influx(self, outputs):
128103
"""
129104
Write output data to influx
@@ -174,8 +149,26 @@ def setup_points(self):
174149
@message
175150
def advance(self):
176151
self.logger.info("advance called")
177-
self.step()
152+
# u represents simulation input values
153+
u = self.default_input.copy()
154+
# look in redis for current writearrays which has an array of controller
155+
# input values, the first element in the array with a value
156+
# is what should be applied to the simulation according to Project Haystack
157+
# convention. If there is no value in the array, then it will not be passed to the
158+
# simulation.
159+
for point in self.run.input_points:
160+
value = point.value
161+
if value is not None:
162+
u[point.name] = value
163+
u[point.name.replace('_u', '_activate')] = 1
178164

179-
@message
180-
def stop(self):
181-
super().stop()
165+
y_output = self.tc.advance(u)
166+
self.logger.debug(f"FMU output is {y_output}")
167+
self.update_sim_status()
168+
169+
# get each of the simulation output values and feed to the database
170+
for point in self.run.output_points:
171+
point.value = y_output[point.name]
172+
173+
if self.historian_enabled:
174+
self.write_outputs_to_influx(y_output)

alfalfa_worker/jobs/openstudio/create_run.py

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def exec(self):
4444
check_output(['openstudio', str(lib_dir / 'merge_osws.rb'), str(default_workflow_path), str(submitted_osw_path)])
4545

4646
# run workflow
47-
check_output(['openstudio', '-I', '/alfalfa/alfalfa_worker/jobs/openstudio/lib/alfalfa-lib-gem/lib', 'run', '-m', '-w', str(submitted_osw_path)])
47+
check_output(['openstudio', '-I', '/alfalfa/alfalfa_worker/jobs/openstudio/lib/alfalfa-lib-gem/lib', '--verbose', 'run', '-m', '-w', str(submitted_osw_path)])
4848

4949
self.logger.info('Loading Building Metadata')
5050
metadata_json_path = submitted_workflow_path / 'reports' / 'alfalfa_metadata_report_metadata.json'
@@ -56,37 +56,13 @@ def exec(self):
5656
self.logger.info('Generating variables from measure reports')
5757
self.variables = Variables(self.run)
5858
self.variables.load_reports()
59-
self.variables.generate_points()
60-
61-
points_json_path = submitted_workflow_path / 'reports/haystack_report_haystack.json'
62-
mapping_json_path = submitted_workflow_path / 'reports/haystack_report_mapping.json'
63-
64-
self.logger.info("Inserting OpenStudio tags")
65-
self.insert_os_tags(points_json_path, mapping_json_path)
59+
self.variables.write_files(simulation_dir)
6660

6761
self.logger.info("Setting up symlinks")
6862
idf_src_path = submitted_workflow_path / 'run' / 'in.idf'
6963
idf_dest_path = simulation_dir / 'sim.idf'
7064
rel_symlink(idf_src_path, idf_dest_path)
7165

72-
haystack_src_path = submitted_workflow_path / 'reports' / 'haystack_report_mapping.json'
73-
haystack_dest_path = simulation_dir / 'haystack_report_mapping.json'
74-
rel_symlink(haystack_src_path, haystack_dest_path)
75-
76-
haystack_src_path = submitted_workflow_path / 'reports' / 'haystack_report_haystack.json'
77-
haystack_dest_path = simulation_dir / 'haystack_report_haystack.json'
78-
rel_symlink(haystack_src_path, haystack_dest_path)
79-
80-
variables_src_path = submitted_workflow_path / 'reports/export_bcvtb_report_variables.cfg'
81-
variables_dest_path = simulation_dir / 'variables.cfg'
82-
rel_symlink(variables_src_path, variables_dest_path)
83-
84-
# variables.cfg also needs to be located next to the idf to satisfy EnergyPlus conventions
85-
idf_src_dir = idf_src_path.parents[0]
86-
variables_ep_path = idf_src_dir / 'variables.cfg'
87-
rel_symlink(variables_src_path, variables_ep_path)
88-
self.variables.write_files(simulation_dir)
89-
9066
# hack. need to find a more general approach to preserve osw resources that might be needed at simulation time
9167
for file in self.run.glob(submitted_workflow_path / 'python' / '*'):
9268
idfdir = idf_src_path.parents[0]
@@ -108,9 +84,6 @@ def exec(self):
10884
def validate(self) -> None:
10985
assert (self.dir / 'simulation' / 'sim.idf').exists(), "Idf was not created"
11086
assert (self.dir / 'simulation' / 'sim.epw').exists(), "Weather file was not created"
111-
assert (self.dir / 'simulation' / 'haystack_report_mapping.json').exists(), "haystack report json was not created"
112-
assert (self.dir / 'simulation' / 'variables.cfg').exists(), "variables file was not created"
113-
assert (self.dir / 'simulation' / 'haystack_report_haystack.json').exists(), "haystack mapping json was not created"
11487

11588
def cleanup(self) -> None:
11689
super().cleanup()

alfalfa_worker/jobs/openstudio/lib/alfalfa-lib-gem/lib/alfalfa.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
require 'alfalfa_mixin'
22
require 'energy_plus_mixin'
3-
require 'input'
43
require 'openstudio_mixin'
5-
require 'output'
64
require 'point'
5+
require 'alfalfa_component'
76

87
# Module which contains all OpenStudio code
98
module OpenStudio
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
module OpenStudio
2+
module Alfalfa
3+
class Component
4+
attr_reader :parameters
5+
6+
def initialize(**parameters)
7+
@parameters = parameters
8+
end
9+
10+
def is_input_capable
11+
raise "is_input_capable not implemented"
12+
end
13+
14+
def is_output_capable
15+
raise "is_output_capable not implemented"
16+
end
17+
18+
def to_dict
19+
raise "to_dict not implemented"
20+
end
21+
end
22+
23+
class GlobalVariable < Component
24+
def initialize(var_name)
25+
super(var_name: var_name)
26+
end
27+
def is_input_capable
28+
true
29+
end
30+
31+
def is_output_capable
32+
true
33+
end
34+
35+
def to_dict
36+
return {type: "GlobalVariable", parameters: @parameters}
37+
end
38+
end
39+
40+
class InternalVariable < Component
41+
def initialize(variable_type, variable_key)
42+
super(variable_type: variable_type, variable_key: variable_key)
43+
end
44+
45+
def is_input_capable
46+
false
47+
end
48+
49+
def is_output_capable
50+
true
51+
end
52+
53+
def to_dict
54+
return {type: "InternalVariable", parameters: @parameters}
55+
end
56+
end
57+
58+
class OutputVariable < Component
59+
def initialize(variable_name, variable_key)
60+
super(variable_name: variable_name, variable_key: variable_key)
61+
end
62+
63+
def is_input_capable
64+
false
65+
end
66+
67+
def is_output_capable
68+
true
69+
end
70+
71+
def to_dict
72+
return {type: "OutputVariable", parameters: @parameters}
73+
end
74+
end
75+
76+
class Meter < Component
77+
def initialize(meter_name)
78+
super(meter_name: meter_name)
79+
end
80+
81+
def is_input_capable
82+
false
83+
end
84+
85+
def is_output_capable
86+
true
87+
end
88+
89+
def to_dict
90+
return {type: "Meter", parameters: @parameters}
91+
end
92+
end
93+
94+
class Actuator < Component
95+
def initialize(component_type, control_type, actuator_key)
96+
super(component_type: component_type, control_type: control_type, actuator_key: actuator_key)
97+
end
98+
99+
def is_input_capable
100+
true
101+
end
102+
103+
def is_output_capable
104+
true
105+
end
106+
107+
def to_dict
108+
return {type: "Actuator", parameters: @parameters}
109+
end
110+
end
111+
end
112+
end

0 commit comments

Comments
 (0)