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

urbanopt / geojson-modelica-translator / 10794805970

10 Sep 2024 02:38PM UTC coverage: 88.037% (-0.2%) from 88.188%
10794805970

Pull #648

github

vtnate
skip removing intermediate file if dir, and add debug logging
Pull Request #648: Update code & dependencies to address deprecation warnings

955 of 1167 branches covered (81.83%)

Branch coverage included in aggregate %.

9 of 13 new or added lines in 5 files covered. (69.23%)

1 existing line in 1 file now uncovered.

2651 of 2929 relevant lines covered (90.51%)

1.81 hits per line

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

88.0
/geojson_modelica_translator/geojson_modelica_translator.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
from pathlib import Path
2✔
6

7
from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson
2✔
8
from geojson_modelica_translator.model_connectors.couplings import Coupling, CouplingGraph
2✔
9
from geojson_modelica_translator.model_connectors.districts import District
2✔
10
from geojson_modelica_translator.model_connectors.energy_transfer_systems import CoolingIndirect, HeatingIndirect
2✔
11
from geojson_modelica_translator.model_connectors.load_connectors import Spawn, Teaser, TimeSeries, TimeSeriesMFT
2✔
12
from geojson_modelica_translator.model_connectors.networks import Network2Pipe
2✔
13
from geojson_modelica_translator.model_connectors.networks.ground_coupling import GroundCoupling
2✔
14
from geojson_modelica_translator.model_connectors.networks.network_distribution_pump import NetworkDistributionPump
2✔
15
from geojson_modelica_translator.model_connectors.plants import CoolingPlant
2✔
16
from geojson_modelica_translator.model_connectors.plants.borefield import Borefield
2✔
17
from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP
2✔
18
from geojson_modelica_translator.modelica.modelica_runner import ModelicaRunner
2✔
19
from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters
2✔
20

21
_log = logging.getLogger(__name__)
2✔
22

23

24
# map the system parameter "load_model" to Python class
25
LOAD_MODEL_TO_CLASS = {
2✔
26
    "spawn": Spawn,
27
    "rc": Teaser,
28
    "time_series": TimeSeries,
29
    "time_series_massflow_temperature": TimeSeriesMFT,
30
}
31

32

33
def _parse_couplings(geojson, sys_params, district_type=None):
2✔
34
    """Given config files, construct the necessary models and their couplings which
35
    can then be passed to CouplingGraph.
36

37
    :param geojson: UrbanOptGeoJson
38
    :param sys_params: SystemParameters
39
    :param district_type: str - type of district [None, "4G", "5G"]
40
    :return: list[Coupling], list of couplings to be passed to CouplingGraph
41
    """
42
    # 4G implementation assumes that all generated district energy system models will have:
43
    #   - one heating plant
44
    #   - one cooling plant
45
    #   - one heating distribution network
46
    #   - one cooling distribution network
47
    #   - one heating and cooling ETS per load
48
    # NOTE: loads can be of any type/combination
49
    all_couplings = []
2✔
50

51
    if district_type is None or district_type == "4G":
2✔
52
        # create the plants and networks
53
        cooling_network = Network2Pipe(sys_params)
2✔
54
        cooling_plant = CoolingPlant(sys_params)
2✔
55
        heating_network = Network2Pipe(sys_params)
2✔
56
        heating_plant = HeatingPlantWithOptionalCHP(sys_params)
2✔
57
        all_couplings += [
2✔
58
            Coupling(cooling_plant, cooling_network),
59
            Coupling(heating_plant, heating_network),
60
        ]
61
    elif district_type == "5G":
2!
62
        # create ambient water stub
63
        ambient_water_stub = NetworkDistributionPump(sys_params)
2✔
64
        # create borefield
65
        borefield = Borefield(sys_params)
2✔
66
        # create ground coupling
67
        ground_coupling = GroundCoupling(sys_params)
2✔
68
        all_couplings.append(Coupling(borefield, ambient_water_stub, district_type))
2✔
69
        all_couplings.append(Coupling(ambient_water_stub, ambient_water_stub, district_type))
2✔
70
        all_couplings.append(Coupling(ground_coupling, borefield, district_type="5G"))
2✔
71

72
    # create the loads and their ETSes
73
    for building in geojson.buildings:
2✔
74
        load_model_type = sys_params.get_param_by_id(building.id, "load_model")
2✔
75
        load_class = LOAD_MODEL_TO_CLASS[load_model_type]
