carnopy 0.1.0a1__py3-none-any.whl
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.
- carnopy/__init__.py +59 -0
- carnopy/__main__.py +9 -0
- carnopy/_version.py +1 -0
- carnopy/api.py +30 -0
- carnopy/backends/__init__.py +29 -0
- carnopy/backends/base.py +42 -0
- carnopy/backends/coolprop.py +109 -0
- carnopy/cli.py +517 -0
- carnopy/config/__init__.py +18 -0
- carnopy/config/io.py +37 -0
- carnopy/config/models.py +99 -0
- carnopy/config/normalize.py +115 -0
- carnopy/config/outputs.py +28 -0
- carnopy/config/visualization.py +81 -0
- carnopy/domain/__init__.py +3 -0
- carnopy/domain/failures.py +58 -0
- carnopy/domain/phases.py +19 -0
- carnopy/domain/properties.py +151 -0
- carnopy/domain/units.py +75 -0
- carnopy/generation/__init__.py +11 -0
- carnopy/generation/common.py +219 -0
- carnopy/generation/property_table.py +57 -0
- carnopy/generation/saturation_table.py +127 -0
- carnopy/generation/vapor_mass_fraction_table.py +99 -0
- carnopy/outputs/__init__.py +27 -0
- carnopy/outputs/layout.py +62 -0
- carnopy/outputs/metadata.py +117 -0
- carnopy/outputs/reports.py +68 -0
- carnopy/outputs/schemas.py +56 -0
- carnopy/outputs/writers.py +90 -0
- carnopy/pipeline.py +234 -0
- carnopy/provenance.py +93 -0
- carnopy/py.typed +1 -0
- carnopy/results.py +53 -0
- carnopy/sampling/__init__.py +4 -0
- carnopy/sampling/generate.py +57 -0
- carnopy/sampling/models.py +98 -0
- carnopy/templates/__init__.py +80 -0
- carnopy/templates/property_table.yaml +34 -0
- carnopy/templates/saturation_table.yaml +25 -0
- carnopy/templates/vapor_mass_fraction_table.yaml +31 -0
- carnopy/visualization/__init__.py +72 -0
- carnopy/visualization/automation.py +272 -0
- carnopy/visualization/config_io.py +29 -0
- carnopy/visualization/configuration.py +326 -0
- carnopy/visualization/curves.py +368 -0
- carnopy/visualization/diagrams.py +157 -0
- carnopy/visualization/export.py +307 -0
- carnopy/visualization/fields.py +191 -0
- carnopy/visualization/heatmaps.py +244 -0
- carnopy/visualization/inspect.py +205 -0
- carnopy/visualization/io.py +261 -0
- carnopy/visualization/models.py +75 -0
- carnopy/visualization/plots.py +652 -0
- carnopy/visualization/render.py +108 -0
- carnopy/visualization/requests.py +295 -0
- carnopy/visualization/selection.py +288 -0
- carnopy/visualization/series.py +331 -0
- carnopy/visualization/xy.py +201 -0
- carnopy-0.1.0a1.dist-info/METADATA +826 -0
- carnopy-0.1.0a1.dist-info/RECORD +64 -0
- carnopy-0.1.0a1.dist-info/WHEEL +4 -0
- carnopy-0.1.0a1.dist-info/entry_points.txt +2 -0
- carnopy-0.1.0a1.dist-info/licenses/LICENSE +21 -0
carnopy/__init__.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from importlib import import_module
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
from carnopy._version import __version__
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from carnopy.api import generate_dataset, load_config, validate_config
|
|
10
|
+
from carnopy.config.models import CarnopyConfig, NormalizedConfig
|
|
11
|
+
from carnopy.config.outputs import OutputConfig
|
|
12
|
+
from carnopy.config.visualization import VisualizationConfig, VisualizationPlotConfig
|
|
13
|
+
from carnopy.results import RunResult, ValidationResult, VisualizationSummary
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"CarnopyConfig",
|
|
17
|
+
"NormalizedConfig",
|
|
18
|
+
"OutputConfig",
|
|
19
|
+
"RunResult",
|
|
20
|
+
"ValidationResult",
|
|
21
|
+
"VisualizationConfig",
|
|
22
|
+
"VisualizationPlotConfig",
|
|
23
|
+
"VisualizationSummary",
|
|
24
|
+
"__version__",
|
|
25
|
+
"generate_dataset",
|
|
26
|
+
"load_config",
|
|
27
|
+
"validate_config",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
_LAZY_EXPORTS = {
|
|
31
|
+
"CarnopyConfig": ("carnopy.config.models", "CarnopyConfig"),
|
|
32
|
+
"NormalizedConfig": ("carnopy.config.models", "NormalizedConfig"),
|
|
33
|
+
"OutputConfig": ("carnopy.config.outputs", "OutputConfig"),
|
|
34
|
+
"RunResult": ("carnopy.results", "RunResult"),
|
|
35
|
+
"ValidationResult": ("carnopy.results", "ValidationResult"),
|
|
36
|
+
"VisualizationConfig": ("carnopy.config.visualization", "VisualizationConfig"),
|
|
37
|
+
"VisualizationPlotConfig": (
|
|
38
|
+
"carnopy.config.visualization",
|
|
39
|
+
"VisualizationPlotConfig",
|
|
40
|
+
),
|
|
41
|
+
"VisualizationSummary": ("carnopy.results", "VisualizationSummary"),
|
|
42
|
+
"generate_dataset": ("carnopy.api", "generate_dataset"),
|
|
43
|
+
"load_config": ("carnopy.api", "load_config"),
|
|
44
|
+
"validate_config": ("carnopy.api", "validate_config"),
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def __getattr__(name: str) -> Any:
|
|
49
|
+
try:
|
|
50
|
+
module_name, attribute_name = _LAZY_EXPORTS[name]
|
|
51
|
+
except KeyError as exc:
|
|
52
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from exc
|
|
53
|
+
value = getattr(import_module(module_name), attribute_name)
|
|
54
|
+
globals()[name] = value
|
|
55
|
+
return value
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def __dir__() -> list[str]:
|
|
59
|
+
return sorted(set(globals()) | set(__all__))
|
carnopy/__main__.py
ADDED
carnopy/_version.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0a1"
|
carnopy/api.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from carnopy.config.io import LoadedConfig, load_config_file
|
|
6
|
+
from carnopy.pipeline import run_generation, validate_loaded_config
|
|
7
|
+
from carnopy.results import RunResult, ValidationResult
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def load_config(path: str | Path) -> LoadedConfig:
|
|
11
|
+
return load_config_file(path)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def validate_config(path: str | Path) -> ValidationResult:
|
|
15
|
+
loaded = load_config_file(path)
|
|
16
|
+
return validate_loaded_config(loaded).result
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def generate_dataset(
|
|
20
|
+
path: str | Path,
|
|
21
|
+
*,
|
|
22
|
+
output_root: str | Path = "outputs",
|
|
23
|
+
figures_root: str | Path = "figures",
|
|
24
|
+
) -> RunResult:
|
|
25
|
+
loaded = load_config_file(path)
|
|
26
|
+
return run_generation(
|
|
27
|
+
loaded,
|
|
28
|
+
Path(output_root),
|
|
29
|
+
Path(figures_root),
|
|
30
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from importlib import import_module
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from carnopy.backends.base import PropertyBackend
|
|
8
|
+
from carnopy.backends.coolprop import CoolPropBackend
|
|
9
|
+
|
|
10
|
+
__all__ = ["CoolPropBackend", "PropertyBackend"]
|
|
11
|
+
|
|
12
|
+
_LAZY_EXPORTS = {
|
|
13
|
+
"CoolPropBackend": ("carnopy.backends.coolprop", "CoolPropBackend"),
|
|
14
|
+
"PropertyBackend": ("carnopy.backends.base", "PropertyBackend"),
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def __getattr__(name: str) -> Any:
|
|
19
|
+
try:
|
|
20
|
+
module_name, attribute_name = _LAZY_EXPORTS[name]
|
|
21
|
+
except KeyError as exc:
|
|
22
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from exc
|
|
23
|
+
value = getattr(import_module(module_name), attribute_name)
|
|
24
|
+
globals()[name] = value
|
|
25
|
+
return value
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def __dir__() -> list[str]:
|
|
29
|
+
return sorted(set(globals()) | set(__all__))
|
carnopy/backends/base.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Protocol
|
|
4
|
+
|
|
5
|
+
from carnopy.domain.failures import BackendResult
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PropertyBackend(Protocol):
|
|
9
|
+
@property
|
|
10
|
+
def name(self) -> str: ...
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def version(self) -> str: ...
|
|
14
|
+
|
|
15
|
+
def list_fluids(self) -> list[str]: ...
|
|
16
|
+
|
|
17
|
+
def aliases_for(self, canonical_fluid: str) -> list[str]: ...
|
|
18
|
+
|
|
19
|
+
def canonicalize_fluid(self, fluid: str) -> str: ...
|
|
20
|
+
|
|
21
|
+
def initialize_reference_states(self, fluids: list[str]) -> None: ...
|
|
22
|
+
|
|
23
|
+
def phase(
|
|
24
|
+
self,
|
|
25
|
+
fluid: str,
|
|
26
|
+
input1: str,
|
|
27
|
+
value1: float,
|
|
28
|
+
input2: str,
|
|
29
|
+
value2: float,
|
|
30
|
+
) -> BackendResult[str]: ...
|
|
31
|
+
|
|
32
|
+
def property(
|
|
33
|
+
self,
|
|
34
|
+
output: str,
|
|
35
|
+
fluid: str,
|
|
36
|
+
input1: str,
|
|
37
|
+
value1: float,
|
|
38
|
+
input2: str,
|
|
39
|
+
value2: float,
|
|
40
|
+
) -> BackendResult[float]: ...
|
|
41
|
+
|
|
42
|
+
def fluid_constant(self, output: str, fluid: str) -> BackendResult[float]: ...
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from functools import cached_property
|
|
4
|
+
|
|
5
|
+
import CoolProp
|
|
6
|
+
import CoolProp.CoolProp as CP
|
|
7
|
+
|
|
8
|
+
from carnopy.domain.failures import BackendInitializationError, BackendResult
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CoolPropBackend:
|
|
12
|
+
@property
|
|
13
|
+
def name(self) -> str:
|
|
14
|
+
return "coolprop"
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def version(self) -> str:
|
|
18
|
+
return str(CoolProp.__version__)
|
|
19
|
+
|
|
20
|
+
@cached_property
|
|
21
|
+
def _aliases(self) -> dict[str, str]:
|
|
22
|
+
aliases: dict[str, str] = {}
|
|
23
|
+
for canonical in self.list_fluids():
|
|
24
|
+
raw_aliases = CP.get_fluid_param_string(canonical, "aliases")
|
|
25
|
+
names = [canonical, *raw_aliases.split(",")]
|
|
26
|
+
for name in names:
|
|
27
|
+
cleaned = name.strip()
|
|
28
|
+
if cleaned:
|
|
29
|
+
aliases[cleaned.casefold()] = canonical
|
|
30
|
+
return aliases
|
|
31
|
+
|
|
32
|
+
def list_fluids(self) -> list[str]:
|
|
33
|
+
return sorted(str(fluid) for fluid in CP.FluidsList())
|
|
34
|
+
|
|
35
|
+
def aliases_for(self, canonical_fluid: str) -> list[str]:
|
|
36
|
+
raw = CP.get_fluid_param_string(canonical_fluid, "aliases")
|
|
37
|
+
aliases = {canonical_fluid}
|
|
38
|
+
aliases.update(name.strip() for name in raw.split(",") if name.strip())
|
|
39
|
+
return sorted(aliases)
|
|
40
|
+
|
|
41
|
+
def canonicalize_fluid(self, fluid: str) -> str:
|
|
42
|
+
if any(token in fluid for token in ("::", "&", "[", "]")):
|
|
43
|
+
raise ValueError(
|
|
44
|
+
f"mixtures and backend-prefixed fluid strings are unsupported: {fluid!r}"
|
|
45
|
+
)
|
|
46
|
+
try:
|
|
47
|
+
return self._aliases[fluid.strip().casefold()]
|
|
48
|
+
except KeyError as exc:
|
|
49
|
+
raise ValueError(f"unsupported CoolProp pure fluid {fluid!r}") from exc
|
|
50
|
+
|
|
51
|
+
def initialize_reference_states(self, fluids: list[str]) -> None:
|
|
52
|
+
for fluid in fluids:
|
|
53
|
+
try:
|
|
54
|
+
CP.set_reference_state(fluid, "DEF")
|
|
55
|
+
except Exception as exc:
|
|
56
|
+
raise BackendInitializationError(
|
|
57
|
+
f"failed to set CoolProp DEF reference state for {fluid}: {exc}"
|
|
58
|
+
) from exc
|
|
59
|
+
|
|
60
|
+
def phase(
|
|
61
|
+
self,
|
|
62
|
+
fluid: str,
|
|
63
|
+
input1: str,
|
|
64
|
+
value1: float,
|
|
65
|
+
input2: str,
|
|
66
|
+
value2: float,
|
|
67
|
+
) -> BackendResult[str]:
|
|
68
|
+
try:
|
|
69
|
+
value = str(CP.PhaseSI(input1, value1, input2, value2, fluid))
|
|
70
|
+
except Exception as exc:
|
|
71
|
+
return BackendResult.failure(
|
|
72
|
+
layer="backend",
|
|
73
|
+
code="backend_phase_call_failed",
|
|
74
|
+
message="CoolProp phase evaluation failed",
|
|
75
|
+
error=exc,
|
|
76
|
+
)
|
|
77
|
+
return BackendResult.success(value)
|
|
78
|
+
|
|
79
|
+
def property(
|
|
80
|
+
self,
|
|
81
|
+
output: str,
|
|
82
|
+
fluid: str,
|
|
83
|
+
input1: str,
|
|
84
|
+
value1: float,
|
|
85
|
+
input2: str,
|
|
86
|
+
value2: float,
|
|
87
|
+
) -> BackendResult[float]:
|
|
88
|
+
try:
|
|
89
|
+
value = float(CP.PropsSI(output, input1, value1, input2, value2, fluid))
|
|
90
|
+
except Exception as exc:
|
|
91
|
+
return BackendResult.failure(
|
|
92
|
+
layer="backend",
|
|
93
|
+
code="backend_property_call_failed",
|
|
94
|
+
message=f"CoolProp property evaluation failed for {output}",
|
|
95
|
+
error=exc,
|
|
96
|
+
)
|
|
97
|
+
return BackendResult.success(value)
|
|
98
|
+
|
|
99
|
+
def fluid_constant(self, output: str, fluid: str) -> BackendResult[float]:
|
|
100
|
+
try:
|
|
101
|
+
value = float(CP.PropsSI(output, fluid))
|
|
102
|
+
except Exception as exc:
|
|
103
|
+
return BackendResult.failure(
|
|
104
|
+
layer="backend",
|
|
105
|
+
code="backend_property_call_failed",
|
|
106
|
+
message=f"CoolProp fluid constant evaluation failed for {output}",
|
|
107
|
+
error=exc,
|
|
108
|
+
)
|
|
109
|
+
return BackendResult.success(value)
|