Exemple #1
0
def validate_sim_par(sim_par_json):
    """Validate all properties of a SimulationParameter JSON against the Honeybee schema.

    \b
    Args:
        sim_par_json: Full path to a SimulationParameter JSON file.
    """
    try:
        # first check the JSON against the OpenAPI specification
        click.echo('Validating SimulationParameter JSON ...')
        schema_simulation_parameter.SimulationParameter.parse_file(
            sim_par_json)
        click.echo('Pydantic validation passed.')
        # re-serialize to make sure no errors are found in re-serialization
        with open(sim_par_json) as json_file:
            data = json.load(json_file)
        SimulationParameter.from_dict(data)
        click.echo('Python re-serialization passed.')
        # if we made it to this point, report that the object is valid
        click.echo('Congratulations! Your SimulationParameter JSON is valid!')
    except Exception as e:
        _logger.exception(
            'SimulationParameter validation failed.\n{}'.format(e))
        sys.exit(1)
    else:
        sys.exit(0)
Exemple #2
0
def dict_to_simulation(sim_dict, raise_exception=True):
    """Get a Python object of any Simulation object from a dictionary.

    Args:
        sim_dict: A dictionary of any Honeybee energy simulation object. Note
            that this should be a non-abridged dictionary to be valid.
        raise_exception: Boolean to note whether an excpetion should be raised
            if the object is not identified as a simulation object. Default: True.

    Returns:
        A Python object derived from the input sim_dict.
    """
    try:  # get the type key from the dictionary
        sim_type = sim_dict['type']
    except KeyError:
        raise ValueError('Simulation dictionary lacks required "type" key.')

    if sim_type == 'SimulationControl':
        return SimulationControl.from_dict(sim_dict)
    elif sim_type == 'RunPeriod':
        return RunPeriod.from_dict(sim_dict)
    elif sim_type == 'DaylightSavingTime':
        return DaylightSavingTime.from_dict(sim_dict)
    elif sim_type == 'ShadowCalculation':
        return ShadowCalculation.from_dict(sim_dict)
    elif sim_type == 'SizingParameter':
        return SizingParameter.from_dict(sim_dict)
    elif sim_type == 'SimulationOutput':
        return SimulationOutput.from_dict(sim_dict)
    elif sim_type == 'SimulationParameter':
        return SimulationParameter.from_dict(sim_dict)
    elif raise_exception:
        raise ValueError(
            '{} is not a recognized energy Simulation type'.format(sim_type))
Exemple #3
0
def test_comfort_sim_par():
    """Test the comfort_sim_par command."""
    runner = CliRunner()
    ddy_path = './tests/ddy/chicago.ddy'

    result = runner.invoke(comfort_sim_par, [ddy_path])
    assert result.exit_code == 0
    simpar_dict = json.loads(result.output)
    sim_par = SimulationParameter.from_dict(simpar_dict)

    assert 'Zone Mean Air Temperature' in sim_par.output.outputs
    assert 'Surface Inside Face Temperature' in sim_par.output.outputs
Exemple #4
0
def test_default_sim_par():
    """Test the default_sim_par command."""
    runner = CliRunner()
    ddy_path = './tests/ddy/chicago.ddy'

    result = runner.invoke(default_sim_par, [ddy_path])
    assert result.exit_code == 0
    simpar_dict = json.loads(result.output)
    sim_par = SimulationParameter.from_dict(simpar_dict)

    assert 'Zone Ideal Loads Supply Air Total Cooling Energy' in sim_par.output.outputs
    assert 'Chiller Electricity Energy' in sim_par.output.outputs
Exemple #5
0
def test_load_balance_sim_par():
    """Test the load_balance_sim_par command."""
    runner = CliRunner()
    ddy_path = './tests/ddy/chicago.ddy'

    result = runner.invoke(load_balance_sim_par, [ddy_path, '--load-type', 'Sensible'])
    assert result.exit_code == 0
    simpar_dict = json.loads(result.output)
    sim_par = SimulationParameter.from_dict(simpar_dict)

    assert 'Zone Ideal Loads Supply Air Sensible Cooling Energy' \
        in sim_par.output.outputs
    assert 'Zone People Sensible Heating Energy' in sim_par.output.outputs
