Question-and-Answer Resource for the Building Energy Modeling Community
Get s tarted with the Help page
Ask Your Question
7

How to model air stratification in an industrial hall?

asked 2016-12-02 03:30:50 -0500

Camille gravatar image

updated 2016-12-02 16:51:15 -0500

Hi everyone, I'm new with OpenStudio and EnergyPlus. I'm trying to do an energy simulation of an industrial hall. The height of this building is 7m so the air stratification is really important. Do you know how to deal with it? I've tried to write an energyPlus measure with the RoomAir:TemperaturePattern:ConstantGradient. Here is my code : Thank you very much for your help

    class ChangeTheRoomType < OpenStudio::Ruleset::ModelUserScript

def name
    return "Taking stratification into account"
    end

def description
    return "Change the room type in order to model air stratification with a certain temperature gradient"
    end

# arguments description
def argments(model)
    ThermOffset = OpenStudio::Ruleset::OSArgument::makeDoubleArgument('ThermOffset',true)
    ThermOffset.setDisplayName('Thermostat Offset')
    ThermOffset.setDefaultValue(0.0)
    args<<ThermOffset

    ReturnAirOffset = OpenStudio::Ruleset::OSArgument::makeDoubleArgument('ReturnAirOffset',true)
    ReturnAirOffset.setDisplayName('Return Air Offset')
    ReturnAirOffset.setDefaultValue(0.0)
    args<<ReturnAirOffset

    ExhaustAirOffset = OpenStudio::Ruleset::OSArgument::makeDoubleArgument('ExhaustAirOffset',true)
    ExhaustAirOffset.setDisplayName('Exhaust Air Offset')
    ExhaustAirOffset.setDefaultValue(0.0)
    args<<ExhaustAirOffset

    return args
    end 

#When the measure is run    
def run(model,runner,user_arguments)
    super(model, runner, user_arguments)

    # errors management
    if not runner.validateUserArguments(argumentents(model),user_arguments)
        return false
    end

    #assign to variables
    ThermOffset=runner.getDoubleArgumentValue("ThermOffset", user_arguments)
    ReturnAirOffset=runner.getDoubleArgumentValue("ReturnAirOffset",user_arguments)
    ExhaustAirOffset=runner.getDoubleArgumentValue("ExhaustAirOffset",user_arguments)

    #Instruction in EP
    Instruction=[]
    #this instruction doesnt use the arguments, it s a test
    Instruction = "
  RoomAir:TemperaturePattern:ConstantGradient,
    StratProduction,  !- Name
    1,                   !- Control Integer for Pattern Control Schedule Name
    0.0,                     !- Thermostat Offset {deltaC}
    0.0,                     !- Return Air Offset {deltaC}
    1.5,                     !- Exhaust Air Offset {deltaC}
    0.5;                     !- Temperature Gradient {K/m}"

    return true
end
ChangeTheRoomType.new.registerWithApplication
edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted
3

answered 2016-12-07 11:49:38 -0500

updated 2016-12-09 10:22:28 -0500

@Camille, you made a string in your run method, but you need to add code that makes a workspace object from the string. Add the code below before the return true. Also ruby variables should start with lowercase character so change Instruction to instruction

idfObject = OpenStudio::IdfObject::load(instruction)
object = idfObject.get
wsObject = workspace.addObject(object)
new_object = wsObject.get

Optionally you can add an info message that spits back the name

runner.registerInfo("An object named '#{new_object.getString(0)}' was added.")

Then repeat this code with a new string for the additional object that @Archmage mentioned in his answer.

Update:

