processforge 0.2.30__tar.gz → 0.2.34__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.
Potentially problematic release.
This version of processforge might be problematic. Click here for more details.
- processforge-0.2.34/PKG-INFO +122 -0
- processforge-0.2.34/README.md +62 -0
- {processforge-0.2.30 → processforge-0.2.34}/flowsheets/closed-loop-chain.json +1 -1
- processforge-0.2.34/flowsheets/custom/simple_hyrdaulic_scheme.json +202 -0
- processforge-0.2.34/flowsheets/festim/hydrogen_transport_1d.json +70 -0
- {processforge-0.2.30 → processforge-0.2.34}/flowsheets/hydraulic-chain.json +1 -1
- {processforge-0.2.30 → processforge-0.2.34}/flowsheets/openmc/msre_eigenvalue.json +2 -1
- {processforge-0.2.30 → processforge-0.2.34}/pyproject.toml +6 -10
- processforge-0.2.34/src/processforge/compose.py +47 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/flowsheet.py +11 -47
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/jacobian.py +7 -4
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/solver.py +0 -1
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/flowsheet.py +149 -162
- processforge-0.2.34/src/processforge/lock.py +41 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/__init__.py +2 -1
- processforge-0.2.34/src/processforge/providers/festim_provider.py +411 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/manager.py +95 -50
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/openmc_provider.py +8 -1
- processforge-0.2.34/src/processforge/providers/registry.py +185 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/result.py +3 -5
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/schemas/flowsheet_schema.json +18 -6
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/schemas/openmc/openmc_model.py +2 -2
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/simulate.py +283 -20
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/state.py +19 -6
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/types.py +121 -1
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/__init__.py +3 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/cstr.py +5 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/flash.py +9 -6
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/heater.py +9 -5
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/pfr.py +4 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/pipes.py +4 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/pump.py +4 -0
- processforge-0.2.34/src/processforge/units/registry.py +24 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/solver_unit.py +4 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/strainer.py +4 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/tank.py +4 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/valve.py +4 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/utils/validate_flowsheet.py +158 -11
- processforge-0.2.34/src/processforge.egg-info/PKG-INFO +122 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge.egg-info/SOURCES.txt +11 -6
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge.egg-info/entry_points.txt +0 -1
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge.egg-info/requires.txt +4 -7
- processforge-0.2.34/tests/test_festim_provider.py +596 -0
- processforge-0.2.34/tests/test_init.py +256 -0
- processforge-0.2.34/tests/test_providers.py +318 -0
- processforge-0.2.34/tests/test_state.py +125 -0
- processforge-0.2.30/PKG-INFO +0 -615
- processforge-0.2.30/README.md +0 -553
- processforge-0.2.30/src/processforge/api/app.py +0 -87
- processforge-0.2.30/src/processforge/api/models.py +0 -83
- processforge-0.2.30/src/processforge/api/runner.py +0 -164
- processforge-0.2.30/src/processforge/api/serve.py +0 -41
- processforge-0.2.30/src/processforge/providers/registry.py +0 -52
- processforge-0.2.30/src/processforge/utils/__init__.py +0 -0
- processforge-0.2.30/src/processforge.egg-info/PKG-INFO +0 -615
- {processforge-0.2.30 → processforge-0.2.34}/LICENSE +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/MANIFEST.in +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/setup.cfg +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/__init__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/__main__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/_schema.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/analysis/__init__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/analysis/dof.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/__init__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/backends/__init__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/backends/base.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/backends/casadi_backend.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/backends/pyomo_backend.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/backends/scipy_backend.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/mixin.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/stream_var.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/units/__init__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/units/flash_eo.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/units/heater_eo.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/units/pipes_eo.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/units/pump_eo.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/units/strainer_eo.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/eo/units/valve_eo.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/fmu/__init__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/fmu/_fmi_vars.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/fmu/builder.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/fmu/slave_template.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/modelica/__init__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/modelica/mo_writer.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/modelica/omc_runner.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/modelica/transpiler.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/modelica/unit_equations.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/pcl/__init__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/pcl/compiler.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/pcl/namespace.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/provenance.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/base.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/base_jacobian_mixin.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/cantera_jacobian.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/cantera_provider.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/coolprop_provider.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/jacobian_contributor.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/modelica_jacobian.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/modelica_provider.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/providers/reference_state_registry.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/schemas/__init__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/solver.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/thermo.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/provider_mixin.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/units/solver.py +0 -0
- {processforge-0.2.30/src/processforge/api → processforge-0.2.34/src/processforge/utils}/__init__.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/utils/flowsheet_diagram.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/utils/mermaid_diagram.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/utils/topology.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/utils/unit_consistency.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge/utils/validation.py +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge.egg-info/dependency_links.txt +0 -0
- {processforge-0.2.30 → processforge-0.2.34}/src/processforge.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: processforge
|
|
3
|
+
Version: 0.2.34
|
|
4
|
+
Summary: A Python-based process simulation framework for chemical engineering applications.
|
|
5
|
+
Author-email: Processforge Team <team@processforge.dev>
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/urjanova/processforge
|
|
8
|
+
Project-URL: Repository, https://github.com/urjanova/processforge
|
|
9
|
+
Project-URL: Issues, https://github.com/urjanova/processforge/issues
|
|
10
|
+
Keywords: process,simulation,chemical,engineering,flowsheet
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: numpy>=2.0
|
|
23
|
+
Requires-Dist: pydantic>=2.0
|
|
24
|
+
Requires-Dist: scipy>=1.14
|
|
25
|
+
Requires-Dist: matplotlib>=3.9
|
|
26
|
+
Requires-Dist: loguru>=0.7
|
|
27
|
+
Requires-Dist: jsonschema>=4.20
|
|
28
|
+
Requires-Dist: graphviz>=0.20
|
|
29
|
+
Requires-Dist: pandas>=2.2
|
|
30
|
+
Requires-Dist: zarr>=3.0
|
|
31
|
+
Requires-Dist: coolprop>=7.2.0
|
|
32
|
+
Requires-Dist: pi>=0.1.2
|
|
33
|
+
Requires-Dist: pip>=26.1.2
|
|
34
|
+
Provides-Extra: eo
|
|
35
|
+
Requires-Dist: pyomo>=6.7; extra == "eo"
|
|
36
|
+
Provides-Extra: eo-casadi
|
|
37
|
+
Requires-Dist: pyomo>=6.7; extra == "eo-casadi"
|
|
38
|
+
Requires-Dist: casadi>=3.6; extra == "eo-casadi"
|
|
39
|
+
Provides-Extra: fmu
|
|
40
|
+
Requires-Dist: pythonfmu>=0.6; extra == "fmu"
|
|
41
|
+
Provides-Extra: modelica
|
|
42
|
+
Requires-Dist: OMPython>=4.0.0; extra == "modelica"
|
|
43
|
+
Requires-Dist: fmpy>=0.3; extra == "modelica"
|
|
44
|
+
Provides-Extra: cantera
|
|
45
|
+
Requires-Dist: cantera>=3.0; extra == "cantera"
|
|
46
|
+
Provides-Extra: coolprop
|
|
47
|
+
Requires-Dist: coolprop>=6.6; extra == "coolprop"
|
|
48
|
+
Provides-Extra: pcl
|
|
49
|
+
Requires-Dist: pint>=0.24; extra == "pcl"
|
|
50
|
+
Provides-Extra: dev
|
|
51
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
52
|
+
Requires-Dist: black; extra == "dev"
|
|
53
|
+
Requires-Dist: flake8; extra == "dev"
|
|
54
|
+
Requires-Dist: build; extra == "dev"
|
|
55
|
+
Requires-Dist: twine; extra == "dev"
|
|
56
|
+
Provides-Extra: docs
|
|
57
|
+
Requires-Dist: sphinx; extra == "docs"
|
|
58
|
+
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
59
|
+
Dynamic: license-file
|
|
60
|
+
|
|
61
|
+
# Processforge
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
65
|
+
A lightweight Python framework for process simulation, coupling hydraulic, thermal, and reactor workflows.
|
|
66
|
+
|
|
67
|
+
## Install
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
uv add processforge
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
For CoolProp-backed units:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
uv add "processforge[coolprop]"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Optional solver backends:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
uv add "processforge[eo]"
|
|
83
|
+
uv add "processforge[eo-casadi]"
|
|
84
|
+
uv add "processforge[modelica]"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Quick start
|
|
88
|
+
|
|
89
|
+
Use `plan` to validate and preview changes, then `apply` to solve and store a snapshot. For flowsheets without Tank units, use `apply` to solve with the EO solver.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pf init
|
|
93
|
+
pf plan flowsheets/hydraulic-chain.json
|
|
94
|
+
pf apply flowsheets/hydraulic-chain.json
|
|
95
|
+
```
|
|
96
|
+
For flowsheets with Tank units, use `run` to solve with the SM solver. For direct run mode (for dynamic flowsheets with Tank units), use `run`:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pf run flowsheets/hydraulic-chain.json
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Python API
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from processforge import EOFlowsheet, validate_flowsheet
|
|
106
|
+
config = validate_flowsheet("flowsheets/hydraulic-chain.json")
|
|
107
|
+
fs = EOFlowsheet(config, backend="scipy")
|
|
108
|
+
results = fs.run()
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Usage and Docker
|
|
112
|
+
Processforge is also available as Docker images, and can be run in the cloud. See the [usage guide](docs/usage.md) for CLI commands, workflows, Docker, and cloud notes.
|
|
113
|
+
|
|
114
|
+
## Flowsheets
|
|
115
|
+
The core of Processforge is the flowsheet JSON format, which defines materials, units, and recycle rules. See below for more information on the formats and example flowsheets.
|
|
116
|
+
- [docs/flowsheets.md](docs/flowsheets.md) : flowsheet JSON format, materials, units, and recycle rules
|
|
117
|
+
- [flowsheets/](flowsheets/) : example flowsheets shipped with the repo
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
BSD 3-Clause License
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Processforge
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
A lightweight Python framework for process simulation, coupling hydraulic, thermal, and reactor workflows.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uv add processforge
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
For CoolProp-backed units:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv add "processforge[coolprop]"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Optional solver backends:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv add "processforge[eo]"
|
|
23
|
+
uv add "processforge[eo-casadi]"
|
|
24
|
+
uv add "processforge[modelica]"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
Use `plan` to validate and preview changes, then `apply` to solve and store a snapshot. For flowsheets without Tank units, use `apply` to solve with the EO solver.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pf init
|
|
33
|
+
pf plan flowsheets/hydraulic-chain.json
|
|
34
|
+
pf apply flowsheets/hydraulic-chain.json
|
|
35
|
+
```
|
|
36
|
+
For flowsheets with Tank units, use `run` to solve with the SM solver. For direct run mode (for dynamic flowsheets with Tank units), use `run`:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pf run flowsheets/hydraulic-chain.json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Python API
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from processforge import EOFlowsheet, validate_flowsheet
|
|
46
|
+
config = validate_flowsheet("flowsheets/hydraulic-chain.json")
|
|
47
|
+
fs = EOFlowsheet(config, backend="scipy")
|
|
48
|
+
results = fs.run()
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage and Docker
|
|
52
|
+
Processforge is also available as Docker images, and can be run in the cloud. See the [usage guide](docs/usage.md) for CLI commands, workflows, Docker, and cloud notes.
|
|
53
|
+
|
|
54
|
+
## Flowsheets
|
|
55
|
+
The core of Processforge is the flowsheet JSON format, which defines materials, units, and recycle rules. See below for more information on the formats and example flowsheets.
|
|
56
|
+
- [docs/flowsheets.md](docs/flowsheets.md) : flowsheet JSON format, materials, units, and recycle rules
|
|
57
|
+
- [flowsheets/](flowsheets/) : example flowsheets shipped with the repo
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
BSD 3-Clause License
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
{
|
|
2
|
+
"metadata": {
|
|
3
|
+
"name": "Hydraulic Chain Example",
|
|
4
|
+
"description": "A two-pump, one-valve, one-strainer steady-state hydraulic system.",
|
|
5
|
+
"version": "2.0"
|
|
6
|
+
},
|
|
7
|
+
"providers": {
|
|
8
|
+
"coolprop": {
|
|
9
|
+
"type": "coolprop"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"materials": {
|
|
13
|
+
"Benzene": {
|
|
14
|
+
"id": 1
|
|
15
|
+
},
|
|
16
|
+
"Toluene": {
|
|
17
|
+
"id": 2
|
|
18
|
+
},
|
|
19
|
+
"Steel": {
|
|
20
|
+
"id": 3
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"material_mixes": {
|
|
24
|
+
"Benzene_Toluene_Mix": {
|
|
25
|
+
"friendly_material_mix_id": 1,
|
|
26
|
+
"percent_type": "ao",
|
|
27
|
+
"components": [
|
|
28
|
+
{"name": "Benzene", "fraction": 0.8},
|
|
29
|
+
{"name": "Toluene", "fraction": 0.2}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"streams": {
|
|
34
|
+
"feed": {
|
|
35
|
+
"T": 298.15,
|
|
36
|
+
"P": 101325,
|
|
37
|
+
"flowrate": 38,
|
|
38
|
+
"material_mix": 1
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"units": {
|
|
42
|
+
"pipe_1": {
|
|
43
|
+
"type": "Pipes",
|
|
44
|
+
"in": "feed",
|
|
45
|
+
"out": "after_pipe_1",
|
|
46
|
+
"delta_p": 1000.0,
|
|
47
|
+
"diameter": 0.040,
|
|
48
|
+
"material": 3
|
|
49
|
+
},
|
|
50
|
+
"valve_1": {
|
|
51
|
+
"type": "Valve",
|
|
52
|
+
"in": "after_pipe_1",
|
|
53
|
+
"out": "after_valve_1",
|
|
54
|
+
"pressure_ratio": 0.5,
|
|
55
|
+
"material": 3
|
|
56
|
+
},
|
|
57
|
+
"pipe_2": {
|
|
58
|
+
"type": "Pipes",
|
|
59
|
+
"in": "after_valve_1",
|
|
60
|
+
"out": "after_pipe_2",
|
|
61
|
+
"delta_p": 1000.0,
|
|
62
|
+
"diameter": 0.08,
|
|
63
|
+
"material": 3
|
|
64
|
+
},
|
|
65
|
+
"pump_1": {
|
|
66
|
+
"type": "Pump",
|
|
67
|
+
"in": "after_pipe_2",
|
|
68
|
+
"out": "after_pump_1",
|
|
69
|
+
"deltaP": 600000.0,
|
|
70
|
+
"efficiency": 0.75,
|
|
71
|
+
"material": 3
|
|
72
|
+
},
|
|
73
|
+
"pipe_3": {
|
|
74
|
+
"type": "Pipes",
|
|
75
|
+
"in": "after_pump_1",
|
|
76
|
+
"out": "after_pipe_3",
|
|
77
|
+
"delta_p": 1000.0,
|
|
78
|
+
"diameter": 0.08,
|
|
79
|
+
"material": 3
|
|
80
|
+
},
|
|
81
|
+
"strainer_1": {
|
|
82
|
+
"type": "Strainer",
|
|
83
|
+
"in": "after_pipe_3",
|
|
84
|
+
"out": "after_strainer_1",
|
|
85
|
+
"deltaP": 5000.0,
|
|
86
|
+
"material": 3
|
|
87
|
+
},
|
|
88
|
+
"pipe_4": {
|
|
89
|
+
"type": "Pipes",
|
|
90
|
+
"in": "after_strainer_1",
|
|
91
|
+
"out": "after_pipe_4",
|
|
92
|
+
"delta_p": 1000.0,
|
|
93
|
+
"diameter": 0.08,
|
|
94
|
+
"material": 3
|
|
95
|
+
},
|
|
96
|
+
"pipe_1a": {
|
|
97
|
+
"type": "Pipes",
|
|
98
|
+
"in": "after_strainer_1",
|
|
99
|
+
"out": "after_pipe_1a",
|
|
100
|
+
"delta_p": 1000.0,
|
|
101
|
+
"diameter": 0.08,
|
|
102
|
+
"material": 3
|
|
103
|
+
},
|
|
104
|
+
"valve_1a": {
|
|
105
|
+
"type": "Valve",
|
|
106
|
+
"in": "after_pipe_1a",
|
|
107
|
+
"out": "after_valve_1a",
|
|
108
|
+
"pressure_ratio": 0.5,
|
|
109
|
+
"material": 3
|
|
110
|
+
},
|
|
111
|
+
"pipe_2a": {
|
|
112
|
+
"type": "Pipes",
|
|
113
|
+
"in": "after_valve_1a",
|
|
114
|
+
"out": "after_pipe_2a",
|
|
115
|
+
"delta_p": 1000.0,
|
|
116
|
+
"diameter": 0.08,
|
|
117
|
+
"material": 3
|
|
118
|
+
},
|
|
119
|
+
"valve_2": {
|
|
120
|
+
"type": "Valve",
|
|
121
|
+
"in": "after_pipe_4",
|
|
122
|
+
"out": "after_valve_2",
|
|
123
|
+
"pressure_ratio": 0.5,
|
|
124
|
+
"material": 3
|
|
125
|
+
},
|
|
126
|
+
"pipe_5": {
|
|
127
|
+
"type": "Pipes",
|
|
128
|
+
"in": "after_valve_2",
|
|
129
|
+
"out": "after_pipe_5",
|
|
130
|
+
"delta_p": 1000.0,
|
|
131
|
+
"diameter": 0.08,
|
|
132
|
+
"material": 3
|
|
133
|
+
},
|
|
134
|
+
"pump_2": {
|
|
135
|
+
"type": "Pump",
|
|
136
|
+
"in": "after_pipe_5",
|
|
137
|
+
"out": "after_pump_2",
|
|
138
|
+
"deltaP": 600000.0,
|
|
139
|
+
"efficiency": 0.75,
|
|
140
|
+
"material": 3
|
|
141
|
+
},
|
|
142
|
+
"pipe_6": {
|
|
143
|
+
"type": "Pipes",
|
|
144
|
+
"in": "after_pump_2",
|
|
145
|
+
"out": "after_pipe_6",
|
|
146
|
+
"delta_p": 1000.0,
|
|
147
|
+
"diameter": 0.08,
|
|
148
|
+
"material": 3
|
|
149
|
+
},
|
|
150
|
+
"valve_3": {
|
|
151
|
+
"type": "Valve",
|
|
152
|
+
"in": "after_pipe_6",
|
|
153
|
+
"out": "after_valve_3",
|
|
154
|
+
"pressure_ratio": 0.5,
|
|
155
|
+
"material": 3
|
|
156
|
+
},
|
|
157
|
+
"pipe_7": {
|
|
158
|
+
"type": "Pipes",
|
|
159
|
+
"in": "after_valve_3",
|
|
160
|
+
"out": "after_pipe_7",
|
|
161
|
+
"delta_p": 1000.0,
|
|
162
|
+
"diameter": 0.08,
|
|
163
|
+
"material": 3
|
|
164
|
+
},
|
|
165
|
+
"valve_4": {
|
|
166
|
+
"type": "Valve",
|
|
167
|
+
"in": "after_pipe_7",
|
|
168
|
+
"out": "after_valve_4",
|
|
169
|
+
"pressure_ratio": 0.5,
|
|
170
|
+
"material": 3
|
|
171
|
+
},
|
|
172
|
+
"pipe_8": {
|
|
173
|
+
"type": "Pipes",
|
|
174
|
+
"in": "after_valve_4",
|
|
175
|
+
"out": "after_pipe_8",
|
|
176
|
+
"delta_p": 1000.0,
|
|
177
|
+
"diameter": 0.08,
|
|
178
|
+
"material": 3
|
|
179
|
+
},
|
|
180
|
+
"valve_5": {
|
|
181
|
+
"type": "Valve",
|
|
182
|
+
"in": ["after_pipe_8","after_pipe_2a"],
|
|
183
|
+
"out": "after_valve_5",
|
|
184
|
+
"pressure_ratio": 0.5,
|
|
185
|
+
"material": 3
|
|
186
|
+
},
|
|
187
|
+
"pipe_9": {
|
|
188
|
+
"type": "Pipes",
|
|
189
|
+
"in": "after_valve_5",
|
|
190
|
+
"out": "after_pipe_9",
|
|
191
|
+
"delta_p": 1000.0,
|
|
192
|
+
"diameter": 0.025,
|
|
193
|
+
"material": 3
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
},
|
|
197
|
+
"simulation": {
|
|
198
|
+
"mode":"dynamic",
|
|
199
|
+
"t_final": 20,
|
|
200
|
+
"t_step": 1
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"metadata": {
|
|
3
|
+
"name": "FESTIM Hydrogen Transport — 1D Diffusion",
|
|
4
|
+
"description": "Simple 1D hydrogen diffusion through a slab. Fixed concentration BCs: c=1 on left, c=0 on right. D_0=1 m²/s, E_D=0 eV, T=300 K.",
|
|
5
|
+
"version": "1.0"
|
|
6
|
+
},
|
|
7
|
+
"providers": {
|
|
8
|
+
"festim": {
|
|
9
|
+
"type": "festim",
|
|
10
|
+
"url": "http://localhost:9002",
|
|
11
|
+
"output_dir": "festim"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"materials": {
|
|
15
|
+
"default": {
|
|
16
|
+
"id": 1,
|
|
17
|
+
"extra": {
|
|
18
|
+
"D_0": 1,
|
|
19
|
+
"E_D": 0.0
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"streams": {},
|
|
24
|
+
"units": {
|
|
25
|
+
"festim_solver": {
|
|
26
|
+
"type": "SolverUnit",
|
|
27
|
+
"provider": "festim",
|
|
28
|
+
"sim_type": "hydrogen_transport",
|
|
29
|
+
"mesh": {
|
|
30
|
+
"vertices": [0.0, 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01]
|
|
31
|
+
},
|
|
32
|
+
"species": [
|
|
33
|
+
{ "name": "H" }
|
|
34
|
+
],
|
|
35
|
+
"subdomains": {
|
|
36
|
+
"volume": [
|
|
37
|
+
{ "id": 1, "borders": [0.0, 0.01], "material": "default" }
|
|
38
|
+
],
|
|
39
|
+
"surface": [
|
|
40
|
+
{ "id": 2, "x": 0.0 },
|
|
41
|
+
{ "id": 3, "x": 0.01 }
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"boundary_conditions": [
|
|
45
|
+
{ "type": "fixed_concentration", "subdomain_id": 2, "species": "H", "value": 1 },
|
|
46
|
+
{ "type": "fixed_concentration", "subdomain_id": 3, "species": "H", "value": 0 }
|
|
47
|
+
],
|
|
48
|
+
"exports": [
|
|
49
|
+
{ "type": "vtx_species", "field": "H", "filename": "hydrogen_concentration.bp", "times": "milestones" },
|
|
50
|
+
{ "type": "profile_1d", "field": "H", "volume_id": 1, "times": "milestones" }
|
|
51
|
+
],
|
|
52
|
+
"solver_config": {
|
|
53
|
+
"atol": 1e-10,
|
|
54
|
+
"rtol": 1e-10,
|
|
55
|
+
"final_time": 2,
|
|
56
|
+
"temperature": 300,
|
|
57
|
+
"stepsize": {
|
|
58
|
+
"initial_value": 0.05,
|
|
59
|
+
"growth_factor": 1.1,
|
|
60
|
+
"cutback_factor": 0.9,
|
|
61
|
+
"target_nb_iterations": 4,
|
|
62
|
+
"milestones": [0.05, 0.1, 0.2, 0.5, 1]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"simulation": {
|
|
68
|
+
"mode": "steady"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "processforge"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.34"
|
|
8
8
|
description = "A Python-based process simulation framework for chemical engineering applications."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "BSD-3-Clause"
|
|
11
11
|
license-files = ["LICENSE"]
|
|
12
12
|
requires-python = ">=3.12"
|
|
13
13
|
authors = [
|
|
14
|
-
{name = "
|
|
14
|
+
{name = "Processforge Team", email = "team@processforge.dev"},
|
|
15
15
|
]
|
|
16
16
|
classifiers = [
|
|
17
17
|
"Development Status :: 3 - Alpha",
|
|
@@ -26,6 +26,7 @@ classifiers = [
|
|
|
26
26
|
keywords = ["process", "simulation", "chemical", "engineering", "flowsheet"]
|
|
27
27
|
dependencies = [
|
|
28
28
|
"numpy>=2.0",
|
|
29
|
+
"pydantic>=2.0",
|
|
29
30
|
"scipy>=1.14",
|
|
30
31
|
"matplotlib>=3.9",
|
|
31
32
|
"loguru>=0.7",
|
|
@@ -33,16 +34,12 @@ dependencies = [
|
|
|
33
34
|
"graphviz>=0.20",
|
|
34
35
|
"pandas>=2.2",
|
|
35
36
|
"zarr>=3.0",
|
|
37
|
+
"coolprop>=7.2.0",
|
|
38
|
+
"pi>=0.1.2",
|
|
39
|
+
"pip>=26.1.2",
|
|
36
40
|
]
|
|
37
41
|
|
|
38
42
|
[project.optional-dependencies]
|
|
39
|
-
api = [
|
|
40
|
-
"fastapi>=0.110",
|
|
41
|
-
"uvicorn[standard]>=0.29",
|
|
42
|
-
"boto3>=1.34",
|
|
43
|
-
"s3fs>=2024.3",
|
|
44
|
-
"pydantic>=2.0",
|
|
45
|
-
]
|
|
46
43
|
eo = [
|
|
47
44
|
"pyomo>=6.7",
|
|
48
45
|
]
|
|
@@ -86,7 +83,6 @@ Issues = "https://github.com/urjanova/processforge/issues"
|
|
|
86
83
|
[project.scripts]
|
|
87
84
|
processforge = "processforge.simulate:main"
|
|
88
85
|
pf = "processforge.simulate:main"
|
|
89
|
-
pf-serve = "processforge.api.serve:main"
|
|
90
86
|
|
|
91
87
|
[tool.setuptools.packages.find]
|
|
92
88
|
where = ["src"]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Generate docker-compose.yml for containerized providers."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
COMPOSE_FILENAME = "docker-compose.yml"
|
|
7
|
+
COMPOSE_HEADER = (
|
|
8
|
+
"# Auto-generated by pf init — do not edit manually.\n"
|
|
9
|
+
"# Re-generate: pf init <flowsheet.json>\n"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _compose_path(pf_dir: str) -> str:
|
|
14
|
+
return os.path.join(pf_dir, COMPOSE_FILENAME)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def generate_compose(
|
|
18
|
+
pf_dir: str,
|
|
19
|
+
containerized_providers: dict[str, dict],
|
|
20
|
+
outputs_dir: str = "outputs",
|
|
21
|
+
) -> None:
|
|
22
|
+
"""Generate docker-compose.yml for providers that need Docker.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
pf_dir: Path to .processforge/ directory.
|
|
26
|
+
containerized_providers: Dict of provider_name -> {"url": ..., "docker_image": ..., "port": ...}.
|
|
27
|
+
outputs_dir: Host directory to mount as /data in containers.
|
|
28
|
+
"""
|
|
29
|
+
if not containerized_providers:
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
lines = [COMPOSE_HEADER, "services:"]
|
|
33
|
+
for name, info in containerized_providers.items():
|
|
34
|
+
image = info["docker_image"]
|
|
35
|
+
port = info.get("port") or 9000
|
|
36
|
+
lines.append(f" {name}:")
|
|
37
|
+
lines.append(f" image: {image}")
|
|
38
|
+
lines.append(f" ports:")
|
|
39
|
+
lines.append(f' - "{port}:{port}"')
|
|
40
|
+
lines.append(f" volumes:")
|
|
41
|
+
lines.append(f' - "${{PROCESSFORGE_OUTPUT_DIR:-{outputs_dir}}}:/data"')
|
|
42
|
+
lines.append("")
|
|
43
|
+
|
|
44
|
+
os.makedirs(pf_dir, exist_ok=True)
|
|
45
|
+
path = _compose_path(pf_dir)
|
|
46
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
47
|
+
f.write("\n".join(lines))
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
from copy import deepcopy
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
import numpy as np
|
|
7
8
|
from loguru import logger
|
|
8
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from ..providers.manager import ProviderMap
|
|
12
|
+
|
|
9
13
|
from .jacobian import GlobalJacobianManager
|
|
10
14
|
from .solver import EOSolver
|
|
11
15
|
from ..types import SnapshotState
|
|
@@ -43,7 +47,7 @@ class EOFlowsheet:
|
|
|
43
47
|
or sim_cfg.get("default_backend", "scipy")
|
|
44
48
|
)
|
|
45
49
|
self._unit_objects: dict = {}
|
|
46
|
-
self._provider_map:
|
|
50
|
+
self._provider_map: ProviderMap | None = None
|
|
47
51
|
self.solver_tol: float = 1e-6
|
|
48
52
|
self.solver_max_iter: int = 50
|
|
49
53
|
|
|
@@ -141,55 +145,15 @@ class EOFlowsheet:
|
|
|
141
145
|
|
|
142
146
|
return manager
|
|
143
147
|
|
|
144
|
-
def _build_units(self, provider_map:
|
|
145
|
-
"""Instantiate unit objects using the
|
|
146
|
-
from
|
|
147
|
-
|
|
148
|
-
from processforge.units.strainer import Strainer
|
|
149
|
-
from processforge.units.pipes import Pipes
|
|
150
|
-
from processforge.units.heater import Heater
|
|
151
|
-
from processforge.units.flash import Flash
|
|
152
|
-
from processforge.units.solver_unit import SolverUnit
|
|
153
|
-
|
|
154
|
-
unit_types = {
|
|
155
|
-
"Pump": (Pump, "kwargs"),
|
|
156
|
-
"Valve": (Valve, "kwargs"),
|
|
157
|
-
"Strainer": (Strainer, "kwargs"),
|
|
158
|
-
"Pipes": (Pipes, "kwargs"),
|
|
159
|
-
"Heater": (Heater, "params"),
|
|
160
|
-
"Flash": (Flash, "params"),
|
|
161
|
-
"SolverUnit": (SolverUnit, "kwargs"),
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
from processforge.providers.manager import get_unit_provider
|
|
165
|
-
_pm = provider_map or {}
|
|
148
|
+
def _build_units(self, provider_map: ProviderMap | None = None) -> dict:
|
|
149
|
+
"""Instantiate unit objects using the shared registry."""
|
|
150
|
+
from ..flowsheet import _build_unit, _merge_provider_types
|
|
151
|
+
_merge_provider_types(provider_map)
|
|
166
152
|
|
|
167
153
|
units = {}
|
|
168
154
|
for unit_name, unit_cfg in self.config["units"].items():
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
raise ValueError(f"Unknown unit type '{unit_type}'.")
|
|
172
|
-
cls, style = unit_types[unit_type]
|
|
173
|
-
|
|
174
|
-
exclude = {"type", "in", "out", "provider"}
|
|
175
|
-
if unit_type == "Flash":
|
|
176
|
-
# Flash uses out_vap / out_liq — exclude both from kwargs
|
|
177
|
-
exclude |= {"out_vap", "out_liq"}
|
|
178
|
-
|
|
179
|
-
params = {k: v for k, v in unit_cfg.items() if k not in exclude}
|
|
180
|
-
if style == "params":
|
|
181
|
-
# Heater / Flash use __init__(name, params_dict)
|
|
182
|
-
unit = cls(unit_name, params)
|
|
183
|
-
else:
|
|
184
|
-
unit = cls(unit_name, **params)
|
|
185
|
-
|
|
186
|
-
# Attach provider so EO residuals can route thermo calls.
|
|
187
|
-
if _pm:
|
|
188
|
-
unit._provider = get_unit_provider(_pm, unit_cfg)
|
|
189
|
-
|
|
190
|
-
units[unit_name] = unit
|
|
191
|
-
logger.info(f"Built unit '{unit_name}' ({unit_type})")
|
|
192
|
-
|
|
155
|
+
units[unit_name] = _build_unit(unit_name, unit_cfg, provider_map)
|
|
156
|
+
logger.info(f"Built unit '{unit_name}' ({unit_cfg['type']})")
|
|
193
157
|
return units
|
|
194
158
|
|
|
195
159
|
def _check_provider_backend_compat(self) -> None:
|