def test_custom_sim_par():
    """Test the custom_sim_par command."""
    runner = CliRunner()
    ddy_path = './tests/ddy/chicago.ddy'

    result = runner.invoke(
        custom_sim_par,
        [ddy_path, 'Surface Window Transmitted Beam Solar Radiation Energy'])
    assert result.exit_code == 0
    simpar_dict = json.loads(result.output)
    sim_par = SimulationParameter.from_dict(simpar_dict)

    assert 'Surface Window Transmitted Beam Solar Radiation Energy' in sim_par.output.outputs
Exemple #7
0
def model_to_idf(model_json, sim_par_json, additional_str, output_file):
    """Translate a Model JSON file to an IDF using direct-to-idf translators.
    \n
    The resulting IDF should be simulate-able but not all Model properties might
    make it into the IDF given that the direct-to-idf translators are used.
    \n
    Args:
        model_json: Full path to a Model JSON file.
    """
    try:
        # check that the model JSON is there
        assert os.path.isfile(model_json), \
            'No Model JSON file found at {}.'.format(model_json)

        # check that the simulation parameters are there and load them
        if sim_par_json is not None:
            assert os.path.isfile(sim_par_json), \
                'No simulation parameter file found at {}.'.format(sim_par_json)
            with open(sim_par_json) as json_file:
                data = json.load(json_file)
            sim_par = SimulationParameter.from_dict(data)
        else:
            sim_par = SimulationParameter()
            sim_par.output.add_zone_energy_use()
            sim_par.output.add_hvac_energy_use()

        # re-serialize the Model to Python
        with open(model_json) as json_file:
            data = json.load(json_file)
        model = Model.from_dict(data)

        # set the schedule directory in case it is needed
        sch_path = os.path.abspath(model_json) if 'stdout' in str(output_file) \
            else os.path.abspath(str(output_file))
        sch_directory = os.path.join(os.path.split(sch_path)[0], 'schedules')

        # create the strings for simulation paramters and model
        ver_str = energyplus_idf_version() if folders.energyplus_version \
            is not None else energyplus_idf_version((9, 2, 0))
        sim_par_str = sim_par.to_idf()
        model_str = model.to.idf(model, schedule_directory=sch_directory)
        idf_str = '\n\n'.join(
            [ver_str, sim_par_str, model_str, additional_str])

        # write out the IDF file
        output_file.write(idf_str)
    except Exception as e:
        _logger.exception('Model translation failed.\n{}'.format(e))
        sys.exit(1)
    else:
        sys.exit(0)
Exemple #8
0
def model_to_idf(model_json, sim_par_json, additional_str, output_file):
    """Translate a Model JSON file to an IDF using direct-to-idf translators.

    If the model contains a feature that is not translate-able through direct-to-idf
    translators, an exception will be raised.

    \b
    Args:
        model_json: Full path to a Model JSON file.
    """
    try:
        # load simulation parameters or generate default ones
        if sim_par_json is not None:
            with open(sim_par_json) as json_file:
                data = json.load(json_file)
            sim_par = SimulationParameter.from_dict(data)
        else:
            sim_par = SimulationParameter()
            sim_par.output.add_zone_energy_use()
            sim_par.output.add_hvac_energy_use()

        # re-serialize the Model to Python
        with open(model_json) as json_file:
            data = json.load(json_file)
        model = Model.from_dict(data)

        # set the schedule directory in case it is needed
        sch_path = os.path.abspath(model_json) if 'stdout' in str(output_file) \
            else os.path.abspath(str(output_file))
        sch_directory = os.path.join(os.path.split(sch_path)[0], 'schedules')

        # create the strings for simulation paramters and model
        ver_str = energyplus_idf_version() if folders.energyplus_version \
            is not None else ''
        sim_par_str = sim_par.to_idf()
        model_str = model.to.idf(model, schedule_directory=sch_directory)
        idf_str = '\n\n'.join(
            [ver_str, sim_par_str, model_str, additional_str])

        # write out the IDF file
        output_file.write(idf_str)
    except Exception as e:
        _logger.exception('Model translation failed.\n{}'.format(e))
        sys.exit(1)
    else:
        sys.exit(0)
