• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

urbanopt / geojson-modelica-translator / 9766694116

02 Jul 2024 07:13PM UTC coverage: 88.188% (-0.5%) from 88.687%
9766694116

push

github

web-flow
Templates and tests for horizontal piping modeling (#627)

* Add customized mo files

* Add kIns and use each

* Introduce a new template for ground coupling

* Supplemental table for calculating soil temperature

* Placeholder python file for ground coupling

* Pass more pipe material parameters

* Add example sys_pamas file for tests

* Modified ground coupling template

* Ground coupling instance

* Update package names

* Modify dis to take more inputs

* Update py file, not final yet

* Update ground_coupling.py

* add method to read a feature from a geojson file by id

* method to read a geojson feature from a jsonpath

* code to read from geojson to templtate

* add test line to attempt injecting from geojson into template

* test for ground_coupling

* empty ground_coupling coupling templates - WIP

* update dependencies

* Add equations for calculating wall thickness

* Add function for searching for weather station

* finalize py file

* get pipe lengths in datDes

* build new coupling

* move dis instance to new coupling

* Access data of sys_params

* Move things in coupling

* Fix typo

* Change pipe length list to be global

* Modify test to instantiate ground coupling

* Reading geojson in district.py, might cause problem to other district tests

* New geojson with thermal connectors for testing

* Modify parameter paths

* Update geojson file name in test

* Rearrange couplings

* Update coupling list in test

* Fix within statements

* Update some parameters

* Update access to borefield id

* Update access to num_buildings in template

* Add TODO

* Change pump input type

* Change how lDis and lEnd are populated

* Replace sqaure brackets

* Convert ft to meter

* Pre-commit changes

* skip a lint check in district.py. A different PR refactors this, so ignore for now

* format modelica code via pre-commit

* Avoid using excel reader

... (continued)

955 of 1165 branches covered (81.97%)

Branch coverage included in aggregate %.

80 of 94 new or added lines in 5 files covered. (85.11%)

2 existing lines in 1 file now uncovered.

2651 of 2924 relevant lines covered (90.66%)

1.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.26
/geojson_modelica_translator/model_connectors/networks/ground_coupling.py
1
# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors.
2
# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md
3

4
import logging
2✔
5
import os
2✔
6
import re
2✔
7
from pathlib import Path
2✔
8

9
import pandas as pd
2✔
10
from modelica_builder.package_parser import PackageParser
2✔
11

12
from geojson_modelica_translator.model_connectors.networks.network_base import NetworkBase
2✔
13
from geojson_modelica_translator.utils import ModelicaPath, simple_uuid
2✔
14

15
logger = logging.getLogger(__name__)
2✔
16

17

18
class GroundCoupling(NetworkBase):
2✔
19
    model_name = "GroundCoupling"
2✔
20

21
    def __init__(self, system_parameters):
2✔
22
        super().__init__(system_parameters)
2✔
23
        self.id = "groCou_" + simple_uuid()
2✔
24
        self.ground_coupling_name = "GroundCoupling_" + simple_uuid()
2✔
25

26
        self.required_mo_files.append(os.path.join(self.template_dir, "UndisturbedSoilTemperature.mo"))
2✔
27
        self.required_mo_files.append(os.path.join(self.template_dir, "UnidirectionalSeries.mo"))
2✔
28
        self.required_mo_files.append(os.path.join(self.template_dir, "ConnectionSeriesAutosize.mo"))
2✔
29

30
    def to_modelica(self, scaffold):
2✔
31
        """
32
        Create timeSeries models based on the data in the buildings and geojsons
33

34
        :param scaffold: Scaffold object, Scaffold of the entire directory of the project.
35
        """
36

37
        template_data = {
2✔
38
            "hydraulic_diameter": self.system_parameters.get_param(
39
                "$.district_system.fifth_generation.horizontal_piping_parameters.hydraulic_diameter"
40
            ),
41
            "insulation_thickness": self.system_parameters.get_param(
42
                "$.district_system.fifth_generation.horizontal_piping_parameters.insulation_thickness"
43
            ),
44
            "insulation_conductivity": self.system_parameters.get_param(
45
                "$.district_system.fifth_generation.horizontal_piping_parameters.insulation_conductivity"
46
            ),
47
            "diameter_ratio": self.system_parameters.get_param(
48
                "$.district_system.fifth_generation.horizontal_piping_parameters.diameter_ratio"
49
            ),
50
            "roughness": self.system_parameters.get_param(
51
                "$.district_system.fifth_generation.horizontal_piping_parameters.roughness"
52
            ),
53
            "rho_cp": self.system_parameters.get_param(
54
                "$.district_system.fifth_generation.horizontal_piping_parameters.rho_cp"
55
            ),
56
            "number_of_segments": self.system_parameters.get_param(
57
                "$.district_system.fifth_generation.horizontal_piping_parameters.number_of_segments"
58
            ),
59
            "buried_depth": self.system_parameters.get_param(
60
                "$.district_system.fifth_generation.horizontal_piping_parameters.buried_depth"
61
            ),
62
            "weather": self.system_parameters.get_param("$.weather"),
63
            "num_buildings": len(self.system_parameters.get_param("$.buildings")),
64
        }
65

66
        # process pipe wall thickness
67
        if template_data["hydraulic_diameter"] and template_data["diameter_ratio"]:
2!
68
            template_data["pipe_wall_thickness"] = template_data["hydraulic_diameter"] / (
2✔
69
                template_data["diameter_ratio"] - 2
70
            )
71
        else:
NEW
72
            template_data["pipe_wall_thickness"] = None
×
73

74
        # get weather station name from weather file
75
        parts = template_data["weather"].split("/")[-1].split("_")
2✔
76
        if len(parts) == 4:
2!
77
            station_name = parts[2]
2✔
NEW
78
        elif len(parts) == 3:
×
NEW
79
            station_name = parts[1]
×
80
        station_name = re.sub(r"\d+", "", station_name).replace(".", " ")
2✔
81

82
        # search for coefficients for calculating soil temperature based on station
83
        coefs = pd.read_csv(Path(__file__).parent / "data" / "Soil_temp_coefficients.csv")
2✔
84
        matching_rows = coefs[coefs.apply(lambda row: row.astype(str).str.contains(station_name).any(), axis=1)]
2✔
85
        if len(matching_rows) == 0:
2!
NEW
86
            raise ValueError(
×
87
                "No matching weather station has been found. Please check your weather file name format."
88
                "(e.g., USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.mos)"
89
            )
90
        else:
91
            template_data["surface_temp"] = matching_rows["Ts,avg, C"].iloc[0] + 273.15
2✔
92
            template_data["first_amplitude"] = matching_rows["Ts,amplitude,1, C"].iloc[0]
2✔
93
            template_data["second_amplitude"] = matching_rows["Ts,amplitude,2, C"].iloc[0]
2✔
94
            template_data["first_phase_lag"] = matching_rows["PL1"].iloc[0]
2✔
95
            template_data["second_phase_lag"] = matching_rows["PL2"].iloc[0]
2✔
96

97
        # create horizontal piping package paths
98
        b_modelica_path = ModelicaPath(self.ground_coupling_name, scaffold.networks_path.files_dir, True)
2✔
99

100
        # load templates
101
        coupling_template = self.template_env.get_template("GroundCoupling.mot")
2✔
102

103
        self.run_template(
2✔
104
            coupling_template,
105
            os.path.join(b_modelica_path.files_dir, "GroundCoupling.mo"),
106
            project_name=scaffold.project_name,
107
            model_name=self.ground_coupling_name,
108
            piping_data=template_data,
109
        )
110

111
        # generate Modelica package
112
        self.copy_required_mo_files(
2✔
113
            dest_folder=scaffold.networks_path.files_dir, within=f"{scaffold.project_name}.Networks"
114
        )
115

116
        # GroundCoupling_ package
117
        subpackage_models = ["GroundCoupling"]
2✔
118
        ground_coupling_package = PackageParser.new_from_template(
2✔
119
            path=b_modelica_path.files_dir,
120
            name=self.ground_coupling_name,
121
            order=subpackage_models,
122
            within=f"{scaffold.project_name}.Networks",
123
        )
124
        ground_coupling_package.save()
2✔
125

126
        # Networks package
127
        package = PackageParser(scaffold.project_path)
2✔
128
        if "Networks" not in package.order:
2!
129
            package.add_model("Networks")
2✔
130
            package.save()
2✔
131

132
        package_models = [self.ground_coupling_name] + [Path(mo).stem for mo in self.required_mo_files]
2✔
133
        networks_package = PackageParser(scaffold.networks_path.files_dir)
2✔
134
        if networks_package.order_data is None:
2!
135
            networks_package = PackageParser.new_from_template(
2✔
136
                path=scaffold.networks_path.files_dir,
137
                name="Networks",
138
                order=package_models,
139
                within=scaffold.project_name,
140
            )
141
        else:
NEW
142
            for model_name in package_models:
×
NEW
143
                networks_package.add_model(model_name)
×
144
        networks_package.save()
2✔
145

146
    def get_modelica_type(self, scaffold):
2✔
147
        return f"Networks.{self.ground_coupling_name}.GroundCoupling"
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc