Class: GLHEProGFunctionImport

Inherits:
OpenStudio::Measure::ModelMeasure
  • Object
show all
Defined in:
lib/measures/GLHEProGFunctionImport/measure.rb

Overview

start the measure

Instance Method Summary collapse

Instance Method Details

#arguments(model) ⇒ Object

define the arguments that the user will input



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
# File 'lib/measures/GLHEProGFunctionImport/measure.rb', line 26

def arguments(model)
  args = OpenStudio::Measure::OSArgumentVector.new

  # make an argument for location of G Function .idf file
  g_function_path = OpenStudio::Measure::OSArgument.makeStringArgument('g_function_path', true)
  g_function_path.setDisplayName('G Function File Path (C:/g_function.idf)')
  args << g_function_path

  # Find the names of all plant loops in the model that contain both a
  # district heating and district cooling object
  loop_names = OpenStudio::StringVector.new
  loop_handles = OpenStudio::StringVector.new
  model.getPlantLoops.each do |loop|
    dist_htg_name = nil
    dist_clg_name = nil
    loop.supplyComponents.each do |sc|
      if sc.to_DistrictHeating.is_initialized
        dist_htg_name = sc.name.get
      elsif sc.to_DistrictCooling.is_initialized
        dist_clg_name = sc.name.get
      end
    end

    if dist_htg_name && dist_clg_name
      loop_names << loop.name.get
      loop_handles << loop.handle.to_s
    end
  end

  # make an argument for plant loops
  object = OpenStudio::Measure::OSArgument.makeChoiceArgument('object', loop_handles, loop_names, true)
  object.setDisplayName('Select plant loop to add GLHX to')
  args << object

  return args
end

#nameObject

define the name that a user will see, this method may be deprecated as the display name in PAT comes from the name field in measure.xml



21
22
23
# File 'lib/measures/GLHEProGFunctionImport/measure.rb', line 21

def name
  return 'GLHEProGFunctionImport'
end

#run(model, runner, user_arguments) ⇒ Object

define what happens when the measure is run



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
# File 'lib/measures/GLHEProGFunctionImport/measure.rb', line 64