Exemple #9
0
def test_simulation_parameter_dict_methods():
    """Test the to/from dict methods."""
    sim_par = SimulationParameter()
    output = SimulationOutput()
    output.add_zone_energy_use()
    sim_par.output = output
    run_period = RunPeriod(Date(1, 1), Date(6, 21))
    sim_par.run_period = run_period
    sim_par.timestep = 4
    sim_control_alt = SimulationControl(run_for_sizing_periods=True,
                                        run_for_run_periods=False)
    sim_par.simulation_control = sim_control_alt
    shadow_calc_alt = ShadowCalculation(calculation_frequency=20)
    sim_par.shadow_calculation = shadow_calc_alt
    sizing_alt = SizingParameter(None, 1, 1)
    relative_path = './tests/ddy/chicago.ddy'
    sizing_alt.add_from_ddy_996_004(relative_path)
    sim_par.sizing_parameter = sizing_alt

    sim_par_dict = sim_par.to_dict()
    new_sim_par = SimulationParameter.from_dict(sim_par_dict)
    new_sim_par.sizing_parameter.apply_location(sizing_alt[0].location)
    assert new_sim_par == sim_par
    assert sim_par_dict == new_sim_par.to_dict()
Exemple #10
0
def simulate_model(model_json, epw_file, sim_par_json, base_osw, folder,
                   check_model, log_file):
    """Simulate a Model JSON file in EnergyPlus.

    \b
    Args:
        model_json: Full path to a Model JSON file.
        epw_file: Full path to an .epw file.
    """
    try:
        # get a ddy variable that might get used later
        epw_folder, epw_file_name = os.path.split(epw_file)
        ddy_file = os.path.join(epw_folder,
                                epw_file_name.replace('.epw', '.ddy'))

        # set the default folder to the default if it's not specified
        if folder is None:
            proj_name = \
                os.path.basename(model_json).replace('.json', '').replace('.hbjson', '')
            folder = os.path.join(folders.default_simulation_folder, proj_name,
                                  'OpenStudio')
        preparedir(folder, remove_content=False)

        # process the simulation parameters and write new ones if necessary
        def ddy_from_epw(epw_file, sim_par):
            """Produce a DDY from an EPW file."""
            epw_obj = EPW(epw_file)
            des_days = [
                epw_obj.approximate_design_day('WinterDesignDay'),
                epw_obj.approximate_design_day('SummerDesignDay')
            ]
            sim_par.sizing_parameter.design_days = des_days

        def write_sim_par(sim_par):
            """Write simulation parameter object to a JSON."""
            sim_par_dict = sim_par.to_dict()
            sp_json = os.path.abspath(
                os.path.join(folder, 'simulation_parameter.json'))
            with open(sp_json, 'w') as fp:
                json.dump(sim_par_dict, fp)
            return sp_json

        if sim_par_json is None:  # generate some default simulation parameters
            sim_par = SimulationParameter()
            sim_par.output.add_zone_energy_use()
            sim_par.output.add_hvac_energy_use()
        else:
            with open(sim_par_json) as json_file:
                data = json.load(json_file)
            sim_par = SimulationParameter.from_dict(data)
        if len(sim_par.sizing_parameter.design_days) == 0 and os.path.isfile(
                ddy_file):
            try:
                sim_par.sizing_parameter.add_from_ddy_996_004(ddy_file)
            except AssertionError:  # no design days within the DDY file
                ddy_from_epw(epw_file, sim_par)
        elif len(sim_par.sizing_parameter.design_days) == 0:
            ddy_from_epw(epw_file, sim_par)
        sim_par_json = write_sim_par(sim_par)

        # run the Model re-serialization and check if specified
        if check_model:
            model_json = measure_compatible_model_json(model_json, folder)

        # Write the osw file to translate the model to osm
        osw = to_openstudio_osw(folder,
                                model_json,
                                sim_par_json,
                                base_osw=base_osw,
                                epw_file=epw_file)

        # run the measure to translate the model JSON to an openstudio measure
        if osw is not None and os.path.isfile(osw):
            gen_files = [osw]
            if base_osw is None:  # separate the OS CLI run from the E+ run
                osm, idf = run_osw(osw)
                # run the resulting idf through EnergyPlus
                if idf is not None and os.path.isfile(idf):
                    gen_files.extend([osm, idf])
                    sql, eio, rdd, html, err = run_idf(idf, epw_file)
                    if err is not None and os.path.isfile(err):
                        gen_files.extend([sql, eio, rdd, html, err])
                    else:
                        raise Exception('Running EnergyPlus failed.')
                else:
                    raise Exception('Running OpenStudio CLI failed.')
            else:  # run the whole simulation with the OpenStudio CLI
                osm, idf = run_osw(osw, measures_only=False)
                if idf is not None and os.path.isfile(idf):
                    gen_files.extend([osm, idf])
                else:
                    raise Exception('Running OpenStudio CLI failed.')
                sql, eio, rdd, html, err = output_energyplus_files(
                    os.path.dirname(idf))
                if os.path.isfile(err):
                    gen_files.extend([sql, eio, rdd, html, err])
                else:
                    raise Exception('Running EnergyPlus failed.')
            log_file.write(json.dumps(gen_files))
        else:
            raise Exception('Writing OSW file failed.')
    except Exception as e:
        _logger.exception('Model simulation failed.\n{}'.format(e))
        sys.exit(1)
    else:
        sys.exit(0)
