RunFeemsSim 0.2.6__tar.gz → 0.5.0__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.
@@ -0,0 +1,562 @@
1
+ Metadata-Version: 2.4
2
+ Name: RunFeemsSim
3
+ Version: 0.5.0
4
+ Summary: A library for running feems simulation
5
+ Author-email: Kevin Koosup Yum <kevinkoosup.yum@gmail.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Repository, https://github.com/SINTEF/FEEMS
8
+ Project-URL: Documentation, https://kevinkoosup.yum@sintef.no.github.io/RunFeemsSim/
9
+ Keywords: FEEMS,,machinery,system,,fuel,,emissions
10
+ Classifier: Natural Language :: English
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Development Status :: 2 - Pre-Alpha
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: pandas
19
+ Requires-Dist: numpy
20
+ Requires-Dist: MachSysS
21
+ Dynamic: license-file
22
+
23
+ # RunFeemsSim - FEEMS Simulation Runner
24
+
25
+ [![PyPI version](https://badge.fury.io/py/RunFeemsSim.svg)](https://badge.fury.io/py/RunFeemsSim)
26
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
27
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
28
+
29
+ **RunFeemsSim** provides a high-level interface for running FEEMS simulations with automated power management. It simplifies time-series simulation, includes Power Management System (PMS) logic for automatic genset control, and integrates seamlessly with the FEEMS ecosystem.
30
+
31
+ ## Features
32
+
33
+ ### 🎯 High-Level Simulation Interface
34
+ - **Simple API**: Run complex simulations with minimal code
35
+ - **Time-Series Support**: Handle operational profiles over time
36
+ - **Automatic Power Balance**: Continuous load balancing across time points
37
+ - **Result Aggregation**: Comprehensive metrics collection
38
+
39
+ ### 🔌 Power Management System (PMS)
40
+ - **Load-Dependent Control**: Automatic genset start/stop based on load
41
+ - **Multiple Strategies**: Configurable PMS algorithms
42
+ - **Efficiency Optimization**: Minimize fuel consumption
43
+ - **Blackout Prevention**: Ensure sufficient spinning reserve
44
+
45
+ ### 📊 Results Analysis
46
+ - **Fuel Consumption**: Total and per-component fuel usage
47
+ - **Emissions**: CO2, NOx with FuelEU Maritime support
48
+ - **Energy Breakdown**: Propulsion vs. auxiliary energy
49
+ - **Operating Hours**: Runtime tracking for maintenance planning
50
+
51
+ ### 🐍 Pure Python Development
52
+ - **Clean Python Modules**: Standard Python package structure
53
+ - **Easy to Understand**: Straightforward code organization
54
+ - **Simple to Extend**: Add new features easily
55
+ - **Type Hints**: Full type annotation support
56
+
57
+ ## Installation
58
+
59
+ ### From PyPI
60
+
61
+ ```bash
62
+ pip install RunFeemsSim
63
+ ```
64
+
65
+ This will install RunFeemsSim along with its dependencies (feems, MachSysS).
66
+
67
+ ### From Source (Developers)
68
+
69
+ ```bash
70
+ # Clone repository
71
+ git clone https://github.com/SINTEF/FEEMS.git
72
+ cd FEEMS
73
+
74
+ # Install with uv (recommended)
75
+ uv sync
76
+
77
+ # Or with pip
78
+ pip install -e RunFEEMSSim/
79
+ ```
80
+
81
+ ## Quick Start
82
+
83
+ ### Basic Simulation
84
+
85
+ ```python
86
+ import numpy as np
87
+ import pandas as pd
88
+ from RunFeemsSim.machinery_calculation import MachineryCalculation
89
+ from feems.system_model import ElectricPowerSystem
90
+ from feems.fuel import FuelSpecifiedBy
91
+
92
+ # Create or load a FEEMS system
93
+ system = ElectricPowerSystem(...)
94
+
95
+ # Initialize machinery calculation
96
+ machinery_calc = MachineryCalculation(system)
97
+
98
+ # Define propulsion power time series
99
+ n_points = 1000
100
+ time_step_s = 1.0
101
+
102
+ propulsion_power = pd.DataFrame({
103
+ 'Propulsion Drive 1': 400 + 200 * np.random.random(n_points),
104
+ 'Propulsion Drive 2': 300 + 150 * np.random.random(n_points)
105
+ }, index=np.arange(0, n_points * time_step_s, time_step_s))
106
+
107
+ # Define auxiliary power
108
+ auxiliary_power = 100 + 50 * np.random.random(n_points)
109
+
110
+ # Run simulation
111
+ result = machinery_calc.calculate_machinery_system_output_from_propulsion_power_time_series(
112
+ propulsion_power=propulsion_power,
113
+ auxiliary_power_kw=auxiliary_power,
114
+ fuel_specified_by=FuelSpecifiedBy.FUEL_EU_MARITIME
115
+ )
116
+
117
+ # Access results
118
+ print(f"Total fuel: {result.multi_fuel_consumption_total_kg.fuels[0].mass_or_mass_fraction:.2f} kg")
119
+ print(f"Total CO2: {result.co2_emission_total_kg.tank_to_wake_kg_or_gco2eq_per_gfuel:.2f} kg")
120
+ print(f"Genset hours: {result.running_hours_genset_total_hr:.2f} hr")
121
+ ```
122
+
123
+ ### With Power Management System
124
+
125
+ ```python
126
+ from RunFeemsSim.pms_basic import PMSBasic
127
+
128
+ # Create PMS with load-dependent genset control
129
+ pms = PMSBasic(
130
+ load_threshold_start=0.75, # Start additional genset at 75% load
131
+ load_threshold_stop=0.40, # Stop genset when load drops below 40%
132
+ min_gensets_running=1 # Always keep at least 1 genset running
133
+ )
134
+
135
+ # Attach PMS to system
136
+ machinery_calc = MachineryCalculation(system, pms=pms)
137
+
138
+ # Run simulation with automatic genset management
139
+ result = machinery_calc.calculate_machinery_system_output_from_propulsion_power_time_series(
140
+ propulsion_power=propulsion_power,
141
+ auxiliary_power_kw=auxiliary_power,
142
+ fuel_specified_by=FuelSpecifiedBy.FUEL_EU_MARITIME
143
+ )
144
+
145
+ # PMS automatically starts/stops gensets based on load
146
+ print(f"Genset start events: {pms.n_starts}")
147
+ print(f"Genset stop events: {pms.n_stops}")
148
+ ```
149
+
150
+ ## Core Components
151
+
152
+ ### MachineryCalculation
153
+
154
+ Main class for running simulations.
155
+
156
+ ```python
157
+ class MachineryCalculation:
158
+ """High-level interface for FEEMS simulations."""
159
+
160
+ def __init__(self, system: ElectricPowerSystem, pms: Optional[PMS] = None):
161
+ """
162
+ Initialize machinery calculation.
163
+
164
+ Args:
165
+ system: FEEMS ElectricPowerSystem
166
+ pms: Optional Power Management System
167
+ """
168
+ ...
169
+
170
+ def calculate_machinery_system_output_from_propulsion_power_time_series(
171
+ self,
172
+ propulsion_power: pd.DataFrame,
173
+ auxiliary_power_kw: np.ndarray,
174
+ fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO,
175
+ integration_method: IntegrationMethod = IntegrationMethod.simpson,
176
+ time_interval_s: float = 1.0
177
+ ) -> ElectricSystemRunResult:
178
+ """
179
+ Run simulation from propulsion power time series.
180
+
181
+ Args:
182
+ propulsion_power: DataFrame with propulsion drive powers
183
+ Index: time in seconds
184
+ Columns: drive names
185
+ Values: power in kW
186
+ auxiliary_power_kw: Auxiliary load time series (kW)
187
+ fuel_specified_by: Emission calculation method
188
+ integration_method: Time integration method
189
+ time_interval_s: Time step in seconds
190
+
191
+ Returns:
192
+ ElectricSystemRunResult with comprehensive metrics
193
+ """
194
+ ...
195
+ ```
196
+
197
+ ### PMSBasic
198
+
199
+ Basic load-dependent Power Management System.
200
+
201
+ ```python
202
+ class PMSBasic:
203
+ """
204
+ Basic PMS with load-dependent genset start/stop.
205
+
206
+ Starts additional gensets when load exceeds threshold.
207
+ Stops gensets when load drops below threshold.
208
+ Maintains minimum number of running gensets.
209
+ """
210
+
211
+ def __init__(
212
+ self,
213
+ load_threshold_start: float = 0.85,
214
+ load_threshold_stop: float = 0.40,
215
+ min_gensets_running: int = 1,
216
+ spinning_reserve: float = 0.20
217
+ ):
218
+ """
219
+ Initialize PMS.
220
+
221
+ Args:
222
+ load_threshold_start: Start genset when load > this (0-1)
223
+ load_threshold_stop: Stop genset when load < this (0-1)
224
+ min_gensets_running: Minimum gensets to keep running
225
+ spinning_reserve: Required spare capacity (0-1)
226
+ """
227
+ ...
228
+
229
+ def determine_genset_status(
230
+ self,
231
+ current_load_kw: float,
232
+ available_gensets: List[Genset],
233
+ current_status: np.ndarray
234
+ ) -> np.ndarray:
235
+ """
236
+ Determine which gensets should be running.
237
+
238
+ Args:
239
+ current_load_kw: Total system load
240
+ available_gensets: List of all gensets
241
+ current_status: Current on/off status
242
+
243
+ Returns:
244
+ Updated status array
245
+ """
246
+ ...
247
+ ```
248
+
249
+ ## Power Management Strategies
250
+
251
+ ### Strategy 1: Load-Dependent Control
252
+
253
+ Automatically start/stop gensets based on load:
254
+
255
+ ```python
256
+ pms = PMSBasic(
257
+ load_threshold_start=0.80, # Start at 80% of running capacity
258
+ load_threshold_stop=0.35, # Stop when below 35% of capacity
259
+ min_gensets_running=1 # Always keep 1 running
260
+ )
261
+ ```
262
+
263
+ **Behavior:**
264
+ - Load increases → Start additional gensets when threshold exceeded
265
+ - Load decreases → Stop gensets when load drops
266
+ - Prevents frequent switching with hysteresis
267
+ - Maintains spinning reserve
268
+
269
+ ### Strategy 2: Time-Based Control
270
+
271
+ Control gensets based on time of day or operational mode:
272
+
273
+ ```python
274
+ # Define mode schedule
275
+ mode_schedule = pd.DataFrame({
276
+ 'time': [0, 21600, 43200, 64800], # 0h, 6h, 12h, 18h
277
+ 'mode': ['port', 'transit', 'transit', 'port']
278
+ })
279
+
280
+ # Different genset configurations per mode
281
+ genset_config = {
282
+ 'port': [True, False, False], # 1 genset
283
+ 'transit': [True, True, False], # 2 gensets
284
+ 'maneuvering': [True, True, True] # 3 gensets
285
+ }
286
+ ```
287
+
288
+ ### Strategy 3: Efficiency Optimization
289
+
290
+ Run gensets at optimal load points:
291
+
292
+ ```python
293
+ pms = PMSBasic(
294
+ load_threshold_start=0.75, # Target 75% load on running gensets
295
+ load_threshold_stop=0.40,
296
+ min_gensets_running=1
297
+ )
298
+ ```
299
+
300
+ **Benefits:**
301
+ - Operates gensets in efficient range (70-85%)
302
+ - Minimizes fuel consumption
303
+ - Reduces emissions
304
+
305
+ ## Development Workflow
306
+
307
+ RunFeemsSim follows standard Python development practices.
308
+
309
+ ### Package Structure
310
+
311
+ ```
312
+ RunFEEMSSim/
313
+ ├── RunFeemsSim/
314
+ │ ├── __init__.py
315
+ │ ├── machinery_calculation.py # Core simulation logic
316
+ │ ├── pms_basic.py # Power Management System
317
+ │ └── utils.py # Utility functions
318
+ ├── tests/
319
+ │ ├── test_machinery_calculation.py
320
+ │ └── test_pms_basic.py
321
+ ├── README.md
322
+ └── pyproject.toml
323
+ ```
324
+
325
+ ### Development Cycle
326
+
327
+ 1. **Edit Python Files**: Make changes directly in `.py` files
328
+ ```bash
329
+ # Edit source files in your preferred editor/IDE
330
+ vim RunFeemsSim/machinery_calculation.py
331
+ ```
332
+
333
+ 2. **Run Tests**: Test your changes
334
+ ```bash
335
+ uv run pytest RunFEEMSSim/tests/
336
+ ```
337
+
338
+ 3. **Lint and Format**: Ensure code quality
339
+ ```bash
340
+ uv run ruff check RunFEEMSSim/
341
+ uv run ruff format RunFEEMSSim/
342
+ ```
343
+
344
+ 4. **Type Check**: Validate type hints (optional)
345
+ ```bash
346
+ uv run mypy RunFeemsSim/
347
+ ```
348
+
349
+ 5. **Build**: Create distribution packages
350
+ ```bash
351
+ cd RunFEEMSSim
352
+ uv build
353
+ ```
354
+
355
+ ### Why Pure Python?
356
+
357
+ - **Simplicity**: Standard Python package structure everyone knows
358
+ - **IDE Support**: Full autocomplete, refactoring, and debugging
359
+ - **Type Safety**: Use mypy and type hints effectively
360
+ - **Flexibility**: Easy integration with any Python tooling
361
+ - **Transparency**: Source code is exactly what gets executed
362
+
363
+ ## Use Cases
364
+
365
+ ### 1. Route Planning
366
+
367
+ Estimate fuel consumption for planned voyages:
368
+
369
+ ```python
370
+ # Load route profile
371
+ route_profile = pd.read_csv('route_profile.csv') # time, speed, power
372
+
373
+ # Run simulation
374
+ machinery_calc = MachineryCalculation(system)
375
+ result = machinery_calc.calculate_machinery_system_output_from_propulsion_power_time_series(
376
+ propulsion_power=route_profile[['power']],
377
+ auxiliary_power_kw=route_profile['aux_power'].values
378
+ )
379
+
380
+ # Estimate fuel for voyage
381
+ fuel_kg = result.multi_fuel_consumption_total_kg.fuels[0].mass_or_mass_fraction
382
+ distance_nm = route_profile['distance'].sum()
383
+ fuel_per_nm = fuel_kg / distance_nm
384
+ ```
385
+
386
+ ### 2. Emissions Reporting
387
+
388
+ Generate IMO/EU compliance reports:
389
+
390
+ ```python
391
+ # Annual operation
392
+ annual_result = machinery_calc.calculate_machinery_system_output_from_propulsion_power_time_series(
393
+ propulsion_power=annual_profile,
394
+ auxiliary_power_kw=annual_aux,
395
+ fuel_specified_by=FuelSpecifiedBy.FUEL_EU_MARITIME
396
+ )
397
+
398
+ # FuelEU Maritime compliance
399
+ well_to_wake_co2 = annual_result.co2_emission_total_kg.well_to_wake_kg_or_gco2eq_per_gfuel
400
+ energy_consumed = annual_result.energy_consumption_propulsion_total_mj
401
+ ghg_intensity = well_to_wake_co2 / (energy_consumed / 1000) # gCO2eq/MJ
402
+
403
+ print(f"GHG Intensity: {ghg_intensity:.2f} gCO2eq/MJ")
404
+ ```
405
+
406
+ ### 3. System Comparison
407
+
408
+ Compare different configurations:
409
+
410
+ ```python
411
+ # Scenario 1: Conventional (3 gensets)
412
+ system_conventional = create_conventional_system()
413
+ calc_conv = MachineryCalculation(system_conventional)
414
+ result_conv = calc_conv.calculate_machinery_system_output_from_propulsion_power_time_series(...)
415
+
416
+ # Scenario 2: Hybrid (2 gensets + battery)
417
+ system_hybrid = create_hybrid_system()
418
+ calc_hybrid = MachineryCalculation(system_hybrid)
419
+ result_hybrid = calc_hybrid.calculate_machinery_system_output_from_propulsion_power_time_series(...)
420
+
421
+ # Compare
422
+ fuel_savings = result_conv.multi_fuel_consumption_total_kg.fuels[0].mass_or_mass_fraction - \
423
+ result_hybrid.multi_fuel_consumption_total_kg.fuels[0].mass_or_mass_fraction
424
+ savings_pct = (fuel_savings / result_conv.multi_fuel_consumption_total_kg.fuels[0].mass_or_mass_fraction) * 100
425
+
426
+ print(f"Hybrid system saves {fuel_savings:.1f} kg ({savings_pct:.1f}%)")
427
+ ```
428
+
429
+ ### 4. PMS Optimization
430
+
431
+ Tune PMS parameters:
432
+
433
+ ```python
434
+ import matplotlib.pyplot as plt
435
+
436
+ # Test different thresholds
437
+ thresholds = [0.70, 0.75, 0.80, 0.85]
438
+ results = {}
439
+
440
+ for threshold in thresholds:
441
+ pms = PMSBasic(load_threshold_start=threshold)
442
+ calc = MachineryCalculation(system, pms=pms)
443
+ result = calc.calculate_machinery_system_output_from_propulsion_power_time_series(...)
444
+ results[threshold] = result
445
+
446
+ # Plot fuel consumption vs. threshold
447
+ fuel_consumptions = [r.multi_fuel_consumption_total_kg.fuels[0].mass_or_mass_fraction
448
+ for r in results.values()]
449
+ plt.plot(thresholds, fuel_consumptions)
450
+ plt.xlabel('Load Threshold')
451
+ plt.ylabel('Fuel Consumption (kg)')
452
+ plt.title('PMS Threshold Optimization')
453
+ plt.show()
454
+ ```
455
+
456
+ ## Package Structure
457
+
458
+ ```
459
+ RunFEEMSSim/
460
+ ├── RunFeemsSim/
461
+ │ ├── __init__.py
462
+ │ ├── machinery_calculation.py # Core simulation interface
463
+ │ ├── pms_basic.py # Power Management System
464
+ │ └── utils.py # Helper utilities
465
+ ├── tests/
466
+ │ ├── test_machinery_calculation.py
467
+ │ └── test_pms_basic.py
468
+ ├── docs/ # Documentation
469
+ ├── README.md
470
+ └── pyproject.toml
471
+ ```
472
+
473
+ ## Requirements
474
+
475
+ - Python ≥ 3.10
476
+ - pandas
477
+ - numpy
478
+ - MachSysS
479
+ - feems
480
+
481
+ ## Related Packages
482
+
483
+ - **feems**: Core FEEMS library
484
+ - **MachSysS**: Data structures and protobuf definitions
485
+
486
+ ## Contributing
487
+
488
+ Contributions welcome! See `CONTRIBUTING.md`.
489
+
490
+ ### Development Setup
491
+
492
+ ```bash
493
+ git clone https://github.com/SINTEF/FEEMS.git
494
+ cd FEEMS
495
+ uv sync
496
+ ```
497
+
498
+ ### Making Changes
499
+
500
+ 1. **Edit Python files** directly in `RunFeemsSim/`
501
+ 2. **Add tests** in `tests/`
502
+ 3. **Run tests**: `uv run pytest RunFEEMSSim/tests/`
503
+ 4. **Lint code**: `uv run ruff check RunFEEMSSim/`
504
+ 5. **Format code**: `uv run ruff format RunFEEMSSim/`
505
+ 6. **Type check** (optional): `uv run mypy RunFeemsSim/`
506
+
507
+ ### Running Tests
508
+
509
+ ```bash
510
+ # All tests
511
+ uv run pytest RunFEEMSSim/tests/
512
+
513
+ # Specific test file
514
+ uv run pytest RunFEEMSSim/tests/test_machinery_calculation.py
515
+
516
+ # With coverage
517
+ uv run pytest --cov=RunFeemsSim RunFEEMSSim/tests/
518
+
519
+ # Verbose output
520
+ uv run pytest -v RunFEEMSSim/tests/
521
+ ```
522
+
523
+ ### Code Quality
524
+
525
+ ```bash
526
+ # Check for issues
527
+ uv run ruff check RunFEEMSSim/
528
+
529
+ # Auto-fix issues
530
+ uv run ruff check --fix RunFEEMSSim/
531
+
532
+ # Format code
533
+ uv run ruff format RunFEEMSSim/
534
+
535
+ # Type checking
536
+ uv run mypy RunFeemsSim/
537
+ ```
538
+
539
+ ## License
540
+
541
+ Licensed under the Apache License 2.0 - see LICENSE file for details.
542
+
543
+ ## Citation
544
+
545
+ ```bibtex
546
+ @software{runfeemssim2024,
547
+ title = {RunFeemsSim: FEEMS Simulation Runner},
548
+ author = {Yum, Kevin Koosup and contributors},
549
+ year = {2024},
550
+ url = {https://github.com/SINTEF/FEEMS}
551
+ }
552
+ ```
553
+
554
+ ## Support
555
+
556
+ - **Issues**: [GitHub Issues](https://github.com/SINTEF/FEEMS/issues)
557
+ - **Documentation**: [https://kevinkoosup.yum@sintef.no.github.io/RunFeemsSim/](https://kevinkoosup.yum@sintef.no.github.io/RunFeemsSim/)
558
+ - **Email**: kevinkoosup.yum@sintef.no
559
+
560
+ ## Acknowledgments
561
+
562
+ Developed by SINTEF Ocean as part of the FEEMS ecosystem for simplified marine power system simulation.