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

Revision history [back]

click to hide/show revision 1
initial version

I've tried a million different ways of getting this to work, unfortunately the inner working of the Workspace / OptionalWorkspace (undocumented?) / IdfObject remain unclear to me. For reference: some documentation is available here: https://s3.amazonaws.com/openstudio-sdk-documentation/index.html under utilities and model.

For now I've written a work-around in which I write the current workspace to a temporary file, append the .idf file file I want to load, and then reload the workspace:

# Save the model
f = "#{File.dirname(__FILE__)}/resources/tmp.idf"
workspace.save(OpenStudio::Path.new(f),true)
# Append .idf
fo = File.open(f,'a')
fo.print(File.read("#{File.dirname(__FILE__)}/resources/import.idf"))
# Reload workspace
workspace = OpenStudio::Workspace::load("#{File.dirname(__FILE__)}/resources/tmp.idf").get

I've tried Credits go to macumber and David. Solution was in using the .toIdfFile and adding all objects simulataneously using the .addObjects.

I created an importer for a million different ways of getting this to work, unfortunately the inner working of the Workspace / OptionalWorkspace (undocumented?) / IdfObject remain unclear to me. For reference: some documentation is available here: https://s3.amazonaws.com/openstudio-sdk-documentation/index.html under utilities YAML-file, which holds data for fixing the remaining missing references. This way the connection between the original .osm-file and model.imported .idf-file can be fixed.

For now I've written I don't belong to any group in the BCL-library, so for ppl looking for a work-around in which I write the current workspace to a temporary file, append the way to import an .idf file file I want to load, and then reload the workspace:fixing remaining links, below the full code, including example .yml file.

# Save the model
f = "#{File.dirname(__FILE__)}/resources/tmp.idf"
workspace.save(OpenStudio::Path.new(f),true)
# Append .idf
fo = File.open(f,'a')
fo.print(File.read("#{File.dirname(__FILE__)}/resources/import.idf"))
# Reload workspace
workspace = OpenStudio::Workspace::load("#{File.dirname(__FILE__)}/resources/tmp.idf").get
YAML style file containing params to be adjusted
---
- class: BuildingSurface:Detailed
  name: Surface Name
  field: 4
  value: OtherSideConditionsModel
- class: BuildingSurface:Detailed
  name: Surface Name
  field: 5
  value: ICS Collector 1 OSCM
- class: SurfaceProperty:ExteriorNaturalVentedCavity
  name: ICSRoofPaverExtVentCav1
  field: 11
  value: Zolder voor
- class: SolarCollector:IntegralCollectorStorage
  name: Collector 1
  field: 2
  value: Surface Name

.

class ImportIDFFile < OpenStudio::Ruleset::WorkspaceUserScript

  # human readable name
  def name
    return " Import IDF-file"
  end

  # human readable description
  def description
    return "This measure can be used to import functionality from EnergyPlus, which is not exposed (yet) to OpenStudio. E.g. HVAC-components can be imported."
  end

  # human readable description of modeling approach
  def modeler_description
    return "Imports an .idf-file from the /resources folder. Connections from .idf-file which are not satisfied internally (e.g. references to objects in the .osm-file) will be broken. Use the .yml-file to restore these references, example file provided.

Note that this measure is run after the preprocessor. This means you cannot use HVACTemplate objects, instead expand these first and copy from the .expidf-file.

"
  end

  # define the arguments that the user will input
  def arguments(workspace)
    args = OpenStudio::Ruleset::OSArgumentVector.new

    idf_file = OpenStudio::Ruleset::OSArgument::makeStringArgument('idf_file', false)
    idf_file.setDisplayName("IDF-file")
    idf_file.setDescription("The name of the IDF-file residing in the resources directory of this measure")
    idf_file.setDefaultValue('import.idf')
    args << idf_file

    yml_file = OpenStudio::Ruleset::OSArgument::makeStringArgument('yml_file', false)
    yml_file.setDisplayName("YML-file")
    yml_file.setDescription("The name of the YML-file residing in the resources directory of this measure")
    yml_file.setDefaultValue('import.yml')
    args << yml_file

    return args
  end 

  # define what happens when the measure is run
  def run(workspace, runner, user_arguments)
    super(workspace, runner, user_arguments)

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

    # Assign the user inputs to variables
    idf_file = runner.getStringArgumentValue("idf_file", user_arguments)
    yml_file = runner.getStringArgumentValue("yml_file", user_arguments)

    # Parameters
    idf_file = "#{File.dirname(__FILE__)}/resources/#{idf_file}"
    yml_file = "#{File.dirname(__FILE__)}/resources/#{yml_file}"

    # Process .idf file
    if !idf_file.empty?
      # Load workspace to be imported
      idf = OpenStudio::Workspace::load(idf_file)
      if idf.empty?
        runner.registerError("Cannot load #{idf_file}")
        return false
      end
      idf = idf.get.toIdfFile()
      workspace.addObjects(idf.objects)
    end

    # Process .yml file
    if !yml_file.empty?
      require 'yaml'
      fixfields = YAML::load_file(yml_file)

      fixfields.each do |f|
        o = workspace.getObjectByTypeAndName(f['class'].to_IddObjectType,f['name'])
        if o.empty?
          runner.registerError("No #{f['class']} found with name #{f['name']}")
          return false
        end
        o = o.get
        if !o.setString(f['field'],f['value'])
          runner.registerError("Unable to set #{f['value']} to field #{f['field']} in #{f['name']}")
          return false
        end
      end
    end

    return true

  end

end 

# register the measure to be used by the application
ImportIDFFile.new.registerWithApplication