def simulate_model(model_json, epw_file, sim_par_json, base_osw, folder,
                   check_model, log_file):
    """Simulate a Model JSON file in EnergyPlus.
    \n
    Args:
        model_json: Full path to a Model JSON file.\n
        epw_file: Full path to an .epw file.
    """
    try:
        # check that the model JSON and the EPW file is there
        assert os.path.isfile(model_json), \
            'No Model JSON file found at {}.'.format(model_json)
        assert os.path.isfile(epw_file), \
            'No EPW file found at {}.'.format(epw_file)
        # ddy variable that might get used later
        epw_folder, epw_file_name = os.path.split(epw_file)
        ddy_file = os.path.join(epw_folder,
                                epw_file_name.replace('.epw', '.ddy'))

        # set the default folder to the default if it's not specified
        if folder is None:
            proj_name = os.path.basename(model_json).replace('.json', '')
            folder = os.path.join(folders.default_simulation_folder, proj_name,
                                  'OpenStudio')
            preparedir(folder, remove_content=False)

        # process the simulation parameters and write new ones if necessary
        def write_sim_par(sim_par):
            """Write simulation parameter object to a JSON."""
            sim_par_dict = sim_par.to_dict()
            sp_json = os.path.abspath(
                os.path.join(folder, 'simulation_parameter.json'))
            with open(sp_json, 'w') as fp:
                json.dump(sim_par_dict, fp)
            return sp_json

        if sim_par_json is None:  # generate some default simulation parameters
            sim_par = SimulationParameter()
            sim_par.output.add_zone_energy_use()
            sim_par.output.add_hvac_energy_use()
            if os.path.isfile(ddy_file):
                sim_par.sizing_parameter.add_from_ddy_996_004(ddy_file)
            else:
                raise ValueError(
                    'No sim-par-json was input and there is no .ddy file next to '
                    'the .epw.\nAt least one of these two cirtieria must be satisfied '
                    'for a successful simulation.')
            sim_par_json = write_sim_par(sim_par)
        else:
            assert os.path.isfile(sim_par_json), \
                'No simulation parameter file found at {}.'.format(sim_par_json)
            with open(sim_par_json) as json_file:
                data = json.load(json_file)
            sim_par = SimulationParameter.from_dict(data)
            if len(sim_par.sizing_parameter.design_days
                   ) == 0 and os.path.isfile(ddy_file):
                sim_par.sizing_parameter.add_from_ddy_996_004(ddy_file)
                sim_par_json = write_sim_par(sim_par)
            elif len(sim_par.sizing_parameter.design_days) == 0:
                raise ValueError(
                    'No design days were found in the input sim-par-json and there is '
                    'no .ddy file next to the .epw.\nAt least one of these two cirtieria '
                    'must be satisfied for a successful simulation.')

        # run the Model re-serialization and check if specified
        if check_model:
            model_json = measure_compatible_model_json(model_json, folder)

        # Write the osw file to translate the model to osm
        osw = to_openstudio_osw(folder,
                                model_json,
                                sim_par_json,
                                base_osw=base_osw,
                                epw_file=epw_file)

        # run the measure to translate the model JSON to an openstudio measure
        if osw is not None and os.path.isfile(osw):
            gen_files = [osw]
            if base_osw is None:  # separate the OS CLI run from the E+ run
                osm, idf = run_osw(osw)
                # run the resulting idf through EnergyPlus
                if idf is not None and os.path.isfile(idf):
                    gen_files.extend([osm, idf])
                    sql, eio, rdd, html, err = run_idf(idf, epw_file)
                    if err is not None and os.path.isfile(err):
                        gen_files.extend([sql, eio, rdd, html, err])
                    else:
                        raise Exception('Running EnergyPlus failed.')
                else:
                    raise Exception('Running OpenStudio CLI failed.')
            else:  # run the whole simulation with the OpenStudio CLI
                osm, idf = run_osw(osw, measures_only=False)
                if idf is not None and os.path.isfile(idf):
                    gen_files.extend([osm, idf])
                else:
                    raise Exception('Running OpenStudio CLI failed.')
                sql, eio, rdd, html, err = output_energyplus_files(
                    os.path.dirname(idf))
                if os.path.isfile(err):
                    gen_files.extend([sql, eio, rdd, html, err])
                else:
                    raise Exception('Running EnergyPlus failed.')
            log_file.write(json.dumps(gen_files))
        else:
            raise Exception('Writing OSW file failed.')
    except Exception as e:
        _logger.exception('Model simulation failed.\n{}'.format(e))
        sys.exit(1)
    else:
        sys.exit(0)
