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)
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()