pydac3 3.0.0__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.
Files changed (188) hide show
  1. pydac/__init__.py +59 -0
  2. pydac/_kit/CITATION.cff +29 -0
  3. pydac/_kit/LICENSE +21 -0
  4. pydac/_kit/README.md +262 -0
  5. pydac/_kit/docs/guide/01_installation.md +244 -0
  6. pydac/_kit/docs/guide/02_quickstart.md +255 -0
  7. pydac/_kit/docs/guide/03_cases.md +287 -0
  8. pydac/_kit/docs/guide/04_running.md +311 -0
  9. pydac/_kit/docs/guide/05_optimization.md +306 -0
  10. pydac/_kit/docs/guide/06_results.md +287 -0
  11. pydac/_kit/docs/guide/07_reproducibility.md +133 -0
  12. pydac/_kit/docs/guide/08_extending.md +231 -0
  13. pydac/_kit/examples/README.md +117 -0
  14. pydac/_kit/examples/cases/01_first_steps.json +16 -0
  15. pydac/_kit/examples/cases/02_custom_case.json +86 -0
  16. pydac/_kit/examples/cases/03_css_tvsa.json +16 -0
  17. pydac/_kit/examples/cases/04_1d_vs_2d.json +18 -0
  18. pydac/_kit/examples/cases/05_nsga2_bounds.json +8 -0
  19. pydac/_kit/examples/cases/05_nsga2_trial.json +15 -0
  20. pydac/_kit/examples/cases/06_breakthrough_validation.json +120 -0
  21. pydac/_kit/examples/cases/07_apdes_nfc_sorbent.json +34 -0
  22. pydac/_kit/examples/cases/07_new_isotherm.json +18 -0
  23. pydac/_kit/examples/cases/quick_1D.json +33 -0
  24. pydac/_kit/examples/data/zanco2022_13x/README.md +51 -0
  25. pydac/_kit/examples/data/zanco2022_13x/center.csv +902 -0
  26. pydac/_kit/examples/data/zanco2022_13x/co2.csv +595 -0
  27. pydac/_kit/examples/data/zanco2022_13x/half_radius.csv +902 -0
  28. pydac/_kit/examples/data/zanco2022_13x/wall.csv +902 -0
  29. pydac/_kit/examples/notebooks/01_first_steps.ipynb +895 -0
  30. pydac/_kit/examples/notebooks/02_custom_case.ipynb +3347 -0
  31. pydac/_kit/examples/notebooks/03_css_tvsa.ipynb +6480 -0
  32. pydac/_kit/examples/notebooks/04_1d_vs_2d.ipynb +959 -0
  33. pydac/_kit/examples/notebooks/05_nsga2_trial.ipynb +1890 -0
  34. pydac/_kit/examples/notebooks/06_breakthrough_validation.ipynb +673 -0
  35. pydac/_kit/examples/notebooks/07_new_isotherm.ipynb +860 -0
  36. pydac/api.py +1022 -0
  37. pydac/cli.py +596 -0
  38. pydac/config/__init__.py +116 -0
  39. pydac/config/bed_profiles.py +32 -0
  40. pydac/config/cli.py +138 -0
  41. pydac/config/contract.py +147 -0
  42. pydac/config/cycle.py +255 -0
  43. pydac/config/derivations.py +138 -0
  44. pydac/config/errors.py +36 -0
  45. pydac/config/execution.py +19 -0
  46. pydac/config/input_help.py +138 -0
  47. pydac/config/json_schema/experiment.schema.json +1019 -0
  48. pydac/config/launch.py +37 -0
  49. pydac/config/loader.py +593 -0
  50. pydac/config/migrations.py +554 -0
  51. pydac/config/model_validation.py +200 -0
  52. pydac/config/nulls.py +103 -0
  53. pydac/config/operating.py +127 -0
  54. pydac/config/profile.py +78 -0
  55. pydac/config/schema.py +448 -0
  56. pydac/config/schema_generation.py +173 -0
  57. pydac/config/sections.py +178 -0
  58. pydac/config/serialization.py +58 -0
  59. pydac/config/settings.py +156 -0
  60. pydac/config/steps.py +265 -0
  61. pydac/config/terminal.py +216 -0
  62. pydac/config/validation.py +113 -0
  63. pydac/core/TVSA_cycle.py +558 -0
  64. pydac/core/__init__.py +1 -0
  65. pydac/core/bed_architectures/__init__.py +197 -0
  66. pydac/core/bed_architectures/base.py +886 -0
  67. pydac/core/bed_architectures/channeling.py +683 -0
  68. pydac/core/bed_architectures/packed_bed.py +879 -0
  69. pydac/core/column_model.py +2976 -0
  70. pydac/core/column_model_factory.py +118 -0
  71. pydac/core/column_model_input.py +82 -0
  72. pydac/core/isotherm_models.py +942 -0
  73. pydac/core/kinetic_models.py +155 -0
  74. pydac/core/outlet_reporting.py +58 -0
  75. pydac/core/pymrm_caching.py +487 -0
  76. pydac/core/solver.py +742 -0
  77. pydac/core/sparsity_patterns/__init__.py +1 -0
  78. pydac/core/sparsity_patterns/analytical_sparsity.py +293 -0
  79. pydac/core/sparsity_patterns/numerical_sparsity.py +132 -0
  80. pydac/core/species_catalog.py +206 -0
  81. pydac/core/state_layout.py +530 -0
  82. pydac/core/ternary_thermodynamics_separators.py +140 -0
  83. pydac/core/thermodynamics_separators.py +120 -0
  84. pydac/extensions.py +60 -0
  85. pydac/inputs/__init__.py +1 -0
  86. pydac/inputs/case_io.py +378 -0
  87. pydac/inputs/case_terminal.py +91 -0
  88. pydac/inputs/defaults/__init__.py +28 -0
  89. pydac/inputs/defaults/_rules.py +97 -0
  90. pydac/inputs/defaults/adsorption.py +87 -0
  91. pydac/inputs/defaults/column.py +138 -0
  92. pydac/inputs/defaults/execution.py +162 -0
  93. pydac/inputs/defaults/mixture.py +54 -0
  94. pydac/inputs/defaults/particle.py +116 -0
  95. pydac/inputs/defaults/profile.py +57 -0
  96. pydac/inputs/defaults/reference.py +31 -0
  97. pydac/inputs/defaults/solver.py +50 -0
  98. pydac/inputs/defaults/steps.py +684 -0
  99. pydac/post_processing/__init__.py +1 -0
  100. pydac/post_processing/context/__init__.py +1 -0
  101. pydac/post_processing/context/runtime_store.py +56 -0
  102. pydac/post_processing/context/simulation_context.py +192 -0
  103. pydac/post_processing/context/store.py +67 -0
  104. pydac/post_processing/kpi/__init__.py +1 -0
  105. pydac/post_processing/kpi/cycle_kpis.py +1229 -0
  106. pydac/post_processing/kpi/plotting.py +1160 -0
  107. pydac/post_processing/kpi/reporting.py +962 -0
  108. pydac/post_processing/metrics/__init__.py +1 -0
  109. pydac/post_processing/metrics/cycle_data.py +24 -0
  110. pydac/post_processing/metrics/cycle_data_loader.py +265 -0
  111. pydac/post_processing/metrics/cycle_metrics.py +303 -0
  112. pydac/post_processing/metrics/step_metrics.py +304 -0
  113. pydac/post_processing/metrics/step_metrics_store.py +121 -0
  114. pydac/post_processing/optimization/__init__.py +1 -0
  115. pydac/post_processing/optimization/nsga2_post_processing.py +607 -0
  116. pydac/post_processing/profiles/__init__.py +1 -0
  117. pydac/post_processing/profiles/cyclic_plotting.py +929 -0
  118. pydac/post_processing/profiles/step_plotting.py +1757 -0
  119. pydac/post_processing/profiles/step_post_processing.py +1722 -0
  120. pydac/starter_kit.py +115 -0
  121. pydac/utils/__init__.py +12 -0
  122. pydac/utils/aspect_ratios.py +56 -0
  123. pydac/utils/campaign.py +21 -0
  124. pydac/utils/column/__init__.py +40 -0
  125. pydac/utils/column/runtime_properties.py +147 -0
  126. pydac/utils/column/validation.py +313 -0
  127. pydac/utils/css/__init__.py +43 -0
  128. pydac/utils/css/cycle.py +533 -0
  129. pydac/utils/css/plotting.py +71 -0
  130. pydac/utils/css/profiles.py +140 -0
  131. pydac/utils/css/pruning.py +26 -0
  132. pydac/utils/css/runner.py +273 -0
  133. pydac/utils/flow_transforms.py +188 -0
  134. pydac/utils/logger.py +76 -0
  135. pydac/utils/model_registry.py +395 -0
  136. pydac/utils/nsga2/__init__.py +13 -0
  137. pydac/utils/nsga2/artifacts.py +73 -0
  138. pydac/utils/nsga2/checkpoint.py +621 -0
  139. pydac/utils/nsga2/decisions.py +121 -0
  140. pydac/utils/nsga2/evaluation.py +234 -0
  141. pydac/utils/nsga2/logging.py +660 -0
  142. pydac/utils/nsga2/warm_start.py +316 -0
  143. pydac/utils/plot_helpers.py +126 -0
  144. pydac/utils/postprocessing/__init__.py +1 -0
  145. pydac/utils/postprocessing/context_model.py +215 -0
  146. pydac/utils/postprocessing/context_schema.py +452 -0
  147. pydac/utils/postprocessing/cyclic_profiles.py +204 -0
  148. pydac/utils/postprocessing/normalization.py +138 -0
  149. pydac/utils/postprocessing/outlet.py +47 -0
  150. pydac/utils/postprocessing/runtime_report.py +696 -0
  151. pydac/utils/postprocessing/saved_solution.py +171 -0
  152. pydac/utils/postprocessing/terminal_state.py +230 -0
  153. pydac/utils/provenance.py +345 -0
  154. pydac/utils/run/__init__.py +35 -0
  155. pydac/utils/run/config.py +167 -0
  156. pydac/utils/run/resume.py +272 -0
  157. pydac/utils/run/steps.py +124 -0
  158. pydac/utils/run/validation.py +263 -0
  159. pydac/utils/solver/__init__.py +155 -0
  160. pydac/utils/solver/composition_domain.py +138 -0
  161. pydac/utils/solver/event_config.py +101 -0
  162. pydac/utils/solver/events.py +390 -0
  163. pydac/utils/solver/flags.py +26 -0
  164. pydac/utils/solver/jacobian.py +28 -0
  165. pydac/utils/solver/outcome.py +149 -0
  166. pydac/utils/solver/oxygen_hot_bed_audit.py +511 -0
  167. pydac/utils/solver/persistence.py +31 -0
  168. pydac/utils/solver/pressure_plateau.py +128 -0
  169. pydac/utils/solver/reporting.py +83 -0
  170. pydac/utils/solver/sparsity.py +211 -0
  171. pydac/utils/solver/species_balance.py +197 -0
  172. pydac/utils/tvsa/__init__.py +77 -0
  173. pydac/utils/tvsa/cycle_steps.py +58 -0
  174. pydac/utils/tvsa/paths.py +87 -0
  175. pydac/utils/tvsa/reporting.py +114 -0
  176. pydac/utils/tvsa/steps.py +163 -0
  177. pydac/utils/tvsa/termination.py +186 -0
  178. pydac/utils/vector_drag.py +48 -0
  179. pydac/utils/version.py +7 -0
  180. pydac/workflows/__init__.py +1 -0
  181. pydac/workflows/orchestrator_NSGA2.py +1532 -0
  182. pydac/workflows/orchestrator_TVSA_cycle_css.py +409 -0
  183. pydac/workflows/orchestrator_TVSA_steps.py +119 -0
  184. pydac3-3.0.0.dist-info/METADATA +298 -0
  185. pydac3-3.0.0.dist-info/RECORD +188 -0
  186. pydac3-3.0.0.dist-info/WHEEL +4 -0
  187. pydac3-3.0.0.dist-info/entry_points.txt +2 -0
  188. pydac3-3.0.0.dist-info/licenses/LICENSE +21 -0
