OpenPinch 0.2.1__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/__init__.py +4 -2
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_problem/__init__.py +4 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_problem/_output.py +58 -36
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_problem/_plot_accessor.py +40 -0
- openpinch-0.2.3/OpenPinch/classes/_problem/_result_extraction.py +48 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_problem/_target_accessor.py +21 -0
- openpinch-0.2.1/OpenPinch/utils/multiscale_targeting.py → openpinch-0.2.3/OpenPinch/classes/_problem/_target_dispatch.py +11 -57
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_problem/_validation.py +11 -1
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_stream_collection/_helpers.py +2 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_workspace/views.py +16 -1
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/pinch_problem.py +106 -12
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/stream.py +42 -62
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/stream_collection.py +3 -1
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/value.py +22 -10
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/zone.py +2 -0
- openpinch-0.2.3/OpenPinch/data/notebooks/01_basic_pinch_and_dtcont_sensitivity.ipynb +224 -0
- openpinch-0.2.3/OpenPinch/data/notebooks/02_total_site_targets_and_sugcc.ipynb +343 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/data/notebooks/03_carnot_hpr_comparison.ipynb +74 -66
- openpinch-0.2.3/OpenPinch/data/notebooks/04_multistate_targeting_and_state_comparison.ipynb +297 -0
- openpinch-0.2.3/OpenPinch/data/notebooks/05_schema_service_and_output_workflows.ipynb +284 -0
- openpinch-0.2.3/OpenPinch/data/sample_cases/crude_preheat_train_multistate.json +306 -0
- openpinch-0.2.3/OpenPinch/data/sample_cases/zonal_site_multistate.json +954 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/__init__.py +2 -2
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/config_metadata.py +2 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/enums.py +6 -8
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/problem_table_types.py +2 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/schemas/__init__.py +13 -3
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/schemas/common.py +1 -2
- openpinch-0.2.3/OpenPinch/lib/schemas/report_units.py +169 -0
- openpinch-0.2.3/OpenPinch/lib/schemas/reporting.py +144 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/schemas/targets.py +192 -52
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/schemas/workspace.py +2 -0
- openpinch-0.2.3/OpenPinch/lib/unit_system.py +265 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/__init__.py +6 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/common/capital_cost_and_area_targeting.py +3 -1
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/common/gcc_manipulation.py +3 -1
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/common/graph_data.py +122 -7
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/common/graph_series_meta.py +18 -1
- openpinch-0.2.3/OpenPinch/services/common/miscellaneous.py +166 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/common/problem_table_analysis.py +8 -11
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/common/temperature_driving_force.py +3 -1
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/common/utility_targeting.py +22 -12
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/direct_heat_integration/direct_integration_entry.py +3 -1
- openpinch-0.2.3/OpenPinch/services/exergy_analysis/__init__.py +15 -0
- openpinch-0.2.3/OpenPinch/services/exergy_analysis/exergy_targeting_entry.py +450 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/common/layout.py +2 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/common/preprocessing.py +2 -1
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/common/shared.py +4 -2
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/heat_pump_and_refrigeration_entry.py +11 -8
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/targeting_services/cascade_vapour_compression.py +2 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/targeting_services/multi_simple_carnot.py +2 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/targeting_services/multi_simple_vapour_compression.py +2 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/indirect_heat_integration/indirect_integration_entry.py +5 -3
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/input_data_processing/_utility_preparation.py +52 -24
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/input_data_processing/data_preparation.py +24 -11
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/power_cogeneration/power_cogeneration_analysis.py +1 -1
- openpinch-0.2.3/OpenPinch/services/power_cogeneration_analysis/power_cogeneration_analysis.py +139 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/services_entry.py +95 -5
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/__init__.py +14 -21
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/_tabular_input.py +3 -3
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/blackbox_minimisers.py +2 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/export.py +77 -82
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/heat_exchanger.py +2 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/plots.py +52 -1
- openpinch-0.2.3/OpenPinch/utils/value_resolution.py +418 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/PKG-INFO +21 -9
- {openpinch-0.2.1 → openpinch-0.2.3}/README.md +20 -8
- {openpinch-0.2.1 → openpinch-0.2.3}/pyproject.toml +3 -1
- openpinch-0.2.1/OpenPinch/data/notebooks/01_basic_pinch_and_dtcont_sensitivity.ipynb +0 -286
- openpinch-0.2.1/OpenPinch/data/notebooks/02_total_site_targets_and_sugcc.ipynb +0 -474
- openpinch-0.2.1/OpenPinch/lib/schemas/reporting.py +0 -74
- openpinch-0.2.1/OpenPinch/services/exergy_analysis/__init__.py +0 -5
- openpinch-0.2.1/OpenPinch/services/exergy_analysis/exergy_targeting_entry.py +0 -124
- openpinch-0.2.1/OpenPinch/services/heat_pump_integration/targeting_services/brayton.py +0 -209
- openpinch-0.2.1/OpenPinch/utils/miscellaneous.py +0 -489
- {openpinch-0.2.1 → openpinch-0.2.3}/.gitignore +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/LICENSE +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/__main__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_problem/_loading.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_problem_table/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_problem_table/_problem_table_constants.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_stream_collection/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_workspace/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_workspace/execution.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/_workspace/payloads.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/pinch_workspace.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/classes/problem_table.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/data/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/data/notebooks/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/data/sample_cases/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/data/sample_cases/basic_pinch.json +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/data/sample_cases/chocolate_factory.json +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/data/sample_cases/crude_preheat_train.json +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/data/sample_cases/heat_pump_targeting.json +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/data/sample_cases/pulp_mill.json +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/data/sample_cases/zonal_site.json +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/config.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/schemas/graphs.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/schemas/hpr.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/schemas/io.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/lib/schemas/turbine.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/main.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/resources.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/common/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/direct_heat_integration/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/common/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/common/encoding.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/common/postprocessing.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/targeting_services/__init__.py +0 -0
- {openpinch-0.2.1/OpenPinch/services/heat_pump_integration/cycles → openpinch-0.2.3/OpenPinch/services/heat_pump_integration/targeting_services}/brayton.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/targeting_services/multi_temperature_carnot.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/unit_models/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/unit_models/brayton_heat_pump.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/unit_models/cascade_vapour_compression_cycle.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/unit_models/parallel_vapour_compression_cycles.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/heat_pump_integration/unit_models/vapour_compression_cycle.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/indirect_heat_integration/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/input_data_processing/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/input_data_processing/_canonicalization.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/power_cogeneration/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/services/power_cogeneration/unit_models/multi_stage_steam_turbine.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/streamlit_webviewer/web_graphing.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/bb_optimisers/__init__.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/bb_optimisers/bayesian_optimisation.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/bb_optimisers/cmaes.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/bb_optimisers/common.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/bb_optimisers/dual_annealing.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/bb_optimisers/rbf_surrogate.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/costing.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/csv_to_json.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/decorators.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/input_validation.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/stream_linearisation.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/water_properties.py +0 -0
- {openpinch-0.2.1 → openpinch-0.2.3}/OpenPinch/utils/wkbook_to_json.py +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""OpenPinch public API."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import warnings as _warnings
|
|
4
6
|
|
|
5
7
|
from . import lib
|
|
@@ -55,6 +57,7 @@ from .lib import (
|
|
|
55
57
|
MaybeVU,
|
|
56
58
|
NonLinearStream,
|
|
57
59
|
PayloadRecordView,
|
|
60
|
+
PinchTemp,
|
|
58
61
|
PinchWorkspaceBundle,
|
|
59
62
|
ProblemTableColumnKey,
|
|
60
63
|
ProblemTableColumnUpdates,
|
|
@@ -82,7 +85,6 @@ from .lib import (
|
|
|
82
85
|
TargetOutput,
|
|
83
86
|
TargetResults,
|
|
84
87
|
TargetType,
|
|
85
|
-
TempPinch,
|
|
86
88
|
THSchema,
|
|
87
89
|
TotalProcessTarget,
|
|
88
90
|
TotalSiteTarget,
|
|
@@ -178,7 +180,7 @@ __all__ = [
|
|
|
178
180
|
"ZoneTreeSchema",
|
|
179
181
|
"HeatUtility",
|
|
180
182
|
"TargetResults",
|
|
181
|
-
"
|
|
183
|
+
"PinchTemp",
|
|
182
184
|
"AnyTargetModel",
|
|
183
185
|
"BaseTargetModel",
|
|
184
186
|
"DirectHeatPumpTarget",
|
|
@@ -14,7 +14,9 @@ from ._output import (
|
|
|
14
14
|
locate_summary_row,
|
|
15
15
|
)
|
|
16
16
|
from ._plot_accessor import _PlotAccessorDescriptor
|
|
17
|
+
from ._result_extraction import extract_results
|
|
17
18
|
from ._target_accessor import _TargetAccessorDescriptor
|
|
19
|
+
from ._target_dispatch import run_targeting_for_zone_and_subzones
|
|
18
20
|
from ._validation import (
|
|
19
21
|
_validate_problem_semantics,
|
|
20
22
|
format_schema_validation_error,
|
|
@@ -30,8 +32,10 @@ __all__ = [
|
|
|
30
32
|
"_validate_problem_semantics",
|
|
31
33
|
"build_graph_payload",
|
|
32
34
|
"build_problem_summary_frame",
|
|
35
|
+
"extract_results",
|
|
33
36
|
"format_schema_validation_error",
|
|
34
37
|
"load_problem_source",
|
|
35
38
|
"locate_summary_row",
|
|
36
39
|
"prepare_in_memory_problem_source",
|
|
40
|
+
"run_targeting_for_zone_and_subzones",
|
|
37
41
|
]
|
|
@@ -6,8 +6,8 @@ from typing import Any, Optional
|
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
|
|
9
|
+
from ...lib.schemas.report_units import split_report_value
|
|
9
10
|
from ...utils.export import build_summary_dataframe
|
|
10
|
-
from ...utils.miscellaneous import get_value
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def build_problem_summary_frame(
|
|
@@ -21,40 +21,55 @@ def build_problem_summary_frame(
|
|
|
21
21
|
|
|
22
22
|
rows = []
|
|
23
23
|
for target in results.targets:
|
|
24
|
+
idx = getattr(target, "idx", None)
|
|
25
|
+
qh_value, qh_unit = split_report_value(target.Qh, idx=idx)
|
|
26
|
+
qc_value, qc_unit = split_report_value(target.Qc, idx=idx)
|
|
27
|
+
qr_value, qr_unit = split_report_value(target.Qr, idx=idx)
|
|
28
|
+
hot_pinch_value, hot_pinch_unit = split_report_value(
|
|
29
|
+
target.pinch_temp.hot_temp,
|
|
30
|
+
idx=idx,
|
|
31
|
+
)
|
|
32
|
+
cold_pinch_value, cold_pinch_unit = split_report_value(
|
|
33
|
+
target.pinch_temp.cold_temp,
|
|
34
|
+
idx=idx,
|
|
35
|
+
)
|
|
24
36
|
rows.append(
|
|
25
37
|
{
|
|
26
38
|
"Target": target.name,
|
|
27
39
|
"State ID": getattr(target, "state_id", None),
|
|
28
|
-
"Hot Utility Target":
|
|
29
|
-
|
|
40
|
+
"Hot Utility Target": format_res(
|
|
41
|
+
value=qh_value,
|
|
42
|
+
unit=qh_unit,
|
|
30
43
|
),
|
|
31
|
-
"Cold Utility Target":
|
|
32
|
-
|
|
44
|
+
"Cold Utility Target": format_res(
|
|
45
|
+
value=qc_value,
|
|
46
|
+
unit=qc_unit,
|
|
33
47
|
),
|
|
34
|
-
"Heat Recovery":
|
|
35
|
-
|
|
48
|
+
"Heat Recovery": format_res(
|
|
49
|
+
value=qr_value,
|
|
50
|
+
unit=qr_unit,
|
|
36
51
|
),
|
|
37
|
-
"Hot Pinch":
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
"Hot Pinch": format_res(
|
|
53
|
+
value=hot_pinch_value,
|
|
54
|
+
unit=hot_pinch_unit,
|
|
40
55
|
),
|
|
41
|
-
"Cold Pinch":
|
|
42
|
-
|
|
43
|
-
|
|
56
|
+
"Cold Pinch": format_res(
|
|
57
|
+
value=cold_pinch_value,
|
|
58
|
+
unit=cold_pinch_unit,
|
|
44
59
|
),
|
|
45
60
|
"Hot Utilities": ", ".join(
|
|
46
|
-
|
|
47
|
-
utility.name,
|
|
48
|
-
utility.heat_flow,
|
|
49
|
-
|
|
61
|
+
format_res(
|
|
62
|
+
name=utility.name,
|
|
63
|
+
value=utility.heat_flow,
|
|
64
|
+
idx=idx,
|
|
50
65
|
)
|
|
51
66
|
for utility in target.hot_utilities
|
|
52
67
|
),
|
|
53
68
|
"Cold Utilities": ", ".join(
|
|
54
|
-
|
|
55
|
-
utility.name,
|
|
56
|
-
utility.heat_flow,
|
|
57
|
-
|
|
69
|
+
format_res(
|
|
70
|
+
name=utility.name,
|
|
71
|
+
value=utility.heat_flow,
|
|
72
|
+
idx=idx,
|
|
58
73
|
)
|
|
59
74
|
for utility in target.cold_utilities
|
|
60
75
|
),
|
|
@@ -106,20 +121,27 @@ def build_graph_payload(results: Any) -> Optional[dict[str, Any]]:
|
|
|
106
121
|
}
|
|
107
122
|
|
|
108
123
|
|
|
109
|
-
def
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def format_utility(
|
|
117
|
-
name: str,
|
|
118
|
-
heat_flow: Any,
|
|
119
|
-
state_id: str | None = None,
|
|
124
|
+
def format_res(
|
|
125
|
+
name: str | None = None,
|
|
126
|
+
value: Any | None = None,
|
|
127
|
+
idx: int | None = None,
|
|
128
|
+
unit: str | None = None,
|
|
120
129
|
) -> str:
|
|
121
130
|
"""Render one utility summary item."""
|
|
122
|
-
|
|
123
|
-
if
|
|
124
|
-
|
|
125
|
-
|
|
131
|
+
val, unt = split_report_value(value, idx=idx)
|
|
132
|
+
if unt is None:
|
|
133
|
+
unt = unit
|
|
134
|
+
if val is None:
|
|
135
|
+
if name:
|
|
136
|
+
return f"{name}: n/a"
|
|
137
|
+
else:
|
|
138
|
+
return "n/a"
|
|
139
|
+
if unt is None:
|
|
140
|
+
if name:
|
|
141
|
+
return f"{name}: {float(val):.2f}"
|
|
142
|
+
else:
|
|
143
|
+
return f"{float(val):.2f}"
|
|
144
|
+
if name:
|
|
145
|
+
return f"{name}: {float(val):.2f} {unt}"
|
|
146
|
+
else:
|
|
147
|
+
return f"{float(val):.2f} {unt}"
|
|
@@ -36,6 +36,9 @@ _GRAPH_TYPE_ALIASES = {
|
|
|
36
36
|
"gcc": GT.GCC.value,
|
|
37
37
|
"grand composite": GT.GCC.value,
|
|
38
38
|
"grand composite curve": GT.GCC.value,
|
|
39
|
+
"gcc_x": GT.GCC_X.value,
|
|
40
|
+
"exergy gcc": GT.GCC_X.value,
|
|
41
|
+
"exergetic grand composite curve": GT.GCC_X.value,
|
|
39
42
|
"nlc": GT.NLP.value,
|
|
40
43
|
"net load": GT.NLP.value,
|
|
41
44
|
"net load curve": GT.NLP.value,
|
|
@@ -47,6 +50,9 @@ _GRAPH_TYPE_ALIASES = {
|
|
|
47
50
|
"net_load curves": GT.NLP.value,
|
|
48
51
|
"net_load profile": GT.NLP.value,
|
|
49
52
|
"net_load profiles": GT.NLP.value,
|
|
53
|
+
"nlp_x": GT.NLP_X.value,
|
|
54
|
+
"exergy nlp": GT.NLP_X.value,
|
|
55
|
+
"exergetic net load profiles": GT.NLP_X.value,
|
|
50
56
|
"tsp": GT.TSP.value,
|
|
51
57
|
"total site": GT.TSP.value,
|
|
52
58
|
"total site profiles": GT.TSP.value,
|
|
@@ -302,6 +308,23 @@ class _PlotAccessor:
|
|
|
302
308
|
return_graph_data=return_graph_data,
|
|
303
309
|
)
|
|
304
310
|
|
|
311
|
+
def exergetic_grand_composite_curve(
|
|
312
|
+
self,
|
|
313
|
+
*,
|
|
314
|
+
zone_name: Optional[str] = None,
|
|
315
|
+
index: float = 0,
|
|
316
|
+
show: bool = False,
|
|
317
|
+
return_graph_data: bool = False,
|
|
318
|
+
):
|
|
319
|
+
"""Return the first matching exergetic GCC output or figure."""
|
|
320
|
+
return self._plot_graph(
|
|
321
|
+
zone_name=zone_name,
|
|
322
|
+
graph_type=GT.GCC_X.value,
|
|
323
|
+
index=index,
|
|
324
|
+
show=show,
|
|
325
|
+
return_graph_data=return_graph_data,
|
|
326
|
+
)
|
|
327
|
+
|
|
305
328
|
def grand_composite_curve_with_heat_pump(
|
|
306
329
|
self,
|
|
307
330
|
*,
|
|
@@ -336,6 +359,23 @@ class _PlotAccessor:
|
|
|
336
359
|
return_graph_data=return_graph_data,
|
|
337
360
|
)
|
|
338
361
|
|
|
362
|
+
def exergetic_net_load_profiles(
|
|
363
|
+
self,
|
|
364
|
+
*,
|
|
365
|
+
zone_name: Optional[str] = None,
|
|
366
|
+
index: float = 0,
|
|
367
|
+
show: bool = False,
|
|
368
|
+
return_graph_data: bool = False,
|
|
369
|
+
):
|
|
370
|
+
"""Return the first matching exergetic NLP payload or figure."""
|
|
371
|
+
return self._plot_graph(
|
|
372
|
+
zone_name=zone_name,
|
|
373
|
+
graph_type=GT.NLP_X.value,
|
|
374
|
+
index=index,
|
|
375
|
+
show=show,
|
|
376
|
+
return_graph_data=return_graph_data,
|
|
377
|
+
)
|
|
378
|
+
|
|
339
379
|
def total_site_profiles(
|
|
340
380
|
self,
|
|
341
381
|
*,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Helpers for converting solved zone trees into serializable result payloads."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import List
|
|
6
|
+
|
|
7
|
+
from ...services.common.graph_data import get_output_graph_data
|
|
8
|
+
from ..stream import Stream
|
|
9
|
+
from ..stream_collection import StreamCollection
|
|
10
|
+
from ..zone import Zone
|
|
11
|
+
|
|
12
|
+
__all__ = ["extract_results"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def extract_results(zone: Zone, state_id: str | None = None) -> dict:
|
|
16
|
+
"""Serialise solved targets, generated utilities, and graph payloads."""
|
|
17
|
+
return {
|
|
18
|
+
"name": zone.name,
|
|
19
|
+
"state_id": state_id,
|
|
20
|
+
"targets": _get_report(zone, state_id=state_id),
|
|
21
|
+
"utilities": _get_utilities(zone),
|
|
22
|
+
"graphs": get_output_graph_data(zone),
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _get_report(zone: Zone, state_id: str | None = None) -> dict:
|
|
27
|
+
"""Create the report payload from one zone and all nested subzones."""
|
|
28
|
+
targets: List[dict] = []
|
|
29
|
+
|
|
30
|
+
for target in zone.targets.values():
|
|
31
|
+
target_payload = target.serialize_json()
|
|
32
|
+
if state_id is not None:
|
|
33
|
+
target_payload["state_id"] = state_id
|
|
34
|
+
targets.append(target_payload)
|
|
35
|
+
|
|
36
|
+
if len(zone.subzones) > 0:
|
|
37
|
+
for subzone in zone.subzones.values():
|
|
38
|
+
targets.extend(_get_report(subzone, state_id=state_id))
|
|
39
|
+
|
|
40
|
+
return targets
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _get_utilities(zone: Zone) -> StreamCollection:
|
|
44
|
+
"""Get any default utilities generated during the analysis."""
|
|
45
|
+
utilities: StreamCollection = zone.hot_utilities + zone.cold_utilities
|
|
46
|
+
default_hu: Stream = next((u for u in utilities if u.name == "HU"), None)
|
|
47
|
+
default_cu: Stream = next((u for u in utilities if u.name == "CU"), None)
|
|
48
|
+
return [default_hu, default_cu]
|
|
@@ -7,6 +7,7 @@ from ...services import (
|
|
|
7
7
|
direct_heat_integration_service,
|
|
8
8
|
direct_heat_pump_service,
|
|
9
9
|
direct_refrigeration_service,
|
|
10
|
+
exergy_targeting_service,
|
|
10
11
|
indirect_heat_integration_service,
|
|
11
12
|
indirect_heat_pump_service,
|
|
12
13
|
indirect_refrigeration_service,
|
|
@@ -198,6 +199,26 @@ class _TargetAccessor:
|
|
|
198
199
|
direct_service_func=area_cost_targeting_service,
|
|
199
200
|
)
|
|
200
201
|
|
|
202
|
+
def exergy(
|
|
203
|
+
self,
|
|
204
|
+
*,
|
|
205
|
+
zone_name: Optional[str] = None,
|
|
206
|
+
options: Optional[dict[str, Any]] = None,
|
|
207
|
+
include_subzones: bool = False,
|
|
208
|
+
state_id: Optional[str] = None,
|
|
209
|
+
) -> BaseTargetModel:
|
|
210
|
+
"""Run exergy targeting on the first compatible base target family."""
|
|
211
|
+
runtime_options = dict(options or {})
|
|
212
|
+
runtime_options["DO_EXERGY_TARGETING"] = True
|
|
213
|
+
if state_id is not None:
|
|
214
|
+
runtime_options["state_id"] = state_id
|
|
215
|
+
return self._problem._execute_exergy_targeting(
|
|
216
|
+
application_zone=zone_name,
|
|
217
|
+
options=runtime_options,
|
|
218
|
+
include_subzones=include_subzones,
|
|
219
|
+
service_func=exergy_targeting_service,
|
|
220
|
+
)
|
|
221
|
+
|
|
201
222
|
|
|
202
223
|
class _TargetAccessorDescriptor:
|
|
203
224
|
"""Non-data descriptor exposing a callable target accessor on instances."""
|
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
"""Recursive dispatch helpers for zone-scale targeting
|
|
1
|
+
"""Recursive dispatch helpers for zone-scale targeting across subzones."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
2
4
|
|
|
3
5
|
import inspect
|
|
4
|
-
from typing import Callable
|
|
6
|
+
from typing import Callable
|
|
5
7
|
|
|
6
|
-
from
|
|
7
|
-
from ..
|
|
8
|
-
from ..classes.zone import Zone
|
|
9
|
-
from ..lib.enums import ZT
|
|
10
|
-
from ..services.common.graph_data import get_output_graph_data
|
|
8
|
+
from ...lib.enums import ZT
|
|
9
|
+
from ..zone import Zone
|
|
11
10
|
|
|
12
|
-
__all__ = [
|
|
13
|
-
"get_targets_for_zone_and_sub_zones",
|
|
14
|
-
"extract_results",
|
|
15
|
-
]
|
|
11
|
+
__all__ = ["run_targeting_for_zone_and_subzones"]
|
|
16
12
|
|
|
17
13
|
|
|
18
|
-
def
|
|
14
|
+
def run_targeting_for_zone_and_subzones(
|
|
19
15
|
zone: Zone,
|
|
20
16
|
direct_service_func: Callable = None,
|
|
21
17
|
indirect_service_func: Callable = None,
|
|
@@ -28,17 +24,6 @@ def get_targets_for_zone_and_sub_zones(
|
|
|
28
24
|
return handler(zone, direct_service_func, indirect_service_func, args)
|
|
29
25
|
|
|
30
26
|
|
|
31
|
-
def extract_results(zone: Zone, state_id: str | None = None) -> dict:
|
|
32
|
-
"""Serialise solved targets, generated utilities, and graph payloads."""
|
|
33
|
-
return {
|
|
34
|
-
"name": zone.name,
|
|
35
|
-
"state_id": state_id,
|
|
36
|
-
"targets": _get_report(zone, state_id=state_id),
|
|
37
|
-
"utilities": _get_utilities(zone),
|
|
38
|
-
"graphs": get_output_graph_data(zone),
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
27
|
################################################################################
|
|
43
28
|
# Helper functions
|
|
44
29
|
################################################################################
|
|
@@ -172,16 +157,11 @@ def _get_site_targets(
|
|
|
172
157
|
indirect_service_func: Callable = None,
|
|
173
158
|
args: dict | None = None,
|
|
174
159
|
):
|
|
175
|
-
"""
|
|
176
|
-
by systematically analysing individual zones and then performing
|
|
177
|
-
site-level indirect integration through the utility system.
|
|
178
|
-
"""
|
|
160
|
+
"""Run site targeting over the full nested zone hierarchy."""
|
|
179
161
|
|
|
180
|
-
# Totally integrated analysis for a site zone
|
|
181
162
|
if isinstance(direct_service_func, Callable):
|
|
182
163
|
_invoke_service(direct_service_func, zone, args)
|
|
183
164
|
|
|
184
|
-
# Targets sub-zone energy requirements
|
|
185
165
|
if len(zone.subzones) > 0:
|
|
186
166
|
for subzone in zone.subzones.values():
|
|
187
167
|
if subzone.type == ZT.O.value:
|
|
@@ -214,7 +194,6 @@ def _get_site_targets(
|
|
|
214
194
|
"site, process, and operation zones."
|
|
215
195
|
)
|
|
216
196
|
|
|
217
|
-
# Calculates indirect targets based on different approaches
|
|
218
197
|
if isinstance(indirect_service_func, Callable):
|
|
219
198
|
_invoke_service(indirect_service_func, zone, args)
|
|
220
199
|
|
|
@@ -227,7 +206,7 @@ def _get_community_targets(
|
|
|
227
206
|
indirect_service_func: Callable = None,
|
|
228
207
|
args: dict | None = None,
|
|
229
208
|
):
|
|
230
|
-
"""
|
|
209
|
+
"""Target a community zone by dispatching each site child."""
|
|
231
210
|
for subzone in zone.subzones.values():
|
|
232
211
|
subzone = _invoke_target_handler(
|
|
233
212
|
_get_site_targets,
|
|
@@ -245,7 +224,7 @@ def _get_regional_targets(
|
|
|
245
224
|
indirect_service_func: Callable = None,
|
|
246
225
|
args: dict | None = None,
|
|
247
226
|
):
|
|
248
|
-
"""
|
|
227
|
+
"""Target a regional zone by dispatching each community child."""
|
|
249
228
|
for subzone in zone.subzones.values():
|
|
250
229
|
subzone = _invoke_target_handler(
|
|
251
230
|
_get_community_targets,
|
|
@@ -257,31 +236,6 @@ def _get_regional_targets(
|
|
|
257
236
|
return zone
|
|
258
237
|
|
|
259
238
|
|
|
260
|
-
def _get_report(zone: Zone, state_id: str | None = None) -> dict:
|
|
261
|
-
"""Creates the database summary of zone targets."""
|
|
262
|
-
targets: List[dict] = []
|
|
263
|
-
|
|
264
|
-
for target in zone.targets.values():
|
|
265
|
-
target_payload = target.serialize_json()
|
|
266
|
-
if state_id is not None:
|
|
267
|
-
target_payload["state_id"] = state_id
|
|
268
|
-
targets.append(target_payload)
|
|
269
|
-
|
|
270
|
-
if len(zone.subzones) > 0:
|
|
271
|
-
for subzone in zone.subzones.values():
|
|
272
|
-
targets.extend(_get_report(subzone, state_id=state_id))
|
|
273
|
-
|
|
274
|
-
return targets
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
def _get_utilities(zone: Zone) -> StreamCollection:
|
|
278
|
-
"""Gets a list of any default utilities generated during the analysis."""
|
|
279
|
-
utilities: StreamCollection = zone.hot_utilities + zone.cold_utilities
|
|
280
|
-
default_hu: Stream = next((u for u in utilities if u.name == "HU"), None)
|
|
281
|
-
default_cu: Stream = next((u for u in utilities if u.name == "CU"), None)
|
|
282
|
-
return [default_hu, default_cu]
|
|
283
|
-
|
|
284
|
-
|
|
285
239
|
_TARGET_HANDLERS = {
|
|
286
240
|
ZT.R.value: _get_regional_targets,
|
|
287
241
|
ZT.C.value: _get_community_targets,
|
|
@@ -12,6 +12,7 @@ from pydantic import ValidationError
|
|
|
12
12
|
from ...lib.enums import ST
|
|
13
13
|
from ...lib.schemas.io import TargetInput
|
|
14
14
|
from ...lib.schemas.workspace import ValidationIssue, ValidationReport
|
|
15
|
+
from ...lib.unit_system import standardise_input_value
|
|
15
16
|
from ..value import Value
|
|
16
17
|
|
|
17
18
|
ValidationContext = dict[str, list[dict[str, Any]]]
|
|
@@ -116,6 +117,8 @@ def semantic_issues(
|
|
|
116
117
|
) -> list[ValidationIssue]:
|
|
117
118
|
"""Return semantic validation issues for one validated problem definition."""
|
|
118
119
|
issues: list[ValidationIssue] = []
|
|
120
|
+
options = problem_inputs.options if isinstance(problem_inputs.options, dict) else {}
|
|
121
|
+
input_unit_config = {"INPUT_UNITS": options.get("INPUT_UNITS", {})}
|
|
119
122
|
|
|
120
123
|
if len(problem_inputs.streams) == 0:
|
|
121
124
|
issues.append(
|
|
@@ -135,6 +138,7 @@ def semantic_issues(
|
|
|
135
138
|
record_label=label,
|
|
136
139
|
field_names=("t_supply", "t_target", "heat_flow", "dt_cont", "htc"),
|
|
137
140
|
optional_field_names=("dt_cont", "htc"),
|
|
141
|
+
config=input_unit_config,
|
|
138
142
|
)
|
|
139
143
|
issues.extend(stream_value_issues)
|
|
140
144
|
issues.extend(
|
|
@@ -168,6 +172,7 @@ def semantic_issues(
|
|
|
168
172
|
"htc",
|
|
169
173
|
"price",
|
|
170
174
|
),
|
|
175
|
+
config=input_unit_config,
|
|
171
176
|
)
|
|
172
177
|
issues.extend(utility_value_issues)
|
|
173
178
|
issues.extend(
|
|
@@ -365,6 +370,7 @@ def _coerce_validation_values(
|
|
|
365
370
|
record_label: Optional[str],
|
|
366
371
|
field_names: tuple[str, ...],
|
|
367
372
|
optional_field_names: tuple[str, ...] = (),
|
|
373
|
+
config: dict[str, dict[str, Any]] | None = None,
|
|
368
374
|
) -> tuple[
|
|
369
375
|
dict[str, Value | None],
|
|
370
376
|
dict[str, tuple[list[str] | None, np.ndarray | None]],
|
|
@@ -382,7 +388,11 @@ def _coerce_validation_values(
|
|
|
382
388
|
values[field_name] = None
|
|
383
389
|
continue
|
|
384
390
|
try:
|
|
385
|
-
values[field_name] =
|
|
391
|
+
values[field_name] = standardise_input_value(
|
|
392
|
+
raw_value,
|
|
393
|
+
field_name=field_name,
|
|
394
|
+
config=config,
|
|
395
|
+
)
|
|
386
396
|
except (TypeError, ValueError) as exc:
|
|
387
397
|
values[field_name] = None
|
|
388
398
|
issues.append(
|
|
@@ -42,6 +42,10 @@ _SUMMARY_METRIC_COLUMNS = [
|
|
|
42
42
|
]
|
|
43
43
|
|
|
44
44
|
|
|
45
|
+
def _unit_column(metric: str) -> str:
|
|
46
|
+
return f"{metric} (unit)"
|
|
47
|
+
|
|
48
|
+
|
|
45
49
|
def invalid_variant_view(
|
|
46
50
|
*,
|
|
47
51
|
variant_name: str,
|
|
@@ -161,6 +165,7 @@ def summary_cards(frame: pd.DataFrame) -> list[SummaryCard]:
|
|
|
161
165
|
target_name=target_name,
|
|
162
166
|
label=metric,
|
|
163
167
|
value=json_safe(row.get(metric)),
|
|
168
|
+
unit=maybe_string(row.get(_unit_column(metric))),
|
|
164
169
|
)
|
|
165
170
|
)
|
|
166
171
|
return cards
|
|
@@ -276,6 +281,13 @@ def summary_metric_deltas(
|
|
|
276
281
|
for metric in _SUMMARY_METRIC_COLUMNS:
|
|
277
282
|
base_value = json_safe(base_row.get(metric))
|
|
278
283
|
variant_value = json_safe(variant_row.get(metric))
|
|
284
|
+
unit = maybe_string(
|
|
285
|
+
base_row.get(_unit_column(metric))
|
|
286
|
+
or variant_row.get(_unit_column(metric))
|
|
287
|
+
)
|
|
288
|
+
units_match = base_row.get(_unit_column(metric)) == variant_row.get(
|
|
289
|
+
_unit_column(metric)
|
|
290
|
+
)
|
|
279
291
|
deltas.append(
|
|
280
292
|
VariantMetricDelta(
|
|
281
293
|
base_variant=base_name,
|
|
@@ -285,7 +297,10 @@ def summary_metric_deltas(
|
|
|
285
297
|
metric=metric,
|
|
286
298
|
base_value=base_value,
|
|
287
299
|
variant_value=variant_value,
|
|
288
|
-
|
|
300
|
+
unit=unit,
|
|
301
|
+
delta=numeric_delta(base_value, variant_value)
|
|
302
|
+
if units_match
|
|
303
|
+
else None,
|
|
289
304
|
)
|
|
290
305
|
)
|
|
291
306
|
return deltas
|