2✔
76
        load = load_class(sys_params, building)
2✔
77

78
        if district_type is None or district_type == "4G":
2✔
79
            cooling_indirect = CoolingIndirect(sys_params, building.id)
2✔
80
            all_couplings.append(Coupling(load, cooling_indirect))
2✔
81
            all_couplings.append(Coupling(cooling_indirect, cooling_network))
2✔
82

83
            heating_indirect = HeatingIndirect(sys_params, building.id)
2✔
84
            all_couplings.append(Coupling(load, heating_indirect))
2✔
85
            all_couplings.append(Coupling(heating_indirect, heating_network))
2✔
86
        elif district_type == "5G":
2!
87
            all_couplings.append(Coupling(load, ambient_water_stub, district_type))
2✔
88

89
    return all_couplings
2✔
90

91

92
class ModelicaPackage:
2✔
93
    """Represents a modelica package which can be simulated"""
94

95
    def __init__(self, project_path, project_name):
2✔
96
        self._project_path = project_path
2✔
97
        self._project_name = project_name
2✔
98

99
    def simulate(self):
2✔
100
        """Simulate the package.
101

102
        :return: tuple(bool, pathlib.Path), True or False depending on simulation success
103
            followed by the path to the results directory
104
        """
NEW
105
        _log.debug(f"Model name: {self._project_name}.Districts.DistrictEnergySystem")
×
NEW
106
        _log.debug(f"file to load: {self._project_path / self._project_name / 'package.mo'}")
×
NEW
107
        _log.debug(f"run path: {self._project_path / self._project_name}")
×
108

109
        modelica_runner = ModelicaRunner()
×
110
        return modelica_runner.run_in_docker(
×
111
            action="compile_and_run",
112
            model_name=f"{self._project_name}.Districts.DistrictEnergySystem",
113
            file_to_load=self._project_path / self._project_name / "package.mo",
114
            run_path=self._project_path / self._project_name,
115
        )
116

117

118
class GeoJsonModelicaTranslator:
2✔
119
    """Main class for using the GeoJSON to Modelica Translator."""
120

121
    def __init__(
2✔
122
        self,
123
        geojson_filepath,
124
        sys_params_filepath,
125
        root_dir,
126
        project_name,
127
    ):
128
        """Create an instance of this class
129

130
        :param geojson_filepath: str, path to GeoJSON file
131
        :param sys_params_filepath: str, path to system parameters file
132
        :param root_dir: str, where to create the package
133
        :project_name: str, name of the package
134
        """
135
        if not Path(geojson_filepath).exists():
2!
136
            raise FileNotFoundError(f"GeoJSON file path does not exist: {geojson_filepath}")
×
137
        if not Path(sys_params_filepath).exists():
2!
138
            raise FileNotFoundError(f"System parameters file path does not exist: {sys_params_filepath}")
×
139

140
        self._system_parameters = SystemParameters(sys_params_filepath)
2✔
141

142
        geojson_ids = self._system_parameters.get_default("$.buildings.[*].geojson_id", [])
2✔
143
        self._geojson = UrbanOptGeoJson(geojson_filepath, geojson_ids)
2✔
144

145
        # Use different couplings for each district system type
146
        district_type = self._system_parameters.get_param("district_system")
2✔
147
        if "fifth_generation" in district_type:
2✔
148
            self._couplings = _parse_couplings(self._geojson, self._system_parameters, district_type="5G")
2✔
149
        elif "fourth_generation" in district_type:
2!
150
            self._couplings = _parse_couplings(self._geojson, self._system_parameters)
2✔
151

152
        self._root_dir = root_dir
2✔
153
        self._project_name = project_name
2✔
154
        self._coupling_graph = CouplingGraph(self._couplings)
2✔
155
        if "fifth_generation" in district_type:
2✔
156
            self._district = District(
2✔
157
                self._root_dir, self._project_name, self._system_parameters, self._coupling_graph, self._geojson
158
            )
159
        else:
160
            self._district = District(self._root_dir, self._project_name, self._system_parameters, self._coupling_graph)
2✔
161
        self._package_created = False
2✔
162

163
    def to_modelica(self):
2✔
164
        """Generate the modelica package. Call `simulate` method on the result
165
        to run the package
166

167
        :return: ModelicaPackage
168
        """
169
        self._district.to_modelica()
2✔
170

171
        return ModelicaPackage(self._root_dir, self._project_name)
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