Exemple #12
0
def simulate_model(model_json, epw_file, sim_par_json, obj_per_model,
                   multiplier, no_plenum, no_cap, shade_dist, base_osw, folder,
                   log_file):
    """Simulate a Dragonfly Model JSON file in EnergyPlus.

    \b
    Args:
        model_json: Full path to a Dragonfly Model JSON file.
        epw_file: Full path to an .epw file.
    """
    try:
        # get a ddy variable that might get used later
        epw_folder, epw_file_name = os.path.split(epw_file)
        ddy_file = os.path.join(epw_folder,
                                epw_file_name.replace('.epw', '.ddy'))

        # set the default folder to the default if it's not specified
        if folder is None:
            proj_name = \
                os.path.basename(model_json).replace('.json', '').replace('.dfjson', '')
            folder = os.path.join(folders.default_simulation_folder, proj_name,
                                  'OpenStudio')
        preparedir(folder, remove_content=False)

        # process the simulation parameters and write new ones if necessary
        def ddy_from_epw(epw_file, sim_par):
            """Produce a DDY from an EPW file."""
            epw_obj = EPW(epw_file)
            des_days = [
                epw_obj.approximate_design_day('WinterDesignDay'),
                epw_obj.approximate_design_day('SummerDesignDay')
            ]
            sim_par.sizing_parameter.design_days = des_days

        def write_sim_par(sim_par):
            """Write simulation parameter object to a JSON."""
            sim_par_dict = sim_par.to_dict()
            sp_json = os.path.abspath(
                os.path.join(folder, 'simulation_parameter.json'))
            with open(sp_json, 'w') as fp:
                json.dump(sim_par_dict, fp)
            return sp_json

        if sim_par_json is None:  # generate some default simulation parameters
            sim_par = SimulationParameter()
            sim_par.output.add_zone_energy_use()
            sim_par.output.add_hvac_energy_use()
        else:
            with open(sim_par_json) as json_file:
                data = json.load(json_file)
            sim_par = SimulationParameter.from_dict(data)
        if len(sim_par.sizing_parameter.design_days) == 0 and os.path.isfile(
                ddy_file):
            try:
                sim_par.sizing_parameter.add_from_ddy_996_004(ddy_file)
            except AssertionError:  # no design days within the DDY file
                ddy_from_epw(epw_file, sim_par)
        elif len(sim_par.sizing_parameter.design_days) == 0:
            ddy_from_epw(epw_file, sim_par)
        sim_par_json = write_sim_par(sim_par)

        # re-serialize the Dragonfly Model
        with open(model_json) as json_file:
            data = json.load(json_file)
        model = Model.from_dict(data)
        model.convert_to_units('Meters')

        # convert Dragonfly Model to Honeybee
        add_plenum = not no_plenum
        cap = not no_cap
        hb_models = model.to_honeybee(obj_per_model, shade_dist, multiplier,
                                      add_plenum, cap)

        # write out the honeybee JSONs
        osms = []
        idfs = []
        sqls = []
        for hb_model in hb_models:
            model_dict = hb_model.to_dict(triangulate_sub_faces=True)
            directory = os.path.join(folder, hb_model.identifier)
            file_path = os.path.join(directory,
                                     '{}.json'.format(hb_model.identifier))
            preparedir(directory, remove_content=False)  # create the directory
            with open(file_path, 'w') as fp:
                json.dump(model_dict, fp, indent=4)

            # Write the osw file to translate the model to osm
            osw = to_openstudio_osw(directory,
                                    file_path,
                                    sim_par_json,
                                    base_osw=base_osw,
                                    epw_file=epw_file)

            # run the measure to translate the model JSON to an openstudio measure
            if osw is not None and os.path.isfile(osw):
                if base_osw is None:  # separate the OS CLI run from the E+ run
                    osm, idf = run_osw(osw)
                    if idf is not None and os.path.isfile(idf):
                        sql, eio, rdd, html, err = run_idf(idf, epw_file)
                        osms.append(osm)
                        idfs.append(idf)
                        sqls.append(sql)
                        if err is None or not os.path.isfile(err):
                            raise Exception('Running EnergyPlus failed.')
                    else:
                        raise Exception('Running OpenStudio CLI failed.')
                else:  # run the whole simulation with the OpenStudio CLI
                    osm, idf = run_osw(osw, measures_only=False)
                    if idf is None or not os.path.isfile(idf):
                        raise Exception('Running OpenStudio CLI failed.')
                    sql, eio, rdd, html, err = \
                        output_energyplus_files(os.path.dirname(idf))
                    if err is None or not os.path.isfile(err):
                        raise Exception('Running EnergyPlus failed.')
                    osms.append(osm)
                    idfs.append(idf)
                    sqls.append(sql)
            else:
                raise Exception('Writing OSW file failed.')
        log_file.write(json.dumps({'osm': osms, 'idf': idfs, 'sql': sqls}))
    except Exception as e:
        _logger.exception('Model translation failed.\n{}'.format(e))
        sys.exit(1)
    else:
        sys.exit(0)