@Camille, in your answer you asked about the difference between an OpenStudio and EnergyPlus measure. For some background look at the digram below. The OSM is the working format for an OpenStudio model. It is what users typically work with, but it isn't what EnergyPlus needs; so prior to running a simulation we convert the OSM file to an IDF file and hand that off to EnergyPlus. If a user needs to model something, like room air models, that EnergyPlus supports but OpenStudio doesn't, an EnergyPlus measure, which is run after translation to IDF but before it is handed to EnergyPlus, will support this. The diagram also shows a third kind of measure, called a reporting measure that runs AfterEnergyPlus has run the simulation. It has access to the SQL file, the final OSM, and the final IDF. The reporting measure does have one method that runs prior to the simulation to inject output variable requests that it will need.

image description

edit flag offensive delete link more

Comments

@Camille, if you want to share this measure and have the community help develop it feel free to post it on the UnmetHours openstudio-measures GitHub.com repository (or I can post it if you need help). Other users can extend the measure add testing, or add argument input validation.

David Goldwasser gravatar image David Goldwasser  ( 2016-12-07 11:55:33 -0500 )edit

Thank you David ! When my measure is finished I'll share it with the community for sure! I'll ask you how to do it though :)

Camille gravatar image Camille  ( 2016-12-08 01:52:43 -0500 )edit
3

answered 2016-12-07 09:14:46 -0500

Archmage gravatar image

I cannot help with the OS measure, but looking at this it seems you may be missing the IDF objects called RoomAirModelType and RoomAir:TemperaturePattern:UserDefined that are also needed here to setup a zone to use the constant gradient pattern.

edit flag offensive delete link more

Comments

Thank you very much for your help ! I totally forgot about it !

Camille gravatar image Camille  ( 2016-12-08 01:47:27 -0500 )edit
1

answered 2016-12-08 10:42:44 -0500

Camille gravatar image

@David, I'm getting closer (at least, I hope so :) ) but I still have some problems with my E+ measure :

  • I don't understand what's the difference between OS measure and E+ measure
  • If I add a workspace object, is my measure E+ or OS?
  • How do you makeChoiceArgument for thermal spaces? I've seen that you already did it in several OS measures but I don't know how to deal with it in E+ measure. (You'll see I used one of your measure and I tried to adapt it for E+ measure ^^ but maybe I'm completely mistaken )

Could you help me? :)

Here is my code :

Thank you very much for your help

    # see the URL below for information on how to write OpenStudio measures
# http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/

# start the measure
class ChangeTheRoomType < OpenStudio::Ruleset::WorkspaceUserScript

# human readable name
def name
return "ChangeTheRoomType"
end

# human readable description
def description
return "Take stratification into account"
end

# human readable description of modeling approach
def modeler_description
return "By changing the room type to constant gradient (vertical)"
end

def arguments(workspace)
args = OpenStudio::Ruleset::OSArgumentVector.new

#----------------------THERMAL ZONE INTO ARGUMENTS------------------------------------------
#populate choice argument for thermal zones in the model
zone_handles = OpenStudio::StringVector.new
zone_display_names = OpenStudio::StringVector.new

#putting zone names into hash
zone_hash = {}
workspace.getObjectsByType("Zone".to_IddObjectType) do |zone|
  zone_hash[zone.name.to_s] = zone
end

#looping through sorted hash of zones
zone_hash.sort.map do |zone_name, zone|
  zone_handles << zone.handle.to_s
  zone_display_names << zone_name
end

#make an argument for zones
zone = OpenStudio::Ruleset::OSArgument::makeChoiceArgument("zone", zone_handles, zone_display_names, true)
zone.setDisplayName("Choose Thermal Zones to add zone ventilation to.")
args << zone
#----------------------------NAME ARGUMENT------------------------------------------
nameRoomAirModel = OpenStudio::Ruleset::OSArgument::makeStringArgument('nameRoomAirModel', true)
nameRoomAirModel.setDisplayName('Name the pattern')
args << nameRoomAirModel

#-------------------------------TEMPERATURE INPUT INTO ARGUMENTS -------------------------------
thermOffset = OpenStudio::Ruleset::OSArgument::makeDoubleArgument('thermOffset',true)
thermOffset.setDisplayName('thermostat Offset')
thermOffset.setDefaultValue(0.0)
args << thermOffset

