|
4 | 4 | process simulations using the NeqSim Java library. It includes equipment |
5 | 5 | like compressors, pumps, heat exchangers, separators, and more. |
6 | 6 |
|
7 | | -Two Approaches for Process Simulation |
8 | | -===================================== |
| 7 | +Four Approaches for Process Simulation |
| 8 | +====================================== |
9 | 9 |
|
10 | | -NeqSim Python offers two ways to build process simulations: |
| 10 | +NeqSim Python offers four ways to build process simulations: |
11 | 11 |
|
12 | | -1. **Python Wrappers (Recommended for beginners)** |
13 | | - Uses simple Python functions with a global process. Best for quick |
14 | | - prototyping, Jupyter notebooks, and learning. |
| 12 | +1. **Python Wrappers with Global Process** (Recommended for beginners) |
| 13 | + Simple functions that auto-add equipment to a global process. |
15 | 14 |
|
16 | | -2. **Direct Java Access (Full control)** |
17 | | - Uses the jneqsim module to access NeqSim Java classes directly. |
18 | | - Best for production code, multiple processes, and advanced features. |
| 15 | +2. **ProcessContext** (Recommended for production) |
| 16 | + Context manager with its own process - supports multiple processes. |
| 17 | +
|
| 18 | +3. **ProcessBuilder** (Fluent API) |
| 19 | + Chainable builder pattern - great for configuration-driven design. |
| 20 | +
|
| 21 | +4. **Direct Java Access** (Full control) |
| 22 | + Direct jneqsim access for advanced features. |
19 | 23 |
|
20 | 24 | Approach 1: Python Wrappers (Global Process) |
21 | 25 | -------------------------------------------- |
|
30 | 34 | >>> my_fluid.addComponent('methane', 1.0) |
31 | 35 | >>> my_fluid.setTemperature(30.0, 'C') |
32 | 36 | >>> my_fluid.setPressure(10.0, 'bara') |
33 | | - >>> my_fluid.setTotalFlowRate(1.0, 'MSm3/day') |
34 | 37 | >>> |
35 | 38 | >>> inlet = stream('inlet', my_fluid) |
36 | 39 | >>> comp = compressor('compressor1', inlet, pres=50.0) |
37 | 40 | >>> runProcess() |
38 | 41 | >>> print(f"Power: {comp.getPower()/1e6:.2f} MW") |
39 | 42 |
|
40 | | -Pros: |
41 | | - - Concise, readable code |
42 | | - - Tab completion and docstrings in IDE |
43 | | - - No Java knowledge required |
44 | | - - Great for learning and prototyping |
| 43 | +Pros: Concise, readable, great for learning and prototyping |
| 44 | +Cons: Global state limits to one process at a time |
45 | 45 |
|
46 | | -Cons: |
47 | | - - Global state limits to one process at a time |
48 | | - - Not all Java features may be exposed |
49 | | - - Less control over process execution |
| 46 | +Approach 2: ProcessContext (Explicit Process Management) |
| 47 | +--------------------------------------------------------- |
| 48 | +Context manager that creates its own ProcessSystem. Supports multiple |
| 49 | +independent processes running simultaneously. |
50 | 50 |
|
51 | | -Approach 2: Direct Java Access (Explicit Process) |
| 51 | + >>> from neqsim.thermo import fluid |
| 52 | + >>> from neqsim.process import ProcessContext |
| 53 | + >>> |
| 54 | + >>> with ProcessContext("Compression") as ctx: |
| 55 | + ... my_fluid = fluid('srk') |
| 56 | + ... my_fluid.addComponent('methane', 1.0) |
| 57 | + ... my_fluid.setPressure(10.0, 'bara') |
| 58 | + ... |
| 59 | + ... inlet = ctx.stream('inlet', my_fluid) |
| 60 | + ... comp = ctx.compressor('comp1', inlet, pres=50.0) |
| 61 | + ... ctx.run() |
| 62 | + ... print(f"Power: {comp.getPower()/1e6:.2f} MW") |
| 63 | +
|
| 64 | +Pros: Multiple processes, explicit control, clean resource management |
| 65 | +Cons: Slightly more verbose than global wrappers |
| 66 | +
|
| 67 | +Approach 3: ProcessBuilder (Fluent/Chainable API) |
52 | 68 | -------------------------------------------------- |
| 69 | +Builder pattern with method chaining. Equipment referenced by name. |
| 70 | +Ideal for configuration-driven process construction. |
| 71 | +
|
| 72 | + >>> from neqsim.thermo import fluid |
| 73 | + >>> from neqsim.process import ProcessBuilder |
| 74 | + >>> |
| 75 | + >>> my_fluid = fluid('srk') |
| 76 | + >>> my_fluid.addComponent('methane', 1.0) |
| 77 | + >>> my_fluid.setPressure(10.0, 'bara') |
| 78 | + >>> |
| 79 | + >>> process = (ProcessBuilder("Compression") |
| 80 | + ... .add_stream('inlet', my_fluid) |
| 81 | + ... .add_compressor('comp1', 'inlet', pressure=50.0) |
| 82 | + ... .run()) |
| 83 | + >>> |
| 84 | + >>> print(f"Power: {process.get('comp1').getPower()/1e6:.2f} MW") |
| 85 | +
|
| 86 | +Pros: Very readable, chainable, equipment by name, declarative style |
| 87 | +Cons: Less direct access during construction |
| 88 | +
|
| 89 | +Approach 4: Direct Java Access |
| 90 | +------------------------------- |
53 | 91 | Create and manage ProcessSystem objects explicitly using jneqsim. |
54 | 92 |
|
55 | 93 | >>> from neqsim import jneqsim |
56 | 94 | >>> from neqsim.thermo import fluid |
57 | 95 | >>> |
58 | | - >>> # Create fluid |
59 | 96 | >>> my_fluid = fluid('srk') |
60 | 97 | >>> my_fluid.addComponent('methane', 1.0) |
61 | | - >>> my_fluid.setTemperature(30.0, 'C') |
62 | 98 | >>> my_fluid.setPressure(10.0, 'bara') |
63 | | - >>> my_fluid.setTotalFlowRate(1.0, 'MSm3/day') |
64 | 99 | >>> |
65 | | - >>> # Create equipment using Java classes |
66 | 100 | >>> inlet = jneqsim.process.equipment.stream.Stream('inlet', my_fluid) |
67 | | - >>> comp = jneqsim.process.equipment.compressor.Compressor('compressor1', inlet) |
| 101 | + >>> comp = jneqsim.process.equipment.compressor.Compressor('comp1', inlet) |
68 | 102 | >>> comp.setOutletPressure(50.0) |
69 | 103 | >>> |
70 | | - >>> # Create and run process explicitly |
71 | 104 | >>> process = jneqsim.process.processmodel.ProcessSystem() |
72 | 105 | >>> process.add(inlet) |
73 | 106 | >>> process.add(comp) |
74 | 107 | >>> process.run() |
75 | | - >>> print(f"Power: {comp.getPower()/1e6:.2f} MW") |
76 | 108 |
|
77 | | -Pros: |
78 | | - - Full access to all NeqSim Java features |
79 | | - - Multiple independent processes possible |
80 | | - - Explicit control over process construction |
81 | | - - Better for production code and testing |
| 109 | +Pros: Full access to all Java features, maximum flexibility |
| 110 | +Cons: Verbose, requires Java knowledge |
82 | 111 |
|
83 | | -Cons: |
84 | | - - More verbose code |
85 | | - - Requires understanding of Java class structure |
86 | | - - Less IDE support (though stubs help) |
| 112 | +Hybrid Approach: Wrappers with process= Parameter |
| 113 | +-------------------------------------------------- |
| 114 | +Wrapper functions accept an optional process= parameter for explicit |
| 115 | +process control while keeping concise syntax: |
| 116 | +
|
| 117 | + >>> from neqsim.process import stream, compressor, newProcess |
| 118 | + >>> |
| 119 | + >>> my_process = newProcess('MyProcess') |
| 120 | + >>> inlet = stream('inlet', my_fluid, process=my_process) |
| 121 | + >>> comp = compressor('comp1', inlet, pres=50.0, process=my_process) |
| 122 | + >>> my_process.run() |
87 | 123 |
|
88 | 124 | Choosing an Approach |
89 | 125 | -------------------- |
90 | | -Use **Python wrappers** when: |
91 | | - - Learning NeqSim or thermodynamics |
92 | | - - Quick calculations in Jupyter notebooks |
93 | | - - Single process simulations |
94 | | - - Prototyping process designs |
95 | | -
|
96 | | -Use **direct Java access** when: |
97 | | - - Building production applications |
98 | | - - Running multiple processes in parallel |
99 | | - - Need features not exposed by wrappers |
100 | | - - Writing automated tests |
101 | | - - Configuration-driven process construction |
102 | | -
|
103 | | -Hybrid Approach |
104 | | ---------------- |
105 | | -You can mix both approaches. Create equipment with wrappers, then access |
106 | | -Java methods directly: |
107 | | -
|
108 | | - >>> from neqsim.process import stream, compressor, runProcess, clearProcess |
109 | | - >>> from neqsim.thermo import fluid |
110 | | - >>> |
111 | | - >>> clearProcess() |
112 | | - >>> my_fluid = fluid('srk') |
113 | | - >>> my_fluid.addComponent('methane', 1.0) |
114 | | - >>> inlet = stream('inlet', my_fluid) |
115 | | - >>> comp = compressor('comp1', inlet, pres=50.0) |
116 | | - >>> |
117 | | - >>> # Access Java methods not exposed by wrapper |
118 | | - >>> comp.setPolytropicEfficiency(0.78) |
119 | | - >>> comp.setUsePolytropicCalc(True) |
120 | | - >>> |
121 | | - >>> runProcess() |
| 126 | ++----------------------------------+--------------------------------+ |
| 127 | +| Use Case | Recommended Approach | |
| 128 | ++==================================+================================+ |
| 129 | +| Learning / tutorials | Wrappers (global process) | |
| 130 | +| Jupyter notebooks | Wrappers (global process) | |
| 131 | +| Quick prototyping | Wrappers (global process) | |
| 132 | +| Production applications | ProcessContext | |
| 133 | +| Multiple parallel processes | ProcessContext | |
| 134 | +| Configuration-driven design | ProcessBuilder | |
| 135 | +| Full Java API access | Direct jneqsim | |
| 136 | ++----------------------------------+--------------------------------+ |
122 | 137 |
|
123 | 138 | Available Equipment |
124 | 139 | ------------------- |
|
135 | 150 | Storage: tank, simplereservoir, manifold |
136 | 151 | Measurement: waterDewPointAnalyser, hydrateEquilibriumTemperatureAnalyser |
137 | 152 | Power: windturbine, solarpanel, batterystorage, fuelcell, electrolyzer, co2electrolyzer |
| 153 | +
|
| 154 | +Classes: ProcessContext, ProcessBuilder |
138 | 155 | """ |
139 | 156 | from __future__ import annotations |
140 | 157 |
|
|
0 commit comments