Exemple #13
0
def model_to_idf(model_json, sim_par_json, obj_per_model, multiplier,
                 no_plenum, no_cap, shade_dist, folder, log_file):
    """Translate a Model JSON file to an IDF using direct-to-idf translators.

    The resulting IDF should be simulate-able but not all Model properties might
    make it into the IDF given that the direct-to-idf translators are used.

    \b
    Args:
        model_json: Full path to a Dragonfly Model JSON file.
    """
    try:
        # set the default folder to the default if it's not specified
        if folder is None:
            proj_name = \
                os.path.basename(model_json).replace('.json', '').replace('.dfjson', '')
            folder = os.path.join(hb_folders.default_simulation_folder,
                                  proj_name, 'EnergyPlus')
        preparedir(folder, remove_content=False)

        # check that the simulation parameters are there and load them
        if sim_par_json is not None:
            with open(sim_par_json) as json_file:
                data = json.load(json_file)
            sim_par = SimulationParameter.from_dict(data)
        else:
            sim_par = SimulationParameter()
            sim_par.output.add_zone_energy_use()
            sim_par.output.add_hvac_energy_use()

        # re-serialize the Dragonfly Model
        with open(model_json) as json_file:
            data = json.load(json_file)
        df_model = Model.from_dict(data)
        df_model.convert_to_units('Meters')

        # convert Dragonfly Model to Honeybee
        add_plenum = not no_plenum
        cap = not no_cap
        hb_models = df_model.to_honeybee(obj_per_model, shade_dist, multiplier,
                                         add_plenum, cap)

        # set the schedule directory in case it is needed
        sch_path = os.path.abspath(model_json) if 'stdout' in str(log_file) \
            else os.path.abspath(str(log_file))
        sch_directory = os.path.join(os.path.split(sch_path)[0], 'schedules')

        # write out the honeybee JSONs
        idfs = []
        for hb_model in hb_models:
            # create the strings for simulation paramters and model
            ver_str = energyplus_idf_version() if folders.energyplus_version \
                is not None else ''
            sim_par_str = sim_par.to_idf()
            model_str = hb_model.to.idf(hb_model,
                                        schedule_directory=sch_directory)
            idf_str = '\n\n'.join([ver_str, sim_par_str, model_str])

            # write out the IDF files
            idf_path = os.path.join(folder,
                                    '{}.idf'.format(hb_model.identifier))
            with open(idf_path, 'w') as idf_file:
                idf_file.write(idf_str)
            idfs.append(idf_path)
        log_file.write('\n'.join(idfs))
    except Exception as e:
        _logger.exception('Model translation failed.\n{}\n'.format(e))
        sys.exit(1)
    else:
        sys.exit(0)