returnAirOffset = OpenStudio::Ruleset::OSArgument::makeDoubleArgument('returnAirOffset',true)
returnAirOffset.setDisplayName('return Air Offset')
returnAirOffset.setDefaultValue(0.0)
args<<returnAirOffset

exhaustAirOffset = OpenStudio::Ruleset::OSArgument::makeDoubleArgument('exhaustAirOffset',true)
exhaustAirOffset.setDisplayName('exhaust Air Offset')
exhaustAirOffset.setDefaultValue(0.0)
args << exhaustAirOffset

return args
end 

#When the measure is run    
def run(workspace,runner,user_arguments)
super(workspace, runner, user_arguments)

# errors management
if not runner.validateUserArguments(argumentents(workspace),user_arguments)
    return false
end

#assign to variables
nameRoomAirModel=runner.getStringArgumentValue('nameRoomAirModel',user_arguments)
zone=runner.getOptionalWorkspaceObjectChoiceValue('zone',user_arguments, workspace)
thermOffset=runner.getDoubleArgumentValue('thermOffset', user_arguments)
returnAirOffset=runner.getDoubleArgumentValue('returnAirOffset',user_arguments)
exhaustAirOffset=runner.getDoubleArgumentValue('exhaustAirOffset',user_arguments)

#Array to hold new IDF Objects = RoomAirModelType here
string_RoomAirModelType=[]

#this instruction doesnt use the arguments, it s a test
string_RoomAirModelType << "
RoomAir:TemperaturePattern:UserDefined,
#{nameRoomAirModel} ,   ! Name
#{zone} ,               ! Zone Name (thermal zone) = user choice
AllwaysOn,          ! Availability Schedule Name = integer used need to be the same as the RoomAir:TemperaturePattern:ConstantGradient (here is 1)
Roomair Pattern 1;      ! Pattern Control Schedule Name"

#Instruction in EP
string_RoomAirModelGradient=[]
#this instruction doesnt use the arguments, it s a test
string_RoomAirModelGradient << "
RoomAir:TemperaturePattern:ConstantGradient,
StratProduction,        !- Name
1,                      !- Control Integer for Pattern Control Schedule Name
#{thermOffset},         !- Thermostat Offset {deltaC}
#{returnAirOffset} ,    !- Return Air Offset {deltaC ...
(more)
edit flag offensive delete link more

Comments

1

Just a note: I'm not sure why you're initializing string_RoomAirModelType as an array, but that probably will make idfObject = OpenStudio::IdfObject::load(string_RoomAirModelType) throw an error, since you're passing an array to a method that expects a string.

Eric Ringold gravatar image Eric Ringold  ( 2016-12-08 16:58:19 -0500 )edit

Good point ! Thank you :)

Camille gravatar image Camille  ( 2016-12-09 02:10:15 -0500 )edit

Haven't been able to look at this but I can check it out this weekend.

David Goldwasser gravatar image David Goldwasser  ( 2016-12-09 10:28:27 -0500 )edit
1

@Camille. I posted a working copy of the measure to UnmetHours GitHub repo. We don't have a lot of examples of choice objects from workspace (vs. model). It ends up being a choice argument in the run section that has the string of the workspace object name. I took two schedules that were hard coded and made them string arguments. Ideally they could be choice arguments as well, but string was easier for now since there may be a number of schedule object types vs. just a single object type

David Goldwasser gravatar image David Goldwasser  ( 2016-12-10 14:35:54 -0500 )edit

@ David, thanks a lot. I'm going to take a closer look at this! The diagram is amazing, I think I got it now, thanks again :)

Camille gravatar image Camille  ( 2016-12-12 07:22:26 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

 

Question Tools

1 follower

Stats

Asked: 2016-12-02 03:30:50 -0500

Seen: 578 times

Last updated: Dec 09 '16