OpenPinch 0.8.0__tar.gz → 0.8.2__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.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/execution/README.md +2 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/execution/executor.py +22 -2
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/README.md +1 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_base/README.md +1 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_base/execution.py +10 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_stagewise/README.md +2 -2
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_stagewise/evolution.py +39 -8
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/problem.py +19 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/results/README.md +2 -2
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/results/assembly.py +14 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/solver/README.md +4 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/solver/arrays.py +1 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/solver/backend.py +72 -3
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/solver/pinch_design_decomposition.py +6 -4
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/README.md +1 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/_shared/README.md +1 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/_shared/air.py +5 -3
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/preprocessing.py +1 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/shared.py +1 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/targeting/README.md +1 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/targeting/_carnot_common.py +5 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/accessors/design.py +6 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/hpr.py +1 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/configuration.py +2 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/configuration_fields.py +9 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/README.md +1 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/execution.py +7 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/configuration_text.py +17 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/PKG-INFO +1 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/pyproject.toml +1 -1
- {openpinch-0.8.0 → openpinch-0.8.2}/.gitignore +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/LICENSE +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/__main__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/io/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/io/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/io/csv.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/io/file_exports.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/io/json.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/io/problem_sources.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/io/records.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/io/tabular.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/io/workbook.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/io/workspace_bundles.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/adapters/optional_dependencies.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/economics.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/energy_transfer/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/energy_transfer/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/energy_transfer/cascade.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/energy_transfer/diagram.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/energy_transfer/selection.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/energy_transfer/serialization.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/energy_transfer/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/exergy/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/exergy/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/exergy/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/graphs/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/graphs/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/graphs/composite.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/graphs/grand_composite.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/graphs/metadata.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/graphs/primitives.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/graphs/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/graphs/specifications.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/context.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/controllability.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/duty_optimisation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/errors.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/execution/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/execution/fake_executor.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/execution/fallbacks.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/execution/pathways.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/execution/settings.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/execution/task_builders.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/extraction/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/extraction/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/extraction/metadata.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/extraction/period_state.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/extraction/recovery.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/extraction/segment_area.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/extraction/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/extraction/utility.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/indexing.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_base/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_base/alpha.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_base/approach.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_base/area.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_base/costing.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_base/parameters.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_base/piecewise.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_base/superstructure.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_pinch_design/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_pinch_design/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_pinch_design/amalgamation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_pinch_design/equations.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_pinch_design/postprocess.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_pinch_design/preprocessing.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_stagewise/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_stagewise/equations.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_stagewise/objectives.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_stagewise/postprocess.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_stagewise/setup.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_stagewise/verification.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/_stagewise/warm_start.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/base.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/fixed_structure.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/packed_pinch_design.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/packed_stagewise.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/pinch_decomposition.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/stage_packing.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/stagewise.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/thermal_profiles.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/prepared_problem.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/reporting/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/reporting/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/reporting/exports.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/reporting/ranking.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/reporting/verification.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/results/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/results/seeds.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/results/selection.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/solver/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/solver/dependencies.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/solver/piecewise.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/targeting/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/targeting/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/targeting/_stage.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/targeting/network_evolution_method.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/targeting/open_hens_method.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/targeting/pinch_design_method.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/targeting/thermal_derivative_method.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/targeting/topology.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_multiperiod/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_multiperiod/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_multiperiod/aggregation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_multiperiod/execution.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_multiperiod/preparation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_multiperiod/setup.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_multiperiod/state.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_process_mvr/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_process_mvr/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_process_mvr/membership.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_process_mvr/replacement_streams.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_process_mvr/selection.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_process_mvr/state.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_process_mvr/values.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/_process_mvr/work.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/_shared/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/_shared/plotting.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/_shared/streams.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/encoding.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/layout.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/load_selection.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/multi_vc_objective.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/postprocessing.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/common/units.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/components.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/cycles/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/cycles/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/cycles/_multi_cycle_base.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/cycles/brayton_heat_pump.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/cycles/carnot_cycles.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/cycles/cascade_vapour_compression_cycle.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/cycles/mechanical_vapour_recompression_cycle.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/cycles/parallel_vapour_compression_cycles.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/cycles/vapour_compression_cycle.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/cycles/vapour_compression_mvr_cascade.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/direct_mvr/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/direct_mvr/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/direct_mvr/execution.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/direct_mvr/models.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/direct_mvr/thermodynamics.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/direct_mvr/units.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/optimisation_adapter.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/adapters/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/adapters/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/adapters/coolprop.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/adapters/tespy.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/characteristics/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/characteristics/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/characteristics/openpinch-single-stage-compressor-v1.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/context.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/coolprop_preflight.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/errors.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/factory.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/fluids.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/generation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/models.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/points.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/protocols.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/provenance.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/resources.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/settings.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/target_basis.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/target_records.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/targeting.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/performance_maps/targeting_models.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/process_mvr.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/targeting/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/targeting/brayton.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/targeting/cascade_carnot.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/targeting/cascade_vapour_compression.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/targeting/parallel_carnot.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/targeting/parallel_vapour_compression.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/targeting/vapour_compression_mvr.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_transfer.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/numerics.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/orc/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/orc/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/orc/carnot.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/orc/costing.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/orc/cycle.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/orc/inputs.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/orc/profile.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/orc/search.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/orc/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/orc/simulated.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/parallelism.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/power/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/power/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/power/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/power/steam_turbine.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/area_cost.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/cascade.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/context.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/direct.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/grand_composite.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/heat_recovery_dt_min.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/indirect.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/residual.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/temperature_driving_force.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/targeting/utilities.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/thermodynamics/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/thermodynamics/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/thermodynamics/water.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/allocation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/bounds.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/codec.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/context.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/errors.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/evaluation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/normalization.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/optimisation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/penalties.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/profiles.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/replay.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/start_points.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/thermodynamics.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/utility_placement/units.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/accessors/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/accessors/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/accessors/component.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/accessors/plot.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/accessors/target.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/arguments.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/input/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/input/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/input/canonicalization.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/input/construction.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/input/loading.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/input/segments.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/input/semantics.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/input/utilities.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/input/validation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/output/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/output/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/output/reporting.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/output/result_extraction.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/periods/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/periods/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/periods/aggregation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/targeting/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/targeting/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/targeting/catalog.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/targeting/dispatch.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/targeting/execution.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/targeting/provenance.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_problem/targeting/state.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_workspace/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_workspace/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_workspace/case_inputs.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/_workspace/state.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/case_derivation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/commands.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/heat_recovery_dt_min.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/hpr_selection.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/problem.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/residual_utility.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/targeting.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/utility_placement.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/application/workspace.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/common.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/controllability.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/graphs.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/heat_recovery_dt_min.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/hpr_performance_map.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/input.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/output.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/report_metrics.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/report_units.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/reporting.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/resources/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/resources/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/resources/hpr_performance_map/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/resources/hpr_performance_map/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/resources/hpr_performance_map/heat-pump-1.0.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/resources/hpr_performance_map/refrigeration-1.0.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/resources/hpr_performance_map/schema-1.0.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/schema.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/synthesis/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/synthesis/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/synthesis/common.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/synthesis/method.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/synthesis/result.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/synthesis/task.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/synthesis/topology.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/synthesis/view.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/turbine.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/units.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/utility_placement.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/contracts/workspace.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_heat_exchanger/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_heat_exchanger/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_heat_exchanger/area.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_heat_exchanger/period_state.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_heat_exchanger/rules.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_heat_exchanger_network/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_heat_exchanger_network/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_heat_exchanger_network/types.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_problem_table/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_problem_table/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_problem_table/constants.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_problem_table/equality.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_problem_table/intervals.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_problem_table/types.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream/linearisation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream/profile.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream/segment.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream/segments.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream/thermodynamics.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream/value_state.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream_collection/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream_collection/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream_collection/filters.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream_collection/numeric_view.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream_collection/serialization.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_stream_collection/sorting.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_validation.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_value/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_value/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_value/coercion.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_value/resolution.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/_value/units.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/analysis.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/enums.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/fluids.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/heat_exchanger.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/heat_exchanger_network.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/hpr.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/problem_table.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/progress.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/solver_options.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/stream.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/stream_collection.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/targets.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/value.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/domain/zone.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/backends/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/backends/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/backends/_multistart.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/backends/_surrogate.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/backends/bayesian.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/backends/cma_es.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/backends/dual_annealing.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/backends/protocol.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/backends/rbf.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/candidates.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/errors.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/feasibility.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/models.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/optimisation/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/configuration.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/dashboard/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/dashboard/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/dashboard/dashboard.css +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/dashboard/dependencies.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/dashboard/exports.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/dashboard/rendering.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/dashboard/state.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/graphs/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/graphs/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/graphs/plotly.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/graphs/problem.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/graphs/simple.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/_constants.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/dependencies.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/geometry.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/labels.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/layout.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/plotly.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/rendering.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/results.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/service.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/state.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/temperatures.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/network_grid/view.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/adapters.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/excel_text.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/hpr.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/problem_table.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/results.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/specialist.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/stream_collection.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/thermal.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/presentation/reporting/workbook.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/resources.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/01_first_solve_and_core_curves.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/02_focused_direct_and_total_site.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/03_multisegment_streams.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/04_workspace_cases_and_scenarios.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/05_workspace_persistence.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/06_multiperiod_heat_integration.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/07_area_cost_and_exergy.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/08_carnot_heat_pump_and_refrigeration.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/09_vapour_compression.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/10_multiperiod_heat_pumps.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/11_process_mvr_and_cascade.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/12_cogeneration.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/13_multiperiod_cogeneration.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/14_energy_transfer.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/15_hen_synthesis_and_selection.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/16_advanced_hen_methods.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/17_multiperiod_hen_synthesis.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/18_results_plots_reports_exports.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/19_utility_placement_optimisation.ipynb +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/notebooks/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/Four-stream-Yee-and-Grossmann-1990-1.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/README.md +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/__init__.py +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/basic_pinch.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/chocolate_factory.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/crude_preheat_train.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/crude_preheat_train_multiperiod.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/dairy_chilling_multiperiod.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/process_mvr.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/pulp_mill.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/zonal_site.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/tutorials/sample_cases/zonal_site_multiperiod.json +0 -0
- {openpinch-0.8.0 → openpinch-0.8.2}/README.md +0 -0
{openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/execution/README.md
RENAMED
|
@@ -18,8 +18,9 @@ Resolves synthesis settings from a prepared problem, plans the quality-tier path
|
|
|
18
18
|
## Invariants
|
|
19
19
|
- A downstream task needs a successful parent outcome and the parent's in-process solver problem; `_parent_problem` raises `WorkflowContractError`, but `LocalSynthesisExecutor.execute` catches it and returns a failed task outcome carrying the message, while `FakeSynthesisExecutor` lets it propagate [executor.py:LocalSynthesisExecutor._parent_problem] [executor.py:LocalSynthesisExecutor.execute] [fake_executor.py:FakeSynthesisExecutor.execute].
|
|
20
20
|
- Tasks are built inside pool workers only when no parent outcomes exist, no task has a parent and more than one worker is in use [executor.py:_can_build_tasks_in_workers].
|
|
21
|
-
- TDM and ESM models use
|
|
21
|
+
- TDM and ESM models use an approach of `max(0.1 K, HENS_MIN_EXCHANGER_APPROACH_SHARE x task approach)` (0.1 K at the default share of 0); PDM uses the task approach temperature [executor.py:_task_model_approach_temperature, LocalSynthesisExecutor._build_problem].
|
|
22
22
|
- A solve counts as successful only when `mSuccess == 1` and `verify()` (if present) passes; failures carry a non-empty error string [executor.py:_solve_built_task, _failed_task_outcome].
|
|
23
|
+
- A successful solve whose solver stopped before converging records `diagnostics["unconverged_termination"]`; it stays a success so downstream tasks can start from it [executor.py:_solve_built_task].
|
|
23
24
|
- Stage-packing scope `"auto"` resolves to `"none"` at execution time [executor.py:_stage_packing_scope]. The scope only decides packing for non-compact PDM tasks and for TDM tasks; PDM tasks with `pdm_mode == "compact"` (tier 0 and the compact routes of tiers 2 to 5) always use the stage-packed model [executor.py:LocalSynthesisExecutor._model_factories_for_task].
|
|
24
25
|
- Outcomes are returned in the order of the input tasks [executor.py:LocalSynthesisExecutor._collect_outcomes].
|
|
25
26
|
- Settings are a frozen dataclass; only `evm_solver_options` is copied on construction, while `pdm_solver_options` and `tdm_solver_options` are shared references [settings.py:SynthesisWorkflowSettings.__post_init__].
|
{openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/execution/executor.py
RENAMED
|
@@ -246,7 +246,10 @@ class LocalSynthesisExecutor:
|
|
|
246
246
|
parent_outcomes: dict[str, HeatExchangerNetworkSynthesisTaskOutcome],
|
|
247
247
|
) -> InternalHeatExchangerNetworkProblem:
|
|
248
248
|
parent_problem = self._parent_problem(task, parent_outcomes)
|
|
249
|
-
dTmin = _task_model_approach_temperature(
|
|
249
|
+
dTmin = _task_model_approach_temperature(
|
|
250
|
+
task,
|
|
251
|
+
min_approach_share=problem.master_zone.config.hens.min_exchanger_approach_share,
|
|
252
|
+
)
|
|
250
253
|
arrays = problem_to_solver_arrays(problem, dTmin)
|
|
251
254
|
stage_selection = _pdm_stage_selection(problem, task)
|
|
252
255
|
decompositions = None
|
|
@@ -407,6 +410,14 @@ def _solve_built_task(
|
|
|
407
410
|
return task, _failed_task_outcome(task, reason), internal_problem
|
|
408
411
|
|
|
409
412
|
network = internal_problem.extract_network(run_id=task.run_id)
|
|
413
|
+
# An unconverged solve stays a success so downstream tasks can start
|
|
414
|
+
# from it; demote_infeasible_outcomes keeps it out of the ranking.
|
|
415
|
+
solver_run = getattr(solved, "solver_run", None)
|
|
416
|
+
diagnostics = (
|
|
417
|
+
{}
|
|
418
|
+
if getattr(solver_run, "converged", True)
|
|
419
|
+
else {"unconverged_termination": str(solver_run.termination_condition)}
|
|
420
|
+
)
|
|
410
421
|
return (
|
|
411
422
|
task,
|
|
412
423
|
HeatExchangerNetworkSynthesisTaskOutcome(
|
|
@@ -415,6 +426,7 @@ def _solve_built_task(
|
|
|
415
426
|
network=network,
|
|
416
427
|
objective_value=network.total_annual_cost,
|
|
417
428
|
solver_status=_solver_status(internal_problem),
|
|
429
|
+
diagnostics=diagnostics,
|
|
418
430
|
),
|
|
419
431
|
internal_problem,
|
|
420
432
|
)
|
|
@@ -507,12 +519,20 @@ def _model_objective(method: HeatExchangerNetworkDesignMethod) -> str:
|
|
|
507
519
|
|
|
508
520
|
def _task_model_approach_temperature(
|
|
509
521
|
task: HeatExchangerNetworkSynthesisTask,
|
|
522
|
+
*,
|
|
523
|
+
min_approach_share: float = 0.0,
|
|
510
524
|
) -> float:
|
|
525
|
+
"""Return the model's minimum approach temperature.
|
|
526
|
+
|
|
527
|
+
The pinch design step uses the task's approach. The thermal derivative and
|
|
528
|
+
evolution steps minimise cost down to 0.1 K, or to ``min_approach_share``
|
|
529
|
+
(``HENS_MIN_EXCHANGER_APPROACH_SHARE``) times the task's approach if larger.
|
|
530
|
+
"""
|
|
511
531
|
if task.method in {
|
|
512
532
|
HeatExchangerNetworkDesignMethod.ThermalDerivative,
|
|
513
533
|
HeatExchangerNetworkDesignMethod.NetworkEvolution,
|
|
514
534
|
}:
|
|
515
|
-
return 0.1
|
|
535
|
+
return max(0.1, min_approach_share * float(task.approach_temperature))
|
|
516
536
|
return float(task.approach_temperature)
|
|
517
537
|
|
|
518
538
|
|
{openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/README.md
RENAMED
|
@@ -25,6 +25,7 @@ Concrete GEKKO-based equation models for heat exchanger network synthesis, plus
|
|
|
25
25
|
- `ThermalProfile` is frozen; its arrays must share one non-zero length and `side` must be "hot" or "cold". Smoothing applies only to symbolic arguments; plain numbers are exact. [thermal_profiles.py:ThermalProfile.__post_init__] [thermal_profiles.py:smooth_max0]
|
|
26
26
|
- Stage packing applies only when `integers` is true, `S > 1` and some stage has positive capacity. [stage_packing.py:add_recovery_stage_packing_constraints]
|
|
27
27
|
- PDM construction needs "above" and "below" decompositions; stage-wise construction needs an explicit stage count or a parent solution. [problem.py:InternalHeatExchangerNetworkProblem._build_pdm] [problem.py:InternalHeatExchangerNetworkProblem._build_stage_wise]
|
|
28
|
+
- The amalgamated PDM case is built, not solved, so it takes the termination condition of the first required side whose solve did not converge; otherwise it keeps its own solver run. [problem.py:InternalHeatExchangerNetworkProblem._carry_unconverged_side_solve]
|
|
28
29
|
- `get_solution` converts `ValueError` into `None` with `solution_failure_reason` set. [problem.py:InternalHeatExchangerNetworkProblem.get_solution]
|
|
29
30
|
- Stage reduction keeps stages whose share of peak recovery meets a threshold (0.1, 5, 8, 10 percent for at most 3, 5, 8, 10 stages and 0 percent for more than 10; PDM and TDM solves only) and returns the original case unless the reduced model solves and verifies. [problem.py:InternalHeatExchangerNetworkProblem._utilisation_threshold] [problem.py:InternalHeatExchangerNetworkProblem.remove_unused_stages]
|
|
30
31
|
|
|
@@ -31,6 +31,7 @@ The parent imports `alpha`, `approach`, `execution`, `parameters` and `piecewise
|
|
|
31
31
|
## Side Effects
|
|
32
32
|
- Creates a local (non-remote) GEKKO model and configures its solver. [execution.py:setup_model]
|
|
33
33
|
- `optimise` always removes the GEKKO run directory afterwards; `cleanup_model` is safe to repeat. [execution.py:optimise] [execution.py:cleanup_model]
|
|
34
|
+
- A solve that stopped before converging (`solver_run.converged` false) keeps `mSuccess` and its values, but is logged as a warning (`[Unconverged]`) rather than `[Success]`. [execution.py:_solve_and_post_process]
|
|
34
35
|
- `get_alpha_values` builds and solves a second GEKKO model and cleans it up. [alpha.py:get_alpha_values]
|
|
35
36
|
- Writes solver results, logs and many attributes onto the model passed in (`mSuccess`, `solver_run`, `area_*`, `LMTD_*`, `z_allowed`). [execution.py:_solve_and_post_process] [area.py:set_utility_lmtd_and_areas]
|
|
36
37
|
- Lazy imports of `OpenPinch.analysis.heat_exchanger_networks.solver.piecewise` inside segmented-stream branches. [area.py:_apply_segment_recovery_areas] [piecewise.py:_utility_cost_expression]
|
|
@@ -96,6 +96,16 @@ def _solve_and_post_process(model, print_output: bool) -> None:
|
|
|
96
96
|
model.name,
|
|
97
97
|
model.m._path,
|
|
98
98
|
)
|
|
99
|
+
elif not model.solver_run.converged:
|
|
100
|
+
# The values are kept (evolution can start from them), but the
|
|
101
|
+
# objective is not a converged optimum to compare against.
|
|
102
|
+
model.mSuccess = model.m.options.SOLVESTATUS
|
|
103
|
+
logger.warning(
|
|
104
|
+
"[Unconverged] [model: %s] [path: %s] [termination: %s]",
|
|
105
|
+
model.name,
|
|
106
|
+
model.m._path,
|
|
107
|
+
model.solver_run.termination_condition,
|
|
108
|
+
)
|
|
99
109
|
else:
|
|
100
110
|
model.mSuccess = model.m.options.SOLVESTATUS
|
|
101
111
|
logger.info(
|
|
@@ -19,7 +19,7 @@ Private helper modules for `StageWiseModel` (`../stagewise.py`), which delegates
|
|
|
19
19
|
- Supported goals: "hot utility", "cold utility", "total utility", "utility costs", "heat recovery", "dQ/dA obj", "total cost", "variable total cost"; others raise `ValueError`. [objectives.py:set_obj]
|
|
20
20
|
- Solver area terms use Chen's LMTD approximation; multiperiod total cost uses one shared area per unit bounded below by each period's requirement. [objectives.py:_chen_mean] [objectives.py:_set_multiperiod_total_cost_objective]
|
|
21
21
|
- `verify` checks cost and area consistency only for the two total-cost goals; once those pass it also runs the reporting-layer network feasibility check. [verification.py:verify]
|
|
22
|
-
- Evolution candidates are usable only if solved and `verify()` passes; the best is adopted only if its TAC is below the original and it
|
|
22
|
+
- Evolution candidates are usable only if solved, converged (`solver_run.converged`) and `verify()` passes; the best is adopted only if it verifies and, when the starting solve converged, its TAC is below the original. When the starting solve did not converge its TAC is not a benchmark: the best usable candidate is adopted, and the workflow's final ranking compares it with the seed network on verified costs. [evolution.py:_is_usable_evolution_candidate] [evolution.py:_benchmark_model] [evolution.py:_update_with_best_model]
|
|
23
23
|
- With more than one add or remove branch, or a patience limit, evolution keeps at most `beam_width` branches ranked by TAC then topology signature, solves each topology once, and orders parallel results by (branch, kind, rank) so serial and parallel runs agree. [evolution.py:get_net_benefit_evolution] [evolution.py:_solve_evolution_candidates]
|
|
24
24
|
- With one add branch, one remove branch and no patience, the original single-path search runs. [evolution.py:get_net_benefit_evolution]
|
|
25
25
|
- Evolution children are relaxed (`integers=False`, `tol=1e-3`) and use the root model's solver. [evolution.py:_build_and_solve_evolution]
|
|
@@ -28,7 +28,7 @@ Private helper modules for `StageWiseModel` (`../stagewise.py`), which delegates
|
|
|
28
28
|
|
|
29
29
|
## Side Effects
|
|
30
30
|
- Evolution builds and solves child `StageWiseModel` instances (GEKKO models), in a `ThreadPoolExecutor` when `max_parallel` exceeds one and `supported_workers` allows it. [evolution.py:_solve_evolution_candidates]
|
|
31
|
-
- `get_net_benefit_evolution` ends by calling `owner.cleanup()` on both search paths (only the early return when `owner.mSuccess != 1` skips it), and `_update_with_best_model` overwrites the owner's variables, `z_allowed`, alpha
|
|
31
|
+
- `get_net_benefit_evolution` ends by calling `owner.cleanup()` on both search paths (only the early return when `owner.mSuccess != 1` skips it), and `_update_with_best_model` overwrites the owner's variables, `z_allowed`, alpha, cost attributes and `solver_run`, then re-runs post-processing. [evolution.py:get_net_benefit_evolution] [evolution.py:_update_with_best_model]
|
|
32
32
|
- `verify` lazily imports and runs `extract_heat_exchanger_network` and `verify_network_feasibility`. [verification.py:_check_network_feasibility]
|
|
33
33
|
- Post-processing runs the post-optimisation alpha solve via `get_alpha_values`. [postprocess.py:_get_multiperiod_post_process]
|
|
34
34
|
- Evolution and verification log mostly at debug level; exceptions in a candidate solve are caught and logged. [evolution.py:_solve_evolution_candidate]
|
|
@@ -82,8 +82,13 @@ def get_net_benefit_evolution(
|
|
|
82
82
|
initial_z = getattr(owner, "z_allowed", None)
|
|
83
83
|
if initial_z is not None:
|
|
84
84
|
seen_signatures.add(_topology_signature_from_z(owner, initial_z))
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
best_model = _benchmark_model(owner)
|
|
86
|
+
frontier = [
|
|
87
|
+
_EvolutionBranchState(
|
|
88
|
+
model=owner,
|
|
89
|
+
best_tac=float(owner.TAC) if best_model is owner else float("inf"),
|
|
90
|
+
)
|
|
91
|
+
]
|
|
87
92
|
|
|
88
93
|
for unit in range(max_depth):
|
|
89
94
|
logger.debug(
|
|
@@ -142,7 +147,7 @@ def get_net_benefit_evolution(
|
|
|
142
147
|
)
|
|
143
148
|
continue
|
|
144
149
|
next_frontier.append(branch_period)
|
|
145
|
-
if candidate.TAC < best_model.TAC:
|
|
150
|
+
if best_model is None or candidate.TAC < best_model.TAC:
|
|
146
151
|
best_model = candidate
|
|
147
152
|
# Keep the best branches by TAC, ties broken on topology signature, so
|
|
148
153
|
# the frontier never grows past the beam width.
|
|
@@ -154,14 +159,14 @@ def get_net_benefit_evolution(
|
|
|
154
159
|
logger.debug("No viable evolution model found.")
|
|
155
160
|
break
|
|
156
161
|
|
|
157
|
-
if best_model is not owner:
|
|
162
|
+
if best_model is not None and best_model is not owner:
|
|
158
163
|
logger.debug(
|
|
159
164
|
"New best evolution model %s with TAC %.6f",
|
|
160
165
|
best_model.name,
|
|
161
166
|
best_model.TAC,
|
|
162
167
|
)
|
|
163
168
|
|
|
164
|
-
if best_model
|
|
169
|
+
if best_model is not None and best_model is not owner:
|
|
165
170
|
_update_with_best_model(owner, best_model)
|
|
166
171
|
else:
|
|
167
172
|
logger.debug("No evolution improvement found over original model.")
|
|
@@ -178,7 +183,7 @@ def _get_source_net_benefit_evolution(
|
|
|
178
183
|
"""Run the original OpenHENS single-path add/remove evolution search."""
|
|
179
184
|
|
|
180
185
|
model = owner
|
|
181
|
-
best_model = owner
|
|
186
|
+
best_model = _benchmark_model(owner)
|
|
182
187
|
for unit in range(max_depth):
|
|
183
188
|
logger.debug(
|
|
184
189
|
"Evolution step %s/%s - Current TAC: %s",
|
|
@@ -205,7 +210,7 @@ def _get_source_net_benefit_evolution(
|
|
|
205
210
|
if model is None:
|
|
206
211
|
logger.debug("No viable model found; ending evolution.")
|
|
207
212
|
break
|
|
208
|
-
if model.TAC < best_model.TAC:
|
|
213
|
+
if best_model is None or model.TAC < best_model.TAC:
|
|
209
214
|
best_model = model
|
|
210
215
|
logger.debug(
|
|
211
216
|
"New best model: %s found with TAC: %.6f",
|
|
@@ -213,7 +218,7 @@ def _get_source_net_benefit_evolution(
|
|
|
213
218
|
best_model.TAC,
|
|
214
219
|
)
|
|
215
220
|
|
|
216
|
-
if best_model
|
|
221
|
+
if best_model is not None and best_model is not owner:
|
|
217
222
|
_update_with_best_model(owner, best_model)
|
|
218
223
|
else:
|
|
219
224
|
logger.debug("No improvement found over original model.")
|
|
@@ -221,6 +226,27 @@ def _get_source_net_benefit_evolution(
|
|
|
221
226
|
return owner
|
|
222
227
|
|
|
223
228
|
|
|
229
|
+
def _benchmark_model(owner):
|
|
230
|
+
"""Return the starting model when its TAC is a fair benchmark, else None.
|
|
231
|
+
|
|
232
|
+
A solve that stopped before converging (for example at IPOPT's iteration
|
|
233
|
+
limit) is still reported as successful, but its objective can be far below
|
|
234
|
+
the cost of any real network. Evolution then keeps its best verified
|
|
235
|
+
candidate, and the workflow's final ranking compares it with the seed
|
|
236
|
+
network on verified costs.
|
|
237
|
+
"""
|
|
238
|
+
|
|
239
|
+
solver_run = getattr(owner, "solver_run", None)
|
|
240
|
+
if getattr(solver_run, "converged", True):
|
|
241
|
+
return owner
|
|
242
|
+
logger.warning(
|
|
243
|
+
"Starting model %s did not converge; evolution candidates are not "
|
|
244
|
+
"compared with its TAC.",
|
|
245
|
+
getattr(owner, "name", None),
|
|
246
|
+
)
|
|
247
|
+
return None
|
|
248
|
+
|
|
249
|
+
|
|
224
250
|
def _select_source_best_candidate(
|
|
225
251
|
owner,
|
|
226
252
|
current_model,
|
|
@@ -507,6 +533,8 @@ def _update_with_best_model(owner, best_model) -> None:
|
|
|
507
533
|
owner.area_cu_shared = copy.deepcopy(best_model.area_cu_shared)
|
|
508
534
|
owner.hu_area_cost_total = copy.deepcopy(best_model.hu_area_cost_total)
|
|
509
535
|
owner.cu_area_cost_total = copy.deepcopy(best_model.cu_area_cost_total)
|
|
536
|
+
if hasattr(best_model, "solver_run"):
|
|
537
|
+
owner.solver_run = best_model.solver_run
|
|
510
538
|
owner.get_post_process()
|
|
511
539
|
|
|
512
540
|
|
|
@@ -688,6 +716,9 @@ def _is_usable_evolution_candidate(candidate) -> bool:
|
|
|
688
716
|
return False
|
|
689
717
|
if not candidate.mSuccess:
|
|
690
718
|
return False
|
|
719
|
+
# A solve stopped at a limit keeps mSuccess, but its TAC is not reliable.
|
|
720
|
+
if not getattr(getattr(candidate, "solver_run", None), "converged", True):
|
|
721
|
+
return False
|
|
691
722
|
verify = getattr(candidate, "verify", None)
|
|
692
723
|
if not callable(verify):
|
|
693
724
|
return True
|
{openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/models/problem.py
RENAMED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from dataclasses import dataclass
|
|
5
|
+
from dataclasses import dataclass, replace
|
|
6
6
|
from typing import Any, Literal, Mapping, Sequence
|
|
7
7
|
|
|
8
8
|
from ....contracts.synthesis.result import HeatExchangerNetworkSynthesisResult
|
|
@@ -248,6 +248,7 @@ class InternalHeatExchangerNetworkProblem:
|
|
|
248
248
|
below_case=self.below,
|
|
249
249
|
above_case=self.above,
|
|
250
250
|
)
|
|
251
|
+
self._carry_unconverged_side_solve()
|
|
251
252
|
self.case.get_post_process()
|
|
252
253
|
if print_output:
|
|
253
254
|
self.case.output_to_cmd_line()
|
|
@@ -259,6 +260,23 @@ class InternalHeatExchangerNetworkProblem:
|
|
|
259
260
|
}
|
|
260
261
|
)
|
|
261
262
|
|
|
263
|
+
def _carry_unconverged_side_solve(self) -> None:
|
|
264
|
+
# The amalgamated model is built, not solved, so its own solver run
|
|
265
|
+
# says nothing about the sides' convergence.
|
|
266
|
+
for side in (self.above, self.below):
|
|
267
|
+
side_run = getattr(side, "solver_run", None)
|
|
268
|
+
if side.side_required and not getattr(side_run, "converged", True):
|
|
269
|
+
case_run = getattr(self.case, "solver_run", None)
|
|
270
|
+
self.case.solver_run = (
|
|
271
|
+
side_run
|
|
272
|
+
if case_run is None
|
|
273
|
+
else replace(
|
|
274
|
+
case_run,
|
|
275
|
+
termination_condition=side_run.termination_condition,
|
|
276
|
+
)
|
|
277
|
+
)
|
|
278
|
+
return
|
|
279
|
+
|
|
262
280
|
def remove_unused_stages(self, case) -> StageWiseModel:
|
|
263
281
|
"""Apply the source stage-utilisation reduction after PDM/TDM solves."""
|
|
264
282
|
|
{openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/results/README.md
RENAMED
|
@@ -6,7 +6,7 @@ Turns executed task outcomes into the canonical synthesis result, resolves seed
|
|
|
6
6
|
## Interface
|
|
7
7
|
- `SynthesisWorkflowResult` (`assembly.py`): frozen dataclass of tasks, outcomes, accepted result and run time.
|
|
8
8
|
- `build_synthesis_result` (`assembly.py`): demotes infeasible outcomes, accepts the best one and builds the result with its manifest.
|
|
9
|
-
- `demote_infeasible_outcomes` (`assembly.py`): marks solver successes that fail `verify_network_feasibility` as failed.
|
|
9
|
+
- `demote_infeasible_outcomes` (`assembly.py`): marks solver successes that fail `verify_network_feasibility`, or that carry `diagnostics["unconverged_termination"]`, as failed.
|
|
10
10
|
- `resolve_seed_networks` (`seeds.py`): returns explicit seed networks or the cached upstream design network.
|
|
11
11
|
- `ranked_networks` (`selection.py`): unique ranked outcomes of a result.
|
|
12
12
|
- `network_for_rank` (`selection.py`): network at a one-based rank, without mutation.
|
|
@@ -14,7 +14,7 @@ Turns executed task outcomes into the canonical synthesis result, resolves seed
|
|
|
14
14
|
|
|
15
15
|
## Invariants
|
|
16
16
|
- The accepted outcome is the successful outcome with the lowest `outcome_ranking_key`, whichever method produced it; ties are broken by task id [assembly.py:_accepted_outcome].
|
|
17
|
-
- Infeasible outcomes are demoted before acceptance, keeping their network and a reason; `WorkflowContractError` is raised only when no success remains [assembly.py:demote_infeasible_outcomes, _accepted_outcome].
|
|
17
|
+
- Infeasible and unconverged outcomes are demoted before acceptance, keeping their network and a reason; `WorkflowContractError` is raised only when no success remains [assembly.py:demote_infeasible_outcomes, _accepted_outcome].
|
|
18
18
|
- The accepted network must be present, and its run id, task id, period id, method are overwritten from settings and task, and the stage count is kept from the network when it has one [assembly.py:build_synthesis_result].
|
|
19
19
|
- Manifest approach temperatures are those the tasks actually ran, falling back to the settings values [assembly.py:build_synthesis_result].
|
|
20
20
|
- Manifest `method_sequence` lists each method once, in outcome order (PDM, TDM, EVM, though tiers above 1 also run some EVM tasks before TDM), without outcomes that failed because Couenne is missing; `settings.method_sequence` does not affect it [assembly.py:_executed_method_sequence].
|
{openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/results/assembly.py
RENAMED
|
@@ -179,10 +179,23 @@ def demote_infeasible_outcomes(
|
|
|
179
179
|
|
|
180
180
|
One infeasible outcome no longer aborts the synthesis: it keeps its network
|
|
181
181
|
and reasons for diagnostics, and the result is selected from the feasible
|
|
182
|
-
outcomes. Selection raises only when none is left.
|
|
182
|
+
outcomes. Selection raises only when none is left. A solve that stopped
|
|
183
|
+
before converging is demoted too: it stayed a success only so downstream
|
|
184
|
+
tasks could start from it, and its objective is not a converged optimum.
|
|
183
185
|
"""
|
|
184
186
|
demoted = []
|
|
185
187
|
for outcome in outcomes:
|
|
188
|
+
termination = outcome.diagnostics.get("unconverged_termination")
|
|
189
|
+
if outcome.status == "success" and termination is not None:
|
|
190
|
+
demoted.append(
|
|
191
|
+
outcome.model_copy(
|
|
192
|
+
update={
|
|
193
|
+
"status": "failed",
|
|
194
|
+
"error": f"solver stopped before converging ({termination})",
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
continue
|
|
186
199
|
failures = (
|
|
187
200
|
verify_network_feasibility(outcome.network)
|
|
188
201
|
if outcome.status == "success"
|
{openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/solver/README.md
RENAMED
|
@@ -7,7 +7,7 @@ Everything between a prepared problem and the equation models: solver arrays bui
|
|
|
7
7
|
- `problem_to_solver_arrays`, `PreparedSolverArrays`, `SEGMENT_PROFILE_VERSION`, `annual_cost_scales` (`arrays.py`): prepared-problem to padded, period-indexed arrays, axis maps, identities and unit conventions.
|
|
8
8
|
- `PiecewiseThermalProfile`, `profile_from_solver_arrays`, `utility_thermal_profile`, `duty_aligned_area_contributions`, `add_piecewise_temperature_mapping`, `add_piecewise_cost_mapping`, `add_piecewise_temperature_contribution_mapping` (`piecewise.py`): segment profiles, duty-aligned area slices, and model constraints mapping duty to temperature, cost or contribution.
|
|
9
9
|
- `build_pinch_design_decomposition`, `PinchDesignDecomposition`, `PinchDesignTarget`, `PinchLocation`, `StageSelection` (`pinch_design_decomposition.py`): per-period pinch targets and clipped active-stream fields for the PDM.
|
|
10
|
-
- `SolverRun`, `create_gekko_model`, `cleanup_gekko_model`, `require_solver_backend`, `configure_gekko_solver`, `solve_gekko_model`, `suppress_gekko_numpy_array_copy_deprecation`, `PYOMO_SOLVERS`, `GEKKO_SOLVERS`, `DEFAULT_IPOPT_GEKKO_OPTIONS` (`backend.py`): solver selection, option files and normalised solves.
|
|
10
|
+
- `SolverRun`, `create_gekko_model`, `cleanup_gekko_model`, `require_solver_backend`, `configure_gekko_solver`, `solve_gekko_model`, `suppress_gekko_numpy_array_copy_deprecation`, `PYOMO_SOLVERS`, `GEKKO_SOLVERS`, `CONVERGED_TERMINATION_CONDITIONS`, `DEFAULT_IPOPT_GEKKO_OPTIONS` (`backend.py`): solver selection, option files and normalised solves.
|
|
11
11
|
- `require_synthesis_dependency`, `require_declared_synthesis_dependencies`, `require_solver_binary`, `SYNTHESIS_DEPENDENCIES`, `SynthesisDependency`, `SYNTHESIS_EXTRA`, `MissingSynthesisDependencyError`, `MissingSynthesisSolverError` (`dependencies.py`): optional package and executable guards.
|
|
12
12
|
|
|
13
13
|
## Invariants
|
|
@@ -20,8 +20,11 @@ Everything between a prepared problem and the equation models: solver arrays bui
|
|
|
20
20
|
- Exchanger duty beyond a profile raises, except for solver noise within a relative allowance that is dropped [piecewise.py:duty_aligned_area_contributions].
|
|
21
21
|
- The PDM decomposition works on a deep copy of the master zone, and its stage boundary count satisfies `K = S + 1` [pinch_design_decomposition.py:_zone_with_hen_dt_contribution, PinchDesignDecomposition].
|
|
22
22
|
- Shifted pinch temperature is the selected pinch (cold pinch when the hot utility target is zero, otherwise hot pinch) in K [pinch_design_decomposition.py:_shifted_pinch_temperature].
|
|
23
|
+
- A stream is active on a side of the pinch only if it reaches more than `tol` past its pinch temperature, so a stream that starts or ends at the pinch is not kept on the far side as a sliver [pinch_design_decomposition.py:_clip_stream_temperatures].
|
|
23
24
|
- Solver names must be in `PYOMO_SOLVERS | GEKKO_SOLVERS`; solver options are validated [backend.py:require_solver_backend, _normalise_solver_options].
|
|
24
25
|
- Pyomo solves that need an option file are serialised by a process-wide lock [backend.py:_solver_working_directory].
|
|
26
|
+
- `create_gekko_model` returns a GEKKO subclass that records each Pyomo solve's termination condition on `SolverRun.termination_condition`. GEKKO reports a solve that stopped at an iteration or time limit as successful; `SolverRun.converged` is false for any condition outside `CONVERGED_TERMINATION_CONDITIONS`, and true when none was recorded (GEKKO-native solvers) [backend.py:create_gekko_model, SolverRun.converged].
|
|
27
|
+
- That subclass and its Pyomo converter are built on first use (importing `backend` does not import gekko) and published once as module attributes of `backend`, so models from `create_gekko_model` pickle for process pool workers [backend.py:_termination_recording_class, __getattr__].
|
|
25
28
|
|
|
26
29
|
## Side Effects
|
|
27
30
|
- Pyomo solves with an option file (solver options supplied) change the process working directory under a per-process thread lock, restoring it afterwards [backend.py:_solver_working_directory].
|
{openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/solver/arrays.py
RENAMED
|
@@ -178,6 +178,7 @@ def problem_to_solver_arrays(
|
|
|
178
178
|
"dt_cont_multipliers",
|
|
179
179
|
None,
|
|
180
180
|
),
|
|
181
|
+
"HENS_MIN_EXCHANGER_APPROACH_SHARE": hens.min_exchanger_approach_share,
|
|
181
182
|
"HENS_SYNTHESIS_QUALITY_TIER": hens.synthesis_quality_tier,
|
|
182
183
|
"HENS_PDM_STAGE_PAIR_LIMIT": hens.pdm_stage_pair_limit,
|
|
183
184
|
"HENS_TDM_PARENT_LIMIT": hens.tdm_parent_limit,
|
{openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_exchanger_networks/solver/backend.py
RENAMED
|
@@ -38,6 +38,12 @@ DEFAULT_IPOPT_GEKKO_OPTIONS: dict[str, Any] = {
|
|
|
38
38
|
"max_iter": 1000,
|
|
39
39
|
"print_level": 5,
|
|
40
40
|
}
|
|
41
|
+
# Pyomo termination conditions of a converged solve. GEKKO's Pyomo extension
|
|
42
|
+
# only warns on the others (an iteration or time limit, for example) and still
|
|
43
|
+
# reports the solve as successful.
|
|
44
|
+
CONVERGED_TERMINATION_CONDITIONS = frozenset(
|
|
45
|
+
{"optimal", "locallyOptimal", "globallyOptimal", "feasible"}
|
|
46
|
+
)
|
|
41
47
|
GEKKO_NUMPY_ARRAY_COPY_DEPRECATION = (
|
|
42
48
|
r"__array__ implementation doesn't accept a copy keyword.*"
|
|
43
49
|
)
|
|
@@ -55,17 +61,78 @@ class SolverRun:
|
|
|
55
61
|
failure_reason: str | None = None
|
|
56
62
|
solver_options: dict[str, Any] | None = None
|
|
57
63
|
option_file: str | None = None
|
|
64
|
+
termination_condition: str | None = None
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def converged(self) -> bool:
|
|
68
|
+
"""False when the solver stopped before converging, for example at its
|
|
69
|
+
iteration limit. Solves without a recorded condition count as converged."""
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
self.termination_condition is None
|
|
73
|
+
or self.termination_condition in CONVERGED_TERMINATION_CONDITIONS
|
|
74
|
+
)
|
|
58
75
|
|
|
59
76
|
|
|
60
77
|
def create_gekko_model(*, remote: bool = False) -> Any:
|
|
61
|
-
"""Create a GEKKO model after the optional dependency has been requested.
|
|
78
|
+
"""Create a GEKKO model after the optional dependency has been requested.
|
|
79
|
+
|
|
80
|
+
The model records the Pyomo termination condition of each solve, which
|
|
81
|
+
GEKKO itself only prints.
|
|
82
|
+
"""
|
|
62
83
|
|
|
63
|
-
|
|
84
|
+
require_synthesis_dependency(
|
|
64
85
|
"gekko",
|
|
65
86
|
package="gekko",
|
|
66
87
|
purpose="GEKKO heat exchanger network equation model construction",
|
|
67
88
|
)
|
|
68
|
-
return
|
|
89
|
+
return _termination_recording_class("_TerminationRecordingGEKKO")(remote=remote)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def __getattr__(name: str) -> type:
|
|
93
|
+
# Pickle looks classes up by module and name, so unpickling a model in a
|
|
94
|
+
# process pool worker resolves the lazily built classes here.
|
|
95
|
+
if name in _TERMINATION_RECORDING_CLASS_NAMES:
|
|
96
|
+
return _termination_recording_class(name)
|
|
97
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
_TERMINATION_RECORDING_CLASS_NAMES = frozenset(
|
|
101
|
+
{"_TerminationRecordingGEKKO", "_TerminationRecordingPyomoConverter"}
|
|
102
|
+
)
|
|
103
|
+
_TERMINATION_RECORDING_CLASS_LOCK = threading.Lock()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _termination_recording_class(name: str) -> type:
|
|
107
|
+
"""Return a GEKKO subclass published as a module attribute of this module.
|
|
108
|
+
|
|
109
|
+
The classes are built on first use, so importing this module does not
|
|
110
|
+
import gekko, and published once, so models pickle by reference to them.
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
with _TERMINATION_RECORDING_CLASS_LOCK:
|
|
114
|
+
if name not in globals():
|
|
115
|
+
_define_termination_recording_classes()
|
|
116
|
+
return globals()[name]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _define_termination_recording_classes() -> None:
|
|
120
|
+
from gekko import GEKKO
|
|
121
|
+
from gekko.gk_solver_extension_pyomo import PyomoConverter
|
|
122
|
+
|
|
123
|
+
class _TerminationRecordingPyomoConverter(PyomoConverter):
|
|
124
|
+
def handle_status(self, status_dict, status, status_string) -> None:
|
|
125
|
+
if isinstance(status, self.TerminationCondition):
|
|
126
|
+
self._gekko_model._openpinch_termination_condition = str(status)
|
|
127
|
+
super().handle_status(status_dict, status, status_string)
|
|
128
|
+
|
|
129
|
+
class _TerminationRecordingGEKKO(GEKKO):
|
|
130
|
+
def solver_extension_pyomo(self, disp=True):
|
|
131
|
+
self.solve_with_converter(_TerminationRecordingPyomoConverter, disp)
|
|
132
|
+
|
|
133
|
+
for cls in (_TerminationRecordingPyomoConverter, _TerminationRecordingGEKKO):
|
|
134
|
+
cls.__qualname__ = cls.__name__
|
|
135
|
+
globals()[cls.__name__] = cls
|
|
69
136
|
|
|
70
137
|
|
|
71
138
|
def cleanup_gekko_model(model: Any) -> None:
|
|
@@ -208,6 +275,7 @@ def solve_gekko_model(
|
|
|
208
275
|
|
|
209
276
|
extension = getattr(model.options, "SOLVER_EXTENSION", None)
|
|
210
277
|
_restore_run_directory(model)
|
|
278
|
+
model._openpinch_termination_condition = None
|
|
211
279
|
start = time.time()
|
|
212
280
|
failure_reason = None
|
|
213
281
|
try:
|
|
@@ -232,6 +300,7 @@ def solve_gekko_model(
|
|
|
232
300
|
failure_reason=failure_reason,
|
|
233
301
|
solver_options=getattr(model, "_openpinch_solver_options", None),
|
|
234
302
|
option_file=getattr(model, "_openpinch_solver_option_file", None),
|
|
303
|
+
termination_condition=model._openpinch_termination_condition,
|
|
235
304
|
)
|
|
236
305
|
|
|
237
306
|
|
|
@@ -474,13 +474,15 @@ def _clip_stream_temperatures(
|
|
|
474
474
|
) -> tuple[tuple[int, ...], tuple[int, ...]]:
|
|
475
475
|
hot_thresholds = shifted_pinch_temperature + np.asarray(hot_contributions)
|
|
476
476
|
cold_thresholds = shifted_pinch_temperature - np.asarray(cold_contributions)
|
|
477
|
+
# The problem table rounds the pinch to tol, so a stream that starts or ends
|
|
478
|
+
# at the pinch can look a sliver past it. It is not active on that side.
|
|
477
479
|
if pinch_location == "above":
|
|
478
480
|
z_i_active = tuple(
|
|
479
|
-
1 if value > threshold else 0
|
|
481
|
+
1 if value > threshold + tol else 0
|
|
480
482
|
for value, threshold in zip(T_h_in, hot_thresholds)
|
|
481
483
|
)
|
|
482
484
|
z_j_active = tuple(
|
|
483
|
-
1 if value > threshold else 0
|
|
485
|
+
1 if value > threshold + tol else 0
|
|
484
486
|
for value, threshold in zip(T_c_out, cold_thresholds)
|
|
485
487
|
)
|
|
486
488
|
for index, is_active in enumerate(z_i_active):
|
|
@@ -497,11 +499,11 @@ def _clip_stream_temperatures(
|
|
|
497
499
|
T_c_out[index] = 0.0
|
|
498
500
|
else:
|
|
499
501
|
z_i_active = tuple(
|
|
500
|
-
1 if value < threshold else 0
|
|
502
|
+
1 if value < threshold - tol else 0
|
|
501
503
|
for value, threshold in zip(T_h_out, hot_thresholds)
|
|
502
504
|
)
|
|
503
505
|
z_j_active = tuple(
|
|
504
|
-
1 if value < threshold else 0
|
|
506
|
+
1 if value < threshold - tol else 0
|
|
505
507
|
for value, threshold in zip(T_c_in, cold_thresholds)
|
|
506
508
|
)
|
|
507
509
|
for index, is_active in enumerate(z_i_active):
|
|
@@ -33,7 +33,7 @@ multi-stage vapour-compression objective, and residual utility accounting.
|
|
|
33
33
|
- A cascade stage whose work is at most `NEGLIGIBLE_STAGE_WORK_FRACTION` of the machine's work is not charged stage capital. [shared.py:_single_cost_unit]
|
|
34
34
|
- The feasibility penalty is `rho * sum(r + r^2)` with violations relative to `Q_hpr_target`. Vapour results price it at the no-heat-pump annual cost, at least 1 $/y; Carnot results scale it by `max(Q_hpr_target, 1) * max(price ratio, 1)` in power-equivalent units, with violations measured against `max(Q_hpr_target, 1)`, with no annual-cost scale or floor. [shared.py:_cycle_penalty] [shared.py:hpr_penalty_cost_scale] [optimisation_adapter.py:build_hpr_accounting]
|
|
35
35
|
- Errors raised after a cycle has solved are re-raised, not ranked as infeasible candidates. [multi_vc_objective.py:_evaluate_multi_vc_objective] [shared.py:post_solve_error]
|
|
36
|
-
- Ambient air and cooling water are applied through `cascade_with_air` on the condenser and evaporator cascades; cooling water applies on the evaporator side only. [shared.py:
|
|
36
|
+
- Ambient air and cooling water are applied through `cascade_with_air` on the condenser and evaporator cascades; cooling water applies on the evaporator side only. Air is left out when `args.ambient_air_enabled` is false (`HPR_AMBIENT_AIR_ENABLED`). [shared.py:_cascade_air_duties]
|
|
37
37
|
- `calc_carnot_heat_pump_cop` and `calc_carnot_heat_engine_eta` take absolute temperatures (K); `satisfies_second_law` takes degC and adds 273.15 internally, and `compute_entropic_mean_temperature` takes degC by default and returns K. [shared.py:calc_carnot_heat_pump_cop] [shared.py:satisfies_second_law]
|
|
38
38
|
- Residual loads below `max(tol, 1e-7 * largest)` are treated as rounding noise and set to zero; duplicate residual temperatures with conflicting values raise `ValueError`. [postprocessing.py:_residual_noise_floor] [postprocessing.py:_deduplicate_residual_profile_rows]
|
|
39
39
|
- `common` imports the parent's `optimisation_adapter` and `performance_maps.targeting` for accounting and backend names. [shared.py] [preprocessing.py]
|
|
@@ -21,7 +21,7 @@ What the parent and siblings import from this package:
|
|
|
21
21
|
## Invariants
|
|
22
22
|
- Air and cooling water never create a utility demand: the duties they take or give are limited by the smallest cascade flow on the affected side, and cannot be negative. [air.py:cascade_with_air]
|
|
23
23
|
- The cascade is supplied with `T` descending and `H_net` clipped to non-negative before use. [air.py:cascade_with_air]
|
|
24
|
-
- Air supplies heat before it takes heat, and cooling water acts only on what air leaves. [air.py:cascade_with_air]
|
|
24
|
+
- Air supplies heat before it takes heat, and cooling water acts only on what air leaves. With `air=False` no air is placed and cooling water acts on the whole cascade. [air.py:cascade_with_air]
|
|
25
25
|
- A sink at or above the top of the cascade takes no heat. [air.py:_sink_duty]
|
|
26
26
|
- Ambient and cooling-water levels are shifted by `dt_env_cont`, `dt_cooling_water` and `dtcont_hp`, with `dtcont_hp` applied in the opposite sense on the source and sink sides. [air.py:ambient_source_temperature]
|
|
27
27
|
- Carnot condenser and evaporator levels closer than `dt_phase_change` are merged and their duties summed before streams are built. [streams.py:_get_carnot_hpr_cycle_cascade_profile]
|
|
@@ -99,6 +99,7 @@ def cascade_with_air(
|
|
|
99
99
|
T_air_sink: float,
|
|
100
100
|
T_cooling_water: float | None = None,
|
|
101
101
|
utility_bands: Sequence[tuple[float, float]] = (),
|
|
102
|
+
air: bool = True,
|
|
102
103
|
) -> CascadeWithAir:
|
|
103
104
|
"""Place free ambient air in a feasible cascade and return external duties.
|
|
104
105
|
|
|
@@ -113,7 +114,8 @@ def cascade_with_air(
|
|
|
113
114
|
saves the dearer hot utility, then takes heat from what flows on.
|
|
114
115
|
Cooling water at ``T_cooling_water`` then takes heat the same way from
|
|
115
116
|
what is left. A level inside one of ``utility_bands``, each ``(upper, lower)``,
|
|
116
|
-
moves to the end of that band, so the band counts as at the level.
|
|
117
|
+
moves to the end of that band, so the band counts as at the level. With
|
|
118
|
+
``air`` false no air is placed and only cooling water acts.
|
|
117
119
|
"""
|
|
118
120
|
T = np.asarray(T, dtype=float)
|
|
119
121
|
H_net = np.maximum(np.asarray(H_net, dtype=float), 0.0)
|
|
@@ -132,7 +134,7 @@ def cascade_with_air(
|
|
|
132
134
|
# Air heat enters at the source level and can only meet deficits below it;
|
|
133
135
|
# it also lowers every flow above that level, which must stay non-negative.
|
|
134
136
|
Q_air_source = 0.0
|
|
135
|
-
if T_air_source > T_grid[-1]:
|
|
137
|
+
if air and T_air_source > T_grid[-1]:
|
|
136
138
|
above = T_grid >= T_air_source
|
|
137
139
|
at = float(np.interp(T_air_source, T_grid[::-1], H_grid[::-1]))
|
|
138
140
|
absorbed_below = at - float(H_grid[T_grid <= T_air_source].min())
|
|
@@ -140,7 +142,7 @@ def cascade_with_air(
|
|
|
140
142
|
Q_air_source = max(min(flow_limit, absorbed_below), 0.0)
|
|
141
143
|
|
|
142
144
|
remaining = H_grid - np.where(_at_or_above(T_grid, T_air_source), Q_air_source, 0.0)
|
|
143
|
-
Q_air_sink = _sink_duty(T_grid, remaining, T_air_sink)
|
|
145
|
+
Q_air_sink = _sink_duty(T_grid, remaining, T_air_sink) if air else 0.0
|
|
144
146
|
remaining = remaining - np.where(_at_or_below(T_grid, T_air_sink), Q_air_sink, 0.0)
|
|
145
147
|
Q_cooling_water = (
|
|
146
148
|
0.0
|
|
@@ -118,6 +118,7 @@ def construct_HPRTargetInputs(
|
|
|
118
118
|
max_pressure_ratio=hpr.max_pressure_ratio,
|
|
119
119
|
T_env=environment.temperature,
|
|
120
120
|
dt_env_cont=hpr.dt_env_cont,
|
|
121
|
+
ambient_air_enabled=hpr.ambient_air_enabled,
|
|
121
122
|
dt_phase_change=thermal.dt_phase_change,
|
|
122
123
|
eta_penalty=hpr.eta_penalty,
|
|
123
124
|
rho_penalty=hpr.rho_penalty,
|
|
@@ -18,7 +18,7 @@ One module per heat pump and refrigeration (HPR) cycle topology. Each defines ho
|
|
|
18
18
|
- Carnot objective vectors hold condenser fractions, evaporator fractions and heat-split fractions, all bounded to [0, 1]; the initial point starts every heat split at 1 [_carnot_common.py:carnot_opt_setup].
|
|
19
19
|
- Parallel Carnot and parallel vapour compression equalise `n_cond` and `n_evap` to the larger value on `args`, and callers rely on that after the solve [_carnot_common.py:normalise_carnot_stage_counts, parallel_vapour_compression.py:optimise_parallel_heat_pump_placement].
|
|
20
20
|
- Condenser temperatures are capped and evaporator temperatures floored through `common.shared` helpers before use [cascade_vapour_compression.py:_parse_cascade_hp_state_variables, parallel_vapour_compression.py:_parse_parallel_hp_state_temperatures].
|
|
21
|
-
- Air is a partner for refrigeration heat sink and heat pump heat source only [_carnot_common.py:parse_carnot_state_variables].
|
|
21
|
+
- Air is a partner for refrigeration heat sink and heat pump heat source only, and adds no availability when `ambient_air_enabled` is false [_carnot_common.py:parse_carnot_state_variables].
|
|
22
22
|
- The Carnot warm start is clipped into the refrigerant's subcritical condensing range and seed duties are encoded against availability at the seed temperatures [cascade_vapour_compression.py:_get_cascade_hp_opt_setup, parallel_vapour_compression.py:_get_parallel_hp_opt_setup, vapour_compression_mvr.py:_get_vc_mvr_opt_setup].
|
|
23
23
|
- Cascade process-control counts depend on mode: a heat pump has `n_cond` heat controls and `n_evap - 1` cool controls, a refrigerator the reverse, with its heat controls on `T_cond[1:]` because the top stage takes the remaining heat [cascade_vapour_compression.py:_cascade_process_control_counts].
|
|
24
24
|
- VC+MVR state arrays are ordered [MVR stages, VC stages]; the MVR lift is at most `MAX_MVR_STAGE_LIFT` (20 K) [vapour_compression_mvr.py:_unpack_vc_mvr_state, vapour_compression_mvr.py:_parse_vc_mvr_state_variables].
|
{openpinch-0.8.0 → openpinch-0.8.2}/OpenPinch/analysis/heat_pumps/targeting/_carnot_common.py
RENAMED
|
@@ -101,7 +101,11 @@ def parse_carnot_state_variables(
|
|
|
101
101
|
# Air can be a refrigerator's heat sink and a heat pump's heat source, but
|
|
102
102
|
# never a heat pump's load or a refrigerator's duty. Where it is a partner
|
|
103
103
|
# it adds generous availability; the cascade decides how much air is used.
|
|
104
|
-
air_allowance =
|
|
104
|
+
air_allowance = (
|
|
105
|
+
float(args.Q_heat_max + args.Q_cool_max)
|
|
106
|
+
if getattr(args, "ambient_air_enabled", True)
|
|
107
|
+
else 0.0
|
|
108
|
+
)
|
|
105
109
|
heat_air = 0.0 if args.is_heat_pumping else air_allowance
|
|
106
110
|
cool_air = air_allowance if args.is_heat_pumping else 0.0
|
|
107
111
|
H_cold_available = args.H_cold + args.z_amb_cold * heat_air
|
|
@@ -340,6 +340,12 @@ class _DesignAccessor:
|
|
|
340
340
|
"""Run the default HEN synthesis workflow.
|
|
341
341
|
|
|
342
342
|
It runs quality tier 0 unless ``HENS_SYNTHESIS_QUALITY_TIER`` is set.
|
|
343
|
+
|
|
344
|
+
``approach_temperatures`` sets the pinch design step's approach. The
|
|
345
|
+
later thermal derivative and evolution steps choose each exchanger's
|
|
346
|
+
approach by total annual cost, down to 0.1 K, or down to
|
|
347
|
+
``HENS_MIN_EXCHANGER_APPROACH_SHARE`` (in ``options``) times the
|
|
348
|
+
requested approach if that is larger.
|
|
343
349
|
"""
|
|
344
350
|
from ....analysis.heat_exchanger_networks.service import (
|
|
345
351
|
_heat_exchanger_network_enhanced_synthesis_method_service,
|