def test_add_model_obj(self):
        filename = os.path.join(self.data_dir, "test_1.mo")
        new_filename = os.path.join(self.output_dir, "test_1_output_5.mo")
        f1 = InputParser(filename)
        data = [
            'annotation (Placement(transformation(extent={{-10,90},{10,110}}), iconTransformation(extent={{-10,90},{10,110}})));'  # noqa
        ]
        f1.add_model_object(
            "Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a", "port_a", data
        )
        f1.save_as(new_filename)

        # verify in the new file that the new model object exists
        f2 = InputParser(new_filename)
        index, model = f2.find_model_object(
            "Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a"
        )
        self.assertFalse(filecmp.cmp(filename, new_filename))
        self.assertGreaterEqual(index, 0)
Пример #2
0
    def post_process(self, scaffold, building_names, keep_original_models=False):
        """
        Cleanup the export of the TEASER files into a format suitable for the district-based analysis. This includes
        the following:

            * Update the partial to inherit from the GeojsonExport class defined in MBL.
            * Rename the files to remove the names of the buildings
            * Move the files to the Loads level and remove the Project folder (default export method from TEASER)
            * Add heat port
            * Add return temperature
            * Remove weaDat and rely on weaBus

        :param project_name: string, name of the project which will be used to set the package.mo file
        :param root_building_dir: string, where the project will be ultimately saved
        :param building_names: list, names of the buildings that need to be cleaned up after export
        :return: None
        """
        for b in building_names:
            # create a list of strings that we need to replace in all the file as we go along
            string_replace_list = []

            # create a new modelica based path for the buildings # TODO: make this work at the toplevel, somehow.
            b_modelica_path = ModelicaPath(f"B{b}", scaffold.loads_path.files_dir, True)

            # copy over the entire model to the new location
            copytree(
                os.path.join(scaffold.loads_path.files_dir, f"Project/B{b}/B{b}_Models"),
                b_modelica_path.files_dir,
            )

            # read in the package to apply the changes as they other files are processed
            # TODO: these should be linked, so a rename method should act across the model and the package.order
            package = PackageParser(os.path.join(scaffold.loads_path.files_dir, f"B{b}"))

            # move the internal gains files to a new resources folder
            mat_files = glob.glob(os.path.join(scaffold.loads_path.files_dir, f"B{b}/*.txt"))
            for f in mat_files:
                new_file_name = os.path.basename(f).replace(f"B{b}", "")
                os.rename(f, f"{b_modelica_path.resources_dir}/{new_file_name}")
                string_replace_list.append(
                    (
                        f"Project/B{b}/B{b}_Models/{os.path.basename(f)}",
                        f"Loads/{b_modelica_path.resources_relative_dir}/{new_file_name}",
                    )
                )

            # process each of the building models
            mo_files = glob.glob(os.path.join(scaffold.loads_path.files_dir, f"B{b}/*.mo"))
            for f in mo_files:
                # ignore the package.mo file
                if os.path.basename(f) == "package.mo":
                    continue

                mofile = InputParser(f)

                # previous paths and replace with the new one.
                # Make sure to update the names of any resources as well.
                mofile.replace_within_string(f"{scaffold.project_name}.Loads.B{b}")

                # remove ReaderTMY3
                mofile.remove_object("ReaderTMY3")

                # updating path to internal loads
                for s in string_replace_list:
                    mofile.replace_model_string("Modelica.Blocks.Sources.CombiTimeTable", "internalGains", s[0], s[1])

                # add heat port
                data = [
                    "annotation (Placement(transformation(extent={{-10,90},{10,110}}), "
                    "iconTransformation(extent={{-10,90},{10,110}})));"
                ]
                mofile.add_model_object(
                    "Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a", "port_a", data,
                )

                # add TAir output
                # TODO: read in the object by name -- parse the parenthetic content
                instance = 'TAir(\n    quantity="ThermodynamicTemperature", unit="K", displayUnit="degC")'
                data = [
                    '"Room air temperature"',
                    "annotation (Placement(transformation(extent={{100,-10},{120,10}})));",
                ]
                mofile.add_model_object(
                    "Buildings.Controls.OBC.CDL.Interfaces.RealOutput", instance, data
                )

                # All existing weaDat.weaBus connections need to be updated to simply weaBus
                mofile.replace_connect_string('weaDat.weaBus', None, 'weaBus', None, True)
                # Now remove the redundant weaBus -> weaBus connection
                mofile.remove_connect_string('weaBus', 'weaBus')

                # add new port connections
                if self.system_parameters.get_param(
                        "buildings.default.load_model_parameters.rc.order", default=2) == 1:
                    data = "annotation (Line(points={{0,100},{96,100},{96,20},{92,20}}, color={191,0,0}))"
                    mofile.add_connect("port_a", "thermalZoneOneElement.intGainsConv", data)

                    data = "annotation (Line(points={{93,32},{98,32},{98,0},{110,0}}, color={0,0,127}))"
                    mofile.add_connect("thermalZoneOneElement.TAir", "TAir", data)
                elif self.system_parameters.get_param(
                        "buildings.default.load_model_parameters.rc.order", default=2) == 2:
                    data = "annotation (Line(points={{0,100},{96,100},{96,20},{92,20}}, color={191,0,0}))"
                    mofile.add_connect("port_a", "thermalZoneTwoElements.intGainsConv", data)

                    data = "annotation (Line(points={{93,32},{98,32},{98,0},{110,0}}, color={0,0,127}))"
                    mofile.add_connect("thermalZoneTwoElements.TAir", "TAir", data)
                elif self.system_parameters.get_param(
                        "buildings.default.load_model_parameters.rc.order", default=2) == 4:
                    data = "annotation (Line(points={{0,100},{96,100},{96,20},{92,20}}, color={191,0,0}))"
                    mofile.add_connect("port_a", "thermalZoneFourElements.intGainsConv", data)

                    data = "annotation (Line(points={{93,32},{98,32},{98,0},{110,0}}, color={0,0,127}))"
                    mofile.add_connect("thermalZoneFourElements.TAir", "TAir", data)

                # change the name of the modelica model to remove the building id, update in package too!
                new_model_name = mofile.model["name"].split("_")[1]
                package.rename_model(mofile.model["name"], new_model_name)
                mofile.model["name"] = new_model_name

                # Save as the new filename (without building ID)
                new_filename = os.path.join(
                    scaffold.loads_path.files_dir, f'B{b}/{os.path.basename(f).split("_")[1]}'
                )
                mofile.save_as(new_filename)
                os.remove(f)

            # save the updated package.mo and package.order.
            new_package = PackageParser.new_from_template(
                package.path, f"B{b}", package.order, within=f"{scaffold.project_name}.Loads"
            )
            new_package.save()

        # remaining clean up tasks across the entire exported project
        if not keep_original_models:
            shutil.rmtree(os.path.join(scaffold.loads_path.files_dir, "Project"))

        # now create the Loads level package. This (for now) will create the package without considering any existing
        # files in the Loads directory.
        # add in the silly 'B' before the building names
        package = PackageParser.new_from_template(
            scaffold.loads_path.files_dir,
            "Loads", ["B" + b for b in building_names],
            within=f"{scaffold.project_name}"
        )
        package.save()