def run(model, runner, user_arguments)
  super(model, runner, user_arguments)

  # Use the built-in error checking
  if !runner.validateUserArguments(arguments(model), user_arguments)
    return false
  end

  # Assign the user inputs to variables
  g_function_path = runner.getStringArgumentValue('g_function_path', user_arguments)
  object = runner.getOptionalWorkspaceObjectChoiceValue('object', user_arguments, model)

  # Check to make sure the g function file exists
  if !File.exist?(g_function_path)
    runner.registerError("The G Function file '#{g_function_path}' could not be found.")
    return false
  end

  # Check the loop selection
  loop = nil
  if object.empty?
    handle = runner.getDoubleArgumentValue('object', user_arguments)
    if handle.empty?
      runner.registerError('No loop was chosen.')
    else
      runner.registerError("The selected loop with handle '#{handle}' was not found in the model. It may have been removed by another measure.")
    end
    return false
  else
    if object.get.to_PlantLoop.is_initialized
      loop = object.get.to_PlantLoop.get
    else
      runner.registerError('Script Error - argument not showing up as loop.')
      return false
    end
  end

  # Check the location of the GFunction
  if !File.exist?(g_function_path)
    runner.registerError("Coulnd't find the G Function file.  Check file path and try again: '#{g_function_path}'.")
  end

  # Remove the district heating and district cooling objects from the loop
  loop.supplyComponents.each do |sc|
    if sc.to_DistrictHeating.is_initialized || sc.to_DistrictCooling.is_initialized
      sc.remove
      runner.registerInfo("Removed #{sc.name} from #{loop.name}.")
    end
  end

  # Fix up the IDF file (GLHEPro exports slightly malformed IDF)
  idf_text = nil
  File.open(g_function_path, 'r') { |f| idf_text = f.read }
  idf_text = idf_text.gsub('GROUND HEAT EXCHANGER:VERTICAL,', 'GROUNDHEATEXCHANGER:VERTICAL,')
  idf_text = idf_text.gsub(' :,', ',')
  File.open(g_function_path, 'w') { |f2| f2.puts idf_text }

  # Remove the setpointmanager from the supply outlet node
  # TODO: this might be necessary?

  # Add a GLHX to the loop
  glhx = OpenStudio::Model::GroundHeatExchangerVertical.new(model)
  glhx.setName("GLHX for #{loop.name}")
  loop.addSupplyBranchForComponent(glhx)
  runner.registerInfo("Added GLHX to #{loop.name}.")

  # Read the input parameters from the G Function .idf file
  g_function_file = OpenStudio::Workspace.load(g_function_path).get
  glhx_idf = g_function_file.getObjectsByType('GROUNDHEATEXCHANGER:VERTICAL'.to_IddObjectType)[0]
  max_flow = glhx_idf.getDouble(3).get
  num_boreholes = glhx_idf.getInt(4).get
  borehole_length = glhx_idf.getDouble(5).get
  borehole_radius = glhx_idf.getDouble(6).get
  ground_cond = glhx_idf.getDouble(7).get
  ground_ht_cap = glhx_idf.getDouble(8).get
  specific_heat = glhx_idf.getDouble(9).get
  t_ground = glhx_idf.getDouble(10).get
  vol_flowrate = glhx_idf.getDouble(11).get
  grout_cond = glhx_idf.getDouble(12).get
  pipe_cond = glhx_idf.getDouble(13).get
  fluid_cond = glhx_idf.getDouble(14).get
  # runner.registerInfo("fluid_cond = #{fluid_cond}")
  fluid_density = glhx_idf.getDouble(15).get
  # runner.registerInfo("fluid_density = #{fluid_density}")
  fluid_visc = glhx_idf.getDouble(16).get
  # runner.registerInfo("fluid_visc = #{fluid_visc}")
  pipe_diam = glhx_idf.getDouble(17).get
  # runner.registerInfo("pipe_diam = #{pipe_diam}")
  u_tube_sep = glhx_idf.getDouble(18).get
  # runner.registerInfo("u_tube_sep = #{u_tube_sep}")
  pipe_wall_thick = glhx_idf.getDouble(19).get
  # runner.registerInfo("pipe_wall_thick = #{pipe_wall_thick}")
  max_sim = glhx_idf.getInt(20).get
  # runner.registerInfo("max_sim = #{max_sim}")
  num_data_pairs = glhx_idf.getInt(21).get
  # runner.registerInfo("num_data_pairs = #{num_data_pairs}")
  reference_ratio = borehole_radius / borehole_length

  # Set the input parameters of the GLHE
  glhx.setMaximumFlowRate(max_flow)
  glhx.setNumberofBoreHoles(num_boreholes)
  glhx.setBoreHoleLength(borehole_length)
  glhx.setBoreHoleRadius(borehole_radius)
  glhx.setGroundThermalConductivity(ground_cond)
  glhx.setGroundThermalHeatCapacity(ground_ht_cap)
  glhx.setGroundTemperature(t_ground)
  glhx.setDesignFlowRate(vol_flowrate)
  glhx.setGroutThermalConductivity(grout_cond)
  glhx.setPipeThermalConductivity(pipe_cond)
  glhx.setPipeOutDiameter(pipe_diam)
  glhx.setUTubeDistance(u_tube_sep)
  glhx.setPipeThickness(pipe_wall_thick)
  glhx.setMaximumLengthofSimulation(max_sim)
  glhx.setGFunctionReferenceRatio(reference_ratio)

  # Add the G Function pairs after removing all old ones
  glhx.removeAllGFunctions
  pair_range = 22..(76 * 2 + 22 - 2) # Pairs start on field 22
  pair_range.step(2) do |i|
    lntts = glhx_idf.getDouble(i)
    gfnc = glhx_idf.getDouble(i + 1)
    if lntts.empty? || gfnc.empty?
      runner.registerWarning("Pair in fields #{i} and #{i + 1} missing.")
      next
    else
      lntts = lntts.get
      gfnc = gfnc.get
    end
    # runner.registerInfo("G Function pair:  #{lntts} : #{gfnc}")
    glhx.addGFunction(lntts, gfnc)
  end

  return true
end