pydac/__init__.py ADDED
@@ -0,0 +1,59 @@
1
+ """pyDAC: simulation of adsorption-based direct air capture processes.
2
+
3
+ The supported Python API (the same layer the ``pydac`` command uses)::
4
+
5
+ import pydac
6
+
7
+ case = pydac.load_case("my_case.json", settings={"execution.max_cycles": 30})
8
+ result = pydac.run_css(case) # RunResult: folder, css_reached, cycle, ...
9
+ pydac.report(result.folder, fmt="png")
10
+ kpis = pydac.CycleKPIs(pydac.CycleDataLoader(result.folder).load())
11
+
12
+ Names are imported on first use, so ``import pydac`` stays light: numpy,
13
+ matplotlib and pymoo load only when a name that needs them is used.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import importlib
19
+
20
+ from pydac.utils.version import __version__
21
+
22
+ _EXPORTS = {
23
+ "load_case": "pydac.api",
24
+ "export_case": "pydac.api",
25
+ "export_settings": "pydac.api",
26
+ "run_steps": "pydac.api",
27
+ "run_css": "pydac.api",
28
+ "run_nsga2": "pydac.api",
29
+ "resume": "pydac.api",
30
+ "report": "pydac.api",
31
+ "RunResult": "pydac.api",
32
+ "ConfigurationError": "pydac.config.errors",
33
+ "RunRefused": "pydac.config.errors",
34
+ "ExperimentConfig": "pydac.config.schema",
35
+ "CycleDataLoader": "pydac.post_processing.metrics.cycle_data_loader",
36
+ "CycleKPIs": "pydac.post_processing.kpi.cycle_kpis",
37
+ "register_equilibrium": "pydac.extensions",
38
+ "register_kinetics": "pydac.extensions",
39
+ "get_started": "pydac.starter_kit",
40
+ "EquilibriumSystem": "pydac.core.isotherm_models",
41
+ "KineticLaw": "pydac.core.kinetic_models",
42
+ "EquilibriumRegistryEntry": "pydac.utils.model_registry",
43
+ "KineticRegistryEntry": "pydac.utils.model_registry",
44
+ }
45
+
46
+ __all__ = ["__version__", *_EXPORTS]
47
+
48
+
49
+ def __getattr__(name: str):
50
+ module = _EXPORTS.get(name)
51
+ if module is None:
52
+ raise AttributeError(f"module 'pydac' has no attribute {name!r}")
53
+ value = getattr(importlib.import_module(module), name)
54
+ globals()[name] = value
55
+ return value
56
+
57
+
58
+ def __dir__():
59
+ return sorted(set(globals()) | set(_EXPORTS))
@@ -0,0 +1,29 @@
1
+ # Citation metadata. At each GitHub release Zenodo adds the DOI and the release date;
2
+ # the paper becomes `preferred-citation` once it is published.
3
+ cff-version: 1.2.0
4
+ message: "If you use pyDAC in your research, please cite it as below."
5
+ title: "pyDAC: simulation of adsorption-based direct air capture processes"
6
+ type: software
7
+ authors:
8
+ - given-names: Mattia
9
+ family-names: Galanti
10
+ - given-names: Ivo
11
+ family-names: Roghair
12
+ - given-names: Martin
13
+ name-particle: van
14
+ family-names: Sint Annaland
15
+ license: MIT
16
+ version: 3.0.0
17
+ repository-code: "https://github.com/process-intensification-lab/pyDAC"
18
+ keywords:
19
+ - direct air capture
20
+ - adsorption
21
+ - TVSA
22
+ - cyclic adsorption
23
+ - packed bed
24
+ - process simulation
25
+ abstract: >-
26
+ pyDAC simulates adsorption cycles composed from configurable steps (by default a
27
+ steam-assisted temperature-vacuum swing adsorption, TVSA, cycle) for CO2 direct air capture
28
+ in 1D and 2D packed beds: single step sequences, cycles to cyclic steady state with KPIs, and
29
+ local NSGA-II optimization of the operating conditions.
pydac/_kit/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mattia Galanti, Ivo Roghair, Martin van Sint Annaland
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pydac/_kit/README.md ADDED
@@ -0,0 +1,262 @@
1
+ # pyDAC
2
+
3
+ pyDAC simulates adsorption-based direct air capture (DAC) processes. It solves the
4
+ coupled mass, energy and momentum balances of a sorbent column in 1D or 2D
5
+ (axisymmetric) and runs adsorption cycles step by step or to cyclic steady state (CSS).
6
+ A cycle is composed from configurable steps (adsorption, blowdown, heating, purge, steam-
7
+ or wall-heated desorption, cooling, pressurization); the default is a steam-assisted
8
+ temperature-vacuum swing adsorption (TVSA) cycle. pyDAC reports process key performance
9
+ indicators (KPIs) and optimizes operating conditions with the NSGA-II genetic algorithm
10
+ (non-dominated sorting genetic algorithm II).
11
+
12
+ pyDAC 3.0.0, development status Beta. MIT license.
13
+
14
+ ## Installation
15
+
16
+ ### 1. Create a dedicated environment
17
+
18
+ Install pyDAC in an environment of its own: never in the system Python, a conda `base`
19
+ environment, or an environment shared with other projects. pyDAC fixes the versions of
20
+ some dependencies (`pymrm==2.1.10`, `pandas<3`, `scikit-sundae` 1.1.x), and pip silently
21
+ replaces versions that are already installed, so a shared environment can break pyDAC
22
+ or the other project without any message.
23
+
24
+ Linux, with `venv`:
25
+
26
+ ```bash
27
+ python3 -m venv pydac-env
28
+ source pydac-env/bin/activate
29
+ ```
30
+
31
+ Windows (PowerShell), with `venv`:
32
+
33
+ ```powershell
34
+ py -m venv pydac-env
35
+ pydac-env\Scripts\Activate.ps1
36
+ ```
37
+
38
+ With conda instead:
39
+
40
+ ```bash
41
+ conda create -n pydac python=3.12
42
+ conda activate pydac
43
+ ```
44
+
45
+ With uv instead (`uv` environments have no `pip`; write `uv pip` where this page writes
46
+ `python -m pip`):
47
+
48
+ ```bash
49
+ uv venv pydac-env
50
+ source pydac-env/bin/activate
51
+ ```
52
+
53
+ ### 2. Install pyDAC
54
+
55
+ ```bash
56
+ python -m pip install pydac3
57
+ ```
58
+
59
+ The distribution is called `pydac3`; the package you import and the command you run are
60
+ both `pydac`. `pip install pydac` installs an unrelated project.
61
+
62
+ One install contains everything: step runs, CSS runs, case validation and NSGA-II
63
+ optimization (pymoo is a regular dependency). `pydac get-started my_pydac` copies the tutorials
64
+ and the user guide into a new folder
65
+ ([Get the tutorials](docs/guide/01_installation.md#get-the-tutorials-and-this-guide)). The optional extra `completion` adds shell
66
+ completion for the `pydac` command (`python -m pip install "pydac3[completion]"`).
67
+
68
+ Python 3.11 to 3.14 on Linux (x86_64) is supported. Windows is being tested; macOS is
69
+ neither tested nor supported.
70
+
71
+ **Want to adapt pyDAC to your own needs, or help improve it?** Install it from a clone in
72
+ editable mode instead; then an edit in `src/pydac/` is used at the next import:
73
+
74
+ ```bash
75
+ git clone https://github.com/process-intensification-lab/pyDAC.git
76
+ cd pyDAC
77
+ python -m pip install -e .
78
+ ```
79
+
80
+ [`CONTRIBUTING.md`](CONTRIBUTING.md) gives the full procedure (dedicated environment, light or
81
+ exact dependencies, tests) and how to propose a change.
82
+
83
+ ### 3. Check the environment
84
+
85
+ ```bash
86
+ python -m pip check
87
+ pydac --version
88
+ python -c "import pydac; print(pydac.__file__)"
89
+ ```
90
+
91
+ `pip check` must report no broken requirements, and the printed path must lie inside
92
+ the environment you created. A path in the user site instead (for example under
93
+ `~/.local/lib/`) means a user-site installation shadows the environment; set
94
+ `PYTHONNOUSERSITE=1` or remove that installation.
95
+
96
+ When the `pydac` command runs outside a virtual environment or a conda environment
97
+ other than `base`, it prints a one-line warning on stderr and continues. Set
98
+ `PYDAC_NO_ENV_WARNING=1` to silence it, for example in a container that uses the system
99
+ Python on purpose. `import pydac` never prints it.
100
+
101
+ ### Exact reproduction
102
+
103
+ To reproduce the qualified environment exactly (every package pinned, with hashes;
104
+ Python 3.12), install from the lock file into a second fresh environment, from the
105
+ root of a clone:
106
+
107
+ ```bash
108
+ python3.12 -m venv pydac-exact
109
+ source pydac-exact/bin/activate
110
+ python -m pip install --require-hashes -r ci/qualification-lock-py3.12.txt
111
+ python -m pip install --no-deps .
112
+ ```
113
+
114
+ ## Tutorials
115
+
116
+ **The best way to learn pyDAC is the seven tutorials. Start with
117
+ [01 First steps](examples/notebooks/01_first_steps.ipynb)**, then follow them in order.
118
+ `pydac get-started my_pydac` copies them, with the user guide, into a new folder. Each
119
+ tutorial is a notebook and states its runtime (from a few minutes to about 40). Tutorials
120
+ 01-06 also run from the terminal, with the commands in [`examples/README.md`](examples/README.md);
121
+ tutorial 07 needs Python, because it registers its own isotherm.
122
+
123
+ | Tutorial | What it shows |
124
+ |---|---|
125
+ | [01 First steps](examples/notebooks/01_first_steps.ipynb) | a step run, the KPI table of each step, step profile plots, time- or event-based stop |
126
+ | [02 Build your own case](examples/notebooks/02_custom_case.ipynb) | replace the defaults block by block (column, gas, sorbent, isotherm, kinetics, steps); a 2D TSA step run |
127
+ | [03 A cycle at its periodic state](examples/notebooks/03_css_tvsa.ipynb) | a CSS run of the built-in TVSA cycle in 2D, the cycle KPIs, where the CO2 and the energy go |
128
+ | [04 1D or 2D](examples/notebooks/04_1d_vs_2d.ipynb) | the same cycle in 1D, in 2D and in 2D with wall channeling |
129
+ | [05 An optimization campaign](examples/notebooks/05_nsga2_trial.ipynb) | a trial NSGA-II campaign: variables, bounds, constraints, the Pareto front |
130
+ | [06 Reproduce the breakthrough validation](examples/notebooks/06_breakthrough_validation.ipynb) | the 2D model of the pyDAC paper against the measurements of Zanco et al. |
131
+ | [07 Your own isotherm](examples/notebooks/07_new_isotherm.ipynb) | a new sorbent from the literature, its isotherm registered from Python and run |
132
+
133
+ ## Quick start from the terminal
134
+
135
+ A case is the complete set of inputs of one simulation. Write the built-in case to a
136
+ file, here with a coarse 1D grid and at most three cycles:
137
+
138
+ ```bash
139
+ pydac validate --set grid.nz=25 --set grid.nr=1 --set execution.max_cycles=3 --set execution.require_css=false --export-case my_case.json
140
+ ```
141
+
142
+ `my_case.json` holds every input of the simulation. To change it, prefer settings over
143
+ editing the file: they recompute the fields that depend on others, such as the bed length
144
+ from its volume ([Cases and settings](docs/guide/03_cases.md)). Then run it exactly as
145
+ saved; it repeats the cycle until cyclic steady state, here for at most three cycles;
146
+ this coarse case reaches CSS at cycle 3:
147
+
148
+ ```bash
149
+ pydac css --case my_case.json
150
+ ```
151
+
152
+ The run takes one to two minutes. It writes everything under
153
+ `simulation_results/cyclic_mode/packed_bed_XXXXXXXX/`, where `XXXXXXXX` is the start of
154
+ the case fingerprint, and prints that run folder as its last line. Inside,
155
+ `1D_mode/cycle_N/` holds each cycle and `1D_mode/kpis/` the KPI tables of the final
156
+ cycle. Running the same case again is refused while that folder exists: continue it with
157
+ `--resume`, replace it with `--overwrite`, or set another `execution.extra_tag`.
158
+
159
+ The other commands are `pydac steps` (startup, then each listed step once),
160
+ `pydac nsga2` (an optimization campaign) and `pydac validate`. Each lists its options
161
+ with `--help`; `pydac validate --show-settings` lists the settings with their built-in
162
+ defaults. Instead of a complete case, `--config` takes a partial preset whose omitted
163
+ fields take the built-in defaults, for example
164
+ [`examples/cases/quick_1D.json`](examples/cases/quick_1D.json) from the repository:
165
+
166
+ ```bash
167
+ pydac css --config examples/cases/quick_1D.json --dry-run
168
+ ```
169
+
170
+ Exit codes: `0` success, `1` failure after the run started, `2` invalid command-line
171
+ arguments, configuration error or refused request, `3` CSS not reached while
172
+ `execution.require_css` is true.
173
+
174
+ ## Quick start from Python
175
+
176
+ The same steps through the Python API, in a script or a notebook. This loads the saved
177
+ case, changes one setting, runs it and reads two KPIs:
178
+
179
+ ```python
180
+ import pydac
181
+
182
+ case = pydac.load_case("my_case.json", settings={"execution.max_cycles": 4})
183
+ result = pydac.run_css(case)
184
+ print(result.folder, result.css_reached, result.cycle)
185
+
186
+ kpis = pydac.CycleKPIs(pydac.CycleDataLoader(result.folder).load())
187
+ print(f"CO2 recovery: {100 * kpis.recovery('CO2'):.1f} %")
188
+ print(f"Productivity: {kpis.productivity():.2f} kg CO2 per m3 bed per day")
189
+ ```
190
+
191
+ `pydac.load_case(path, exact=True)` runs a complete case exactly, as `--case` does. The
192
+ supported API is the set of names in `pydac.__all__`: `load_case`, `export_case`,
193
+ `export_settings`, `run_steps`, `run_css`, `run_nsga2`, `resume`, `report`, `get_started`,
194
+ `RunResult`, `ConfigurationError`, `RunRefused`, `ExperimentConfig`, `CycleDataLoader`,
195
+ `CycleKPIs`, `register_equilibrium`, `register_kinetics`, `EquilibriumSystem`, `KineticLaw`,
196
+ `EquilibriumRegistryEntry`, `KineticRegistryEntry` and the version string `__version__`.
197
+
198
+ ## Reproducibility
199
+
200
+ Every run folder contains the resolved case (`resolved_config.json`), its fingerprint
201
+ (`case_metadata.json`) and a provenance record: the pyDAC version, the Python version,
202
+ the platform and the versions of the numerical dependencies. Run from a clone, the
203
+ record also says whether the checkout had uncommitted changes; it does not record the Git
204
+ revision, so keep the commit of an unreleased checkout yourself. To
205
+ rerun a result, run its `resolved_config.json` with `--case` (in another output root, or
206
+ with `--overwrite`); to rebuild the environment, use the lock file above.
207
+
208
+ ## Documentation
209
+
210
+ Read in this order: the tutorials (above) teach pyDAC on real runs; the user guide is
211
+ the reference for using it, in more technical detail; the reference manual describes how pyDAC
212
+ works inside, in full technical detail, for contributors and for checking the model. The
213
+ documentation index is [`docs/README.md`](docs/README.md). The user guide explains how to use
214
+ pyDAC:
215
+
216
+ - [Installation](docs/guide/01_installation.md): environments, Jupyter, shell
217
+ completion, exact reproduction, troubleshooting.
218
+ - [Quick start](docs/guide/02_quickstart.md): one case from the terminal, a script
219
+ and a notebook; the Python API and its errors.
220
+ - [Cases and settings](docs/guide/03_cases.md): presets, settings, frozen cases,
221
+ model choices, `null`, fingerprints.
222
+ - [Running steps and cycles](docs/guide/04_running.md): step sequence, stop rules,
223
+ resume, replay, report, run folders, exit codes.
224
+ - [Optimization campaigns](docs/guide/05_optimization.md): NSGA-II campaigns, bounds,
225
+ constraints, stop rules, continuing and reporting a campaign.
226
+ - [Results](docs/guide/06_results.md): run folders, KPI files, reading results from
227
+ Python, which folders to trust.
228
+ - [Reproducibility](docs/guide/07_reproducibility.md): sharing a case, provenance,
229
+ the exact environment, compatibility across versions.
230
+ - [Extending pyDAC](docs/guide/08_extending.md): your own isotherms and kinetic laws,
231
+ registered from Python; what needs a change to the package.
232
+
233
+ The reference chapters describe the model and the code:
234
+
235
+ | Chapter | Contents |
236
+ |---|---|
237
+ | [`00_framework_map.md`](docs/manual/00_framework_map.md) | Layers, entry points and what a run does end to end |
238
+ | [`01_inputs.md`](docs/manual/01_inputs.md) | Cases, presets, settings and the case document |
239
+ | [`02_pydac_core.md`](docs/manual/02_pydac_core.md) | Model construction, state vector, solver and cycle orchestration |
240
+ | [`03_pymrm_discretization.md`](docs/manual/03_pymrm_discretization.md) | Finite-volume operators and boundary conditions |
241
+ | [`04_governing_equations.md`](docs/manual/04_governing_equations.md) | Balances and closures, and where the code assembles them |
242
+ | [`05_cycle_steps.md`](docs/manual/05_cycle_steps.md) | Each cycle step: physics, boundary conditions, stop rules |
243
+ | [`06_post_processing.md`](docs/manual/06_post_processing.md) | KPIs, separators, plots and result files |
244
+ | [`07_nsga2_optimization.md`](docs/manual/07_nsga2_optimization.md) | NSGA-II campaigns |
245
+
246
+ To work on pyDAC itself, read [`CONTRIBUTING.md`](CONTRIBUTING.md).
247
+
248
+ ## How to cite
249
+
250
+ If you use pyDAC in your research, please cite it with the metadata in
251
+ [`CITATION.cff`](CITATION.cff). Each GitHub release has its own DOI on Zenodo; once the
252
+ pyDAC paper is published, it becomes the preferred citation.
253
+
254
+ ## License and authors
255
+
256
+ pyDAC is released under the MIT license ([`LICENSE`](LICENSE)). Authors: Mattia
257
+ Galanti, Ivo Roghair and Martin van Sint Annaland (Eindhoven University of Technology).
258
+ Maintainer: Mattia Galanti.
259
+
260
+ ## Acknowledgements
261
+
262
+ We thank Shell Global Solutions International BV for financial support.
@@ -0,0 +1,244 @@
1
+ ---
2
+ title: "Installation"
3
+ toc: true
4
+ toc-depth: 3
5
+ embed-resources: true
6
+ ---
7
+
8
+ > **New to pyDAC? Do the [tutorials](../../examples/README.md) first, starting with
9
+ > [01 First steps](../../examples/notebooks/01_first_steps.ipynb).** They teach pyDAC step by
10
+ > step on real runs; this guide is the reference behind them and goes into more technical detail.
11
+
12
+ This page installs pyDAC in an environment of its own, checks it, and connects it to
13
+ Jupyter and to your shell. The [README](../../README.md) gives the short version.
14
+
15
+ ## What you need
16
+
17
+ - Python 3.11, 3.12, 3.13 or 3.14.
18
+ - Linux (x86_64) is the supported platform. Windows is being tested; macOS is neither
19
+ tested nor supported.
20
+ - About 1 GB of disk space for the environment (see
21
+ [What gets installed](#what-gets-installed)).
22
+
23
+ ## Why pyDAC needs its own environment
24
+
25
+ pyDAC fixes the versions of some dependencies: `pymrm==2.1.10`, `pandas<3` and
26
+ `scikit-sundae` 1.1.x. pip silently replaces versions that are already installed: in an
27
+ environment that already had pandas 3.0.6, installing pyDAC downgraded it to 2.3.3
28
+ without a question. In a shared environment, installing pyDAC can therefore break another
29
+ project, and installing another project can break pyDAC.
30
+
31
+ Install pyDAC only in a new environment created for it. Never use:
32
+
33
+ - the system Python;
34
+ - the conda `base` environment;
35
+ - an environment shared with another project.
36
+
37
+ ## Create the environment
38
+
39
+ Pick one tool. Each block creates an environment and activates it; later commands on this
40
+ page run inside the active environment.
41
+
42
+ Linux, with `venv`:
43
+
44
+ ```bash
45
+ python3 -m venv pydac-env
46
+ source pydac-env/bin/activate
47
+ ```
48
+
49
+ Windows (PowerShell), with `venv`:
50
+
51
+ ```powershell
52
+ py -m venv pydac-env
53
+ pydac-env\Scripts\Activate.ps1
54
+ ```
55
+
56
+ With conda:
57
+
58
+ ```bash
59
+ conda create -n pydac python=3.12
60
+ conda activate pydac
61
+ ```
62
+
63
+ With uv:
64
+
65
+ ```bash
66
+ uv venv pydac-env
67
+ source pydac-env/bin/activate
68
+ ```
69
+
70
+ A uv environment has no `pip`: wherever this page writes `python -m pip`, write `uv pip`
71
+ instead.
72
+
73
+ Activate the environment again in every new terminal before you use pyDAC.
74
+
75
+ ## Install pyDAC
76
+
77
+ ```bash
78
+ python -m pip install pydac3
79
+ ```
80
+
81
+ Until pyDAC 3.0.0 is on PyPI, install it from a clone of the repository:
82
+
83
+ ```bash
84
+ git clone https://github.com/process-intensification-lab/pyDAC.git
85
+ cd pyDAC
86
+ python -m pip install .
87
+ ```
88
+
89
+ One install contains every workflow: step runs, cyclic steady state (CSS) runs, case
90
+ validation and NSGA-II optimization. Shell completion is an optional extra, see
91
+ [Shell completion](#shell-completion).
92
+
93
+ ### Names
94
+
95
+ | Name | What it is |
96
+ |---|---|
97
+ | `pydac3` | the distribution: the name you give to `pip install` |
98
+ | `pydac` | the package you import (`import pydac`) and the command you run (`pydac css`) |
99
+ | pyDAC | the project |
100
+
101
+ `pip install pydac` installs an unrelated project with the same name. If you installed it
102
+ by mistake, remove it with `python -m pip uninstall pydac`.
103
+
104
+ ### What gets installed
105
+
106
+ The environment holds about 100 packages and 0.9 GB. pyDAC's own dependencies are numpy,
107
+ scipy, pandas, matplotlib, seaborn, pymoo, scikit-sundae and pymrm; pymrm 2.1.10 in turn
108
+ requires its documentation, notebook and test tools (sphinx, ipython, ipykernel, nbclient,
109
+ pytest, numba and others). They are installed even though pyDAC does not call them. One
110
+ useful consequence: the environment already holds a Jupyter kernel (ipykernel), so VS Code
111
+ or an existing Jupyter installation can run notebooks on it
112
+ ([Use pyDAC in Jupyter](#use-pydac-in-jupyter)). The browser interface itself (JupyterLab
113
+ or Notebook) is not included: install it separately if you want it.
114
+
115
+ ### Get the tutorials and this guide
116
+
117
+ The installed package also holds a starter kit: the README, the licence, the citation
118
+ file, this guide and the tutorials (cases, notebooks and data). Copy it into a new
119
+ folder:
120
+
121
+ ```bash
122
+ pydac get-started my_pydac
123
+ cd my_pydac
124
+ ```
125
+
126
+ (`pydac.get_started("my_pydac")` does the same from Python.) The folder has the layout
127
+ of the repository, so the tutorials run as written in
128
+ [`examples/README.md`](../../examples/README.md) from inside it. The kit has no source code,
129
+ tests or developer manual: its links to the manual open it in the public repository, at
130
+ the version you installed. `pydac get-started` refuses a folder that already holds files. A clone
131
+ of the repository already has everything; it needs no kit.
132
+
133
+ ## Check the environment
134
+
135
+ ```bash
136
+ python -m pip check
137
+ pydac --version
138
+ python -c "import pydac; print(pydac.__file__)"
139
+ ```
140
+
141
+ A correct environment prints:
142
+
143
+ - `No broken requirements found.`;
144
+ - `pydac 3.0.0` (the installed version);
145
+ - a path inside the environment you created, ending in `site-packages/pydac/__init__.py`.
146
+
147
+ If the path lies in the user site instead (for example under `~/.local/lib/`), a
148
+ package installed with `pip install --user` shadows the environment's own. A venv
149
+ ignores the user site, but a conda environment searches it before its own packages. Set
150
+ `PYTHONNOUSERSITE=1` in the shell before running pyDAC, or remove the user-site
151
+ installation.
152
+
153
+ ### The environment warning
154
+
155
+ When the `pydac` command runs outside a dedicated environment, it prints one line on
156
+ stderr and continues:
157
+
158
+ ```text
159
+ Warning: pydac is running outside a dedicated environment (PREFIX). pyDAC pins some dependencies, and pip replaces installed versions without asking: install it in its own venv or conda environment (README, Installation). PYDAC_NO_ENV_WARNING=1 silences this.
160
+ ```
161
+
162
+ The command counts as dedicated when it runs in a virtual environment (venv, uv) or in a
163
+ conda environment other than `base`. The warning never stops a run. `import pydac` never
164
+ prints it, so in scripts and notebooks the check above is your only safeguard. To silence
165
+ it on purpose, for example in a container that uses the system Python by design, set
166
+ `PYDAC_NO_ENV_WARNING=1`.
167
+
168
+ ## Use pyDAC in Jupyter
169
+
170
+ Register the environment as a Jupyter kernel, once, with the environment active:
171
+
172
+ ```bash
173
+ python -m ipykernel install --user --name pydac-env --display-name "Python (pyDAC)"
174
+ ```
175
+
176
+ In Jupyter (or VS Code), select the kernel "Python (pyDAC)". A notebook running on another
177
+ kernel imports another environment's packages, or none. To check from a notebook cell:
178
+
179
+ ```python
180
+ import sys
181
+ import pydac
182
+
183
+ print(sys.executable)
184
+ print(pydac.__file__)
185
+ ```
186
+
187
+ Both paths must lie inside the pyDAC environment. To remove the kernel later:
188
+
189
+ ```bash
190
+ jupyter kernelspec uninstall pydac-env
191
+ ```
192
+
193
+ ## Shell completion
194
+
195
+ The `completion` extra adds tab completion of the `pydac` subcommands and flags in bash
196
+ and zsh:
197
+
198
+ ```bash
199
+ python -m pip install "pydac3[completion]"
200
+ eval "$(register-python-argcomplete pydac)"
201
+ ```
202
+
203
+ The second line enables completion in the current shell; run it again in each new shell
204
+ after activating the environment. Then `pydac cs` + Tab completes to `pydac css`, and
205
+ `pydac css --ov` + Tab lists `--overwrite` and `--overwrite-case`.
206
+
207
+ ## Exact reproduction
208
+
209
+ To rebuild the environment in which pyDAC was qualified, every package at the exact
210
+ version and checked against its hash, use the lock file of the repository. It is written
211
+ for Python 3.12. From the root of a clone, in a second fresh environment:
212
+
213
+ ```bash
214
+ python3.12 -m venv pydac-exact
215
+ source pydac-exact/bin/activate
216
+ python -m pip install --require-hashes -r ci/qualification-lock-py3.12.txt
217
+ python -m pip install --no-deps .
218
+ ```
219
+
220
+ `--no-deps` installs pyDAC itself without letting pip change any version the lock fixed.
221
+
222
+ ## Update or remove
223
+
224
+ To update pyDAC, run `python -m pip install --upgrade pydac3` in its environment, then
225
+ `python -m pip check`. A new pyDAC version may require other dependency versions; if
226
+ `pip check` reports a conflict, create a new environment instead of repairing the old one.
227
+
228
+ To remove pyDAC, delete the environment: the `pydac-env` folder, or
229
+ `conda env remove -n pydac`. Remove the Jupyter kernel as shown above.
230
+
231
+ ## Troubleshooting
232
+
233
+ | Symptom | Cause and fix |
234
+ |---|---|
235
+ | `pydac: command not found` | The environment is not active. Activate it (`source pydac-env/bin/activate`). |
236
+ | `pydac.__file__` points into `~/.local` | A user-site installation shadows the environment. Set `PYTHONNOUSERSITE=1`, or uninstall the user-site copy. |
237
+ | `pip check` reports a broken requirement | Another install changed a version pyDAC fixes. Create a new environment and install pyDAC alone in it. |
238
+ | `import pydac` fails in a notebook | The notebook runs another kernel. Select "Python (pyDAC)" (see [Use pyDAC in Jupyter](#use-pydac-in-jupyter)). |
239
+ | `pip install pydac` installed version 0.0.x | That is an unrelated project. Uninstall it and install `pydac3`. |
240
+
241
+ ## Related pages
242
+
243
+ - [README](../../README.md): overview and quick start.
244
+ - [CONTRIBUTING](../../CONTRIBUTING.md): the environment for working on pyDAC itself.