processforge 0.2.10__tar.gz → 0.2.12__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.
- {processforge-0.2.10/src/processforge.egg-info → processforge-0.2.12}/PKG-INFO +1 -1
- {processforge-0.2.10 → processforge-0.2.12}/pyproject.toml +1 -1
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/flowsheet.py +8 -6
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/schemas/flowsheet_schema.json +2 -1
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/utils/validate_flowsheet.py +58 -58
- {processforge-0.2.10 → processforge-0.2.12/src/processforge.egg-info}/PKG-INFO +1 -1
- {processforge-0.2.10 → processforge-0.2.12}/LICENSE +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/MANIFEST.in +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/README.md +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/flowsheets/archive/example_dynamic_hybrid.json +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/flowsheets/archive/example_dynamic_tank.json +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/flowsheets/archive/example_flash.json +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/flowsheets/archive/hydraulic_chain.json +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/flowsheets/closed-loop-chain.json +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/flowsheets/hydraulic-chain.json +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/setup.cfg +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/__init__.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/_schema.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/__init__.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/backends/__init__.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/backends/base.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/backends/casadi_backend.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/backends/pyomo_backend.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/backends/scipy_backend.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/flowsheet.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/jacobian.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/mixin.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/solver.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/stream_var.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/units/__init__.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/units/flash_eo.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/units/heater_eo.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/units/pipes_eo.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/units/pump_eo.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/units/strainer_eo.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/eo/units/valve_eo.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/fmu/__init__.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/fmu/_fmi_vars.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/fmu/builder.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/fmu/slave_template.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/modelica/__init__.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/modelica/mo_writer.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/modelica/omc_runner.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/modelica/transpiler.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/modelica/unit_equations.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/provenance.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/result.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/schemas/__init__.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/simulate.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/solver.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/thermo.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/units/__init__.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/units/flash.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/units/heater.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/units/pipes.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/units/pump.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/units/solver.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/units/strainer.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/units/tank.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/units/valve.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/utils/__init__.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/utils/flowsheet_diagram.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/utils/validation.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge/validate.py +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge.egg-info/SOURCES.txt +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge.egg-info/dependency_links.txt +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge.egg-info/entry_points.txt +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge.egg-info/requires.txt +0 -0
- {processforge-0.2.10 → processforge-0.2.12}/src/processforge.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "processforge"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.12"
|
|
8
8
|
description = "A Python-based process simulation framework for chemical engineering applications."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "BSD-3-Clause"
|
|
@@ -85,14 +85,16 @@ class Flowsheet:
|
|
|
85
85
|
if not unit_class:
|
|
86
86
|
logger.error(f"Unknown unit type: {unit_type}")
|
|
87
87
|
raise ValueError(f"Unknown unit type: {unit_type}")
|
|
88
|
-
|
|
88
|
+
_UNIT_META_KEYS = {"type", "in", "out", "material", "material_mix"}
|
|
89
|
+
unit = unit_class(
|
|
89
90
|
unit_name,
|
|
90
|
-
**{
|
|
91
|
-
k: v
|
|
92
|
-
for k, v in unit_config.items()
|
|
93
|
-
if k not in ["type", "in", "out"]
|
|
94
|
-
},
|
|
91
|
+
**{k: v for k, v in unit_config.items() if k not in _UNIT_META_KEYS},
|
|
95
92
|
)
|
|
93
|
+
if "material" in unit_config:
|
|
94
|
+
unit.material = unit_config["material"]
|
|
95
|
+
if "material_mix" in unit_config:
|
|
96
|
+
unit.material_mix = unit_config["material_mix"]
|
|
97
|
+
self.units[unit_name] = unit
|
|
96
98
|
logger.info(f"Built unit {unit_name} of type {unit_type}")
|
|
97
99
|
|
|
98
100
|
def _get_unit_inlets(self, unit_name):
|
|
@@ -154,82 +154,82 @@ def _check_pipe_linkage(config):
|
|
|
154
154
|
|
|
155
155
|
def _check_material_semantics(config):
|
|
156
156
|
"""
|
|
157
|
-
Validate
|
|
157
|
+
Validate material definitions and enforce that every unit has a valid material.
|
|
158
158
|
|
|
159
159
|
Checks:
|
|
160
|
-
1. density_units values are valid OpenMC units (when present).
|
|
160
|
+
1. density_units values are valid OpenMC units (when materials section is present).
|
|
161
161
|
2. friendly_material_id values are unique across all materials.
|
|
162
162
|
3. material_mixes component names resolve to entries in materials.
|
|
163
163
|
4. material_mixes fraction sum equals 1.0 (only when all fractions are provided).
|
|
164
164
|
5. Stream z-keys resolve to defined materials (when materials section is present).
|
|
165
|
-
6.
|
|
165
|
+
6. Every unit must have a material field referencing a valid friendly_material_id.
|
|
166
166
|
"""
|
|
167
|
-
materials = config.get("materials")
|
|
168
|
-
if not materials:
|
|
169
|
-
return True
|
|
170
|
-
|
|
171
|
-
material_mixes = config.get("material_mixes", {})
|
|
172
|
-
all_material_names = set(materials.keys())
|
|
167
|
+
materials = config.get("materials", {})
|
|
173
168
|
valid_ids = {mat_def["friendly_material_id"] for mat_def in materials.values()}
|
|
174
169
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if units is not None and units not in _VALID_DENSITY_UNITS:
|
|
179
|
-
raise ValueError(
|
|
180
|
-
f"❌ Material '{mat_name}' has invalid density_units '{units}'. "
|
|
181
|
-
f"Must be one of: {sorted(_VALID_DENSITY_UNITS)}"
|
|
182
|
-
)
|
|
170
|
+
if materials:
|
|
171
|
+
all_material_names = set(materials.keys())
|
|
172
|
+
material_mixes = config.get("material_mixes", {})
|
|
183
173
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
for i in ids:
|
|
189
|
-
if i in seen:
|
|
190
|
-
dupes.add(i)
|
|
191
|
-
seen.add(i)
|
|
192
|
-
raise ValueError(
|
|
193
|
-
f"❌ Duplicate friendly_material_id values found: {sorted(dupes)}"
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
# 3 & 4. Mix component name resolution and fraction sum
|
|
197
|
-
for mix_name, mix_def in material_mixes.items():
|
|
198
|
-
fractions = []
|
|
199
|
-
for component in mix_def.get("components", []):
|
|
200
|
-
comp_name = component["name"]
|
|
201
|
-
if comp_name not in all_material_names:
|
|
174
|
+
# 1. density_units validity — only checked when the field is present
|
|
175
|
+
for mat_name, mat_def in materials.items():
|
|
176
|
+
units = mat_def.get("density_units")
|
|
177
|
+
if units is not None and units not in _VALID_DENSITY_UNITS:
|
|
202
178
|
raise ValueError(
|
|
203
|
-
f"❌
|
|
204
|
-
f"
|
|
179
|
+
f"❌ Material '{mat_name}' has invalid density_units '{units}'. "
|
|
180
|
+
f"Must be one of: {sorted(_VALID_DENSITY_UNITS)}"
|
|
205
181
|
)
|
|
206
|
-
if "fraction" in component:
|
|
207
|
-
fractions.append(component["fraction"])
|
|
208
182
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
for comp_name in stream_def.get("z", {}):
|
|
221
|
-
if comp_name not in all_material_names:
|
|
222
|
-
raise ValueError(
|
|
223
|
-
f"❌ Stream '{stream_name}' z-key '{comp_name}' is not defined in materials."
|
|
224
|
-
)
|
|
183
|
+
# 2. friendly_material_id uniqueness
|
|
184
|
+
ids = [mat_def["friendly_material_id"] for mat_def in materials.values()]
|
|
185
|
+
if len(ids) != len(set(ids)):
|
|
186
|
+
seen, dupes = set(), set()
|
|
187
|
+
for i in ids:
|
|
188
|
+
if i in seen:
|
|
189
|
+
dupes.add(i)
|
|
190
|
+
seen.add(i)
|
|
191
|
+
raise ValueError(
|
|
192
|
+
f"❌ Duplicate friendly_material_id values found: {sorted(dupes)}"
|
|
193
|
+
)
|
|
225
194
|
|
|
226
|
-
|
|
195
|
+
# 3 & 4. Mix component name resolution and fraction sum
|
|
196
|
+
for mix_name, mix_def in material_mixes.items():
|
|
197
|
+
fractions = []
|
|
198
|
+
for component in mix_def.get("components", []):
|
|
199
|
+
comp_name = component["name"]
|
|
200
|
+
if comp_name not in all_material_names:
|
|
201
|
+
raise ValueError(
|
|
202
|
+
f"❌ material_mixes['{mix_name}'] references '{comp_name}', "
|
|
203
|
+
f"which is not defined in materials."
|
|
204
|
+
)
|
|
205
|
+
if "fraction" in component:
|
|
206
|
+
fractions.append(component["fraction"])
|
|
207
|
+
|
|
208
|
+
components = mix_def.get("components", [])
|
|
209
|
+
if len(fractions) == len(components) and fractions:
|
|
210
|
+
frac_sum = sum(fractions)
|
|
211
|
+
if abs(frac_sum - 1.0) > 1e-6:
|
|
212
|
+
raise ValueError(
|
|
213
|
+
f"❌ material_mixes['{mix_name}'] component fractions sum to "
|
|
214
|
+
f"{frac_sum:.8f}, expected 1.0."
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
# 5. Stream z-keys resolve to materials
|
|
218
|
+
for stream_name, stream_def in config.get("streams", {}).items():
|
|
219
|
+
for comp_name in stream_def.get("z", {}):
|
|
220
|
+
if comp_name not in all_material_names:
|
|
221
|
+
raise ValueError(
|
|
222
|
+
f"❌ Stream '{stream_name}' z-key '{comp_name}' is not defined in materials."
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# 6. Every unit must reference a valid friendly_material_id
|
|
226
|
+
hint = " (no materials section defined)" if not materials else ""
|
|
227
227
|
for unit_name, unit_def in config.get("units", {}).items():
|
|
228
228
|
mat_id = unit_def.get("material")
|
|
229
|
-
if mat_id
|
|
229
|
+
if mat_id not in valid_ids:
|
|
230
230
|
raise ValueError(
|
|
231
231
|
f"❌ Unit '{unit_name}' references material id {mat_id}, "
|
|
232
|
-
f"which does not match any friendly_material_id in materials."
|
|
232
|
+
f"which does not match any friendly_material_id in materials{hint}."
|
|
233
233
|
)
|
|
234
234
|
|
|
235
235
|
return True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|