EnergySystemModels 20260416003__tar.gz → 20260416005__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.
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/PKG-INFO +1 -1
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/setup.py +1 -1
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PV/ProductionElectriquePV.py +158 -57
- energysystemmodels-20260416005/src/ThermodynamicCycles/Combustion/NG_Boiler_Efficiency_EN1295X.py +292 -0
- energysystemmodels-20260416005/src/ThermodynamicCycles/Combustion/NG_Heating_Value.py +131 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/energysystemmodels.egg-info/PKG-INFO +1 -1
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/energysystemmodels.egg-info/SOURCES.txt +2 -1
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/energysystemmodels.egg-info/top_level.txt +0 -1
- energysystemmodels-20260416003/src/EnergySystemModels/__init__.py +0 -35
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/LICENSE +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/README.md +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/setup.cfg +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/AirPort/AirPort.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/AirPort/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/Coil/CoolingCoil.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/Coil/CoolingCoil_Expert.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/Coil/CoolingCoil_Sensible.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/Coil/CoolingCoil_Tc.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/Coil/HeatingCoil.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/Coil/HeatingCoilNUT.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/Coil/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/Connect.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/FreshAir/AirMix.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/FreshAir/FreshAir.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/FreshAir/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/GenericAHU/AirRecoveryAHU.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/GenericAHU/AirRecyclingAHU.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/GenericAHU/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/HeatRecovery/Heat_plate_exchanger.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/HeatRecovery/Thermal_wheel_exchanger.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/HeatRecovery/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/Humidification/Humidifier.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/Humidification/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/air_humide/PsychrometricChart.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/air_humide/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/air_humide/air_humide.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/AHU/air_humide/air_humide_NB.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/CEE/CEE.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/CEE/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Distillation/Deethanizer.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Distillation/PengRobinson.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Distillation/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Distillation/diag_enthalpy_models.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Distillation/reverse_engineer_enthalpies.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/ATR_Transport_Distribution.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/SONALGAZ_Elec.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/SONALGAZ_gaz.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/TURPE.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/coefficients_elec.json +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/coefficients_gaz_ATRD.json +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/coefficients_gaz_ATRT.json +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/coefficients_gaz_TICGN.json +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/coefficients_gaz_TVA.json +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/coefficients_sonalgaz_elec.json +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/coefficients_sonalgaz_gaz.json +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/df_utils.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/Facture/test.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/HeatTransfer/CompositeWall.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/HeatTransfer/ParallelepipedicBody.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/HeatTransfer/PipeInsulationAnalysis.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/HeatTransfer/PlateHeatTransfer.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/HeatTransfer/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/IPMVP/IPMVP.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/IPMVP/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/MeteoCiel/DJU_costic.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/MeteoCiel/MeteoCiel_Scraping.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/MeteoCiel/MeteoCiel_dayScraping.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/MeteoCiel/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_content_widget.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_edge.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_edge_dragging.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_edge_validators.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_editor_widget.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_editor_window.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_graphics_cutline.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_graphics_edge.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_graphics_edge_path.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_graphics_node.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_graphics_scene.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_graphics_socket.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_graphics_view.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_node.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_scene.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_scene_clipboard.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_scene_history.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_serializable.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/node_socket.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/nodeeditor/utils.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/setup.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/tests/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/tests/test_000_import.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/NodeEditor/tox.ini +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/OpenWeatherMap/OpenWeatherMap_call.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/OpenWeatherMap/OpenWeatherMap_call_location.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/OpenWeatherMap/SQlite_OpenWeatherMap.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/OpenWeatherMap/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/OpenWeatherMap/config.ini +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/OpenWeatherMap/config_historical.ini +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/OpenWeatherMap/data.json +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/OpenWeatherMap/get_weather.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PV/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/PinchAnalysis.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/Two_flow_pinch_analysis.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/apply_heat_exchange_above.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/apply_heat_exchange_below.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/calculation_HEN.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/calculation_allowed_combinations.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/calculation_below_above_stream.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/calculation_composite_curve.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/calculation_decomposition.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/calculation_graphical_HEN.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/calculation_surplus_deficit.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/check_additional_heat_exchanges.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/draw_hen_from_df.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PinchAnalysis/functions/plotting.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/calc_conf.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/calc_drag_listbox.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/calc_node_base.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/calc_sub_window.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/calc_window.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/config.ini +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/main.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/Simple_HEX.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/air_input.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/air_mixer.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/air_output.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/compressor.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/compressor_m.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/condenser.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/cooling_coil.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/cooling_coil_expert.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/cooling_coil_sensible.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/desuperheater.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/evaporator.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/expansion_valve.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/heating_coil.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/humidificateur.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/input.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/operations.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/output.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/random_meteo.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/source_P_h.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PyqtSimulator/nodes/turbine.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Aeraulic/StraightPipe.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Aeraulic/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Carnot_Cycle_Analysis.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Chiller.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Combustion/Combustor_cantera.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Combustion/Gaz_Boiler.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Combustion/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Compressor/Compressor.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Compressor/Compressor_m.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Compressor/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Condenser/Condenser.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Condenser/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Connect.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Desuperheater/Desuperheater.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Desuperheater/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Evaporator/Evaporator.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Evaporator/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Expansion_Valve/Expansion_Valve.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Expansion_Valve/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/FluidPort/FluidPort.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/FluidPort/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/HEX/AirCooled_HEX.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/HEX/DTLM_HEX.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/HEX/NUT_HEX.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/HEX/Simple_HEX.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/HEX/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Hydraulic/StraightPipe.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Hydraulic/TA_Valve.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Hydraulic/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Pump/Pump.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Pump/Pump_m.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Pump/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Sink/Sink.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Sink/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Source/Source.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Source/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Tank/MixedStorage.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Tank/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Temperature_Entropy_Chart.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Turbine/Turbine.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/Turbine/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/ThermodynamicCycles/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/TkinterGUI/Chiller.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/TkinterGUI/__init__.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/energysystemmodels.egg-info/dependency_links.txt +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/energysystemmodels.egg-info/requires.txt +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/test/test_api_diagnostic.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/test/test_api_key.py +0 -0
- {energysystemmodels-20260416003 → energysystemmodels-20260416005}/test/test_compare_keys.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: energysystemmodels
|
|
3
|
-
Version:
|
|
3
|
+
Version: 20260416005
|
|
4
4
|
Summary: Energy systems models are the mathematical models that are developed in order to represent as reliably as possible various energy-related problems.
|
|
5
5
|
Author: Zoheir HADID
|
|
6
6
|
Author-email: zoheir.hadid@gmail.com
|
|
@@ -11,7 +11,7 @@ setup(
|
|
|
11
11
|
name='energysystemmodels',
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
version='
|
|
14
|
+
version='20260416005',
|
|
15
15
|
|
|
16
16
|
description='Energy systems models are the mathematical models that are developed in order to represent as reliably as possible various energy-related problems.',
|
|
17
17
|
|
{energysystemmodels-20260416003 → energysystemmodels-20260416005}/src/PV/ProductionElectriquePV.py
RENAMED
|
@@ -121,7 +121,7 @@ class SolarSystem:
|
|
|
121
121
|
self.ac = pvlib.inverter.sandia(self.dc['v_mp'], self.dc['p_mp'], self.inverter)
|
|
122
122
|
#print("puissance CA (courant alternatif)", self.ac)
|
|
123
123
|
# Calcul de l'énergie annuelle
|
|
124
|
-
self.annual_energy =
|
|
124
|
+
self.annual_energy = self.ac.sum()
|
|
125
125
|
|
|
126
126
|
module_area = self.module['Area'] if self.module is not None else 0
|
|
127
127
|
module_wc = self.module['Impo'] * self.module['Vmpo'] if self.module is not None else 0
|
|
@@ -148,30 +148,26 @@ class SolarSystem:
|
|
|
148
148
|
'Productivite (kWh/kWc/an)',
|
|
149
149
|
])
|
|
150
150
|
|
|
151
|
-
def summary(self, nb_modules=1, module_wc=None,
|
|
152
|
-
|
|
151
|
+
def summary(self, nb_modules=1, module_wc=None,
|
|
152
|
+
capex_eur_m2=None, opex_eur_m2=None,
|
|
153
|
+
tarif_elec_eur_mwh=None, duree_vie=25):
|
|
153
154
|
"""Retourne un DataFrame de synthese technique et economique.
|
|
154
155
|
|
|
155
156
|
Parameters
|
|
156
157
|
----------
|
|
157
158
|
nb_modules : int
|
|
158
|
-
Nombre de modules dans l'installation
|
|
159
|
+
Nombre de modules dans l'installation.
|
|
159
160
|
module_wc : float or None
|
|
160
|
-
Puissance crete d'un module en Wc.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
Cout d'exploitation annuel (EUR/
|
|
166
|
-
tarif_elec_eur_mwh : float
|
|
167
|
-
Prix de l'electricite
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
Returns
|
|
172
|
-
-------
|
|
173
|
-
pd.DataFrame
|
|
174
|
-
Tableau a deux colonnes (Indicateur, Valeur).
|
|
161
|
+
Puissance crete d'un module en Wc.
|
|
162
|
+
capex_eur_m2 : float or None
|
|
163
|
+
Cout d'investissement par m2 de panneau installe (EUR/m2).
|
|
164
|
+
Si None, pas d'analyse economique.
|
|
165
|
+
opex_eur_m2 : float or None
|
|
166
|
+
Cout d'exploitation annuel par m2 (EUR/m2/an).
|
|
167
|
+
tarif_elec_eur_mwh : float or None
|
|
168
|
+
Prix de l'electricite valorisee (EUR/MWh).
|
|
169
|
+
duree_vie : int
|
|
170
|
+
Duree de vie du projet en annees (defaut 25 ans).
|
|
175
171
|
"""
|
|
176
172
|
if module_wc is None:
|
|
177
173
|
module_wc = self.module['Impo'] * self.module['Vmpo']
|
|
@@ -183,18 +179,9 @@ class SolarSystem:
|
|
|
183
179
|
module_area = self.module['Area'] if self.module is not None else 1.65
|
|
184
180
|
surface_m2 = nb_modules * module_area
|
|
185
181
|
|
|
186
|
-
capex = puissance_kwc * capex_eur_kwc
|
|
187
|
-
opex = puissance_kwc * opex_eur_kwc
|
|
188
|
-
eco_annuelle = prod_totale_mwh * taux_autoconso * tarif_elec_eur_mwh
|
|
189
|
-
gain_net = eco_annuelle - opex
|
|
190
|
-
tri = capex / gain_net if gain_net > 0 else np.inf
|
|
191
|
-
|
|
192
182
|
rows = [
|
|
183
|
+
("--- SIMULATION ---", ""),
|
|
193
184
|
("Site", self.name),
|
|
194
|
-
("Latitude", f"{self.latitude:.3f} deg"),
|
|
195
|
-
("Longitude", f"{self.longitude:.3f} deg"),
|
|
196
|
-
("Azimut", f"{self.azimut} deg"),
|
|
197
|
-
("Inclinaison", f"{self.inclinaison} deg"),
|
|
198
185
|
("Module", self.module.name if self.module is not None else "N/A"),
|
|
199
186
|
("Surface module", f"{module_area:.3f} m2"),
|
|
200
187
|
("Nb modules", nb_modules),
|
|
@@ -203,15 +190,106 @@ class SolarSystem:
|
|
|
203
190
|
("Production / module", f"{prod_module_kwh:.1f} kWh/an"),
|
|
204
191
|
("Productivite specifique", f"{productivite:.0f} kWh/kWc/an"),
|
|
205
192
|
("Production totale", f"{prod_totale_mwh:.1f} MWh/an"),
|
|
206
|
-
("Taux autoconsommation", f"{taux_autoconso*100:.0f} %"),
|
|
207
|
-
("CAPEX", f"{capex/1000:.0f} kEUR"),
|
|
208
|
-
("OPEX annuel", f"{opex/1000:.1f} kEUR/an"),
|
|
209
|
-
("Economies annuelles", f"{eco_annuelle/1000:.1f} kEUR/an"),
|
|
210
|
-
("Gain net annuel", f"{gain_net/1000:.1f} kEUR/an"),
|
|
211
|
-
("TRI simple", f"{tri:.1f} ans"),
|
|
212
193
|
]
|
|
194
|
+
|
|
195
|
+
if all(v is not None for v in [capex_eur_m2, opex_eur_m2,
|
|
196
|
+
tarif_elec_eur_mwh]):
|
|
197
|
+
capex = surface_m2 * capex_eur_m2
|
|
198
|
+
opex = surface_m2 * opex_eur_m2
|
|
199
|
+
valorisation = prod_totale_mwh * tarif_elec_eur_mwh
|
|
200
|
+
gain_net = valorisation - opex
|
|
201
|
+
payback = capex / gain_net if gain_net > 0 else np.inf
|
|
202
|
+
roi = ((gain_net * duree_vie - capex) / capex * 100) if capex > 0 else 0
|
|
203
|
+
|
|
204
|
+
# TRI : taux r tel que sum(gain_net/(1+r)^t, t=1..N) = capex
|
|
205
|
+
tri = 0.0
|
|
206
|
+
if gain_net > 0 and capex > 0:
|
|
207
|
+
from scipy.optimize import brentq
|
|
208
|
+
def npv(r):
|
|
209
|
+
return sum(gain_net / (1 + r) ** t
|
|
210
|
+
for t in range(1, duree_vie + 1)) - capex
|
|
211
|
+
try:
|
|
212
|
+
tri = brentq(npv, -0.5, 5.0) * 100
|
|
213
|
+
except Exception:
|
|
214
|
+
tri = 0.0
|
|
215
|
+
|
|
216
|
+
rows += [
|
|
217
|
+
("--- HYPOTHESES ECO ---", ""),
|
|
218
|
+
("CAPEX", f"{capex_eur_m2} EUR/m2"),
|
|
219
|
+
("OPEX", f"{opex_eur_m2} EUR/m2/an"),
|
|
220
|
+
("Tarif electricite", f"{tarif_elec_eur_mwh} EUR/MWh"),
|
|
221
|
+
("Duree de vie", f"{duree_vie} ans"),
|
|
222
|
+
("--- RESULTATS ECO ---", ""),
|
|
223
|
+
("Investissement", f"{capex/1000:.0f} kEUR"),
|
|
224
|
+
("Valorisation annuelle", f"{valorisation/1000:.1f} kEUR/an"),
|
|
225
|
+
("OPEX annuel", f"{opex/1000:.1f} kEUR/an"),
|
|
226
|
+
("Gain net annuel", f"{gain_net/1000:.1f} kEUR/an"),
|
|
227
|
+
("Payback", f"{payback:.1f} ans"),
|
|
228
|
+
("ROI ({0} ans)".format(duree_vie), f"{roi:.0f} %"),
|
|
229
|
+
("TRI", f"{tri:.1f} %"),
|
|
230
|
+
]
|
|
231
|
+
|
|
213
232
|
return pd.DataFrame(rows, columns=["Indicateur", "Valeur"])
|
|
214
233
|
|
|
234
|
+
def plot(self, figsize=(14, 5), nb_modules=1):
|
|
235
|
+
"""Trace la production horaire AC et le profil mensuel."""
|
|
236
|
+
ac_kw = self.ac * nb_modules / 1000
|
|
237
|
+
|
|
238
|
+
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=figsize)
|
|
239
|
+
|
|
240
|
+
ax1.plot(ac_kw.values, linewidth=0.3)
|
|
241
|
+
ax1.set_xlabel('Heure de l\'annee')
|
|
242
|
+
ax1.set_ylabel('Production AC (kW)')
|
|
243
|
+
ax1.set_title(f'{self.name} - Production horaire ({nb_modules} modules)')
|
|
244
|
+
ax1.grid(True, alpha=0.3)
|
|
245
|
+
|
|
246
|
+
monthly = ac_kw.resample('ME').sum()
|
|
247
|
+
total_mwh = abs(ac_kw.sum()) / 1000
|
|
248
|
+
ax2.bar(range(len(monthly)), monthly.values, color='orange')
|
|
249
|
+
ax2.set_xticks(range(len(monthly)))
|
|
250
|
+
ax2.set_xticklabels(['J','F','M','A','M','J','J','A','S','O','N','D'][:len(monthly)])
|
|
251
|
+
ax2.set_ylabel('Production mensuelle (kWh)')
|
|
252
|
+
ax2.set_title(f'{self.name} - Profil mensuel | Total : {total_mwh:.1f} MWh/an')
|
|
253
|
+
ax2.grid(axis='y', alpha=0.3)
|
|
254
|
+
|
|
255
|
+
plt.tight_layout()
|
|
256
|
+
plt.show()
|
|
257
|
+
return fig
|
|
258
|
+
|
|
259
|
+
def to_excel(self, filename=None, nb_modules=1):
|
|
260
|
+
"""Exporte la production horaire en fichier Excel.
|
|
261
|
+
|
|
262
|
+
Parameters
|
|
263
|
+
----------
|
|
264
|
+
filename : str or None
|
|
265
|
+
Chemin du fichier. Si None, genere '{name}_production.xlsx'.
|
|
266
|
+
nb_modules : int
|
|
267
|
+
Nombre de modules (defaut 1).
|
|
268
|
+
|
|
269
|
+
Returns
|
|
270
|
+
-------
|
|
271
|
+
str
|
|
272
|
+
Chemin du fichier cree.
|
|
273
|
+
"""
|
|
274
|
+
if filename is None:
|
|
275
|
+
filename = f"{self.name.replace(' ', '_')}_production.xlsx"
|
|
276
|
+
|
|
277
|
+
df_export = pd.DataFrame({
|
|
278
|
+
'Production_AC_kW': self.ac * nb_modules / 1000,
|
|
279
|
+
'Irradiance_POA_W_m2': self.total_irradiance['poa_global'],
|
|
280
|
+
'T_cellule_C': self.cell_temperature,
|
|
281
|
+
'T_air_C': self.weather['temp_air'],
|
|
282
|
+
})
|
|
283
|
+
df_export.index.name = 'datetime_utc'
|
|
284
|
+
|
|
285
|
+
with pd.ExcelWriter(filename, engine='openpyxl') as writer:
|
|
286
|
+
df_export.to_excel(writer, sheet_name='Horaire')
|
|
287
|
+
df_export.resample('ME').sum().to_excel(writer, sheet_name='Mensuel')
|
|
288
|
+
self.df.to_excel(writer, sheet_name='Synthese')
|
|
289
|
+
|
|
290
|
+
print(f"Export : {filename}")
|
|
291
|
+
return filename
|
|
292
|
+
|
|
215
293
|
def plot_annual_energy(self):
|
|
216
294
|
energies = pd.Series({self.name: self.annual_energy})
|
|
217
295
|
energies.plot(kind='bar', rot=0)
|
|
@@ -219,7 +297,7 @@ class SolarSystem:
|
|
|
219
297
|
|
|
220
298
|
@staticmethod
|
|
221
299
|
def orientation_study(latitude, longitude, name, altitude, timezone,
|
|
222
|
-
scenarios
|
|
300
|
+
scenarios):
|
|
223
301
|
"""Etude parametrique d'orientation et d'inclinaison.
|
|
224
302
|
|
|
225
303
|
Parameters
|
|
@@ -228,16 +306,17 @@ class SolarSystem:
|
|
|
228
306
|
Parametres du site (identiques a __init__).
|
|
229
307
|
scenarios : list[dict]
|
|
230
308
|
Liste de dicts avec cles 'nom', 'azimut', 'inclinaison'.
|
|
231
|
-
Exemple : [{'nom': 'Sud 35', 'azimut': 180, 'inclinaison': 35}]
|
|
232
|
-
save_fig : str or None
|
|
233
|
-
Chemin du fichier image a sauvegarder. Si None, pas de sauvegarde.
|
|
234
309
|
|
|
235
310
|
Returns
|
|
236
311
|
-------
|
|
237
|
-
pd.DataFrame
|
|
312
|
+
df : pd.DataFrame
|
|
238
313
|
Tableau comparatif trie par production decroissante.
|
|
314
|
+
df_monthly : pd.DataFrame
|
|
315
|
+
Production mensuelle (kWh/kWc) par scenario (colonnes)
|
|
316
|
+
et par mois (index).
|
|
239
317
|
"""
|
|
240
318
|
resultats = []
|
|
319
|
+
monthly_data = {}
|
|
241
320
|
for sc in scenarios:
|
|
242
321
|
pv = SolarSystem(
|
|
243
322
|
latitude=latitude, longitude=longitude,
|
|
@@ -246,12 +325,15 @@ class SolarSystem:
|
|
|
246
325
|
azimut=sc['azimut'], inclinaison=sc['inclinaison']
|
|
247
326
|
)
|
|
248
327
|
pv.retrieve_module_inverter_data()
|
|
249
|
-
pv.retrieve_weather_data()
|
|
250
328
|
pv.calculate_solar_parameters()
|
|
251
329
|
|
|
252
330
|
module_wc = pv.module['Impo'] * pv.module['Vmpo']
|
|
253
|
-
|
|
331
|
+
ac_kwh_kwc = pv.ac / module_wc
|
|
332
|
+
monthly = ac_kwh_kwc.resample('ME').sum()
|
|
333
|
+
monthly.index = range(1, len(monthly) + 1)
|
|
334
|
+
monthly_data[sc['nom']] = monthly
|
|
254
335
|
|
|
336
|
+
prod_kwh_kwc = pv.annual_energy / 1000 / (module_wc / 1000)
|
|
255
337
|
resultats.append({
|
|
256
338
|
'Configuration': sc['nom'],
|
|
257
339
|
'Azimut (deg)': sc['azimut'],
|
|
@@ -267,23 +349,42 @@ class SolarSystem:
|
|
|
267
349
|
df = df.sort_values('Production (kWh/kWc/an)', ascending=False)
|
|
268
350
|
df = df.reset_index(drop=True)
|
|
269
351
|
|
|
270
|
-
|
|
352
|
+
df_monthly = pd.DataFrame(monthly_data)
|
|
353
|
+
return df, df_monthly
|
|
354
|
+
|
|
355
|
+
@staticmethod
|
|
356
|
+
def plot_orientation_study(df, df_monthly, name='', save_fig=None):
|
|
357
|
+
"""Trace les profils mensuels par orientation.
|
|
358
|
+
|
|
359
|
+
Parameters
|
|
360
|
+
----------
|
|
361
|
+
df : pd.DataFrame
|
|
362
|
+
Resultat de orientation_study() (tableau annuel).
|
|
363
|
+
df_monthly : pd.DataFrame
|
|
364
|
+
Profils mensuels par scenario.
|
|
365
|
+
name : str
|
|
366
|
+
Nom du site (pour le titre).
|
|
367
|
+
save_fig : str or None
|
|
368
|
+
Chemin fichier image. Si None, pas de sauvegarde.
|
|
369
|
+
"""
|
|
271
370
|
fig, ax = plt.subplots(figsize=(12, 6))
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
ax.
|
|
281
|
-
|
|
282
|
-
ax.
|
|
283
|
-
ax.
|
|
371
|
+
mois_labels = ['Jan','Fev','Mar','Avr','Mai','Jun',
|
|
372
|
+
'Jul','Aou','Sep','Oct','Nov','Dec']
|
|
373
|
+
totaux = df.set_index('Configuration')['Production (kWh/kWc/an)']
|
|
374
|
+
for col in df_monthly.columns:
|
|
375
|
+
total = totaux.get(col, df_monthly[col].sum())
|
|
376
|
+
ax.plot(df_monthly.index, df_monthly[col], 'o-',
|
|
377
|
+
linewidth=1.5, markersize=4,
|
|
378
|
+
label=f'{col} ({total:.0f} kWh/kWc/an)')
|
|
379
|
+
ax.set_xticks(range(1, len(df_monthly) + 1))
|
|
380
|
+
ax.set_xticklabels(mois_labels[:len(df_monthly)])
|
|
381
|
+
ax.set_xlabel('Mois')
|
|
382
|
+
ax.set_ylabel('Production mensuelle (kWh/kWc)')
|
|
383
|
+
ax.set_title(f'Profil mensuel par orientation - {name}')
|
|
384
|
+
ax.legend(fontsize=11)
|
|
385
|
+
ax.grid(True, alpha=0.3)
|
|
284
386
|
fig.tight_layout()
|
|
285
387
|
if save_fig:
|
|
286
388
|
fig.savefig(save_fig, dpi=150)
|
|
287
389
|
plt.show()
|
|
288
|
-
|
|
289
|
-
return df
|
|
390
|
+
return fig
|
energysystemmodels-20260416005/src/ThermodynamicCycles/Combustion/NG_Boiler_Efficiency_EN1295X.py
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import re
|
|
4
|
+
from ThermodynamicCycles.Combustion.NG_Heating_Value import NG_Heating_Value
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class NG_Boiler_Efficiency:
|
|
8
|
+
"""
|
|
9
|
+
EN12952-15 / EN12953-11 indirect method boiler efficiency calculator.
|
|
10
|
+
Computes heat losses (flue gas sensible, CO, radiation, condensation)
|
|
11
|
+
and derives LHV/HHV efficiencies for natural gas boilers.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
R = 8.314510 # J/mol/K
|
|
15
|
+
VMOL = 22.414e-3 # m3/mol at 0C, 101.325 kPa
|
|
16
|
+
T_NTP = 273.15 # K (Normal Temperature 0C)
|
|
17
|
+
P_NTP = 101.325 # kPa
|
|
18
|
+
|
|
19
|
+
# Dry air molar composition
|
|
20
|
+
DRY_AIR = {'CO2': 0.00033, 'O2': 0.20946, 'N2': 0.78102, 'Ar': 0.00919}
|
|
21
|
+
|
|
22
|
+
# Flue gas Cp in kJ/Nm3/K (mean values for typical boiler temperature range)
|
|
23
|
+
FG_CP = {'CO2': 1.7, 'H2O': 1.5, 'N2': 1.3, 'O2': 1.3, 'Ar': 0.93}
|
|
24
|
+
|
|
25
|
+
# Radiation loss constants
|
|
26
|
+
RADIATION_CONSTANT = {'water_tube': 0.0113, 'fire_tube': 0.0072}
|
|
27
|
+
|
|
28
|
+
# CO net calorific value kJ/Nm3
|
|
29
|
+
NCV_CO = 12633.0
|
|
30
|
+
|
|
31
|
+
# Latent heat of water vaporization kJ/kg at 25C
|
|
32
|
+
LATENT_HEAT_WATER = 2442.5
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
gas_composition: dict,
|
|
37
|
+
ng_flow_Nm3h: float,
|
|
38
|
+
ng_temperature_C: float = 25.0,
|
|
39
|
+
ng_LHV_kWh_Nm3: float = None,
|
|
40
|
+
flue_gas_temperature_C: float = 180.0,
|
|
41
|
+
O2_measured: float = 0.035,
|
|
42
|
+
O2_basis: str = 'dry',
|
|
43
|
+
CO_ppm: float = 0.0,
|
|
44
|
+
ambient_temperature_C: float = 25.0,
|
|
45
|
+
ambient_RH: float = 0.5,
|
|
46
|
+
ambient_pressure_mbar: float = 1013.25,
|
|
47
|
+
air_temperature_C: float = None,
|
|
48
|
+
boiler_type: str = 'water_tube',
|
|
49
|
+
design_useful_heat_kW: float = 1000.0,
|
|
50
|
+
electrical_credit_kW: float = 0.0,
|
|
51
|
+
other_heat_credit_kW: float = 0.0,
|
|
52
|
+
T_ref: float = 25.0,
|
|
53
|
+
):
|
|
54
|
+
self.gas_composition = gas_composition
|
|
55
|
+
self.ng_flow = ng_flow_Nm3h
|
|
56
|
+
self.ng_temperature = ng_temperature_C
|
|
57
|
+
self.ng_LHV_kWh_Nm3_input = ng_LHV_kWh_Nm3
|
|
58
|
+
self.T_fg = flue_gas_temperature_C
|
|
59
|
+
self.O2_measured = O2_measured
|
|
60
|
+
self.O2_basis = O2_basis
|
|
61
|
+
self.CO_ppm = CO_ppm
|
|
62
|
+
self.T_amb = ambient_temperature_C
|
|
63
|
+
self.RH = ambient_RH
|
|
64
|
+
self.P_atm = ambient_pressure_mbar * 100.0 # Pa
|
|
65
|
+
self.T_air = air_temperature_C if air_temperature_C is not None else ambient_temperature_C
|
|
66
|
+
self.boiler_type = boiler_type
|
|
67
|
+
self.design_useful_heat_kW = design_useful_heat_kW
|
|
68
|
+
self.electrical_credit = electrical_credit_kW
|
|
69
|
+
self.other_heat_credit = other_heat_credit_kW
|
|
70
|
+
self.T_ref = T_ref
|
|
71
|
+
self.df = None
|
|
72
|
+
|
|
73
|
+
def calculate(self):
|
|
74
|
+
# --- 1. NG properties via NG_Heating_Value ---
|
|
75
|
+
comps = [
|
|
76
|
+
NG_Heating_Value.GasComponent(formula, x)
|
|
77
|
+
for formula, x in self.gas_composition.items()
|
|
78
|
+
]
|
|
79
|
+
ng_props = NG_Heating_Value(comps)
|
|
80
|
+
props_df = ng_props.df
|
|
81
|
+
|
|
82
|
+
def get_prop(name, unit):
|
|
83
|
+
row = props_df[(props_df['Property'] == name) & (props_df['Unit'] == unit)]
|
|
84
|
+
return row['Value'].values[0] if not row.empty else None
|
|
85
|
+
|
|
86
|
+
LHV_kWh = get_prop('LHV vol', 'kWh/Nm3') if self.ng_LHV_kWh_Nm3_input is None else self.ng_LHV_kWh_Nm3_input
|
|
87
|
+
HHV_kWh = get_prop('HHV vol', 'kWh/Nm3')
|
|
88
|
+
density = get_prop('Density real', 'kg/Nm3')
|
|
89
|
+
Cp_mass = ng_props.Cp_mix() # J/kg/K
|
|
90
|
+
|
|
91
|
+
# --- 2. NG heat power ---
|
|
92
|
+
Cp_kWh_Nm3_K = (Cp_mass * density) / 3.6e6 # J/kg/K * kg/Nm3 -> J/Nm3/K -> kWh/Nm3/K
|
|
93
|
+
sensible_heat = Cp_kWh_Nm3_K * (self.ng_temperature - self.T_ref)
|
|
94
|
+
Q_ng_LHV = (LHV_kWh + sensible_heat) * self.ng_flow # kW
|
|
95
|
+
Q_ng_HHV = (HHV_kWh + sensible_heat) * self.ng_flow # kW
|
|
96
|
+
|
|
97
|
+
# --- 3. Ambient air moisture ---
|
|
98
|
+
Psat = 610.78 * np.exp(17.2694 * self.T_amb / (self.T_amb + 237.29)) # Pa
|
|
99
|
+
Pw = self.RH * Psat
|
|
100
|
+
x_H2O_air = Pw / self.P_atm # molar fraction
|
|
101
|
+
|
|
102
|
+
# --- 4-5. Wet air composition ---
|
|
103
|
+
wet_air = {}
|
|
104
|
+
for species, xi in self.DRY_AIR.items():
|
|
105
|
+
wet_air[species] = xi * (1 - x_H2O_air)
|
|
106
|
+
wet_air['H2O'] = x_H2O_air
|
|
107
|
+
|
|
108
|
+
# --- 6. Stoichiometric combustion ---
|
|
109
|
+
stoich_O2 = 0.0 # Nm3 O2 per Nm3 fuel
|
|
110
|
+
stoich_CO2 = 0.0 # Nm3 CO2 produced per Nm3 fuel
|
|
111
|
+
stoich_H2O = 0.0 # Nm3 H2O produced per Nm3 fuel
|
|
112
|
+
stoich_N2_fuel = 0.0
|
|
113
|
+
|
|
114
|
+
for formula, x in self.gas_composition.items():
|
|
115
|
+
if formula == 'N2':
|
|
116
|
+
stoich_N2_fuel += x
|
|
117
|
+
continue
|
|
118
|
+
if formula == 'CO2':
|
|
119
|
+
stoich_CO2 += x
|
|
120
|
+
continue
|
|
121
|
+
if formula == 'H2':
|
|
122
|
+
stoich_O2 += x * 0.5
|
|
123
|
+
stoich_H2O += x * 1.0
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
# Parse CnHm
|
|
127
|
+
clean = formula.replace("n-", "").replace("i-", "").replace("neo-", "")
|
|
128
|
+
matches = re.findall(r'([CHON])(\d*)', clean)
|
|
129
|
+
atoms = {elem: int(num) if num else 1 for elem, num in matches}
|
|
130
|
+
n_C = atoms.get('C', 0)
|
|
131
|
+
n_H = atoms.get('H', 0)
|
|
132
|
+
|
|
133
|
+
if n_C == 0 and n_H == 0:
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
O2_needed = n_C + n_H / 4.0
|
|
137
|
+
stoich_O2 += x * O2_needed
|
|
138
|
+
stoich_CO2 += x * n_C
|
|
139
|
+
stoich_H2O += x * n_H / 2.0
|
|
140
|
+
|
|
141
|
+
# Stoichiometric air (Nm3 air / Nm3 fuel) based on O2 in dry air
|
|
142
|
+
stoich_air = stoich_O2 / self.DRY_AIR['O2']
|
|
143
|
+
|
|
144
|
+
# --- 7. Excess air from O2 measurement ---
|
|
145
|
+
O2_dry_frac = self.O2_measured
|
|
146
|
+
if self.O2_basis == 'wet':
|
|
147
|
+
# Convert wet O2 to dry O2 (approximate)
|
|
148
|
+
# Need iterative approach, but use first approximation
|
|
149
|
+
O2_dry_frac = self.O2_measured / (1 - x_H2O_air)
|
|
150
|
+
|
|
151
|
+
O2_dry_pct = O2_dry_frac * 100.0
|
|
152
|
+
O2_ref_pct = self.DRY_AIR['O2'] * 100.0
|
|
153
|
+
|
|
154
|
+
total_air_ratio = O2_ref_pct / (O2_ref_pct - O2_dry_pct)
|
|
155
|
+
total_air = stoich_air * total_air_ratio # Nm3 wet air / Nm3 fuel
|
|
156
|
+
excess_air_pct = (total_air_ratio - 1) * 100.0
|
|
157
|
+
|
|
158
|
+
# --- 8. Flue gas composition (Nm3 per Nm3 fuel) ---
|
|
159
|
+
fg = {}
|
|
160
|
+
fg['CO2'] = stoich_CO2 + total_air * wet_air.get('CO2', 0)
|
|
161
|
+
fg['H2O'] = stoich_H2O + total_air * wet_air.get('H2O', 0)
|
|
162
|
+
fg['O2'] = total_air * wet_air.get('O2', 0) - stoich_O2
|
|
163
|
+
fg['N2'] = stoich_N2_fuel + total_air * wet_air.get('N2', 0)
|
|
164
|
+
fg['Ar'] = total_air * wet_air.get('Ar', 0)
|
|
165
|
+
|
|
166
|
+
fg_total = sum(fg.values()) # Nm3 flue gas / Nm3 fuel
|
|
167
|
+
fg_dry = fg_total - fg['H2O']
|
|
168
|
+
|
|
169
|
+
# Flue gas flows
|
|
170
|
+
fg_flow = fg_total * self.ng_flow # Nm3/h
|
|
171
|
+
fg_flow_dry = fg_dry * self.ng_flow
|
|
172
|
+
|
|
173
|
+
# H2O volume fraction in flue gas
|
|
174
|
+
x_H2O_fg = fg['H2O'] / fg_total
|
|
175
|
+
|
|
176
|
+
# --- 9-10. Flue gas sensible heat loss ---
|
|
177
|
+
dT = self.T_fg - self.T_ref
|
|
178
|
+
# Weighted Cp of flue gas mixture (kJ/Nm3_mix/K)
|
|
179
|
+
Cp_fg_mix = sum(fg[sp] / fg_total * self.FG_CP.get(sp, 1.3) for sp in fg)
|
|
180
|
+
|
|
181
|
+
flue_gas_loss = fg_flow * Cp_fg_mix * dT / 3600.0 # kW
|
|
182
|
+
|
|
183
|
+
# CO loss
|
|
184
|
+
CO_loss = self.CO_ppm * 1e-6 * fg_flow_dry * self.NCV_CO / 3600.0 # kW
|
|
185
|
+
|
|
186
|
+
# Radiation loss
|
|
187
|
+
k_rad = self.RADIATION_CONSTANT.get(self.boiler_type, 0.0113)
|
|
188
|
+
radiation_loss = k_rad * self.design_useful_heat_kW ** 0.7 # kW
|
|
189
|
+
|
|
190
|
+
# --- 11. Condensation check ---
|
|
191
|
+
# Dew point from H2O partial pressure in flue gas
|
|
192
|
+
P_H2O_fg = x_H2O_fg * self.P_atm # Pa
|
|
193
|
+
# Inverse of Antoine: T_dew = 237.29 * ln(P/610.78) / (17.2694 - ln(P/610.78))
|
|
194
|
+
if P_H2O_fg > 0:
|
|
195
|
+
ln_ratio = np.log(P_H2O_fg / 610.78)
|
|
196
|
+
T_condensation = 237.29 * ln_ratio / (17.2694 - ln_ratio)
|
|
197
|
+
else:
|
|
198
|
+
T_condensation = 0.0
|
|
199
|
+
|
|
200
|
+
condensation_recovery = 0.0
|
|
201
|
+
if self.T_fg < T_condensation:
|
|
202
|
+
# Saturation pressure at flue gas temperature
|
|
203
|
+
Psat_fg = 610.78 * np.exp(17.2694 * self.T_fg / (self.T_fg + 237.29))
|
|
204
|
+
# Maximum H2O that can remain as vapor (mole fraction)
|
|
205
|
+
x_H2O_sat = Psat_fg / self.P_atm
|
|
206
|
+
# Condensed water: difference in Nm3 per Nm3 fuel
|
|
207
|
+
H2O_remaining_vapor = x_H2O_sat / (1 - x_H2O_sat) * (fg_total - fg['H2O'])
|
|
208
|
+
H2O_condensed_Nm3 = max(0, fg['H2O'] - H2O_remaining_vapor) # Nm3/Nm3_fuel
|
|
209
|
+
# Convert to kg: 1 Nm3 H2O = 18.015 / 22.414 = 0.8034 kg
|
|
210
|
+
H2O_condensed_kg_per_Nm3_fuel = H2O_condensed_Nm3 * 18.015 / 22.414
|
|
211
|
+
H2O_condensed_kg_h = H2O_condensed_kg_per_Nm3_fuel * self.ng_flow
|
|
212
|
+
|
|
213
|
+
# Latent heat recovery
|
|
214
|
+
latent_recovery = H2O_condensed_kg_h * self.LATENT_HEAT_WATER / 3600.0 # kW
|
|
215
|
+
# Sensible heat recovery from cooling condensate from T_condensation to T_fg
|
|
216
|
+
sensible_recovery = H2O_condensed_kg_h * 4.18 * (T_condensation - self.T_fg) / 3600.0 # kW
|
|
217
|
+
condensation_recovery = latent_recovery + sensible_recovery
|
|
218
|
+
|
|
219
|
+
# --- 12. Boiler efficiency (indirect method) ---
|
|
220
|
+
heat_credits = self.electrical_credit + self.other_heat_credit
|
|
221
|
+
|
|
222
|
+
# LHV basis
|
|
223
|
+
total_losses_LHV = flue_gas_loss + CO_loss + radiation_loss - condensation_recovery
|
|
224
|
+
efficiency_LHV = 1.0 - total_losses_LHV / (Q_ng_LHV + heat_credits) if (Q_ng_LHV + heat_credits) > 0 else 0.0
|
|
225
|
+
|
|
226
|
+
# HHV basis: flue gas loss must include latent heat of ALL water vapor
|
|
227
|
+
# Additional latent heat = total H2O in flue gas (as vapor) * latent heat
|
|
228
|
+
H2O_vapor_Nm3_h = fg['H2O'] * self.ng_flow # Nm3/h of water vapor
|
|
229
|
+
if self.T_fg < T_condensation:
|
|
230
|
+
H2O_vapor_Nm3_h = H2O_remaining_vapor * self.ng_flow
|
|
231
|
+
H2O_vapor_kg_h = H2O_vapor_Nm3_h * 18.015 / 22.414
|
|
232
|
+
latent_loss_all_water = H2O_vapor_kg_h * self.LATENT_HEAT_WATER / 3600.0 # kW
|
|
233
|
+
|
|
234
|
+
flue_gas_loss_HHV = flue_gas_loss + latent_loss_all_water
|
|
235
|
+
total_losses_HHV = flue_gas_loss_HHV + CO_loss + radiation_loss - condensation_recovery
|
|
236
|
+
efficiency_HHV = 1.0 - total_losses_HHV / (Q_ng_HHV + heat_credits) if (Q_ng_HHV + heat_credits) > 0 else 0.0
|
|
237
|
+
|
|
238
|
+
# --- 13. Useful heat ---
|
|
239
|
+
useful_heat_LHV = efficiency_LHV * Q_ng_LHV + heat_credits
|
|
240
|
+
useful_heat_HHV = efficiency_HHV * Q_ng_HHV + heat_credits
|
|
241
|
+
|
|
242
|
+
# --- Build output DataFrame ---
|
|
243
|
+
rows = [
|
|
244
|
+
('--- INPUTS ---', ''),
|
|
245
|
+
('NG flow (Nm3/h)', round(self.ng_flow, 2)),
|
|
246
|
+
('LHV (kWh/Nm3)', round(LHV_kWh, 4)),
|
|
247
|
+
('HHV (kWh/Nm3)', round(HHV_kWh, 4)),
|
|
248
|
+
('T flue gas (C)', round(self.T_fg, 1)),
|
|
249
|
+
('O2 dry (%)', round(O2_dry_pct, 2)),
|
|
250
|
+
('Boiler type', self.boiler_type),
|
|
251
|
+
('--- COMBUSTION ---', ''),
|
|
252
|
+
('Air/fuel ratio (Nm3/Nm3)', round(total_air, 3)),
|
|
253
|
+
('Excess air (%)', round(excess_air_pct, 1)),
|
|
254
|
+
('Flue gas flow (Nm3/h)', round(fg_flow, 1)),
|
|
255
|
+
('Condensation T (C)', round(T_condensation, 1)),
|
|
256
|
+
('--- HEAT BALANCE (LHV) ---', ''),
|
|
257
|
+
('NG heat input (kW)', round(Q_ng_LHV, 1)),
|
|
258
|
+
('Flue gas loss (kW)', round(flue_gas_loss, 1)),
|
|
259
|
+
('CO loss (kW)', round(CO_loss, 2)),
|
|
260
|
+
('Radiation loss (kW)', round(radiation_loss, 2)),
|
|
261
|
+
('Condensation recovery (kW)', round(condensation_recovery, 2)),
|
|
262
|
+
('Total losses (kW)', round(total_losses_LHV, 1)),
|
|
263
|
+
('Heat credits (kW)', round(heat_credits, 1)),
|
|
264
|
+
('Useful heat (kW)', round(useful_heat_LHV, 1)),
|
|
265
|
+
('Efficiency LHV (%)', round(efficiency_LHV * 100, 2)),
|
|
266
|
+
('--- HEAT BALANCE (HHV) ---', ''),
|
|
267
|
+
('Efficiency HHV (%)', round(efficiency_HHV * 100, 2)),
|
|
268
|
+
]
|
|
269
|
+
|
|
270
|
+
self.df = pd.DataFrame(rows, columns=['Parameter', 'Value'])
|
|
271
|
+
self.df = self.df.set_index('Parameter')
|
|
272
|
+
|
|
273
|
+
# Store key results as attributes for programmatic access
|
|
274
|
+
self.LHV_kWh_Nm3 = LHV_kWh
|
|
275
|
+
self.HHV_kWh_Nm3 = HHV_kWh
|
|
276
|
+
self.Q_ng_LHV = Q_ng_LHV
|
|
277
|
+
self.Q_ng_HHV = Q_ng_HHV
|
|
278
|
+
self.efficiency_LHV = efficiency_LHV
|
|
279
|
+
self.efficiency_HHV = efficiency_HHV
|
|
280
|
+
self.useful_heat_LHV = useful_heat_LHV
|
|
281
|
+
self.useful_heat_HHV = useful_heat_HHV
|
|
282
|
+
self.excess_air_pct = excess_air_pct
|
|
283
|
+
self.air_fuel_ratio = total_air
|
|
284
|
+
self.fg_flow_Nm3h = fg_flow
|
|
285
|
+
self.T_condensation = T_condensation
|
|
286
|
+
self.condensation_recovery = condensation_recovery
|
|
287
|
+
self.flue_gas_loss = flue_gas_loss
|
|
288
|
+
self.radiation_loss = radiation_loss
|
|
289
|
+
self.CO_loss = CO_loss
|
|
290
|
+
self.total_losses_LHV = total_losses_LHV
|
|
291
|
+
|
|
292
|
+
return self.df
|