From ab21a22db0385567e25332171cb89e4d92243874 Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 26 Mar 2024 08:12:35 +0100 Subject: [PATCH 01/28] fixed all issues for the build system and updated feems --- RunFEEMSSim/00_machinery_calculation.ipynb | 44 +- RunFEEMSSim/build_library.sh | 2 +- feems/MANIFEST.in | 1 + .../components_model/component_electric.py | 12 +- .../components_model/component_mechanical.py | 4 +- feems/feems/components_model/node.py | 172 ++-- feems/feems/components_model/utility.py | 15 +- feems/feems/fuel.py | 8 + feems/pyproject.toml | 6 +- feems/readme.md | 15 +- feems/tests/test_components.py | 162 +-- .../test_mechanical_system_simulation.py | 2 +- feems/tests/test_node.py | 6 +- .../00_ConvertToFeems.ipynb | 291 +++--- .../01_ConvertToProtobuf.ipynb | 957 ++++++++++-------- machinery-system-structure/02_Utility.ipynb | 10 +- .../03_ConvertFEEMSResultToProto.ipynb | 216 ++-- .../04_ConvertGymirResultToProto.ipynb | 88 +- ...ConvertTimeSeriesResultProtoToPandas.ipynb | 162 +-- .../MachSysS/convert_feems_result_to_proto.py | 117 ++- .../MachSysS/convert_gymir_result_to_proto.py | 80 +- .../MachSysS/convert_proto_timeseries.py | 61 +- .../MachSysS/convert_to_feems.py | 100 +- .../MachSysS/convert_to_protobuf.py | 385 ++++--- .../MachSysS/feems_result_pb2.py | 1 + .../MachSysS/feems_result_pb2.pyi | 274 +++++ .../MachSysS/gymir_result_pb2.py | 1 + .../MachSysS/gymir_result_pb2.pyi | 179 ++++ .../MachSysS/system_structure_pb2.py | 101 +- .../MachSysS/system_structure_pb2.pyi | 865 ++++++++++++++++ .../MachSysS/utility.py | 4 +- machinery-system-structure/build_package.sh | 7 - .../build_package_linux.sh | 13 + .../build_package_mac.sh | 13 + machinery-system-structure/index.ipynb | 4 +- .../proto/system_structure.proto | 7 + machinery-system-structure/settings.ini | 2 +- machinery-system-structure/setup.py | 9 +- machinery-system-structure/tests/utility.py | 77 +- .../tests/utility_compare_proto.py | 130 ++- requirements_dev.txt | 1 + 41 files changed, 3248 insertions(+), 1356 deletions(-) create mode 100644 feems/MANIFEST.in create mode 100644 machinery-system-structure/MachSysS/feems_result_pb2.pyi create mode 100644 machinery-system-structure/MachSysS/gymir_result_pb2.pyi create mode 100644 machinery-system-structure/MachSysS/system_structure_pb2.pyi delete mode 100644 machinery-system-structure/build_package.sh create mode 100644 machinery-system-structure/build_package_linux.sh create mode 100644 machinery-system-structure/build_package_mac.sh diff --git a/RunFEEMSSim/00_machinery_calculation.ipynb b/RunFEEMSSim/00_machinery_calculation.ipynb index ece1008..b0c67e7 100644 --- a/RunFEEMSSim/00_machinery_calculation.ipynb +++ b/RunFEEMSSim/00_machinery_calculation.ipynb @@ -378,7 +378,6 @@ "metadata": {}, "outputs": [], "source": [ - "import json\n", "import os\n", "import random\n", "import pandas as pd\n", @@ -387,7 +386,9 @@ "from MachSysS.convert_to_feems import convert_proto_propulsion_system_to_feems\n", "from MachSysS.utility import retrieve_machinery_system_from_file\n", "from MachSysS.convert_feems_result_to_proto import FEEMSResultConverter\n", - "from RunFeemsSim.machinery_calculation import MachineryCalculation, convert_gymir_result_to_propulsion_power_series" + "from RunFeemsSim.machinery_calculation import MachineryCalculation, convert_gymir_result_to_propulsion_power_series\n", + "\n", + "pd.options.plotting.backend = \"plotly\"" ] }, { @@ -395,14 +396,6 @@ "execution_count": null, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2023-11-22 09:55:46,545 - feems.components_model.utility - ERROR - The data is not compatible with the given time step.\n", - "2023-11-22 09:55:46,545 - feems.components_model.node - WARNING - Integration occurred for other loadThe data is not compatible with the given time step.\n" - ] - }, { "name": "stdout", "output_type": "stream", @@ -987,16 +980,8 @@ " }\n", "}\n", "\n", - "Average bsfc for engines: 216.35748287185723 g/kWh\n" + "Average bsfc for engines: 305.69896408621025 g/kWh\n" ] - }, - { - "data": { - "image/png": "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", - "text/plain": "
" - }, - "metadata": {}, - "output_type": "display_data" } ], "source": [ @@ -1048,16 +1033,6 @@ "execution_count": null, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2023-11-22 09:55:46,623 - feems.components_model.utility - ERROR - The data is not compatible with the given time step.\n", - "2023-11-22 09:55:46,624 - feems.components_model.node - WARNING - Integration occurred for other loadThe data is not compatible with the given time step.\n", - "2023-11-22 09:55:46,629 - feems.components_model.utility - ERROR - The data is not compatible with the given time step.\n", - "2023-11-22 09:55:46,629 - feems.components_model.node - WARNING - Integration occurred for other loadThe data is not compatible with the given time step.\n" - ] - }, { "name": "stdout", "output_type": "stream", @@ -1085,16 +1060,7 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2023-11-22 09:55:46,814 - feems.components_model.utility - ERROR - The data is not compatible with the given time step.\n", - "2023-11-22 09:55:46,814 - feems.components_model.node - WARNING - Integration occurred for other loadThe data is not compatible with the given time step.\n" - ] - } - ], + "outputs": [], "source": [ "# Testing MachineryCalculation with time series result (protobuf)\n", "path_to_system = os.path.join(\"tests\", \"mechanical_propulsion_with_electric_system.mss\")\n", diff --git a/RunFEEMSSim/build_library.sh b/RunFEEMSSim/build_library.sh index a6eea84..dc531c7 100644 --- a/RunFEEMSSim/build_library.sh +++ b/RunFEEMSSim/build_library.sh @@ -3,4 +3,4 @@ nbdev_export nbdev_test nbdev_clean ECHO Build a wheel -python setup.py sdist bdist_wheel +python -m build diff --git a/feems/MANIFEST.in b/feems/MANIFEST.in new file mode 100644 index 0000000..e2915b6 --- /dev/null +++ b/feems/MANIFEST.in @@ -0,0 +1 @@ +include feems/package_data/*.csv \ No newline at end of file diff --git a/feems/feems/components_model/component_electric.py b/feems/feems/components_model/component_electric.py index 3b8a527..243bf64 100644 --- a/feems/feems/components_model/component_electric.py +++ b/feems/feems/components_model/component_electric.py @@ -430,6 +430,7 @@ def __init__( fuel_cell_module: FuelCell, converter: ElectricComponent, switchboard_id: SwbId, + number_modules: int = 1, ): super(FuelCellSystem, self).__init__( name=name, @@ -441,6 +442,7 @@ def __init__( ) self.converter = converter self.fuel_cell = fuel_cell_module + self.number_modules = number_modules def get_fuel_cell_run_point( self, @@ -473,13 +475,19 @@ def get_fuel_cell_run_point( if power_out_kw is None: power_out_kw = self.power_output power_out_fuel_cell_kw, load_ratio = self.set_power_input_from_output(power_out_kw) - return self.fuel_cell.get_fuel_cell_run_point( - power_out_kw=power_out_fuel_cell_kw, + result_per_module = self.fuel_cell.get_fuel_cell_run_point( + power_out_kw=power_out_fuel_cell_kw / self.number_modules, fuel_specified_by=fuel_specified_by, lhv_mj_per_g=lhv_mj_per_g, ghg_emission_factor_well_to_tank_gco2eq_per_mj=ghg_emission_factor_well_to_tank_gco2eq_per_mj, ghg_emission_factor_tank_to_wake=ghg_emission_factor_tank_to_wake, ) + return FuelCellRunPoint( + load_ratio=result_per_module.load_ratio, + fuel_flow_rate_kg_per_s=result_per_module.fuel_flow_rate_kg_per_s + * self.number_modules, + efficiency=result_per_module.efficiency, + ) class BatterySystem(Battery): diff --git a/feems/feems/components_model/component_mechanical.py b/feems/feems/components_model/component_mechanical.py index fb4471b..e03a52a 100644 --- a/feems/feems/components_model/component_mechanical.py +++ b/feems/feems/components_model/component_mechanical.py @@ -357,8 +357,8 @@ def get_engine_run_point_from_power_out_kw( """ if power is None: power = self.power_output + self.engine.power_output = power return self.engine.get_engine_run_point_from_power_out_kw( - power_kw=power, fuel_specified_by=fuel_specified_by, lhv_mj_per_g=lhv_mj_per_g, ghg_emission_factor_well_to_tank_gco2eq_per_mj=ghg_emission_factor_well_to_tank_gco2eq_per_mj, @@ -435,8 +435,8 @@ def get_engine_run_point_from_power_out_kw( power = self.power_output load_ratio = self.get_load(power) eff_gearbox = self.gearbox.get_efficiency_from_load_percentage(load_ratio) + self.engine.power_output = power / eff_gearbox return self.engine.get_engine_run_point_from_power_out_kw( - power_kw=power / eff_gearbox, fuel_specified_by=fuel_specified_by, lhv_mj_per_g=lhv_mj_per_g, ghg_emission_factor_well_to_tank_gco2eq_per_mj=ghg_emission_factor_well_to_tank_gco2eq_per_mj, diff --git a/feems/feems/components_model/node.py b/feems/feems/components_model/node.py index ca829e7..bba855c 100644 --- a/feems/feems/components_model/node.py +++ b/feems/feems/components_model/node.py @@ -30,7 +30,12 @@ Engine, EngineDualFuel, ) -from .utility import integrate_data, IntegrationMethod, integrate_multi_fuel_consumption +from .utility import ( + integrate_data, + IntegrationMethod, + integrate_multi_fuel_consumption, + IntegrationError, +) from .. import get_logger from ..exceptions import InputError from ..fuel import ( @@ -119,7 +124,11 @@ def get_fuel_emission_energy_balance_for_component( energy_consumption_mechanical_total_mj=0, energy_stored_total_mj=0, ) - running_hours = np.dot((component.power_output != 0), time_interval_s).sum() / 3600 + running_hours = ( + (np.atleast_1d(component.power_output)[0] != 0) * np.atleast_1d(time_interval_s)[0] / 3600 + ) + if len(np.atleast_1d(component.power_output)) > 1: + running_hours = np.dot((component.power_output != 0), time_interval_s).sum() / 3600 # Calculate fuel consumption for engines if component.type in [ TypeComponent.MAIN_ENGINE, @@ -209,31 +218,43 @@ def get_fuel_emission_energy_balance_for_component( power_input = component.power_input.copy() power_input[power_input < 0] = 0 # PTI mode if isSystemMechanical: - res.energy_input_mechanical_total_mj = integrate_data( - data_to_integrate=power_input, - time_interval_s=time_interval_s, - integration_method=integration_method, - ) / 1000 + res.energy_input_mechanical_total_mj = ( + integrate_data( + data_to_integrate=power_input, + time_interval_s=time_interval_s, + integration_method=integration_method, + ) + / 1000 + ) else: - res.energy_consumption_mechanical_total_mj = integrate_data( - data_to_integrate=power_input, - time_interval_s=time_interval_s, - integration_method=integration_method, - ) / 1000 + res.energy_consumption_mechanical_total_mj = ( + integrate_data( + data_to_integrate=power_input, + time_interval_s=time_interval_s, + integration_method=integration_method, + ) + / 1000 + ) power_input = component.power_input.copy() power_input[power_input > 0] = 0 # PTO mode if isSystemMechanical: - res.energy_consumption_mechanical_total_mj = integrate_data( - data_to_integrate=power_input, - time_interval_s=time_interval_s, - integration_method=integration_method, - ) / 1000 + res.energy_consumption_mechanical_total_mj = ( + integrate_data( + data_to_integrate=power_input, + time_interval_s=time_interval_s, + integration_method=integration_method, + ) + / 1000 + ) else: - res.energy_input_mechanical_total_mj = integrate_data( - data_to_integrate=-power_input, - time_interval_s=time_interval_s, - integration_method=integration_method, - ) / 1000 + res.energy_input_mechanical_total_mj = ( + integrate_data( + data_to_integrate=-power_input, + time_interval_s=time_interval_s, + integration_method=integration_method, + ) + / 1000 + ) res.running_hours_pti_pto_total_hr += running_hours #: Calculate electric energy stored for energy storage system @@ -243,11 +264,11 @@ def get_fuel_emission_energy_balance_for_component( component, ) res.energy_stored_total_mj = ( - component.get_energy_stored_kj( + component.get_energy_stored_kj( time_interval_s=time_interval_s, integration_method=integration_method, ) - / 1000 + / 1000 ) #: Calculate electric energy input for shore power @@ -255,7 +276,7 @@ def get_fuel_emission_energy_balance_for_component( component = cast(Union[ShorePowerConnection, ShorePowerConnectionSystem], component) res.energy_input_electric_total_mj = ( integrate_data( - data_to_integrate=component.power_output, + data_to_integrate=component.power_input, time_interval_s=time_interval_s, integration_method=integration_method, ) @@ -263,15 +284,20 @@ def get_fuel_emission_energy_balance_for_component( ) elif component.type in [ TypeComponent.OTHER_LOAD, - TypeComponent.OTHER_MECHANICAL_LOAD + TypeComponent.OTHER_MECHANICAL_LOAD, ]: - res.energy_consumption_auxiliary_total_mj = ( - integrate_data( - data_to_integrate=component.power_output, - time_interval_s=time_interval_s, - integration_method=integration_method, - ) / 1000 - ) + component.set_power_output_from_input(component.power_input) + try: + res.energy_consumption_auxiliary_total_mj = ( + integrate_data( + data_to_integrate=component.power_output, + time_interval_s=time_interval_s, + integration_method=integration_method, + ) + / 1000 + ) + except IntegrationError as e: + logger.warning("Integration occurred for other load: " + e.__str__()) elif component.type in [ TypeComponent.PROPELLER_LOAD, TypeComponent.PROPULSION_DRIVE, @@ -281,15 +307,14 @@ def get_fuel_emission_energy_balance_for_component( data_to_integrate=component.power_output, time_interval_s=time_interval_s, integration_method=integration_method, - ) / 1000 + ) + / 1000 ) else: raise TypeError( f"Component type {component.type} not supported for energy balance calculation" ) - - return res @@ -739,7 +764,10 @@ def get_fuel_energy_consumption_running_time( Returns: FEEMSResult """ - if fuel_specified_by not in [FuelSpecifiedBy.IMO, FuelSpecifiedBy.FUEL_EU_MARITIME]: + if fuel_specified_by not in [ + FuelSpecifiedBy.IMO, + FuelSpecifiedBy.FUEL_EU_MARITIME, + ]: raise NotImplementedError( f"Fuel specified by {fuel_specified_by.name} is not implemented" ) @@ -772,6 +800,24 @@ def get_fuel_energy_consumption_running_time( res = res.sum_with_freeze_duration(res_comp) + if ( + component + not in self.component_by_power_type[TypePower.POWER_SOURCE.value] + + self.component_by_power_type[TypePower.PTI_PTO.value] + + self.component_by_power_type[TypePower.ENERGY_STORAGE.value] + ): + continue + + if component.type == TypeComponent.GENSET: + res_comp.energy_consumption_mechanical_total_mj = ( + integrate_data( + data_to_integrate=component.aux_engine.power_output, + time_interval_s=time_interval_s, + integration_method=integration_method, + ) + / 1000 + ) + #: Add the calculation to the result_dataframe data_to_add = [ *res_comp.to_list_for_electric_component(), @@ -819,7 +865,10 @@ def get_fuel_energy_consumption_running_time_without_details( Returns: FEEMSResult """ - if fuel_specified_by not in [FuelSpecifiedBy.IMO, FuelSpecifiedBy.FUEL_EU_MARITIME]: + if fuel_specified_by not in [ + FuelSpecifiedBy.IMO, + FuelSpecifiedBy.FUEL_EU_MARITIME, + ]: raise NotImplementedError( f"Fuel specified by {fuel_specified_by.name} is not implemented" ) @@ -837,14 +886,6 @@ def get_fuel_energy_consumption_running_time_without_details( # Get the fuel consumption / running hours for each power source, pti/pto, # energy_storage component for component in self.components: - if ( - component - not in self.component_by_power_type[TypePower.POWER_SOURCE.value] - + self.component_by_power_type[TypePower.PTI_PTO.value] - + self.component_by_power_type[TypePower.ENERGY_STORAGE.value] - ): - continue - #: Calculate running hours res_component = get_fuel_emission_energy_balance_for_component( component=component, @@ -1182,13 +1223,17 @@ def get_fuel_calculation_running_hours( total running hours for engines[hours], CO2 emissions [kg], NOx emissions [kg] and the detail numbers for each engine and PTI/PTO """ - if fuel_specified_by not in [FuelSpecifiedBy.IMO, FuelSpecifiedBy.FUEL_EU_MARITIME]: + if fuel_specified_by not in [ + FuelSpecifiedBy.IMO, + FuelSpecifiedBy.FUEL_EU_MARITIME, + ]: raise NotImplementedError( f"Fuel specified by {fuel_specified_by.name} is not implemented" ) #: Get the main engine instances and collect the names main_engines = self.component_by_power_type[TypePower.POWER_SOURCE] pti_ptos = self.component_by_power_type[TypePower.PTI_PTO] + loads = self.component_by_power_type[TypePower.POWER_CONSUMER] #: Create a dataframe template for the result column_names = [ @@ -1205,18 +1250,7 @@ def get_fuel_calculation_running_hours( res = FEEMSResult(detail_result=pd.DataFrame(columns=column_names)) #: Get the fuel consumption rate and on time for each engine / integrate them - for component in [*main_engines, *pti_ptos]: - - if not ( - isinstance(component, MainEngineForMechanicalPropulsion) - or isinstance(component, MainEngineWithGearBoxForMechanicalPropulsion) - or isinstance(component, PTIPTO) - ): - raise TypeError( - "Main engine or PTI/PTO component is not of " - "main engine type or PTI/PTO type" - ) - + for component in [*main_engines, *pti_ptos, *loads]: # Calculate fuel consumption res_comp = get_fuel_emission_energy_balance_for_component( component=component, @@ -1225,6 +1259,26 @@ def get_fuel_calculation_running_hours( fuel_specified_by=fuel_specified_by, ) res = res.sum_with_freeze_duration(res_comp) + if not ( + isinstance(component, MainEngineForMechanicalPropulsion) + or isinstance(component, MainEngineWithGearBoxForMechanicalPropulsion) + or isinstance(component, PTIPTO) + ): + continue + + # Calculate shaft energy output for main engine, genset + if component.type in [ + TypeComponent.MAIN_ENGINE, + TypeComponent.MAIN_ENGINE_WITH_GEARBOX, + ]: + res_comp.energy_consumption_mechanical_total_mj = ( + integrate_data( + data_to_integrate=component.engine.power_output, + time_interval_s=time_step, + integration_method=integration_method, + ) + / 1000 + ) # Add the calculation to the result_dataframe data_to_add = [ diff --git a/feems/feems/components_model/utility.py b/feems/feems/components_model/utility.py index 1cf325b..9083338 100644 --- a/feems/feems/components_model/utility.py +++ b/feems/feems/components_model/utility.py @@ -6,7 +6,7 @@ import numpy as np import pandas as pd from numpy import cumsum -from scipy.integrate import trapz, simps +from scipy.integrate import trapezoid, simpson from scipy.interpolate import PchipInterpolator from feems import get_logger @@ -54,11 +54,12 @@ def integrate_data( :param data_to_integrate: Data samples to integrate, numpy float array :param time_interval_s: Time interval of the data samples in seconds must be a float for - simpson or trapezoid, and a array for 'sum_with_time'. sum_with_times is the dot product + simpson or trapezoid, and an array for 'sum_with_time'. sum_with_times is the dot product of data_to_integrate and time_interval_s :param integration_method: Numerical integration method. Choose among `IntegrationMethod` :return: Integrated value """ + data_to_integrate = np.atleast_1d(data_to_integrate) time_interval_s_is_scalar_number = np.isscalar(time_interval_s) and isinstance( time_interval_s, (float, int) ) @@ -74,18 +75,22 @@ def integrate_data( msg = f"The time interval for {integration_method.value} must be a scalar value" logger.error(msg) raise IntegrationError(msg) - return simps(data_to_integrate) * time_interval_s + return simpson(data_to_integrate) * time_interval_s elif integration_method == IntegrationMethod.trapezoid: if not time_interval_s_is_scalar_number: msg = f"The time interval for {integration_method.value} must be a scalar value" logger.error(msg) raise IntegrationError(msg) - return trapz(data_to_integrate) * time_interval_s + return trapezoid(data_to_integrate) * time_interval_s elif integration_method == IntegrationMethod.sum_with_time: if not data_is_valid_for_variable_time_interval( time_interval_s=time_interval_s, data_to_integrate=data_to_integrate ): - err_msg = "The data is not compatible with the given time step." + err_msg = ( + "The data is not compatible with the given time step. " + "Either the data should have the same shape as time step " + "if time step is given as an array or the data should be scalar." + ) logger.error(err_msg) raise IntegrationError(err_msg) result = np.dot(data_to_integrate, time_interval_s) # type: ignore[arg-type] diff --git a/feems/feems/fuel.py b/feems/feems/fuel.py index 5496ebe..5d8d72d 100644 --- a/feems/feems/fuel.py +++ b/feems/feems/fuel.py @@ -494,6 +494,14 @@ def __add__(self, other: "FuelConsumption"): sum_fuel.fuels.append(each_fuel.copy) return sum_fuel + def __mul__(self, other: Union[float, np.ndarray]): + res = FuelConsumption() + for fuel in self.fuels: + fuel_to_add = fuel.copy + fuel_to_add.mass_or_mass_fraction *= other + res.fuels.append(fuel_to_add) + return res + @property def total_fuel_consumption(self) -> Union[float, np.ndarray]: """Returns the total fuel consumption in kg or kg/s depending on the context.""" diff --git a/feems/pyproject.toml b/feems/pyproject.toml index 2f6f50e..6631d7b 100644 --- a/feems/pyproject.toml +++ b/feems/pyproject.toml @@ -1,8 +1,8 @@ [tool.poetry] name = "feems" -version = "0.10.4" +version = "0.10.5" description = "" -authors = ["Kevin Koosup Yum "] +authors = ["Kevin Koosup Yum "] readme = "readme.md" include = ["feems/py.typed"] license = "Proprietary" @@ -11,7 +11,6 @@ license = "Proprietary" python = ">=3.9,<3.13" pandas = "^2.1.1" scipy = "^1.11.2" -numpy = "^1.22.0" [tool.poetry.group.dev.dependencies] pytest = "^7.4.2" @@ -31,3 +30,4 @@ target-version = ['py37'] [build-system] requires = ["poetry>=1.4.0", "setuptools>=40.8.0"] build-backend = "poetry.core.masonry.api" + diff --git a/feems/readme.md b/feems/readme.md index b99bc0a..6d20ad3 100644 --- a/feems/readme.md +++ b/feems/readme.md @@ -1,18 +1,23 @@ # Fuel, Emissions, Energy Calculation for Machinery System (FEEMS) -FEEMS is modeling framework for a marine power and propulsion system for calculation of fuel consumption, emissions, and energy balance with the input of operation mode and external power load.In this framework, a modeler can configure a power system based on the single line diagram and component library. It supports the following types of power / propulsion systems + +FEEMS is modeling framework for a marine power and propulsion system for calculation of fuel consumption, emissions, and energy balance with the input of operation mode and external power load.In this framework, a modeler can configure a power system based on the single line diagram and component library. It supports the following types of power / propulsion systems - Hybrid/Conventional Diesel Electric Propulsion -- Hybrid Propulsion with PTI/PTO -- Mechanical Propulsion with a Separate Electric Power System +- Hybrid Propulsion with PTI/PTO +- Mechanical Propulsion with a Separate Electric Power System After the system model is configured, given the operational control inputs and power load on the consumers, power balance calculation is performed to obtain the load on the power producers. Then fuel/emission calculation is performed. ## Installing FEEMS + ``` pip install feems ``` + ## Building from the source code -You should have installed poetry + +You should have installed poetry + ``` -``` \ No newline at end of file +``` diff --git a/feems/tests/test_components.py b/feems/tests/test_components.py index 137a476..4cce041 100644 --- a/feems/tests/test_components.py +++ b/feems/tests/test_components.py @@ -15,6 +15,7 @@ Genset, SerialSystemElectric, FuelCell, + FuelCellSystem, ) from feems.components_model.component_mechanical import ( Engine, @@ -43,6 +44,53 @@ class TestComponent(TestCase): + + def setUp(self): + """Create a serial system for testing for a pti/pto system with 5 components.""" + gearbox = BasicComponent( + type_=TypeComponent.GEARBOX, + name="gearbox", + power_type=TypePower.POWER_TRANSMISSION, + rated_power=3000, + rated_speed=150, + eff_curve=np.array([98.0]), + ) + synch_mach = ElectricMachine( + type_=TypeComponent.SYNCHRONOUS_MACHINE, + name="synchronous machine", + rated_power=3000, + rated_speed=150, + eff_curve=ELECTRIC_MACHINE_EFF_CURVE, + ) + rectifier = ElectricComponent( + type_=TypeComponent.RECTIFIER, + name="rectifier", + rated_power=3000, + eff_curve=np.array([99.5]), + ) + inverter = ElectricComponent( + type_=TypeComponent.INVERTER, + name="inverter", + rated_power=3000, + eff_curve=CONVERTER_EFF, + ) + transformer = ElectricComponent( + type_=TypeComponent.TRANSFORMER, + name="transformer", + rated_power=3000, + eff_curve=np.array([99]), + ) + + self.components = [gearbox, synch_mach, rectifier, inverter, transformer] + self.pti_pto = SerialSystem( + TypeComponent.PTI_PTO_SYSTEM, + TypePower.PTI_PTO, + "PTIPTO 1", + self.components, + rated_power=transformer.rated_power, + rated_speed=synch_mach.rated_speed, + ) + def test_component(self): name = "component" component = create_components(name, 1, 1000, 1000) @@ -374,74 +422,28 @@ def test_electric_component_with_file_input(self): os.unlink(filename) def test_serial_system(self): - gearbox = BasicComponent( - type_=TypeComponent.GEARBOX, - name="gearbox", - power_type=TypePower.POWER_TRANSMISSION, - rated_power=3000, - rated_speed=150, - eff_curve=np.array([98.0]), - ) - synch_mach = ElectricMachine( - type_=TypeComponent.SYNCHRONOUS_MACHINE, - name="synchronous machine", - rated_power=3000, - rated_speed=150, - eff_curve=ELECTRIC_MACHINE_EFF_CURVE, - ) - rectifier = ElectricComponent( - type_=TypeComponent.RECTIFIER, - name="rectifier", - rated_power=3000, - eff_curve=np.array([99.5]), - ) - inverter = ElectricComponent( - type_=TypeComponent.INVERTER, - name="inverter", - rated_power=3000, - eff_curve=CONVERTER_EFF, - ) - transformer = ElectricComponent( - type_=TypeComponent.TRANSFORMER, - name="transformer", - rated_power=3000, - eff_curve=np.array([99]), - ) - - components = [gearbox, synch_mach, rectifier, inverter, transformer] - pti_pto = SerialSystem( - TypeComponent.PTI_PTO_SYSTEM, - TypePower.PTI_PTO, - "PTIPTO 1", - components, - rated_power=transformer.rated_power, - rated_speed=synch_mach.rated_speed, - ) + load_perc = 0.50 # np.random.rand() * 100 efficiency = 1 - for component in components: + for component in self.components: efficiency *= component.get_efficiency_from_load_percentage(load_perc) self.assertAlmostEqual( - pti_pto.get_efficiency_from_load_percentage(load_perc), + self.pti_pto.get_efficiency_from_load_percentage(load_perc), efficiency, places=-1, ) - return pti_pto def test_pti_pto(self): - #: Get a generic pti_pto instance from SerialSystem testing - pti_pto_serial = self.test_serial_system() - #: Create a PTIPTO instance switchboard_id = 1 shaft_line_id = 1 pti_pto = PTIPTO( - pti_pto_serial.name, - pti_pto_serial.components, + self.pti_pto.name, + self.pti_pto.components, switchboard_id, - pti_pto_serial.rated_power, - pti_pto_serial.rated_speed, + self.pti_pto.rated_power, + self.pti_pto.rated_speed, shaft_line_id, ) self.assertEqual(shaft_line_id, pti_pto.shaft_line_id) @@ -450,18 +452,17 @@ def test_serial_system_electric(self): switchboard_no = 0 power_type = TypePower.PTI_PTO # noinspection PyShadowingNames - PTIPTO = self.test_serial_system() - PTIPTO_electric = SerialSystemElectric( - PTIPTO.type, - PTIPTO.name, + pti_pto_electric = SerialSystemElectric( + self.pti_pto.type, + self.pti_pto.name, power_type, - PTIPTO.components, + self.pti_pto.components, switchboard_no, - PTIPTO.rated_power, - PTIPTO.rated_speed, + self.pti_pto.rated_power, + self.pti_pto.rated_speed, ) - self.assertEqual(PTIPTO_electric.switchboard_id, switchboard_no) - self.assertEqual(PTIPTO_electric.power_type, power_type) + self.assertEqual(pti_pto_electric.switchboard_id, switchboard_no) + self.assertEqual(pti_pto_electric.power_type, power_type) # noinspection DuplicatedCode def test_main_engine_with_gear_box(self): @@ -619,3 +620,40 @@ def test_fuel_cell(self): fuel_cell_run_point.fuel_flow_rate_kg_per_s.total_fuel_consumption, natural_gas_consumption_kg_per_s, ) + + number_modules = 2 + converter = ElectricComponent( + type_=TypeComponent.POWER_CONVERTER, + name="converter", + rated_power=fuel_cell.rated_power * number_modules * 1.05, + eff_curve=create_random_monotonic_eff_curve(), + ) + fuel_cell_system = FuelCellSystem( + name="fuel cell system 1", + fuel_cell_module=fuel_cell, + converter=converter, + switchboard_id=1, + number_modules=2, + ) + power = np.random.rand(5) * fuel_cell_system.rated_power + power_after_converter, _ = converter.get_power_input_from_bidirectional_output(power) + fuel_cell_system_run_point = fuel_cell_system.get_fuel_cell_run_point(power) + fuel_cell_module_run_point = fuel_cell_system.fuel_cell.get_fuel_cell_run_point( + power_out_kw=power_after_converter / number_modules, + ) + assert np.allclose( + fuel_cell_system_run_point.load_ratio, + fuel_cell_module_run_point.load_ratio, + ) + for fuel_con_system, fuel_con_module in zip( + fuel_cell_system_run_point.fuel_flow_rate_kg_per_s.fuels, + fuel_cell_module_run_point.fuel_flow_rate_kg_per_s.fuels, + ): + assert np.allclose( + fuel_con_system.mass_or_mass_fraction, + fuel_con_module.mass_or_mass_fraction * number_modules, + ) + assert np.allclose( + fuel_cell_system_run_point.efficiency, + fuel_cell_module_run_point.efficiency, + ) diff --git a/feems/tests/test_mechanical_system_simulation.py b/feems/tests/test_mechanical_system_simulation.py index 89a9cf9..4ce105e 100644 --- a/feems/tests/test_mechanical_system_simulation.py +++ b/feems/tests/test_mechanical_system_simulation.py @@ -124,7 +124,7 @@ def test_run_simulation_without_pti_pto(self): # Check if the BSFC is in the sane range total_energy_kj = ( - integrate.simps(total_power_kw, dx=time_interval_s) + integrate.simpson(total_power_kw, dx=time_interval_s) if len(total_power_kw) > 1 else total_power_kw * time_interval_s ) diff --git a/feems/tests/test_node.py b/feems/tests/test_node.py index 8999c0b..0b3894a 100644 --- a/feems/tests/test_node.py +++ b/feems/tests/test_node.py @@ -3,7 +3,7 @@ from unittest import TestCase import numpy as np -from scipy.integrate import simps +from scipy.integrate import simpson from feems.components_model import ( ElectricComponent, @@ -431,7 +431,7 @@ def test_shaft_line(self): main_engine.rated_power * total_load_percentage_ref * main_engine.status ).fuel_flow_rate_kg_per_s.total_fuel_consumption fuel_consumption_rate_ref += fuel_consumption_rate_temp - fuel_consumption_ref = simps(fuel_consumption_rate_ref) * time_step + fuel_consumption_ref = simpson(fuel_consumption_rate_ref) * time_step #: Set the PTI/PTO power 0 pti_pto.power_input = pti_pto.set_power_output_from_input(np.zeros(number_test_points)) @@ -497,7 +497,7 @@ def test_shaft_line(self): engine.power_output = total_load_percentage_ref * engine.rated_power * engine.status res_engine = engine.get_engine_run_point_from_power_out_kw() fuel_consumption_ref += ( - simps(res_engine.fuel_flow_rate_kg_per_s.total_fuel_consumption) * time_step + simpson(res_engine.fuel_flow_rate_kg_per_s.total_fuel_consumption) * time_step ) total_running_hours_ref += engine.status.sum() * time_step / 3600 diff --git a/machinery-system-structure/00_ConvertToFeems.ipynb b/machinery-system-structure/00_ConvertToFeems.ipynb index 41529b3..19d348f 100644 --- a/machinery-system-structure/00_ConvertToFeems.ipynb +++ b/machinery-system-structure/00_ConvertToFeems.ipynb @@ -16,47 +16,32 @@ }, { "cell_type": "code", - "execution_count": 1, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:39.326282Z", - "start_time": "2023-11-27T14:04:39.295843Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| default_exp convert_to_feems\n", + "# | default_exp convert_to_feems\n", "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", - "execution_count": 2, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:39.659964Z", - "start_time": "2023-11-27T14:04:39.569691Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| include: false\n", + "# | include: false\n", "from nbdev.showdoc import *" ] }, { "cell_type": "code", - "execution_count": 3, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:40.696430Z", - "start_time": "2023-11-27T14:04:40.041326Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| export\n", + "# | export\n", "from functools import reduce\n", "from typing import Union, List, Dict, Any, Optional\n", "\n", @@ -168,7 +153,9 @@ " fuel_cell = FuelCell(\n", " name=subsystem.fuel_cell.name,\n", " rated_power=subsystem.fuel_cell.rated_power_kw,\n", - " eff_curve=convert_proto_efficiency_bsfc_to_np_array(subsystem.fuel_cell.efficiency),\n", + " eff_curve=convert_proto_efficiency_bsfc_to_np_array(\n", + " subsystem.fuel_cell.efficiency\n", + " ),\n", " fuel_type=TypeFuel(subsystem.fuel_cell.fuel.fuel_type),\n", " fuel_origin=FuelOrigin(subsystem.fuel_cell.fuel.fuel_origin),\n", " )\n", @@ -205,13 +192,16 @@ " \"\"\"Converts protobuf nox calculation type to feems nox calculation method\"\"\"\n", " nox_calculation_method = NOxCalculationMethod.TIER_2\n", " if proto_engine.nox_calculation_method is not None:\n", - " name = proto.Engine.NOxCalculationMethod.Name(proto_engine.nox_calculation_method)\n", + " name = proto.Engine.NOxCalculationMethod.Name(\n", + " proto_engine.nox_calculation_method\n", + " )\n", " nox_calculation_method = NOxCalculationMethod[name]\n", " return nox_calculation_method\n", "\n", "\n", "def convert_proto_engine_to_feems(\n", - " proto_engine: proto.Engine, type_engine: TypeComponent = TypeComponent.AUXILIARY_ENGINE\n", + " proto_engine: proto.Engine,\n", + " type_engine: TypeComponent = TypeComponent.AUXILIARY_ENGINE,\n", ") -> Engine:\n", " \"\"\"Converts protobuf engine message to feems engine component\"\"\"\n", " nox_calculation_method = convert_nox_calculation_method(proto_engine)\n", @@ -230,7 +220,9 @@ " rated_power=proto_engine.rated_power_kw,\n", " rated_speed=proto_engine.rated_speed_rpm,\n", " bsfc_curve=convert_proto_efficiency_bsfc_to_np_array(proto_engine.bsfc),\n", - " bspfc_curve=convert_proto_efficiency_bsfc_to_np_array(proto_engine.pilot_bsfc),\n", + " bspfc_curve=convert_proto_efficiency_bsfc_to_np_array(\n", + " proto_engine.pilot_bsfc\n", + " ),\n", " fuel_type=TypeFuel(proto_engine.main_fuel.fuel_type),\n", " fuel_origin=FuelOrigin(proto_engine.main_fuel.fuel_origin),\n", " pilot_fuel_type=TypeFuel(proto_engine.pilot_fuel.fuel_type),\n", @@ -251,7 +243,9 @@ " )\n", "\n", "\n", - "def convert_proto_genset_to_feems(subsystem: proto.Subsystem, switchboard_id: int) -> Genset:\n", + "def convert_proto_genset_to_feems(\n", + " subsystem: proto.Subsystem, switchboard_id: int\n", + ") -> Genset:\n", " \"\"\"Converts protobuf subsystem message to feems component\"\"\"\n", " engine = convert_proto_engine_to_feems(proto_engine=subsystem.engine)\n", " generator = convert_proto_electric_machine_to_feems(\n", @@ -268,7 +262,9 @@ " power_type=TypePower.POWER_TRANSMISSION,\n", " switchboard_id=switchboard_id,\n", " )\n", - " return Genset(name=subsystem.name, aux_engine=engine, generator=generator, rectifier=rectifier)\n", + " return Genset(\n", + " name=subsystem.name, aux_engine=engine, generator=generator, rectifier=rectifier\n", + " )\n", "\n", "\n", "def convert_proto_battery_to_feems(\n", @@ -299,7 +295,10 @@ " power_type=TypePower.POWER_TRANSMISSION,\n", " )\n", " return BatterySystem(\n", - " name=subsystem.name, battery=battery, converter=converter, switchboard_id=switchboard_id\n", + " name=subsystem.name,\n", + " battery=battery,\n", + " converter=converter,\n", + " switchboard_id=switchboard_id,\n", " )\n", "\n", "\n", @@ -355,7 +354,9 @@ " ]\n", " return sorted(\n", " components,\n", - " key=lambda component: component.get(\"proto_component\").order_from_switchboard_or_shaftline,\n", + " key=lambda component: component.get(\n", + " \"proto_component\"\n", + " ).order_from_switchboard_or_shaftline,\n", " )\n", "\n", "\n", @@ -437,7 +438,9 @@ " components=components_feems,\n", " switchboard_id=switchboard_id,\n", " rated_power=None if subsystem.rated_power_kw == 0 else subsystem.rated_power_kw,\n", - " rated_speed=None if subsystem.rated_speed_rpm == 0 else subsystem.rated_speed_rpm,\n", + " rated_speed=(\n", + " None if subsystem.rated_speed_rpm == 0 else subsystem.rated_speed_rpm\n", + " ),\n", " )\n", "\n", "\n", @@ -479,7 +482,9 @@ " )\n", " elif subsystem.component_type == proto.Subsystem.ComponentType.GENSET:\n", " components.append(\n", - " convert_proto_genset_to_feems(subsystem=subsystem, switchboard_id=switchboard_id)\n", + " convert_proto_genset_to_feems(\n", + " subsystem=subsystem, switchboard_id=switchboard_id\n", + " )\n", " )\n", " elif subsystem.component_type == proto.Subsystem.ComponentType.BATTERY_SYSTEM:\n", " components.append(\n", @@ -493,7 +498,10 @@ " proto_component=subsystem.battery, switchboard_id=switchboard_id\n", " )\n", " )\n", - " elif subsystem.component_type == proto.Subsystem.ComponentType.SUPERCAPACITOR_SYSTEM:\n", + " elif (\n", + " subsystem.component_type\n", + " == proto.Subsystem.ComponentType.SUPERCAPACITOR_SYSTEM\n", + " ):\n", " components.append(\n", " convert_proto_supercapacitor_system_to_feems(\n", " subsystem=subsystem, switchboard_id=switchboard_id\n", @@ -502,7 +510,8 @@ " elif subsystem.component_type == proto.Subsystem.ComponentType.SUPERCAPACITOR:\n", " components.append(\n", " convert_proto_supercapacitor_to_feems(\n", - " proto_component=subsystem.supercapacitor, switchboard_id=switchboard_id\n", + " proto_component=subsystem.supercapacitor,\n", + " switchboard_id=switchboard_id,\n", " )\n", " )\n", " else:\n", @@ -533,12 +542,16 @@ " MainEngineForMechanicalPropulsion(\n", " name=sub_system.name,\n", " engine=convert_proto_engine_to_feems(\n", - " proto_engine=sub_system.engine, type_engine=TypeComponent.MAIN_ENGINE\n", + " proto_engine=sub_system.engine,\n", + " type_engine=TypeComponent.MAIN_ENGINE,\n", " ),\n", " shaft_line_id=shaft_line_id,\n", " )\n", " )\n", - " elif sub_system.component_type == proto.Subsystem.ComponentType.MAIN_ENGINE_WITH_GEARBOX:\n", + " elif (\n", + " sub_system.component_type\n", + " == proto.Subsystem.ComponentType.MAIN_ENGINE_WITH_GEARBOX\n", + " ):\n", " components.append(\n", " MainEngineWithGearBoxForMechanicalPropulsion(\n", " name=sub_system.name,\n", @@ -563,20 +576,28 @@ " if pti_ptos is None:\n", " components.append(\n", " convert_proto_pti_pto_subsystem_to_feems(\n", - " subsystem=sub_system, switchboard_id=1, shaft_line_id=shaft_line_id\n", + " subsystem=sub_system,\n", + " switchboard_id=1,\n", + " shaft_line_id=shaft_line_id,\n", " )\n", " )\n", " else:\n", " try:\n", " pti_pto = next(\n", - " filter(lambda pti_pto: pti_pto.name == sub_system.name, pti_ptos)\n", + " filter(\n", + " lambda pti_pto: pti_pto.name == sub_system.name, pti_ptos\n", + " )\n", " )\n", " except StopIteration as e:\n", - " print(f\"PTI/PTO {sub_system.name} not found in pti_ptos given as argument.\")\n", + " print(\n", + " f\"PTI/PTO {sub_system.name} not found in pti_ptos given as argument.\"\n", + " )\n", " print(\"Creating a new PTI/PTO from the proto definition.\")\n", " components.append(\n", " convert_proto_pti_pto_subsystem_to_feems(\n", - " subsystem=sub_system, switchboard_id=1, shaft_line_id=shaft_line_id\n", + " subsystem=sub_system,\n", + " switchboard_id=1,\n", + " shaft_line_id=shaft_line_id,\n", " )\n", " )\n", " else:\n", @@ -604,18 +625,13 @@ " name=f\"Shaftline {shaftline.shaft_line_id}\",\n", " shaft_line_id=shaftline.shaft_line_id,\n", " component_list=components,\n", - " )\n" + " )" ] }, { "cell_type": "code", - "execution_count": 4, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:40.706119Z", - "start_time": "2023-11-27T14:04:40.694342Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ "# Test collect_electric_components_from_sub_system\n", @@ -628,19 +644,16 @@ "subsystem.other_load.order_from_switchboard_or_shaftline = order_for_other_load\n", "components = collect_electric_components_from_sub_system(subsystem)\n", "assert len(components) == 2\n", - "assert components[order_for_other_load-1].get(\"proto_component\").name == \"Other load\"\n", - "assert components[order_for_transformer-1].get(\"proto_component\").name == \"Transformer\"" + "assert components[order_for_other_load - 1].get(\"proto_component\").name == \"Other load\"\n", + "assert (\n", + " components[order_for_transformer - 1].get(\"proto_component\").name == \"Transformer\"\n", + ")" ] }, { "cell_type": "code", - "execution_count": 5, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:41.460182Z", - "start_time": "2023-11-27T14:04:41.401172Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [ { "name": "stderr", @@ -662,7 +675,7 @@ " switchboard_id=1,\n", " rated_power_available_total=10000,\n", " no_power_sources=2,\n", - " no_power_consumer=3\n", + " no_power_consumer=3,\n", ")\n", "switchboard_proto = convert_switchboard_to_protobuf(switchboard_feems)\n", "switchboard_feems_converted = convert_proto_switchboard_to_feems(switchboard_proto)\n", @@ -678,23 +691,16 @@ }, { "cell_type": "markdown", - "metadata": { - "collapsed": false - }, + "metadata": {}, "source": [] }, { "cell_type": "code", - "execution_count": 6, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:43.882112Z", - "start_time": "2023-11-27T14:04:43.866771Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| export\n", + "# | export\n", "def convert_feems_switchboards_to_feems_electric_power_system(\n", " switchboards: List[Switchboard],\n", ") -> ElectricPowerSystem:\n", @@ -713,7 +719,9 @@ " switchboards,\n", " [],\n", " )\n", - " bus_tie_connection = [(index + 1, index + 2) for index in range(len(switchboards) - 1)]\n", + " bus_tie_connection = [\n", + " (index + 1, index + 2) for index in range(len(switchboards) - 1)\n", + " ]\n", " return ElectricPowerSystem(\n", " name=\"electric power system\",\n", " power_plant_components=components,\n", @@ -725,14 +733,18 @@ " shaftlines: List[ShaftLine],\n", ") -> MechanicalPropulsionSystem:\n", "\n", - " components = reduce(lambda acc, shaftline: [*acc, *shaftline.components], shaftlines, [])\n", + " components = reduce(\n", + " lambda acc, shaftline: [*acc, *shaftline.components], shaftlines, []\n", + " )\n", " return MechanicalPropulsionSystem(\n", " name=\"mechanical propulsion system\",\n", " components_list=components,\n", " )\n", "\n", "\n", - "def convert_proto_electric_system_to_feems(system: proto.ElectricSystem) -> ElectricPowerSystem:\n", + "def convert_proto_electric_system_to_feems(\n", + " system: proto.ElectricSystem,\n", + ") -> ElectricPowerSystem:\n", " switchboards = [\n", " convert_proto_switchboard_to_feems(proto_switchboard)\n", " for proto_switchboard in system.switchboards\n", @@ -748,7 +760,9 @@ " if pti_ptos is not None:\n", " pti_ptos_for_shaft_lines = list(\n", " filter(\n", - " lambda pti_pto: pti_pto.shaft_line_id == proto_shaftline.shaft_line_id, pti_ptos\n", + " lambda pti_pto: pti_pto.shaft_line_id\n", + " == proto_shaftline.shaft_line_id,\n", + " pti_ptos,\n", " )\n", " )\n", " else:\n", @@ -758,7 +772,9 @@ " shaftline=proto_shaftline, pti_ptos=pti_ptos_for_shaft_lines\n", " )\n", " )\n", - " return convert_feems_shaftlines_to_feems_mechanical_propulsion_system(shaftlines=shaft_lines)\n", + " return convert_feems_shaftlines_to_feems_mechanical_propulsion_system(\n", + " shaftlines=shaft_lines\n", + " )\n", "\n", "\n", "def convert_proto_propulsion_system_to_feems(\n", @@ -772,8 +788,12 @@ " if system.propulsion_type == proto.MachinerySystem.PropulsionType.MECHANICAL:\n", " return MechanicalPropulsionSystemWithElectricPowerSystem(\n", " name=system.name,\n", - " electric_system=convert_proto_electric_system_to_feems(system.electric_system),\n", - " mechanical_system=convert_proto_mechanical_system_to_feems(system.mechanical_system),\n", + " electric_system=convert_proto_electric_system_to_feems(\n", + " system.electric_system\n", + " ),\n", + " mechanical_system=convert_proto_mechanical_system_to_feems(\n", + " system.mechanical_system\n", + " ),\n", " )\n", " if system.propulsion_type == proto.MachinerySystem.PropulsionType.ELECTRIC:\n", " return convert_proto_electric_system_to_feems(system.electric_system)\n", @@ -792,21 +812,22 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:07:49.826476Z", - "start_time": "2023-11-27T14:07:49.772998Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "from tests.utility_compare_proto import compare_proto_machinery_system, \\\n", - " compare_proto_electric_systems\n", + "from tests.utility_compare_proto import (\n", + " compare_proto_machinery_system,\n", + " compare_proto_electric_systems,\n", + ")\n", "import os\n", "from MachSysS.utility import retrieve_machinery_system_from_file\n", "from MachSysS.convert_to_feems import convert_proto_propulsion_system_to_feems\n", - "from MachSysS.convert_to_protobuf import convert_hybrid_propulsion_system_to_protobuf, convert_electric_system_to_protobuf_machinery_system, convert_mechanical_propulsion_system_with_electric_system_to_protobuf\n", + "from MachSysS.convert_to_protobuf import (\n", + " convert_hybrid_propulsion_system_to_protobuf,\n", + " convert_electric_system_to_protobuf_machinery_system,\n", + " convert_mechanical_propulsion_system_with_electric_system_to_protobuf,\n", + ")\n", "from google.protobuf import json_format\n", "from deepdiff.diff import DeepDiff\n", "from pprint import pprint\n", @@ -814,16 +835,24 @@ "pathToMSSFile = os.path.join(\"tests\", \"electric_propulsion_system.mss\")\n", "system_proto = retrieve_machinery_system_from_file(pathToMSSFile)\n", "system_feems = convert_proto_propulsion_system_to_feems(system_proto)\n", - "fuel_cells = list(filter(\n", - " lambda component: component.type == TypeComponent.FUEL_CELL_SYSTEM, system_feems.power_sources\n", - "))\n", + "fuel_cells = list(\n", + " filter(\n", + " lambda component: component.type == TypeComponent.FUEL_CELL_SYSTEM,\n", + " system_feems.power_sources,\n", + " )\n", + ")\n", "for fuel_cell in fuel_cells:\n", " fuel_cell.number_modules = 3\n", - "system_proto_reconverted = convert_electric_system_to_protobuf_machinery_system(system_feems)\n", + "system_proto_reconverted = convert_electric_system_to_protobuf_machinery_system(\n", + " system_feems\n", + ")\n", "diff = compare_proto_machinery_system(system_proto, system_proto_reconverted)\n", "assert len(diff.diff_electric_system.switchboards_added) == 0\n", "assert len(diff.diff_electric_system.switchboards_removed) == 0\n", - "for switchboard_id, diff_switchboard in diff.diff_electric_system.switchboards_modified.items():\n", + "for (\n", + " switchboard_id,\n", + " diff_switchboard,\n", + ") in diff.diff_electric_system.switchboards_modified.items():\n", " assert len(diff_switchboard.subsystems_added) == 0\n", " assert len(diff_switchboard.subsystems_removed) == 0\n", " for key, diff_subsystem in diff_switchboard.subsystems_modified.items():\n", @@ -831,24 +860,23 @@ " assert len(diff_subsystem.components_removed) == 0\n", " assert len(diff_subsystem.components_added) == 0\n", " for component_key, diff_component in diff_subsystem.components_modified.items():\n", - " assert len(diff_component) == 0, f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"" + " assert (\n", + " len(diff_component) == 0\n", + " ), f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"" ] }, { "cell_type": "code", - "execution_count": 8, - "metadata": { - "ExecuteTime": { - "end_time": "2023-09-05T07:49:05.309264Z", - "start_time": "2023-09-05T07:49:05.277630Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ "pathToMSSFile = os.path.join(\"tests\", \"mechanical_propulsion_with_electric_system.mss\")\n", "system_proto = retrieve_machinery_system_from_file(pathToMSSFile)\n", "system_feems = convert_proto_propulsion_system_to_feems(system_proto)\n", - "system_proto_reconverted = convert_mechanical_propulsion_system_with_electric_system_to_protobuf(system_feems)\n", + "system_proto_reconverted = (\n", + " convert_mechanical_propulsion_system_with_electric_system_to_protobuf(system_feems)\n", + ")\n", "diff = compare_proto_machinery_system(system_proto, system_proto_reconverted)\n", "with open(pathToMSSFile, \"wb\") as f:\n", " f.write(system_proto_reconverted.SerializeToString())\n", @@ -856,7 +884,10 @@ "assert len(diff.diff_electric_system.switchboards_removed) == 0\n", "assert len(diff.diff_mechanical_system.shaft_lines_added) == 0\n", "assert len(diff.diff_mechanical_system.shaft_lines_removed) == 0\n", - "for shaft_line_id, diff_shaft_line in diff.diff_mechanical_system.shaft_lines_modified.items():\n", + "for (\n", + " shaft_line_id,\n", + " diff_shaft_line,\n", + ") in diff.diff_mechanical_system.shaft_lines_modified.items():\n", " assert len(diff_shaft_line.subsystems_added) == 0\n", " assert len(diff_shaft_line.subsystems_removed) == 0\n", " for key, diff_subsystem in diff_shaft_line.subsystems_modified.items():\n", @@ -864,8 +895,13 @@ " assert len(diff_subsystem.components_removed) == 0\n", " assert len(diff_subsystem.components_added) == 0\n", " for component_key, diff_component in diff_subsystem.components_modified.items():\n", - " assert len(diff_component) == 0, f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"\n", - "for switchboard_id, diff_switchboard in diff.diff_electric_system.switchboards_modified.items():\n", + " assert (\n", + " len(diff_component) == 0\n", + " ), f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"\n", + "for (\n", + " switchboard_id,\n", + " diff_switchboard,\n", + ") in diff.diff_electric_system.switchboards_modified.items():\n", " assert len(diff_switchboard.subsystems_added) == 0\n", " assert len(diff_switchboard.subsystems_removed) == 0\n", " for key, diff_subsystem in diff_switchboard.subsystems_modified.items():\n", @@ -873,7 +909,9 @@ " assert len(diff_subsystem.components_removed) == 0\n", " assert len(diff_subsystem.components_added) == 0\n", " for component_key, diff_component in diff_subsystem.components_modified.items():\n", - " assert len(diff_component) == 0, f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"\n" + " assert (\n", + " len(diff_component) == 0\n", + " ), f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"" ] }, { @@ -885,27 +923,28 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": { - "ExecuteTime": { - "end_time": "2023-09-05T07:49:06.813761Z", - "start_time": "2023-09-05T07:49:06.783152Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ "pathToMSSFile = os.path.join(\"tests\", \"hybrid_propulsion_system.mss\")\n", "system_proto = retrieve_machinery_system_from_file(pathToMSSFile)\n", "system_feems = convert_proto_propulsion_system_to_feems(system_proto)\n", "# Make sure that the pti_pto of the electric system is the same instance as the pti_pto of the mechanical system\n", - "assert system_feems.electric_system.pti_pto[0] == system_feems.mechanical_system.pti_ptos[0]\n", + "assert (\n", + " system_feems.electric_system.pti_pto[0]\n", + " == system_feems.mechanical_system.pti_ptos[0]\n", + ")\n", "system_proto_reconverted = convert_hybrid_propulsion_system_to_protobuf(system_feems)\n", "diff = compare_proto_machinery_system(system_proto, system_proto_reconverted)\n", "assert len(diff.diff_electric_system.switchboards_added) == 0\n", "assert len(diff.diff_electric_system.switchboards_removed) == 0\n", "assert len(diff.diff_mechanical_system.shaft_lines_added) == 0\n", "assert len(diff.diff_mechanical_system.shaft_lines_removed) == 0\n", - "for shaft_line_id, diff_shaft_line in diff.diff_mechanical_system.shaft_lines_modified.items():\n", + "for (\n", + " shaft_line_id,\n", + " diff_shaft_line,\n", + ") in diff.diff_mechanical_system.shaft_lines_modified.items():\n", " assert len(diff_shaft_line.subsystems_added) == 0\n", " assert len(diff_shaft_line.subsystems_removed) == 0\n", " for key, diff_subsystem in diff_shaft_line.subsystems_modified.items():\n", @@ -913,8 +952,13 @@ " assert len(diff_subsystem.components_removed) == 0\n", " assert len(diff_subsystem.components_added) == 0\n", " for component_key, diff_component in diff_subsystem.components_modified.items():\n", - " assert len(diff_component) == 0, f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"\n", - "for switchboard_id, diff_switchboard in diff.diff_electric_system.switchboards_modified.items():\n", + " assert (\n", + " len(diff_component) == 0\n", + " ), f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"\n", + "for (\n", + " switchboard_id,\n", + " diff_switchboard,\n", + ") in diff.diff_electric_system.switchboards_modified.items():\n", " assert len(diff_switchboard.subsystems_added) == 0\n", " assert len(diff_switchboard.subsystems_removed) == 0\n", " for key, diff_subsystem in diff_switchboard.subsystems_modified.items():\n", @@ -922,18 +966,15 @@ " assert len(diff_subsystem.components_removed) == 0\n", " assert len(diff_subsystem.components_added) == 0\n", " for component_key, diff_component in diff_subsystem.components_modified.items():\n", - " assert len(diff_component) == 0, f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"" + " assert (\n", + " len(diff_component) == 0\n", + " ), f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"" ] }, { "cell_type": "code", - "execution_count": 9, - "metadata": { - "ExecuteTime": { - "end_time": "2023-09-05T06:02:43.487001Z", - "start_time": "2023-09-05T06:02:43.458808Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [] } diff --git a/machinery-system-structure/01_ConvertToProtobuf.ipynb b/machinery-system-structure/01_ConvertToProtobuf.ipynb index c988c09..18465af 100644 --- a/machinery-system-structure/01_ConvertToProtobuf.ipynb +++ b/machinery-system-structure/01_ConvertToProtobuf.ipynb @@ -16,50 +16,40 @@ }, { "cell_type": "code", - "execution_count": 1, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:19.675916Z", - "start_time": "2023-11-27T14:04:19.573615Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| default_exp convert_to_protobuf\n", + "# | default_exp convert_to_protobuf\n", "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", - "execution_count": 2, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:19.688534Z", - "start_time": "2023-11-27T14:04:19.586593Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| include: false\n", + "# | include: false\n", "from nbdev.showdoc import *" ] }, { "cell_type": "code", - "execution_count": 3, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:20.393940Z", - "start_time": "2023-11-27T14:04:19.668876Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| export\n", - "from feems.components_model import Engine, Switchboard, ShaftLine, \\\n", - " MainEngineForMechanicalPropulsion, MechanicalPropulsionComponent, \\\n", - " MainEngineWithGearBoxForMechanicalPropulsion\n", + "# | export\n", + "from feems.components_model import (\n", + " Engine,\n", + " Switchboard,\n", + " ShaftLine,\n", + " MainEngineForMechanicalPropulsion,\n", + " MechanicalPropulsionComponent,\n", + " MainEngineWithGearBoxForMechanicalPropulsion,\n", + ")\n", "from typing import cast, Union, List\n", "\n", "from feems.types_for_feems import TypeComponent, NOxCalculationMethod, EmissionCurve\n", @@ -72,48 +62,64 @@ " Battery,\n", " SuperCapacitorSystem,\n", " PTIPTO,\n", - " SuperCapacitor\n", + " SuperCapacitor,\n", ")\n", "from feems.components_model.component_electric import SerialSystemElectric, Genset\n", - "from feems.system_model import ElectricPowerSystem, MechanicalPropulsionSystem, \\\n", - " MechanicalPropulsionSystemWithElectricPowerSystem, HybridPropulsionSystem\n", + "from feems.system_model import (\n", + " ElectricPowerSystem,\n", + " MechanicalPropulsionSystem,\n", + " MechanicalPropulsionSystemWithElectricPowerSystem,\n", + " HybridPropulsionSystem,\n", + ")\n", "\n", "import MachSysS.system_structure_pb2 as proto\n", "\n", "\n", - "def convert_efficiency_curve_to_protobuf(component: ElectricComponent) -> proto.Efficiency:\n", + "def convert_efficiency_curve_to_protobuf(\n", + " component: ElectricComponent,\n", + ") -> proto.Efficiency:\n", " \"\"\"Convert efficiency value or curve in the component to protobuf message\"\"\"\n", " efficiency = proto.Efficiency()\n", " if len(component._efficiency_points) == 1:\n", " efficiency.value = component._efficiency_points[0]\n", " else:\n", - " efficiency.curve.curve.points.extend([\n", - " proto.Point(x=each_point[0], y=each_point[1])\n", - " for each_point in component._efficiency_points\n", - " ])\n", + " efficiency.curve.curve.points.extend(\n", + " [\n", + " proto.Point(x=each_point[0], y=each_point[1])\n", + " for each_point in component._efficiency_points\n", + " ]\n", + " )\n", " efficiency.curve.x_label = \"power load\"\n", " efficiency.curve.y_label = \"efficiency\"\n", " return efficiency\n", "\n", "\n", - "def convert_bsfc_curve_to_protobuf(component: Union[Engine, EngineDualFuel], for_pilot_fuel: bool = False) -> proto.BSFC:\n", + "def convert_bsfc_curve_to_protobuf(\n", + " component: Union[Engine, EngineDualFuel], for_pilot_fuel: bool = False\n", + ") -> proto.BSFC:\n", " \"\"\"Convert bsfc value or curve in the component to protobuf message\"\"\"\n", " bsfc = proto.BSFC()\n", - " bsfc_points = component.specific_fuel_consumption_points if not for_pilot_fuel else component.specific_pilot_fuel_consumption_points\n", + " bsfc_points = (\n", + " component.specific_fuel_consumption_points\n", + " if not for_pilot_fuel\n", + " else component.specific_pilot_fuel_consumption_points\n", + " )\n", " if len(bsfc_points) == 1:\n", " bsfc.value = bsfc_points[0]\n", " else:\n", - " bsfc.curve.curve.points.extend([\n", - " proto.Point(x=each_point[0], y=each_point[1]) for each_point in bsfc_points\n", - " ])\n", + " bsfc.curve.curve.points.extend(\n", + " [\n", + " proto.Point(x=each_point[0], y=each_point[1])\n", + " for each_point in bsfc_points\n", + " ]\n", + " )\n", " bsfc.curve.x_label = \"power load\"\n", " bsfc.curve.y_label = \"bsfc\"\n", " return bsfc\n", "\n", "\n", "def convert_electric_machine_to_protobuf(\n", - " component: ElectricMachine,\n", - " order_from_switchboard: int = 1\n", + " component: ElectricMachine, order_from_switchboard: int = 1\n", ") -> proto.ElectricMachine:\n", " \"\"\"Convert elecrtic machine component of FEEMS to protobuf message\"\"\"\n", " return proto.ElectricMachine(\n", @@ -121,26 +127,24 @@ " rated_power_kw=component.rated_power,\n", " rated_speed_rpm=component.rated_speed,\n", " efficiency=convert_efficiency_curve_to_protobuf(component),\n", - " order_from_switchboard_or_shaftline=order_from_switchboard\n", + " order_from_switchboard_or_shaftline=order_from_switchboard,\n", " )\n", "\n", "\n", "def convert_electric_component_to_protobuf(\n", - " component: ElectricComponent,\n", - " order_from_switchboard: int = 1\n", + " component: ElectricComponent, order_from_switchboard: int = 1\n", ") -> proto.ElectricMachine:\n", " \"\"\"Convert converter component of FEEMS to protobuf message\"\"\"\n", " return proto.ElectricComponent(\n", " name=component.name,\n", " rated_power_kw=component.rated_power,\n", " efficiency=convert_efficiency_curve_to_protobuf(component),\n", - " order_from_switchboard_or_shaftline=order_from_switchboard\n", + " order_from_switchboard_or_shaftline=order_from_switchboard,\n", " )\n", "\n", "\n", "def convert_battery_component_to_protobuf(\n", - " component: Battery,\n", - " order_from_switchboard: int = 1\n", + " component: Battery, order_from_switchboard: int = 1\n", ") -> proto.ElectricMachine:\n", " \"\"\"Convert battery component of FEEMS to protobuf message\"\"\"\n", " return proto.Battery(\n", @@ -151,13 +155,12 @@ " efficiency_charging=component.eff_charging,\n", " efficiency_discharging=component.eff_discharging,\n", " initial_state_of_charge=component.soc0,\n", - " order_from_switchboard_or_shaftline=order_from_switchboard\n", + " order_from_switchboard_or_shaftline=order_from_switchboard,\n", " )\n", "\n", "\n", "def convert_supercapacitor_component_to_protobuf(\n", - " component: SuperCapacitor,\n", - " order_from_switchboard: int = 1\n", + " component: SuperCapacitor, order_from_switchboard: int = 1\n", ") -> proto.ElectricMachine:\n", " \"\"\"Convert converter component of FEEMS to protobuf message\"\"\"\n", " return proto.SuperCapacitor(\n", @@ -167,50 +170,67 @@ " efficiency_charging=component.eff_charging,\n", " efficiency_discharging=component.eff_discharging,\n", " initial_state_of_charge=component.soc0,\n", - " order_from_switchboard_or_shaftline=order_from_switchboard\n", + " order_from_switchboard_or_shaftline=order_from_switchboard,\n", " )\n", "\n", "\n", "def convert_serial_electric_system_to_protobuf(\n", " component: Union[SerialSystemElectric, PTIPTO],\n", - " initial_order_from_switchboard: int = 1\n", + " initial_order_from_switchboard: int = 1,\n", ") -> proto.Subsystem:\n", " \"\"\"Convert serial electric system or PTI/PTO component to protobuf message\"\"\"\n", " order = initial_order_from_switchboard\n", " subsystem = proto.Subsystem()\n", " for subcomponent in component.components:\n", " if subcomponent.type == TypeComponent.TRANSFORMER:\n", - " subsystem.transformer.CopyFrom(convert_electric_component_to_protobuf(\n", - " component=subcomponent, order_from_switchboard=order\n", - " ))\n", - " if subcomponent.type in [TypeComponent.POWER_CONVERTER, TypeComponent.INVERTER, TypeComponent.RECTIFIER, TypeComponent.ACTIVE_FRONT_END]:\n", - " if not subsystem.HasField('converter1'):\n", - " subsystem.converter1.CopyFrom(convert_electric_component_to_protobuf(\n", + " subsystem.transformer.CopyFrom(\n", + " convert_electric_component_to_protobuf(\n", " component=subcomponent, order_from_switchboard=order\n", - " ))\n", + " )\n", + " )\n", + " if subcomponent.type in [\n", + " TypeComponent.POWER_CONVERTER,\n", + " TypeComponent.INVERTER,\n", + " TypeComponent.RECTIFIER,\n", + " TypeComponent.ACTIVE_FRONT_END,\n", + " ]:\n", + " if not subsystem.HasField(\"converter1\"):\n", + " subsystem.converter1.CopyFrom(\n", + " convert_electric_component_to_protobuf(\n", + " component=subcomponent, order_from_switchboard=order\n", + " )\n", + " )\n", " else:\n", - " subsystem.converter2.CopyFrom(convert_electric_component_to_protobuf(\n", - " component=subcomponent, order_from_switchboard=order\n", - " ))\n", + " subsystem.converter2.CopyFrom(\n", + " convert_electric_component_to_protobuf(\n", + " component=subcomponent, order_from_switchboard=order\n", + " )\n", + " )\n", " if subcomponent.type in [\n", " TypeComponent.SYNCHRONOUS_MACHINE,\n", " TypeComponent.INDUCTION_MACHINE,\n", - " TypeComponent.ELECTRIC_MOTOR\n", + " TypeComponent.ELECTRIC_MOTOR,\n", " ]:\n", - " subsystem.electric_machine.CopyFrom(convert_electric_machine_to_protobuf(\n", - " component=subcomponent, order_from_switchboard=order\n", - " ))\n", + " subsystem.electric_machine.CopyFrom(\n", + " convert_electric_machine_to_protobuf(\n", + " component=subcomponent, order_from_switchboard=order\n", + " )\n", + " )\n", " order += 1\n", " return subsystem\n", "\n", "\n", - "def convert_nox_calculation_method_to_protobuf(nox_calculation_method_feems: NOxCalculationMethod) -> proto.Engine.NOxCalculationMethod:\n", + "def convert_nox_calculation_method_to_protobuf(\n", + " nox_calculation_method_feems: NOxCalculationMethod,\n", + ") -> proto.Engine.NOxCalculationMethod:\n", " \"\"\"Convert nox calculation method of FEEMS to protobuf message\"\"\"\n", " index = proto.Engine.NOxCalculationMethod.Value(nox_calculation_method_feems.name)\n", " return index\n", "\n", "\n", - "def convert_emission_curves_to_protobuf(emission_curves_feems: List[EmissionCurve]) -> List[proto.EmissionCurve]:\n", + "def convert_emission_curves_to_protobuf(\n", + " emission_curves_feems: List[EmissionCurve],\n", + ") -> List[proto.EmissionCurve]:\n", " \"\"\"Convert emission curves of FEEMS to protobuf message\"\"\"\n", " if emission_curves_feems is None:\n", " return []\n", @@ -220,11 +240,13 @@ " y_label=\"emission_g_per_kwh\",\n", " curve=proto.Curve1D(\n", " points=[\n", - " proto.Point(x=each_point.load_ratio, y=each_point.emission_g_per_kwh)\n", + " proto.Point(\n", + " x=each_point.load_ratio, y=each_point.emission_g_per_kwh\n", + " )\n", " for each_point in each_curve.points_per_kwh\n", " ]\n", " ),\n", - " emission_type=proto.EmissionType.Value(each_curve.emission_type.value)\n", + " emission_type=proto.EmissionType.Value(each_curve.emission_type.value),\n", " )\n", " for each_curve in emission_curves_feems\n", " ]\n", @@ -232,7 +254,7 @@ "\n", "def convert_engine_component_to_protobuf(\n", " engine_feems: Union[Engine, EngineDualFuel],\n", - " order_from_shaftline_or_switchboard: int = 1\n", + " order_from_shaftline_or_switchboard: int = 1,\n", ") -> proto.Engine:\n", " \"\"\"Convert engine component of FEEMS to protobuf message\"\"\"\n", " engine = proto.Engine(\n", @@ -244,20 +266,30 @@ " fuel_type=engine_feems.fuel_type.value,\n", " fuel_origin=engine_feems.fuel_origin.value,\n", " ),\n", - " nox_calculation_method=convert_nox_calculation_method_to_protobuf(engine_feems.nox_calculation_method),\n", - " emission_curves = convert_emission_curves_to_protobuf(engine_feems.emission_curves),\n", - " order_from_switchboard_or_shaftline=order_from_shaftline_or_switchboard\n", + " nox_calculation_method=convert_nox_calculation_method_to_protobuf(\n", + " engine_feems.nox_calculation_method\n", + " ),\n", + " emission_curves=convert_emission_curves_to_protobuf(\n", + " engine_feems.emission_curves\n", + " ),\n", + " order_from_switchboard_or_shaftline=order_from_shaftline_or_switchboard,\n", " )\n", " if isinstance(engine_feems, EngineDualFuel):\n", - " engine.pilot_bsfc.CopyFrom(convert_bsfc_curve_to_protobuf(engine_feems, for_pilot_fuel=True))\n", - " engine.pilot_fuel.CopyFrom(proto.Fuel(\n", - " fuel_type=engine_feems.pilot_fuel_type.value,\n", - " fuel_origin=engine_feems.pilot_fuel_origin.value,\n", - " ))\n", + " engine.pilot_bsfc.CopyFrom(\n", + " convert_bsfc_curve_to_protobuf(engine_feems, for_pilot_fuel=True)\n", + " )\n", + " engine.pilot_fuel.CopyFrom(\n", + " proto.Fuel(\n", + " fuel_type=engine_feems.pilot_fuel_type.value,\n", + " fuel_origin=engine_feems.pilot_fuel_origin.value,\n", + " )\n", + " )\n", " return engine\n", "\n", "\n", - "def convert_switchboard_to_protobuf(switchboard_feems: Switchboard) -> proto.Switchboard:\n", + "def convert_switchboard_to_protobuf(\n", + " switchboard_feems: Switchboard,\n", + ") -> proto.Switchboard:\n", " switchboard_proto = proto.Switchboard()\n", " switchboard_proto.switchboard_id = switchboard_feems.id\n", "\n", @@ -267,66 +299,91 @@ " component_type=component.type.value,\n", " name=component.name,\n", " rated_power_kw=component.rated_power,\n", - " rated_speed_rpm=component.rated_speed\n", + " rated_speed_rpm=component.rated_speed,\n", " )\n", " if component.type == TypeComponent.GENERATOR:\n", - " subsystem.electric_machine.CopyFrom(convert_electric_machine_to_protobuf(\n", - " component=component,\n", - " ))\n", + " subsystem.electric_machine.CopyFrom(\n", + " convert_electric_machine_to_protobuf(\n", + " component=component,\n", + " )\n", + " )\n", " elif component.type == TypeComponent.FUEL_CELL_SYSTEM:\n", " component = cast(FuelCellSystem, component)\n", - " subsystem.converter1.CopyFrom(convert_electric_component_to_protobuf(\n", - " component=component.converter\n", - " ))\n", - " subsystem.fuel_cell.CopyFrom(proto.FuelCell(\n", - " name=component.fuel_cell.name,\n", - " rated_power_kw=component.fuel_cell.rated_power,\n", - " efficiency=convert_efficiency_curve_to_protobuf(component.fuel_cell),\n", - " fuel=proto.Fuel(\n", - " fuel_type=component.fuel_cell.fuel_type.value,\n", - " fuel_origin=component.fuel_cell.fuel_origin.value,\n", - " ),\n", - " number_modules=component.number_modules,\n", - " order_from_switchboard_or_shaftline=2\n", - " ))\n", + " subsystem.converter1.CopyFrom(\n", + " convert_electric_component_to_protobuf(component=component.converter)\n", + " )\n", + " subsystem.fuel_cell.CopyFrom(\n", + " proto.FuelCell(\n", + " name=component.fuel_cell.name,\n", + " rated_power_kw=component.fuel_cell.rated_power,\n", + " efficiency=convert_efficiency_curve_to_protobuf(\n", + " component.fuel_cell\n", + " ),\n", + " fuel=proto.Fuel(\n", + " fuel_type=component.fuel_cell.fuel_type.value,\n", + " fuel_origin=component.fuel_cell.fuel_origin.value,\n", + " ),\n", + " number_modules=component.number_modules,\n", + " order_from_switchboard_or_shaftline=2,\n", + " )\n", + " )\n", " elif component.type == TypeComponent.GENSET:\n", " component = cast(Genset, component)\n", - " subsystem.electric_machine.CopyFrom(convert_electric_machine_to_protobuf(\n", - " component=component.generator,\n", - " ))\n", - " subsystem.engine.CopyFrom(convert_engine_component_to_protobuf(\n", - " engine_feems=component.aux_engine,\n", - " order_from_shaftline_or_switchboard=2\n", - " ))\n", + " subsystem.electric_machine.CopyFrom(\n", + " convert_electric_machine_to_protobuf(\n", + " component=component.generator,\n", + " )\n", + " )\n", + " subsystem.engine.CopyFrom(\n", + " convert_engine_component_to_protobuf(\n", + " engine_feems=component.aux_engine,\n", + " order_from_shaftline_or_switchboard=2,\n", + " )\n", + " )\n", " elif component.type == TypeComponent.OTHER_LOAD:\n", " subsystem.other_load.CopyFrom(\n", - " convert_electric_component_to_protobuf(component=component))\n", - " elif component.type in [TypeComponent.PTI_PTO_SYSTEM, TypeComponent.PROPULSION_DRIVE]:\n", - " subsystem.MergeFrom(convert_serial_electric_system_to_protobuf(component=component))\n", + " convert_electric_component_to_protobuf(component=component)\n", + " )\n", + " elif component.type in [\n", + " TypeComponent.PTI_PTO_SYSTEM,\n", + " TypeComponent.PROPULSION_DRIVE,\n", + " ]:\n", + " subsystem.MergeFrom(\n", + " convert_serial_electric_system_to_protobuf(component=component)\n", + " )\n", " elif component.type == TypeComponent.BATTERY_SYSTEM:\n", " component = cast(BatterySystem, component)\n", - " subsystem.converter1.CopyFrom(convert_electric_component_to_protobuf(component=component.converter))\n", - " subsystem.battery.CopyFrom(convert_battery_component_to_protobuf(\n", - " component=component.battery,\n", - " order_from_switchboard=2\n", - " ))\n", + " subsystem.converter1.CopyFrom(\n", + " convert_electric_component_to_protobuf(component=component.converter)\n", + " )\n", + " subsystem.battery.CopyFrom(\n", + " convert_battery_component_to_protobuf(\n", + " component=component.battery, order_from_switchboard=2\n", + " )\n", + " )\n", " elif component.type == TypeComponent.BATTERY:\n", " subsystem.battery.CopyFrom(\n", - " convert_battery_component_to_protobuf(component=component))\n", + " convert_battery_component_to_protobuf(component=component)\n", + " )\n", " elif component.type == TypeComponent.SUPERCAPACITOR_SYSTEM:\n", " component = cast(SuperCapacitorSystem, component)\n", - " subsystem.converter1.CopyFrom(convert_electric_component_to_protobuf(component=component.converter))\n", - " subsystem.battery.CopyFrom(convert_supercapacitor_component_to_protobuf(\n", - " component=component.supercapacitor,\n", - " order_from_switchboard=2\n", - " ))\n", + " subsystem.converter1.CopyFrom(\n", + " convert_electric_component_to_protobuf(component=component.converter)\n", + " )\n", + " subsystem.battery.CopyFrom(\n", + " convert_supercapacitor_component_to_protobuf(\n", + " component=component.supercapacitor, order_from_switchboard=2\n", + " )\n", + " )\n", " elif component.type == TypeComponent.SUPERCAPACITOR:\n", " subsystem.battery.CopyFrom(\n", - " convert_supercapacitor_component_to_protobuf(component=component))\n", + " convert_supercapacitor_component_to_protobuf(component=component)\n", + " )\n", " else:\n", " raise TypeError(\n", " f\"The component type ({component.type.name}) is not a proper type for an electric \"\n", - " f\"system or the conversion for the type is not implemented.\")\n", + " f\"system or the conversion for the type is not implemented.\"\n", + " )\n", " switchboard_proto.subsystems.append(subsystem)\n", " return switchboard_proto\n", "\n", @@ -342,7 +399,7 @@ " # The gear box is added to the protobuf message first.\n", " for gear in filter(\n", " lambda component: component.type == TypeComponent.GEARBOX,\n", - " shaftline_feems.components\n", + " shaftline_feems.components,\n", " ):\n", " gear = cast(MechanicalPropulsionComponent, gear)\n", " gear_proto = proto.Gear(\n", @@ -359,14 +416,15 @@ " component_type=component.type.value,\n", " name=component.name,\n", " rated_power_kw=component.rated_power,\n", - " rated_speed_rpm=component.rated_speed\n", + " rated_speed_rpm=component.rated_speed,\n", " )\n", " if component.type == TypeComponent.MAIN_ENGINE:\n", " component = cast(MainEngineForMechanicalPropulsion, component)\n", - " subsystem.engine.CopyFrom(convert_engine_component_to_protobuf(\n", - " engine_feems=component.engine,\n", - " order_from_shaftline_or_switchboard=1\n", - " ))\n", + " subsystem.engine.CopyFrom(\n", + " convert_engine_component_to_protobuf(\n", + " engine_feems=component.engine, order_from_shaftline_or_switchboard=1\n", + " )\n", + " )\n", " elif component.type == TypeComponent.MAIN_ENGINE_WITH_GEARBOX:\n", " if gear_proto is not None:\n", " raise ValueError(\n", @@ -375,46 +433,51 @@ " f\"component.\"\n", " )\n", " component = cast(MainEngineWithGearBoxForMechanicalPropulsion, component)\n", - " subsystem.engine.CopyFrom(convert_engine_component_to_protobuf(\n", - " engine_feems=component.main_engine,\n", - " order_from_shaftline_or_switchboard=2\n", - " ))\n", - " subsystem.gear.CopyFrom(proto.Gear(\n", - " name=component.gearbox.name,\n", - " rated_power_kw=component.gearbox.rated_power,\n", - " rated_speed_rpm=component.gearbox.rated_speed,\n", - " efficiency=convert_efficiency_curve_to_protobuf(component.gearbox),\n", - " order_from_switchboard_or_shaftline=1,\n", - " ))\n", + " subsystem.engine.CopyFrom(\n", + " convert_engine_component_to_protobuf(\n", + " engine_feems=component.main_engine,\n", + " order_from_shaftline_or_switchboard=2,\n", + " )\n", + " )\n", + " subsystem.gear.CopyFrom(\n", + " proto.Gear(\n", + " name=component.gearbox.name,\n", + " rated_power_kw=component.gearbox.rated_power,\n", + " rated_speed_rpm=component.gearbox.rated_speed,\n", + " efficiency=convert_efficiency_curve_to_protobuf(component.gearbox),\n", + " order_from_switchboard_or_shaftline=1,\n", + " )\n", + " )\n", " elif component.type == TypeComponent.PROPELLER_LOAD:\n", " if gear_proto is not None:\n", " subsystem.gear.CopyFrom(gear_proto)\n", - " subsystem.propeller.CopyFrom(proto.Propeller(\n", - " efficiency=convert_efficiency_curve_to_protobuf(component),\n", - " propulsor_id=propeller_id,\n", - " order_from_switchboard_or_shaftline=2,\n", - " ))\n", + " subsystem.propeller.CopyFrom(\n", + " proto.Propeller(\n", + " efficiency=convert_efficiency_curve_to_protobuf(component),\n", + " propulsor_id=propeller_id,\n", + " order_from_switchboard_or_shaftline=2,\n", + " )\n", + " )\n", " propeller_id += 1\n", " elif component.type == TypeComponent.PTI_PTO_SYSTEM:\n", - " subsystem.MergeFrom(convert_serial_electric_system_to_protobuf(component=component))\n", + " subsystem.MergeFrom(\n", + " convert_serial_electric_system_to_protobuf(component=component)\n", + " )\n", " elif component.type == TypeComponent.GEARBOX:\n", " continue\n", " else:\n", - " raise ValueError(f\"The shaftline contains a component ({component.name}) that has an \"\n", - " f\"imcompatible type ({component.type}) for conversion.\")\n", + " raise ValueError(\n", + " f\"The shaftline contains a component ({component.name}) that has an \"\n", + " f\"imcompatible type ({component.type}) for conversion.\"\n", + " )\n", " shaftline_proto.subsystems.append(subsystem)\n", - " return shaftline_proto\n" + " return shaftline_proto" ] }, { "cell_type": "code", - "execution_count": 4, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:20.434100Z", - "start_time": "2023-11-27T14:04:20.395272Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -727,19 +790,27 @@ ], "source": [ "# Test converting\n", - "from tests.utility import create_switchboard_with_components, create_shaftline_with_components\n", - "from MachSysS.convert_to_protobuf import convert_switchboard_to_protobuf, convert_shaftline_to_protobuf\n", + "from tests.utility import (\n", + " create_switchboard_with_components,\n", + " create_shaftline_with_components,\n", + ")\n", + "from MachSysS.convert_to_protobuf import (\n", + " convert_switchboard_to_protobuf,\n", + " convert_shaftline_to_protobuf,\n", + ")\n", "\n", "switchboard_feems = create_switchboard_with_components(\n", " switchboard_id=1,\n", " rated_power_available_total=10000,\n", " no_power_sources=2,\n", - " no_power_consumer=3\n", + " no_power_consumer=3,\n", ")\n", "\n", "switchboard = convert_switchboard_to_protobuf(switchboard_feems)\n", "assert len(switchboard_feems.components) == len(switchboard.subsystems)\n", - "for subsystem, component_feems in zip(switchboard.subsystems, switchboard_feems.components):\n", + "for subsystem, component_feems in zip(\n", + " switchboard.subsystems, switchboard_feems.components\n", + "):\n", " assert subsystem.component_type == component_feems.type.value\n", "\n", "shaftline_feems = create_shaftline_with_components(\n", @@ -748,7 +819,7 @@ " no_power_sources=2,\n", " no_power_consumer=1,\n", " has_gear=True,\n", - " has_pti_pto=True\n", + " has_pti_pto=True,\n", ")\n", "\n", "shaftline_proto = convert_shaftline_to_protobuf(shaftline_feems)\n", @@ -757,18 +828,14 @@ }, { "cell_type": "code", - "execution_count": 5, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:20.440108Z", - "start_time": "2023-11-27T14:04:20.419818Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| export\n", - "def convert_electric_system_to_protobuf(electric_system: ElectricPowerSystem) \\\n", - " -> proto.ElectricSystem:\n", + "# | export\n", + "def convert_electric_system_to_protobuf(\n", + " electric_system: ElectricPowerSystem,\n", + ") -> proto.ElectricSystem:\n", " \"\"\"Convert electric system to protobuf message\"\"\"\n", " return proto.ElectricSystem(\n", " switchboards=[\n", @@ -780,7 +847,7 @@ "\n", "def convert_electric_system_to_protobuf_machinery_system(\n", " electric_system: ElectricPowerSystem,\n", - " maximum_allowed_genset_load_percentage: float = 80.0\n", + " maximum_allowed_genset_load_percentage: float = 80.0,\n", ") -> proto.MachinerySystem:\n", " \"\"\"Convert electric system to protobuf message as a machinery system\"\"\"\n", " return proto.MachinerySystem(\n", @@ -788,11 +855,12 @@ " propulsion_type=proto.MachinerySystem.PropulsionType.ELECTRIC,\n", " fuel_storage=[],\n", " maximum_allowed_genset_load_percentage=maximum_allowed_genset_load_percentage,\n", - " electric_system=convert_electric_system_to_protobuf(electric_system)\n", + " electric_system=convert_electric_system_to_protobuf(electric_system),\n", " )\n", "\n", + "\n", "def convert_mechanical_system_to_protobuf(\n", - " mechanical_propulsion_system: MechanicalPropulsionSystem\n", + " mechanical_propulsion_system: MechanicalPropulsionSystem,\n", ") -> proto.MechanicalSystem:\n", " return proto.MechanicalSystem(\n", " shaft_lines=[\n", @@ -811,8 +879,12 @@ " propulsion_type=proto.MachinerySystem.PropulsionType.MECHANICAL,\n", " fuel_storage=[],\n", " maximum_allowed_genset_load_percentage=maximum_allowed_genset_load_percentage,\n", - " mechanical_system=convert_mechanical_system_to_protobuf(system_feems.mechanical_system),\n", - " electric_system=convert_electric_system_to_protobuf(system_feems.electric_system)\n", + " mechanical_system=convert_mechanical_system_to_protobuf(\n", + " system_feems.mechanical_system\n", + " ),\n", + " electric_system=convert_electric_system_to_protobuf(\n", + " system_feems.electric_system\n", + " ),\n", " )\n", "\n", "\n", @@ -825,8 +897,12 @@ " propulsion_type=proto.MachinerySystem.HYBRID,\n", " fuel_storage=[],\n", " maximum_allowed_genset_load_percentage=maximum_allowed_genset_load_percentage,\n", - " mechanical_system=convert_mechanical_system_to_protobuf(system_feems.mechanical_system),\n", - " electric_system=convert_electric_system_to_protobuf(system_feems.electric_system)\n", + " mechanical_system=convert_mechanical_system_to_protobuf(\n", + " system_feems.mechanical_system\n", + " ),\n", + " electric_system=convert_electric_system_to_protobuf(\n", + " system_feems.electric_system\n", + " ),\n", " )" ] }, @@ -839,13 +915,8 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:20.509534Z", - "start_time": "2023-11-27T14:04:20.431783Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [ { "name": "stderr", @@ -2658,19 +2729,17 @@ "\n", "import numpy as np\n", "from MachSysS.convert_to_protobuf import (\n", - " convert_electric_system_to_protobuf, \n", - " convert_mechanical_system_to_protobuf, \n", + " convert_electric_system_to_protobuf,\n", + " convert_mechanical_system_to_protobuf,\n", " convert_mechanical_propulsion_system_with_electric_system_to_protobuf,\n", - " convert_electric_system_to_protobuf_machinery_system\n", + " convert_electric_system_to_protobuf_machinery_system,\n", ")\n", "from feems.system_model import (\n", " ElectricPowerSystem,\n", " MechanicalPropulsionSystem,\n", - " MechanicalPropulsionSystemWithElectricPowerSystem\n", - ")\n", - "from feems.components_model.component_mechanical import (\n", - " Engine\n", + " MechanicalPropulsionSystemWithElectricPowerSystem,\n", ")\n", + "from feems.components_model.component_mechanical import Engine\n", "from feems.components_model.component_electric import (\n", " Genset,\n", " Battery,\n", @@ -2681,26 +2750,25 @@ " FuelCell,\n", " BatterySystem,\n", ")\n", - "from feems.fuel import (\n", - " TypeFuel, FuelOrigin\n", - ")\n", - "from feems.types_for_feems import (\n", - " TypePower, TypeComponent, NOxCalculationMethod\n", + "from feems.fuel import TypeFuel, FuelOrigin\n", + "from feems.types_for_feems import TypePower, TypeComponent, NOxCalculationMethod\n", + "from tests.utility import (\n", + " create_switchboard_with_components,\n", + " create_shaftline_with_components,\n", ")\n", - "from tests.utility import create_switchboard_with_components, create_shaftline_with_components\n", "\n", "components = []\n", - "for switchboard_id in [1,2,3]:\n", - " components.extend(create_switchboard_with_components(\n", - " switchboard_id=switchboard_id,\n", - " rated_power_available_total=10000*random.random(),\n", - " no_power_sources=2,\n", - " no_power_consumer=3\n", - " ).components)\n", + "for switchboard_id in [1, 2, 3]:\n", + " components.extend(\n", + " create_switchboard_with_components(\n", + " switchboard_id=switchboard_id,\n", + " rated_power_available_total=10000 * random.random(),\n", + " no_power_sources=2,\n", + " no_power_consumer=3,\n", + " ).components\n", + " )\n", "electric_system = ElectricPowerSystem(\n", - " name=\"El 1\",\n", - " power_plant_components=components,\n", - " bus_tie_connections=[(1,2), (2,3)]\n", + " name=\"El 1\", power_plant_components=components, bus_tie_connections=[(1, 2), (2, 3)]\n", ")\n", "electric_system_proto = convert_electric_system_to_protobuf(electric_system)\n", "assert len(electric_system.switchboards) == len(electric_system_proto.switchboards)\n", @@ -2719,145 +2787,178 @@ "system_feems = MechanicalPropulsionSystemWithElectricPowerSystem(\n", " name=\"ME Propulsion System\",\n", " mechanical_system=mechanical_system,\n", - " electric_system=electric_system\n", + " electric_system=electric_system,\n", + ")\n", + "system_proto = convert_mechanical_propulsion_system_with_electric_system_to_protobuf(\n", + " system_feems\n", ")\n", - "system_proto = convert_mechanical_propulsion_system_with_electric_system_to_protobuf(system_feems)\n", "print(system_proto)\n", "\n", "# Create an electric propulsion system\n", "number_gensets = 4\n", "gensets = []\n", "for index in range(number_gensets):\n", - " gensets.append(Genset(\n", - " name=f\"Genset {index + 1}\",\n", - " aux_engine=Engine(\n", - " type_=TypeComponent.AUXILIARY_ENGINE,\n", - " rated_power=1000,\n", - " rated_speed=1000,\n", - " bsfc_curve=np.array([\n", - " [0.1, 270], [0.25, 240], [0.5, 220], [0.75, 210], [1.0, 220]\n", - " ]),\n", - " nox_calculation_method=NOxCalculationMethod.TIER_3,\n", - " fuel_type=TypeFuel.DIESEL,\n", - " fuel_origin=FuelOrigin.FOSSIL,\n", - " ),\n", - " generator=ElectricMachine(\n", - " type_=TypeComponent.GENERATOR,\n", - " power_type=TypePower.POWER_SOURCE,\n", - " name=f\"Generator {index + 1}\",\n", - " rated_power=1000,\n", - " rated_speed=1000,\n", - " eff_curve=np.array([\n", - " [0.1, 0.70], [0.25, 0.85], [0.5, 0.96], [0.75, 0.97],\n", - " ]),\n", - " switchboard_id=int(index/2) + 1\n", - " ),\n", - " ))\n", + " gensets.append(\n", + " Genset(\n", + " name=f\"Genset {index + 1}\",\n", + " aux_engine=Engine(\n", + " type_=TypeComponent.AUXILIARY_ENGINE,\n", + " rated_power=1000,\n", + " rated_speed=1000,\n", + " bsfc_curve=np.array(\n", + " [[0.1, 270], [0.25, 240], [0.5, 220], [0.75, 210], [1.0, 220]]\n", + " ),\n", + " nox_calculation_method=NOxCalculationMethod.TIER_3,\n", + " fuel_type=TypeFuel.DIESEL,\n", + " fuel_origin=FuelOrigin.FOSSIL,\n", + " ),\n", + " generator=ElectricMachine(\n", + " type_=TypeComponent.GENERATOR,\n", + " power_type=TypePower.POWER_SOURCE,\n", + " name=f\"Generator {index + 1}\",\n", + " rated_power=1000,\n", + " rated_speed=1000,\n", + " eff_curve=np.array(\n", + " [\n", + " [0.1, 0.70],\n", + " [0.25, 0.85],\n", + " [0.5, 0.96],\n", + " [0.75, 0.97],\n", + " ]\n", + " ),\n", + " switchboard_id=int(index / 2) + 1,\n", + " ),\n", + " )\n", + " )\n", "energy_storages = []\n", "power_consumers = []\n", "fuel_cell_systems = []\n", "number_batteries = 2\n", "for index in range(number_batteries):\n", - " energy_storages.append(BatterySystem(\n", - " name=\"Battery system 1\",\n", - " battery=Battery(\n", - " name=\"Battery 1\",\n", - " rated_capacity_kwh=1000,\n", - " charging_rate_c=1,\n", - " discharge_rate_c=1,\n", - " switchboard_id=index + 1\n", - " ),\n", - " converter=ElectricComponent(\n", - " type_=TypeComponent.POWER_CONVERTER,\n", - " power_type=TypePower.POWER_TRANSMISSION,\n", - " name=\"Converter 1\",\n", - " rated_power=1000,\n", - " eff_curve=np.array([\n", - " [0.1, 0.90], [0.25, 0.95], [0.5, 0.96], [0.75, 0.97], [1.0, 0.96]\n", - " ]),\n", - " ),\n", - " switchboard_id=index + 1\n", - " ))\n", - " \n", - "number_propulsion_drives = 2\n", - "for index in range(number_propulsion_drives):\n", - " power_consumers.append(SerialSystemElectric(\n", - " name=\"Propulsion Drive 1\",\n", - " type_=TypeComponent.PROPULSION_DRIVE,\n", - " power_type=TypePower.POWER_CONSUMER,\n", - " components=[\n", - " ElectricComponent(\n", + " energy_storages.append(\n", + " BatterySystem(\n", + " name=\"Battery system 1\",\n", + " battery=Battery(\n", + " name=\"Battery 1\",\n", + " rated_capacity_kwh=1000,\n", + " charging_rate_c=1,\n", + " discharge_rate_c=1,\n", + " switchboard_id=index + 1,\n", + " ),\n", + " converter=ElectricComponent(\n", " type_=TypeComponent.POWER_CONVERTER,\n", " power_type=TypePower.POWER_TRANSMISSION,\n", " name=\"Converter 1\",\n", - " rated_power=2000,\n", - " eff_curve=np.array([\n", - " [0.1, 0.90], [0.25, 0.95], [0.5, 0.96], [0.75, 0.97], [1.0, 0.96]\n", - " ]),\n", - " switchboard_id=index + 1\n", - " ),\n", - " ElectricMachine(\n", - " type_=TypeComponent.SYNCHRONOUS_MACHINE,\n", - " power_type=TypePower.POWER_CONSUMER,\n", - " name=\"Propulsion motor 1\",\n", - " rated_power=2000,\n", - " rated_speed=1000,\n", - " eff_curve=np.array([\n", - " [0.1, 0.70], [0.25, 0.85], [0.5, 0.96], [0.75, 0.97], [1.0, 0.96]\n", - " ]),\n", - " switchboard_id=index + 1\n", + " rated_power=1000,\n", + " eff_curve=np.array(\n", + " [[0.1, 0.90], [0.25, 0.95], [0.5, 0.96], [0.75, 0.97], [1.0, 0.96]]\n", + " ),\n", " ),\n", - " ],\n", - " switchboard_id=index + 1,\n", - " rated_power=2000,\n", - " rated_speed=1000,\n", - " ))\n", + " switchboard_id=index + 1,\n", + " )\n", + " )\n", + "\n", + "number_propulsion_drives = 2\n", + "for index in range(number_propulsion_drives):\n", + " power_consumers.append(\n", + " SerialSystemElectric(\n", + " name=\"Propulsion Drive 1\",\n", + " type_=TypeComponent.PROPULSION_DRIVE,\n", + " power_type=TypePower.POWER_CONSUMER,\n", + " components=[\n", + " ElectricComponent(\n", + " type_=TypeComponent.POWER_CONVERTER,\n", + " power_type=TypePower.POWER_TRANSMISSION,\n", + " name=\"Converter 1\",\n", + " rated_power=2000,\n", + " eff_curve=np.array(\n", + " [\n", + " [0.1, 0.90],\n", + " [0.25, 0.95],\n", + " [0.5, 0.96],\n", + " [0.75, 0.97],\n", + " [1.0, 0.96],\n", + " ]\n", + " ),\n", + " switchboard_id=index + 1,\n", + " ),\n", + " ElectricMachine(\n", + " type_=TypeComponent.SYNCHRONOUS_MACHINE,\n", + " power_type=TypePower.POWER_CONSUMER,\n", + " name=\"Propulsion motor 1\",\n", + " rated_power=2000,\n", + " rated_speed=1000,\n", + " eff_curve=np.array(\n", + " [\n", + " [0.1, 0.70],\n", + " [0.25, 0.85],\n", + " [0.5, 0.96],\n", + " [0.75, 0.97],\n", + " [1.0, 0.96],\n", + " ]\n", + " ),\n", + " switchboard_id=index + 1,\n", + " ),\n", + " ],\n", + " switchboard_id=index + 1,\n", + " rated_power=2000,\n", + " rated_speed=1000,\n", + " )\n", + " )\n", "\n", "# Add other load\n", - "power_consumers.append(ElectricComponent(\n", - " type_=TypeComponent.OTHER_LOAD,\n", - " power_type=TypePower.POWER_CONSUMER,\n", - " name=\"Other load 1\",\n", - " rated_power=1000,\n", - " switchboard_id=1\n", - ")) \n", + "power_consumers.append(\n", + " ElectricComponent(\n", + " type_=TypeComponent.OTHER_LOAD,\n", + " power_type=TypePower.POWER_CONSUMER,\n", + " name=\"Other load 1\",\n", + " rated_power=1000,\n", + " switchboard_id=1,\n", + " )\n", + ")\n", "\n", "# Add fuel cells\n", "number_fuel_cells = 2\n", "for index in range(number_fuel_cells):\n", - " fuel_cell_systems.append(FuelCellSystem(\n", - " name=\"Fuel cell system 1\",\n", - " fuel_cell_module=FuelCell(\n", - " name=\"Fuel cell 1\",\n", - " rated_power=1000,\n", - " eff_curve=np.array([\n", - " [0.1, 0.70], [0.25, 0.85], [0.5, 0.96], [0.75, 0.97], [1.0, 0.96]\n", - " ]),\n", - " fuel_type=TypeFuel.HYDROGEN,\n", - " fuel_origin=FuelOrigin.RENEWABLE_NON_BIO,\n", - " ),\n", - " converter=ElectricComponent(\n", - " type_=TypeComponent.POWER_CONVERTER,\n", - " power_type=TypePower.POWER_TRANSMISSION,\n", - " name=\"Converter 1\",\n", - " rated_power=3150,\n", - " eff_curve=np.array([\n", - " [0.1, 0.90], [0.25, 0.95], [0.5, 0.96], [0.75, 0.97], [1.0, 0.96]\n", - " ]),\n", - " ),\n", - " switchboard_id=index + 1,\n", - " number_modules=3\n", - " ))\n", + " fuel_cell_systems.append(\n", + " FuelCellSystem(\n", + " name=\"Fuel cell system 1\",\n", + " fuel_cell_module=FuelCell(\n", + " name=\"Fuel cell 1\",\n", + " rated_power=1000,\n", + " eff_curve=np.array(\n", + " [[0.1, 0.70], [0.25, 0.85], [0.5, 0.96], [0.75, 0.97], [1.0, 0.96]]\n", + " ),\n", + " fuel_type=TypeFuel.HYDROGEN,\n", + " fuel_origin=FuelOrigin.RENEWABLE_NON_BIO,\n", + " ),\n", + " converter=ElectricComponent(\n", + " type_=TypeComponent.POWER_CONVERTER,\n", + " power_type=TypePower.POWER_TRANSMISSION,\n", + " name=\"Converter 1\",\n", + " rated_power=3150,\n", + " eff_curve=np.array(\n", + " [[0.1, 0.90], [0.25, 0.95], [0.5, 0.96], [0.75, 0.97], [1.0, 0.96]]\n", + " ),\n", + " ),\n", + " switchboard_id=index + 1,\n", + " number_modules=3,\n", + " )\n", + " )\n", "# Create the electric system\n", "electric_system = ElectricPowerSystem(\n", " name=\"Electric propulsion system\",\n", - " power_plant_components=gensets + energy_storages + power_consumers + fuel_cell_systems,\n", - " bus_tie_connections=[(1,2)]\n", + " power_plant_components=gensets\n", + " + energy_storages\n", + " + power_consumers\n", + " + fuel_cell_systems,\n", + " bus_tie_connections=[(1, 2)],\n", ")\n", "\n", "system_proto = convert_electric_system_to_protobuf_machinery_system(electric_system)\n", "fuel_cells = [\n", - " subsystem.fuel_cell for switchboard in system_proto.electric_system.switchboards\n", + " subsystem.fuel_cell\n", + " for switchboard in system_proto.electric_system.switchboards\n", " for subsystem in switchboard.subsystems\n", " if subsystem.HasField(\"fuel_cell\")\n", "]\n", @@ -2877,13 +2978,8 @@ }, { "cell_type": "code", - "execution_count": 7, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:20.525466Z", - "start_time": "2023-11-27T14:04:20.511367Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ "# Create a system\n", @@ -2893,53 +2989,58 @@ " Engine,\n", " EngineDualFuel,\n", " MechanicalPropulsionComponent,\n", - " MainEngineForMechanicalPropulsion\n", + " MainEngineForMechanicalPropulsion,\n", ")\n", "from feems.components_model.component_electric import (\n", " Genset,\n", - " ElectricComponent, ElectricMachine,\n", + " ElectricComponent,\n", + " ElectricMachine,\n", ")\n", "from feems.system_model import (\n", " MechanicalPropulsionSystem,\n", " ElectricPowerSystem,\n", - " MechanicalPropulsionSystemWithElectricPowerSystem\n", - ")\n", - "from feems.types_for_feems import (\n", - " TypeComponent, Power_kW, Speed_rpm, TypePower\n", + " MechanicalPropulsionSystemWithElectricPowerSystem,\n", ")\n", + "from feems.types_for_feems import TypeComponent, Power_kW, Speed_rpm, TypePower\n", "from feems.fuel import TypeFuel, FuelOrigin\n", - "from MachSysS.convert_to_protobuf import convert_mechanical_propulsion_system_with_electric_system_to_protobuf\n", + "from MachSysS.convert_to_protobuf import (\n", + " convert_mechanical_propulsion_system_with_electric_system_to_protobuf,\n", + ")\n", "from functools import reduce\n", "\n", "# Create the engine\n", - "bsfc_for_main_engine = np.array([\n", - " [.25, 151.2],\n", - " [.30, 149.5],\n", - " [.40, 146.3],\n", - " [.50, 143.2],\n", - " [.60, 141.7],\n", - " [.70, 141.0],\n", - " [.75, 140.8],\n", - " [.80, 140.9],\n", - " [.85, 141.0],\n", - " [.90, 141.4],\n", - " [.95, 141.9],\n", - " [1.00, 142.8]\n", - "])\n", - "bspfc_for_main_engine = np.array([\n", - " [.25, 1.6],\n", - " [.30, 1.4],\n", - " [.40, 1.1],\n", - " [.50, 0.9],\n", - " [.60, 0.8],\n", - " [.70, 0.8],\n", - " [.75, 0.7],\n", - " [.80, 0.7],\n", - " [.85, 0.7],\n", - " [.90, 0.6],\n", - " [.95, 0.6],\n", - " [1.00, 0.6]\n", - "])\n", + "bsfc_for_main_engine = np.array(\n", + " [\n", + " [0.25, 151.2],\n", + " [0.30, 149.5],\n", + " [0.40, 146.3],\n", + " [0.50, 143.2],\n", + " [0.60, 141.7],\n", + " [0.70, 141.0],\n", + " [0.75, 140.8],\n", + " [0.80, 140.9],\n", + " [0.85, 141.0],\n", + " [0.90, 141.4],\n", + " [0.95, 141.9],\n", + " [1.00, 142.8],\n", + " ]\n", + ")\n", + "bspfc_for_main_engine = np.array(\n", + " [\n", + " [0.25, 1.6],\n", + " [0.30, 1.4],\n", + " [0.40, 1.1],\n", + " [0.50, 0.9],\n", + " [0.60, 0.8],\n", + " [0.70, 0.8],\n", + " [0.75, 0.7],\n", + " [0.80, 0.7],\n", + " [0.85, 0.7],\n", + " [0.90, 0.6],\n", + " [0.95, 0.6],\n", + " [1.00, 0.6],\n", + " ]\n", + ")\n", "main_engine = MainEngineForMechanicalPropulsion(\n", " engine=EngineDualFuel(\n", " type_=TypeComponent.MAIN_ENGINE,\n", @@ -2954,7 +3055,7 @@ " nox_calculation_method=NOxCalculationMethod.TIER_3,\n", " ),\n", " name=\"Main engine for mechanical propulsion\",\n", - " shaft_line_id=1\n", + " shaft_line_id=1,\n", ")\n", "propeller = MechanicalPropulsionComponent(\n", " type_=TypeComponent.PROPELLER_LOAD,\n", @@ -2962,31 +3063,32 @@ " name=\"Propeller\",\n", " rated_power=Power_kW(25000),\n", " rated_speed=Speed_rpm(60),\n", - " shaft_line_id=1\n", + " shaft_line_id=1,\n", ")\n", "mechanical_propulsion_system = MechanicalPropulsionSystem(\n", - " name=\"Mechanical propulsion system\",\n", - " components_list=[main_engine, propeller]\n", + " name=\"Mechanical propulsion system\", components_list=[main_engine, propeller]\n", ")\n", "number_gensets = 3\n", - "bsfc_for_aux_engine = np.array([\n", - " [.25, 248.0],\n", - " [.30, 235.0],\n", - " [.35, 225.0],\n", - " [.40, 218.0],\n", - " [.45, 213.0],\n", - " [.50, 208.0],\n", - " [.55, 205.0],\n", - " [.60, 203.0],\n", - " [.65, 200.0],\n", - " [.70, 199.0],\n", - " [.75, 197.0],\n", - " [.80, 197.0],\n", - " [.85, 196.0],\n", - " [.90, 196.0],\n", - " [.95, 196.0],\n", - " [1.00, 195.2]\n", - "])\n", + "bsfc_for_aux_engine = np.array(\n", + " [\n", + " [0.25, 248.0],\n", + " [0.30, 235.0],\n", + " [0.35, 225.0],\n", + " [0.40, 218.0],\n", + " [0.45, 213.0],\n", + " [0.50, 208.0],\n", + " [0.55, 205.0],\n", + " [0.60, 203.0],\n", + " [0.65, 200.0],\n", + " [0.70, 199.0],\n", + " [0.75, 197.0],\n", + " [0.80, 197.0],\n", + " [0.85, 196.0],\n", + " [0.90, 196.0],\n", + " [0.95, 196.0],\n", + " [1.00, 195.2],\n", + " ]\n", + ")\n", "gensets = [\n", " Genset(\n", " name=f\"Genset {i + 1}\",\n", @@ -3005,21 +3107,23 @@ " name=f\"Generator {i + 1}\",\n", " rated_power=Power_kW(1000),\n", " rated_speed=Speed_rpm(900),\n", - " eff_curve=np.array([\n", - " [0.0, 0.88],\n", - " [0.1, 0.89],\n", - " [0.2, 0.90],\n", - " [0.3, 0.91],\n", - " [0.4, 0.92],\n", - " [0.5, 0.93],\n", - " [0.6, 0.93],\n", - " [0.7, 0.94],\n", - " [0.8, 0.94],\n", - " [0.9, 0.95],\n", - " [1.0, 0.95],\n", - " ]),\n", + " eff_curve=np.array(\n", + " [\n", + " [0.0, 0.88],\n", + " [0.1, 0.89],\n", + " [0.2, 0.90],\n", + " [0.3, 0.91],\n", + " [0.4, 0.92],\n", + " [0.5, 0.93],\n", + " [0.6, 0.93],\n", + " [0.7, 0.94],\n", + " [0.8, 0.94],\n", + " [0.9, 0.95],\n", + " [1.0, 0.95],\n", + " ]\n", + " ),\n", " power_type=TypePower.POWER_SOURCE,\n", - " switchboard_id=int(i/2) + 1\n", + " switchboard_id=int(i / 2) + 1,\n", " ),\n", " )\n", " for i in range(number_gensets)\n", @@ -3029,29 +3133,24 @@ " name=\"Other load\",\n", " rated_power=Power_kW(4000),\n", " power_type=TypePower.POWER_CONSUMER,\n", - " switchboard_id=1\n", + " switchboard_id=1,\n", ")\n", "electric_power_system = ElectricPowerSystem(\n", " name=\"Electric power system\",\n", " power_plant_components=[*gensets, other_load],\n", - " bus_tie_connections=[(1, 1)]\n", + " bus_tie_connections=[(1, 1)],\n", ")\n", "machinery_system = MechanicalPropulsionSystemWithElectricPowerSystem(\n", " name=\"Base case system\",\n", " mechanical_system=mechanical_propulsion_system,\n", - " electric_system=electric_power_system\n", + " electric_system=electric_power_system,\n", ")" ] }, { "cell_type": "code", - "execution_count": 8, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:20.553975Z", - "start_time": "2023-11-27T14:04:20.526180Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -3232,13 +3331,8 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:20.554663Z", - "start_time": "2023-11-27T14:04:20.536484Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -3890,21 +3984,18 @@ ], "source": [ "# Conversion of the mechanical propulsion system with electric power system\n", - "mechanical_propulsion_system_with_electric_system_proto = convert_mechanical_propulsion_system_with_electric_system_to_protobuf(\n", - " system_feems=machinery_system\n", + "mechanical_propulsion_system_with_electric_system_proto = (\n", + " convert_mechanical_propulsion_system_with_electric_system_to_protobuf(\n", + " system_feems=machinery_system\n", + " )\n", ")\n", "print(mechanical_propulsion_system_with_electric_system_proto)" ] }, { "cell_type": "code", - "execution_count": 10, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:20.566212Z", - "start_time": "2023-11-27T14:04:20.552602Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -4752,7 +4843,7 @@ " name=\"rectifier\",\n", " rated_power=rated_power,\n", " eff_curve=np.array([99.5]),\n", - " switchboard_id=switchboard_id\n", + " switchboard_id=switchboard_id,\n", ")\n", "\n", "# Create a inverter instance\n", @@ -4762,7 +4853,7 @@ " name=\"inverter\",\n", " rated_power=rated_power,\n", " eff_curve=np.array([98.5]),\n", - " switchboard_id=switchboard_id\n", + " switchboard_id=switchboard_id,\n", ")\n", "\n", "# Create a transformer instance\n", @@ -4772,7 +4863,7 @@ " name=\"transformer\",\n", " rated_power=rated_power,\n", " eff_curve=np.array([99]),\n", - " switchboard_id=switchboard_id\n", + " switchboard_id=switchboard_id,\n", ")\n", "\n", "pto = PTIPTO(\n", @@ -4788,12 +4879,12 @@ "all_electric_components = reduce(\n", " lambda acc, switchboard: [*acc, *switchboard.components],\n", " machinery_system.electric_system.switchboards.values(),\n", - " [pto]\n", + " [pto],\n", ")\n", "bus_tie_breakers = reduce(\n", " lambda acc, bus_tie_breaker: [*acc, bus_tie_breaker.switchboard_ids],\n", " machinery_system.electric_system.bus_tie_breakers,\n", - " []\n", + " [],\n", ")\n", "electric_system_with_pto = ElectricPowerSystem(\n", " name=\"electric power system with PTO\",\n", @@ -4805,7 +4896,7 @@ "all_mechanical_components = reduce(\n", " lambda acc, shaftline: [*acc, *shaftline.components],\n", " machinery_system.mechanical_system.shaft_line,\n", - " [pto]\n", + " [pto],\n", ")\n", "\n", "mechanical_system_with_pto = MechanicalPropulsionSystem(\n", @@ -4827,13 +4918,8 @@ }, { "cell_type": "code", - "execution_count": 11, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:04:20.601773Z", - "start_time": "2023-11-27T14:04:20.566500Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ "# Save the systems to a file\n", @@ -4844,8 +4930,7 @@ " mechanical_propulsion_system=mechanical_system_with_pto\n", ")\n", "electric_propulsion_system_proto = convert_electric_system_to_protobuf_machinery_system(\n", - " electric_system=electric_system,\n", - " maximum_allowed_genset_load_percentage=80\n", + " electric_system=electric_system, maximum_allowed_genset_load_percentage=80\n", ")\n", "files_to_save = {\n", " \"electric_system_with_pto.mss\": electric_system_with_pto_proto,\n", diff --git a/machinery-system-structure/02_Utility.ipynb b/machinery-system-structure/02_Utility.ipynb index 00e261b..11325d3 100644 --- a/machinery-system-structure/02_Utility.ipynb +++ b/machinery-system-structure/02_Utility.ipynb @@ -18,7 +18,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| default_exp utility\n", + "# | default_exp utility\n", "%load_ext autoreload\n", "%autoreload 2" ] @@ -29,7 +29,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| include: false\n", + "# | include: false\n", "from nbdev.showdoc import *" ] }, @@ -39,7 +39,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| export\n", + "# | export\n", "import io\n", "import os\n", "from typing import Union\n", @@ -59,7 +59,9 @@ " return system\n", "\n", "\n", - "def retrieve_gymir_result_from_file(file: Union[str, io.BytesIO]) -> proto_gymir.GymirResult:\n", + "def retrieve_gymir_result_from_file(\n", + " file: Union[str, io.BytesIO]\n", + ") -> proto_gymir.GymirResult:\n", " if isinstance(file, str):\n", " file = open(file, \"rb\")\n", " system = proto_gymir.GymirResult()\n", diff --git a/machinery-system-structure/03_ConvertFEEMSResultToProto.ipynb b/machinery-system-structure/03_ConvertFEEMSResultToProto.ipynb index 3da7d6f..2eb887c 100644 --- a/machinery-system-structure/03_ConvertFEEMSResultToProto.ipynb +++ b/machinery-system-structure/03_ConvertFEEMSResultToProto.ipynb @@ -16,48 +16,33 @@ }, { "cell_type": "code", - "execution_count": 1, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:19:50.345345Z", - "start_time": "2023-11-27T14:19:50.276901Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| default_exp convert_feems_result_to_proto\n", + "# | default_exp convert_feems_result_to_proto\n", "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", - "execution_count": 2, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:19:50.355402Z", - "start_time": "2023-11-27T14:19:50.287632Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| include: false\n", + "# | include: false\n", "\n", "from nbdev.showdoc import *" ] }, { "cell_type": "code", - "execution_count": 3, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:19:50.860396Z", - "start_time": "2023-11-27T14:19:50.355929Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| export\n", + "# | export\n", "from functools import cached_property\n", "from typing import Union, List, Dict, Optional, cast\n", "\n", @@ -69,7 +54,7 @@ " ElectricPowerSystem,\n", " HybridPropulsionSystem,\n", " MechanicalPropulsionSystem,\n", - " FEEMSResultForMachinerySystem\n", + " FEEMSResultForMachinerySystem,\n", ")\n", "import pandas as pd\n", "import numpy as np\n", @@ -80,16 +65,11 @@ }, { "cell_type": "code", - "execution_count": 4, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:19:50.902752Z", - "start_time": "2023-11-27T14:19:50.873230Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "#| export\n", + "# | export\n", "# Define logger\n", "logger = logging.getLogger(__name__)\n", "logger.setLevel(logging.INFO)\n", @@ -97,7 +77,7 @@ "ch = logging.StreamHandler()\n", "ch.setLevel(logging.INFO)\n", "\n", - "formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')\n", + "formatter = logging.Formatter(\"%(asctime)s - %(name)s - %(levelname)s - %(message)s\")\n", "ch.setFormatter(formatter)\n", "\n", "logger.addHandler(ch)\n", @@ -127,15 +107,13 @@ " MechanicalPropulsionSystemWithElectricPowerSystem,\n", " ElectricPowerSystem,\n", " HybridPropulsionSystem,\n", - " None\n", + " None,\n", " ] = None\n", " _time_series_data_for_electric_component: Union[\n", - " List[Dict[str, proto.TimeSeriesResultForComponent]],\n", - " None\n", + " List[Dict[str, proto.TimeSeriesResultForComponent]], None\n", " ] = None\n", " _time_series_data_for_mechanical_component: Union[\n", - " List[Dict[str, proto.TimeSeriesResultForComponent]],\n", - " None\n", + " List[Dict[str, proto.TimeSeriesResultForComponent]], None\n", " ] = None\n", "\n", " def __init__(\n", @@ -170,11 +148,17 @@ "\n", " @property\n", " def electric_system(self) -> ElectricPowerSystem:\n", - " return self.system_feems if self.isSystemElectric else self.system_feems.electric_system\n", + " return (\n", + " self.system_feems\n", + " if self.isSystemElectric\n", + " else self.system_feems.electric_system\n", + " )\n", "\n", " @property\n", " def mechanical_system(self) -> MechanicalPropulsionSystem:\n", - " return self.system_feems.mechanical_system if not self.isSystemElectric else None\n", + " return (\n", + " self.system_feems.mechanical_system if not self.isSystemElectric else None\n", + " )\n", "\n", " @cached_property\n", " def _time_interval_to_time_array(self) -> np.ndarray:\n", @@ -182,14 +166,18 @@ " if self.time_series_input is None:\n", " time_interval_s = self.electric_system.time_interval_s\n", " if np.isscalar(time_interval_s):\n", - " return np.linspace(0, (number_points - 1) * time_interval_s, number_points)\n", + " return np.linspace(\n", + " 0, (number_points - 1) * time_interval_s, number_points\n", + " )\n", " else:\n", " return time_interval_s.cumsum()\n", " else:\n", - " return np.array([\n", - " power_instance.epoch_s\n", - " for power_instance in self.time_series_input.propulsion_power_timeseries\n", - " ])[:number_points]\n", + " return np.array(\n", + " [\n", + " power_instance.epoch_s\n", + " for power_instance in self.time_series_input.propulsion_power_timeseries\n", + " ]\n", + " )[:number_points]\n", "\n", " def _retrieve_time_series_data_from_components(self):\n", " \"\"\"Retrieve time series data from components of power sources and energy storages and\n", @@ -197,9 +185,11 @@ " the data in the proto data type of TimeSeriesResultForComponent and the switchboard id.\n", " \"\"\"\n", " # in the feems result\n", - " power_sources_electric = self.electric_system.power_sources \\\n", - " + self.electric_system.energy_storage \\\n", - " + self.electric_system.pti_pto\n", + " power_sources_electric = (\n", + " self.electric_system.power_sources\n", + " + self.electric_system.energy_storage\n", + " + self.electric_system.pti_pto\n", + " )\n", " if self.mechanical_system is not None:\n", " power_sources_mechanical = self.mechanical_system.main_engines\n", " else:\n", @@ -211,8 +201,10 @@ " power_output_kw=power_source.power_output.tolist(),\n", " )\n", " if power_source.type == TypeComponent.GENSET:\n", - " genset_result = power_source.get_fuel_cons_load_bsfc_from_power_out_generator_kw(\n", - " fuel_specified_by=self.fuel_specified_by,\n", + " genset_result = (\n", + " power_source.get_fuel_cons_load_bsfc_from_power_out_generator_kw(\n", + " fuel_specified_by=self.fuel_specified_by,\n", + " )\n", " )\n", " for fuel in genset_result.engine.fuel_flow_rate_kg_per_s.fuels:\n", " result_proto.fuel_consumption_kg_per_s.fuels.append(\n", @@ -224,9 +216,14 @@ " lhv_mj_per_g=fuel.lhv_mj_per_g,\n", " )\n", " )\n", - " elif power_source.type in [TypeComponent.FUEL_CELL_SYSTEM, TypeComponent.FUEL_CELL]:\n", + " elif power_source.type in [\n", + " TypeComponent.FUEL_CELL_SYSTEM,\n", + " TypeComponent.FUEL_CELL,\n", + " ]:\n", " power_source = cast(FuelCellSystem, power_source)\n", - " fuel_cell_result = power_source.get_fuel_cell_run_point(power_source.power_output)\n", + " fuel_cell_result = power_source.get_fuel_cell_run_point(\n", + " power_source.power_output\n", + " )\n", " for fuel in fuel_cell_result.fuel_flow_rate_kg_per_s.fuels:\n", " result_proto.fuel_consumption_kg_per_s.fuels.append(\n", " proto.FuelArray(\n", @@ -237,7 +234,10 @@ " lhv_mj_per_g=fuel.lhv_mj_per_g,\n", " )\n", " )\n", - " elif power_source.type in [TypeComponent.BATTERY, TypeComponent.BATTERY_SYSTEM]:\n", + " elif power_source.type in [\n", + " TypeComponent.BATTERY,\n", + " TypeComponent.BATTERY_SYSTEM,\n", + " ]:\n", " pass\n", " elif power_source.type == [TypeComponent.PTI_PTO_SYSTEM]:\n", " pass\n", @@ -279,11 +279,11 @@ " )\n", "\n", " def _get_feems_result_proto_for_subsystem(\n", - " self,\n", - " feems_result: FEEMSResult,\n", - " feems_system: Union[ElectricPowerSystem, MechanicalPropulsionSystem],\n", - " include_time_series_for_components: bool = False,\n", - " verbose: bool = False\n", + " self,\n", + " feems_result: FEEMSResult,\n", + " feems_system: Union[ElectricPowerSystem, MechanicalPropulsionSystem],\n", + " include_time_series_for_components: bool = False,\n", + " verbose: bool = False,\n", " ) -> proto.FeemsResult:\n", " \"\"\"Convert the result of FEEMS calculation to the proto data type of FeemsResult.\n", " Args:\n", @@ -300,8 +300,11 @@ " )\n", " if include_time_series_for_components:\n", " self._retrieve_time_series_data_from_components()\n", - " time_series_data = self._time_series_data_for_electric_component if is_electric \\\n", + " time_series_data = (\n", + " self._time_series_data_for_electric_component\n", + " if is_electric\n", " else self._time_series_data_for_mechanical_component\n", + " )\n", " else:\n", " time_series_data = None\n", " result = proto.FeemsResult()\n", @@ -331,14 +334,22 @@ " logger.warning(f\"Value for {key} is None.\")\n", " else:\n", " if verbose:\n", - " logger.warning(f\"There is no matching key in Protobuf message for {key}\")\n", + " logger.warning(\n", + " f\"There is no matching key in Protobuf message for {key}\"\n", + " )\n", " if feems_result.detail_result is not None:\n", - " for component_name, component_result in feems_result.detail_result.iterrows():\n", - " result_per_component = proto.ResultPerComponent(component_name=component_name)\n", + " for (\n", + " component_name,\n", + " component_result,\n", + " ) in feems_result.detail_result.iterrows():\n", + " result_per_component = proto.ResultPerComponent(\n", + " component_name=component_name\n", + " )\n", " for key, value in component_result.items():\n", " key_result_per_component = _COLUMN_NAMES.get(key)\n", - " if hasattr(result_per_component, key_result_per_component) \\\n", - " or result_per_component.HasField(key_result_per_component):\n", + " if hasattr(\n", + " result_per_component, key_result_per_component\n", + " ) or result_per_component.HasField(key_result_per_component):\n", " if key_result_per_component == \"multi_fuel_consumption_kg\":\n", " for fuel in value.fuels:\n", " result_per_component.multi_fuel_consumption_kg.fuels.append(\n", @@ -352,7 +363,9 @@ " )\n", " continue\n", " if value is not None:\n", - " setattr(result_per_component, key_result_per_component, value)\n", + " setattr(\n", + " result_per_component, key_result_per_component, value\n", + " )\n", " else:\n", " if verbose:\n", " logger.warning(f\"Value for {key} is None.\")\n", @@ -379,19 +392,19 @@ " time_series_item[\"node_id\"]\n", " == switchboard_shaft_line_id\n", " ),\n", - " time_series_data\n", + " time_series_data,\n", " )\n", " ).get(\"data\")\n", " )\n", " except StopIteration:\n", - " logger.warning(f\"No time-series data found for {component_name}\")\n", + " logger.warning(\n", + " f\"No time-series data found for {component_name}\"\n", + " )\n", " result.detailed_result.append(result_per_component)\n", " return result\n", "\n", " def get_feems_result_proto(\n", - " self,\n", - " include_time_series_for_components: bool = False,\n", - " verbose: bool = False\n", + " self, include_time_series_for_components: bool = False, verbose: bool = False\n", " ) -> proto.FeemsResultForMachinerySystem:\n", " if self.isSystemElectric:\n", " feems_result_electric = self._get_feems_result_proto_for_subsystem(\n", @@ -435,19 +448,16 @@ " data = each_time_series[\"data\"]\n", " df[f\"{name}-power_output_kw\"] = list(data.power_output_kw)\n", " if len(data.fuel_consumption_kg_per_s) > 0:\n", - " df[f\"{name}-fuel_consumption_kg_per_s\"] = list(data.fuel_consumption_kg_per_s)\n", + " df[f\"{name}-fuel_consumption_kg_per_s\"] = list(\n", + " data.fuel_consumption_kg_per_s\n", + " )\n", " return df" ] }, { "cell_type": "code", - "execution_count": 5, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:19:50.920379Z", - "start_time": "2023-11-27T14:19:50.904789Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ "import random\n", @@ -464,28 +474,25 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:19:50.938978Z", - "start_time": "2023-11-27T14:19:50.921212Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ "from feems.types_for_feems import TypePower\n", "\n", + "\n", "# Create a random GymirResult and load the system\n", "def create_gymir_result() -> GymirResult:\n", " return GymirResult(\n", " name=\"test\",\n", - " auxiliary_load_kw = 500 * random.random(),\n", + " auxiliary_load_kw=500 * random.random(),\n", " result=[\n", " SimulationInstance(epoch_s=100 * index + 1, power_kw=1000 * random.random())\n", " for index, _ in enumerate(range(10))\n", " ],\n", " )\n", "\n", + "\n", "path = os.path.join(\"tests\", \"system_proto.mss\")\n", "with open(path, \"rb\") as file:\n", " system_proto = MachinerySystem()\n", @@ -496,13 +503,8 @@ }, { "cell_type": "code", - "execution_count": 7, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-27T14:19:50.961446Z", - "start_time": "2023-11-27T14:19:50.940237Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -566,7 +568,7 @@ "Genset 3 2 \n", "Genset 4 2 \n", "Fuel cell system 1 2 \n", - "Battery system 1 2 , multi_fuel_consumption_total_kg=FuelConsumption(fuels=[, ]), co2_emission_total_kg=190.28127237235447, energy_input_mechanical_total_mj=0.0, energy_input_electric_total_mj=0.0, energy_consumption_propulsion_total_mj=517.7388296715692, energy_consumption_auxiliary_total_mj=255.6994485825417)\n", + "Battery system 1 2 , multi_fuel_consumption_total_kg=FuelConsumption(fuels=[, ]), co2_emission_total_kg=190.28127237235447, energy_input_mechanical_total_mj=0.0, energy_input_electric_total_mj=0.0, energy_consumption_propulsion_total_mj=517.7388296715692, energy_consumption_auxiliary_total_mj=255.6994485825417)\n", "electric_system {\n", " duration_s: 900\n", " multi_fuel_consumption_total_kg {\n", @@ -1095,8 +1097,7 @@ ], "source": [ "machinery_calculation = MachineryCalculation(\n", - " feems_system=system_feems,\n", - " maximum_allowed_power_source_load_percentage=80\n", + " feems_system=system_feems, maximum_allowed_power_source_load_percentage=80\n", ")\n", "gymir_result = create_gymir_result()\n", "res = machinery_calculation.calculate_machinery_system_output_from_gymir_result(\n", @@ -1104,17 +1105,20 @@ ")\n", "print(res)\n", "feems_result_converter = FEEMSResultConverter(\n", - " feems_result=res,\n", - " system_feems=machinery_calculation.system_feems\n", + " feems_result=res, system_feems=machinery_calculation.system_feems\n", ")\n", "number_sources = len(system_feems.power_sources)\n", "number_batteries = len(system_feems.energy_storage)\n", - "feems_result_proto = feems_result_converter.get_feems_result_proto(include_time_series_for_components=True)\n", - "assert number_sources + number_batteries == len(feems_result_converter._time_series_data_for_electric_component)\n", + "feems_result_proto = feems_result_converter.get_feems_result_proto(\n", + " include_time_series_for_components=True\n", + ")\n", + "assert number_sources + number_batteries == len(\n", + " feems_result_converter._time_series_data_for_electric_component\n", + ")\n", "number_points = len(system_feems.power_sources[0].power_output)\n", "for each_time_series, component in zip(\n", - " feems_result_converter._time_series_data_for_electric_component,\n", - " system_feems.power_sources + system_feems.energy_storage\n", + " feems_result_converter._time_series_data_for_electric_component,\n", + " system_feems.power_sources + system_feems.energy_storage,\n", "):\n", " assert each_time_series.get(\"name\") == component.name\n", " assert len(each_time_series.get(\"data\").time) == number_points\n", @@ -1125,8 +1129,10 @@ " for fuel in fuel_consumption.fuels:\n", " assert len(fuel.mass_or_mass_fraction) == number_points\n", "print(feems_result_proto)\n", - "feems_result_proto = feems_result_converter.get_feems_result_proto(include_time_series_for_components=False)\n", - "print(feems_result_proto)\n" + "feems_result_proto = feems_result_converter.get_feems_result_proto(\n", + " include_time_series_for_components=False\n", + ")\n", + "print(feems_result_proto)" ] } ], diff --git a/machinery-system-structure/04_ConvertGymirResultToProto.ipynb b/machinery-system-structure/04_ConvertGymirResultToProto.ipynb index 616e83a..8e1b4ac 100644 --- a/machinery-system-structure/04_ConvertGymirResultToProto.ipynb +++ b/machinery-system-structure/04_ConvertGymirResultToProto.ipynb @@ -20,7 +20,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| default_exp convert_gymir_result_to_proto\n", + "# | default_exp convert_gymir_result_to_proto\n", "%load_ext autoreload\n", "%autoreload 2" ] @@ -31,7 +31,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| include: false\n", + "# | include: false\n", "import json\n", "\n", "import pandas as pd\n", @@ -44,7 +44,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| export\n", + "# | export\n", "from io import BytesIO\n", "from typing import Union\n", "import pandas as pd\n", @@ -60,51 +60,51 @@ "ch = logging.StreamHandler()\n", "ch.setLevel(logging.INFO)\n", "\n", - "formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')\n", + "formatter = logging.Formatter(\"%(asctime)s - %(name)s - %(levelname)s - %(message)s\")\n", "ch.setFormatter(formatter)\n", "\n", "logger.addHandler(ch)\n", "\n", "vocabulary = {\n", - " 'task': 'task_type',\n", - " 'assignment': 'task_name',\n", - " 'latitude': 'latitude_deg',\n", - " 'longitude': 'longitude_deg',\n", - " 'heading': 'heading_deg',\n", - " 'wave height significant': 'wave_height_significant_m',\n", - " 'wave peak period (tp)': 'wave_peak_period_s',\n", - " 'wave direction in degrees relative to geographic north': 'wave_dir_rel_north_deg',\n", - " 'wave direction in degrees relative to vessel heading': 'wave_dir_rel_vessel_deg',\n", - " 'wind speed in meter per sec': 'wind_speed_mps',\n", - " 'wind direction in degrees relative to geographic north': 'wind_dir_rel_north_deg',\n", - " 'wind direction in degrees relative to vessel heading': 'wind_dir_rel_vessel_deg',\n", - " 'speed over ground': 'speed_over_ground_kn',\n", - " 'speed': 'speed_over_ground_kn',\n", - " 'speed through water': 'speed_through_water_kn',\n", - " 'sea current speed in meter pr sec': 'current_speed_mps',\n", - " 'sea current direction in degrees relative to geographic north': 'current_dir_rel_north_deg',\n", - " 'power': 'power_kw',\n", - " 'torque': 'torque_k_nm',\n", - " 'thrust': 'thrust_k_n',\n", - " 'rtot': 'total_resistance_k_n',\n", - " 'weather source': 'weather_source',\n", + " \"task\": \"task_type\",\n", + " \"assignment\": \"task_name\",\n", + " \"latitude\": \"latitude_deg\",\n", + " \"longitude\": \"longitude_deg\",\n", + " \"heading\": \"heading_deg\",\n", + " \"wave height significant\": \"wave_height_significant_m\",\n", + " \"wave peak period (tp)\": \"wave_peak_period_s\",\n", + " \"wave direction in degrees relative to geographic north\": \"wave_dir_rel_north_deg\",\n", + " \"wave direction in degrees relative to vessel heading\": \"wave_dir_rel_vessel_deg\",\n", + " \"wind speed in meter per sec\": \"wind_speed_mps\",\n", + " \"wind direction in degrees relative to geographic north\": \"wind_dir_rel_north_deg\",\n", + " \"wind direction in degrees relative to vessel heading\": \"wind_dir_rel_vessel_deg\",\n", + " \"speed over ground\": \"speed_over_ground_kn\",\n", + " \"speed\": \"speed_over_ground_kn\",\n", + " \"speed through water\": \"speed_through_water_kn\",\n", + " \"sea current speed in meter pr sec\": \"current_speed_mps\",\n", + " \"sea current direction in degrees relative to geographic north\": \"current_dir_rel_north_deg\",\n", + " \"power\": \"power_kw\",\n", + " \"torque\": \"torque_k_nm\",\n", + " \"thrust\": \"thrust_k_n\",\n", + " \"rtot\": \"total_resistance_k_n\",\n", + " \"weather source\": \"weather_source\",\n", "}\n", "\n", + "\n", "def find_csv_name_from_message_field_name(name: str) -> Union[str, None]:\n", " try:\n", - " return next(filter(\n", - " lambda key: vocabulary.get(key) == name,\n", - " vocabulary\n", - " ))\n", + " return next(filter(lambda key: vocabulary.get(key) == name, vocabulary))\n", " except StopIteration:\n", " return None\n", "\n", + "\n", "def get_message_type_for_simulation_instance(field_name: str) -> Union[str, None]:\n", " fields = proto.SimulationInstance.DESCRIPTOR.fields_by_name\n", " field = fields.get(field_name, None)\n", " if field is not None:\n", " return field.message_type if field.message_type is not None else field.type\n", "\n", + "\n", "class GymirResultConverter:\n", " gymir_result: Union[proto.GymirResult, None] = None\n", "\n", @@ -112,7 +112,7 @@ " self,\n", " *,\n", " file: Union[str, BytesIO] = None,\n", - " gymir_result: Union[proto.GymirResult, None] = None\n", + " gymir_result: Union[proto.GymirResult, None] = None,\n", " ):\n", " if file is not None:\n", " self.gymir_result = proto.GymirResult()\n", @@ -140,11 +140,12 @@ " if value is not None:\n", " file.write(f\"{epoch_s},{csv_name},{value}\\n\")\n", "\n", - " def read_csv(self, file: Union[str, BytesIO], auxiliary_load_kw: float = 0, name: str = None):\n", + " def read_csv(\n", + " self, file: Union[str, BytesIO], auxiliary_load_kw: float = 0, name: str = None\n", + " ):\n", " df = pd.read_csv(file, header=None)\n", " self.gymir_result = proto.GymirResult(\n", - " auxiliary_load_kw=auxiliary_load_kw,\n", - " name=name\n", + " auxiliary_load_kw=auxiliary_load_kw, name=name\n", " )\n", " epoch_s = 0\n", " current_simulation_instance = proto.SimulationInstance()\n", @@ -153,9 +154,7 @@ " if epoch_s != 0:\n", " self.gymir_result.result.append(current_simulation_instance)\n", " epoch_s = row[0]\n", - " current_simulation_instance = proto.SimulationInstance(\n", - " epoch_s=epoch_s\n", - " )\n", + " current_simulation_instance = proto.SimulationInstance(epoch_s=epoch_s)\n", " field_name = vocabulary.get(row[1])\n", " if field_name is None:\n", " logger.warning(f\"No field name found for {row[1]}\")\n", @@ -168,7 +167,7 @@ " FieldDescriptor.TYPE_INT32,\n", " FieldDescriptor.TYPE_INT64,\n", " FieldDescriptor.TYPE_UINT32,\n", - " FieldDescriptor.TYPE_UINT64\n", + " FieldDescriptor.TYPE_UINT64,\n", " ]:\n", " value = int(value)\n", " elif value_type == FieldDescriptor.TYPE_BOOL:\n", @@ -186,10 +185,15 @@ "source": [ "import json\n", "\n", - "with open(\"shipX2DeSim.json\", 'wt') as file:\n", - " file.write(json.dumps(list(map(\n", - " lambda each: dict(shipX=each, deSim=vocabulary[each]),\n", - " vocabulary)), indent=2))" + "with open(\"shipX2DeSim.json\", \"wt\") as file:\n", + " file.write(\n", + " json.dumps(\n", + " list(\n", + " map(lambda each: dict(shipX=each, deSim=vocabulary[each]), vocabulary)\n", + " ),\n", + " indent=2,\n", + " )\n", + " )" ] }, { diff --git a/machinery-system-structure/05_ConvertTimeSeriesResultProtoToPandas.ipynb b/machinery-system-structure/05_ConvertTimeSeriesResultProtoToPandas.ipynb index fd93d5c..2039f0e 100644 --- a/machinery-system-structure/05_ConvertTimeSeriesResultProtoToPandas.ipynb +++ b/machinery-system-structure/05_ConvertTimeSeriesResultProtoToPandas.ipynb @@ -29,7 +29,7 @@ } ], "source": [ - "#| default_exp convert_proto_timeseries\n", + "# | default_exp convert_proto_timeseries\n", "%load_ext autoreload\n", "%autoreload 2" ] @@ -40,7 +40,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| include: false\n", + "# | include: false\n", "from nbdev.showdoc import *" ] }, @@ -50,7 +50,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| export\n", + "# | export\n", "import pandas as pd\n", "import numpy as np\n", "import MachSysS.gymir_result_pb2 as proto\n", @@ -70,27 +70,40 @@ "logger.addHandler(ch)\n", "\n", "\n", - "def convert_proto_timeseries_to_pd_series(proto_timeseries: proto.TimeSeriesResult) -> pd.Series:\n", + "def convert_proto_timeseries_to_pd_series(\n", + " proto_timeseries: proto.TimeSeriesResult,\n", + ") -> pd.Series:\n", " \"\"\"Convert a TimeSeriesResult proto message to a pandas Series for propulsion power\"\"\"\n", " time = map(lambda each: each.epoch_s, proto_timeseries.propulsion_power_timeseries)\n", " propulsion_power = map(\n", - " lambda each: each.propulsion_power_kw, proto_timeseries.propulsion_power_timeseries\n", + " lambda each: each.propulsion_power_kw,\n", + " proto_timeseries.propulsion_power_timeseries,\n", " )\n", " return pd.Series(index=time, data=propulsion_power)\n", "\n", "\n", - "def convert_proto_timeseries_to_pd_dataframe(proto_timeseries: proto.TimeSeriesResult) -> pd.DataFrame:\n", + "def convert_proto_timeseries_to_pd_dataframe(\n", + " proto_timeseries: proto.TimeSeriesResult,\n", + ") -> pd.DataFrame:\n", " \"\"\"\n", " Convert a TimeSeriesResult proto message to a pandas DataFrame\n", " for propulsion and auxiliary power and other operational parameters such as speed and draft\n", " \"\"\"\n", - " time = list(map(lambda each: each.epoch_s, proto_timeseries.propulsion_power_timeseries))\n", - " propulsion_power = list(map(\n", - " lambda each: each.propulsion_power_kw, proto_timeseries.propulsion_power_timeseries\n", - " ))\n", - " auxiliary_power = list(map(\n", - " lambda each: each.auxiliary_power_kw, proto_timeseries.propulsion_power_timeseries\n", - " ))\n", + " time = list(\n", + " map(lambda each: each.epoch_s, proto_timeseries.propulsion_power_timeseries)\n", + " )\n", + " propulsion_power = list(\n", + " map(\n", + " lambda each: each.propulsion_power_kw,\n", + " proto_timeseries.propulsion_power_timeseries,\n", + " )\n", + " )\n", + " auxiliary_power = list(\n", + " map(\n", + " lambda each: each.auxiliary_power_kw,\n", + " proto_timeseries.propulsion_power_timeseries,\n", + " )\n", + " )\n", " if (np.array(auxiliary_power) == 0).all():\n", " auxiliary_power = [proto_timeseries.auxiliary_power_kw] * len(time)\n", " df = pd.DataFrame(\n", @@ -98,18 +111,18 @@ " data=dict(\n", " propulsion_power_kw=propulsion_power,\n", " auxiliary_power_kw=auxiliary_power,\n", - " )\n", + " ),\n", " )\n", " if len(proto_timeseries.operation_profile) > 0:\n", - " time_operation_profile = list(map(\n", - " lambda each: each.epoch_s, proto_timeseries.operation_profile\n", - " ))\n", - " speed_array = np.array(list(map(\n", - " lambda each: each.speed_kn, proto_timeseries.operation_profile\n", - " )))\n", - " draft_array = np.array(list(map(\n", - " lambda each: each.draft_m, proto_timeseries.operation_profile\n", - " )))\n", + " time_operation_profile = list(\n", + " map(lambda each: each.epoch_s, proto_timeseries.operation_profile)\n", + " )\n", + " speed_array = np.array(\n", + " list(map(lambda each: each.speed_kn, proto_timeseries.operation_profile))\n", + " )\n", + " draft_array = np.array(\n", + " list(map(lambda each: each.draft_m, proto_timeseries.operation_profile))\n", + " )\n", "\n", " if time_operation_profile != time:\n", " logger.warning(\n", @@ -128,33 +141,29 @@ }, { "cell_type": "code", - "execution_count": 1, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-06T21:59:10.516259Z", - "start_time": "2023-11-06T21:59:10.108958Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ "from MachSysS.convert_proto_timeseries import (\n", - " convert_proto_timeseries_to_pd_series, \n", + " convert_proto_timeseries_to_pd_series,\n", " convert_proto_timeseries_to_pd_dataframe,\n", ")\n", - "from MachSysS.gymir_result_pb2 import TimeSeriesResult, PropulsionPowerInstance, OperationProfilePoint\n", + "from MachSysS.gymir_result_pb2 import (\n", + " TimeSeriesResult,\n", + " PropulsionPowerInstance,\n", + " OperationProfilePoint,\n", + ")\n", "import numpy as np\n", - "import random" + "import random\n", + "\n", + "pd.options.plotting.backend = \"plotly\"" ] }, { "cell_type": "code", - "execution_count": 2, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-06T21:59:12.290881Z", - "start_time": "2023-11-06T21:59:11.478457Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [ { "name": "stderr", @@ -165,16 +174,20 @@ }, { "data": { - "text/plain": "" + "text/plain": [ + "" + ] }, - "execution_count": 2, + "execution_count": null, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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wZA4jAAjSElJCW688UaUlJREXZR2j6nrcDD1HA6mnsPB1HN4RF3X7daJ12AwGAwGQ/vFaGAMBoPBYDAkDiPAGAwGg8FgSBxGgDEYDAaDwZA4jABjMBgMBoMhcRgBRpB77rkHAwcORGlpKUaPHo158+ZFXaREMWnSJBx88MHo0qULevXqhTPOOAPLly93nFNfX4/x48ejR48e6Ny5M8466yysX7/ecc7q1atxyimnoGPHjujVqxeuuuoqNDc3h3krieG2225DKpXChAkTcr+ZOlbH2rVrce6556JHjx7o0KEDhg8fjg8++CB33LIsTJw4Eb1790aHDh0wZswYrFy50pHGli1bMG7cOJSVlaG8vBwXXXQRtm3bFvatxJaWlhbccMMNGDRoEDp06IA999wTN998s2OvHFPPcsyaNQunnXYa+vTpg1Qqheeee85xXFW9fvzxxzjyyCNRWlqKfv36YfLkycELbxm4efrpp63i4mLroYcespYuXWpdfPHFVnl5ubV+/fqoi5YYxo4daz388MPWkiVLrIULF1onn3yy1b9/f2vbtm25cy699FKrX79+1owZM6wPPvjAOvTQQ63DDjssd7y5udkaNmyYNWbMGOujjz6yXnnlFatnz57WddddF8UtxZp58+ZZAwcOtPbff3/r8ssvz/1u6lgNW7ZssQYMGGD95Cc/sebOnWt98cUX1muvvWZ99tlnuXNuu+02q2vXrtZzzz1nLVq0yPrud79rDRo0yNq5c2funBNPPNE64IADrDlz5ljvvPOOtddee1nnnHNOFLcUS2699VarR48e1ksvvWStWrXKeuaZZ6zOnTtbf/3rX3PnmHqW45VXXrF+97vfWc8++6wFwJo6darjuIp6ra2ttSoqKqxx48ZZS5YssZ566imrQ4cO1gMPPBCo7EaAEeCQQw6xxo8fn/ve0tJi9enTx5o0aVKEpUo2GzZssABYb7/9tmVZllVTU2MVFRVZzzzzTO6cTz75xAJgzZ4927Ks1hcunU5b1dXVuXPuu+8+q6yszGpoaAj3BmLM1q1brb333tuaPn269Z3vfCcnwJg6Vsc111xjHXHEEdTjmUzGqqystG6//fbcbzU1NVZJSYn11FNPWZZlWcuWLbMAWPPnz8+d8+qrr1qpVMpau3atvsIniFNOOcX66U9/6vjtzDPPtMaNG2dZlqlnVbgFGFX1eu+991rdunVz9B3XXHONte+++wYqrzEhcdLY2IgFCxZgzJgxud/S6TTGjBmD2bNnR1iyZFNbWwsA6N69OwBgwYIFaGpqctTz4MGD0b9//1w9z549G8OHD0dFRUXunLFjx6Kurg5Lly4NsfTxZvz48TjllFMcdQmYOlbJCy+8gFGjRuEHP/gBevXqhREjRuDvf/977viqVatQXV3tqOuuXbti9OjRjrouLy/HqFGjcueMGTMG6XQac+fODe9mYsxhhx2GGTNmYMWKFQCARYsW4d1338VJJ50EwNSzLlTV6+zZs3HUUUehuLg4d87YsWOxfPlyfPvtt9Lla7ebOapm06ZNaGlpcXToAFBRUYFPP/00olIlm0wmgwkTJuDwww/HsGHDAADV1dUoLi5GeXm549yKigpUV1fnziE9h+wxA/D000/jww8/xPz58z3HTB2r44svvsB9992HK6+8Er/97W8xf/58/OpXv0JxcTEuuOCCXF2R6tJe17169XIcLywsRPfu3U1dt3Httdeirq4OgwcPRkFBAVpaWnDrrbdi3LhxAGDqWROq6rW6uhqDBg3ypJE91q1bN6nyGQHGEBnjx4/HkiVL8O6770ZdlHbFmjVrcPnll2P69OkoLS2Nujjtmkwmg1GjRuGPf/wjAGDEiBFYsmQJ7r//flxwwQURl6798J///AdPPPEEnnzySey3335YuHAhJkyYgD59+ph63oUxJiROevbsiYKCAs9KjfXr16OysjKiUiWXyy67DC+99BLefPNN7L777rnfKysr0djYiJqaGsf59nqurKwkPofssV2dBQsWYMOGDTjooINQWFiIwsJCvP3225gyZQoKCwtRUVFh6lgRvXv3xtChQx2/DRkyBKtXrwaQrytWv1FZWYkNGzY4jjc3N2PLli2mrtu46qqrcO211+Lss8/G8OHDcd555+GKK67ApEmTAJh61oWqetXVnxgBhpPi4mKMHDkSM2bMyP2WyWQwY8YMVFVVRViyZGFZFi677DJMnToVM2fO9KgVR44ciaKiIkc9L1++HKtXr87Vc1VVFRYvXux4aaZPn46ysjLPYLIrctxxx2Hx4sVYuHBh7m/UqFEYN25c7rOpYzUcfvjhnjAAK1aswIABAwAAgwYNQmVlpaOu6+rqMHfuXEdd19TUYMGCBblzZs6ciUwmg9GjR4dwF/Fnx44dSKedw1VBQQEymQwAU8+6UFWvVVVVmDVrFpqamnLnTJ8+Hfvuu6+0+QiAWUYtwtNPP22VlJRYjzzyiLVs2TLrkksuscrLyx0rNQxsfv7zn1tdu3a13nrrLeubb77J/e3YsSN3zqWXXmr179/fmjlzpvXBBx9YVVVVVlVVVe54donvCSecYC1cuNCaNm2atdtuu5klvgzsq5Asy9SxKubNm2cVFhZat956q7Vy5UrriSeesDp27Gg9/vjjuXNuu+02q7y83Hr++eetjz/+2Dr99NOJy1BHjBhhzZ0713r33Xetvffee5df3mvnggsusPr27ZtbRv3ss89aPXv2tK6++urcOaae5di6dav10UcfWR999JEFwLrzzjutjz76yPrqq68sy1JTrzU1NVZFRYV13nnnWUuWLLGefvppq2PHjmYZddjcfffdVv/+/a3i4mLrkEMOsebMmRN1kRIFAOLfww8/nDtn586d1i9+8QurW7duVseOHa3vfe971jfffONI58svv7ROOukkq0OHDlbPnj2tX//611ZTU1PId5Mc3AKMqWN1vPjii9awYcOskpISa/DgwdaDDz7oOJ7JZKwbbrjBqqiosEpKSqzjjjvOWr58ueOczZs3W+ecc47VuXNnq6yszLrwwgutrVu3hnkbsaaurs66/PLLrf79+1ulpaXWHnvsYf3ud79zLMs19SzHm2++SeyTL7jgAsuy1NXrokWLrCOOOMIqKSmx+vbta912222By56yLFsoQ4PBYDAYDIYEYHxgDAaDwWAwJA4jwBgMBoPBYEgcRoAxGAwGg8GQOIwAYzAYDAaDIXEYAcZgMBgMBkPiMAKMwWAwGAyGxGEEGIPBYDAYDInDCDAGg8FgMBgShxFgDAaDwWAwJA4jwBgMBoPBYEgcRoAxGAwGg8GQOIwAYzAYDAaDIXH8P+DiOYgEGH0IAAAAAElFTkSuQmCC", - "text/plain": "
" + "text/plain": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -182,7 +195,9 @@ { "data": { "image/png": "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", - "text/plain": "
" + "text/plain": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -198,15 +213,15 @@ "timeseries_result = TimeSeriesResult()\n", "timeseries_result.auxiliary_power_kw = auxiliary_power\n", "for time, propulsion_power, speed_kn, draft_m in zip(\n", - " time_array, propulsion_power_array, speed_array, draft_array\n", + " time_array, propulsion_power_array, speed_array, draft_array\n", "):\n", - " timeseries_result.propulsion_power_timeseries.append(PropulsionPowerInstance(\n", - " epoch_s=time, propulsion_power_kw=propulsion_power\n", - " ))\n", + " timeseries_result.propulsion_power_timeseries.append(\n", + " PropulsionPowerInstance(epoch_s=time, propulsion_power_kw=propulsion_power)\n", + " )\n", " if random.random() > 0.9:\n", - " timeseries_result.operation_profile.append(OperationProfilePoint(\n", - " epoch_s=time, speed_kn=speed_kn, draft_m=draft_m\n", - " ))\n", + " timeseries_result.operation_profile.append(\n", + " OperationProfilePoint(epoch_s=time, speed_kn=speed_kn, draft_m=draft_m)\n", + " )\n", "\n", "with open(\"timeseries_test.sim\", \"wb\") as file:\n", " file.write(timeseries_result.SerializeToString())\n", @@ -220,13 +235,8 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-06T21:59:13.250508Z", - "start_time": "2023-11-06T21:59:13.053738Z" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [ { "name": "stderr", @@ -237,16 +247,20 @@ }, { "data": { - "text/plain": "" + "text/plain": [ + "" + ] }, - "execution_count": 3, + "execution_count": null, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjAAAAGdCAYAAAAMm0nCAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAADyuklEQVR4nOxdd5wURdp+emfzLrvLgiwsLAICEiSDkkFEUcxyZ9ZTUQygIuaEivFQgU/FnPDMeuaAcCgZQYmSQcmw5M15pr8/Zmemu6e6u6q6uqcH+7kf52x31VtvV1dXvfWmkmRZluHBgwcPHjx48BBHSIg1Ax48ePDgwYMHD6zwBBgPHjx48ODBQ9zBE2A8ePDgwYMHD3EHT4Dx4MGDBw8ePMQdPAHGgwcPHjx48BB38AQYDx48ePDgwUPcwRNgPHjw4MGDBw9xB0+A8eDBgwcPHjzEHRJjzYBdCAQC2Lt3Lxo0aABJkmLNjgcPHjx48OCBArIso7S0FPn5+UhI0NezHLMCzN69e1FQUBBrNjx48ODBgwcPHNi1axdatGihe/+YFWAaNGgAINgBWVlZMebGgwcPHjx48ECDkpISFBQUhNdxPRyzAkzIbJSVleUJMB48ePDgwUOcwcz9w3Pi9eDBgwcPHjzEHTwBxoMHDx48ePAQd/AEGA8ePHjw4MFD3OGY9YHx4MGDB7dAlmXU1dXB7/fHmhUPHmIOn8+HxMREyylOPAHGgwcPHmxETU0N9u3bh4qKiliz4sGDa5Ceno5mzZohOTmZm4YnwHjw4MGDTQgEAti2bRt8Ph/y8/ORnJzsJdb08LeGLMuoqanBwYMHsW3bNrRr184wWZ0RPAHGgwcPHmxCTU0NAoEACgoKkJ6eHmt2PHhwBdLS0pCUlIQdO3agpqYGqampXHQ8J14PHjx4sBm8O0wPHo5ViPgmvK/KgwcPHjx48BB3YBZg5s+fj3PPPRf5+fmQJAlfffWV6r4sy5g4cSKaNWuGtLQ0DB8+HFu2bFGVOXLkCK644gpkZWUhJycHo0ePRllZmarMmjVrMGjQIKSmpqKgoACTJ09mfzoPHjx48ODBwzEJZgGmvLwc3bp1w/Tp04n3J0+ejBdeeAGvvvoqli5dioyMDIwYMQJVVVXhMldccQXWrVuH2bNn47vvvsP8+fMxZsyY8P2SkhKcccYZOP7447F8+XI8++yzePTRR/H6669zPKIHDx48eDhWMHfuXEiShKKiIqFlPUSwfft2SJKEVatWxZoVQzA78Z511lk466yziPdkWca0adPw0EMP4fzzzwcAvPfee8jLy8NXX32FSy+9FBs2bMDMmTPx22+/oXfv3gCAF198ESNHjsRzzz2H/Px8fPDBB6ipqcHbb7+N5ORkdO7cGatWrcKUKVNUgo4HDx48ePCgh/79+2Pfvn3Izs6ONSsebIBQH5ht27ahsLAQw4cPD1/Lzs7GKaecgiVLlgAAlixZgpycnLDwAgDDhw9HQkICli5dGi4zePBgVXz4iBEjsGnTJhw9epTYdnV1NUpKSlT/PMQea3YX4d1F2xAIyLFmJSaQ5WP3uatqY5+UTZZl/LxxP3Yd8XKsxBI1NTWxZoGI5ORkNG3a1Atd18Ct74sVQgWYwsJCAEBeXp7qel5eXvheYWEhmjRporqfmJiI3NxcVRkSDWUbWjz99NPIzs4O/ysoKLD+QB6iUFxZiy9W7EZpVS1V+fNeWoRHv12Pb9fstZkzMo6U16DWHzAsU1njx8bCEuHCRmWNH6c9Pw/3fL6aq/6a3UUorqDrZ6fxwdId6PDwTHy1ck9M+Zi76SCue/d3DJr8S0z5oIUsy6ioqaP+V15di4OlVSiprGGqR/rHMr6HDh2KcePGYdy4ccjOzkbjxo3x8MMPh2m0atUKjz/+OK6++mpkZWWFNeP//e9/0blzZ6SkpKBVq1Z4/vnnVXRD9S677DJkZGSgefPmKncEkumiqKgIkiRh7ty5RF537NiBc889Fw0bNkRGRgY6d+6MH374AQDZhETD41NPPYXrrrsODRo0QMuWLandF0L8f/zxx+jfvz9SU1Nx0kknYd68eapy8+bNw8knn4yUlBQ0a9YM9913H+rq6gAA3333HXJycsJZm1etWgVJknDfffeF619//fW48sorw38vXLgQgwYNQlpaGgoKCnDbbbehvLxc9Uyk90ULv9+P6667Dh06dMDOnTtx11134ZxzzgnfnzZtGiRJwsyZM8PX2rZtizfffJOpHVYcM3lg7r//fkyYMCH8d0lJyd9GiNlXXIlZ6/bjH71aICPF3lc67sMVWLDlEEZ0zsNrV/U2r1CPrQfKzAsJxs7DFRj87C84Ma8BfrpjsG65C19ehI2FpXjz6t4Y3ilPtxwrZq0vxF+HyvHXoXJM/kc3proLtxzClW8tRU56ElZNPEMYT6Lw4JdrAQDjP1mFC3o0jxkfy7YfiVnbPKis9aPTxJ9i0vb6SSOQnkw/P8yYMQOjR4/GwkVL8OPcxXj03tvRsmVL3HDDDQCA5557DhMnTsQjjzwCAFi+fDkuvvhiPProo7jkkkuwePFi3HLLLWjUqBGuueaaMN1nn30WDzzwAB577DH89NNPuP3229G+fXucfvrpXM81duxY1NTUYP78+cjIyMD69euRmZlJLEvL4/PPP4/HH38cDzzwAD7//HPcfPPNGDJkCE488UQqnu6++25MmzYNnTp1wpQpU3Duuedi27ZtaNSoEfbs2YORI0fimmuuwXvvvYeNGzfihhtuQGpqKh599FEMGjQIpaWlWLlyJXr37o158+ahcePGKgFu3rx5uPfeewEAf/75J84880w88cQTePvtt3Hw4MGw8PnOO++E62jfFy2qq6tx2WWXYfv27ViwYAGOO+44DBkyBG+++Sb8fj98Pp+KxzPPPBN79uzBn3/+iaFDhzK1xQqhq13Tpk0BAPv370ezZs3C1/fv34/u3buHyxw4cEBVr66uDkeOHAnXb9q0Kfbv368qE/o7VEaLlJQUpKSkCHmOeMMF0xdhf0k1NuwrwTOjutra1oIthwAAP63bb1JSDV+C8yrc7//YBwDYtL/UsNzGwuD9L1ftESrAWFFbz14f1DQWuVQD4xZ4hgH7UFBQgKlTp2LH4QqceUE+Nm5Yi6lTp4YFmGHDhuHOO+8Ml7/iiitw2mmn4eGHHwYAtG/fHuvXr8ezzz6rEg4GDBgQ1ia0b98eixYtwtSpU7kFmJ07d2LUqFHo0qULAKBNmza6ZadMmULF48iRI3HLLbcAAO69915MnToVv/zyC7UAM27cOIwaNQoA8Morr2DmzJl46623cM899+Dll19GQUEBXnrpJUiShA4dOmDv3r249957MXHiRGRnZ6N79+6YO3cuevfujblz5+KOO+7AY489hrKyMhQXF2Pr1q0YMmQIgKD14YorrsD48eMBAO3atcMLL7yAIUOG4JVXXgknidO+LxqUlZXh7LPPRnV1NX755ZewL5FSyOrVqxfmz5+Pu+++OxyVPHfuXDRv3hxt27Zlao8VQgWY1q1bo2nTppgzZ05YYCkpKcHSpUtx8803AwD69euHoqIiLF++HL169QIA/PzzzwgEAjjllFPCZR588EHU1tYiKSkJADB79myceOKJaNiwoUiWjwnsL6kGAMzbfDDGnOjDFwMbdIDRJJTIKGRt2V+KhVsP4cq+xyPJF22NZaXngR3x5tqQluTD+kkjqMvvPVqJIxVBf4WTmrM5oq7dUwwAaJqVhsYNkpGW5DMsL8uySuju27ev6u9uPU/Gf16fHjZtKP0YAWDDhg3h4I0QBgwYgGnTpoV36kBwfleiX79+mDZtGtOzKXHbbbfh5ptvxqxZszB8+HCMGjUKXbuSN3K0PCrrS5JE3HgbQfmMiYmJ6N27NzZs2BDmoV+/fqq+HTBgAMrKyrB281/o1K4NhgwZgrlz5+LOO+/EggUL8PTTT+PTTz/FwoULceTIEeTn56Ndu3YAgNWrV2PNmjX44IMPwvRkWQ4fY9GxY0cA0e+LBpdddhlatGiBn3/+GWlpaeHrOTk56NatG+bOnYvk5GQkJydjzJgxeOSRR1BWVoZ58+aFBSw7wewDU1ZWhlWrVoVtlNu2bcOqVauwc+dOSJKE8ePH44knnsA333yDP/74A1dffTXy8/NxwQUXAAA6duyIM888EzfccAOWLVuGRYsWYdy4cbj00kuRn58PALj88suRnJyM0aNHY926dfjkk0/wf//3fyoTkYdouHkuT3BoMZdlGWt2F6Gyxs/sOMyqJTp96nw89u16zFi8XQg9JY5d11+xkFw96qMhSRLSkxOp/6Ul+5CaFPzHUi89OTFcLzU5AenJxif/FlfWYv2+EmrfNgDIyMgQ0SUqhLKzKv11amuNebr++uvx119/4aqrrsIff/yB3r1748UXX7TER2jjHIIkSQgEjH3pRGBfcSV2HqnA0KFDsXDhQqxevRpJSUno0KEDhg4dirlz50YJB2VlZbjxxhvD6/KqVauwevVqbNmyBSeccEK4HM/7GjlyJNasWRMOwlFCy09ubi46duyIhQsXuleA+f3339GjRw/06NEDADBhwgT06NEDEydOBADcc889uPXWWzFmzBj06dMHZWVlmDlzpuqsgw8++AAdOnTAaaedhpEjR2LgwIEqJ6ns7GzMmjUL27ZtQ69evXDnnXdi4sSJrgmh9gdkvLVwW3iH48EcCQ5tlT9bvhvnvbQIl7/5K1gDn3i1RCt2RiLjtuwvxcfLdiIQkD0NjAOINw2MW7HjcDn8ARnbDkUcP0NRoSGsWfkb2rVrF9ZSaNGxY0csWrQIu49WYE9RJQBg0aJFaN++varOr7/+qqr366+/okOHDigsrkJ2w0YAgH379oXv0+QiKSgowE033YQvvvgCd955J9544w1DHpUg8WgVymesq6vD8uXLw5qQjh07YsmSJSohbdGiRcjIbIC8Zs1RVl0XNtFMnTo1LAiEBIb/zfkFXXpHNDw9e/bE+vXr0bZt26h/Vk56BoCbb74ZzzzzDM4777woR+QhQ4Zg4cKFmDNnTtjXZejQofjoo4+wefNm2/1fAA4T0tChQw292SVJwqRJkzBp0iTdMrm5ufjwww8N2+natSsWLFjAyp4j+Pi3nXj8u/UAgO3PnB1jbiJwc6ggwcJiCz75bRcAYOXOIgxudxxT3UQfX//5FZLS6VPn19NKQKPMyOShVc8fKa/Bsz9twiV9CtC9IIer3XjH3qJKPPjlH7huYGsMYnxXHuzHzp07MWHCBJxz8VX47ffl+OidNzB1yvO65e+880706dMHTz/5JEacdyFm/bkWL730El5++WVVuUWLFmHy5Mm44IILMHv2bHz22Wd444PPcaC0CimJCejbty+eeeYZtG7dGgcOHMBDDz1kyOf48eNx1llnoX379jh69Ch++eWXsLCgx+Pjjz+OSy65BEuWLCHyaBXTp09Hu3bt0LFjR0ydOhVHjx7FddddBwC45ZZbMG3aNNx6660YN24cNm3ahEceeQRX3XBLWAPVsGFDdO3aFR988AFeeuklAMDgwYNx8cUXo7a2Fp179UWdP4BEXwLuvfde9O3bF+PGjcP1118fdmSePXt2uK4V3HrrrfD7/TjnnHPw448/YuDAgWF+SktL8d133+GZZ54BEJQP/vGPf6BZs2Zo37695bbN4J2FxIH1e70cM6xwSgOjbIXVB4aXRz9B1bN2T7FKA6MtMvHrtfho2U5cMH0R3ILdRyuwaOshx9q7979r8Mumg7jqrWXcNNwgtBdX1GL5jiOuzfnD20NXX301KisrccEZQ/HUQ3fjiutuNNSC9+zZEx9+9DFmfvsFRg3vj0cffQSTJk1SOccCQSEipMl/4oknMGXKFPQaMBQAUF0XwNtvv426ujr06tUr7JJgBL/fj7Fjx4bdE9q3b68rkPTs2ROffvopPv74Y5x00kmYOHEikUereOaZZ/DMM8+gW7duWLhwIb755hs0btwYANC8eXP88MMPWLZsGbp164abbroJo0ePxg233aWiMWTIEPj9/ojSICUTHTp2ROMmeWh1Qrtwua5du2LevHnYvHkzBg0aFLaIhFwyQpBlGXuOVuBQWTXz84wfPx6PPfYYRo4cicWLFwMIClldunTBcccdhw4dOgAICjWBQMAR8xFwDIVRO4lYTFM7Dpdj26FyDD2xiXlhFyIWUUgkwcIIvCYfUjuJCZLqmWv9AfgSIirqWISVm2Hgv4O5VD69sR9Obp1re3uFxVXmhUwQe/EFOGPaPOwvqcarV/bEmSc1M68QJ0hKSsK0adNw3xPPobgy6IcSEhi3b99OrHPhRaPQsX8wmqhzfjbxu8/KysKnn36qurZmd1H4d8eOHbFg4SIcrajB4bJqpCUlqoRDrRXAyN+FZDEYNWpUOEJIi4Ol1Vi1fjNy0tWmFxozlnIe6NixY5QJTokhQ4Zg2TK14K7sAyCYWyXk3Hy0vAa7j1bg/e/VZpwQ+vTpg1mzZum2t337dpRV1+Gvg8F5p3GmccRuq1atovptwoQJUX6o2n7Jzc11xFcoBE8DEycY8uxcXPPOb/jNJXkvWDe+TgkwSi0Kqw8Mr6NxHaEhn09CouK4eFZhKpb4fYc7xli8IBQFOHMtOcmmNdj/3diXUZl/zO8tqsTeokpU1wVQVOlM1tiqWn/YiZYV+0uqsG5vMcqq7Ul7UCngHR2L2dA9ASbOsGpnke49J7XprOYWp0xIyvne7jDqEEjCSVJCgsrvRyvkuMH0cSzA7d1olgXaDdhx2H3HMBytcD7VPc0m46mnnkJmZmbUv9bNGuOWq/6BfUXWtYokiB7nes+RmZmpe9ahG+GZkOIMRouyk5M5q70/FiYk1h0HrwaGNPElJEjwGWhg3OovAbCFJsdagHBTGLX2jS7eegh3f/I7po60P1NxQJZR55eRnMi+JyUJWXpp+82gfBukEa5neooX3HTTTbj44oujrm/cV4KU1FTkNcu35dsWvQHUew4AqnwvJBRX1MAvA7kZ1iKcRMATYDgQy7XHaE0mTeZbD5Tir4PlOKOzOoOxNiqGh4/xH6/EtEt7UJV3KpGd2omXre7hsho89u06XNX3eLQ5jpyKnASSUJmYoH4bdYw7cRfLNyrEWnzgHVZbD5Rh3uaDuOKUlkg1SfDGizs+XYVEIOw/wgXK59u6vwxVdX60a5KJtKjjAoyJCB1qZhKMi0HDbm5uLnJzo/3DKlKLhPOjhOj9n95zmEGWZeyoN7E1SElEEofALBKeCSnOwGoWGT5lPsb8Z7nKd2blzqPo8+T/8MWK3ZZ4+WqV8QGNSg2IU4nsVO0z9tXny3fjnUXbmSODSD4w2pBsUpljAUZC8K4jFdhicoyD5fY56w2fMg+Pf7ceX68Sdxildrg5ZjYFUFUX9JEo4hGW4mBoulljCdBrmGVZRnFlDWrq2Hxa3Ghy9rvgnXgCTJzBOAePfr11iqR7N7+/AofKajDhU75TkmmhXLSdkl+UfcAqwIRQUlXHVJ5kqkpMkFTrgtaE5MYJiQdG73XQ5F9w+tT5rjtR+0h5xL/iUJl9vhbx8obleJBgGFFRU4ddRypc54NUXFmLHYcrwuev0cJJYdgIbhspngkpzkC7kd+yv1T3ZGqnJGelAOGUD4zScONU5A+pP5X+L4C5BiYQkFFaVYfs9CTDcm6Dng+Ksu/3lVTa9lw88/qB0oijZdOsVIOSbNC+YTcLqYGAjK0Hy5CRbG4+c+9T6COUpsAfkNGqsfgjD3hRXs22OQrBS+pNhqeBcRDl1XUY9+EKzFy7z7ywDrSL8r7iyvDv0Bg/UFqF06fOR/9nfo7ci8FkqtbAOCTAqDQwjjSJOr+OBkYh2FTWGKuMr3n3N3SbNAubGHdmdmDptsNY+tdhusI6r7WmLrLztfNIBTcLCW7EgdIqbDtUjuLKWlTV+nG4nKyBOlxWrZpbYg3eT7m6ziENjIC5xmgku2acu0wF4wkwXOB7i6/O+xPfrdmHm95fwd+yZrd/7Tu/RZUhJUmLxfj3+53XwChBE4UkwrYeEiqVtLQ+MCNfWIBp/9usS2N+/UniHy3baZkfq5i76SAuef1Xqvwgem9VKcDoCa+xmpOVr1zkfKwdSwk2z661/gD2l1Sp+toMhcVVKK2qNfWV2VNUiYOl1aioqQOvDsYda50zXNC2YlzOJUKKAdzxTiPwBBgHcbCUPYWzFto1WWlLdY2UXg+laSU2Ghjzz02EmSn0nEpaWh8YAJj2vy2W23ISVAKMngZG4XugNy5FWDLdNOSjTEg2L0g7Dldgf0kVtisOYKQFrX+YncnPtm/fDkmSwtlcf1uyEN0KGqKoqAgA8PWnH2Jg5+MtteG2BdcQhsPF+pN06dAO77/5ikUq7upRT4CJM9BMPG7JjVEXUC5izrSpfHaauVdEdFBoklfS0vrAsMINjpU0ArHeWFMKMHb6IvGMdZUGxkZ/MLvHfFA7EolAYkLshxcKCgqwb98+nHTSScT7I869EF/P+z34hwv49eC+9A6eAMMB9+aB4btnF5RHYljps6d/3IAZi7ezt++QBqaOIMAEfWAsk44paBZgXQ1MnbkAI2KBd5MGRrvIuoU1y3zwEjAZ/z6fD02bNkViIjnYIDUtDY0a659SXlPnx18Hy1BapW8Oq6lxPqMvL6y8p3h6TpHwBBgHIWKy5d4xxsSJV2mb5+N77Z5ivDbvLzzyzTqq8qwmJBEamNACrUxWZ+bzY/Y23KBFo+GAxgfGXg0MO2i1W7uPVuDDpTu5zwoimk1lGagpp/4n1ZZDqq2AVFuBv/YcgFxdprhXQfhXHnUfoWuMc8eiX/6H04cNRZfW+RjcpQ3GXXMJ/vzzTwDBTL2SJIXNPUDwYL/kRB/27Ar6cd1w/Wh07doV1dVB03lNTQ169OiBq6++GkC0CUkLpQlJBvDnn3/i/PPPR15eHjIzM9G7z8n43//+h20KE1qrVq3w+OOP48HxN6F/x5Z45O7bMWzYMIwbN05F++DBg0hOTsacOXMU74bcDyGal112GTIyMtC8eXNMnz5dVWbvnl24/brL0ffEFsjKysLFF1+M/fv3AwCKi4vh8/nw++9BbVIgEMCgk1qjb9++4frvv/8+hvfpHP57165duPjii5GTk4Pc3Fxc9s9R4X4FgIfvuAWjLroQTz75JPLz83HiiSeSmUfQFLypsDRqPnzzzTeRk5ODOXPm4LvvvkNOTg78/uBYX7VqFSRJwn333Rcuf/311+Pqq6/SbScW8MKo4wyGi3Ls1zwVlAsXr9xVxhl2qG3fShlaGrVRTsv6tPXuhNa8uDEh6ZSpdciEZBVGnJ0+ZT4qa/3YW1SJu0boLxARWhQqmNoK4Kl8av7y6/+R0MWkbtT9B4wTT2pRWVmBcbfdjoK2HVF4uAgvP/cULrzwQqqTmQFgyrT/Q59ePXDfffdh6tSpePDBB1FUVISXXnqJiY8QysrKMHLkSDz55JNISUnB1JffwG3XXoav5y1D1xY54XLPPfccrr/tbtw0/l4k+SQc2rYe48aNw/PPP4+UlOApzO+//z6aN2+OYcOGEdvSZip/9tln8cADD+Cxxx7DTz/9hNtvvx3t27fH6aefjkAggNuvuxxp6Rl4+7PvkJoIPHz3BFxyySWYO3cusrOz0b17d8ydOxeXntAJWzaugyRJWLlyJcrKypCZmYl58+ahd98BAIDa2lqMOHsE+vXrhwULFiAxMRGPPDoJt1z1D3w+ayGSkoMp/H/++WdkZ2dj9uzZhv22+2glquv8qrVj8uTJmDx5MmbNmoWTTz4ZxcXFKC0txcqVK9G7d2/MmzcPjRs3Vh0pMW/ePNx1991M78xueAJMnIFmLXCLWj0WC5dy0tETmnYcLkeTBqlIS/Yxp/gnIayBcfAYeSdApYHRKaQMX7Uz75CdYz10AvCiPw/hLpgLMD/8UYhAQA5nnXbJZ0gEzRsZPvI8tG6cgaKKWuQ0rcFjz7+Eod3aYv369VRtZGZm4P3338eQIUPQoEEDTJs2Db/88guysrK4OO7WrRu6desWvnL7vQ9j1g/fYu7sHzHilIi4NmzYMPzrxqDGJdmXgME9OmDcuHH4+uuvw+f/vPvuu7jmmmuoAx8GDBgQ1ka0b98eixYtwtSpU3H66adjzpw52LJxPX5YvApN81sAACZNfRkXndYPv/32G/r06YOhQ4cGBZjRt+D3JYvQd9BQFO78CwsXLsSZZ56JuXPn4sobbgUA/PTtFwgEAnj9jTfCvnTTX3sDLZs1wW9LFqL/kKDQlZGRgTfffBPJycZnEmk3vVOfegQ/ffUZ5s2bh86dg1ofpZDVu3dvzJ07F3fccQcee+wxlJWVobi4GFu3bsWgQUMQ2lK6wUTuCTAC8MKcLWjRMA0X9Wxhe1uGhzlq/ku65yRUGpgYtx/Cmt1FOO+lRcjPTsXi+08TY0KSQyYktcYpjpRl3KAzIfEJdlW1ftNziqw68YoemD+s3YdzugZ1JkQTUlI6kyZkX3GlKlvw8bnpyEoLJgX8Q5FdO4QmDZKRl5Wmut8sOxWNM1OCbSO6jh52bPsTkyZMxrJly3Dk8GEE6t/jzp07kZ6eTkWjX79+uOuuu/D444/j3nvvxcCBA6nb16KsrAyPPvoovv/+e+zbtw+1tXWoqqpE4Z7gkSjl1XWo9QfQvnM3Vb3U1FRcddVVePvtt3HxxRdjxYoVWLt2Lb755hvqtvv16xf197Rp0wAAGzZsQF5+87DwAgAntO+AnJwcbNiwAX369MGQIUPw1ltvwe/34/dfF6Hf4FNR1qYl5s6di65du2Lr1q3o0y/YN5vXr8XWrVvRoEGWKoFddXUVdu/YFv77pJNOMhVeAKjG+Huvv4TKigqsXLEcbdq0URUbMmQI5s6dizvvvBMLFizA008/jU8//RQLFy7EkSNHkJ+fj7bt2mFjYUk04RjBE2A4oJwA1+wuwpTZwfweIgQYf0DGWwv/wsmtG6F7QY5h225HnQATEivUhzlGN/rj2kIAwN7iYDZWkSakY+28I5qnoTMhsbc9/ZetePanTXj32j4YemITg/bZafOizh/AmP8sR4+CHNx6WjtimcLiSJZfIm+SBCTTZ4aVkxIgJ0WmaTk5A0hOqr8X7bwqJ6UAyWnq+8lpQHIKdZsh3HbtZWjTuhX+PfUlpOU0RiAQwKjh/VFTU4PMzOBhp0qfvNpaNT8ygv4eixYtgs/nw9atW5l5UNK66667MHv2bDz33HNo27YtCsv8uPX6q8LtFpYE+15OjH7W66+/Ht27d8fu3bvxzjvvYNiwYTj+eG2Itn3f7+DBg1FaWoo/Vq/CiqWLcdu9D0Mu2otnnnkG3bp1Q35+Po4/4QT4AzIqysvRsUt3PP3C68jNTEaTBqkorazBnqIqNGzUKEwzI4NuHCmfqufJ/bDg51n49NNPVf4tADB06FC8/fbbWL16NZKSktChQ4ew5ujo0aMYMmSIitr2wxXwB2QUNExDdnpsTqb2nHgt4ohOJktefL58F576YaPugYJGC66ROtTuiX76L1ujDsaLte8DqXltN9jlxCu7wovFfliJQjLCsz9tAgA8+OVaLr5oQfOWQo84a/1+/LzxAJ6frZ+QUPkNusERmxdFR49g+59bcM+992PgkFPRpt2JKCkuCt8/7rhgdNC+fZGs4iTfmGeffRYbN27EvHnzMHPmTLzzzjt8DMnAokWLcM011+DCCy9Ely5d0DgvD3t371SVIVQDAHTp0gW9e/fGG2+8gQ8//BDXXXcdU/O//vpr1N8dO3YEAHTs2BH79+5B4d7I4bh/bt6IoqIidOrUCQCQk5ODrl27YsabryIxKQmt27bH4MGDsXLlSnz33Xf1wkEQHbt0w85tfyK3cWO0bnMC2rZti9YntEXL1m3QICubiW8tTureC9Pf+wxPPfUUnnvuOdW9QYMGobS0FFOnTg3zExJg5s6di6FDh0ad7xaQYzvPeQKMozCf0DYVRmfRVYLGhOQ01uwuwrM/bcLtH69SXVebkGSs2HkUEz5dpTqLRjSUKle6MGrrfit1BCdeXrhp0dOLeFMei6DH7fd/RBY2K4LsnqJKFBtkjXUyeSNrZmJbWHNIlZmVnYOchrl45+03sf2vP7F00Xw8N+mh8P22bduioKAAjz76KLZs2YLvv/8ezz//vIrGqhUrMXHiRLz55psYMGAApkyZgttvvx1//fUXF0/t2rXDF198gVWrVmH16tW48+bRqkR7Zj1z/fXX45lnnoEsy7jwwgsNy4ZoheaHRYsWYfLkydi8eTOmT5+Ozz77DLfffjsAYPjw4WjboRPuv3UMNvyxGn+sXI6Hxt+MgYMGo3fv3mGaQ4cOxZeffYJep/QHAOTm5qJjx4745JNPMGTIkPDYGXnhP5GT2wi3j74CSxcvwrZt27Bw/jw8M/Fe7N+nf3q6PyBTRal2730KfvjhBzz22GNhMxgANGzYEF27dsUHH3yAoUOHAghqjlasWIHNmzdj8ODBqKjmi8izC54AYxFOS5+GeWCk0H+jZ047F0a981S0JqSLXl6ML1bswQNf0O+qWedr5bOTBBht1/BqYKoVycNCk6g26iqezH0s6P1EJOpBT4D4cmVkorXqxDtl1ibde1xh1DL5t275UFuMjbktMzYLEhIS8O/pb2HVyhU4fWAfPPfYA5jw4KTw/aSkJHz00UfYuHEjunbtin//+9944oknwverq6pw7TX/wjXXXINzzz0XADBmzBiceuqpuOqqq8LhuiyYMmUKGjZsiP79++Pcc8/FoKGnoeNJXcP3zXQBl112GRITE3HZZZchNdX8EM+ALGPd3hLU+gOYMGECfv/9d/To0QNPPPEEpkyZghEjRgAIvuf/e+sDZGXn4Np/nI0bL78QLY5vhXfe+0BFb8iQIfD7/ejdL+IHNHToUPj9/nqBIThe0tLS8c7n36NZ8xYYfdVl6NixI2695UbUVFcjI7MBkdc6fwDr9hZjC+EYGdIqNXDgQHz//fd46KGH8OKLL0bxGBJgcnNz0alTJzRt2hR5Ldtg19GKKKqxHOWeD4zLYPYR2pk5VDSUAoSS622HjLVMokCz8ycdxGiGqlo/ej0eWcRDC3RtQGlCsgY3v+ZyCg2MEla1XPuK7dPYiYZSZrHj+C9xw8KcUt9BQ7Fs5RoUV9TiaEVwk6KcfwYMGIA1a9ao6lTX+sNOnitWr4lywv7666/Dv1u1ahWmt2Z3Efr0G4jVu44iJycHO8uKcP7Fl+P8iy9Xlf/558gBtVv2l2LUVaNVj/TjEjU/Shw6dAhVVVUYPXq0bhkllHNDg6wsfPrpp7plmzUvwP+9/aHq2nGN1D4qF1xwAXYdKVe5HUybNi2sBVm/tyR8vXGTPDwx9RU0aZCKptmpKKqowc4jEeHh8akvo1OzSDRXaX26CZKWMPQU2r4ZPHgwysrUc7GSnxBCpsE/D6rLumEt8jQwcQZjE5K1GXPtnmLc/P5y/HVQjIDBIxxowbzrVfwmdZW2j2jPhFFi3d5i1SIeIqF9Xjd84Hqg4Y3Oide8jIBIdUvtG4HmGUMaNtbvy80KGOqR6ZIhTMOGXpna2loUFhbioYceQt++fdGzZ0+RrBkw5GDnOdCU7pwRw4HuCTAcUGlJHP7AefPA0IyxWz9aiR/XFuKfry5hZ4wAlQZG8dsp1TqNBoZnjtEjq/e8JJh1gZ1d9OaCv9Dnyf8RTy1nhzmjIvyM+FuPBqvb4erdxdil2P3S8qMn8FTV+rH7SAVqeM4wYuJA74q7secoZV9rHkzvk1u0aBGaNWuG3377Da+++qrq3oIFC5CZmYnMzEw0bdwQfU9sEcym26ABcnMiGg6eaZ65joUXtWTRwjDvoecJ/et1An3iRCO4Mc2VZ0JyECIWJUMNjAF9mqZDp2Xr+bSwotxCFl1eGB0lUF3nx0u/8IdyhunqSDDaV2NFtrVz8/bE9xsAAI9+sw7vX3+KJVqx18Cwf1Qz60PpAfp+fm3+n+h9fC4TP3qs/XmwDP6AjPIaP05sSvZp0IOwYWHb+LJOmH7+0XZwdNsygn4mehuK3r17h00k5dW12HWkEgDQPq8B/LKMWgRNL0pzjV0gDhfK4d29Zy98OnM+AKCDhtetB0qtMVYPvbXH84GJYzgdRGbnwtahaQP8vuOoMHrKBFzOQT8T788bDkSV5ulOO6PDndTGmmmoaMaaHruZKYnhYyDszFDM2l97iyrx8tw/HWlLr3io36tt0cCIh01nOQonRhyvJvXS0tLQtm1bAEBZVS2k7OC5Sm3zs+GXZWzYV2JUnZ0fRtD2fWpaGlq2Diama6s4VgEAajNKVHmZeOHGNFeeCYkDNANzwZaDuO2jlTgqOE8Mjc8G74STnCh2OBwqqw7/VrJtxF+AMhRQD8pFRhv9QoqG4WlLr45WmHWxCwwAPv8fLfQWdSVtEe2IQiSLaBCiNyCq/rBDGnVBV5ZX12FfcaW5iVYgryRSyt6trvVbd5y3WN9ueiyo8wdwuLxaqPnWTd9xCJ4GxiL03ulVby0DAKQl+fDvf3QlF2KgFwKvFGzrzl6Hp5BJKljEnHF/QMbI/1uAhhlJ+HhMP9PyZtB+cKK+P5p3oNeW9pC4WML0Mag0MORnUS5utJu/D5buwLer9+KNq3ubFw63z4bdRytNy2zeXypk4+HuKCR+KKNRmmWnGZR0jtu/DpULbU0ErVg68e84XIHymjqUVtYJnPf0nHjF0OeBJ8DYjL3F5hMmC4x9YAwy8VKMMtHfm54GRg9bDpRi035r9lrVUQIaSYNDw0yE7juI8oGJLlcXkJHkc4kAY6MGRkn6s9934f1fd+C1q3ohLyuSf0M7JkNZd9+Yz5DojFEYpBFgzpg6n4mmHtzxlgVA78DOWie9OokhhWHU+gNITHCXQYH162IdL0b0y2uC5tuSqlrb+yWW49xdbzwO4bSQLWTR0bnOrSLUIVim48RLs+bwPqeRCYlEky8KiSYEmVwm1scrKCFi7BIPLIS675duO4JVu4rwZL3zcLh9nT4qY8j2qQ6bN3+g0ir1mBT9/aotSLak4nWUirac1gRnVN7pkS7cHKiizQ4752oPQXgCjIMQMRiNTJoh+mbzpvKzuuadZeEQUZGf/9o9xdiyP6Jqdu4wR0UmXps2iDQKGFkGsUNDmX/13pGTE5aZIGZlQSDR1hNotdD2TUBWn62kVzaY/VjGSz9vwS8box22SbRZQCWQKMociyYk5XuItSU0qnmnvYbNKNitglG3xnkvvuEJMBxgGQ6iF27RWpK5mw7i3v/WZ2jkIL18x1HMWleoulZcUYtzXlwYPh2WhzT3YzKehcTz0HoLO01zdZQOIU5MOSKUQaRFTJZlYl9od6S0ieH+t2E/uk+aZRqWLyM4np+btRnXvvsbFW3R/UyTB8ZSwsljdy0yROixhw4divHjxxuWCeGsfl3x7hvTYxbtRfuqyqvrdAV0ETsaMz4Ol1VTby5I8MKoPVCD5iwks2RW2ruH68OdeXbco15ZHHXN7LBGmoldjBOd8d9618xAo9mRZfIzhDQwbnDot8sHRm+MWmmtosaPpdsOY1iHPNV1pQlLlmXhPmcR2nQT9YHS6oijtp6WTXLH+xcFWZZxtKIWqUkJ8Kneh8hGOIvIwKbCUrTPaxB1rIEZaA7vNOSHogPKq+vCTtEpiWz8qdrirFdeXYc9RcFvpqsm/Doe4GlgLMJs4Ii2y9oRypaaHPxw7IzS4V0saavV+QMY++EK/KhIUmb1EMGNhSWYuXZf1HW9d0AbaRUL7C+pwviPV2L5jiPha6ZRsJxRSHrPaMeibdVPQTRTL8zZgqmzNwPQF3hibXphhe5z1N8pq67D7qMVgjI700Nr0jOaY7S+T2aQEYxssgKaoUWb7NNSxKDBPV3NDxO8owTiCurTbJ1dkHgz8RohLSk4DPQoL9hyELd/TJ/ThrSQs5uQ2Gr8tG4/vl+jFjaiwqgZ+Tpz2gLc9P4K1aIfpGvOjwzyBBZKKOX0Ivb4d+vx1aq9GPVK5JgIEcI1WQOjJ+BR0uTkxS15Kl74OZjtmeTgLMsyqv1VqPJXospfiYraCsN/VXWV4bJV/kpU1EXqKK+H/lX6o+9X1tdh/aZmf/81+vfpgRPyG2FwlzYYc9kFqKgox8N33ILxo6/AtGefwnHHHYf8Jo3w+P13oLYmMj8EAgE8N/nfaN26NdLS0tCtWzd8/vnnKvpr167FWWedhczMTJzaoz0euP1GHD1yOHy/oqIcD46/CX1PbIFWLVvg+eefZ+JfiQQJePPNN5GTk4M5c+YACJqjbrvtNtxzzz3Izc1F21YFeGXKM8EK2q7iGFoiDNiFxVWqwx95YPtX4YVRe6CFoQmpfiSxOPECCKtW9Sa4UE6bFMpEd0QTi4K0rgOr0iETwJ6iSqzbW0zVJmknExVGzfklbywsRS9FGnndRHYU9M00MHYJNgcUOXlCMDOF0XQXiV1dAcaigEE8nFMyvm9Kk6EscyZeQvnKukr86+fhbIQEYenlSyN/mDz4wf2FuG/c9Xjsiacw7MxzsOfAEaxYtiTcyUsXzUdmRjrmzp2L1eu3YNzNNyAnJxcvTZkMAHjrpSmY9c1/8eqrr6Jdu3aYP38+rrzyShx33HEYMmQIioqKMGzYMFx//fWYOnUqVm8/gGlPPYq7b74Wb37yDQBg6hMTsfzXRfi/tz5Aj/bH47FHHsaKFSvQvXt3AGzr5ovTnsdL06Zg1qxZOPnkk8PXZ8yYgQkTJmDp0qX4ef4C3HzD9eje+xR0uuR8VX2uKCRBZXYfrUBBbjoHB87A84GJY9g5ARLb4z0LyeBmWkiAMWk7ZCs1A8/Ofv7mg/h29V7VtQHP/MxMR4noMOroMjSLnrYMXSI7mdgPtZQndItWJjTOTI5ug5FGICDj0993qa6RxpWTZjKrJ7DbCTebigwtDrKMQwf2o66uDueefwFy85ojvVEztOvYOVwmKSkJz73wCtq3aIwmLdviljvvx9QnH8ELzz2DmupqvPnSVHz/40wMGzIIANCmTRssXLgQr732GoYMGYKXXnoJPXr0wFNPPQUAqMlsiknPv4gzTj4J2//aiiZ5TfHlJ+/jqf97DacMHIL2eQ0wY8YMtGjRgsizZPBMU596BDO//Azz5s1D586dVfe6du2KRx55BADQtKAVXnxxOpYumofRGgGG1Ed1fhlJRps6RgnGyfGyqbAEjTJT4LMjVM5BeAKMzXBLFJKRE29YgDEhTRuW/MMf0X4jZkLN1W8vU5cX0G90zrbmDWlLWDGRhNpzauGVZRmvz/9LFdKu5YUW367Zi/u++EN1jayB0eOFqTk6WNXAMNRhfWek8mmJaXj/tDmo9gcdRE/KzzakUVhchUPlEe1Z06y0sDC6lqCdPK5BKvIapKjuN89JQ8P0ZKQlpgGgM0e073QSThk4BANO7oXBpw5HrwFDcPrI85GVkxO+n5Ye0Qp069UHFeVl2LlrF3bu2I+qygqcd/ZZKpo1NTXo0aMHAGD16tX45ZdfkJmZCUA9Znbv2IbqqkrU1tSgS49e4eu5ubk48cQTyQzreEa/9/pLqKyowLxFS9C5c4eo+127qrOkH9ckD0cOHdLvmHpsP1yB0qpatG6cgQapScQyAVlGQJZ1cyUB4n0kyW1Eo7ougL1FldSanf0lxoEZsYInwNgM1knVbFEJBIKOV4kJEhI00rOk+S8twk68ZrxRfmzTf4k+LI+5H4TkYdD6wIgBXSI742c2ez5Ru7GZawvx9I8bifdM88Bo7q/ZHb1gEn1g9Jx4Kd8ATXbfcFkO+k6B9BySJCEtKQ0SggJMepLxApKaKCHVF9nlpyWmIT0pKKCk+qKFkbTEVKQnparuK+vQwufz4bUPv8S+zavx06xZ+Oid1/Hi5Cfw/jf/izyLTt2KiqDz6+dffoO2rVuq7qWkBPkoKyvDsDPOwrh7H0HT7FQUFkcWyMZ5edi13Twbs7J/9TQwPU/uhwU/z8JXX/wX3Ts/GHU/KUktfEiSBNnMBg6gtKoWQDCCU0+AOVpRg8paP9rnsZ04ToRNQ5t2mvEEmGMULLtYox0c7Rk5pdW16PbYLHTKz8J/b+5P3bYRQhoYMykj1klkDfvIJJw3mJuE07mY8kwlFX29MjTtGbTBiu2HK3Tvsb5Psg9KdMfrCUaHy2rw18EytDkuk61hSvCMTzud8PV23iyyKcENmLE8PyRJQt9+/dGl1ym4+pY7cWbfrvh55ncAgM3r16KyqhJAOiQAa1b8jvSMTBQUFOBIXRKSU1Kwa9cOnHn6MCLtnj174sNPPkN+QUs0SEtBcq46ZLng+NZITErCHyuXo1nzAsgAjh49is2bN2PIkCHUz3BS91649JobMO7qfyIzLQV33XUXZ2/wwSwU2+rwq67zY/fRSlX4enQj1towQyxNpV4UkkWIWNTv/+IPDH1uLipqzEPq1u4pQWWtH8t3HI2+aXQWksEgo/WBsfIhsEch8bcVgtIHZuC/fyEmaxJ5lABN4IJZe04e9GieiVf7d3R5Erd64esbC0sx7Pl52EvpSxXVFqExbR4YPVj1y5EJ7f+y6UBUEkcl9J3V7X/HVgWzNSt/x5svPo+VK5Zjz65dmPPjtzh65BDatGsPAKitrcXdt92M9evXY/ZPM/HKlGdw6TXXIyEhARmZDfCvMeNw3z13Y8aMGfjzzz+xYsUKvPjii5gxYwYAYOzYsSguOor7xl2P1SuXY9f2bVg0dw4enjAWfr8f6RmZuPCSKzH1yYlYumg+1q1di2uuuQYJ9ef6aN+nUZd2730KPv3iazz22GOYNm0aV384sXfjGRW7jlSivLoOJfUaITLcpZkUCU8DwwHlRC4idPOjZTsBIMqJ1SmkhsKoTR7Fiore7ghXoi+GYpLbU1SJr1eJ6V+6MGpjM4ornE+FaGDoyimxelcR8nOMTjHma1+v2SPlNRj67C8Y0bmpsdMlA2rqArj2HeNsv3bkgbHuAUeHzMwGWL50CT56+zWUlpagafMC3Pnw4xh46un46ZsvccqAwWjdpi0GDx6MqupqnHneKNx8x33h+mPvfhAntMzH008/jb/++gs5OTno2bMnHnjgAQBAfn4+Znw5E9OeehSjL70QNdXVaNaiAAOGnBYWUiY8NAkVFeW47drLkJXVAHfdeSeKi4tRXl2HdXuLVYcUSoZuvEDf/gPw/fffY+TIkfD5fLj11lsNn9+pJd/SvCjTZfY+dsUXT4CxDNIAVIb0OmmXD/vAEGZIo0nTlxDKA2OfCUmMTwvbrlYrXJI87mn4itJE0ByGpFPO6VQlRu+dVfgmPQ9LIrsQak1DyflW+GC23Oi6Hy3biZKqOny2fDcuP0Xtk8HSA0rKdRQe4nrP4QLR1RRt2p2IV97/HC1z01FR41edLB/CXQ88jKmTn8KhsuoorZokSbhl3K24964Jum0c3/oETH3jP0hN8hFNLekZmXjq/14D/g9o1yQTacmJuPvuu7FmdxEA83fw45I1qr8HDx6MsrKIM/vcuXNV92UA0976gEzMpu/WbX5bPIjlePZMSBahXQSqav3o/MhPMeKGD6GPyGxOdjJRmBATkmahTNQIMJ/9votrYuIJvWapKxLGjsRsdUnlWRLZhUB7HhQN1HlgyKHrqvLCWjaHLW0JGz/WCblJEDPNfUXzuLGWJRjdWPTYpc3ueyzA08BYhPbD2H7YWvppKzDMA0Mx3bAuaCxQ1qXZYdNkzd1TVIlGGclITfIRn65Ekz48yaeW1+/+fA3uHqETlqlsV9Mw7VEC5EnH3lmyqtaPR75eh9M75WF4pzzDsuwaGLpyZoJwLacAQxSglOdn2SSM8kKIq4uGRqzXWCVkGGvbRPKqpbVi6WLccvXF4b+1BqRfN+0Wyotd/W7H+AudrUQDMUJo7ERZT4DhgWLQaReB6lr15KxeuI3JivKLYKUS4tHM8c+iuVYo1u8twcgXFqBlbjrm33MqVZ1EX3TP7DqiH6WjB9qjBIjXbV6B3l60DZ/8vguf/L4L258527AsbV4fAFi7pxj/+XVH1HWWKKQQQsn8RCzwND4wosCeiTdSobC4Es2TkqOEaLtguhmxUPfxqS8DCJ5ifLisGnlZqUyE9E4rZ0Gnrj3w6cz54b+TEiXU1rE9VWlVLfaXVKNFwzTmgx7dAlcIZt5RAvEL7YdYbfFwLCsDymgc2Z0FmAUb9pXg09934eLeBQZtGdP4sf6QxZ31AgjN8ymd/mjbCZZRF9JPlR/5vfVAGZ74br05cf1WuWodKIn2VdBtwVRgjdw/58WFxDIsUUjh+2Y+MIZ39cGTlJDav4kRX67crTrcsLiyFvLRSrRunCGEvpvAarLYeqAMVZzzZMj8mJqWhpat24SvJycmGB5MSHqt2+oPa9x5pMJSrhYrYybWGjURw93zgYljaBczMad7WgOvsGKaiZdmgaB0/rjn8zXkcqHihGtTZm8ybd8ISQQNDA9oJqy3Fm5DeU20Y2KtP4A7P12NP/bQnfHEimSGKBsRKQDW7yuJThhY/7delnJeE5IZAjpOvCwQpSG745PV4QUyBLOcIG6EHQtsZa2fKmeSlpGALGP9vhLibStvvY70IQh+8IOl1cFkcEaO/jGQZgIxF6GswRNgLEI1/mQ5apJiGh4W11f+6A06Li35wPBXDYOU4TcEmkcnRSHxdJkV89A3q/fivyt2mxfkHAwsQpqpP0797bs+W21Y7L0latNSSD7RO2eFuGBQorC4Cue8uADvE8xZNP5FWo5oszUHi8XebZX6G7RiQ7IAWed3+BpnMkkZ+hmeacDqw2umqWNqW5axr7gS+0uqUGOT8K4FrSDvdFCBaHgCjEVE+cBYNSHFYECFfWBMPlMno2/0hKqQzwrPUqKNQgq2Q8GL5m/9VPnmOFpufBbNR0t34uW5WympRYPFxyIgA2XVdfjhj32GSRQ/X24scL27eDsAYOfhCjz30yYcrD/5Wi8TrZUopNs+Wom1e0rw0Fdro2/a+u3E+UzvFOhkYsdheV41qM9CWjt12DbfU06QIkymngkpzqB85ep09cHUzrqFbUbkLCT2ISXLsqlJwdEwap3rgyb/QrxuZ2K46CgkC7RM7pdW12HyzE3Yr+PL8ufBMpw5bT6+W0NOyqcVYAwzjMvA+I9X4pYPVpia9IwQ8mm56JXFeOmXrbj945UA9DUwpidy656FJGPZ9iO61USMTt7T3llgLRMv+1PGboGJ5tW+OcTupxQkwbgMsT4exio8AcYiRGpgYjXRPD97M/o+PQdFFXQn1RpBXwUv9kvRUqNZE0R9rPpOvOKeUe9xJny6GhsLSzHuw5XE+yQtkx5kWcb/NhwAAHy3hnSCOB1CAkwo2dnhei2T3vksNEngzJCeHH2Cuojup7bQxGjid7xZ2cK8RHItiVm/0QggzjNnrUUDYdsSXUZ4ZyHFL7SLVnUMHfWsbOz2l1TjUJmxAGPFiZf1Q7VjouPd/UXZw61oYIiTOj1Bs4gPNhOSmE7Wo6M9LT2EOjMNjA6KKiPnvRzfKDqah+d5opL1UZJw+8bVkgtM1O4g8nP0P8/B5Efv5+YhNNY//+BdnHFyZ3RvmYsZr0/nosUEVicYyhZlipJG9+08TJQVvLx4JqQ4g/JFax2/jDQwdr9o49OurdPn8Rfhb8z4Nk9fiporaA9zpC1DFGp06ps9t/KsH7NwZTONFG1/6bXDbULSwU7FydppSdHHX9i9FCifxk0Lj53gEAkN7wZkoKy0BE8/fA+uveV2zP5tPS6+8lo6wcjxM6Ro67NQ5+XEnvEW76PYE2A4oPKB0UzeWgGGJfOq5VNqDVNRWx+qVAu0TiE3zPeisuCKthuTBCLeBTJJITSYhfTbroHhNCHpCeJmERyLtx7CA1/+EU2P4bugHSMix0B1rR+7jlTQhVnztOvQFrm2xtwEHZBl7NuzG3W1tRg0bASOy2uKtPR0c+IMpizuPEKc9VgIR2lzbWrSWa1I7HQwwgUYv9+Phx9+GK1bt0ZaWhpOOOEEPP7442qthSxj4sSJaNasGdLS0jB8+HBs2bJFRefIkSO44oorkJWVhZycHIwePVp1EFcsoZyv1U68hDBqGxfupX8dJl63K109lQlJp21mE5INz2C7BoZGQ0UZRqqrgTGZK5QmpJq6gDFPgvpDLyxaz5rFq4FRIkShTHFcxN06jsgs792orGRT2t/thytwtKJGlfhOD5ZMQ4yoqCjHzTdch7bNj8NpvTpgxmsvqe6f1a8rXpv2LO4cOwb9O7bEpHvHAwCmPvUIzh3cG/mNc9CmTRs8/PDDqK0Nmv/+M2MG/nH6AADA2QO6o1tBQ9x3+034/ddF+OCtV9GtoCG6FTTEnl07DZ/styUL0a2gIRbNnYOLzxyMbq2b4PpLzsPhQwex4Jf/4YJTT0H/ji1x37jrUVlZwR4FaXpBcctMk2lEJ9YSjIFwFQ8Qnon33//+N1555RXMmDEDnTt3xu+//45rr70W2dnZuO222wAAkydPxgsvvIAZM2agdevWePjhhzFixAisX78eqanBtNRXXHEF9u3bh9mzZ6O2thbXXnstxowZgw8//FA0y8xQLmAsTryWNSwajP9klZq+QVmeMGYtv9bCqNkYMC3O0ZdETQfFZ6uXqI0H1CYknSbMoq2UxyWYaSzMBFJqbYSeACM4jFq9CQKOlNfg4a/XMdHQsrRyZxHKq+uQkcI2FfIK2LIsQ66sBKqCC7q/PAnVpUHBJQAgUJGkLl9ZBVRGItJkXwCB5Pq2K9UnQAOAnCgjkBhAIBAI3w9UAgHUQUpLY+J16hMTsXjhArzz4afwpWXjhcmPY8PaNTixc5dwmfdefxG33nkfrr/t7vC1jIwGeHzKdHQ/sTV2bN2EG264AQ0aNMA999yDC//xTyQ0aIwxl12AD76dg6b5zZGSmoptf25B2xM74ZY7g2akho0aU/H46tR/4/7HJ6NJwyzcdO1VuOfma5GcnIKnX3wDleVluOOGq/DRO6/jvnvvZXp27eu1a3GPR6FBi1j6wAgXYBYvXozzzz8fZ58dPIelVatW+Oijj7Bs2TIAwQ942rRpeOihh3D++ecDAN577z3k5eXhq6++wqWXXooNGzZg5syZ+O2339C7d28AwIsvvoiRI0fiueeeQ35+vmi2maDye9FIsFZyXAQPJKMf0noqehLE+MA497mxOr5RHRApTAOj24J5ZaK/C51WBmA7dddcgDGmRQs9OnrvhDeRnfZbW/InWQMZzYf+vR/XFmLboXLMHD+Yum3S37SQKytRffoghMSUzQCUIgsp17Tyfkn9P+31EIrq/ynvH6j/d+KK5dR8VpSX4ctP3sdrb76LQUNOxcHSajwx5RWccXJnVbk+/Qfj+ltuQ5nCuXzM7XcBAApy09G1Y3vcdddd+Pjjj3HPPfcgNTUN2Q1zAQSFlMZNggeOJiUlIzUtLfy3FnrdPe7uB9GjT180TE/GBZdeiReemYQfFq1C85bHAwCGn30eflu8EDIYBRiBMJ7TrX2E+r5y2uMtKYnxSCPHUhRS//79MWfOHGzevBkAsHr1aixcuBBnnXUWAGDbtm0oLCzE8OHDw3Wys7NxyimnYMmSJQCAJUuWICcnJyy8AMDw4cORkJCApUuXimaZGWonXvUgiWVcfWiiZnEK1QMvDVFCgpGwVBeQuRoivRue/DFWTEgi6xFpKd5STV2Ayf+DWIaCOT2fFn0nXhMfGL08MKac8GFjYWmkDSMTkgO8uAW7dmxDbU0NevXpE76W3bAhjj+hrapc567dVX/LAGZ+8wX+deEIdGjdEpmZmXjooYewc2fQJCQ6D0y7jhGBqlHjJkhNS0eL41uprh05fNC6CclKWQvmJyMSYnoyvkeycA3Mfffdh5KSEnTo0AE+nw9+vx9PPvkkrrjiCgBAYWEhACAvTy1p5+Xlhe8VFhaiSZMmakYTE5Gbmxsuo0V1dTWqqyOq1pIS8pkZIqCcr7WJ7LQH2cX38FDDkg8M4XIgIOuG2hoJgiQzHWXibMIVmkXc+G8WELUtRBMSuREzTZNybJo78Rrepn5OPTq6Rwlw+sCo+LFJG0jvxMvXvpSWhpTZC1BWb0LqnJ+FdXsjc9VJzbNV5QtLqnCoNDKv5WakID8naGZfSzhP67gGKcjLSkWdPxAWzFrkpiEnLbnehBR0tKXXCRg/Z1q6Opx96a9L8MBtY3DzhPtwwblno2XTxvj444/x/PPPAxCfBDIxMSl8T5IkJCWplzRJkiALyDtkFyyPYn0VjDBSboZwAebTTz/FBx98gA8//BCdO3fGqlWrMH78eOTn5+Nf//qX6ObCePrpp/HYY4/ZRl8J5SSnncisnNdhPQgpSIDsZ8Hog0KkQVFPzweGQLEuICNZZ5Ez4re61s/pA8NchQgruW7Imi06oQYwn5eU1cwEGKrTmykeSm/M6+XU4zYhORAybezES1fOCJIkBQUJKTj1JqSnA2mR/DYJmogcqVYC6iKKciktOVImjRD1k5aChPQ0JPgDQFrQrJOQlo6E9GR1ORP+C45vjcSkJCz/7TecdV4LAEBJURF2/PUnevcdoFvv1yW/olnzAtxw211o0TAduRnJ2LEjcm6VnoCYmJQMv19MDi2S8YTq2+Rt0Gwj4EAbWnD48HLjmPKBufvuu3Hffffh0ksvBQB06dIFO3bswNNPP41//etfaNq0KQBg//79aNasWbje/v370b17dwBA06ZNceDAARXduro6HDlyJFxfi/vvvx8TJkwI/11SUoKCggKRjxaGVuuihFnujViBh6sj5TX4r+IcHNF5YOoCASTrWDGN6BA1MFSZeMW8GyuvmBwyHV3OipNoCDUmC4KpBoayTf0opNgffmgXrETJWTFFOTW7pGdk4sJLrsQjD92PBtkNIaVn46XJTyAhwdjroG3btijcuxs/fv1fDB/cH+//MhtffvllpIDOAzQvaIk/Vi7Hnl07kZ6Rgeychqq2ZFm/LhUsfvv0Gqt4Bq8TTOwg3AemoqIiapD7fL6gVzyA1q1bo2nTppgzZ074fklJCZYuXYp+/foBAPr164eioiIsXx5xOvv5558RCARwyimnENtNSUlBVlaW6p9dUKcvV/vDRJmQbHR81S7ahos4BxvjPlyBJ3/YEP7bUiZewmWjcFqjtsgmJPuceKP9nAT7wDDQMnXiVfyu88vYeaRCvyyVSZAfek7mZs+gd1v93fHxZAZqssfOqqWLCQ9NQt/+A3D1Zf/AjZdfiB4n90WnLt0M65x97rm48vqb8czD92BI/5OxePFiPPzww+H7et129Y3j4PP5cNGwvhjarS327aE5sV0BEcK4TVLK7qPR0WIexEC4Bubcc8/Fk08+iZYtW6Jz585YuXIlpkyZguuuuw5AUIU6fvx4PPHEE2jXrl04jDo/Px8XXHABAKBjx44488wzccMNN+DVV19FbW0txo0bh0svvTTmEUiAeuLXbj6tmpDcEi0kyzIWa6I8rGhgSNeNIraMfWD4VM2izGKW7PiU/i7cAoyi4sGyany4VJtPIwK7lYV2amDk+v8Jp2swIGxKA8MTL+II0jMy8cqb7+CFOhkHSqsAANfcdFv4/o9LyHl37nhwEu54cBJaNExDbkYKAGD8+PEAguO6Q+cuWL3rqKpOqzZt8Z+vZ1Hz1qffwCga5198Oc6/+HLVtZsn3IebJ9wX7uC6QAA+STL1JSN8kUyllSitqjW8zw2DZnmWAO5lI4ZKG+ECzIsvvoiHH34Yt9xyCw4cOID8/HzceOONmDhxYrjMPffcg/LycowZMwZFRUUYOHAgZs6cGc4BAwAffPABxo0bh9NOOw0JCQkYNWoUXnjhBdHsckG5A9fuCrVKBScnJqsRJ2bgcXg1gpG5zWghqaoNRH0zNCYk2iRyPHSCtPg0GqRu0KNlpmlSsrZxX6l+QQrIsmxJGBYtwDgRxk/bgrBoGhkQKsKI7iLBwroTMyJp1MkIbnw2FZYiPTkRbZtkGnPGwKYbhU8RB6bS4pjygWnQoAGmTZuGadOm6ZaRJAmTJk3CpEmTdMvk5ua6ImkdCcoBqzUZ2XdcPD14NQ1mNKh27DpliCYkQwFGvwl/IMApeERf43lfwt8xUStDLqoU1EZMnY/nL+6milyJ/eiLgCVPEQ2Uz+b0ZybLauFRaPsG8gtrD8qa/zoBZQ4YIaYcAI/ffwe+/+Kz8N8hWTggA2df9E88/PRUZspFFUFNSEWN8YGoJHrC+tNIayKqDccROxFGuADzd4D2+ADVPSsmJMJA8Adk3WgOEtbuKUZ1bbT0LeLjoDMh0WsnjExIxgKMOR8kkAQPmvcVKnGgtAp3froa2w+Xk8txmKOC9OnfjnIobNpfihve+x1L7j+NSN+q/CDLVn1g6Msqj+DQzQPD6APjD8hYtasItXX0T2ElL0d8gcUkYu1pK2v82F9ShbysVOr+veXOB/CvMbeG/27eMA1pST5sPVCGjAYNjCsTBMKgAGoT4lxbE8/wBBgOqH1g1ENSaxaxslOrrvPjtOfnoXXjDOJ97US/aOthnPPiQtOFg87cQrzKWU+sE68/IEdNRrzCA4u8+fh3G7BgyyF9+lRUCGYsBg2M9uUpzwIC3KEBDEHPz4B09fI3fjWlx2oGfX7WJrw890+mOrRNxPtp1HZxT6L758EyBGQZ5TV1aJyZQkWnUePj0KjxceG/j2+UgYxkH2oyyPm9zJ6HdezE99tlgEz8yYRjyoT0d4DeTlCWjRcQKsFB8Xv5jqPYfbSS2Yud6FPBuHulpRvVDgM9Ix8YMwEmul3zlkk0tSZAEkJFlAnFtFi58yhu+2glNS3VNdNa9FDSEjGxWFmnWdpfsbPItIzMONm+Oo9ReDEDRx6Y4FCVdSvIYPSAiaOVNcRq6LvzB2T+8SRCYDQdkHHUuWFY41lZu6LGj71FZcjPTkW2Nm+QDRCxCfAEGA6onHg191jywGzeX4of/tgX/lsr4BgdDMkKGUGHzKMV/B7xVsKoSTBKKW9EhSR0cJtvqEKJzctc+PJicwZ0QOrXZduPEMuaz8HumYT1BHZe05baB4ZGYCXQMPXRENt/RVUB1PplyHU1ANgOU3QLxArYsRmfVk1I+pplticS+fwyxL6bHfWm8R1HKtCVRYDh7NiKimCKh6Qk0qledPAEGA4oB3OUCYlhRJ0xdb7hfZIvCy8e/HItXpyzFYUlVVTlWbLDquvpXCdUNsrIatQWyW+FpttJz+R0lnESnywyB0seGBGwlrCNb2bjrScCRu9ClYCOslsq62TM+asM5yT70DhBQmVlEvy11ZDrgqa/qqoqBOpqwt9HVZX6+6ytqa4XfoKoq5FRVRXMs6W8HikPVFVJqPUHwvdrqhNQlRBQ1QkkSJB1vr/KqipV3dpAgNgWCdXVkbq11QmoSpRVdWtryHyb002AT07UrVtXEwj3qUx4Nn9tALWSL1y/SvGMgYQEVFVVobq6JnytWnEfAGqqfaiSIn5aoXv+BD+qqyTqZwrICZDrN25VVVXw19ZArk8L4Zd9kHWST9ZUJ0S1sWkP3WGmRtB7H9pxaPR8VVVVjAcLy6ioqMCBAweQk5MDn89Hz7AGngDDAd0washRi6uVBYU334keaIUXPdBpYOjp+Q2kB6Mdtj8gRy3kvDtyGhOSSJBDuel5MJsmrDiRC4eeBoZTQHHiVdE2weJr9MWG4M72jLYBJNaU4nBZNSrrNyeJFak4WFwVHpvJlWotTXFlLUoVfk7lKT5UHg3ujg8QTMsVKT5UpCfDH5BxoDj4vdcVJyE9OVFVJ0HSNwknVqTiQFGwbk16EvwBWcWDEeTSFBysN7XWpCWhKDVRxWdFamKU3xYN6oqTkZKYEH4mLUqTfKisdwT3SdEbydKkBCQn+lBcGdRAJ1emhfnyJUjwlaeivLouoqEuTcEBhck4UJKM1KTIQhuqm5qUgMq0JBwo0TcvK5GYIIU3bsmVadhfUhX2BUzySbp+gTXpSeEoKpGoSPGhrDp6ndGOQ9JYCyGpIo1Lq5qTk6ObWZ8WngDDAeUQ0y4YUfH3FmZdkRoYVhDZptLA6Nj6GdX5ZiYkvkRNJK0SPSExuXRoL5LBlIDLYhiSrO+6QQXxehTyxoGPgihO6Mr+d0M5lu/3Y+ZtnfHOV2ux6M+gM/g34wbgjh+Worw+FHnOnUNVdd9a+Bc+XLo3/PeIzk1xz5mtAQDXfzE3qq3zuuXj9uGtcaC0Cjd+FXSMfmBkR5zWOk9VJz05UTec+KuxAzDmy0UAgFuHtcP+0ip8+tteYlktpl3aHY9+swoAcNOQE/DPjgUqPi/s0RxfrjxArmyAB8/uhB5Nc3DjV2RTbf8TGmPxn/oO9n3bNEKPlpl4Ze4eAMF+DvGVk56M/97cH9+u3oNpv2wBALxwaQ88+k3Ep23S+SdhQOvG4b9DdXsd3xC3DC3Ao1//RvUcTTJTcKCsOszDE+8uw/bDQVNKi9x07NbJnH3bsHZ4oZ43kTinaz6+WxP9PrTjkDTWQph9xxDdQ3n1kJSUZEnzEoInwHBALxOvLIs9C0m0BsYqqJ5Mz1bMSM9oh0s0IXGat2jel907f1ryJVW1pjt/F7nAiPeBcUIDY5CkUCk88kR7VfuB1NRUFNUAe0qD33ZSSioKy/woqQr+rUzmCQAV/oRwWQAorZXCZZTXw/frgvcTq+Tw/TopMapOZopE3HkDQHJyarhcDXxRPBghICWFy1YFfEhNTVXVVT47C2rhQ1JKim7dI4rnJeFodZBGqIySr2o5gNTUVFTLieFrsi9JRc+v6EMg8gxtqoGEpGTqZ/JLARQqeDhUGaGVkhLQpVOt4F0kSmolIl3tODRqOy0t1XRjZReEn4X0d4ChD4zBgsh6Xo9IJ14RoDIh6V1n1MAY+ab45WgTEg1vpFdDI2/O23zQvBAleJPp7SmqRNdHZ2GlSbSOmxwuuX1gaPLAcPJm1NWrdhXh+dmbmeuxQnuqNevu1Qih8bypMJKFmdd5PVyX4dlVjtaEilY2eIbzhalgL5v6acg6v4P0+fjSwojPWOw9aMdBkk+/72IlvACeBoYLah8YxW9Y+0C1A8FtAgxvpI9+WaOP2dgHhqtdUiI7iorLth1BYXGVkEWM9jRqLb5fQ6fCd1N+EtHzmizAhGSEC6YvMryvfJynFYecWoJsbGrTCoFmjx3ql2vfpTNpkFlSapjZOlpZnuhzxjk/mvFBc7K66XhU8h5FkG+u0sJYEDJow6bPmvb9dm2Rg+U7jkZdj/WB854GhgMqs5Hi+pPfb8Dq3cWqslbGXXWtscrQ6WgNurN+9FXw0dcM6BjcJOeBMQdZA0P3hkKH2dkBXt6JtARPdC6Sh1yF/21g9+MIQXUkgcY0ZR2UmhXhFOvLyuTfIRhFHprRNZp/aEyrLP5jUeKLIA2M8abNefBmNQ9B9HEhzO3HtPU4hXKgKT+cj5ZFn/xrZQGIpQaGbOrgq6d3nVclTNbA8AlXtDtCO4VFuggq2oVJ3DRotmiYwU4fGAuGCO6adoA1P4lpHhvSd8aYEkErhDA5uiuKEhNHWhBgjGAqwMBcW2AkfIkyIRlFPcZis0BvSiSXi7H84gkwPNBz4rUK7VhwnwmJRkhgoGe4o9KvF5BlZtU6QPar0WtH+6yiPlRWQY6ljLZcjOcWU6GP5agBQLNDjsFsb0eLQdOGkX8BIz1KJitNtLu80DOvh8ArwCzYctDwBSzaapwTxdgHRg6XUZZXl9DRLMtsZjajNAdG86Fd493q0SOx9H8BPB8YLqgldfoBwPqujTLV2g3uRHa6URy0F4Mw8kfwBwj8UfBG9j8hV9ypCWeUJDELGG+/0kI5P1o+zBHWeDNNusdIXKuB4eHNjSYxlvdkphEz8rHiWQRZ+1lZlDR98QowX63ai075WVx1ATpNl5EJSdRGVZQpShSoTdM612O9SfI0MBzQS2THgv+t329axuxjd1r4tZTIjjSxcvKhVcMG03nzUdPr4yHPzlX9baetl8q3KAYmJLvAncguxs8mahesjkKKPpjUCsQI2fxQO/FGU+L1gQGA/63n9zuSYR6FpE2JoaovyPRjGIVkJNzQN8EEqxoYzwcmDqEc6Oa2V/L969/7PeqadiwYndZsN8i2dL56enV5v52obMcyvxmGdj6NpQlJluXYOfFaqGumXmZWPxttkW2GXc3JELsIiN7hM5/1YyLAWIvS5K5a78RrVkaxMaV2hmbbPLkpUTZgfb7wopDiEMqBLt7KE6EdldU3xhC/OPIRrAvImkgOSh8YBhOSFqIWGR7B0ExA2320Ajf9ZzmW71AfAGnV8diqxkG3dTO2dPpahPziNhMSzcKqrmB227qJMsr/g8WEpChLElasCDBWvkFZZquvZZNXcxJN14iO84OT9n3osRZrHxhPgOGAU+OsLoYaGF6IOkrACFoNTECmO1qANHlQa2AAIdtw8gJjTtho4rv1o5WYua4Qo15ZouobIUcfWBjswvPAxFj6ENW62pdHbUL656uL8eaCv8J/M3dhjKcM5fdEirixkhTSZ2G7HwxXV/xt4CsERH9vosw72rJKnkRFOrHAuhOvIEY44QkwHFAl1DIZvizjQ7tjjq0TL2c9XROSnT4wlH4kJFq0YdQ2fqk0SbiMivx5oExV1i2wc26LtTAjDLJ6bP22/Sie+F4/SZ6pts7gGm2PqTRdlN9WpLzChCTYXmLVhKTUwJA1oSrJMqq+Pm2+/tHStSpM8MBz4v0bQvXSmQQUcyjH8CwKR1+3gddezgLtadQyKA93JJShnTRE2XrJzVEIX7o6XLWvlDqM2qIJiYozfYgW+oSYkKw8kaD1RcuDyG4SvQiyZ+Il/xYBqyYkZXWSdkirGVNC1BEAxukh9O/ZJdpY3QiIPAaDq/2Yth6nUEUhxZAPO8E7sHXDqAmXH/lmHVc7gYBaYAnuEinqEU1I9BoYu06jpnHiNSqj1NTFOlKHCiYs6k2JsdRI2gUZjGHUJoNl++EKTPx6LVfdSDnFb5iPT03t8C+RB9sC1jYR2igkoj+c8rdWA6NHV45vHxhqAVWnnBeFFI9QLZ5xsGA4CN0PnXBtx+EKrNxVxNwGyYREM4vwHuYICPS2J6quzasYTTTK0FSRawbr5KyF6Knthz8Kw795+dKr99/lu/kIWoQsi83yvHpXEd5bskPTBv9LZK3KEqHJCks+MBoNjJlPnvY7Mu5DFhOS+m+1D4x7TUh6iLUJyUtkxwGzA8uUYPKBifVoEABdHxid66VVdcxtBAKyajKjDWQklaK100uQhDjScScIpG4gNgL1vZ+voS4rRpMl9jnv/Gy1Y21qTRWG67LIEGuuOqwmJPs0MFZMkr/vOIo2x2WE/yZrYJSmWMImSQdWPjkjoUldzp7vOt4z8XoaGA6w2OLjVT9jYc/GVLqOwyxQp/WBodQUkMrQm5AombOBB1lmOQtJ+VuIxEWFT37fFXVNr8/iUWlpF89BzQD94HKi67Snfos8C8kKfBY/wk9/j2jZzE60197eX1KNRVsPkaOXLHGlbNO9JiS9UrHedHsCDAfMzvtwCm5U2OieLaTzCfD4NWhNSMEwavP3QBYe6NoU9Zp5fGB0K5rQsr4Btv7QPBMcTR1uExJfNUttGvEgw/7vWEa035hdsFMDkyBwtTJnTV1g6v8244o3l2KO5hRyy2ZW5cuPwVJiNdVYrBPZeSYkDmid3GgRa2mVBaJ9DPQ6iifbcFQmXn3y6noE5kRPsmYg7+BMNDCQqXdKondx1rQ4OgnpRCiGZOBoRY11QjGGHHSCIaKwuAofLtX6s7C3UVMXwGlT5qFVo3RKptT8sTT51A+REHDRn5ZIcwU5D4xa80TC3M0HMLxTniktHrhaA6NTTKT/Fg88AYYDqpcpcMyxjt9Y2x9JYF3weLIN+wPqOT9oYjGvZyUTL/9pSxS0TQiz7PJUxSxOiCLmUwn2bCyr6/yY+PU65npuNF/pRXKc+9JCHCqzLqQt23YE2w6VY9uhcua6rBqG/SXV4d+i88CIjHghsUajvayts9OEJIgQA6x+D1Ycq0XAMyFxgEVSDi2Q+4or8eHSnRTludkSCtEhq3qPxaWB0e4KKe30pCKkfBB2grc12npiTUgC1eNKmgKmfBELOyuEmZBk9W9SN323Zi8OllZHXedhISWRbZoXtT8T/W2JXCtNw6gpTd7UOag4eQq3Y9M0Re8DQy4X6z20J8BwgMdR7dwXF6K8xm9M10Uuvy/M2cJVTz8KiXyD57gErdnHiiMarZxmx+IVgqVTvrXllA6YLhhPPFrCWKul7cK+4iqiUELqonEfrhTWbmqSj7uuLPOPI9HmWatOvEqQtENawZKEGsKEYUd0mlPQm3vmUx754OWBiUOonXjp6tDsGN2ifQGA79fs46rHGkbNZULShjga0DfjwUoacB6QKNCQpRFyEhMkqkmYFrS+RXrQm9pCfMVi6rOy2Ij4PAdN/llFSZbtXwRYNTBK0J4zpldXJESazIkmJJXwTwZRMy1qc2NAyK7NiJ6MefXby6jqx9qJ1xNgOKB857FwvHIC/KYOtpo1dQHsPlrBVCcQkDU+MHQeKiQBxGoYoQicP32RcduUJrIkX4LaEdEyZx5Eo6o2oNJMsH4vPEI0qymHN0hBC6sRLlr4OFarsaeeQLxO2oSqhX89E9Kx5QNj1Yk31kcJeE68HLBrkTgWFhxdDYxO+Se+32B4eB0JdQH1tE+tgSFcczoKiWc7S+tAnORTa2BECNdWT6MmTW8xHecu+Mi2H44I7LJsvzP+O4u281dmjEJSwooPTIIUvaDzaKr06pj5wOh9OyQNjBM+MHbBapueCSkOofywzCZ4lvHhpmMJRPMikpw2p0WUU69ePWIUEl2bovqDlwrNRJOcmBDl3GwFdg9HPfKxdgwkIeisKaZDDpRUqf5m2cQ6MUPQmFJoYCUKaeiJTaKu8flTkUHUDlG4BtTUxcYHxjYnXos+gJ4JKQ5Bky+Am7YbtoiwYEJygH2/1mQkU/qRECZUpogy6pJiQRvKmuRLEH7QqDUfGIkojLhITqeHQJ612sNY72KNwBpGrYRVDQzNNTPoCT2shzmGYKcGJhbwNDB/QwTUa6cHBfQEMJGCmV97GjUlfVIJ6ky8dMXM6XASouEz6AOjbMsa13YJ0//bsB+vz/8zRk68samroqN5R0xrgAMTjvrbkrkbtWKeJQkePIulXhUzbawe51ofGFl2xvRjVwv00Y1kxDoXmSfAcEC5MPy88YBBSbZFwE2SvOiFVqgJSZajtGC8UUjO54Hh8YGJ/L8REjVbVBGPZoWG0dz21A8b+QnHObQmGvfqX6y9fysLO0nbwpM0Td8HJvqa8r0w+cBo/m7TOCOqjFthXQMjiBHe9mPbfHzCTYKG2+CEH08gwBcJRipHa6e3Mw+MeR2ZzlYtiXcwt6qF4cnpYuec6AY/M22oO9thjs7u9mVY2MxYiEIiCR48m329BZZ8lIDyD3I9Uh4YbVkXWwSjYHUD52XijUOwZeKlp+sW/xcrcOIJtLkpgpOsectEAcamdymaBu3YCGgWRyuwWj+eJnIaCBNiNX+5uZ+sPLM1HxhRJiRyHRJvavmFRQOjLmuHWcUuudtqEINnQopD2GmPZBmo8bRTFUkvIGvU8BqBxqgezTUyxPDPQ0UGHZ/Bc4fM1eDMjVuByxZnV2wRtDt2HhIOaZKspMq3EoUkyvlb14SkkEMOl9fg7BcWoLSq1rQtbeZwkobKZUPeEMbHF5h3eKxNSF4eGA64JnmdjYOH9wlZ88BwthKlhqehL/pwOR7wLjx61bRDQOTQtKyBceFUbu2ZRAmxGv8tlrqy+r92IMq/jNeJV7AGhocPWifedXtLsG5vieI+uR5NFJIdkTn/nmmPz5jZ+Utmj+JFIcUh2MxC9tB1LxzwgdFM+rSaK6uCZ6xeD8siou4X6xzHQgFj55zILZiL5EFBbOXOIqzcWcRMw6lNlJUxZGXDQNrZ82lgyNfNaOn1LzkPjBpuNglqYeSnRNPdsdbAeAIMB2yzR9pD1lHoamAEPly0DwzlUQIW2oy5cMlhq441yy5UwLgCyvdyz3/XsNUNaWDEsaPbRui3naH/eiBqYDgY0dMCmmmH9O5GHSUgR/MVa78QFhj1Kc2Zf54GJg5xLDjbmoLzEW/8z3IdcoJ9YASFUTsNLh5kuh23JIk+zJHf/8GtsKJREBeJZp2QYxoYC3VF54HhocaSB0bdGPk+TRh1/IgvxkImzRDzBJg4hF2uFG4I8bSKw+XkU7fF+maoxSHaowQstSmMDjsl2rOQAERppmIJCe5Tp3NHgQkcwJY0gaGsQA69WlYfHSVE54Hhoae3wJoeAaNzneY4EreNeSMYaaJo5o+EGEsQngDDAbbQW4aycIHavx6i+RDtQ6A1lTgi/MVQwKSNQlKOTRGCdiyEIDtV8LzPI/LbjGU4PnM7FrRwVjQwZBMSDx3ydTPW9Px3yJe1JiRzvtwCo3mTZjPkaWDiEHY58R7LsNUHxoKdnhZVtX4xAgEHDa3AZljWYlvadq1AkiTXRSLxa2DE8mEVzjnx8te1FIVEWJn4TEg6PjAmHzNLW9rHZFofYjyurM5psfb38cKoGWHrTp+R9N83D4x2P8BiZOHDeS8tEkKHl0va7lOXs94nsZ5g3QK3dEPofdgpwEQtyLxaKwssEn1ghGpgjImxLOwiTIKxglE/0Djxxnp74mlgGGGv/OKWaRIor/ELpSdywg1oNC7av90MHkFOBn3/aXOMxBJmk1ss2OPtk6KKGuwvqRLLjAU4ldLIysaD1oTUMD0p6ho5jJqDF10fGONq9BpPa47usf5GjULdqQIjBPLCA0+AYYTTSezO6drM0fbsgngnXvVCHesPiRZ8JiS6SVKStIKdAA2MxfpGGuZYOK3z9smCLYfw2LfrBXPDDjnqhx1tqP3LeNuiFWBojw1wUgPDAjdtPFlh1A2yzm91/dg+uyfAMIJ552PRHhprG6MoiNwxan1e4incl5dNag2MizrCjUPXPb1jDU5tpKxE+NHySJrjRGXiZTmNWn2fvi0rkW2xHo+GUUgUDxbr6cYTYBjBOuSYnMEI11y4BnBBuA+MNg9MzKcCOvAsPDLoxpEESbgTr9X3ZjR+YzH5xXrCtQqnfWBIhy/TglYDQ5IxSNd4NkG6GhgzJ14GnzNtUTYnXjf7wFir7wQ8J15GOP2+3LiL5YHIbtMeJRCIIxsS7wdPM9EdKqvG16tKFW1xNSUM5j4wMfGCiUGb4uHUUwQCMvciSzvWSUKGKBOSXhSc2dhj2nhyf9Nc1YSiqpbuLAG9Z4z1M3gaGEbY6sRLcEY1irOPJ/OS0ERgpDBqYdTthdHZI3qgDRPXJhG0KiCIMM0ZjVHdyAY7z0KKl4FiAls1MJp2+E1IdOXIPjDR5UQe5mjuxKt/75W5f3K1SWyHvqjjoDuexfOBiSvYO3FE044fEcUYIrUBAYLJKNaqWDvBHSQeaw2MyUzu6V94EHwCp4a7lVwu9BoYOh8YnpentwH8YsUew3pGvCtPhpZBCDunNT+F/8+dUPsZmpeJBTwBhhGsAoxlHwKDRWDrgTJLtJ2EaK9/bbRNrD8kWthpQoqqw9XSsY1jRdB16jGCJiS+uqLzwPB8O3rT5/d/7DOsx5ZBXV22WXYqknx0W083j0aa/o715+QJMIyw832RnFHjyEpkCKE+MAFNiF88mZC44qj5NFhWF2vL5iOYOfE6/9biZZzowRkn3ght7eHLvHSMQJrjyCYkdvCmumfpXq1ZOMmXgD8eHUHRhrtHo6z7h/KyZ0KKK8gWvPJNaROuHSPyi71RSIj9ToAW3LtZneslVXXMdZjajUG/2nn8QLyMEzPEQxg1LWhNSDxCPO8GkMmJl3AtNclHV9fFA5Iqkd2xqIHZs2cPrrzySjRq1AhpaWno0qULfv/99/B9WZYxceJENGvWDGlpaRg+fDi2bNmionHkyBFcccUVyMrKQk5ODkaPHo2ystibTOwMoyYh1odliQKP86oeovLAyNxeIo6DS5MCvonOqt9RXUDGwbJqfgImKhjPB4YdIf5tDSZQ/LYShURbi1oDw8GHExoYK/3j5vFI58QbWwgXYI4ePYoBAwYgKSkJP/74I9avX4/nn38eDRs2DJeZPHkyXnjhBbz66qtYunQpMjIyMGLECFRVRVJ1X3HFFVi3bh1mz56N7777DvPnz8eYMWNEs8sMW0NTCR/CMSK/CD5KQOsDE/udAC24fFk4n8/q7u6KN3/FqFcWW6JhBD327BRG3bzjZYFjTrxWJjzKqiQhg3gWEgcLvPNnRa2+ZlMLLV+h8fvouZ34GncLKJx4j7k8MP/+979RUFCAd955J3ytdevW4d+yLGPatGl46KGHcP755wMA3nvvPeTl5eGrr77CpZdeig0bNmDmzJn47bff0Lt3bwDAiy++iJEjR+K5555Dfn6+aLapwToBMknyhGvxFCptBJHDPLhzkTVX4gO8nPImwLMCwxwRFHDbSdRA8EiAYwFOJbLT5lyyA6QpzifICYZXA/PavL+oyskGDnindmiCRw2On+DdmDgFGtk11vwL18B888036N27N/75z3+iSZMm6NGjB954443w/W3btqGwsBDDhw8PX8vOzsYpp5yCJUuWAACWLFmCnJycsPACAMOHD0dCQgKWLl1KbLe6uholJSWqf3bATg0MaTAcI/KLDT4wStrxs7PmiybijARxQZfwOPHGyauMCUJ95lQXWRGUqE1IlNe48sAw12BHVOBFfas0ArybTd/q8+b0vtVjzIn3r7/+wiuvvIJ27drhp59+ws0334zbbrsNM2bMAAAUFhYCAPLy8lT18vLywvcKCwvRpEkT1f3ExETk5uaGy2jx9NNPIzs7O/yvoKBA9KMBcP6FHSPyi/izkJR/wxVrNRV4+4FPAxPbXjETvuPlnbkRTqnu/RZUMLRzJdGJl6CB4fGjc0KDzZuQ0e1nuNHwFuts38IFmEAggJ49e+Kpp55Cjx49MGbMGNxwww149dVXRTelwv3334/i4uLwv127dtnSDuv7YllESB+8p4GJRpQPTECOuS2WFlyCCOca4oYu4cnE60EfESdeW53xwr8CFhzkaWuRfWBI9HiceJmrMCGeNk+soDHSx3qTJFyAadasGTp1UjsvdezYETt37gQANG3aFACwf/9+VZn9+/eH7zVt2hQHDhxQ3a+rq8ORI0fCZbRISUlBVlaW6p8dsD2Ft4b8MROFJLDb/m5h1MHn4xN8Ygl3noV0bMCxRHaEhk44LkNoG+QoJDFh1E7Mn9waGLf7wFB0eKz5Fy7ADBgwAJs2bVJd27x5M44//ngAQYfepk2bYs6cOeH7JSUlWLp0Kfr16wcA6NevH4qKirB8+fJwmZ9//hmBQACnnHKKaJaZ4PQLo/n8stOSbOfDKoRm4tWakBxwNBQF/oPxeOq4u1d0o5BczncsEUlkZ38bQNCEpH0dtGYZ2tdIoucTdZijA/s/PUH8WAnAMEKsP1XhUUh33HEH+vfvj6eeegoXX3wxli1bhtdffx2vv/46gOBLHT9+PJ544gm0a9cOrVu3xsMPP4z8/HxccMEFAIIamzPPPDNseqqtrcW4ceNw6aWXxjQCCXDO+z8Emo8gKy0RxZW1NnAkDiK7Teu063ZbshK8GXXj8SgBmh2oBz44lsiO4HdCuyzTathIZh7y2OExIcVQA2N7y/ZCGyhBQqw3ScIFmD59+uDLL7/E/fffj0mTJqF169aYNm0arrjiinCZe+65B+Xl5RgzZgyKioowcOBAzJw5E6mpqeEyH3zwAcaNG4fTTjsNCQkJGDVqFF544QXR7DKD9X1ZD6M2r+fGcFUtRJoLtNlBZZLtzaXg/eD5BB+upmKOeOXbCYS6xqnTqP0ySQMjtj0SPWIeGJ5HdkQDo9M0Rdtu1jbGg4lXuAADAOeccw7OOecc3fuSJGHSpEmYNGmSbpnc3Fx8+OGHdrBnCXYKMCTQCCfxoKkUmYmXHEYtjr6d4EtIxyuexTgKCZLhBK1379dth+1i6ZiBkz4w2oWMVqtBbUIizHGxPguJFrKBA55Z2243favmWB1OYz3vemchMcKpQ9RCoPGijwP5RXAmXq2HfPyYkLh3NRwPGOsQRzPosbdoqyfAmMHO8a6N8OOmQ1mONMeRnXjZeSH50oiGlqtQkzQtu3neCvX316v2YNeRSmKZWGtpPAGGEXa/Lr2PwQjx4Cwmst+0PjBBgcbFM4ECvOsBT7VYq6c9HxjxCL1Tx/LAEE1IlPMNLYuUeWBc68Qr6/xNkQfGzQhxd/vHq3TLxHqT5AkwjHDaaYlmsnC/+CJ2MZWjTEjxo4HhzQPDA7d3idsncDfDqZ6z4sRLC6ITL4kXjg/BGQFGJwop3jPxUrAW602SJ8Awws4XRoxCoqkYBxKM8DwwUcm24gNOfu9b9sf29HZPA2Mf7HXiNf626BUwtFFIdInseGB3gIMMAxNSnOeBoRGTY82/J8AwwlbbM2HAHCsaGOE+MApydf740cDwgEU88yVIGNSuMQBgTxHZbu0kjDg/hl+Z7XBq50vOA0NXl96JNxqi8sDYnYkXOHbDqKkOc7SfDUN4AgwjnLb5HTM+MKI1MLLm75h/SvaBZafmkyQcl5liL0PUcP+4jDeExoFTTrx+QkOitRp2HiXgyFlInG2XV9e5etbyTEjHIFg/Ij+DxKN1TgWOnSgkoQNd47RbZ+HAuWMOEuJjQCD26ud4hlMbKVKOJQd8eImLP08qBts1MAZJJs2avuT1X139DdCsdbFm3xNgGMH6ERWWVOFASRVVWdJgOGbywNiogfEHjmX9C9sk4aahYD4uj+W3Zi+cyghu7SgBOh5pz0JyqwZGv23j+9sOlcPN3wDN64t1Jl5PgGEEz0f01sJt3O15mXijoVW4BCdZ904ETkKSXDYeDF6L98rYEfqOnOo7kgaZ/igBOhBNSCR6cecD46LvkAN0JiT7+TCCJ8AwgueF1fjp1DbEKCQaJ16Hv5PmOWnMdcT7wKhNSPuK6bRc8QiZ0cfHLRo5CZ4Tr11wSmCXLUQh0YJsQiLxwkPb/o9BVwtBdZSAWF5Egka7Emv+PQGGESw+LSHU0gowpCgk5tbsx3e3DkTXFtlMdUSakLROrWVVdVi+46i4BuIY8bTr87Rm7Ah1ma2nUSvmIbITLyUdSh5JGpgESUJmSvCkm4LctCi+aOGIBkbnOtVZSEI5cQ5tjssAAPx7VNeY8mHLWUjHMqrr2D3Jauv4hynNWR5O23l5mhOayE4zle0tqgw68h6jYPKBkdwj9JrmwXCGjWMSTnl9+QPR364T840kAW/9qzcqavxYuu0IXp33J58GxoGvQY8vJ07CthNG/X3j4Da4oEdzpCT6nGOIAE+AYURlrZ+5DrUGhhBMQ+cD4ywkjmlBrAlJPakeKqsWR9yFYAmjluAeE5IZPAUMOxzRwESlKFBDfCZeUhi1hFPaNAIALNt+JMgXB21HMvHqcEZ3FpJ7PwIzITnWwgvgmZCYUcUjwFiYbWg+AscXLI5VUmwiO1mlcTlUViOMdrzDTTmBzMRcN0/ebodT0R+kdliGGM07NjPzhG7zPLPtp1HDwIk3zk1I8aDU9gQYRnAJMBxmpxDoEtlxk+cCj5lC5IQry8HsuyEcLD22NTBgOG07mAbGPUKMEeJgfnQvHIxCigqjZhhfNOOWJHRLqvv0tLRIiOEKR3UWkos/AiPh0y1zjCfAMIJLgKE2IZF2OzRHCTjsA8NRR/R3WqdIyBMyIblI+RBTuKUfJMlkB+7iydutCKn1HdPAkMKoWTQwFGWIhzkqroXmNx6NnRN+KLqJ7FzyHfIiHj5PT4BhRGUNuwBjLYzavJ7zGhj2BkXPtzUKDczh8qAJqVFGsthGXAKmvpPif+L0YA6nfGD8joRRkzQwpER2HLQ56rCC96yoYF33igkuZi0MT4BhRGUtRxQSpQADAF+v2qv6myoTLzNH1sDTnugdYw3BLJeWHHunMhIapCTinK7NuOszyi+ugRkvcTA/ug6Rs5Cc8oEhRCExjLLJMzealjGjZsWEZLdPGCnwItI2RX2h3IiGu7kDvCgkZvCZkOgGwspdRVHXqL6/GIRRsw5t0QIMSShMjKXB2wDn98hHboa1AxZpey84YbtHjDFMZBcPWzyXwikHS6smpNfm/2VaxiyRnTUnXuYqzDhWM/EajjGXPJo7Z3wXg0eAqaPUwATPxlDDjYc5SpCYt0Oi1yqyAOOSr0oDnrBzJVj6TnKRCclNEVFGiCfTY2go2Cn8mSayE21CInwdqitSyAeGnbYjPjB6YdRUcdRieRGJeNhfeAIMI3gEGNrkd6TxTpfIjpEhi+BLZCeWB1Jkl8+lAowHMtwyPybE4bhx8jRqK1FIZqARuEO33ZgHRjaIEIxz+SUuNKSeAMMInkR2diMepl/hPjAEs1yij74nnBT6rGpFmM5BgrvGg9Frj/VJtiG4qb9oYWcmXu1r0b4nkd+OHimVCSnsA+PSKCSd6zQaSDcLCe7lLAJPgGEEjxOvFc0A3WGO8XCUgFgeSCYkHwNjTqf5trJrfWfhduqJTpIk15iQ4gVGYyE/O9VBTijgQCZeLew+poPc/ZLiF78JyRHohVE7zIZouGWDYQRPgGHEoHaNcWXflkx1qBdLkjMbXzVbIUGKuRMvKQqJxRTgZJ9xJC5W4ZPfdzG15RaYnoXkkvnRiM+kRPdNkbIsY93eYvvoa/7WHmArcsMkSWQPMeJp1DyHOTpgHjxmo5BczVwQXhQSIy7uXYCLexdg8/4yLNt2hKqOlY+Iyok3DnxgRG/irGpgHO8zp9qR4if6wS3zo9EGI9nnLgFGhoz/bTiA1+aZR/cIazMqjFocWIIseeaQWOSBCbdNZUISzIxAuJi1MNz1dR6jsLIJOGYy8Qr+UklqbRazkJN95rRZxy0mJNM+joMZMsllAgwA/Hf5bkfb035qQn1gdJy2JMJvnjkkloc5xjvcLFyF4L6vM17A8HKt+FtQCT+Oa2A4TqO2hRM13ByF5JyfUrzoX9wz8ceTCUmW1cdo2NOGbPi3WA0Mebwqv5ewEy8nfTvBclI8sb5LvgESjHhzyxzjrq/zGAXtukr2ZaPRwDgLCWDe2jjhEMYkwMSB2U2Jsuo6R9oRiWDCQ/337pYdnlGfJTNEtjkFUgSendDmghEqjOuQUmlgrEgwDsAKW275BkjwTqM+lsHwDVvRwLDYiJ0C12nUDnwNLP3gtLImM8Wau9mR+vOezBB0GHbfokuCW+ZHo+/TbdmdZdAnxrTShhJahY/Ib4dlvLoxDwxgVQPjXrg5xDsEd32d8QTG7Ki8oDrM0WkfGA6fDreZkJz1gQEapFoTYEhRV3ptuQVmrLhlgjTi02XyCwCgzmENTLT2VGQUEpkaaRy7Maw3eBYS/1lRbob7ejsaLvw8jz3QfneknYjbMvGG2mL2gXHga3BzFFKDlCRL9Wknb7dNnkZsu2WCNPrGnM4XRINa231gjP8Wa0EiEyMnsuOhbz+i+otlZLvlIyDBgDe3aHk9AcYBWBmjbvNLDbHDOoCd2D25Nw+MZFkDw2KBc8ncEjd5YIwGg9sEGFmWHdfARGsYxIHuKIFgAa45xBETEv/7cLMTrxs1Xlp4AowTsDAOaHbUzmpg+BpzRIBh8eF1eGFqkGpNA0OLeMoD4xYYa2AcZIQSyhxIOel2jCv1txqdyE5cSzpR1KoxbEUD4wTsPCuKFSLHq1v7WwlPgHE7XOYDI2n+SwsnPgYWh0unzW5WNTDUbTnSCh0kiT1jsx6Ob5QuiFI0jPrMbaH5MtQ5kFrm2tcv4TZjsUBLxJ8cZOzn1S1RSCc1z8I34wYKo2fEmlu+Ck+AcQBW1IRui0IK+8CwOvE6IMC41YQEAFmOaWCOzbOQstPs6z+j/nKLrV8JpQbGCROXrYc5ShKxj9Vh1MH/usXpWwkZ7olCEi2subG/tfAEGAdgZRy4zQYf+khYPxYnbL0u2yyHIQFIS/Y52p7q7xj1i1BfCYG0omnHjwlJltVRSHZoiKJPo1b/7YQJSV0mWCLERgpDckG3Z+J1s5BgxJlbuPYEGAdA+7JpwwmjyzipgtH8lxJui0Jy4pA3VXsxXAhdtgbzwcYxbkTabSYkQK2BYRnzvIjWwNgvwZDaCPGhNJvRvJ7n/9mNlzsquEYDI3gouFm4CsETYBwA7UAglaLLA+MceH1g/tZRSJJzmjRSVEfMtHgS3LNVM4DRguw2DSig9oGxgz3tK4v2gREHPVpkE5L67+BvY24kAC1t9J+yCtHTosjxYMSbW74KT4DhBIvakLYkaZF3XxQSXz0n0lKz5YFx9hN0qrmgACNFXYt32PkIRnKv2wQYGRoNjAMaoj1Flaq/RX47wXPV6OiR5hAqH0E2lpggy7JrNBWin9MdT2UMZ0IjPFCB9B24TwPjrgldCZasqc5qYMiOira0RXhDUoxUISLHip3dZ0TbhRYkx31gtBCqgSFoDEPXI79Df8j17UeHWOvTt9epfWNhKTYWltrXACNEfnMukcsM4WlgOMEyUGgHAlEDQ5WJ17lZljcKyQkwHSUQA/6dWAzNFgOn4eZEXSEY5oFxmwQjy6rTqO349h/5Zp3hfQfOclQLKfX/JW7w3LihciFLPPAS2R3DsMOEpE0YBdAterHxgXHfV8rm0Oig0Bf6r2N2JM2fsXKBcWChs5u220xIAFCr0MDYIV9t2FdieF+sBoY8kxCPEjC4p0tf8f+OIVbrvmBtk2EeGJd8Fp4A4wRonXg5dxixyMTrlgGsBIuAcMxqYBA9Zty4CLPCTuHPiLYTUT4s0E4RsXi3ItuUQCuE6GmoKdpw1yuMGxj59rRo6A7HaM8HxgFYcuKl+vhioU1wrEldJCZIqogMttOoHUTI7OaAL4pZUjAn4YIhQgVDHxiXb/FiIpyK1Kzp0CJd5tngBY/W+HuARhi0iqcv6gJ/QMbJrXPtbYgSngDjIpBMSFRe9jGwIbnBhJSW5ENpdV34b7f6wIST/zmlgYkyIcX+XVlFrExIbu+7WLjoiP32daKQCE68JI0AlYnd5e/QrSAJjP3aNEKrxhnOM6MDl+8vjg3QO/FGX3NfFFL9f10wJ6QkqbPbsvAU76p3XRB2nDHTwDiwUxdDO45MSJo5IhaJ9kR3CdHxnBBpRI7SNNHAxGKr5a4hww3PidcDAHqHX7LN0Z0+MG5Akk9STeBMeWDsYEivLUn9X1vbMmg/FoiDOdBwF+/GTLxKxEIQF+vES99exIlXirpnVNlFU5bt8MKoPQiHtTBqwcxYhJv4kaA+FyWRyYTkbg3MG1f35m7HCRNSkwYp5nyIzANjo8hpRNtN4x2I3gzFIsxb+EkCJA2MFP0HaYPntvcTS4iWN3gzwzsJT4BxAFZMSG5DaBF2gyZGkiSVAOO6nB31kDT/NcOz/+iK0zvl8bVFyGxK6hYWYY/cjqXqHA3aSNrIidcF4xwAWumkw493H5hg9xo7nkdpYFT1aZx43fEOnYDYowTcvyB5AowDsHaUgLvAuhjbCUkCknwKAcblYdTaNvu2IXvyW1k0aZ14rZpGaMP73T8FGo8Ft5iQstOTAURvhmJiQhKqgaEn5oVRO4t4SBzoCTCcsEM4DZCikFz29bkpE2+CJnGTa6OQwn0WabRvm1yc2y3ftraUIHWLUvAT1Y6dsLM5IyHADeMc0H/+2AjiYjUwZBOSvhOvsryZACe6ey7oLv6bFQZZFvq8cZFFO9YM/B1Aq4rjPazMWU2fpPj/2EKS1BMYkwYmBk+gFCQGtTtOl18r6wM56sIODYyYMtTtxciE5JYoJD02YsGfcB8YkzZCI5qsEaBoQyC/Z3d1sQAjGLxn8zkJT4DhhB0vMp6ceK3uwjJTrKcgSpDUizXLmhyLPDC0ApZl3jQESPSSfFZ9YOjqx4Md3UiYdYsPTAiuCKMWSUuSyM6iqjLB/4Y0AirhxoQZltOuaeASi6IuhPrAiCNlGzwBhhMs87KVKCS3QdT38fGYvpZpBP09Ihy5NhNvqE3NxGvGwzldm1lqI3yNUM6RhU+kqcHOKCRDJ17bmmWCvgkpvjUwAP3p1zx5YETDrYECdiAOliNPgHECtLZE3kR2TiKsgYktGwCi7ecsu2Und9YkrZUE/YPXQov1i5f1QJ9WDdnb02lfiUS358jXIFaJ7NyyYIWz0WquHxtRSMaa54gGhsSLCX2IHTtu08hZwczxgwzvx8OGOr5msTiFpTwwrhAVIhCVFl/EPCBJkmpCYdIqxGTi1/5t4oAoSUjVZBs2bYPQsaRJN9GiCYmKF4G0NhaWCqSmhhGfblmw9LiI90y8kqQ3P6qFfSBijiRl6TVrQxTc4hOlD3r+OjTNMrzvfvHFAQHmmWeegSRJGD9+fPhaVVUVxo4di0aNGiEzMxOjRo3C/v37VfV27tyJs88+G+np6WjSpAnuvvtu1NXV4VgGZyJeRxH5fq06gVp/sAStBsalJqRQW8rF0GgeVO8+2TiVEO13QqLgloWZFkfKa2yjbTRsXKKAUUTiaBLZxcKEJJgerbMoSUNtGoUkid0EUp29JKw1NggXOOLAJ9NWAea3337Da6+9hq5du6qu33HHHfj222/x2WefYd68edi7dy8uuuii8H2/34+zzz4bNTU1WLx4MWbMmIF3330XEydOtJNd22BlYLlsvAg7C0mIBgYaDQxTHpjY7lyl8P8Zg2cB1U70pGetqQuwE2aE2yY7PcSFCUlnsMR9GDUkcxO7prmo78isDZEmJJeMBz14TryCUFZWhiuuuAJvvPEGGjaM2PGLi4vx1ltvYcqUKRg2bBh69eqFd955B4sXL8avv/4KAJg1axbWr1+P999/H927d8dZZ52Fxx9/HNOnT0dNjX07MbsQD5EYRjjhuMjpo6HJy+p3IsaEpOaDJbWJo9NQ/cNqNTA0PLDusCUp2hRJIlHtgAADxMkkaNDFrjEZ6LAR94nsdExIks7v6PomGhjBRvh401xaQSAgR2tzXfb8tgkwY8eOxdlnn43hw4erri9fvhy1tbWq6x06dEDLli2xZMkSAMCSJUvQpUsX5OVF0qmPGDECJSUlWLduHbG96upqlJSUqP65BZY0MC4YMAPbNo66ZlkDI2BakSSJ29wSm52r9m9zJlg3fEEBRkuDpIHxsxEmtGNaxnX6Qz0YaGBc8P0ZIRbciT3jSu/MHYn4O1QnVrCY/9F2iOwbGe6PRLKejIOAjz/+GCtWrMBvv/0Wda+wsBDJycnIyclRXc/Ly0NhYWG4jFJ4Cd0P3SPh6aefxmOPPSaAextgYRC4YfokZcW0TlMADah5YzrM0cGeJZndjHaGRpO3eVsSYdcUXa7G74wGJh5gGEbtEpOB/lhxqH2FpkSsBkaiDqMmwSyYThupaBVu2FA6BVl2fySScHly165duP322/HBBx8gNTVVNHld3H///SguLg7/27Vrl2Ntm8GaBkYYG0IQCaPmZ6x7QY4Q8SEhQa2hcOtRAiHQOvGq67C1QTIhkbQITpiQ9CNM3AXDBdIl31/EiVd73RkGVWNXIN2gBsb4DDhDh3eHc0K7xqRIgCyLHQ8yotcutz29cAFm+fLlOHDgAHr27InExEQkJiZi3rx5eOGFF5CYmIi8vDzU1NSgqKhIVW///v1o2rQpAKBp06ZRUUmhv0NltEhJSUFWVpbqn51wal52gxpeqznQXmNBp2ZZ+OLm/sKceNUhle504tXLnaOfByYCZh8YEJx4CeXiQbBwCkZ97BYTkq4Tr0PtKwU5oV2iY0Mi5YEhXaCKChLIr1vGgxOQZfnvp4E57bTT8Mcff2DVqlXhf71798YVV1wR/p2UlIQ5c+aE62zatAk7d+5Ev379AAD9+vXDH3/8gQMHDoTLzJ49G1lZWejUqZNolm1HvDvxkjQHvN9xZkpivVre+kSgDaNmikKy3Do7tJOfrgCjuM4zYUZNOjY8LJ0PTHwgLkxIIQ2MdrV3yoTEuVEwp6uXoI6uDVMnXklsF8VZ/kdLkGWSxi82vOhBuA9MgwYNcNJJJ6muZWRkoFGjRuHro0ePxoQJE5Cbm4usrCzceuut6NevH/r2DaaXP+OMM9CpUydcddVVmDx5MgoLC/HQQw9h7NixSElJEc0yF1jeY7ybkCTCb27NkEUBSE1LUk1gTFFIDvZruK9Uu0q6+AhmPgk+BSQSwzo0wc8bDxDu/P1grIFxkBED6LHolEaANXSZnm60z1ZUGU2LpPnIrA1RcLsGRiR3MmTXa2pjIk9OnToV55xzDkaNGoXBgwejadOm+OKLL8L3fT4fvvvuO/h8PvTr1w9XXnklrr76akyaNCkW7BLB8l6tDAI3fC7KXWh4MrAmv4jxgdHsrphOo461D4xBOeWEzWdCMg99vKBHcya60e3YIHzFCkYaGJc8hN6JzE5xJ7FKDbR0YX6EiqEPjAkvok3wbjepiATJidcNLg1K2BKFpMXcuXNVf6empmL69OmYPn26bp3jjz8eP/zwg82cOQPas5CIcMF4IWtgOGmFNTDWH0yCWqXLJMA4GYVU35TWj4CGXTFOvIRyCDpTr9pVxNbAMQijceNmp03AOSFR2Udm31m7JpnYcqCMii4P/6ypE0R2UZ2fby5PTkyIu+SRMtwvsP2NLHrxCZEL7UNnd8RFPDtvgbuvkso6EWQABCdSZf/4HDjfxwro7fqR3zwamOhdejQNSbL/HJ14CTk14tJtPjBR1x0SxFmmANYlz6y80Tgy40V0GHUdSV1EgRQHEshY2igT8MyPGzFv80GhNEXDE2AcgFuE2OY5aVySA8mkwbs4lVbX1tfnqq7mS9KEUTMQdXJdCmutNH4EVLtHLideLQ0ST5Il7UI8yCZ5WXT+coZOvC57zqiw1hhoYERCgkQ+xNbA50bSKWfUhii0PS6Tq15yojNLrWiBdtyHK9X0XfY9eAKMA7DkAyPS3izxDXDSZMJtQgqFYQv40CTN9oppko3Bl6hNUKfHgdqvh70NmvTfkmQtosItQrkRqDVeBvdicdozCxzjjqEhlqhLSQI5jFoV9aRf3/QwR5P6rEj0Sbjs5ALjNhUNdmmeDQC4qKc1nzMPZDjiA+OBH26YPn1S9GRidVIQkwdGvcCzLMiOamAIPjC0EOHEq9euWxxU7QLt4xn1g1vMYCE+ooQDh/hT9pFo2ZWYyI7ysZx+P6ym1//e3B+Hy6vx2/ajNnIVRDCRnb1tuONriMDTwDgAK3lgxH6gEtcAT1LYbyMaFE4OBD5OgkaLEU95YLQ5bJSQOIWyUF06E5ITPjDiaL12VS/29gUUdIsCRo8Np/izN4zapIw2jFrBTJKJ31usBdDkxAQ0y05z3cJ/rMATYByA3XlgWOjzfEgpSQoBJqyB4fskSf4gvAj6wCiEAqajBJybUsIneCuaTPIlUIYis2pgon0KSBoGbd+xwul1oXlOGnMd2r6LhyikEBvRqd3dp4FhnY+Ip1FL5N9aJFM4xwo1w0P0+dZxBpc9uifA/I3A+yGTJgmr41iEAJEgqTVKbGHU9uLaAa2i21TtHBMM3odaU8MKulwhkv0aGIG9bKccYUQ61jv4EHT9pZzSwNhFV9I7C0lhtjbgJdFMAwN3vEMeFvq1aYQHRnYQz8wxBE+A4QSLWWhfcRV3O6I/PZ4PSa2BscZRWBthiUqIlpofptOobZzT+rVphMtPbhndpuI3bVQCs5ZEoveTiCcfGB5hiNb8Fh+ZePXE0Ni2b52uNQ1MIsVLFmvyclb7+LfW9lDAE2BcDrHqT74PIlnlAyOIFyEmJI0PDIsAY+PEIEMmPp+SvaAJyRysXEoAtLm2SDSCzoiMxE1oktoQBR5aPHl3tHBdFFKMzqZhaofBhiRBoiiu9YEh/z6peVYUn3YIHDzkeOcb5v2LzePBbQKVJ8Bwwjm1pNh2eNhWagvC9TnZilS3/lwSyAdNOgmW03CVYyY5kc6hmtkHRqLPxBtXGhg7TUgGtF2TyE7vumNRSPRlmXxg9DQwDDRCaNM4k3D44N/HZyUeUhuIhifAcMKpE6bF7mL5iKUoBJjQY7vhMMeo06hZZllB/Urq02AfRV/XamBomGAPo5YIu/RoGpIk2b44x3rZoO86IxNSrJ8iCF0nXofYY3FmZsoDo1PeyISkN/fUBZxJ1c8zj/K+J/YNjM3ftDs+hzA8AeZvBi4fmERf+HdokuAeyGEByDokSVItMO7NxFvv90PtxBuZ0HnOQvIHzDUwgLUIG8fzb/AkYKQsZ9THLlHAQN8V2xkGbXvfFHRpW67VOafIbYsuC+KYdUfgCTAuh1AHNE6KShNSaJKwKL8IeTCtBoZlkhW1s9ZX7Uf/VpalduLlWEFpTpCVEF95YLh8YCgrGfrAuGT1C2tgorIsO9u+HdAROxRt6zeuvFfnJ2tgaFinfT5uXxauWhw+MJztuIU+KzwBxoMplInsanUmCVqEJmAxO0dJNYGxLsgTTm8vgIdo6CnQlUJTMq0TL4cGJqp9kg+M5B7zCA14OKXXwNAtkLGErqDsVPuKhswsRKx5YFjPQoLOPd2DFik6SaSgSqLEbUKyxMmxD0+AcTloDj9lccfh+ZCUckFIgOH9IEOsiolCUn/grJOQGDOWOe3Qb2XZoAnJHh8Y7S6d6MQrORCFFOs8MNS7an24JQpJd5w5xJ5thzlK5k68RpHSSrZq6vQ0MOa8075nmqgmkd6RLAL039CH1xNg3A6RzsLaBZ+lXgghE9IJnKeyygJ9YBIk/rOQbIVMnniUi0CST39aVb5yHh+YqKMEdFqKJw0Mz4ihfT6jRcIl8kv4HcYqE69KIBdpGoT5wqt9P3rN62lgaPi1X1DlND1xfP92wi0ayRDcMuXHHZySdmk0MCywOv5q63c51wxohZuGnIBPxvRlqh/KuiniQ5AsmpCEaIEoJqZIGHXkWhKl+oNHyIjygSFpYCA+CmnqJd1M2+UFlw+MANpumbBjrYFRnaRuUpZNIxytMdS2Z2jiU/zW84GhAa321unRwNKeU5GxboJ3GrXLIVoDw1kz/Ku2PgopJdGH+85iT3MtVAOTACQo5ixmE5JNs78MWccOrvCBSTSKQiLXoQXNYY6QLNr9CVVz0pL56dkAEY6ZbjEhhUDKc+IE7GqFxrdH+wr0HPd1o5Ao+GA6R40nIo63A3nSKNgId30NngaGG069SNEytdUBrjdJ0CIswNig/YhJ0jGKJkM7SKUwmmwYRq2sy8gOYUdLPMwR4hdn0pk2osDnAkPv16AHt0UhRV13lo1gm6Y+IAx5YPR8YJSmYcp3oJcHhkbIo/eBodC4UlGigztGn3vhCTAuB8lDnxdBkwtHPUUdbY4RK7xYpqGZ/FjOQgrVtwskc5Gy75IS6U6jZnfipR8z8eQDw6NpaNU4naqc0bBxSxdFfGD4vr8r+0afzWWVFwA4vVNe1H0mExIk02fSvgO9gx4taWAY3rOd5kwrbcmyEz4w9tJnhSfAcMIxa+MxZtYMCLQhSZL6HBVWDYyo4wy0kGU17dCJuUonwySfpNsHqmficOLTLiBEDYwkWYpCouNF3GzHQ+nWYe3oaBs68bpkxrbIxm2n0fUFK0j5jNKSfISSOtDTwCgemFYLppfigU7T6VYfGPoW7dSAuhWeAONyCHXi1V8zzaoJg0gTUoKk1jaw+8BY54GGRlJ9eJTSyTCJMmSKOZU4orVkZCdeFy3OFGBltWOzLKQn0y2khiYkl/jAhLjgVciKfNdmpFo0TKOnBQoTksE7UJar09XAiDQhcc6hnP3PHIXE1Ur8whNgOOHUQBFpQgJiH1UR2iXoTTYs0E5+zFFIljkgQ4Z64gnxpdTAJCTQ7a14Fh46DYw1nyGammJ9AdiosTi/G/WxS+QXy7ArURuJanMTAeaGQa0j9SVzzYGRE6+Sg9Qk/uWM5Ttz1ITEUNaJICS3HYzpCTCccEpZR2qHZYejBL8dVtygDX1kDdOTLNNK0JiQ7M6Z8POdQ6JpUPRq2ITk12pGaHxgKJlT0NQuCHok3OKgaheojxIwuOea06gtvivLGhiG6j1bNjQmpeHFbOE1PkoAeO2qXjjhuAy8dHlPnULG9AGxTryiIEmMPjD2seJaeAKMy2GWZtsJSLC2u1EikolXwvUDWxuWNYWk3mnbvSA3SKUTurS7/5ATrzZKQo9bdSI7ESYkggbGhjwwUW0IJG/nrtdYA+MSAab+vwdKq6nrNM1KDf8WmuRRmRNG8fuhszvitmFtcUH35sbVVb8l4sJrFIWkfSUjOjfFnDuH4qTm2arr53bLJ5Yngc2Jl31M8A4jJh+YoPOdvXDH5xCGJ8C4HRRi9Rmd8qh2EJLEF4UEABnJYlIGqRZniwuodmJjNyFZ/xpp+jORYEKircujVaLJAyNJ4gU+N+XREnW8hksUMGFo0+Ub8d45Pyv8W6Qvj54J6bSOeZhwxonm37XitiSBOMepE9nxcAm8eFmPKB714BZBNQqeBsYQngDjchA1MJpRnZ2ehPWTRlDR403ClJ7CEFlgiMjzWJ0ytD4wzA6vNs1ZWh+YsAaGw++HfWKV0KeVsQo/WMriWUhO58NgJCZDZkhkpw+nFrabhpxgeN8qG048B62goQqDlsz9/KI0MDph1Lrt0YxVFg0MfVEu+txtyXzzOwvcJud5AozLQYpCis6LEMyMawYrYy89SbwGxqo9mWbyEwm9aB5y2cidsBOvX2tCssMHBphw+om4oHu+KQ3R9nx78+qwEWcaFga0nYpCGtyuseF9q1zYFYVkZOrR50VRX+fJVFoeA7I0TSZTSOqxDm7Qg3eYozE8AcblIJ4TYoEeny+BJFADY40XJcpr/JbMFnZNWlpzW8iJt5bShKR0wuUxs6Ul+zBmcGRHT1wkJBsy8dqY5p6Vkgz63ajRGTqOmRbMrC6WnXgtVaczwzCEIit/s/rAqPkybzM5McE0yaXdGyFezQiz/tWdcpht8AQYlyMzJVrzEXU6K220hcQv/PQoMDdL0EAVNWSVlixzJ2/q0DSLfXIgXdP0fadmWXjqwi6qsqRMvHr0zOjT8qjOo0EqJ7nOv8MIkgTcc+aJ1BM0Sxh1Va2+AOOc/GLckFU2xPrAkE04vE0wm5A4NDJplDmBqGAqbApsisUHxgFttNumDE+AcTn6ndBIKD2ej0uGjLtGtMeNQ9rgm3EDLLWv/Mis7m5lmc9x9PqBrXHnGe3FJLLT/P3D7YPQspE6hX2ijgmJBjwmJOV/AfLiGBRm+TuATvjiJk/ELUPbYvMTZ6mcU/XAklY9w0C76JQJyZRXqxoU20xIClMpddi60gdGMs3EK+KoB6bswHaA1weGRYDhbyZu4Z1G7WJc1KO5Tgis8d96sLJgpScn4v6zOnLXD8FK3hYtArLMJcDcNeJEpCb5ONSz9E4wRCfeqPAg8zbZw6gl1X+1vOjx6HaEnifJlyDcrHN8oww8dl5nvL1oG3YcrgAAvHR5D/gkCakOLXzm8ou5r4hT0GuTRROspGVmQjLLA6PljUTPNCsz4/lNrOB9T2xh1JyNMMBtvkKeAMMJR3xHbRgrsR6AKidei7T8Afee/6E6yyWsgdGakMx7QIgGhkIItgMi29BzHNUD66j4V/9W2F9ShZfn/gkAGHlSMyQkSCivrmOkZA/4NKf2QI8uj7IqGEZt7OdnqIGhHGVpgtJAOA2XyQuug2dCcjF0P07troNykFvxgREFWR2GZImWPxDgEiRT6g+g4/UvMbumRVLYiZcuh4fISC2AvABIkmRJk8GbDVoPZqYaSee3HmSZPYxapHaQFbHeWLBAOT5VZ5HROvFqfpt9wtE+MOx9lWaSiFNQ0JpBHfvfbzB1gL3tuG2UegIMJ5yYb3TDX+1v2jZYOWlZi7oAu/7li1v6hz9yIT4wOkSUlxPrvWijonQo6DObkEIaGJN2JMna8zfNTsOH159CxwwF3vxXb1zZt6UBLSVZc7pWtQ8ixwhdeyb3nWFDv30dBq0K23o+MMoHZvFD0uMh3UQDw+IA6+S7YAqjdqcy2lZ4AgwnnLE36l3X7kgo6YX/L4ZQmZCsMROQZebwR+Up0E51RSiMmhZWhLywDwxFPavP37+tOneJpZB2k/o0Pj1KnNYhj8snw6hdO2HqAxPr71YB5bYhoHLKpySgeRjSNsTofUu6f+jDzJfJ7umc3weGHk6cJOA2xKdh8G8COybPWJ8mKlJNX+dnd+JVtcmp3TC7BqgnkkSdg2joDnNklmCiONDzgbH9LCTG8qSkjax0r+p7PLq0yMZ53fJxuLyGkQNCW67RwLhzabJyGjygL7jS54Ghg5kTr6ijJ0TDTYIr4D5+PAHGxaBZHIN/06tgYj0AReYqCMjWXHhjrYGh0pJwyi+mC6JFfyh7xpH+26Rd0Jo0SMHFvQuCdShbDZGLrQrexAfIRQuHsp9USRepw6gVvyXzfjcUYLTaaJ1yplFINoP3/bEe5uimceIEPBOSB0chMpFdXUC2JBCxCwdkTQYJfgVfSXoaGIo2eR1tzXxgnJBmteRbafLjqMvq+EKE7hvQVUKpVXJyMv94TF9L9WkETvJ1501cytek9EtnCSZQUiaf9xaBVrHD88hm2kaWrZBVbdilfQro22JoypnAWHdJSJ4A42JQ5+9gGFOxHn4Cg5AQCPDlgQm3r9Mb/QUkD1SGTDP7wFhI9hdxPjWvZ0kDw1Hn05v6Gd43FGAUz2M0iXJFiNTTI/piUNKzP1FarL9cBWSyDwzP6eY0gplhHhhKembWLbu1b8oxO3pgazTKSKasRw/ZgcMc3QZPgHE19PbOvLtyKeYqRpF5W4JRSGz0aAQoXaGB6ANDLqtMWmfFhETjVnBcg5QITc1/9SBJ9p/zox2nZuPWyCGbWgNDKejQgpaG1b6041048amrHc5pTUjKd2SOKA2M8nfUPbFzJpEWj5AskX+LbMuJnFixXj+08AQYF4M1j4VdELk7EZnjxG9RA2Mn/ArdesiJN2SHb54TyqGiJ9jQ7T5DOD43YpohFicJXnplKUGq26dVLj9BGKvAaRcA7mRqHPd4yunBTHvBQ9+JRHZKbSHvwm5uQqLXwOgh1hqYqPaoS7pMYnAZPAHGxRA9dIOOm7H9IETOE/6ATB25QgJrTxCjkHTKtmqUgVaN0tGleXZ48vzspn4466SmmHHdybr0AK0JyZwvtdZBn1cV35L4kZCdnoTJ/+iqaEPbpgE/YAijNjIhMYZbi4LVtnTcpCL0da47cYBfdJuR3wGODYlKGIXOWUiKMiIS2TmZKNB8D0HPC5MG5m94GJIXheRi0O/+7PkgrNTRhUAfGH9Ahi+B0YQE8x2jiOdN9CVgzp1D6zUdQYKd87PxypW9Iu1Q0KFSyxMFK+MFX6KlrdskuW5WKv+UQqsCN1rsLb074qGCdLAqDjp1aCQvlP2qlweGFj4KR2vV+GXZZnN2o2sT2TGUdaky2lZ4GhhOxKPHNy81oSYkwT4wzO1bSKRH3FkZkPAlSJZzrZjtzAG1loYpg6zNM7GWvFlzhuNMs2vXA0kbZQW0mwOa92QEXhOSEX9OaGd4mtAKMMxHCSh/074fTbkzOuVR1RMGbh8Y+sJ6J7C7zW9FJDwBxsWwwwcm1mPZigChhWUfmBh3Bl2kEFsZWiHLah4YI264aknGCy6XDwyjBtMko70xDYu9aSboxtr0q4TeWUi0SFQKMCCHUSsf1/gwRzoox8wdw9vjH71aqO4zPYVFicC++Zr8FCIdxN0mDHkCDCeceI/ifWCkmI/AgEWnPyWCPjCsJqQIxPSEFTMMRRkaCxJh0Tb1gYG1wxxpzG/RPjDG7VEqYAzpiM4uTNtFVpu1w4lXpN+HngBV6w8QrxtBay5L9kUvQ0Y+MBrGjP5U0FDT1vaNk2HUwfboGmT1gSFuYOhJxB08AYYTjpiQdEYvi3NkVF0L/IiASAHCz5GJVx01wWhCIpQXHcmjBY2QoXWKDF4z18o4LctaMSGZPQ/pHq3WwklTkx5YTuOONZSvqaqWXYBJVEkTwLRLu0eVUQusmns2CHNsieyswS6fxXh0a7AKT4D5G8EN6j+ROx2/1Uy8etdj3FHKR6IRYFR+H0z2dRauNHUprrNOdiLywIh+dyIOhKSBqQnJoIFJ53dWhObbD+Vrqqr1M9f3aQ5U7dA0C7/cNVS/vGEYNfv7kWBNCHEyEILZT0/wJsvt8AQYF4PeB8Yeid5uiDAhWXKB0TOD6JVnKEvVPkVtXtMEzYLv9G7K2BIgUb9LI6GOR5gLlbMiDFv1M+DJYhvC1f1aYdF9w9Agxb6gUr0opOo6axqYsNN5VHuRK9F9q/+Oace6tpz9JiTyb6aKJtAbv27TmoiEJ8C4GLpZJTknO8mAphHs+ratfliJCRIzc24KNaTzb2HUwFDStmpC0jdvara6LDA0IdGRjVU0stVmrUYxCWGCA3waGHNzILXGjbLNaB8Y9X2WecHqvEUTeRVpix66NAWOCzdtgAFPgHE1WHeQfze8fnVvWzQwLOXt7nuaBZnkOGueB0YiCiEn5jVg5lFN1+gevx8CbYI6njDq8FlIFgaT3RoYGqdpx2DRhKQ8WiM8Xk3MgrRRaPo0jO/broFx4EV5TrweXAXRA493123XB2D1m+51fEPmKKSURKX9XU+LQE/Pym5Mrx3lQk4TVaNWT0uGtPXqhXDjkDYY0VlMjgyWnpEk9cnGpPuR3wY+EZTlRMNqU+ZOvO5Zhqw68VJpYDQ3eM5Z0rseFIjEf7fU9ZlM/tbfu8jPwD2jMAhPgHExaH00mBYKDj7cZHbRgkV+ufyUlujULCv8N7MGhqTJcIEGhuT3YVZNksiLguXJ2VgFYwhajybDJjgeQMQ7tN+J1xp9kVD6WlTVcWhgCD4wWmi/NU3gkqI+XZtGB0KKhpkjrV3vUpZlspbYdWKHOHgCDCdGD2xtexvid5CxP41aCRHPR7vojerZAk9d2CXmEUZKUCWpYwyjVhA3vK+njZPq/ycCrH1tlFiZdgGIlQ+M7SYkDpp2ZeJVkuXLxKuOQgr+V/2E0c65dIKOLkzfj5u3aXTQewKhGhgXzZ+AJ8Bw47xu+ba3QatePYYFbFNYmaP1J0UGGvzNC8wDQ+cfoqqjM/XbqYGx4oeg5JY2CokWoRpO+lNpYWpCOoa+cW0eGBrodQ9tFFKUBkZT0M9wLAnPq9DWoZ23mNqS9fzdjl0IF2Cefvpp9OnTBw0aNECTJk1wwQUXYNOmTaoyVVVVGDt2LBo1aoTMzEyMGjUK+/fvV5XZuXMnzj77bKSnp6NJkya4++67UVdXJ5pdS2ialWpvA4JHXnDX7Z7hLIIT7UQwemBr5GfTvRfW9vW6Li8rhZGSMT0lqJx4CX/ROL2SNTN0WjpeHxvjstazk8ZqeFvVwIhM9243rOoqfJqjBGjAm+uI1I4kRY9NK6faa0Gj+bJDO6avgXHe9O0UhAsw8+bNw9ixY/Hrr79i9uzZqK2txRlnnIHy8vJwmTvuuAPffvstPvvsM8ybNw979+7FRRddFL7v9/tx9tlno6amBosXL8aMGTPw7rvvYuLEiaLZtQSec0BYQJ9JND5Ho4iPSDsRPHxOJyy6bxhVW3rtj+zSDADQtkmmafuSJOHda0/Gya1y8emN/cwZpoCIRHZm1fSEWd5XElqTjMaiqRKfOoxasAZGMm/flAZ/VQA0GhgKTZzmb7tmJ6vTXiLhWc00KXrvldsHRvN3gEUDwyNAxdQHhu4aDdy20ggXYGbOnIlrrrkGnTt3Rrdu3fDuu+9i586dWL58OQCguLgYb731FqZMmYJhw4ahV69eeOedd7B48WL8+uuvAIBZs2Zh/fr1eP/999G9e3ecddZZePzxxzF9+nTU1NSIZpkbIqV2EkQPdLcNPhEgHsBnMWKhdeMM/P7QcPx4+yAqOh2bZeHTm/rh5Na5VOXN2leVYdSGSJr/6retM7ExmKCUSAz5NRhM1GbvxWgRV96h1cA4cRpzpF2rGhgT+hTXzZ6WJDjQQvl8Sr+z16/qhcaZyXh/9CnUtLSnUdO1r/jNISSb1T+n3iXAahqBYFvGIoPjRwkQaMSTxs8ItvvAFBcXAwByc4OT+/Lly1FbW4vhw4eHy3To0AEtW7bEkiVLAABLlixBly5dkJcXCeccMWIESkpKsG7dOmI71dXVKCkpUf2zH3ZrYHSuU9p9aeo6jX5tGoV/87CSluRT/W3XGtU4MwVJhEPmREKcDwzpmtmOnlwmgdOEZDkRmwQ8dHYng/boFgC+idn6R2Hdd4hTgjGA9tsQfdAlAJzRuSl+e3A4BrZrTF1HlQdGp0x0FJL67xsGtUZGsg+3DG1L1aa2f7X0J57TCVMv6Yb/XH8yMy23g3aj8vGYvua0XPbots7QgUAA48ePx4ABA3DSSScBAAoLC5GcnIycnBxV2by8PBQWFobLKIWX0P3QPRKefvppZGdnh/8VFBQIfppouE0DM3lUV8McHpIkLsKEFy9d3iP8m3UiaNskE+nJagFm7LDgBHZ+d3anahbfEL3rVj5omqpUAgzB30W1M9cZp6T1TJknhwWhKBojTYnZk7RslI7PbiKb4SSd31qoM646N9bt3tGK+G6taGCU0I4n1n5WRSFRfmvaTLoPnt0Jax4dgYLcdKo2tSYcLf20ZB8u7NECjTL4/NmY2gdLJl76vtX7zsmmYvW1Fg3TqPvSTbBVgBk7dizWrl2Ljz/+2M5mAAD3338/iouLw/927dple5t2+8DQIjQUL+5TgNeu6m1cNobyy2kdmqBRZmSC4OFF2+NXntISc+4cgikXd2emFevNhN7zq31g2OjQJ7Ija1qSOQUYUbt7Gq2jUVMqUwfl9ynim7A7fJvHaVr79FbOW1Likj7BzSGryTSERAonXu1VkoBIMjnShlvTmOTiDXopJUwsWkaXCLTc1UO2nf41btw4fPfdd5g/fz5atGgRvt60aVPU1NSgqKhIpYXZv38/mjZtGi6zbNkyFb1QlFKojBYpKSlISbFHetaD3fKL3m6AdzcW66Fnh9OuJEk44ThzZ1sR/MQikR1dHhg+nwLS8yT7ErjGV2gxUfFikttDdY9a8OI3ISUnJqDG4PBBK0eD2q3Z5KGu/VZ8PjE8dmyWhRUPn47stCSu+iQfGLP3blVApo3cFhWBF1XHYn0ayLKOltiEn1DdeIRwDYwsyxg3bhy+/PJL/Pzzz2jdurXqfq9evZCUlIQ5c+aEr23atAk7d+5Ev35B9XG/fv3wxx9/4MCBA+Eys2fPRlZWFjp10reTOw27NDC3DWuLC7rn44q+LanKMzmFRdVlYMwy6HZBRhDb47Heh5HbUT4jXSbeaIpmC6oE8rtP0fgYGdVXIrSrtt5zOjtolWDEWjuISed1Zq5DC4kwk6YmJeBKym9Yi9ev6mWRo2iI0sAAQG5GsmnklB4SKZx4tXOa1oSkBxoNnlFBJzQM1NGlBFOXEVjCqO3Iwh0LCNfAjB07Fh9++CG+/vprNGjQIOyzkp2djbS0NGRnZ2P06NGYMGECcnNzkZWVhVtvvRX9+vVD375BJ6IzzjgDnTp1wlVXXYXJkyejsLAQDz30EMaOHeu4lsUIdkmtF/RojjacWgUzkPwSzB5DVDSHGA0MZ9uka6waGOLuhv+hhDnxqmhKURdZbOPJvgSuFZ1mQhQXdaVfyKi+WV+KDqPu0yoXl/Zpifd/3clEq/8JjdAsO01Nn3pl1gevwAGIFenVfERr7kjticyzo6d9pAVPXUdMLwyJ7OJRWCFBuAbmlVdeQXFxMYYOHYpmzZqF/33yySfhMlOnTsU555yDUaNGYfDgwWjatCm++OKL8H2fz4fvvvsOPp8P/fr1w5VXXomrr74akyZNEs2uJdgVpmn2sfJGIfFEq9DgFEpbeFRLHG2L7PNYf8M0+h/WTLyRa5HfJNNI0KE7GrQ+MNomwxoYi51KU523DdrdPg/c6MSr/VREOfFaRSKXE69SAydAzxfDrpAMdo03DTlBXVZUe9prpHIxnxHZIVwDQ7PApKamYvr06Zg+fbpumeOPPx4//PCDSNaEw64oJFMBxgJtWmc2Frzxr97o+ugsDl7YIVJm1HX4Y2DMjolQ+Yg8zpt617T3iSYkG514rWpXwmVoGOKkzQsS6Vj6FXQvyIkSXO0Io+aBjyKMWgvqV0chpMZioaZt8b6zOuDVeX9ytSGDnMiO1LqXB8aDbT4w7M6ltOWiI09EDOSsVH1nPlrbNQ1ozF12QvQnr7egKkPF6QQDkgYmco00TCWJ/O5TEhO4ohHCTrwGtWk+F5q2jcasURt6XSlCq0fiyYpTsBaswt8XN/d3sQZGbc4Bot97tA+MciJhb9PoNOrWjTPYCTLCIvthnNO1me4mQ99UTLpIWc7lsC0K6e8AuxZT00VL5EizedAmSFJY0GOJSiFBhjMmJBa2rGnD1GiWnYoeLXNwRqdILh/WMGoWvkhlUhLpnHi1COeBUQms6haMFvRQUd7EfZE29KFHW4Qm1fZoNMbypDnEigZG5PPx+OJYlb2U1YPOsZEr3946kI2W1b6wMMEkJyYgMyUR1XXRGelZhnEcyipEeAKMBdjnA8NW3pIPDFtTzEhQGHx5nDpFgez/w0pDLL9actcPaoPRA1urrtGdhcTRNiTiy09OTOB6TrPFUZLMTpuOlDODoQCjaETrz6NXT4QmlTSWhU4POsyfeuJxivbUDcaDBoZWeFT7wOhD7552fCq7kzU6i8Y8G31NXN/7dQaWLMvU5uSozYVOXbfDMyFZwHUDWpsX4oDpomVhZozy9mdUTbM3qN8WD1kH1gRGGhZ2taKickiRB5pLc+4cgn/1O151nzTOeBPZkcKotdRF2d2N+lw5PhqkJmFkl0jeKL32/fWrqJUNie2J7AjXVjx8Olo0pM+e6rN83oMYKDUwtIcopqfQaQaz08nmbEOhx+GVW4JkKROv368jwOjROEbMRSS4Y0THKe4ecSI+GdMXeVmR0O4mDVLQsVmWJbqmg8vSoqn9W59Wkk/Cya1y0aV5tindPq0aEq+rc5RohCdTqtEQ6sRLkXNEXT6CTs2ykJggYfI/ugrkJxqsJhWSKSYgAyccl4mhHZqYtker3mcVTiQE07VfN6A1Lj9FPzcKr9NyCNrxcXW/VqY8CtHAkHxghDqcR1/LzUg25EFrsrP5aC9qKKOQ6igFmAYpdEnzXr+qNzo1y8I71/RRXTcL02YBz/QrTGCQjTQw5HFITHFAIhCHQo1LhnR8ItGXgFPaNFLtWpc+cBr+0auFQS1zsO9U+Uee0Xo15eLu+PSmflSL2n9Gn0IU3Jo0SI38YVEDEzRG8a0K2rwaJH5YMHpga2x8/Ez0acWXTp0W/Ic5Rn6H+ixKeKUQ1AD1AZx6CB/Qp6NxC7U18dxOeOrCLrp0RGmlIvQi0BvGfgFOMCTaIp14eaBd59yigUlSRCHR9n2D1Ii3g5EGrmOzLPxw+yCcqhXWBWh/RSFoTuUbGzLYxyuNCSle4Y4RfQxBL78GC2wNo9ZUFqXWT03yoUvziADzn9En4+RWuXjlyp5C2+L57i/tU4Abh7SJus4sJmoqJFrc0tJMqnROvEr/gOBvpV0/pKaPSuZF2QEnNm1AaFTLZ8iExPeOQ89Aw5PxODJyFDY2IVmB7RoYAdtjQScJWIZyQ1TrDx7tYNZVWZzHFoSgHvsSrMyiVt8FS23SkDXSGNIKK8RycaiC8Zx4BSAxgc5ZkBZ2OfEChIErcMwqv6tB7Y7DoHbHoarWH74mwk+AdU1IkIBnRpHNPLQaCKfAu1MyMwWF1metRsTK+9BOdsSD9RRlzJo6Ma9BPV80bevD6KRkvecNLQhuPg5GhL+Ydp4yw+WntMSHS9myCNNA+U7qdPw5tFBpYHjajOKBg4hLYJfAHY/wNDACINq732xwWfKpZbAFh3ZHtDD7rLQ7Z1aJX6ZphAHx8AnTnYVEEB5UPjAEDYzi/0MY3P64+rrMbIY1Pokc2/ypl3QLO1/SmZD0yxjN7crn//KW/uHfjMOcGjLELZRcZDR9wWpBykyJCA12JeWrC9B1fgODXFM0UAnvBvdYafHxQu/ES4LRGKd12NVeEzlWnYSngREArSnBugmJrbw1k5J+bVYBhkyf/Dt4gZ1eLP0K7N610DrgRdcj/w4htPgYTdwzxw8Ka0FoEGWKrP8E9A7qM3oM5anrVsOojcoqF/A0RbLAkFOkm0/k5dPAqB+IVQOjfJciuubsLs3Q8/iGqmu1lBqYLJUPDHvbIp14nYSWT2Hn0gmhEnt4AowAJGl2nVYXOjvTPEf7wOiXpZ1cDNtTfCrRGhhWWvZHdhhdtxtkHxhzZpRlSNrAsMpZI1Ao66Um+iJ+KJT8KhFaHJN0/IJotW1UPj8GtIyT5ZHr0YbyMsOBYy8Mm49y4mWjodyYiVg4p1/RM+oarQYmI8XaUqV88qD/l1Ib6ewHb6U1nrdAe/J0PAo1nglJALSLhnUfGBMTkvZvhgZZ6taxmpBMvi7WhFHENgSWt/skaRFgbYeUUM5PNCGJnbZD7SoFGBV96sbYNE5aRPnAKH7rfVehUF5e7Z6e5oo2d4kW3Ceum3QdjQBzy9DIYYJOJL4LbZLMBCSVZo+jHaubJ1Vdix8/mwaRrS2zg13D1zQ94GbtoxE8AUYARJuQnNQAGPvAiHAWI/8O/h1bmV9XAxOjvQipVZrDFZXPQVp0QotD9C6UTIMHoXb1fGCMyLPyYbSuGh8lQL5uVQPz1jW9VX9fO6AVTmqehcfPP4mq/ty7hlpqPwTtIqR9KhoBRjWWHAhbot0kWeVFpA9MLMEjaJAejzQUYj0f88ATYARAa0KyClMNjJXdhLaukQmJUr0bAmkHq140re+CnDgLyU2QJAmTzu9sWEY5XkhjJxKFpO1/HWGDI/Ip1G6Sws+Cy1eBpowBYe34UC9c5Hp6icFoEcqGe/eIE3FJ7wJMPKcTvrt1EApy6bLktqI4TJDLB0bzXCEnbcN2FH2kfJd27dBpN0lWc9hEaWAsfPyWN6iQHNV4mB32Gs/wfGAEIMo5zrIPjKXqupBl0sen31htHeNXRjz1WLm4au+xkddpgh9u+4Z1OkQZQkqspvhN0sBEopDUdWgWd1qElJC6GhgD8qpwa86w8RAGtG2se8/ORHYAMPbUtkLokCAiwd/lJ7dEVmoiGqYn4+q3l5nSU75LVvPa+6NPwUe/7cTsdftRY6BlCeeBMSGflMA2RrTQphBgCfGPJdyijXcrPA2MADitgdGCNyoj2JZ+WRFRSErwnEKrhTNHCYhrgwV6zWaZhJAq/V58hLFIygMDSf85aR6/WXaq6m+fiQmJFrwamJNb5WL1I2egcWaKtnT4l96Bk4HwWUi0XDoPmjHZrUUOgMh8RDIhnd+9OZo3JGSlJkDtxEtVJYyB7Rpj+uU90TDDeOzSHiUgYu5QwtZv3Iy2hbZ5hugVhKM7tHvuWGeN5oWngRGAqER2Fuk5KnULNSER6Ov8NmtbFAxPQLaiRnbwHfVo2dDwvpkGJuwDE+XEq9zVGtBX3JtycTes3lWES09WT4ohFb/S7KBcm2g1PLxh1Ik+Cdkm2Vr1SFs1ITkBLe/tmmRGlXn+4m54de6fuPTkAu52lH2R5IATL60PjK5zOCW0WaiVYHeU5WCAs76Vpp6+qAva5zVA94IcPPH9Bg3deNS3RMPTwAiASGe3Cae3N09kF/U3ffvRByrq16XNkmnYnkZ1S9N285w0DGqnbwoQBbd9wnqvPTcjGcseOM2gnrEPTMhEEuW3Qvn1K9f30zrm4bHzTwovKBf1bA4AuHFw8KgG5beg1ODRCkhUphIapgm0lRoY5TOFNTAMdGON167qFXWtcWYKHjqnE9o2CUZF6cllRv2nNKepNDBcXJq/T3ofGIuaPZd97LwaDxYfwLQkH3od31DHYdf42suEkHc3whNgBECb+8LKxzLQxoVbhmyrCcns46KdhGRZxnvXnYx1j41gaj/ewDJOmmSl6t4zi0IKkDQwksHiQilsAMDz/+yGtY+NwEn1J5YrvwUe3xK6KKToQjT+J7o+MCbjdsLp7THQwLfGCSgf+fELTkKb46I1MFrwLJHKd6Y0jYt0nleCNg+MapPIMb9qs1AbRSWZwbKG3WJ95vZITryav1s1UjuSt1Vo+HLSrWVBthOeCUkAovLAWBiiPEnsaKuQ5iAjbU96MtvwIJqQOJx45fp6VpNXmcFtnvi8zqTKpyAJiYQ8dlGTOC8kSVKlnFd+C0oNHm1TrCakf/RqgQdHdkTDjGRyWQ2vWjqyDAw4wVg4ue20dgCAVvd9b86cTaioiZwpJiKfkh6UY1A5lnjFFzNNA62WlzWLsBZWtNaiwZS3yyY2Qzx8NXYA3lm0Dfee2UHXsdlds6QangAjAFZPJVaCzolRHH0jWjcPOUH/JgdohTOj01ZFItbyi3YiK6uu46QT+U0KN434wKjb5tHKm1VRLnq0DppGQoZpeUBXeNFCOf5kGVj6wGnYfqgCJ7fOpaofSxRV1IZ/U783ne/I+CwphQnJotBAA1otr3Jc8QgfknrwW8qBFMuNj6iZMfQE3Qty8H+X9gAAFCvGmJHp303wTEgCEH2UgFj62l21yAyyerw2zkwJH7BHCzO5I3oHTG5c13YvAed2ywcA9G1jfdHR60UqLYCAfYlWLV9WxSfA0B4lEM2z2qQUuWplfCkFmADxuhbKXqAT4Fl2sPoawCYNUlXCi5t9eY+U14R/028E2NtRamBUzdh2mCMdYauRnrTzHg8t5voW6p7RKc9a40ZMsFuUYw5PgBEA0VFIWmhDVmkTZFmBHWnEaUnqzWmyDDxzURdMvaQbXruqN7kQA9y2sSjn1cAofhuakDR2f65EcwyVaM0Dyl0/qwmJ5RnsPGPMbhytUAgwVh1aDe6p3oXiul2yHY8GhgdRPjAxXpbpheUInx9efwrOq9/AUdU0eETzb0G5uXHvd+MJMALAooH57KZ+zPS1AsyFPZqrQkapfWAQ/eHqDWSeCcPsm6Q9j8TIYTAjJREX9mhhGjJLBzIHTk1u0SYkv05Jejqk90bqz6ATL5mGqN2qSgNjUE7JHl0UEoMGRvnbtJp7VTCjerYI/6b9NHkiXZRCZ6YigaJdTry0fl+qMGrBpk/mMGr25jXt8Y20/m0bQ5IkIXnHiAoYHbIORNNzwxNgBEAbRm00wXZtkc1Mv1+bRqq/ExKCkRFc0C5OOsV4QsPNJjkWJ14n4LaNRVl1rXkhAtQ+MAQTEkmAgUStkeAV6OrUiWB0waqBUWcUpuctXjUw/5swGP1PiMwBtM/RVidSyai6cqz0a9MI/+zVAg+M7CD8m3zp8h5okJqIGdedDIDiIFiBYdSSBLR0QIutywttTiRIxHf1zbiB4fQF3DyYsGDFR8hJeE68AsDj7OaDH37QnVY7dlhbVNcF8Nr8v8LX1KGz6vZP75SH2ev3E2lpx6JIDYwZaHc6Ipx4Lz+lJT5cujMcQULkx3IrYlHOq4FRPAnRhETS0kvRJiU9KH3UWfqMNgqJ3QeGngdVHhilE28MtC0SApA59owtczNQVBkxIdE+/yPndkZaciL+2buFeeF6qLRhkoRn/9kNAPD+rzuNK1aVAMkZQALdnHZO13yMPKlZ0BxWWQTIxhpV1RlbRgX9dYAvelmLvHsZkGWkJfuwauLppgEYPvghQ0JA+d50XkAi6lDnwJLasVkWplzcHV+s2ENdJxtlKEdqmD+SEKXXr24W/D0NjABEqfQkoAEq0FPajC75WZpbEoYmrMTalNG4IGFhFC3SWElJ9OH+kR1129d+gy9c2gPvXNuHivcEkBfNKB+Ykn3AOyOBtf+NXPPXAuu/AcoPAeAxIZE/DOXpwM1wGM1xMFheArXx+PHzT8LM2/rhjooXgdWfEMvoCVSpRzYAcx4PTso6aLv1bWDVh+aMVB4FXhsMLHrBtOg1/VsFfwT8wFe3AMveIJbrLm3FD8n3o1/COgBA85KVaIxiAEAi4X0GCFFIgH7/Rwm5nMJsnZ/SiVem09SQaLH5wAT/m4pq+kqCkIcjWJ5yEx5I/IC6Tg5KkYFKoLoEviN/hq/Tbi4aZiTj6Yu6oKcmk7ORBoArlL94D/BMAfDu2cDil4Af71V9p22kvXgu6VXg0FZVtYQECSj8A/j38Wg0a6xhE6QjMqKwfx3w7+OBuf8GincD5Ycj9+qrP5T4Pkb9fCpQWoic1ERkVugLAQkI4Ifk+/Ft8oOQUD+Wty3AeQvOQ9+E9QCABvUpBG70fYsNKdeih7RFTUTHfKtEK2kfLkqYH2lDNLYvxOrUMfgp+V4koY7IQxSPOr/dBk+AsYJtC4DVn+Cy+kPSLlbsdP6T/BS+SHkUX51RjicuOElV7d3kZ5Em1WBa8suq6wMT/kCb7y4BDm4Gdi4FZj8SXEg1yN35E07/7QY0RfAD1YbOpiX7cOqJTaLqybKsmvyv9M3Gt2WXobe0MapsVDjurAeBHYuAz6+LXFvyEvDpVcAbp0bVBxDcWb1+Kkb7gvkzqE1IoW++rhpLUm/FotTbkYQ63Fz5BvBiT2DP8uAkWVpIJoDgJN9h/4+QVr4HfDlGtxwJbT4/A1jwHDD3aeL9ttJunLTuOeCrm82JLZwG7FsNzH7YsNjM8YMwPBRhsO5LYNUHwA93Ect+kPwkOiXswEfJT+IS3y/4x5obMCvlbtyd+DGGf9EN2PmrqnxYgNFEHUX1f1VxuPOb4yAu981BCmpUwiyNwHBBwkK8kfQ8pNoy88IAmm79HFj9MQC63Z6henvzLODtM4H5zwLf3g4pUKcoK+HshF+xMfVaNNwQLUiYycbJqEV3aatqoTk74Vfg5f7Bb9YAYxK/R65UhjGJ+rlkJARwjW8mTqjZCKmuEqtSb8SalOuR9HJvNHqnP06UgloQVR8d/hP436PqxdoCVObGiiNBIb2m3FhjFdrU7FwSnCeWvgp8PwGY2gUt5T14P/kp/MM3H3jv/Oi6S6YDADI2fxl9r2hXcA4s3kM3Bn95CqgpA+Y+BUztDDzbJnwrQZKQjTJcn/gjUmuOAFv/B8x6CPi/rsBKslDZWtqHExN2o3PCDjRE/ViecQ6yy7fj4+QnVGXvT/oISZIfTyW9pX62yW2AA+o0/gBUu725KXdiSvKruIiwoT0u6mwvMhqiJLghrq2MvrkxOOZOSNiHQQlrMNb3Fa6rfBeYcS5QFxHmJUnCsIQVWJwyDml7lqiuuxWeCckKZpwDAGg0tjtW3NYBie+dCyy+AQmJ56B7QtDc49v4LdJbRgQYo7HwfvLTQCGA6RrtSc+rgIatwn92mHcLAOCWxGxMrLuWPrGVHFBJ008kvQMAeCn5RfStnq4qek7XZuq69VoWFTZ8F/xvUb16WTvHLXkJ2LsCDyetwFv+s4M7rm0LgI3fAcMf1ZXswyak/evC1zJRgQtrvgWOAHhjWPBi4Vrg2u+BmnIgUAekavyLyjRmNFlWvQDTXjuwHsDAqMvHScW6NKNQVRx9bf03QON2SMuI5Nk5PleRCfOQYhfnrwPqqoCUiD9DhhSZdC7x/QIAyJXKMDbxm+A7WPEfoGXfcBnSplpCkO0TpD1Igh9JhzcA/zkV6HIxgHGYmXIfGkiVyJcOoSahs/7zERASzJP3fgxgaLA9nS7KRQk6/f4A8DuAzhdBCviRhipUQj/zcEptGSYkfoqv/QMAaM79+fCfwf/uDE7ADdNOBHA8gKAAPT05qAnLX3A/cNot+g9xdDtQWxVc5NqPAE6+AdOSpmOkbxmeqb0Ur/rPA1BP7wCCQvKYubrkainMxSMTluHRpPeAQ+9hc9nPAACfJAPlQQ3kgIR12ORvqd4IvH4qUF0MHNgIXP6xaRuA8XBVaj/xwT+BPb8D2xdBlkcZVCJEz/3+NgDgDukd5EtHgtdKdkeXS9R/z/jPhcDhLcCOxUi89LvwZV1BM6WBLikJQMcEhRksNQf4tX7O+7p+HHS/XNU5c1LuDv8+17cEs/3q4xsmJb6DX9ELP6Br+FoAijPGfnog+N//Xg+c90OElyN/4ofEO/GyfC6+CAwOX++VEC0EF+Sm4/l/dsNxSQTBRIG3kp9Dz4StwP8CAAarb+5bHf75dvJzwR/VALYBWP810PXi6Ptf/QMAhYY5xvA0MDyoLALeOTvyd/lBJM6fDBTtAGY9hOaFcyL3svKtO0GV7Av/VO7+/PWvj0a9emHCAnT5oBsaH1oGIKjtCSEVEfv6lIu74bWremHM4DYaCoRZQ2nv/vw6nHV4hvp+TbnqT0lCUOhb+irwZFPk7ZkVvueDH0MSVqMBKiItKQQYH6n9HQuDppmn8oFnWkbvPmSFSnbrHGBya2DDt8G/i3ZCkiMTb7+EdbjF95VajasViAAMS1iBm33fRC4ECCa4QCCoQautAvw16nvbFwW1Vi/3RW5GMh46uyMeO68z0pIVfVl+IPL7lX7A082DY46ABiBMbOnqHDlKE1Ii6tBZ2g4JMiTImJNyd1BYWfhUsPAfn0KSgAZSkO7AhD+4Q+qT6iIaGD0KOZJCSxOoQ9bH52FD6nVoCH3z3cnbX8FtiV/VLzDGvKWU7or8PkzYCSsQWhhTUAP8Xzfg5VOArbPDmrCRvuC3c1/Sx9H8kQT8g5vQ+svzcGrCStQq9oqDE1ZjTvKd6CVtCmpVts0HSvaGTYIAEPBF77xLETxFWqWBqa4XkHfVa93+mge8dDKwYwmI2LcGzd7pTTRfAxoT0p7fg/9d+zlkGTheKsSLSS8ETZsVR4C9K+uZ1ffdSiCZRcoPA0fq/fmSDJxpD9cL8ruXqfz8VFqiqmKgLCjgIY2QG8of/MYTJEltOtQKXV/fEpkbAGjnu8eSZmBx6m2qa1cnzsbL0jOqawFIQW3V/vWRiwfVGu6kHyagrbQHU5JfjaobhUAAo468jsFf9AY2/hB9vx49E+rNc0tfxeOJb4dNRQCC5jQ91JSF5xZdHxgE8FTim7jGN1OfTozgCTA8WPxCcPEMITFNtVj2W3Fn5F5VcVQOAmYoNAktpIPh3zvloJmIRgMzNfkVJNaUot/vtwOo1/bUIwXB6JeTmmfh3G75GNG5adT5TsRtT4JCgbf2vzjnyLsAEPTHmPcsULpPXVzDZ89fbwvbjEf7fsCM5H/j7eTJaCbvD05MChNRIgi7PEBtminaqb6n5Pn9i4L+KJ9cCfw1F5jWBa1mj0Foovoo+Unck/Qpzkz4LVInRe2/hNoqvJ38HAb/f3tnHh5Fkffxb/dcSQg5SEjCkXCIXHITiAE8iRwieK2rCIh4oqDiCd7vrougrr4Csp4rXigLKqio8LIBUQQChFsUEBEQCFcICSSZzFHvHzU900d1T/dkkjBYn+fJk5nu6u7qmu6qX/2usoWEP+bsc80s4N1BwJf3KVS0AIDDmxVf77ioLcZKvi8Sp2UCzPHArGxmD/wedzNG2goVRV1QCUgA4K5QfPX7CVBdDgEELzvewNeuJ+Aomg2xJiQ82Mv2as8ToO3JHzBcXA3AWtRPVhNGxB0hwNInMc72LQDAKf9da87AcYi2/0DbJt3zNjnzK3vHr4WaTYI3JOC1mFdgotYI+hMZ8Yh9gXKDt1pb6LPbkXBsM+Y4X4KHhN6VD5wv4DzxMD5z/Q1LXVOoKv+VThhtD9VfYAgF2QJ9LthmtsC2D0YAx3dSfxQWn94Ge8VBhfn6QnEHbrB9B4Cg/6nF6CWoNAGB9+hW21IMt62lAt2M7sBblwIH1rHfgQAelpJ/dh9gZk9qInKENDDS5GHqtUqTO0RHMCoyEZXweWVtMz0H+Gc76q+WwBJg6PshCKF+DgC7zr99F/yoKBuGpigLfibS7/C6LF2G7FpJOANx3w/M8/hUw3EH91bq0/PjDLpB0uiEYYz9vxgirpOdmNFHSBQ+R6+x+7+6RfqRjbjZvpxqB88yuAkpElQDBGx2wK5jq6wq1bUheolJ+bE85GjWSQgN0tJZg5OTVa9S88yYhbrqVIFoZ0TSy7r4vov068AUYFhqcYLZzhnACq1fDWsiv9D1LNpXv49rbT8CAPqIu1CI+4EPPwDahVZgtgsmInQEG+A+DVSeAFJbKTUwcoreAgAkHSjEl87fcISEOr4cQSY8uBrjCnEDDpMmuETcCsx4SHsuvwdQmzuWPUP/b5sPdBqh3LfFQM3vPk0FN5bZqeokAGCa3MYOwCkwOmJ3OXBiDwrEYnQT9yDHXQ1MX4Jm7a9HRxsVRJxrZ8LWdnjwELGqNPhZLqS0Fw6ix/YHcZUT2OQOv2CinDaZKQhmH5LegT/WA2tew7MOYI5vKJzygeKN/qH6GDg0VrpC/l3BV+u3lVRIVZH+0xxMte/HVO8o9sl+nEF/ryEvAOgHAHAJ4QevpkKZcoNaUAUUfinMgdwIon3e77cvwjzv5bD7q+ngnyIzn6n7GOILaAJXA0umAFc8ByS1UPQlEpI/x1P2j5B8ohJjXcAuvzZMV9LKAaDPGADs/j9D5yHmfVcG2mXXEsARH9w887p2sMWn4MquKvO1IwE2UcAI8UfMdM4GdgH49TPgPNkK7Sd2s81RK6cDf2yALf8NpVDC6huqy4IfG4EhkOrQVQxFhxK5CYnBRPsi3X1SpNNNfbIxb/0BTCl/PtTOgbNbIfjOGQkw0nu/ZAqEu9cyi+SQQ6Evc4YBN82lk9PNc4H+DwKN0pjH1QdcgIkE9ezI79O35VadVOatkHU0VQgJPcyZtMTGD4E86jDaUQipxG2BiBNn6W7Akwj891m6Y8McoP/9mtNQtC+BKKi2nfqDqmOdMvUu6yUQtAKMAz7kiVrhBQBySlcztzvhwXGi0nYc3AC0CdlyTc2I/F5qb971LXDrN8xBgF4w5G/STdwLagymxMv8S7D2X3hbvswOyyfVYPYJAPhZZm4q/DtQsjX0/eBGoEVg2Xr3aeCVztQkkJhlfE4ZzHapLgdm9cI7Ut0DVUzeJYsgE0SInpAgLlaHBBg5CbL2yBV2WQth3vsDil2v4RHPeGxBHt14cp+sBFHWX6ZptBkJMHEhAcbpq6Qq8A9G6JYfZS9EsZ8RTu/zhITNJZOR2GERAKVJNYjqndf4tLA0MLLGqjGZMkFC1Bl0Oov70HPFLcCJzcCEdcqdZQeU3+f+BdgT0Op8eE3YayYLlcHP7UWloDPGs4A64qohfkMTklew64+73zwC5N4e/Dq8fSMgpZm2nCMedlGgwovER9cDT4W00SBgv+8B7UWztLmIE2RtynpvA5MEAEgQzAswQb8R6N+q4zRtT7kGXY2kgZl2XVc8OawTHDNUZ9ObkDGohqzj8hqMLRKJ+ksUpJFQu1Cz/at0sgwCVBwBrmdHS9YH3IRklcpSYINyFkwFGB0NTGUpBJ0ZilyAYfoySBz7GXihFdoKh3CpbXNwsx1+JOE0UuYMAGb2CJVnzQbD8LbjZaCmknaCr3YDXssN+ZSUHwb+WKc9SNTKv8zOH0BL4SiGbJ7I3GeDH6VI0u7whwY3UzMibzUVXgDaOeq98Nvm654i3mqIrc9L2237Z2zNiZwfXlZ+f/syGkZ6eCvwSqeQP8Np/eiqGqIcCJ0sAUYxa9NBEBUmJDN0EvdpN/r9VKt0IhDm65PVZ98qpAkVmON8KTQnPRPqwJ3wKgQkOUYCjE8MvTeJ3pNUMAyD2t8AAHBsp+KrndBnjPkMqNpKk+/DVwPsWc6OAoF1DYxcuJTTUjiG5BOb6Zd9P8r2CMDC8crCewoRHnOz+vE+HYdOQgyFeC9R3be6L5T3pVVldL/Kdw6OeDDd/NRCnkE9XGcOaU1Iah+3wLPbXfgVbQWl+dssBCIEhiDV4ZN8ZOAkknCGcVSgSoHhWBAENI5zQONwYEEBY4cPqaWbqXO3kQZGIjFDV3OURsqUG079EaqMzEG4IeACjFV2LNJu83v1BZhDGzHoq774i20lAOUjWUlCx+j6eEi4y7Hc9UjIWQvAZMc8bI1jhAgbzpLZO6+wFQPPNwNe7UJnMuUHacQQAKx7U3tA6V7q4KhCT4CRm77UOOFFKWGYvHyhNmlkZkYkf1ErSizNWCLG76Who5/eBvxnjPXjf/6KOjabEToAOFWmtEYsAaCSrU1RYCDA6GlZmL/tlo+BhXfT8HYA8FRqyyjqFnJ2dcKjKzAamZBsMufrvBMLNX5Fptmn1Ah2bUlV4cxnTTWoMgWSD68F/tlBE8YOMASeMNhq2AKMwg8hXpbfRRCo74tFHDp5oBT4DIR64rfmA2OksSz9jQqjzzcH/tggq2QChK0M06tGgNG/F4f7pFaA8QR+5yEBR1yvGyjdiy9cz+AD5wv69TSAAMioOcDc11PcrTTDBY8IVEk9HGsmouYlmJbCMVy0ciR1RDf6/SQaNdVsagz6LtvVkyS5C4XMBNgQcAHGKixtypmjTAdCCYf3NP7peFNzfJVMzWcXojjY/vKNbhI2SxFRkkpVYDwmco2PjPfGdAVhlFdEm6iwwwc3GJk4ZRqYRCMNlYRcje+riUiAseK8B4A6dAdCRrF3JQ3ttsJv34XX3FhFHT7OQhAg1pgTmiQcLCFbJQToaSCCz53sXjsL+9BEYA/URhoYefLFi47No3mBImHvSsXXYcffwcxr2uClEQxfH7fy+f2L7XsksLSC7lPAu4M1g4+RQMZC1BFgFMgEfJw5ptBumaFALEYvdeI1q4QTYASVACMXTNQc2Q6seoV+/nZyaLvdRRPkqZG3MfEZ1sPuLlUK4F53aGCXopd8NSFNYoT0En/FI3tuZe6rgUOjgZEnnhxv/wpY/BAdIw5uBDwqbY2FDOUdRf0JI5PACyrX8G6LuwMdhf3a7NHysUVmjm8IuA9MNJh/i+migj/00slNSDYzMyGzHNoIfP0wgGtYNQAAeIgNjnCOscEZukrqeUU/L8gFGS5qWlLNjlKh3yE7BC97JvhryDPenAnJrfwcgQBjxXkPALBWmYxQ7ohqivLIVNWGmDYhsX8TvX5Srf1holb/hy5I/3lC7TvfpU3SKGEkwMg1MBq6jwS2fGJUwxCyqBMAELb+ByPscYocOkEYbXWXfbG2nMTW+QqHWasCjM2McBnO/yoM7zhfDl8oHFY1MHOG6J/rhCy6TC7UH9oINGaswizXBHjdhvVwuE/CJci0DPK0BFL0ks+jmDRFit5v3RhVSFRpYPLFHcpCG/4N5I7TMYuaF2BSmQ57BgT6Tg/scMr64iWuKdDMW+T9C9fA/MmQvXTVRKaBiaYAAwTzeWihL4HXjFOhJMCoNSqshFQSnipA1GpTUg00MA542Sa0k78HP6pffCbyDs3viUiAseK8FxXMzLTrAsGma0LSW4vKAS/jmVJtCGdC8pr4HaEUYJ61v0+jHw5vBb6dgmalDH8sCQNnRA2s+/9jPVsIc2vLXiD8joNEJwLjS6W/19DOWhW9EeYEmNoPtlHByAfGivOyTLjVaCUrDkGDLGoIvhrDegh+j1K7Kp3f5gppEXzu8M9vLUgSzsCl6uc+dE7XFnRXsLXexK9xyG2O49qwdwCXy3wlTVF+CI7PxrJN0mrk6TEaWIDhGph6RpANsvLon6gLMEktsfr2y7H9YDnu/ECutqUDjjkBJtCRW7E7LZmiVX3CWLPRKSMOjhPG929KM1I8R/l99azwx6gYZjMYHOsCXY1FHWOkgdE5hOkwLKeqTNeE1I9sAlCgHKQMeNzxCS4Qf8e73qEYZ18K7APwJg3zTzU6UJaxOCLsLrZg46kEEWwKB81M4WQo70cY8lsnAxasNaZMSFIEVUMSJgrJ7IK1tLBs8JQnc9RDFjVEtSf69RB8NUoTkiT8uBIBW2Ai6auhDvkyDpMmaCaY8CkzQRIqzfXzZ46zU1RUHAb+0RS47CngEpolWJ1czzR97gDWvxP6vnupeWFACoMHmJGo9QnXwNQ3MvWbXNUYdQGmcRaaJcfjis7KGanNW4V/2P/NcCZjEBRgLDwm+9kZQI0Gv6YJtrD338hMffcywjzPdsxECNQFgqgQpuXomZAc8Bonsnt/uK4A85QvYGozqYEBgBG2NVjksjhIG2V2NYPNpU2ICABeN4QmyuzUVN1u0oyjF9KvVw0zAox8ANdQT+vX+I19TyyZzsyE+8qRa2kWjFVGwKmIq9iHYTaZc7VkQnImAraAxtjn0WhgivwdrdXJgCSh0pyrwOkjxoLBin/o7zNLtHxXWOkD6hEuwNQ3skFDPmhHXYDRyUsjEK8i46chwbrWvjOMF/Q7Jxvxhk1Ud79BAihOBAgiBF0fGPagwxys5Y9GyVZds0YGSqlAbFIDEzE2Z/gyRtiddBkINTsWhVLbB/BBDB89KCEN8mmMfDQMbDph1KaxMumoDd4qQwHGkm+fxbB+hR+Lt5oZFSknTe4wLgk/TpkGpuIw8O1jimNW+HpYqxOLHqMB0Cy8pqK+zhzTSRIaRRxREmDq0ORmBi7AWCaMI1VamGylMgFGsvMnmlUtWsEe6sitOhAGiaJ5I8Egv4odXnaEC0fBjz5riyoaYiDAsPJYADTkNqw1cbfBILLieUsamIiorQDjrggs4qniJ+1qyU54zb+3knkj3tAAFsSUCcmI+lpBeOMHuhGPANCcmDAFSchNE2ZQa6Ck9ZXMIAkwchMSgzLoLxBpmvgU+k9wa5OGsjhzzNTvF3G/DiiTlNaGup6QhIELMNEm3AxL9rInu0RcIOzF9rg78Jnrb9Gth2QH2Lcad9sMoiWMkGZEUTBzxBv4sNiJJ/oCXKzD6FSZoeaRYmBCEnRm1A7BC3HdW8B7V2mX05AoYiSMkzi0qZ40MLUYvA9tgtlojx7iHiSZMW0CwHeBtccCg1k4bO5T4QsZUescSBbacM9y3V2XEQs+ZawFMY2oTfoByQfGaSzAVJAoOKkGzJqmtC8A1SyF8y2Zf4thbq2wRM2EVMcTkjBwJ95ok96OrtWhh0xNmugEJti/qJt6SIPQnKGYHOm4Jw1SVuycmV2BI9s0mwfYfmIUpjxyZDL2CIwU4n9mEjOBU8qEWDXRFGBEEYJOuLVNVwPjhW1pID/H9y9RbcKmj8xfs+Z0PWhgHNR8YtHnpN5QLxCqQ61NSLUVYJyJFiLkrK3Ro4vVZ0MehWQVkxqYM+p1ziIhoO0I6wQvUXWSvTClnB1f4FPnt5HXKWompIYVYLgGxiq+MKaOlFbANa/TPxayXCWi36fNvhgtouEcKq2tYuVcAe94q5wn1kE+lFiiaScgp1/oO2OmXqMz3/i15bWWLycYmJAe3jeeub27bNE6/DgD+O//WLvo4S2K0Pg6QRDq3H9gsufOyA+uLxOSHsNnmCvXwAnKTCH3gbGKNJF0NlaY29WcQTQ0MLQtB9lMJlysOmnKh8nIrzAs3IT0JyVc7gWbE+hxM9DtRvZ+mTZDgE+zhLoGK8546e1Dn30eQ698U5w6QAUusxqY5BwaxWEGZy3DXc81fDXKTiUuRVPETbQamNW+zijq8j/WrycIEBi5TQAgo0apmjYbKnxWQEidO7DWyqzgTABuXwa33di3wl5XAkzLvubK6Q1wjc8iTWlVFMKbnY0MNTDyXF2RX8OisFB1EnUeRVbbaD2JBjYhcQHGKuG0EVJInt4sUKaBSa3aj6tt7BWaQ+dTCQRdbwCGvsQu2yi0Si/8njBhlmYgdPVgs4tDEp/hbCaIzQk8cTB8OSsMeNDyIQcGRLbeSZ3gVwmcjBkwy4R0BnEQBBEYNNX6NU0Okj6nObNHXVFK2MLucr0IkTrOTVFZG7OCaAey++JQqrEgIXr0I3Kq0rtGeG0HcwFWJnYdIe2BrezttWHoi5Edp5OywRLOBEMBRk/raQmrwkJVmbn1i2pDtDRsXAMTY4QzIYWLgrAaN68WCFrkAg6dDrT32NDnkm3AL19buxaLqpPmBRifRzd8W4Fe51gb1CvLmuBU66HRr0ek+LzKcFRGp8dy4vXCRgMW+k0EHlWu41Kd3kX/ep4qCCbDVn3OKERi1IIDJIO5Xb6WmII61sDIF2G1TECA8DGyVZuFRDx7JoDN5IBs06mfmQmKVeLD+HvUJfY4Q6EuOgKMxf7OfQo4bSF6KxIiEWB6jgZuW0rNbpc9Rbd5Ki2t0RRtuABjFbMaGD3CCQPqjk2tgTHqgLreAAyRaRUWTzK+lhk8leZfJr/XnAmpLtJPRzAg+M0IW/WFWgPDGKRYGhgvbCFlc6N0xb64zlfqX0++7kwYGloD8wdJZ26v0tOEiHUswMDgGdfzfZOQBBghckGARPrcEmJeA+OqR6G1Pq+lxh5nGLLMXHXcKlb6pqad6P9oaJeMiEQIzr2NrhP2xB9A3l2BjaThknGCCzDWCecDY/CwXiWuoWutGKGOnlB3VqJDP2W2IAAtc43Pr+Kr5vczfSuCFP4d2B/GzCXhN2lCMunIaIkIZt1EjHwQOZaRb+2ArG7G+30epQaG0Y4sDYwHdv3+99LHgU7DgQEPWaioFn8DCzAVhN3Z6mpC6kLDJ7+ukQmp2030T4/Ac9o0NfI2JZHe3w3vmRdgGqXTWfbAZ4B2V0R2PbOYFWDqwjQYRhi0tBSCnNTWoc/hJrVy1AuJnnd5ZNcPRyQ+iPJnR/4MNmAkEhdgrBLOMbaR/qJtrzln0ZVVjVCHP9rVGhiH8Sq0ZjuoAH/Ed8Ir3r/oFwhXXzl+rzkT0nVvmT+nWYwEGD2tUC2SfflFi2aEcFonu0slHGvr5iba39ZD7Oz0/ucPopqIGz8CCp61VlcVfpOhv6axKMBW6Wg8mCakln1qvx5SGAxNSKJoHAUVeD+bJEWudYjIhDTqU6DzCAvaAIFGFF70cN0nxYuTPV+prfVNSnq/63XvsLebQd2/RoNOI4ArZKtJW0muqI4+tPrutblE+T3gF0nUQSWRaMHlz46UrgDgAkxMEU6ASW4R3etpHn7BWICxmImUiDY0FcosV4uJ3xP++hOLgWZhtBGAsgOQaNxcv7y8k219EZDeIfRdp06CAEz30NnyUp81zRUz2duFE/QPCPfc3PiR0r+KMWjomZDYAQvRG3RItAUYAyGfRbWOr4siOiqpJXDfRiC1lTX7fgQz3LBOvEbCtDTBqIUviWUNTLuC0H3WdYp6s7S5OPRZrg0QbEqh4h6Z9levXVv2Vn6/ejbQoje7rJq6MGff8D5w3kAgIZ22vYk++VHPXbjU/bLWl89k4sMgam3W6E+BicUQ2g9Wbg830b3lC1zu/qf+MYIQMkM1YCQSF2CsEs7el5hpvN8Md64IfVbPEIjPeDC0oq4EkJnSCK0Ekz4uyTlASo7+/kseCz+jMdtx596u3aZ+CeXIOzebA2g/SPmdASHAG74R6FD9Hl72Gaj9Gdi9DAfY9oOVuVzkGP1mfe4EsvuGNU+yTUg6A1IUZ81iQpRNfuEEmLu+U6QEqCIu4E5ttleXPDFYWlsg7Tz6uY5D9PU0QkEMNTCBfWbTDbCwOuiO/kx2XZP9Q11rXS57MvRZfj+CqBzwMzqHPuu1WZO2QN49oe/xqUD3kebqEakGpr1BAIAoUm3Rw79QzZeJNl/guxS/k2ZaAabVAP2D+twJXCkTMvpPAoZMU5aJS6bJVdVCbzgBJqMzytTRf2r/S0nb3oCRSFyAsYqR9gOIzgynRa/Q54Q07fWjaEIa3iMHpR10ctaoGfkxcP8WYJwqA+SNHwHjVwEDHg4/25ALGqM+0y/HeultTmDEazrnlXW4gk1ppghTJzecmD/xMsMycipIPA60vp5+USwdQYBBz7EPMpqlSKpxxe+qHUAGdsnWnhY2xDtYz5zJAciESaFxGkPz9civwEO/mLuGGvUzraZ5T+CyJ4Jfq+CkM+oOwxTFbPK1YOTnNNDAbPS3w5iaKQbX7qW/768fAqM/0xcaJYx8NVgaGJfFCDo9AcbRCHiyxPhYi/0DRedZSmoZwbmkU8onHLK2cFcohQr5e53IjkYDoPQdEe36Tqr97lN+lwb2AotLuRQ8q4n602Bz0Pob9D8nSGMMc8tSIMjzP93wvrF/UO5tQJ87gLtWUgF/4DNASg4+9sq0ipKQoY5cDfccEIKEOIb/pRzpOeQmpBjCSAOjzmcQQW6SIENeAHrdQkPX5Ph9+k68gGUTktPhwI2j7wbuXQs8HiY3i7MRnV206geMmBXabo8DsrrSfeF8YOQdy/kFwKM6C7CJDuCq/1U6v9ocQK8xwGN7GQfIBRiRhvoF68dok9GfK76mNDbnkzCp5l4Mcr+IA62uB0bOA/76QWhnamvqRD35d+2BNbJVW0fMoksuSEidVBhnxkvbazUXPojo3Jxh4jHr1Nw4K3wZlkYjsSmQFGFSM1W0FBPZbDuo8fjr+8CEdfB2H41DpAm+8MkzF8v8Jgw0MFv9bfGD38CEedtSKpzd8D6dvV70MJDZhT6LnUdQk4B6QFcPBkaDgzTBkf/+D/+sX56BbhSSsxEdVIzMJ2YFGCPBdvgMqhm56hXtPrOaJXkfJhdYKk/onyMuGbh/M9D3bu0+udAq2PRTTTRpq/wuXbvf/WGrrMCRwBaU2xVotxloYN73DsZPpE1og9wfKL298e9ld1EBqXkP+psHni3FIo+SkKHRwMj6B1cSvf+bFyiOW/rIQNUxOhoYbkKKIYwG6J5jlN8vfzry61w4ng50nUbQTlSC+IEU7Uw8iEUTUvChzOgU3vlRPjDIOzi51slIJXvTJ9o1PhqFZs4feK+gAlu/++kLlnsbcPN87XVY64TIB2zRpuxc1J1xowygnerl1Kv3sJcVg80i/wAcRhrtODoMBTI7A3f/AIxZFIo8YDmpyoWTXrcoTSKSj8m1bwEZF1CNFkuFz1j7JU2oQJs0RkeqPl4u2Pa+NfQ5pZX2WDV6g0GkmMnZIxM6gz4wNgfQtAP8w2ehv3smdhHZeyD//eURICpE9bo96hwWdicVzi64Bpi8j85q7/mRPot6qAUmIy2spJ1pP5g+W7cvs5yTQ9ATLqSMr2O0K2eH6sYeEH23fEUnCx2vApJaAJc/pX+O3rcC964B0tpp9w2YRJ/fHIMoPUFUBivIBRa/R78Pc8QDTdoASTKNYP5E+l8efZnYFPDrrAVVc0b5XerPzYbe21zAFc9RXyvWZHHUp4xjVOVkmqutcuEFUPrBNWlj/CzpjEXJguwepb7FyOzo91HNcftBwC1fUM14XBIaxauOUf8uQQ1Mw5mQzurFHGfPno2XXnoJJSUl6N69O2bNmoW+fU2mwq4DCCGouvJFoNNVwM9fAju/VWa7JV6aN0VOJLZk9TkufgRYFZjteKuB7iPxfyk3Yf6xlnjH+bLyOL9H/5pxydoVXP0e5fUaZQCVx9jHC4KsLAldh/iU51Bfv3kvmh8jJVt7bwD8Wd0gHtmG9kNvRWXfy0P3AlChSjpf9anQdvU1iJea3g5toss4yNtBFJXlm7QGPJWo9lUBgfVEKgXGOQG6LERSc2DezYHr0vJefzUqpbqktwPQTnlvk7YBmz8CVga0clfPBL6aBFz6RCj5k3Q9u4tua9IauPO/dNvvP2jr0/lqYPtnQLe/Av9HB5iLM07S+5AmtMHfxK+sjzMeqA74jHQYAmx8n35Oahb+GSVeZZmR8/R/BzM07aB/3ICHNecuhSvU1qDvIRG8qIAdldJ5Kg6Gjsu/Fzj+C9BpBPbu34c2G6cHj/UKXkCoCR1H/Mq6MJ5PDfLjASqcSqtHeyq151Qg+1163Bw6JlDeTwSIgn5isCJfR3Sy2WFnnT+xKT2XzUF9qqSUDXp90vXvAp/dRgWX7Fzg9qV0u/Rsst51vXONmA2c2kcFCtEOHN0BHFjLvon4FDprl47111AT0IEiGkUmCMrrpbYGyvbR599TCXS5Fvj+RaBVf+DyJ+k2uwuYsA44+jOQfj5wqDh0jqEvAN9OBi5+FKgoUf42ouw+W/cH9qlSRgg1GFzzdyx0BSL5et4M9L1D//lnaSOIT2XiFoDBU/HRN9/hO9I52KcAQGWzvlTgSW0NgGiPVZ6Y+bzGC6dDz6dUH3mbAopnDr7q0Hmy+4b2y/sogP5O8us5qAYovuZMgy02IhDSgGn0DPjPf/6DW265BW+88Qby8vLw6quvYsGCBdi5cycyMgxsoQHKy8uRnJyMU6dOISkpOlEUZ2rO4JL386JyLg6Hw+FwYp2VvSejUa8x4QtawOz4fdYKMHl5eejTpw9ee406bfr9fmRnZ+O+++7DlCkGTngB6kKAOX3qBA7kGXiFczgcDofzJyL7h2+Q2LRN+IIWMDt+n5U+MDU1NSguLkZBQcghShRFFBQUYM0adoplt9uN8vJyxV+0iT+bUs9zOBwOh9PAxCeEt4jUFWelD8zx48fh8/mQmanMqZKZmYlffmGHbk6bNg1/+5vFUDiLiAkJ6LCxWLmx6iTwvxcACU2BSVu0B/28GDi+i0YkGfkL+H3AkZ+AzAushWJXlwE/fw10GqYMwZM4sA6Y+xeaTj7vHuDrB2mSpa8C4YSP7KH+EXrnfiWQh2HcEnMJ6OqCJU8AG98DbpoLtFWFO795CXBiN/DAFssJ0jS4K4AF4+jSCfkTFaG85zR7VtBQ3l3fAmtn04ieB7cryxzbBWyeS8NQjaKIXmwHeCvp83bxI9SOvv5t6pfQ6iK6Fpgr4LR6eCvwyU00f5DcsTjKuL0+OEQRoqjz/i0YB+xeClxwHXC1Tpi+jCcXbsPX2w5jdc9CJIge4MqXle92TSWw4Fbqa2Tk/Kui9z+WobLGh0kF7XH3xW3DH2CEzwuseY1mZm3Rs3bnOrwVmDOEBikMNbmC+8nfgdf70bxIowOOrb98DWz+BBgxk+2IX59snU/77jxGRFOAqhofVu46hv7np6Gxi+1YvPPAEfxz8Ubc3a8Fcrt1ZffxhADTAglOJ23TpBGYW7Qf//h6BwDg578P0R7v91HHZ0EAng84MN+9iuY+YuGtAfYU0mhRucP8HwG/IClNx6k/gPX/BvrcDiRHHhIvqJ1965Gz0oR06NAhtGjRAqtXr0Z+fsib/bHHHsPKlStRVFSkOcbtdsPtDi2UWF5ejuzs7KiakHSpLKUe4VIUwNmGp1obSVJdTvOOhOtI9q2mTmUW11iKKoTQNm6Upt3n89DIAqsZK/XwuqkjcItc8yv3nit4qoFNH9JlCFJNRCexOLkP2LOcOqiaSRKmdhRsCNwVwK+FwPlXmI4I8vj8cNiiq8A+fKoKa/acwPDuzaN+7lpTU2m9f6sqo1Ewdby4ZkywvwjwnGFmfvb6/Ph800H0bd0ErdPDPH8l22moedtLjMvFODHtA1NTU4OEhAR8+umnuOaaa4Lbx44di7KyMnzxxRdhz1EXPjAcDofD4XDqlpj2gXE6nejduzcKCwuD2/x+PwoLCxUaGQ6Hw+FwOH9Ozlod+UMPPYSxY8ciNzcXffv2xauvvoozZ85g3LhxDV01DofD4XA4DcxZK8DceOONOHbsGJ555hmUlJSgR48eWLJkicaxl8PhcDgczp+Ps9IHJhpwHxgOh8PhcGKPmPaB4XA4HA6HwzGCCzAcDofD4XBiDi7AcDgcDofDiTm4AMPhcDgcDifm4AIMh8PhcDicmIMLMBwOh8PhcGIOLsBwOBwOh8OJObgAw+FwOBwOJ+bgAgyHw+FwOJyY46xdSqC2SAmGy8vLG7gmHA6Hw+FwzCKN2+EWCjhnBZiKigoAQHZ2dgPXhMPhcDgcjlUqKiqQnJysu/+cXQvJ7/fj0KFDaNy4MQRBiNp5y8vLkZ2djQMHDvA1luoY3tb1A2/n+oG3c/3A27n+qKu2JoSgoqICzZs3hyjqe7qcsxoYURTRsmXLOjt/UlISfznqCd7W9QNv5/qBt3P9wNu5/qiLtjbSvEhwJ14Oh8PhcDgxBxdgOBwOh8PhxBxcgLGIy+XCs88+C5fL1dBVOefhbV0/8HauH3g71w+8neuPhm7rc9aJl8PhcDgczrkL18BwOBwOh8OJObgAw+FwOBwOJ+bgAgyHw+FwOJyYgwswHA6Hw+FwYg4uwFhk9uzZaN26NeLi4pCXl4d169Y1dJViimnTpqFPnz5o3LgxMjIycM0112Dnzp2KMtXV1ZgwYQLS0tKQmJiI66+/HkeOHFGU2b9/P4YNG4aEhARkZGTg0Ucfhdfrrc9biRmmT58OQRAwadKk4DbextHj4MGDGD16NNLS0hAfH4+uXbtiw4YNwf2EEDzzzDNo1qwZ4uPjUVBQgN27dyvOUVpailGjRiEpKQkpKSm4/fbbcfr06fq+lbMWn8+Hp59+Gm3atEF8fDzOO+88PPfcc4q1cng7R8b333+P4cOHo3nz5hAEAYsWLVLsj1a7bt26FRdddBHi4uKQnZ2NF198sfaVJxzTzJs3jzidTvLuu++Sn376idx5550kJSWFHDlypKGrFjMMHjyYzJkzh2zfvp1s3ryZXHnllSQnJ4ecPn06WGb8+PEkOzubFBYWkg0bNpALL7yQ9OvXL7jf6/WSLl26kIKCArJp0ybyzTffkPT0dPL44483xC2d1axbt460bt2adOvWjTzwwAPB7byNo0NpaSlp1aoVufXWW0lRURH57bffyNKlS8mvv/4aLDN9+nSSnJxMFi1aRLZs2UJGjBhB2rRpQ6qqqoJlhgwZQrp3707Wrl1LfvjhB9KuXTsycuTIhrils5KpU6eStLQ0snjxYrJ3716yYMECkpiYSGbMmBEsw9s5Mr755hvy5JNPks8//5wAIAsXLlTsj0a7njp1imRmZpJRo0aR7du3k08++YTEx8eTN998s1Z15wKMBfr27UsmTJgQ/O7z+Ujz5s3JtGnTGrBWsc3Ro0cJALJy5UpCCCFlZWXE4XCQBQsWBMv8/PPPBABZs2YNIYS+cKIokpKSkmCZ119/nSQlJRG3212/N3AWU1FRQc4//3yybNkycskllwQFGN7G0WPy5MlkwIABuvv9fj/JysoiL730UnBbWVkZcblc5JNPPiGEELJjxw4CgKxfvz5Y5ttvvyWCIJCDBw/WXeVjiGHDhpHbbrtNse26664jo0aNIoTwdo4WagEmWu36r3/9i6Smpir6jsmTJ5MOHTrUqr7chGSSmpoaFBcXo6CgILhNFEUUFBRgzZo1DViz2ObUqVMAgCZNmgAAiouL4fF4FO3csWNH5OTkBNt5zZo16Nq1KzIzM4NlBg8ejPLycvz000/1WPuzmwkTJmDYsGGKtgR4G0eTL7/8Erm5ubjhhhuQkZGBnj174u233w7u37t3L0pKShRtnZycjLy8PEVbp6SkIDc3N1imoKAAoiiiqKio/m7mLKZfv34oLCzErl27AABbtmzBqlWrMHToUAC8neuKaLXrmjVrcPHFF8PpdAbLDB48GDt37sTJkycjrt85u5hjtDl+/Dh8Pp+iQweAzMxM/PLLLw1Uq9jG7/dj0qRJ6N+/P7p06QIAKCkpgdPpREpKiqJsZmYmSkpKgmVYv4O0jwPMmzcPGzduxPr16zX7eBtHj99++w2vv/46HnroITzxxBNYv3497r//fjidTowdOzbYVqy2lLd1RkaGYr/dbkeTJk14WweYMmUKysvL0bFjR9hsNvh8PkydOhWjRo0CAN7OdUS02rWkpARt2rTRnEPal5qaGlH9uADDaTAmTJiA7du3Y9WqVQ1dlXOKAwcO4IEHHsCyZcsQFxfX0NU5p/H7/cjNzcXzzz8PAOjZsye2b9+ON954A2PHjm3g2p07zJ8/H3PnzsXHH3+MCy64AJs3b8akSZPQvHlz3s5/YrgJySTp6emw2WyaSI0jR44gKyurgWoVu0ycOBGLFy/GihUr0LJly+D2rKws1NTUoKysTFFe3s5ZWVnM30Ha92enuLgYR48eRa9evWC322G327Fy5UrMnDkTdrsdmZmZvI2jRLNmzdC5c2fFtk6dOmH//v0AQm1l1G9kZWXh6NGjiv1erxelpaW8rQM8+uijmDJlCm666SZ07doVY8aMwYMPPohp06YB4O1cV0SrXeuqP+ECjEmcTid69+6NwsLC4Da/34/CwkLk5+c3YM1iC0IIJk6ciIULF2L58uUatWLv3r3hcDgU7bxz507s378/2M75+fnYtm2b4qVZtmwZkpKSNIPJn5GBAwdi27Zt2Lx5c/AvNzcXo0aNCn7mbRwd+vfvr0kDsGvXLrRq1QoA0KZNG2RlZSnaury8HEVFRYq2LisrQ3FxcbDM8uXL4ff7kZeXVw93cfZTWVkJUVQOVzabDX6/HwBv57oiWu2an5+P77//Hh6PJ1hm2bJl6NChQ8TmIwA8jNoK8+bNIy6Xi7z33ntkx44d5K677iIpKSmKSA2OMffccw9JTk4m3333HTl8+HDwr7KyMlhm/PjxJCcnhyxfvpxs2LCB5Ofnk/z8/OB+KcR30KBBZPPmzWTJkiWkadOmPMTXAHkUEiG8jaPFunXriN1uJ1OnTiW7d+8mc+fOJQkJCeSjjz4Klpk+fTpJSUkhX3zxBdm6dSu5+uqrmWGoPXv2JEVFRWTVqlXk/PPP/9OH98oZO3YsadGiRTCM+vPPPyfp6enkscceC5bh7RwZFRUVZNOmTWTTpk0EAHnllVfIpk2byL59+wgh0WnXsrIykpmZScaMGUO2b99O5s2bRxISEngYdX0za9YskpOTQ5xOJ+nbty9Zu3ZtQ1cppgDA/JszZ06wTFVVFbn33ntJamoqSUhIINdeey05fPiw4jy///47GTp0KImPjyfp6enk4YcfJh6Pp57vJnZQCzC8jaPHV199Rbp06UJcLhfp2LEjeeuttxT7/X4/efrpp0lmZiZxuVxk4MCBZOfOnYoyJ06cICNHjiSJiYkkKSmJjBs3jlRUVNTnbZzVlJeXkwceeIDk5OSQuLg40rZtW/Lkk08qwnJ5O0fGihUrmH3y2LFjCSHRa9ctW7aQAQMGEJfLRVq0aEGmT59e67oLhMhSGXI4HA6Hw+HEANwHhsPhcDgcTszBBRgOh8PhcDgxBxdgOBwOh8PhxBxcgOFwOBwOhxNzcAGGw+FwOBxOzMEFGA6Hw+FwODEHF2A4HA6Hw+HEHFyA4XA4HA6HE3NwAYbD4XA4HE7MwQUYDofD4XA4MQcXYDgcDofD4cQcXIDhcDgcDocTc/w/pTztsxX2GeUAAAAASUVORK5CYII=", - "text/plain": "
" + "text/plain": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -260,16 +274,20 @@ "draft_array = np.random.random(len(time_array)) * 10\n", "\n", "timeseries_result = TimeSeriesResult()\n", - "for time, propulsion_power, auxiliary_power in zip(time_array, propulsion_power_array, auxiliary_power_array):\n", - " timeseries_result.propulsion_power_timeseries.append(PropulsionPowerInstance(\n", - " epoch_s=time,\n", - " propulsion_power_kw=propulsion_power,\n", - " auxiliary_power_kw=auxiliary_power\n", - " ))\n", + "for time, propulsion_power, auxiliary_power in zip(\n", + " time_array, propulsion_power_array, auxiliary_power_array\n", + "):\n", + " timeseries_result.propulsion_power_timeseries.append(\n", + " PropulsionPowerInstance(\n", + " epoch_s=time,\n", + " propulsion_power_kw=propulsion_power,\n", + " auxiliary_power_kw=auxiliary_power,\n", + " )\n", + " )\n", " if random.random() > 0.9:\n", - " timeseries_result.operation_profile.append(OperationProfilePoint(\n", - " epoch_s=time, speed_kn=speed_kn, draft_m=draft_m\n", - " ))\n", + " timeseries_result.operation_profile.append(\n", + " OperationProfilePoint(epoch_s=time, speed_kn=speed_kn, draft_m=draft_m)\n", + " )\n", "\n", "with open(\"timeseries_test_.sim\", \"wb\") as file:\n", " file.write(timeseries_result.SerializeToString())\n", @@ -282,9 +300,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [] } diff --git a/machinery-system-structure/MachSysS/convert_feems_result_to_proto.py b/machinery-system-structure/MachSysS/convert_feems_result_to_proto.py index 9db823f..cefbb7b 100644 --- a/machinery-system-structure/MachSysS/convert_feems_result_to_proto.py +++ b/machinery-system-structure/MachSysS/convert_feems_result_to_proto.py @@ -1,7 +1,7 @@ # AUTOGENERATED! DO NOT EDIT! File to edit: ../03_ConvertFEEMSResultToProto.ipynb. # %% auto 0 -__all__ = ['logger', 'ch', 'formatter', 'FEEMSResultConverter'] +__all__ = ["logger", "ch", "formatter", "FEEMSResultConverter"] # %% ../03_ConvertFEEMSResultToProto.ipynb 3 from functools import cached_property @@ -15,7 +15,7 @@ ElectricPowerSystem, HybridPropulsionSystem, MechanicalPropulsionSystem, - FEEMSResultForMachinerySystem + FEEMSResultForMachinerySystem, ) import pandas as pd import numpy as np @@ -31,7 +31,7 @@ ch = logging.StreamHandler() ch.setLevel(logging.INFO) -formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") ch.setFormatter(formatter) logger.addHandler(ch) @@ -61,15 +61,13 @@ class FEEMSResultConverter: MechanicalPropulsionSystemWithElectricPowerSystem, ElectricPowerSystem, HybridPropulsionSystem, - None + None, ] = None _time_series_data_for_electric_component: Union[ - List[Dict[str, proto.TimeSeriesResultForComponent]], - None + List[Dict[str, proto.TimeSeriesResultForComponent]], None ] = None _time_series_data_for_mechanical_component: Union[ - List[Dict[str, proto.TimeSeriesResultForComponent]], - None + List[Dict[str, proto.TimeSeriesResultForComponent]], None ] = None def __init__( @@ -104,11 +102,17 @@ def isSystemElectric(self) -> bool: @property def electric_system(self) -> ElectricPowerSystem: - return self.system_feems if self.isSystemElectric else self.system_feems.electric_system + return ( + self.system_feems + if self.isSystemElectric + else self.system_feems.electric_system + ) @property def mechanical_system(self) -> MechanicalPropulsionSystem: - return self.system_feems.mechanical_system if not self.isSystemElectric else None + return ( + self.system_feems.mechanical_system if not self.isSystemElectric else None + ) @cached_property def _time_interval_to_time_array(self) -> np.ndarray: @@ -116,14 +120,18 @@ def _time_interval_to_time_array(self) -> np.ndarray: if self.time_series_input is None: time_interval_s = self.electric_system.time_interval_s if np.isscalar(time_interval_s): - return np.linspace(0, (number_points - 1) * time_interval_s, number_points) + return np.linspace( + 0, (number_points - 1) * time_interval_s, number_points + ) else: return time_interval_s.cumsum() else: - return np.array([ - power_instance.epoch_s - for power_instance in self.time_series_input.propulsion_power_timeseries - ])[:number_points] + return np.array( + [ + power_instance.epoch_s + for power_instance in self.time_series_input.propulsion_power_timeseries + ] + )[:number_points] def _retrieve_time_series_data_from_components(self): """Retrieve time series data from components of power sources and energy storages and @@ -131,9 +139,11 @@ def _retrieve_time_series_data_from_components(self): the data in the proto data type of TimeSeriesResultForComponent and the switchboard id. """ # in the feems result - power_sources_electric = self.electric_system.power_sources \ - + self.electric_system.energy_storage \ - + self.electric_system.pti_pto + power_sources_electric = ( + self.electric_system.power_sources + + self.electric_system.energy_storage + + self.electric_system.pti_pto + ) if self.mechanical_system is not None: power_sources_mechanical = self.mechanical_system.main_engines else: @@ -145,8 +155,10 @@ def _retrieve_time_series_data_from_components(self): power_output_kw=power_source.power_output.tolist(), ) if power_source.type == TypeComponent.GENSET: - genset_result = power_source.get_fuel_cons_load_bsfc_from_power_out_generator_kw( - fuel_specified_by=self.fuel_specified_by, + genset_result = ( + power_source.get_fuel_cons_load_bsfc_from_power_out_generator_kw( + fuel_specified_by=self.fuel_specified_by, + ) ) for fuel in genset_result.engine.fuel_flow_rate_kg_per_s.fuels: result_proto.fuel_consumption_kg_per_s.fuels.append( @@ -158,9 +170,14 @@ def _retrieve_time_series_data_from_components(self): lhv_mj_per_g=fuel.lhv_mj_per_g, ) ) - elif power_source.type in [TypeComponent.FUEL_CELL_SYSTEM, TypeComponent.FUEL_CELL]: + elif power_source.type in [ + TypeComponent.FUEL_CELL_SYSTEM, + TypeComponent.FUEL_CELL, + ]: power_source = cast(FuelCellSystem, power_source) - fuel_cell_result = power_source.get_fuel_cell_run_point(power_source.power_output) + fuel_cell_result = power_source.get_fuel_cell_run_point( + power_source.power_output + ) for fuel in fuel_cell_result.fuel_flow_rate_kg_per_s.fuels: result_proto.fuel_consumption_kg_per_s.fuels.append( proto.FuelArray( @@ -171,7 +188,10 @@ def _retrieve_time_series_data_from_components(self): lhv_mj_per_g=fuel.lhv_mj_per_g, ) ) - elif power_source.type in [TypeComponent.BATTERY, TypeComponent.BATTERY_SYSTEM]: + elif power_source.type in [ + TypeComponent.BATTERY, + TypeComponent.BATTERY_SYSTEM, + ]: pass elif power_source.type == [TypeComponent.PTI_PTO_SYSTEM]: pass @@ -213,11 +233,11 @@ def _retrieve_time_series_data_from_components(self): ) def _get_feems_result_proto_for_subsystem( - self, - feems_result: FEEMSResult, - feems_system: Union[ElectricPowerSystem, MechanicalPropulsionSystem], - include_time_series_for_components: bool = False, - verbose: bool = False + self, + feems_result: FEEMSResult, + feems_system: Union[ElectricPowerSystem, MechanicalPropulsionSystem], + include_time_series_for_components: bool = False, + verbose: bool = False, ) -> proto.FeemsResult: """Convert the result of FEEMS calculation to the proto data type of FeemsResult. Args: @@ -234,8 +254,11 @@ def _get_feems_result_proto_for_subsystem( ) if include_time_series_for_components: self._retrieve_time_series_data_from_components() - time_series_data = self._time_series_data_for_electric_component if is_electric \ + time_series_data = ( + self._time_series_data_for_electric_component + if is_electric else self._time_series_data_for_mechanical_component + ) else: time_series_data = None result = proto.FeemsResult() @@ -265,14 +288,22 @@ def _get_feems_result_proto_for_subsystem( logger.warning(f"Value for {key} is None.") else: if verbose: - logger.warning(f"There is no matching key in Protobuf message for {key}") + logger.warning( + f"There is no matching key in Protobuf message for {key}" + ) if feems_result.detail_result is not None: - for component_name, component_result in feems_result.detail_result.iterrows(): - result_per_component = proto.ResultPerComponent(component_name=component_name) + for ( + component_name, + component_result, + ) in feems_result.detail_result.iterrows(): + result_per_component = proto.ResultPerComponent( + component_name=component_name + ) for key, value in component_result.items(): key_result_per_component = _COLUMN_NAMES.get(key) - if hasattr(result_per_component, key_result_per_component) \ - or result_per_component.HasField(key_result_per_component): + if hasattr( + result_per_component, key_result_per_component + ) or result_per_component.HasField(key_result_per_component): if key_result_per_component == "multi_fuel_consumption_kg": for fuel in value.fuels: result_per_component.multi_fuel_consumption_kg.fuels.append( @@ -286,7 +317,9 @@ def _get_feems_result_proto_for_subsystem( ) continue if value is not None: - setattr(result_per_component, key_result_per_component, value) + setattr( + result_per_component, key_result_per_component, value + ) else: if verbose: logger.warning(f"Value for {key} is None.") @@ -313,19 +346,19 @@ def _get_feems_result_proto_for_subsystem( time_series_item["node_id"] == switchboard_shaft_line_id ), - time_series_data + time_series_data, ) ).get("data") ) except StopIteration: - logger.warning(f"No time-series data found for {component_name}") + logger.warning( + f"No time-series data found for {component_name}" + ) result.detailed_result.append(result_per_component) return result def get_feems_result_proto( - self, - include_time_series_for_components: bool = False, - verbose: bool = False + self, include_time_series_for_components: bool = False, verbose: bool = False ) -> proto.FeemsResultForMachinerySystem: if self.isSystemElectric: feems_result_electric = self._get_feems_result_proto_for_subsystem( @@ -369,5 +402,7 @@ def get_timeseries_for_power_sources_and_energy_storage(self): data = each_time_series["data"] df[f"{name}-power_output_kw"] = list(data.power_output_kw) if len(data.fuel_consumption_kg_per_s) > 0: - df[f"{name}-fuel_consumption_kg_per_s"] = list(data.fuel_consumption_kg_per_s) + df[f"{name}-fuel_consumption_kg_per_s"] = list( + data.fuel_consumption_kg_per_s + ) return df diff --git a/machinery-system-structure/MachSysS/convert_gymir_result_to_proto.py b/machinery-system-structure/MachSysS/convert_gymir_result_to_proto.py index 5f52286..37b27b5 100644 --- a/machinery-system-structure/MachSysS/convert_gymir_result_to_proto.py +++ b/machinery-system-structure/MachSysS/convert_gymir_result_to_proto.py @@ -1,8 +1,15 @@ # AUTOGENERATED! DO NOT EDIT! File to edit: ../04_ConvertGymirResultToProto.ipynb. # %% auto 0 -__all__ = ['logger', 'ch', 'formatter', 'vocabulary', 'find_csv_name_from_message_field_name', - 'get_message_type_for_simulation_instance', 'GymirResultConverter'] +__all__ = [ + "logger", + "ch", + "formatter", + "vocabulary", + "find_csv_name_from_message_field_name", + "get_message_type_for_simulation_instance", + "GymirResultConverter", +] # %% ../04_ConvertGymirResultToProto.ipynb 3 from io import BytesIO @@ -20,51 +27,51 @@ ch = logging.StreamHandler() ch.setLevel(logging.INFO) -formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") ch.setFormatter(formatter) logger.addHandler(ch) vocabulary = { - 'task': 'task_type', - 'assignment': 'task_name', - 'latitude': 'latitude_deg', - 'longitude': 'longitude_deg', - 'heading': 'heading_deg', - 'wave height significant': 'wave_height_significant_m', - 'wave peak period (tp)': 'wave_peak_period_s', - 'wave direction in degrees relative to geographic north': 'wave_dir_rel_north_deg', - 'wave direction in degrees relative to vessel heading': 'wave_dir_rel_vessel_deg', - 'wind speed in meter per sec': 'wind_speed_mps', - 'wind direction in degrees relative to geographic north': 'wind_dir_rel_north_deg', - 'wind direction in degrees relative to vessel heading': 'wind_dir_rel_vessel_deg', - 'speed over ground': 'speed_over_ground_kn', - 'speed': 'speed_over_ground_kn', - 'speed through water': 'speed_through_water_kn', - 'sea current speed in meter pr sec': 'current_speed_mps', - 'sea current direction in degrees relative to geographic north': 'current_dir_rel_north_deg', - 'power': 'power_kw', - 'torque': 'torque_k_nm', - 'thrust': 'thrust_k_n', - 'rtot': 'total_resistance_k_n', - 'weather source': 'weather_source', + "task": "task_type", + "assignment": "task_name", + "latitude": "latitude_deg", + "longitude": "longitude_deg", + "heading": "heading_deg", + "wave height significant": "wave_height_significant_m", + "wave peak period (tp)": "wave_peak_period_s", + "wave direction in degrees relative to geographic north": "wave_dir_rel_north_deg", + "wave direction in degrees relative to vessel heading": "wave_dir_rel_vessel_deg", + "wind speed in meter per sec": "wind_speed_mps", + "wind direction in degrees relative to geographic north": "wind_dir_rel_north_deg", + "wind direction in degrees relative to vessel heading": "wind_dir_rel_vessel_deg", + "speed over ground": "speed_over_ground_kn", + "speed": "speed_over_ground_kn", + "speed through water": "speed_through_water_kn", + "sea current speed in meter pr sec": "current_speed_mps", + "sea current direction in degrees relative to geographic north": "current_dir_rel_north_deg", + "power": "power_kw", + "torque": "torque_k_nm", + "thrust": "thrust_k_n", + "rtot": "total_resistance_k_n", + "weather source": "weather_source", } + def find_csv_name_from_message_field_name(name: str) -> Union[str, None]: try: - return next(filter( - lambda key: vocabulary.get(key) == name, - vocabulary - )) + return next(filter(lambda key: vocabulary.get(key) == name, vocabulary)) except StopIteration: return None + def get_message_type_for_simulation_instance(field_name: str) -> Union[str, None]: fields = proto.SimulationInstance.DESCRIPTOR.fields_by_name field = fields.get(field_name, None) if field is not None: return field.message_type if field.message_type is not None else field.type + class GymirResultConverter: gymir_result: Union[proto.GymirResult, None] = None @@ -72,7 +79,7 @@ def __init__( self, *, file: Union[str, BytesIO] = None, - gymir_result: Union[proto.GymirResult, None] = None + gymir_result: Union[proto.GymirResult, None] = None, ): if file is not None: self.gymir_result = proto.GymirResult() @@ -100,11 +107,12 @@ def to_csv(self, filename: str): if value is not None: file.write(f"{epoch_s},{csv_name},{value}\n") - def read_csv(self, file: Union[str, BytesIO], auxiliary_load_kw: float = 0, name: str = None): + def read_csv( + self, file: Union[str, BytesIO], auxiliary_load_kw: float = 0, name: str = None + ): df = pd.read_csv(file, header=None) self.gymir_result = proto.GymirResult( - auxiliary_load_kw=auxiliary_load_kw, - name=name + auxiliary_load_kw=auxiliary_load_kw, name=name ) epoch_s = 0 current_simulation_instance = proto.SimulationInstance() @@ -113,9 +121,7 @@ def read_csv(self, file: Union[str, BytesIO], auxiliary_load_kw: float = 0, name if epoch_s != 0: self.gymir_result.result.append(current_simulation_instance) epoch_s = row[0] - current_simulation_instance = proto.SimulationInstance( - epoch_s=epoch_s - ) + current_simulation_instance = proto.SimulationInstance(epoch_s=epoch_s) field_name = vocabulary.get(row[1]) if field_name is None: logger.warning(f"No field name found for {row[1]}") @@ -128,7 +134,7 @@ def read_csv(self, file: Union[str, BytesIO], auxiliary_load_kw: float = 0, name FieldDescriptor.TYPE_INT32, FieldDescriptor.TYPE_INT64, FieldDescriptor.TYPE_UINT32, - FieldDescriptor.TYPE_UINT64 + FieldDescriptor.TYPE_UINT64, ]: value = int(value) elif value_type == FieldDescriptor.TYPE_BOOL: diff --git a/machinery-system-structure/MachSysS/convert_proto_timeseries.py b/machinery-system-structure/MachSysS/convert_proto_timeseries.py index 8819c4a..6bc1b7b 100644 --- a/machinery-system-structure/MachSysS/convert_proto_timeseries.py +++ b/machinery-system-structure/MachSysS/convert_proto_timeseries.py @@ -1,7 +1,13 @@ # AUTOGENERATED! DO NOT EDIT! File to edit: ../05_ConvertTimeSeriesResultProtoToPandas.ipynb. # %% auto 0 -__all__ = ['logger', 'ch', 'formatter', 'convert_proto_timeseries_to_pd_series', 'convert_proto_timeseries_to_pd_dataframe'] +__all__ = [ + "logger", + "ch", + "formatter", + "convert_proto_timeseries_to_pd_series", + "convert_proto_timeseries_to_pd_dataframe", +] # %% ../05_ConvertTimeSeriesResultProtoToPandas.ipynb 3 import pandas as pd @@ -23,27 +29,40 @@ logger.addHandler(ch) -def convert_proto_timeseries_to_pd_series(proto_timeseries: proto.TimeSeriesResult) -> pd.Series: +def convert_proto_timeseries_to_pd_series( + proto_timeseries: proto.TimeSeriesResult, +) -> pd.Series: """Convert a TimeSeriesResult proto message to a pandas Series for propulsion power""" time = map(lambda each: each.epoch_s, proto_timeseries.propulsion_power_timeseries) propulsion_power = map( - lambda each: each.propulsion_power_kw, proto_timeseries.propulsion_power_timeseries + lambda each: each.propulsion_power_kw, + proto_timeseries.propulsion_power_timeseries, ) return pd.Series(index=time, data=propulsion_power) -def convert_proto_timeseries_to_pd_dataframe(proto_timeseries: proto.TimeSeriesResult) -> pd.DataFrame: +def convert_proto_timeseries_to_pd_dataframe( + proto_timeseries: proto.TimeSeriesResult, +) -> pd.DataFrame: """ Convert a TimeSeriesResult proto message to a pandas DataFrame for propulsion and auxiliary power and other operational parameters such as speed and draft """ - time = list(map(lambda each: each.epoch_s, proto_timeseries.propulsion_power_timeseries)) - propulsion_power = list(map( - lambda each: each.propulsion_power_kw, proto_timeseries.propulsion_power_timeseries - )) - auxiliary_power = list(map( - lambda each: each.auxiliary_power_kw, proto_timeseries.propulsion_power_timeseries - )) + time = list( + map(lambda each: each.epoch_s, proto_timeseries.propulsion_power_timeseries) + ) + propulsion_power = list( + map( + lambda each: each.propulsion_power_kw, + proto_timeseries.propulsion_power_timeseries, + ) + ) + auxiliary_power = list( + map( + lambda each: each.auxiliary_power_kw, + proto_timeseries.propulsion_power_timeseries, + ) + ) if (np.array(auxiliary_power) == 0).all(): auxiliary_power = [proto_timeseries.auxiliary_power_kw] * len(time) df = pd.DataFrame( @@ -51,18 +70,18 @@ def convert_proto_timeseries_to_pd_dataframe(proto_timeseries: proto.TimeSeriesR data=dict( propulsion_power_kw=propulsion_power, auxiliary_power_kw=auxiliary_power, - ) + ), ) if len(proto_timeseries.operation_profile) > 0: - time_operation_profile = list(map( - lambda each: each.epoch_s, proto_timeseries.operation_profile - )) - speed_array = np.array(list(map( - lambda each: each.speed_kn, proto_timeseries.operation_profile - ))) - draft_array = np.array(list(map( - lambda each: each.draft_m, proto_timeseries.operation_profile - ))) + time_operation_profile = list( + map(lambda each: each.epoch_s, proto_timeseries.operation_profile) + ) + speed_array = np.array( + list(map(lambda each: each.speed_kn, proto_timeseries.operation_profile)) + ) + draft_array = np.array( + list(map(lambda each: each.draft_m, proto_timeseries.operation_profile)) + ) if time_operation_profile != time: logger.warning( diff --git a/machinery-system-structure/MachSysS/convert_to_feems.py b/machinery-system-structure/MachSysS/convert_to_feems.py index 79c2962..031f40e 100644 --- a/machinery-system-structure/MachSysS/convert_to_feems.py +++ b/machinery-system-structure/MachSysS/convert_to_feems.py @@ -143,7 +143,9 @@ def convert_proto_fuel_cell_system_to_feems( fuel_cell = FuelCell( name=subsystem.fuel_cell.name, rated_power=subsystem.fuel_cell.rated_power_kw, - eff_curve=convert_proto_efficiency_bsfc_to_np_array(subsystem.fuel_cell.efficiency), + eff_curve=convert_proto_efficiency_bsfc_to_np_array( + subsystem.fuel_cell.efficiency + ), fuel_type=TypeFuel(subsystem.fuel_cell.fuel.fuel_type), fuel_origin=FuelOrigin(subsystem.fuel_cell.fuel.fuel_origin), ) @@ -180,13 +182,16 @@ def convert_nox_calculation_method(proto_engine: proto.Engine) -> NOxCalculation """Converts protobuf nox calculation type to feems nox calculation method""" nox_calculation_method = NOxCalculationMethod.TIER_2 if proto_engine.nox_calculation_method is not None: - name = proto.Engine.NOxCalculationMethod.Name(proto_engine.nox_calculation_method) + name = proto.Engine.NOxCalculationMethod.Name( + proto_engine.nox_calculation_method + ) nox_calculation_method = NOxCalculationMethod[name] return nox_calculation_method def convert_proto_engine_to_feems( - proto_engine: proto.Engine, type_engine: TypeComponent = TypeComponent.AUXILIARY_ENGINE + proto_engine: proto.Engine, + type_engine: TypeComponent = TypeComponent.AUXILIARY_ENGINE, ) -> Engine: """Converts protobuf engine message to feems engine component""" nox_calculation_method = convert_nox_calculation_method(proto_engine) @@ -205,7 +210,9 @@ def convert_proto_engine_to_feems( rated_power=proto_engine.rated_power_kw, rated_speed=proto_engine.rated_speed_rpm, bsfc_curve=convert_proto_efficiency_bsfc_to_np_array(proto_engine.bsfc), - bspfc_curve=convert_proto_efficiency_bsfc_to_np_array(proto_engine.pilot_bsfc), + bspfc_curve=convert_proto_efficiency_bsfc_to_np_array( + proto_engine.pilot_bsfc + ), fuel_type=TypeFuel(proto_engine.main_fuel.fuel_type), fuel_origin=FuelOrigin(proto_engine.main_fuel.fuel_origin), pilot_fuel_type=TypeFuel(proto_engine.pilot_fuel.fuel_type), @@ -226,7 +233,9 @@ def convert_proto_engine_to_feems( ) -def convert_proto_genset_to_feems(subsystem: proto.Subsystem, switchboard_id: int) -> Genset: +def convert_proto_genset_to_feems( + subsystem: proto.Subsystem, switchboard_id: int +) -> Genset: """Converts protobuf subsystem message to feems component""" engine = convert_proto_engine_to_feems(proto_engine=subsystem.engine) generator = convert_proto_electric_machine_to_feems( @@ -243,7 +252,9 @@ def convert_proto_genset_to_feems(subsystem: proto.Subsystem, switchboard_id: in power_type=TypePower.POWER_TRANSMISSION, switchboard_id=switchboard_id, ) - return Genset(name=subsystem.name, aux_engine=engine, generator=generator, rectifier=rectifier) + return Genset( + name=subsystem.name, aux_engine=engine, generator=generator, rectifier=rectifier + ) def convert_proto_battery_to_feems( @@ -274,7 +285,10 @@ def convert_proto_battery_system_to_feems( power_type=TypePower.POWER_TRANSMISSION, ) return BatterySystem( - name=subsystem.name, battery=battery, converter=converter, switchboard_id=switchboard_id + name=subsystem.name, + battery=battery, + converter=converter, + switchboard_id=switchboard_id, ) @@ -330,7 +344,9 @@ def collect_electric_components_from_sub_system( ] return sorted( components, - key=lambda component: component.get("proto_component").order_from_switchboard_or_shaftline, + key=lambda component: component.get( + "proto_component" + ).order_from_switchboard_or_shaftline, ) @@ -412,7 +428,9 @@ def convert_proto_serial_subsystem_to_feems( components=components_feems, switchboard_id=switchboard_id, rated_power=None if subsystem.rated_power_kw == 0 else subsystem.rated_power_kw, - rated_speed=None if subsystem.rated_speed_rpm == 0 else subsystem.rated_speed_rpm, + rated_speed=( + None if subsystem.rated_speed_rpm == 0 else subsystem.rated_speed_rpm + ), ) @@ -454,7 +472,9 @@ def convert_proto_switchboard_to_feems(switchboard: proto.Switchboard) -> Switch ) elif subsystem.component_type == proto.Subsystem.ComponentType.GENSET: components.append( - convert_proto_genset_to_feems(subsystem=subsystem, switchboard_id=switchboard_id) + convert_proto_genset_to_feems( + subsystem=subsystem, switchboard_id=switchboard_id + ) ) elif subsystem.component_type == proto.Subsystem.ComponentType.BATTERY_SYSTEM: components.append( @@ -468,7 +488,10 @@ def convert_proto_switchboard_to_feems(switchboard: proto.Switchboard) -> Switch proto_component=subsystem.battery, switchboard_id=switchboard_id ) ) - elif subsystem.component_type == proto.Subsystem.ComponentType.SUPERCAPACITOR_SYSTEM: + elif ( + subsystem.component_type + == proto.Subsystem.ComponentType.SUPERCAPACITOR_SYSTEM + ): components.append( convert_proto_supercapacitor_system_to_feems( subsystem=subsystem, switchboard_id=switchboard_id @@ -477,7 +500,8 @@ def convert_proto_switchboard_to_feems(switchboard: proto.Switchboard) -> Switch elif subsystem.component_type == proto.Subsystem.ComponentType.SUPERCAPACITOR: components.append( convert_proto_supercapacitor_to_feems( - proto_component=subsystem.supercapacitor, switchboard_id=switchboard_id + proto_component=subsystem.supercapacitor, + switchboard_id=switchboard_id, ) ) else: @@ -508,12 +532,16 @@ def convert_proto_shaftline_to_feems( MainEngineForMechanicalPropulsion( name=sub_system.name, engine=convert_proto_engine_to_feems( - proto_engine=sub_system.engine, type_engine=TypeComponent.MAIN_ENGINE + proto_engine=sub_system.engine, + type_engine=TypeComponent.MAIN_ENGINE, ), shaft_line_id=shaft_line_id, ) ) - elif sub_system.component_type == proto.Subsystem.ComponentType.MAIN_ENGINE_WITH_GEARBOX: + elif ( + sub_system.component_type + == proto.Subsystem.ComponentType.MAIN_ENGINE_WITH_GEARBOX + ): components.append( MainEngineWithGearBoxForMechanicalPropulsion( name=sub_system.name, @@ -538,20 +566,28 @@ def convert_proto_shaftline_to_feems( if pti_ptos is None: components.append( convert_proto_pti_pto_subsystem_to_feems( - subsystem=sub_system, switchboard_id=1, shaft_line_id=shaft_line_id + subsystem=sub_system, + switchboard_id=1, + shaft_line_id=shaft_line_id, ) ) else: try: pti_pto = next( - filter(lambda pti_pto: pti_pto.name == sub_system.name, pti_ptos) + filter( + lambda pti_pto: pti_pto.name == sub_system.name, pti_ptos + ) ) except StopIteration as e: - print(f"PTI/PTO {sub_system.name} not found in pti_ptos given as argument.") + print( + f"PTI/PTO {sub_system.name} not found in pti_ptos given as argument." + ) print("Creating a new PTI/PTO from the proto definition.") components.append( convert_proto_pti_pto_subsystem_to_feems( - subsystem=sub_system, switchboard_id=1, shaft_line_id=shaft_line_id + subsystem=sub_system, + switchboard_id=1, + shaft_line_id=shaft_line_id, ) ) else: @@ -601,7 +637,9 @@ def get_all_components(switchboard: Switchboard) -> List[Any]: switchboards, [], ) - bus_tie_connection = [(index + 1, index + 2) for index in range(len(switchboards) - 1)] + bus_tie_connection = [ + (index + 1, index + 2) for index in range(len(switchboards) - 1) + ] return ElectricPowerSystem( name="electric power system", power_plant_components=components, @@ -613,14 +651,18 @@ def convert_feems_shaftlines_to_feems_mechanical_propulsion_system( shaftlines: List[ShaftLine], ) -> MechanicalPropulsionSystem: - components = reduce(lambda acc, shaftline: [*acc, *shaftline.components], shaftlines, []) + components = reduce( + lambda acc, shaftline: [*acc, *shaftline.components], shaftlines, [] + ) return MechanicalPropulsionSystem( name="mechanical propulsion system", components_list=components, ) -def convert_proto_electric_system_to_feems(system: proto.ElectricSystem) -> ElectricPowerSystem: +def convert_proto_electric_system_to_feems( + system: proto.ElectricSystem, +) -> ElectricPowerSystem: switchboards = [ convert_proto_switchboard_to_feems(proto_switchboard) for proto_switchboard in system.switchboards @@ -636,7 +678,9 @@ def convert_proto_mechanical_system_to_feems( if pti_ptos is not None: pti_ptos_for_shaft_lines = list( filter( - lambda pti_pto: pti_pto.shaft_line_id == proto_shaftline.shaft_line_id, pti_ptos + lambda pti_pto: pti_pto.shaft_line_id + == proto_shaftline.shaft_line_id, + pti_ptos, ) ) else: @@ -646,7 +690,9 @@ def convert_proto_mechanical_system_to_feems( shaftline=proto_shaftline, pti_ptos=pti_ptos_for_shaft_lines ) ) - return convert_feems_shaftlines_to_feems_mechanical_propulsion_system(shaftlines=shaft_lines) + return convert_feems_shaftlines_to_feems_mechanical_propulsion_system( + shaftlines=shaft_lines + ) def convert_proto_propulsion_system_to_feems( @@ -660,8 +706,12 @@ def convert_proto_propulsion_system_to_feems( if system.propulsion_type == proto.MachinerySystem.PropulsionType.MECHANICAL: return MechanicalPropulsionSystemWithElectricPowerSystem( name=system.name, - electric_system=convert_proto_electric_system_to_feems(system.electric_system), - mechanical_system=convert_proto_mechanical_system_to_feems(system.mechanical_system), + electric_system=convert_proto_electric_system_to_feems( + system.electric_system + ), + mechanical_system=convert_proto_mechanical_system_to_feems( + system.mechanical_system + ), ) if system.propulsion_type == proto.MachinerySystem.PropulsionType.ELECTRIC: return convert_proto_electric_system_to_feems(system.electric_system) diff --git a/machinery-system-structure/MachSysS/convert_to_protobuf.py b/machinery-system-structure/MachSysS/convert_to_protobuf.py index beac0a3..1205e74 100644 --- a/machinery-system-structure/MachSysS/convert_to_protobuf.py +++ b/machinery-system-structure/MachSysS/convert_to_protobuf.py @@ -1,20 +1,35 @@ # AUTOGENERATED! DO NOT EDIT! File to edit: ../01_ConvertToProtobuf.ipynb. # %% auto 0 -__all__ = ['convert_efficiency_curve_to_protobuf', 'convert_bsfc_curve_to_protobuf', 'convert_electric_machine_to_protobuf', - 'convert_electric_component_to_protobuf', 'convert_battery_component_to_protobuf', - 'convert_supercapacitor_component_to_protobuf', 'convert_serial_electric_system_to_protobuf', - 'convert_nox_calculation_method_to_protobuf', 'convert_emission_curves_to_protobuf', - 'convert_engine_component_to_protobuf', 'convert_switchboard_to_protobuf', 'convert_shaftline_to_protobuf', - 'convert_electric_system_to_protobuf', 'convert_electric_system_to_protobuf_machinery_system', - 'convert_mechanical_system_to_protobuf', - 'convert_mechanical_propulsion_system_with_electric_system_to_protobuf', - 'convert_hybrid_propulsion_system_to_protobuf'] +__all__ = [ + "convert_efficiency_curve_to_protobuf", + "convert_bsfc_curve_to_protobuf", + "convert_electric_machine_to_protobuf", + "convert_electric_component_to_protobuf", + "convert_battery_component_to_protobuf", + "convert_supercapacitor_component_to_protobuf", + "convert_serial_electric_system_to_protobuf", + "convert_nox_calculation_method_to_protobuf", + "convert_emission_curves_to_protobuf", + "convert_engine_component_to_protobuf", + "convert_switchboard_to_protobuf", + "convert_shaftline_to_protobuf", + "convert_electric_system_to_protobuf", + "convert_electric_system_to_protobuf_machinery_system", + "convert_mechanical_system_to_protobuf", + "convert_mechanical_propulsion_system_with_electric_system_to_protobuf", + "convert_hybrid_propulsion_system_to_protobuf", +] # %% ../01_ConvertToProtobuf.ipynb 3 -from feems.components_model import Engine, Switchboard, ShaftLine, \ - MainEngineForMechanicalPropulsion, MechanicalPropulsionComponent, \ - MainEngineWithGearBoxForMechanicalPropulsion +from feems.components_model import ( + Engine, + Switchboard, + ShaftLine, + MainEngineForMechanicalPropulsion, + MechanicalPropulsionComponent, + MainEngineWithGearBoxForMechanicalPropulsion, +) from typing import cast, Union, List from feems.types_for_feems import TypeComponent, NOxCalculationMethod, EmissionCurve @@ -27,48 +42,64 @@ Battery, SuperCapacitorSystem, PTIPTO, - SuperCapacitor + SuperCapacitor, ) from feems.components_model.component_electric import SerialSystemElectric, Genset -from feems.system_model import ElectricPowerSystem, MechanicalPropulsionSystem, \ - MechanicalPropulsionSystemWithElectricPowerSystem, HybridPropulsionSystem +from feems.system_model import ( + ElectricPowerSystem, + MechanicalPropulsionSystem, + MechanicalPropulsionSystemWithElectricPowerSystem, + HybridPropulsionSystem, +) import MachSysS.system_structure_pb2 as proto -def convert_efficiency_curve_to_protobuf(component: ElectricComponent) -> proto.Efficiency: +def convert_efficiency_curve_to_protobuf( + component: ElectricComponent, +) -> proto.Efficiency: """Convert efficiency value or curve in the component to protobuf message""" efficiency = proto.Efficiency() if len(component._efficiency_points) == 1: efficiency.value = component._efficiency_points[0] else: - efficiency.curve.curve.points.extend([ - proto.Point(x=each_point[0], y=each_point[1]) - for each_point in component._efficiency_points - ]) + efficiency.curve.curve.points.extend( + [ + proto.Point(x=each_point[0], y=each_point[1]) + for each_point in component._efficiency_points + ] + ) efficiency.curve.x_label = "power load" efficiency.curve.y_label = "efficiency" return efficiency -def convert_bsfc_curve_to_protobuf(component: Union[Engine, EngineDualFuel], for_pilot_fuel: bool = False) -> proto.BSFC: +def convert_bsfc_curve_to_protobuf( + component: Union[Engine, EngineDualFuel], for_pilot_fuel: bool = False +) -> proto.BSFC: """Convert bsfc value or curve in the component to protobuf message""" bsfc = proto.BSFC() - bsfc_points = component.specific_fuel_consumption_points if not for_pilot_fuel else component.specific_pilot_fuel_consumption_points + bsfc_points = ( + component.specific_fuel_consumption_points + if not for_pilot_fuel + else component.specific_pilot_fuel_consumption_points + ) if len(bsfc_points) == 1: bsfc.value = bsfc_points[0] else: - bsfc.curve.curve.points.extend([ - proto.Point(x=each_point[0], y=each_point[1]) for each_point in bsfc_points - ]) + bsfc.curve.curve.points.extend( + [ + proto.Point(x=each_point[0], y=each_point[1]) + for each_point in bsfc_points + ] + ) bsfc.curve.x_label = "power load" bsfc.curve.y_label = "bsfc" return bsfc def convert_electric_machine_to_protobuf( - component: ElectricMachine, - order_from_switchboard: int = 1 + component: ElectricMachine, order_from_switchboard: int = 1 ) -> proto.ElectricMachine: """Convert elecrtic machine component of FEEMS to protobuf message""" return proto.ElectricMachine( @@ -76,26 +107,24 @@ def convert_electric_machine_to_protobuf( rated_power_kw=component.rated_power, rated_speed_rpm=component.rated_speed, efficiency=convert_efficiency_curve_to_protobuf(component), - order_from_switchboard_or_shaftline=order_from_switchboard + order_from_switchboard_or_shaftline=order_from_switchboard, ) def convert_electric_component_to_protobuf( - component: ElectricComponent, - order_from_switchboard: int = 1 + component: ElectricComponent, order_from_switchboard: int = 1 ) -> proto.ElectricMachine: """Convert converter component of FEEMS to protobuf message""" return proto.ElectricComponent( name=component.name, rated_power_kw=component.rated_power, efficiency=convert_efficiency_curve_to_protobuf(component), - order_from_switchboard_or_shaftline=order_from_switchboard + order_from_switchboard_or_shaftline=order_from_switchboard, ) def convert_battery_component_to_protobuf( - component: Battery, - order_from_switchboard: int = 1 + component: Battery, order_from_switchboard: int = 1 ) -> proto.ElectricMachine: """Convert battery component of FEEMS to protobuf message""" return proto.Battery( @@ -106,13 +135,12 @@ def convert_battery_component_to_protobuf( efficiency_charging=component.eff_charging, efficiency_discharging=component.eff_discharging, initial_state_of_charge=component.soc0, - order_from_switchboard_or_shaftline=order_from_switchboard + order_from_switchboard_or_shaftline=order_from_switchboard, ) def convert_supercapacitor_component_to_protobuf( - component: SuperCapacitor, - order_from_switchboard: int = 1 + component: SuperCapacitor, order_from_switchboard: int = 1 ) -> proto.ElectricMachine: """Convert converter component of FEEMS to protobuf message""" return proto.SuperCapacitor( @@ -122,50 +150,67 @@ def convert_supercapacitor_component_to_protobuf( efficiency_charging=component.eff_charging, efficiency_discharging=component.eff_discharging, initial_state_of_charge=component.soc0, - order_from_switchboard_or_shaftline=order_from_switchboard + order_from_switchboard_or_shaftline=order_from_switchboard, ) def convert_serial_electric_system_to_protobuf( component: Union[SerialSystemElectric, PTIPTO], - initial_order_from_switchboard: int = 1 + initial_order_from_switchboard: int = 1, ) -> proto.Subsystem: """Convert serial electric system or PTI/PTO component to protobuf message""" order = initial_order_from_switchboard subsystem = proto.Subsystem() for subcomponent in component.components: if subcomponent.type == TypeComponent.TRANSFORMER: - subsystem.transformer.CopyFrom(convert_electric_component_to_protobuf( - component=subcomponent, order_from_switchboard=order - )) - if subcomponent.type in [TypeComponent.POWER_CONVERTER, TypeComponent.INVERTER, TypeComponent.RECTIFIER, TypeComponent.ACTIVE_FRONT_END]: - if not subsystem.HasField('converter1'): - subsystem.converter1.CopyFrom(convert_electric_component_to_protobuf( + subsystem.transformer.CopyFrom( + convert_electric_component_to_protobuf( component=subcomponent, order_from_switchboard=order - )) + ) + ) + if subcomponent.type in [ + TypeComponent.POWER_CONVERTER, + TypeComponent.INVERTER, + TypeComponent.RECTIFIER, + TypeComponent.ACTIVE_FRONT_END, + ]: + if not subsystem.HasField("converter1"): + subsystem.converter1.CopyFrom( + convert_electric_component_to_protobuf( + component=subcomponent, order_from_switchboard=order + ) + ) else: - subsystem.converter2.CopyFrom(convert_electric_component_to_protobuf( - component=subcomponent, order_from_switchboard=order - )) + subsystem.converter2.CopyFrom( + convert_electric_component_to_protobuf( + component=subcomponent, order_from_switchboard=order + ) + ) if subcomponent.type in [ TypeComponent.SYNCHRONOUS_MACHINE, TypeComponent.INDUCTION_MACHINE, - TypeComponent.ELECTRIC_MOTOR + TypeComponent.ELECTRIC_MOTOR, ]: - subsystem.electric_machine.CopyFrom(convert_electric_machine_to_protobuf( - component=subcomponent, order_from_switchboard=order - )) + subsystem.electric_machine.CopyFrom( + convert_electric_machine_to_protobuf( + component=subcomponent, order_from_switchboard=order + ) + ) order += 1 return subsystem -def convert_nox_calculation_method_to_protobuf(nox_calculation_method_feems: NOxCalculationMethod) -> proto.Engine.NOxCalculationMethod: +def convert_nox_calculation_method_to_protobuf( + nox_calculation_method_feems: NOxCalculationMethod, +) -> proto.Engine.NOxCalculationMethod: """Convert nox calculation method of FEEMS to protobuf message""" index = proto.Engine.NOxCalculationMethod.Value(nox_calculation_method_feems.name) return index -def convert_emission_curves_to_protobuf(emission_curves_feems: List[EmissionCurve]) -> List[proto.EmissionCurve]: +def convert_emission_curves_to_protobuf( + emission_curves_feems: List[EmissionCurve], +) -> List[proto.EmissionCurve]: """Convert emission curves of FEEMS to protobuf message""" if emission_curves_feems is None: return [] @@ -175,11 +220,13 @@ def convert_emission_curves_to_protobuf(emission_curves_feems: List[EmissionCurv y_label="emission_g_per_kwh", curve=proto.Curve1D( points=[ - proto.Point(x=each_point.load_ratio, y=each_point.emission_g_per_kwh) + proto.Point( + x=each_point.load_ratio, y=each_point.emission_g_per_kwh + ) for each_point in each_curve.points_per_kwh ] ), - emission_type=proto.EmissionType.Value(each_curve.emission_type.value) + emission_type=proto.EmissionType.Value(each_curve.emission_type.value), ) for each_curve in emission_curves_feems ] @@ -187,7 +234,7 @@ def convert_emission_curves_to_protobuf(emission_curves_feems: List[EmissionCurv def convert_engine_component_to_protobuf( engine_feems: Union[Engine, EngineDualFuel], - order_from_shaftline_or_switchboard: int = 1 + order_from_shaftline_or_switchboard: int = 1, ) -> proto.Engine: """Convert engine component of FEEMS to protobuf message""" engine = proto.Engine( @@ -199,20 +246,30 @@ def convert_engine_component_to_protobuf( fuel_type=engine_feems.fuel_type.value, fuel_origin=engine_feems.fuel_origin.value, ), - nox_calculation_method=convert_nox_calculation_method_to_protobuf(engine_feems.nox_calculation_method), - emission_curves = convert_emission_curves_to_protobuf(engine_feems.emission_curves), - order_from_switchboard_or_shaftline=order_from_shaftline_or_switchboard + nox_calculation_method=convert_nox_calculation_method_to_protobuf( + engine_feems.nox_calculation_method + ), + emission_curves=convert_emission_curves_to_protobuf( + engine_feems.emission_curves + ), + order_from_switchboard_or_shaftline=order_from_shaftline_or_switchboard, ) if isinstance(engine_feems, EngineDualFuel): - engine.pilot_bsfc.CopyFrom(convert_bsfc_curve_to_protobuf(engine_feems, for_pilot_fuel=True)) - engine.pilot_fuel.CopyFrom(proto.Fuel( - fuel_type=engine_feems.pilot_fuel_type.value, - fuel_origin=engine_feems.pilot_fuel_origin.value, - )) + engine.pilot_bsfc.CopyFrom( + convert_bsfc_curve_to_protobuf(engine_feems, for_pilot_fuel=True) + ) + engine.pilot_fuel.CopyFrom( + proto.Fuel( + fuel_type=engine_feems.pilot_fuel_type.value, + fuel_origin=engine_feems.pilot_fuel_origin.value, + ) + ) return engine -def convert_switchboard_to_protobuf(switchboard_feems: Switchboard) -> proto.Switchboard: +def convert_switchboard_to_protobuf( + switchboard_feems: Switchboard, +) -> proto.Switchboard: switchboard_proto = proto.Switchboard() switchboard_proto.switchboard_id = switchboard_feems.id @@ -222,66 +279,91 @@ def convert_switchboard_to_protobuf(switchboard_feems: Switchboard) -> proto.Swi component_type=component.type.value, name=component.name, rated_power_kw=component.rated_power, - rated_speed_rpm=component.rated_speed + rated_speed_rpm=component.rated_speed, ) if component.type == TypeComponent.GENERATOR: - subsystem.electric_machine.CopyFrom(convert_electric_machine_to_protobuf( - component=component, - )) + subsystem.electric_machine.CopyFrom( + convert_electric_machine_to_protobuf( + component=component, + ) + ) elif component.type == TypeComponent.FUEL_CELL_SYSTEM: component = cast(FuelCellSystem, component) - subsystem.converter1.CopyFrom(convert_electric_component_to_protobuf( - component=component.converter - )) - subsystem.fuel_cell.CopyFrom(proto.FuelCell( - name=component.fuel_cell.name, - rated_power_kw=component.fuel_cell.rated_power, - efficiency=convert_efficiency_curve_to_protobuf(component.fuel_cell), - fuel=proto.Fuel( - fuel_type=component.fuel_cell.fuel_type.value, - fuel_origin=component.fuel_cell.fuel_origin.value, - ), - number_modules=component.number_modules, - order_from_switchboard_or_shaftline=2 - )) + subsystem.converter1.CopyFrom( + convert_electric_component_to_protobuf(component=component.converter) + ) + subsystem.fuel_cell.CopyFrom( + proto.FuelCell( + name=component.fuel_cell.name, + rated_power_kw=component.fuel_cell.rated_power, + efficiency=convert_efficiency_curve_to_protobuf( + component.fuel_cell + ), + fuel=proto.Fuel( + fuel_type=component.fuel_cell.fuel_type.value, + fuel_origin=component.fuel_cell.fuel_origin.value, + ), + number_modules=component.number_modules, + order_from_switchboard_or_shaftline=2, + ) + ) elif component.type == TypeComponent.GENSET: component = cast(Genset, component) - subsystem.electric_machine.CopyFrom(convert_electric_machine_to_protobuf( - component=component.generator, - )) - subsystem.engine.CopyFrom(convert_engine_component_to_protobuf( - engine_feems=component.aux_engine, - order_from_shaftline_or_switchboard=2 - )) + subsystem.electric_machine.CopyFrom( + convert_electric_machine_to_protobuf( + component=component.generator, + ) + ) + subsystem.engine.CopyFrom( + convert_engine_component_to_protobuf( + engine_feems=component.aux_engine, + order_from_shaftline_or_switchboard=2, + ) + ) elif component.type == TypeComponent.OTHER_LOAD: subsystem.other_load.CopyFrom( - convert_electric_component_to_protobuf(component=component)) - elif component.type in [TypeComponent.PTI_PTO_SYSTEM, TypeComponent.PROPULSION_DRIVE]: - subsystem.MergeFrom(convert_serial_electric_system_to_protobuf(component=component)) + convert_electric_component_to_protobuf(component=component) + ) + elif component.type in [ + TypeComponent.PTI_PTO_SYSTEM, + TypeComponent.PROPULSION_DRIVE, + ]: + subsystem.MergeFrom( + convert_serial_electric_system_to_protobuf(component=component) + ) elif component.type == TypeComponent.BATTERY_SYSTEM: component = cast(BatterySystem, component) - subsystem.converter1.CopyFrom(convert_electric_component_to_protobuf(component=component.converter)) - subsystem.battery.CopyFrom(convert_battery_component_to_protobuf( - component=component.battery, - order_from_switchboard=2 - )) + subsystem.converter1.CopyFrom( + convert_electric_component_to_protobuf(component=component.converter) + ) + subsystem.battery.CopyFrom( + convert_battery_component_to_protobuf( + component=component.battery, order_from_switchboard=2 + ) + ) elif component.type == TypeComponent.BATTERY: subsystem.battery.CopyFrom( - convert_battery_component_to_protobuf(component=component)) + convert_battery_component_to_protobuf(component=component) + ) elif component.type == TypeComponent.SUPERCAPACITOR_SYSTEM: component = cast(SuperCapacitorSystem, component) - subsystem.converter1.CopyFrom(convert_electric_component_to_protobuf(component=component.converter)) - subsystem.battery.CopyFrom(convert_supercapacitor_component_to_protobuf( - component=component.supercapacitor, - order_from_switchboard=2 - )) + subsystem.converter1.CopyFrom( + convert_electric_component_to_protobuf(component=component.converter) + ) + subsystem.battery.CopyFrom( + convert_supercapacitor_component_to_protobuf( + component=component.supercapacitor, order_from_switchboard=2 + ) + ) elif component.type == TypeComponent.SUPERCAPACITOR: subsystem.battery.CopyFrom( - convert_supercapacitor_component_to_protobuf(component=component)) + convert_supercapacitor_component_to_protobuf(component=component) + ) else: raise TypeError( f"The component type ({component.type.name}) is not a proper type for an electric " - f"system or the conversion for the type is not implemented.") + f"system or the conversion for the type is not implemented." + ) switchboard_proto.subsystems.append(subsystem) return switchboard_proto @@ -297,7 +379,7 @@ def convert_shaftline_to_protobuf(shaftline_feems: ShaftLine) -> proto.ShaftLine # The gear box is added to the protobuf message first. for gear in filter( lambda component: component.type == TypeComponent.GEARBOX, - shaftline_feems.components + shaftline_feems.components, ): gear = cast(MechanicalPropulsionComponent, gear) gear_proto = proto.Gear( @@ -314,14 +396,15 @@ def convert_shaftline_to_protobuf(shaftline_feems: ShaftLine) -> proto.ShaftLine component_type=component.type.value, name=component.name, rated_power_kw=component.rated_power, - rated_speed_rpm=component.rated_speed + rated_speed_rpm=component.rated_speed, ) if component.type == TypeComponent.MAIN_ENGINE: component = cast(MainEngineForMechanicalPropulsion, component) - subsystem.engine.CopyFrom(convert_engine_component_to_protobuf( - engine_feems=component.engine, - order_from_shaftline_or_switchboard=1 - )) + subsystem.engine.CopyFrom( + convert_engine_component_to_protobuf( + engine_feems=component.engine, order_from_shaftline_or_switchboard=1 + ) + ) elif component.type == TypeComponent.MAIN_ENGINE_WITH_GEARBOX: if gear_proto is not None: raise ValueError( @@ -330,40 +413,51 @@ def convert_shaftline_to_protobuf(shaftline_feems: ShaftLine) -> proto.ShaftLine f"component." ) component = cast(MainEngineWithGearBoxForMechanicalPropulsion, component) - subsystem.engine.CopyFrom(convert_engine_component_to_protobuf( - engine_feems=component.main_engine, - order_from_shaftline_or_switchboard=2 - )) - subsystem.gear.CopyFrom(proto.Gear( - name=component.gearbox.name, - rated_power_kw=component.gearbox.rated_power, - rated_speed_rpm=component.gearbox.rated_speed, - efficiency=convert_efficiency_curve_to_protobuf(component.gearbox), - order_from_switchboard_or_shaftline=1, - )) + subsystem.engine.CopyFrom( + convert_engine_component_to_protobuf( + engine_feems=component.main_engine, + order_from_shaftline_or_switchboard=2, + ) + ) + subsystem.gear.CopyFrom( + proto.Gear( + name=component.gearbox.name, + rated_power_kw=component.gearbox.rated_power, + rated_speed_rpm=component.gearbox.rated_speed, + efficiency=convert_efficiency_curve_to_protobuf(component.gearbox), + order_from_switchboard_or_shaftline=1, + ) + ) elif component.type == TypeComponent.PROPELLER_LOAD: if gear_proto is not None: subsystem.gear.CopyFrom(gear_proto) - subsystem.propeller.CopyFrom(proto.Propeller( - efficiency=convert_efficiency_curve_to_protobuf(component), - propulsor_id=propeller_id, - order_from_switchboard_or_shaftline=2, - )) + subsystem.propeller.CopyFrom( + proto.Propeller( + efficiency=convert_efficiency_curve_to_protobuf(component), + propulsor_id=propeller_id, + order_from_switchboard_or_shaftline=2, + ) + ) propeller_id += 1 elif component.type == TypeComponent.PTI_PTO_SYSTEM: - subsystem.MergeFrom(convert_serial_electric_system_to_protobuf(component=component)) + subsystem.MergeFrom( + convert_serial_electric_system_to_protobuf(component=component) + ) elif component.type == TypeComponent.GEARBOX: continue else: - raise ValueError(f"The shaftline contains a component ({component.name}) that has an " - f"imcompatible type ({component.type}) for conversion.") + raise ValueError( + f"The shaftline contains a component ({component.name}) that has an " + f"imcompatible type ({component.type}) for conversion." + ) shaftline_proto.subsystems.append(subsystem) return shaftline_proto # %% ../01_ConvertToProtobuf.ipynb 5 -def convert_electric_system_to_protobuf(electric_system: ElectricPowerSystem) \ - -> proto.ElectricSystem: +def convert_electric_system_to_protobuf( + electric_system: ElectricPowerSystem, +) -> proto.ElectricSystem: """Convert electric system to protobuf message""" return proto.ElectricSystem( switchboards=[ @@ -375,7 +469,7 @@ def convert_electric_system_to_protobuf(electric_system: ElectricPowerSystem) \ def convert_electric_system_to_protobuf_machinery_system( electric_system: ElectricPowerSystem, - maximum_allowed_genset_load_percentage: float = 80.0 + maximum_allowed_genset_load_percentage: float = 80.0, ) -> proto.MachinerySystem: """Convert electric system to protobuf message as a machinery system""" return proto.MachinerySystem( @@ -383,11 +477,12 @@ def convert_electric_system_to_protobuf_machinery_system( propulsion_type=proto.MachinerySystem.PropulsionType.ELECTRIC, fuel_storage=[], maximum_allowed_genset_load_percentage=maximum_allowed_genset_load_percentage, - electric_system=convert_electric_system_to_protobuf(electric_system) + electric_system=convert_electric_system_to_protobuf(electric_system), ) + def convert_mechanical_system_to_protobuf( - mechanical_propulsion_system: MechanicalPropulsionSystem + mechanical_propulsion_system: MechanicalPropulsionSystem, ) -> proto.MechanicalSystem: return proto.MechanicalSystem( shaft_lines=[ @@ -406,8 +501,12 @@ def convert_mechanical_propulsion_system_with_electric_system_to_protobuf( propulsion_type=proto.MachinerySystem.PropulsionType.MECHANICAL, fuel_storage=[], maximum_allowed_genset_load_percentage=maximum_allowed_genset_load_percentage, - mechanical_system=convert_mechanical_system_to_protobuf(system_feems.mechanical_system), - electric_system=convert_electric_system_to_protobuf(system_feems.electric_system) + mechanical_system=convert_mechanical_system_to_protobuf( + system_feems.mechanical_system + ), + electric_system=convert_electric_system_to_protobuf( + system_feems.electric_system + ), ) @@ -420,6 +519,10 @@ def convert_hybrid_propulsion_system_to_protobuf( propulsion_type=proto.MachinerySystem.HYBRID, fuel_storage=[], maximum_allowed_genset_load_percentage=maximum_allowed_genset_load_percentage, - mechanical_system=convert_mechanical_system_to_protobuf(system_feems.mechanical_system), - electric_system=convert_electric_system_to_protobuf(system_feems.electric_system) + mechanical_system=convert_mechanical_system_to_protobuf( + system_feems.mechanical_system + ), + electric_system=convert_electric_system_to_protobuf( + system_feems.electric_system + ), ) diff --git a/machinery-system-structure/MachSysS/feems_result_pb2.py b/machinery-system-structure/MachSysS/feems_result_pb2.py index 4d3669c..842109a 100644 --- a/machinery-system-structure/MachSysS/feems_result_pb2.py +++ b/machinery-system-structure/MachSysS/feems_result_pb2.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: feems_result.proto +# Protobuf Python Version: 4.25.2 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool diff --git a/machinery-system-structure/MachSysS/feems_result_pb2.pyi b/machinery-system-structure/MachSysS/feems_result_pb2.pyi new file mode 100644 index 0000000..d03307e --- /dev/null +++ b/machinery-system-structure/MachSysS/feems_result_pb2.pyi @@ -0,0 +1,274 @@ +import system_structure_pb2 as _system_structure_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ( + ClassVar as _ClassVar, + Iterable as _Iterable, + Mapping as _Mapping, + Optional as _Optional, + Union as _Union, +) + +DESCRIPTOR: _descriptor.FileDescriptor + +class FuelScalar(_message.Message): + __slots__ = ( + "fuel_type", + "fuel_origin", + "fuel_specified_by", + "mass_or_mass_fraction", + "lhv_mj_per_g", + "ghg_emission_factor_well_to_tank_gco2eq_per_mj", + "ghg_emission_factor_tank_to_wake", + ) + FUEL_TYPE_FIELD_NUMBER: _ClassVar[int] + FUEL_ORIGIN_FIELD_NUMBER: _ClassVar[int] + FUEL_SPECIFIED_BY_FIELD_NUMBER: _ClassVar[int] + MASS_OR_MASS_FRACTION_FIELD_NUMBER: _ClassVar[int] + LHV_MJ_PER_G_FIELD_NUMBER: _ClassVar[int] + GHG_EMISSION_FACTOR_WELL_TO_TANK_GCO2EQ_PER_MJ_FIELD_NUMBER: _ClassVar[int] + GHG_EMISSION_FACTOR_TANK_TO_WAKE_FIELD_NUMBER: _ClassVar[int] + fuel_type: _system_structure_pb2.FuelType + fuel_origin: _system_structure_pb2.FuelOrigin + fuel_specified_by: _system_structure_pb2.FuelSpecifiedBy + mass_or_mass_fraction: float + lhv_mj_per_g: float + ghg_emission_factor_well_to_tank_gco2eq_per_mj: float + ghg_emission_factor_tank_to_wake: float + def __init__( + self, + fuel_type: _Optional[_Union[_system_structure_pb2.FuelType, str]] = ..., + fuel_origin: _Optional[_Union[_system_structure_pb2.FuelOrigin, str]] = ..., + fuel_specified_by: _Optional[ + _Union[_system_structure_pb2.FuelSpecifiedBy, str] + ] = ..., + mass_or_mass_fraction: _Optional[float] = ..., + lhv_mj_per_g: _Optional[float] = ..., + ghg_emission_factor_well_to_tank_gco2eq_per_mj: _Optional[float] = ..., + ghg_emission_factor_tank_to_wake: _Optional[float] = ..., + ) -> None: ... + +class FuelArray(_message.Message): + __slots__ = ( + "fuel_type", + "fuel_origin", + "fuel_specified_by", + "mass_or_mass_fraction", + "lhv_mj_per_g", + "ghg_emission_factor_well_to_tank_gco2eq_per_mj", + "ghg_emission_factor_tank_to_wake", + ) + FUEL_TYPE_FIELD_NUMBER: _ClassVar[int] + FUEL_ORIGIN_FIELD_NUMBER: _ClassVar[int] + FUEL_SPECIFIED_BY_FIELD_NUMBER: _ClassVar[int] + MASS_OR_MASS_FRACTION_FIELD_NUMBER: _ClassVar[int] + LHV_MJ_PER_G_FIELD_NUMBER: _ClassVar[int] + GHG_EMISSION_FACTOR_WELL_TO_TANK_GCO2EQ_PER_MJ_FIELD_NUMBER: _ClassVar[int] + GHG_EMISSION_FACTOR_TANK_TO_WAKE_FIELD_NUMBER: _ClassVar[int] + fuel_type: _system_structure_pb2.FuelType + fuel_origin: _system_structure_pb2.FuelOrigin + fuel_specified_by: _system_structure_pb2.FuelSpecifiedBy + mass_or_mass_fraction: _containers.RepeatedScalarFieldContainer[float] + lhv_mj_per_g: float + ghg_emission_factor_well_to_tank_gco2eq_per_mj: float + ghg_emission_factor_tank_to_wake: float + def __init__( + self, + fuel_type: _Optional[_Union[_system_structure_pb2.FuelType, str]] = ..., + fuel_origin: _Optional[_Union[_system_structure_pb2.FuelOrigin, str]] = ..., + fuel_specified_by: _Optional[ + _Union[_system_structure_pb2.FuelSpecifiedBy, str] + ] = ..., + mass_or_mass_fraction: _Optional[_Iterable[float]] = ..., + lhv_mj_per_g: _Optional[float] = ..., + ghg_emission_factor_well_to_tank_gco2eq_per_mj: _Optional[float] = ..., + ghg_emission_factor_tank_to_wake: _Optional[float] = ..., + ) -> None: ... + +class FuelConsumptionScalar(_message.Message): + __slots__ = ("fuels",) + FUELS_FIELD_NUMBER: _ClassVar[int] + fuels: _containers.RepeatedCompositeFieldContainer[FuelScalar] + def __init__( + self, fuels: _Optional[_Iterable[_Union[FuelScalar, _Mapping]]] = ... + ) -> None: ... + +class FuelConsumptionRateArray(_message.Message): + __slots__ = ("fuels",) + FUELS_FIELD_NUMBER: _ClassVar[int] + fuels: _containers.RepeatedCompositeFieldContainer[FuelArray] + def __init__( + self, fuels: _Optional[_Iterable[_Union[FuelArray, _Mapping]]] = ... + ) -> None: ... + +class TimeSeriesResultForComponent(_message.Message): + __slots__ = ("time", "power_output_kw", "fuel_consumption_kg_per_s") + TIME_FIELD_NUMBER: _ClassVar[int] + POWER_OUTPUT_KW_FIELD_NUMBER: _ClassVar[int] + FUEL_CONSUMPTION_KG_PER_S_FIELD_NUMBER: _ClassVar[int] + time: _containers.RepeatedScalarFieldContainer[float] + power_output_kw: _containers.RepeatedScalarFieldContainer[float] + fuel_consumption_kg_per_s: FuelConsumptionRateArray + def __init__( + self, + time: _Optional[_Iterable[float]] = ..., + power_output_kw: _Optional[_Iterable[float]] = ..., + fuel_consumption_kg_per_s: _Optional[ + _Union[FuelConsumptionRateArray, _Mapping] + ] = ..., + ) -> None: ... + +class ResultPerComponent(_message.Message): + __slots__ = ( + "component_name", + "multi_fuel_consumption_kg", + "electric_energy_consumption_mj", + "mechanical_energy_consumption_mj", + "energy_stored_mj", + "running_hours_h", + "co2_emissions_kg", + "nox_emissions_kg", + "component_type", + "rated_capacity", + "rated_capacity_unit", + "switchboard_id", + "shaftline_id", + "result_time_series", + ) + COMPONENT_NAME_FIELD_NUMBER: _ClassVar[int] + MULTI_FUEL_CONSUMPTION_KG_FIELD_NUMBER: _ClassVar[int] + ELECTRIC_ENERGY_CONSUMPTION_MJ_FIELD_NUMBER: _ClassVar[int] + MECHANICAL_ENERGY_CONSUMPTION_MJ_FIELD_NUMBER: _ClassVar[int] + ENERGY_STORED_MJ_FIELD_NUMBER: _ClassVar[int] + RUNNING_HOURS_H_FIELD_NUMBER: _ClassVar[int] + CO2_EMISSIONS_KG_FIELD_NUMBER: _ClassVar[int] + NOX_EMISSIONS_KG_FIELD_NUMBER: _ClassVar[int] + COMPONENT_TYPE_FIELD_NUMBER: _ClassVar[int] + RATED_CAPACITY_FIELD_NUMBER: _ClassVar[int] + RATED_CAPACITY_UNIT_FIELD_NUMBER: _ClassVar[int] + SWITCHBOARD_ID_FIELD_NUMBER: _ClassVar[int] + SHAFTLINE_ID_FIELD_NUMBER: _ClassVar[int] + RESULT_TIME_SERIES_FIELD_NUMBER: _ClassVar[int] + component_name: str + multi_fuel_consumption_kg: FuelConsumptionScalar + electric_energy_consumption_mj: float + mechanical_energy_consumption_mj: float + energy_stored_mj: float + running_hours_h: float + co2_emissions_kg: float + nox_emissions_kg: float + component_type: str + rated_capacity: float + rated_capacity_unit: str + switchboard_id: int + shaftline_id: int + result_time_series: TimeSeriesResultForComponent + def __init__( + self, + component_name: _Optional[str] = ..., + multi_fuel_consumption_kg: _Optional[ + _Union[FuelConsumptionScalar, _Mapping] + ] = ..., + electric_energy_consumption_mj: _Optional[float] = ..., + mechanical_energy_consumption_mj: _Optional[float] = ..., + energy_stored_mj: _Optional[float] = ..., + running_hours_h: _Optional[float] = ..., + co2_emissions_kg: _Optional[float] = ..., + nox_emissions_kg: _Optional[float] = ..., + component_type: _Optional[str] = ..., + rated_capacity: _Optional[float] = ..., + rated_capacity_unit: _Optional[str] = ..., + switchboard_id: _Optional[int] = ..., + shaftline_id: _Optional[int] = ..., + result_time_series: _Optional[ + _Union[TimeSeriesResultForComponent, _Mapping] + ] = ..., + ) -> None: ... + +class FeemsResult(_message.Message): + __slots__ = ( + "duration_s", + "multi_fuel_consumption_total_kg", + "energy_consumption_electric_total_mj", + "energy_consumption_mechanical_total_mj", + "energy_stored_total_mj", + "running_hours_main_engines_hr", + "running_hours_genset_total_hr", + "running_hours_fuel_cell_total_hr", + "running_hours_pti_pto_total_hr", + "co2_emission_total_kg", + "nox_emission_total_kg", + "detailed_result", + "energy_input_mechanical_total_mj", + "energy_input_electric_total_mj", + "energy_consumption_propulsion_total_mj", + "energy_consumption_auxiliary_total_mj", + ) + DURATION_S_FIELD_NUMBER: _ClassVar[int] + MULTI_FUEL_CONSUMPTION_TOTAL_KG_FIELD_NUMBER: _ClassVar[int] + ENERGY_CONSUMPTION_ELECTRIC_TOTAL_MJ_FIELD_NUMBER: _ClassVar[int] + ENERGY_CONSUMPTION_MECHANICAL_TOTAL_MJ_FIELD_NUMBER: _ClassVar[int] + ENERGY_STORED_TOTAL_MJ_FIELD_NUMBER: _ClassVar[int] + RUNNING_HOURS_MAIN_ENGINES_HR_FIELD_NUMBER: _ClassVar[int] + RUNNING_HOURS_GENSET_TOTAL_HR_FIELD_NUMBER: _ClassVar[int] + RUNNING_HOURS_FUEL_CELL_TOTAL_HR_FIELD_NUMBER: _ClassVar[int] + RUNNING_HOURS_PTI_PTO_TOTAL_HR_FIELD_NUMBER: _ClassVar[int] + CO2_EMISSION_TOTAL_KG_FIELD_NUMBER: _ClassVar[int] + NOX_EMISSION_TOTAL_KG_FIELD_NUMBER: _ClassVar[int] + DETAILED_RESULT_FIELD_NUMBER: _ClassVar[int] + ENERGY_INPUT_MECHANICAL_TOTAL_MJ_FIELD_NUMBER: _ClassVar[int] + ENERGY_INPUT_ELECTRIC_TOTAL_MJ_FIELD_NUMBER: _ClassVar[int] + ENERGY_CONSUMPTION_PROPULSION_TOTAL_MJ_FIELD_NUMBER: _ClassVar[int] + ENERGY_CONSUMPTION_AUXILIARY_TOTAL_MJ_FIELD_NUMBER: _ClassVar[int] + duration_s: float + multi_fuel_consumption_total_kg: FuelConsumptionScalar + energy_consumption_electric_total_mj: float + energy_consumption_mechanical_total_mj: float + energy_stored_total_mj: float + running_hours_main_engines_hr: float + running_hours_genset_total_hr: float + running_hours_fuel_cell_total_hr: float + running_hours_pti_pto_total_hr: float + co2_emission_total_kg: float + nox_emission_total_kg: float + detailed_result: _containers.RepeatedCompositeFieldContainer[ResultPerComponent] + energy_input_mechanical_total_mj: float + energy_input_electric_total_mj: float + energy_consumption_propulsion_total_mj: float + energy_consumption_auxiliary_total_mj: float + def __init__( + self, + duration_s: _Optional[float] = ..., + multi_fuel_consumption_total_kg: _Optional[ + _Union[FuelConsumptionScalar, _Mapping] + ] = ..., + energy_consumption_electric_total_mj: _Optional[float] = ..., + energy_consumption_mechanical_total_mj: _Optional[float] = ..., + energy_stored_total_mj: _Optional[float] = ..., + running_hours_main_engines_hr: _Optional[float] = ..., + running_hours_genset_total_hr: _Optional[float] = ..., + running_hours_fuel_cell_total_hr: _Optional[float] = ..., + running_hours_pti_pto_total_hr: _Optional[float] = ..., + co2_emission_total_kg: _Optional[float] = ..., + nox_emission_total_kg: _Optional[float] = ..., + detailed_result: _Optional[ + _Iterable[_Union[ResultPerComponent, _Mapping]] + ] = ..., + energy_input_mechanical_total_mj: _Optional[float] = ..., + energy_input_electric_total_mj: _Optional[float] = ..., + energy_consumption_propulsion_total_mj: _Optional[float] = ..., + energy_consumption_auxiliary_total_mj: _Optional[float] = ..., + ) -> None: ... + +class FeemsResultForMachinerySystem(_message.Message): + __slots__ = ("electric_system", "mechanical_system") + ELECTRIC_SYSTEM_FIELD_NUMBER: _ClassVar[int] + MECHANICAL_SYSTEM_FIELD_NUMBER: _ClassVar[int] + electric_system: FeemsResult + mechanical_system: FeemsResult + def __init__( + self, + electric_system: _Optional[_Union[FeemsResult, _Mapping]] = ..., + mechanical_system: _Optional[_Union[FeemsResult, _Mapping]] = ..., + ) -> None: ... diff --git a/machinery-system-structure/MachSysS/gymir_result_pb2.py b/machinery-system-structure/MachSysS/gymir_result_pb2.py index 9d85a58..bbfc0b8 100644 --- a/machinery-system-structure/MachSysS/gymir_result_pb2.py +++ b/machinery-system-structure/MachSysS/gymir_result_pb2.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: gymir_result.proto +# Protobuf Python Version: 4.25.2 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool diff --git a/machinery-system-structure/MachSysS/gymir_result_pb2.pyi b/machinery-system-structure/MachSysS/gymir_result_pb2.pyi new file mode 100644 index 0000000..54b9751 --- /dev/null +++ b/machinery-system-structure/MachSysS/gymir_result_pb2.pyi @@ -0,0 +1,179 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ( + ClassVar as _ClassVar, + Iterable as _Iterable, + Mapping as _Mapping, + Optional as _Optional, + Union as _Union, +) + +DESCRIPTOR: _descriptor.FileDescriptor + +class GymirResult(_message.Message): + __slots__ = ("name", "auxiliary_load_kw", "result") + NAME_FIELD_NUMBER: _ClassVar[int] + AUXILIARY_LOAD_KW_FIELD_NUMBER: _ClassVar[int] + RESULT_FIELD_NUMBER: _ClassVar[int] + name: str + auxiliary_load_kw: float + result: _containers.RepeatedCompositeFieldContainer[SimulationInstance] + def __init__( + self, + name: _Optional[str] = ..., + auxiliary_load_kw: _Optional[float] = ..., + result: _Optional[_Iterable[_Union[SimulationInstance, _Mapping]]] = ..., + ) -> None: ... + +class SimulationInstance(_message.Message): + __slots__ = ( + "epoch_s", + "task_type", + "task_name", + "latitude_deg", + "longitude_deg", + "heading_deg", + "wave_height_significant_m", + "wave_peak_period_s", + "wave_dir_rel_north_deg", + "wave_dir_rel_vessel_deg", + "wind_speed_mps", + "wind_dir_rel_north_deg", + "wind_dir_rel_vessel_deg", + "weather_source", + "speed_over_ground_kn", + "speed_through_water_kn", + "current_speed_mps", + "current_dir_rel_north_deg", + "power_kw", + "torque_k_nm", + "thrust_k_n", + "total_resistance_k_n", + ) + EPOCH_S_FIELD_NUMBER: _ClassVar[int] + TASK_TYPE_FIELD_NUMBER: _ClassVar[int] + TASK_NAME_FIELD_NUMBER: _ClassVar[int] + LATITUDE_DEG_FIELD_NUMBER: _ClassVar[int] + LONGITUDE_DEG_FIELD_NUMBER: _ClassVar[int] + HEADING_DEG_FIELD_NUMBER: _ClassVar[int] + WAVE_HEIGHT_SIGNIFICANT_M_FIELD_NUMBER: _ClassVar[int] + WAVE_PEAK_PERIOD_S_FIELD_NUMBER: _ClassVar[int] + WAVE_DIR_REL_NORTH_DEG_FIELD_NUMBER: _ClassVar[int] + WAVE_DIR_REL_VESSEL_DEG_FIELD_NUMBER: _ClassVar[int] + WIND_SPEED_MPS_FIELD_NUMBER: _ClassVar[int] + WIND_DIR_REL_NORTH_DEG_FIELD_NUMBER: _ClassVar[int] + WIND_DIR_REL_VESSEL_DEG_FIELD_NUMBER: _ClassVar[int] + WEATHER_SOURCE_FIELD_NUMBER: _ClassVar[int] + SPEED_OVER_GROUND_KN_FIELD_NUMBER: _ClassVar[int] + SPEED_THROUGH_WATER_KN_FIELD_NUMBER: _ClassVar[int] + CURRENT_SPEED_MPS_FIELD_NUMBER: _ClassVar[int] + CURRENT_DIR_REL_NORTH_DEG_FIELD_NUMBER: _ClassVar[int] + POWER_KW_FIELD_NUMBER: _ClassVar[int] + TORQUE_K_NM_FIELD_NUMBER: _ClassVar[int] + THRUST_K_N_FIELD_NUMBER: _ClassVar[int] + TOTAL_RESISTANCE_K_N_FIELD_NUMBER: _ClassVar[int] + epoch_s: float + task_type: str + task_name: str + latitude_deg: float + longitude_deg: float + heading_deg: float + wave_height_significant_m: float + wave_peak_period_s: float + wave_dir_rel_north_deg: float + wave_dir_rel_vessel_deg: float + wind_speed_mps: float + wind_dir_rel_north_deg: float + wind_dir_rel_vessel_deg: float + weather_source: str + speed_over_ground_kn: float + speed_through_water_kn: float + current_speed_mps: float + current_dir_rel_north_deg: float + power_kw: float + torque_k_nm: float + thrust_k_n: float + total_resistance_k_n: float + def __init__( + self, + epoch_s: _Optional[float] = ..., + task_type: _Optional[str] = ..., + task_name: _Optional[str] = ..., + latitude_deg: _Optional[float] = ..., + longitude_deg: _Optional[float] = ..., + heading_deg: _Optional[float] = ..., + wave_height_significant_m: _Optional[float] = ..., + wave_peak_period_s: _Optional[float] = ..., + wave_dir_rel_north_deg: _Optional[float] = ..., + wave_dir_rel_vessel_deg: _Optional[float] = ..., + wind_speed_mps: _Optional[float] = ..., + wind_dir_rel_north_deg: _Optional[float] = ..., + wind_dir_rel_vessel_deg: _Optional[float] = ..., + weather_source: _Optional[str] = ..., + speed_over_ground_kn: _Optional[float] = ..., + speed_through_water_kn: _Optional[float] = ..., + current_speed_mps: _Optional[float] = ..., + current_dir_rel_north_deg: _Optional[float] = ..., + power_kw: _Optional[float] = ..., + torque_k_nm: _Optional[float] = ..., + thrust_k_n: _Optional[float] = ..., + total_resistance_k_n: _Optional[float] = ..., + ) -> None: ... + +class PropulsionPowerInstance(_message.Message): + __slots__ = ("epoch_s", "propulsion_power_kw", "auxiliary_power_kw") + EPOCH_S_FIELD_NUMBER: _ClassVar[int] + PROPULSION_POWER_KW_FIELD_NUMBER: _ClassVar[int] + AUXILIARY_POWER_KW_FIELD_NUMBER: _ClassVar[int] + epoch_s: float + propulsion_power_kw: float + auxiliary_power_kw: float + def __init__( + self, + epoch_s: _Optional[float] = ..., + propulsion_power_kw: _Optional[float] = ..., + auxiliary_power_kw: _Optional[float] = ..., + ) -> None: ... + +class OperationProfilePoint(_message.Message): + __slots__ = ("epoch_s", "speed_kn", "draft_m") + EPOCH_S_FIELD_NUMBER: _ClassVar[int] + SPEED_KN_FIELD_NUMBER: _ClassVar[int] + DRAFT_M_FIELD_NUMBER: _ClassVar[int] + epoch_s: float + speed_kn: float + draft_m: float + def __init__( + self, + epoch_s: _Optional[float] = ..., + speed_kn: _Optional[float] = ..., + draft_m: _Optional[float] = ..., + ) -> None: ... + +class TimeSeriesResult(_message.Message): + __slots__ = ( + "propulsion_power_timeseries", + "auxiliary_power_kw", + "operation_profile", + ) + PROPULSION_POWER_TIMESERIES_FIELD_NUMBER: _ClassVar[int] + AUXILIARY_POWER_KW_FIELD_NUMBER: _ClassVar[int] + OPERATION_PROFILE_FIELD_NUMBER: _ClassVar[int] + propulsion_power_timeseries: _containers.RepeatedCompositeFieldContainer[ + PropulsionPowerInstance + ] + auxiliary_power_kw: float + operation_profile: _containers.RepeatedCompositeFieldContainer[ + OperationProfilePoint + ] + def __init__( + self, + propulsion_power_timeseries: _Optional[ + _Iterable[_Union[PropulsionPowerInstance, _Mapping]] + ] = ..., + auxiliary_power_kw: _Optional[float] = ..., + operation_profile: _Optional[ + _Iterable[_Union[OperationProfilePoint, _Mapping]] + ] = ..., + ) -> None: ... diff --git a/machinery-system-structure/MachSysS/system_structure_pb2.py b/machinery-system-structure/MachSysS/system_structure_pb2.py index 48a288e..621cfb3 100644 --- a/machinery-system-structure/MachSysS/system_structure_pb2.py +++ b/machinery-system-structure/MachSysS/system_structure_pb2.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: system_structure.proto +# Protobuf Python Version: 4.25.2 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +14,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x16system_structure.proto\x12\x18machinerySystemStructure"\x1d\n\x05Point\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01":\n\x07\x43urve1D\x12/\n\x06points\x18\x01 \x03(\x0b\x32\x1f.machinerySystemStructure.Point"_\n\tBSFCCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"e\n\x0f\x45\x66\x66iciencyCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"X\n\x04\x42SFC\x12\x32\n\x05\x63urve\x18\x01 \x01(\x0b\x32#.machinerySystemStructure.BSFCCurve\x12\x12\n\x05value\x18\x02 \x01(\x01H\x00\x88\x01\x01\x42\x08\n\x06_value"s\n\nEfficiency\x12=\n\x05\x63urve\x18\x01 \x01(\x0b\x32).machinerySystemStructure.EfficiencyCurveH\x00\x88\x01\x01\x12\x12\n\x05value\x18\x02 \x01(\x01H\x01\x88\x01\x01\x42\x08\n\x06_curveB\x08\n\x06_value"\x85\x01\n\x19PropulsionPowerTimeSeries\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x14\n\x0cpropulsor_id\x18\x03 \x01(\r\x12\x30\n\x05\x63urve\x18\x04 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"\x85\x01\n\x17\x41uxiliaryLoadTimeSeries\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x16\n\x0eswitchboard_id\x18\x03 \x01(\r\x12\x30\n\x05\x63urve\x18\x04 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"8\n\rAuxiliaryLoad\x12\x16\n\x0eswitchboard_id\x18\x01 \x01(\r\x12\x0f\n\x07load_kw\x18\x02 \x01(\x01"\xa2\x01\n\rEmissionCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D\x12=\n\remission_type\x18\x04 \x01(\x0e\x32&.machinerySystemStructure.EmissionType"\xd8\x01\n\x04Gear\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\ngear_ratio\x18\x02 \x01(\x01\x12\x16\n\x0erated_power_kw\x18\x03 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x04 \x01(\x01\x12\x38\n\nefficiency\x18\x05 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x06 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x07 \x01(\x01"x\n\x04\x46uel\x12\x35\n\tfuel_type\x18\x01 \x01(\x0e\x32".machinerySystemStructure.FuelType\x12\x39\n\x0b\x66uel_origin\x18\x02 \x01(\x0e\x32$.machinerySystemStructure.FuelOrigin"\xd3\x05\n\x06\x45ngine\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x03 \x01(\x01\x12,\n\x04\x62sfc\x18\x04 \x01(\x0b\x32\x1e.machinerySystemStructure.BSFC\x12\x31\n\tmain_fuel\x18\x05 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12+\n#order_from_switchboard_or_shaftline\x18\x06 \x01(\r\x12\x32\n\npilot_bsfc\x18\x07 \x01(\x0b\x32\x1e.machinerySystemStructure.BSFC\x12\x32\n\npilot_fuel\x18\x08 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12U\n\x16nox_calculation_method\x18\t \x01(\x0e\x32\x35.machinerySystemStructure.Engine.NOxCalculationMethod\x12@\n\x0f\x65mission_curves\x18\n \x03(\x0b\x32\'.machinerySystemStructure.EmissionCurve\x12K\n\x11\x65ngine_cycle_type\x18\x0b \x01(\x0e\x32\x30.machinerySystemStructure.Engine.EngineCycleType\x12\x16\n\x0eunit_price_usd\x18\x0c \x01(\x01"E\n\x14NOxCalculationMethod\x12\n\n\x06TIER_2\x10\x00\x12\n\n\x06TIER_1\x10\x01\x12\n\n\x06TIER_3\x10\x02\x12\t\n\x05\x43URVE\x10\x03"O\n\x0f\x45ngineCycleType\x12\x08\n\x04NONE\x10\x00\x12\n\n\x06\x44IESEL\x10\x01\x12\x08\n\x04OTTO\x10\x02\x12\x1c\n\x18LEAN_BURN_SPARK_IGNITION\x10\x03"\xcf\x01\n\x0f\x45lectricMachine\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x03 \x01(\x01\x12\x38\n\nefficiency\x18\x04 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x06 \x01(\x01"\x98\x02\n\x07\x42\x61ttery\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1b\n\x13\x65nergy_capacity_kwh\x18\x02 \x01(\x01\x12\x1d\n\x15rated_charging_rate_c\x18\x03 \x01(\x01\x12 \n\x18rated_discharging_rate_c\x18\x04 \x01(\x01\x12\x1b\n\x13\x65\x66\x66iciency_charging\x18\x05 \x01(\x01\x12\x1e\n\x16\x65\x66\x66iciency_discharging\x18\x06 \x01(\x01\x12\x1f\n\x17initial_state_of_charge\x18\x07 \x01(\x01\x12+\n#order_from_switchboard_or_shaftline\x18\x08 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\t \x01(\x01"\xb8\x01\n\x11\x45lectricComponent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x04 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x05 \x01(\x01"\xf5\x01\n\x08\x46uelCell\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r\x12,\n\x04\x66uel\x18\x06 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12\x16\n\x0eunit_price_usd\x18\x07 \x01(\x01\x12\x16\n\x0enumber_modules\x18\x08 \x01(\r"\x96\x01\n\tPropeller\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x38\n\nefficiency\x18\x02 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12\x14\n\x0cpropulsor_id\x18\x03 \x01(\r\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r"$\n\nBusBreaker\x12\x16\n\x0eswitchboard_to\x18\x01 \x01(\x05"\xf5\x01\n\x0eSuperCapacitor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1a\n\x12\x65nergy_capacity_wh\x18\x02 \x01(\x01\x12\x16\n\x0erated_power_kw\x18\x03 \x01(\x01\x12\x1b\n\x13\x65\x66\x66iciency_charging\x18\x04 \x01(\x01\x12\x1e\n\x16\x65\x66\x66iciency_discharging\x18\x05 \x01(\x01\x12\x1f\n\x17initial_state_of_charge\x18\x06 \x01(\x01\x12+\n#order_from_switchboard_or_shaftline\x18\x07 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x08 \x01(\x01"\xba\x01\n\x13MechanicalComponent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x04 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x05 \x01(\x01"\xba\r\n\tSubsystem\x12,\n\x04gear\x18\x01 \x01(\x0b\x32\x1e.machinerySystemStructure.Gear\x12\x30\n\x06\x65ngine\x18\x02 \x01(\x0b\x32 .machinerySystemStructure.Engine\x12\x43\n\x10\x65lectric_machine\x18\x03 \x01(\x0b\x32).machinerySystemStructure.ElectricMachine\x12@\n\x0btransformer\x18\x04 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12?\n\nconverter1\x18\x05 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12?\n\nconverter2\x18\x06 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12\x32\n\x07\x62\x61ttery\x18\x07 \x01(\x0b\x32!.machinerySystemStructure.Battery\x12\x35\n\tfuel_cell\x18\x08 \x01(\x0b\x32".machinerySystemStructure.FuelCell\x12\x36\n\tpropeller\x18\t \x01(\x0b\x32#.machinerySystemStructure.Propeller\x12\x39\n\x0b\x62us_breaker\x18\n \x01(\x0b\x32$.machinerySystemStructure.BusBreaker\x12@\n\x0esupercapacitor\x18\x0b \x01(\x0b\x32(.machinerySystemStructure.SuperCapacitor\x12?\n\nother_load\x18\x0c \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12\x41\n\npower_type\x18\r \x01(\x0e\x32-.machinerySystemStructure.Subsystem.PowerType\x12I\n\x0e\x63omponent_type\x18\x0e \x01(\x0e\x32\x31.machinerySystemStructure.Subsystem.ComponentType\x12\x0c\n\x04name\x18\x0f \x01(\t\x12\x16\n\x0erated_power_kw\x18\x10 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x11 \x01(\x01\x12-\n%ramp_up_rate_limit_percent_per_second\x18\x12 \x01(\x01\x12/\n\'ramp_down_rate_limit_percent_per_second\x18\x13 \x01(\x01\x12\x17\n\x0f\x62\x61se_load_order\x18\x14 \x01(\r"s\n\tPowerType\x12\t\n\x05NONE1\x10\x00\x12\x10\n\x0cPOWER_SOURCE\x10\x01\x12\x12\n\x0ePOWER_CONSUMER\x10\x02\x12\x0b\n\x07PTI_PTO\x10\x03\x12\x12\n\x0e\x45NERGY_STORAGE\x10\x04\x12\x14\n\x10SHORE_CONNECTION\x10\x05"\xa7\x04\n\rComponentType\x12\x08\n\x04NONE\x10\x00\x12\x0f\n\x0bMAIN_ENGINE\x10\x01\x12\x14\n\x10\x41UXILIARY_ENGINE\x10\x02\x12\r\n\tGENERATOR\x10\x03\x12\x14\n\x10PROPULSION_DRIVE\x10\x04\x12\x0e\n\nOTHER_LOAD\x10\x05\x12\x12\n\x0ePTI_PTO_SYSTEM\x10\x06\x12\x12\n\x0e\x42\x41TTERY_SYSTEM\x10\x07\x12\x14\n\x10\x46UEL_CELL_SYSTEM\x10\x08\x12\r\n\tRECTIFIER\x10\t\x12\x1c\n\x18MAIN_ENGINE_WITH_GEARBOX\x10\n\x12\x12\n\x0e\x45LECTRIC_MOTOR\x10\x0b\x12\n\n\x06GENSET\x10\x0c\x12\x0f\n\x0bTRANSFORMER\x10\r\x12\x0c\n\x08INVERTER\x10\x0e\x12\x13\n\x0f\x43IRCUIT_BREAKER\x10\x0f\x12\x14\n\x10\x41\x43TIVE_FRONT_END\x10\x10\x12\x13\n\x0fPOWER_CONVERTER\x10\x11\x12\x17\n\x13SYNCHRONOUS_MACHINE\x10\x12\x12\x15\n\x11INDUCTION_MACHINE\x10\x13\x12\x0b\n\x07GEARBOX\x10\x14\x12\r\n\tFUEL_CELL\x10\x15\x12\x12\n\x0ePROPELLER_LOAD\x10\x16\x12\x19\n\x15OTHER_MECHANICAL_LOAD\x10\x17\x12\x0b\n\x07\x42\x41TTERY\x10\x18\x12\x12\n\x0eSUPERCAPACITOR\x10\x19\x12\x19\n\x15SUPERCAPACITOR_SYSTEM\x10\x1a\x12\x0f\n\x0bSHORE_POWER\x10\x1b"^\n\x0bSwitchboard\x12\x16\n\x0eswitchboard_id\x18\x01 \x01(\r\x12\x37\n\nsubsystems\x18\x02 \x03(\x0b\x32#.machinerySystemStructure.Subsystem"[\n\tShaftLine\x12\x15\n\rshaft_line_id\x18\x01 \x01(\r\x12\x37\n\nsubsystems\x18\x02 \x03(\x0b\x32#.machinerySystemStructure.Subsystem"L\n\x10MechanicalSystem\x12\x38\n\x0bshaft_lines\x18\x01 \x03(\x0b\x32#.machinerySystemStructure.ShaftLine"M\n\x0e\x45lectricSystem\x12;\n\x0cswitchboards\x18\x01 \x03(\x0b\x32%.machinerySystemStructure.Switchboard"Y\n\x0b\x46uelStorage\x12\x35\n\tfuel_type\x18\x01 \x01(\x0e\x32".machinerySystemStructure.FuelType\x12\x13\n\x0b\x63\x61pacity_kg\x18\x02 \x01(\x01"\xfe\x03\n\x0fMachinerySystem\x12\x0c\n\x04name\x18\x01 \x01(\t\x12Q\n\x0fpropulsion_type\x18\x02 \x01(\x0e\x32\x38.machinerySystemStructure.MachinerySystem.PropulsionType\x12;\n\x0c\x66uel_storage\x18\x03 \x03(\x0b\x32%.machinerySystemStructure.FuelStorage\x12.\n&maximum_allowed_genset_load_percentage\x18\x04 \x01(\x01\x12\x45\n\x11mechanical_system\x18\x05 \x01(\x0b\x32*.machinerySystemStructure.MechanicalSystem\x12\x41\n\x0f\x65lectric_system\x18\x06 \x01(\x0b\x32(.machinerySystemStructure.ElectricSystem\x12\x31\n)maximum_allowed_fuel_cell_load_percentage\x18\x07 \x01(\x01\x12$\n\x1c\x61verage_base_load_percentage\x18\x08 \x01(\x01":\n\x0ePropulsionType\x12\x0e\n\nMECHANICAL\x10\x00\x12\x0c\n\x08\x45LECTRIC\x10\x01\x12\n\n\x06HYBRID\x10\x02*T\n\x0c\x45missionType\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03SOX\x10\x01\x12\x07\n\x03NOX\x10\x02\x12\x06\n\x02\x43O\x10\x03\x12\x06\n\x02PM\x10\x04\x12\x06\n\x02HC\x10\x05\x12\x07\n\x03\x43H4\x10\x06\x12\x07\n\x03N2O\x10\x07*\x90\x01\n\x08\x46uelType\x12\n\n\x06\x44IESEL\x10\x00\x12\x07\n\x03HFO\x10\x01\x12\x0f\n\x0bNATURAL_GAS\x10\x02\x12\x0c\n\x08HYDROGEN\x10\x03\x12\x0b\n\x07\x41MMONIA\x10\x04\x12\x0f\n\x0bLPG_PROPANE\x10\x05\x12\x0e\n\nLPG_BUTANE\x10\x06\x12\x0b\n\x07\x45THANOL\x10\x07\x12\x0c\n\x08METHANOL\x10\x08\x12\x07\n\x03LFO\x10\t*C\n\nFuelOrigin\x12\t\n\x05NONE1\x10\x00\x12\n\n\x06\x46OSSIL\x10\x01\x12\x07\n\x03\x42IO\x10\x02\x12\x15\n\x11RENEWABLE_NON_BIO\x10\x03*E\n\x0f\x46uelSpecifiedBy\x12\t\n\x05NONE2\x10\x00\x12\x14\n\x10\x46UEL_EU_MARITIME\x10\x01\x12\x07\n\x03IMO\x10\x02\x12\x08\n\x04USER\x10\x03\x62\x06proto3' + b'\n\x16system_structure.proto\x12\x18machinerySystemStructure"\x1d\n\x05Point\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01":\n\x07\x43urve1D\x12/\n\x06points\x18\x01 \x03(\x0b\x32\x1f.machinerySystemStructure.Point"_\n\tBSFCCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"e\n\x0f\x45\x66\x66iciencyCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"X\n\x04\x42SFC\x12\x32\n\x05\x63urve\x18\x01 \x01(\x0b\x32#.machinerySystemStructure.BSFCCurve\x12\x12\n\x05value\x18\x02 \x01(\x01H\x00\x88\x01\x01\x42\x08\n\x06_value"s\n\nEfficiency\x12=\n\x05\x63urve\x18\x01 \x01(\x0b\x32).machinerySystemStructure.EfficiencyCurveH\x00\x88\x01\x01\x12\x12\n\x05value\x18\x02 \x01(\x01H\x01\x88\x01\x01\x42\x08\n\x06_curveB\x08\n\x06_value"\x85\x01\n\x19PropulsionPowerTimeSeries\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x14\n\x0cpropulsor_id\x18\x03 \x01(\r\x12\x30\n\x05\x63urve\x18\x04 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"\x85\x01\n\x17\x41uxiliaryLoadTimeSeries\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x16\n\x0eswitchboard_id\x18\x03 \x01(\r\x12\x30\n\x05\x63urve\x18\x04 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"8\n\rAuxiliaryLoad\x12\x16\n\x0eswitchboard_id\x18\x01 \x01(\r\x12\x0f\n\x07load_kw\x18\x02 \x01(\x01"\xa2\x01\n\rEmissionCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D\x12=\n\remission_type\x18\x04 \x01(\x0e\x32&.machinerySystemStructure.EmissionType"\xd8\x01\n\x04Gear\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\ngear_ratio\x18\x02 \x01(\x01\x12\x16\n\x0erated_power_kw\x18\x03 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x04 \x01(\x01\x12\x38\n\nefficiency\x18\x05 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x06 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x07 \x01(\x01"x\n\x04\x46uel\x12\x35\n\tfuel_type\x18\x01 \x01(\x0e\x32".machinerySystemStructure.FuelType\x12\x39\n\x0b\x66uel_origin\x18\x02 \x01(\x0e\x32$.machinerySystemStructure.FuelOrigin"\x85\x06\n\x06\x45ngine\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x03 \x01(\x01\x12,\n\x04\x62sfc\x18\x04 \x01(\x0b\x32\x1e.machinerySystemStructure.BSFC\x12\x31\n\tmain_fuel\x18\x05 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12+\n#order_from_switchboard_or_shaftline\x18\x06 \x01(\r\x12\x32\n\npilot_bsfc\x18\x07 \x01(\x0b\x32\x1e.machinerySystemStructure.BSFC\x12\x32\n\npilot_fuel\x18\x08 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12U\n\x16nox_calculation_method\x18\t \x01(\x0e\x32\x35.machinerySystemStructure.Engine.NOxCalculationMethod\x12@\n\x0f\x65mission_curves\x18\n \x03(\x0b\x32\'.machinerySystemStructure.EmissionCurve\x12K\n\x11\x65ngine_cycle_type\x18\x0b \x01(\x0e\x32\x30.machinerySystemStructure.Engine.EngineCycleType\x12\x16\n\x0eunit_price_usd\x18\x0c \x01(\x01\x12\x15\n\rstart_delay_s\x18\r \x01(\x01\x12\x19\n\x11turn_off_power_kw\x18\x0e \x01(\x01"E\n\x14NOxCalculationMethod\x12\n\n\x06TIER_2\x10\x00\x12\n\n\x06TIER_1\x10\x01\x12\n\n\x06TIER_3\x10\x02\x12\t\n\x05\x43URVE\x10\x03"O\n\x0f\x45ngineCycleType\x12\x08\n\x04NONE\x10\x00\x12\n\n\x06\x44IESEL\x10\x01\x12\x08\n\x04OTTO\x10\x02\x12\x1c\n\x18LEAN_BURN_SPARK_IGNITION\x10\x03"\xcf\x01\n\x0f\x45lectricMachine\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x03 \x01(\x01\x12\x38\n\nefficiency\x18\x04 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x06 \x01(\x01"\x82\x03\n\x07\x42\x61ttery\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1b\n\x13\x65nergy_capacity_kwh\x18\x02 \x01(\x01\x12\x1d\n\x15rated_charging_rate_c\x18\x03 \x01(\x01\x12 \n\x18rated_discharging_rate_c\x18\x04 \x01(\x01\x12\x1b\n\x13\x65\x66\x66iciency_charging\x18\x05 \x01(\x01\x12\x1e\n\x16\x65\x66\x66iciency_discharging\x18\x06 \x01(\x01\x12\x1f\n\x17initial_state_of_charge\x18\x07 \x01(\x01\x12+\n#order_from_switchboard_or_shaftline\x18\x08 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\t \x01(\x01\x12&\n\x1eself_discharge_percent_per_day\x18\n \x01(\x01\x12\x1f\n\x17state_of_energy_minimum\x18\x0b \x01(\x01\x12\x1f\n\x17state_of_energy_maximum\x18\x0c \x01(\x01"\xb8\x01\n\x11\x45lectricComponent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x04 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x05 \x01(\x01"\xac\x02\n\x08\x46uelCell\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r\x12,\n\x04\x66uel\x18\x06 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12\x16\n\x0eunit_price_usd\x18\x07 \x01(\x01\x12\x16\n\x0enumber_modules\x18\x08 \x01(\r\x12\x1e\n\x16power_minimum_specific\x18\t \x01(\x01\x12\x15\n\rstart_delay_s\x18\n \x01(\x01"\x96\x01\n\tPropeller\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x38\n\nefficiency\x18\x02 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12\x14\n\x0cpropulsor_id\x18\x03 \x01(\r\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r"$\n\nBusBreaker\x12\x16\n\x0eswitchboard_to\x18\x01 \x01(\x05"\xf5\x01\n\x0eSuperCapacitor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1a\n\x12\x65nergy_capacity_wh\x18\x02 \x01(\x01\x12\x16\n\x0erated_power_kw\x18\x03 \x01(\x01\x12\x1b\n\x13\x65\x66\x66iciency_charging\x18\x04 \x01(\x01\x12\x1e\n\x16\x65\x66\x66iciency_discharging\x18\x05 \x01(\x01\x12\x1f\n\x17initial_state_of_charge\x18\x06 \x01(\x01\x12+\n#order_from_switchboard_or_shaftline\x18\x07 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x08 \x01(\x01"\xba\x01\n\x13MechanicalComponent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x04 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x05 \x01(\x01"\xba\r\n\tSubsystem\x12,\n\x04gear\x18\x01 \x01(\x0b\x32\x1e.machinerySystemStructure.Gear\x12\x30\n\x06\x65ngine\x18\x02 \x01(\x0b\x32 .machinerySystemStructure.Engine\x12\x43\n\x10\x65lectric_machine\x18\x03 \x01(\x0b\x32).machinerySystemStructure.ElectricMachine\x12@\n\x0btransformer\x18\x04 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12?\n\nconverter1\x18\x05 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12?\n\nconverter2\x18\x06 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12\x32\n\x07\x62\x61ttery\x18\x07 \x01(\x0b\x32!.machinerySystemStructure.Battery\x12\x35\n\tfuel_cell\x18\x08 \x01(\x0b\x32".machinerySystemStructure.FuelCell\x12\x36\n\tpropeller\x18\t \x01(\x0b\x32#.machinerySystemStructure.Propeller\x12\x39\n\x0b\x62us_breaker\x18\n \x01(\x0b\x32$.machinerySystemStructure.BusBreaker\x12@\n\x0esupercapacitor\x18\x0b \x01(\x0b\x32(.machinerySystemStructure.SuperCapacitor\x12?\n\nother_load\x18\x0c \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12\x41\n\npower_type\x18\r \x01(\x0e\x32-.machinerySystemStructure.Subsystem.PowerType\x12I\n\x0e\x63omponent_type\x18\x0e \x01(\x0e\x32\x31.machinerySystemStructure.Subsystem.ComponentType\x12\x0c\n\x04name\x18\x0f \x01(\t\x12\x16\n\x0erated_power_kw\x18\x10 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x11 \x01(\x01\x12-\n%ramp_up_rate_limit_percent_per_second\x18\x12 \x01(\x01\x12/\n\'ramp_down_rate_limit_percent_per_second\x18\x13 \x01(\x01\x12\x17\n\x0f\x62\x61se_load_order\x18\x14 \x01(\r"s\n\tPowerType\x12\t\n\x05NONE1\x10\x00\x12\x10\n\x0cPOWER_SOURCE\x10\x01\x12\x12\n\x0ePOWER_CONSUMER\x10\x02\x12\x0b\n\x07PTI_PTO\x10\x03\x12\x12\n\x0e\x45NERGY_STORAGE\x10\x04\x12\x14\n\x10SHORE_CONNECTION\x10\x05"\xa7\x04\n\rComponentType\x12\x08\n\x04NONE\x10\x00\x12\x0f\n\x0bMAIN_ENGINE\x10\x01\x12\x14\n\x10\x41UXILIARY_ENGINE\x10\x02\x12\r\n\tGENERATOR\x10\x03\x12\x14\n\x10PROPULSION_DRIVE\x10\x04\x12\x0e\n\nOTHER_LOAD\x10\x05\x12\x12\n\x0ePTI_PTO_SYSTEM\x10\x06\x12\x12\n\x0e\x42\x41TTERY_SYSTEM\x10\x07\x12\x14\n\x10\x46UEL_CELL_SYSTEM\x10\x08\x12\r\n\tRECTIFIER\x10\t\x12\x1c\n\x18MAIN_ENGINE_WITH_GEARBOX\x10\n\x12\x12\n\x0e\x45LECTRIC_MOTOR\x10\x0b\x12\n\n\x06GENSET\x10\x0c\x12\x0f\n\x0bTRANSFORMER\x10\r\x12\x0c\n\x08INVERTER\x10\x0e\x12\x13\n\x0f\x43IRCUIT_BREAKER\x10\x0f\x12\x14\n\x10\x41\x43TIVE_FRONT_END\x10\x10\x12\x13\n\x0fPOWER_CONVERTER\x10\x11\x12\x17\n\x13SYNCHRONOUS_MACHINE\x10\x12\x12\x15\n\x11INDUCTION_MACHINE\x10\x13\x12\x0b\n\x07GEARBOX\x10\x14\x12\r\n\tFUEL_CELL\x10\x15\x12\x12\n\x0ePROPELLER_LOAD\x10\x16\x12\x19\n\x15OTHER_MECHANICAL_LOAD\x10\x17\x12\x0b\n\x07\x42\x41TTERY\x10\x18\x12\x12\n\x0eSUPERCAPACITOR\x10\x19\x12\x19\n\x15SUPERCAPACITOR_SYSTEM\x10\x1a\x12\x0f\n\x0bSHORE_POWER\x10\x1b"^\n\x0bSwitchboard\x12\x16\n\x0eswitchboard_id\x18\x01 \x01(\r\x12\x37\n\nsubsystems\x18\x02 \x03(\x0b\x32#.machinerySystemStructure.Subsystem"[\n\tShaftLine\x12\x15\n\rshaft_line_id\x18\x01 \x01(\r\x12\x37\n\nsubsystems\x18\x02 \x03(\x0b\x32#.machinerySystemStructure.Subsystem"L\n\x10MechanicalSystem\x12\x38\n\x0bshaft_lines\x18\x01 \x03(\x0b\x32#.machinerySystemStructure.ShaftLine"M\n\x0e\x45lectricSystem\x12;\n\x0cswitchboards\x18\x01 \x03(\x0b\x32%.machinerySystemStructure.Switchboard"Y\n\x0b\x46uelStorage\x12\x35\n\tfuel_type\x18\x01 \x01(\x0e\x32".machinerySystemStructure.FuelType\x12\x13\n\x0b\x63\x61pacity_kg\x18\x02 \x01(\x01"\xfe\x03\n\x0fMachinerySystem\x12\x0c\n\x04name\x18\x01 \x01(\t\x12Q\n\x0fpropulsion_type\x18\x02 \x01(\x0e\x32\x38.machinerySystemStructure.MachinerySystem.PropulsionType\x12;\n\x0c\x66uel_storage\x18\x03 \x03(\x0b\x32%.machinerySystemStructure.FuelStorage\x12.\n&maximum_allowed_genset_load_percentage\x18\x04 \x01(\x01\x12\x45\n\x11mechanical_system\x18\x05 \x01(\x0b\x32*.machinerySystemStructure.MechanicalSystem\x12\x41\n\x0f\x65lectric_system\x18\x06 \x01(\x0b\x32(.machinerySystemStructure.ElectricSystem\x12\x31\n)maximum_allowed_fuel_cell_load_percentage\x18\x07 \x01(\x01\x12$\n\x1c\x61verage_base_load_percentage\x18\x08 \x01(\x01":\n\x0ePropulsionType\x12\x0e\n\nMECHANICAL\x10\x00\x12\x0c\n\x08\x45LECTRIC\x10\x01\x12\n\n\x06HYBRID\x10\x02*T\n\x0c\x45missionType\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03SOX\x10\x01\x12\x07\n\x03NOX\x10\x02\x12\x06\n\x02\x43O\x10\x03\x12\x06\n\x02PM\x10\x04\x12\x06\n\x02HC\x10\x05\x12\x07\n\x03\x43H4\x10\x06\x12\x07\n\x03N2O\x10\x07*\x90\x01\n\x08\x46uelType\x12\n\n\x06\x44IESEL\x10\x00\x12\x07\n\x03HFO\x10\x01\x12\x0f\n\x0bNATURAL_GAS\x10\x02\x12\x0c\n\x08HYDROGEN\x10\x03\x12\x0b\n\x07\x41MMONIA\x10\x04\x12\x0f\n\x0bLPG_PROPANE\x10\x05\x12\x0e\n\nLPG_BUTANE\x10\x06\x12\x0b\n\x07\x45THANOL\x10\x07\x12\x0c\n\x08METHANOL\x10\x08\x12\x07\n\x03LFO\x10\t*C\n\nFuelOrigin\x12\t\n\x05NONE1\x10\x00\x12\n\n\x06\x46OSSIL\x10\x01\x12\x07\n\x03\x42IO\x10\x02\x12\x15\n\x11RENEWABLE_NON_BIO\x10\x03*E\n\x0f\x46uelSpecifiedBy\x12\t\n\x05NONE2\x10\x00\x12\x14\n\x10\x46UEL_EU_MARITIME\x10\x01\x12\x07\n\x03IMO\x10\x02\x12\x08\n\x04USER\x10\x03\x62\x06proto3' ) _globals = globals() @@ -21,14 +22,14 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "system_structure_pb2", _globals) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None - _globals["_EMISSIONTYPE"]._serialized_start = 6343 - _globals["_EMISSIONTYPE"]._serialized_end = 6427 - _globals["_FUELTYPE"]._serialized_start = 6430 - _globals["_FUELTYPE"]._serialized_end = 6574 - _globals["_FUELORIGIN"]._serialized_start = 6576 - _globals["_FUELORIGIN"]._serialized_end = 6643 - _globals["_FUELSPECIFIEDBY"]._serialized_start = 6645 - _globals["_FUELSPECIFIEDBY"]._serialized_end = 6714 + _globals["_EMISSIONTYPE"]._serialized_start = 6554 + _globals["_EMISSIONTYPE"]._serialized_end = 6638 + _globals["_FUELTYPE"]._serialized_start = 6641 + _globals["_FUELTYPE"]._serialized_end = 6785 + _globals["_FUELORIGIN"]._serialized_start = 6787 + _globals["_FUELORIGIN"]._serialized_end = 6854 + _globals["_FUELSPECIFIEDBY"]._serialized_start = 6856 + _globals["_FUELSPECIFIEDBY"]._serialized_end = 6925 _globals["_POINT"]._serialized_start = 52 _globals["_POINT"]._serialized_end = 81 _globals["_CURVE1D"]._serialized_start = 83 @@ -54,45 +55,45 @@ _globals["_FUEL"]._serialized_start = 1264 _globals["_FUEL"]._serialized_end = 1384 _globals["_ENGINE"]._serialized_start = 1387 - _globals["_ENGINE"]._serialized_end = 2110 - _globals["_ENGINE_NOXCALCULATIONMETHOD"]._serialized_start = 1960 - _globals["_ENGINE_NOXCALCULATIONMETHOD"]._serialized_end = 2029 - _globals["_ENGINE_ENGINECYCLETYPE"]._serialized_start = 2031 - _globals["_ENGINE_ENGINECYCLETYPE"]._serialized_end = 2110 - _globals["_ELECTRICMACHINE"]._serialized_start = 2113 - _globals["_ELECTRICMACHINE"]._serialized_end = 2320 - _globals["_BATTERY"]._serialized_start = 2323 - _globals["_BATTERY"]._serialized_end = 2603 - _globals["_ELECTRICCOMPONENT"]._serialized_start = 2606 - _globals["_ELECTRICCOMPONENT"]._serialized_end = 2790 - _globals["_FUELCELL"]._serialized_start = 2793 - _globals["_FUELCELL"]._serialized_end = 3038 - _globals["_PROPELLER"]._serialized_start = 3041 - _globals["_PROPELLER"]._serialized_end = 3191 - _globals["_BUSBREAKER"]._serialized_start = 3193 - _globals["_BUSBREAKER"]._serialized_end = 3229 - _globals["_SUPERCAPACITOR"]._serialized_start = 3232 - _globals["_SUPERCAPACITOR"]._serialized_end = 3477 - _globals["_MECHANICALCOMPONENT"]._serialized_start = 3480 - _globals["_MECHANICALCOMPONENT"]._serialized_end = 3666 - _globals["_SUBSYSTEM"]._serialized_start = 3669 - _globals["_SUBSYSTEM"]._serialized_end = 5391 - _globals["_SUBSYSTEM_POWERTYPE"]._serialized_start = 4722 - _globals["_SUBSYSTEM_POWERTYPE"]._serialized_end = 4837 - _globals["_SUBSYSTEM_COMPONENTTYPE"]._serialized_start = 4840 - _globals["_SUBSYSTEM_COMPONENTTYPE"]._serialized_end = 5391 - _globals["_SWITCHBOARD"]._serialized_start = 5393 - _globals["_SWITCHBOARD"]._serialized_end = 5487 - _globals["_SHAFTLINE"]._serialized_start = 5489 - _globals["_SHAFTLINE"]._serialized_end = 5580 - _globals["_MECHANICALSYSTEM"]._serialized_start = 5582 - _globals["_MECHANICALSYSTEM"]._serialized_end = 5658 - _globals["_ELECTRICSYSTEM"]._serialized_start = 5660 - _globals["_ELECTRICSYSTEM"]._serialized_end = 5737 - _globals["_FUELSTORAGE"]._serialized_start = 5739 - _globals["_FUELSTORAGE"]._serialized_end = 5828 - _globals["_MACHINERYSYSTEM"]._serialized_start = 5831 - _globals["_MACHINERYSYSTEM"]._serialized_end = 6341 - _globals["_MACHINERYSYSTEM_PROPULSIONTYPE"]._serialized_start = 6283 - _globals["_MACHINERYSYSTEM_PROPULSIONTYPE"]._serialized_end = 6341 + _globals["_ENGINE"]._serialized_end = 2160 + _globals["_ENGINE_NOXCALCULATIONMETHOD"]._serialized_start = 2010 + _globals["_ENGINE_NOXCALCULATIONMETHOD"]._serialized_end = 2079 + _globals["_ENGINE_ENGINECYCLETYPE"]._serialized_start = 2081 + _globals["_ENGINE_ENGINECYCLETYPE"]._serialized_end = 2160 + _globals["_ELECTRICMACHINE"]._serialized_start = 2163 + _globals["_ELECTRICMACHINE"]._serialized_end = 2370 + _globals["_BATTERY"]._serialized_start = 2373 + _globals["_BATTERY"]._serialized_end = 2759 + _globals["_ELECTRICCOMPONENT"]._serialized_start = 2762 + _globals["_ELECTRICCOMPONENT"]._serialized_end = 2946 + _globals["_FUELCELL"]._serialized_start = 2949 + _globals["_FUELCELL"]._serialized_end = 3249 + _globals["_PROPELLER"]._serialized_start = 3252 + _globals["_PROPELLER"]._serialized_end = 3402 + _globals["_BUSBREAKER"]._serialized_start = 3404 + _globals["_BUSBREAKER"]._serialized_end = 3440 + _globals["_SUPERCAPACITOR"]._serialized_start = 3443 + _globals["_SUPERCAPACITOR"]._serialized_end = 3688 + _globals["_MECHANICALCOMPONENT"]._serialized_start = 3691 + _globals["_MECHANICALCOMPONENT"]._serialized_end = 3877 + _globals["_SUBSYSTEM"]._serialized_start = 3880 + _globals["_SUBSYSTEM"]._serialized_end = 5602 + _globals["_SUBSYSTEM_POWERTYPE"]._serialized_start = 4933 + _globals["_SUBSYSTEM_POWERTYPE"]._serialized_end = 5048 + _globals["_SUBSYSTEM_COMPONENTTYPE"]._serialized_start = 5051 + _globals["_SUBSYSTEM_COMPONENTTYPE"]._serialized_end = 5602 + _globals["_SWITCHBOARD"]._serialized_start = 5604 + _globals["_SWITCHBOARD"]._serialized_end = 5698 + _globals["_SHAFTLINE"]._serialized_start = 5700 + _globals["_SHAFTLINE"]._serialized_end = 5791 + _globals["_MECHANICALSYSTEM"]._serialized_start = 5793 + _globals["_MECHANICALSYSTEM"]._serialized_end = 5869 + _globals["_ELECTRICSYSTEM"]._serialized_start = 5871 + _globals["_ELECTRICSYSTEM"]._serialized_end = 5948 + _globals["_FUELSTORAGE"]._serialized_start = 5950 + _globals["_FUELSTORAGE"]._serialized_end = 6039 + _globals["_MACHINERYSYSTEM"]._serialized_start = 6042 + _globals["_MACHINERYSYSTEM"]._serialized_end = 6552 + _globals["_MACHINERYSYSTEM_PROPULSIONTYPE"]._serialized_start = 6494 + _globals["_MACHINERYSYSTEM_PROPULSIONTYPE"]._serialized_end = 6552 # @@protoc_insertion_point(module_scope) diff --git a/machinery-system-structure/MachSysS/system_structure_pb2.pyi b/machinery-system-structure/MachSysS/system_structure_pb2.pyi new file mode 100644 index 0000000..95db015 --- /dev/null +++ b/machinery-system-structure/MachSysS/system_structure_pb2.pyi @@ -0,0 +1,865 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ( + ClassVar as _ClassVar, + Iterable as _Iterable, + Mapping as _Mapping, + Optional as _Optional, + Union as _Union, +) + +DESCRIPTOR: _descriptor.FileDescriptor + +class EmissionType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + NONE: _ClassVar[EmissionType] + SOX: _ClassVar[EmissionType] + NOX: _ClassVar[EmissionType] + CO: _ClassVar[EmissionType] + PM: _ClassVar[EmissionType] + HC: _ClassVar[EmissionType] + CH4: _ClassVar[EmissionType] + N2O: _ClassVar[EmissionType] + +class FuelType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + DIESEL: _ClassVar[FuelType] + HFO: _ClassVar[FuelType] + NATURAL_GAS: _ClassVar[FuelType] + HYDROGEN: _ClassVar[FuelType] + AMMONIA: _ClassVar[FuelType] + LPG_PROPANE: _ClassVar[FuelType] + LPG_BUTANE: _ClassVar[FuelType] + ETHANOL: _ClassVar[FuelType] + METHANOL: _ClassVar[FuelType] + LFO: _ClassVar[FuelType] + +class FuelOrigin(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + NONE1: _ClassVar[FuelOrigin] + FOSSIL: _ClassVar[FuelOrigin] + BIO: _ClassVar[FuelOrigin] + RENEWABLE_NON_BIO: _ClassVar[FuelOrigin] + +class FuelSpecifiedBy(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + NONE2: _ClassVar[FuelSpecifiedBy] + FUEL_EU_MARITIME: _ClassVar[FuelSpecifiedBy] + IMO: _ClassVar[FuelSpecifiedBy] + USER: _ClassVar[FuelSpecifiedBy] + +NONE: EmissionType +SOX: EmissionType +NOX: EmissionType +CO: EmissionType +PM: EmissionType +HC: EmissionType +CH4: EmissionType +N2O: EmissionType +DIESEL: FuelType +HFO: FuelType +NATURAL_GAS: FuelType +HYDROGEN: FuelType +AMMONIA: FuelType +LPG_PROPANE: FuelType +LPG_BUTANE: FuelType +ETHANOL: FuelType +METHANOL: FuelType +LFO: FuelType +NONE1: FuelOrigin +FOSSIL: FuelOrigin +BIO: FuelOrigin +RENEWABLE_NON_BIO: FuelOrigin +NONE2: FuelSpecifiedBy +FUEL_EU_MARITIME: FuelSpecifiedBy +IMO: FuelSpecifiedBy +USER: FuelSpecifiedBy + +class Point(_message.Message): + __slots__ = ("x", "y") + X_FIELD_NUMBER: _ClassVar[int] + Y_FIELD_NUMBER: _ClassVar[int] + x: float + y: float + def __init__( + self, x: _Optional[float] = ..., y: _Optional[float] = ... + ) -> None: ... + +class Curve1D(_message.Message): + __slots__ = ("points",) + POINTS_FIELD_NUMBER: _ClassVar[int] + points: _containers.RepeatedCompositeFieldContainer[Point] + def __init__( + self, points: _Optional[_Iterable[_Union[Point, _Mapping]]] = ... + ) -> None: ... + +class BSFCCurve(_message.Message): + __slots__ = ("x_label", "y_label", "curve") + X_LABEL_FIELD_NUMBER: _ClassVar[int] + Y_LABEL_FIELD_NUMBER: _ClassVar[int] + CURVE_FIELD_NUMBER: _ClassVar[int] + x_label: str + y_label: str + curve: Curve1D + def __init__( + self, + x_label: _Optional[str] = ..., + y_label: _Optional[str] = ..., + curve: _Optional[_Union[Curve1D, _Mapping]] = ..., + ) -> None: ... + +class EfficiencyCurve(_message.Message): + __slots__ = ("x_label", "y_label", "curve") + X_LABEL_FIELD_NUMBER: _ClassVar[int] + Y_LABEL_FIELD_NUMBER: _ClassVar[int] + CURVE_FIELD_NUMBER: _ClassVar[int] + x_label: str + y_label: str + curve: Curve1D + def __init__( + self, + x_label: _Optional[str] = ..., + y_label: _Optional[str] = ..., + curve: _Optional[_Union[Curve1D, _Mapping]] = ..., + ) -> None: ... + +class BSFC(_message.Message): + __slots__ = ("curve", "value") + CURVE_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + curve: BSFCCurve + value: float + def __init__( + self, + curve: _Optional[_Union[BSFCCurve, _Mapping]] = ..., + value: _Optional[float] = ..., + ) -> None: ... + +class Efficiency(_message.Message): + __slots__ = ("curve", "value") + CURVE_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + curve: EfficiencyCurve + value: float + def __init__( + self, + curve: _Optional[_Union[EfficiencyCurve, _Mapping]] = ..., + value: _Optional[float] = ..., + ) -> None: ... + +class PropulsionPowerTimeSeries(_message.Message): + __slots__ = ("x_label", "y_label", "propulsor_id", "curve") + X_LABEL_FIELD_NUMBER: _ClassVar[int] + Y_LABEL_FIELD_NUMBER: _ClassVar[int] + PROPULSOR_ID_FIELD_NUMBER: _ClassVar[int] + CURVE_FIELD_NUMBER: _ClassVar[int] + x_label: str + y_label: str + propulsor_id: int + curve: Curve1D + def __init__( + self, + x_label: _Optional[str] = ..., + y_label: _Optional[str] = ..., + propulsor_id: _Optional[int] = ..., + curve: _Optional[_Union[Curve1D, _Mapping]] = ..., + ) -> None: ... + +class AuxiliaryLoadTimeSeries(_message.Message): + __slots__ = ("x_label", "y_label", "switchboard_id", "curve") + X_LABEL_FIELD_NUMBER: _ClassVar[int] + Y_LABEL_FIELD_NUMBER: _ClassVar[int] + SWITCHBOARD_ID_FIELD_NUMBER: _ClassVar[int] + CURVE_FIELD_NUMBER: _ClassVar[int] + x_label: str + y_label: str + switchboard_id: int + curve: Curve1D + def __init__( + self, + x_label: _Optional[str] = ..., + y_label: _Optional[str] = ..., + switchboard_id: _Optional[int] = ..., + curve: _Optional[_Union[Curve1D, _Mapping]] = ..., + ) -> None: ... + +class AuxiliaryLoad(_message.Message): + __slots__ = ("switchboard_id", "load_kw") + SWITCHBOARD_ID_FIELD_NUMBER: _ClassVar[int] + LOAD_KW_FIELD_NUMBER: _ClassVar[int] + switchboard_id: int + load_kw: float + def __init__( + self, switchboard_id: _Optional[int] = ..., load_kw: _Optional[float] = ... + ) -> None: ... + +class EmissionCurve(_message.Message): + __slots__ = ("x_label", "y_label", "curve", "emission_type") + X_LABEL_FIELD_NUMBER: _ClassVar[int] + Y_LABEL_FIELD_NUMBER: _ClassVar[int] + CURVE_FIELD_NUMBER: _ClassVar[int] + EMISSION_TYPE_FIELD_NUMBER: _ClassVar[int] + x_label: str + y_label: str + curve: Curve1D + emission_type: EmissionType + def __init__( + self, + x_label: _Optional[str] = ..., + y_label: _Optional[str] = ..., + curve: _Optional[_Union[Curve1D, _Mapping]] = ..., + emission_type: _Optional[_Union[EmissionType, str]] = ..., + ) -> None: ... + +class Gear(_message.Message): + __slots__ = ( + "name", + "gear_ratio", + "rated_power_kw", + "rated_speed_rpm", + "efficiency", + "order_from_switchboard_or_shaftline", + "unit_price_usd", + ) + NAME_FIELD_NUMBER: _ClassVar[int] + GEAR_RATIO_FIELD_NUMBER: _ClassVar[int] + RATED_POWER_KW_FIELD_NUMBER: _ClassVar[int] + RATED_SPEED_RPM_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_FIELD_NUMBER: _ClassVar[int] + ORDER_FROM_SWITCHBOARD_OR_SHAFTLINE_FIELD_NUMBER: _ClassVar[int] + UNIT_PRICE_USD_FIELD_NUMBER: _ClassVar[int] + name: str + gear_ratio: float + rated_power_kw: float + rated_speed_rpm: float + efficiency: Efficiency + order_from_switchboard_or_shaftline: int + unit_price_usd: float + def __init__( + self, + name: _Optional[str] = ..., + gear_ratio: _Optional[float] = ..., + rated_power_kw: _Optional[float] = ..., + rated_speed_rpm: _Optional[float] = ..., + efficiency: _Optional[_Union[Efficiency, _Mapping]] = ..., + order_from_switchboard_or_shaftline: _Optional[int] = ..., + unit_price_usd: _Optional[float] = ..., + ) -> None: ... + +class Fuel(_message.Message): + __slots__ = ("fuel_type", "fuel_origin") + FUEL_TYPE_FIELD_NUMBER: _ClassVar[int] + FUEL_ORIGIN_FIELD_NUMBER: _ClassVar[int] + fuel_type: FuelType + fuel_origin: FuelOrigin + def __init__( + self, + fuel_type: _Optional[_Union[FuelType, str]] = ..., + fuel_origin: _Optional[_Union[FuelOrigin, str]] = ..., + ) -> None: ... + +class Engine(_message.Message): + __slots__ = ( + "name", + "rated_power_kw", + "rated_speed_rpm", + "bsfc", + "main_fuel", + "order_from_switchboard_or_shaftline", + "pilot_bsfc", + "pilot_fuel", + "nox_calculation_method", + "emission_curves", + "engine_cycle_type", + "unit_price_usd", + "start_delay_s", + "turn_off_power_kw", + ) + + class NOxCalculationMethod(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + TIER_2: _ClassVar[Engine.NOxCalculationMethod] + TIER_1: _ClassVar[Engine.NOxCalculationMethod] + TIER_3: _ClassVar[Engine.NOxCalculationMethod] + CURVE: _ClassVar[Engine.NOxCalculationMethod] + + TIER_2: Engine.NOxCalculationMethod + TIER_1: Engine.NOxCalculationMethod + TIER_3: Engine.NOxCalculationMethod + CURVE: Engine.NOxCalculationMethod + + class EngineCycleType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + NONE: _ClassVar[Engine.EngineCycleType] + DIESEL: _ClassVar[Engine.EngineCycleType] + OTTO: _ClassVar[Engine.EngineCycleType] + LEAN_BURN_SPARK_IGNITION: _ClassVar[Engine.EngineCycleType] + + NONE: Engine.EngineCycleType + DIESEL: Engine.EngineCycleType + OTTO: Engine.EngineCycleType + LEAN_BURN_SPARK_IGNITION: Engine.EngineCycleType + NAME_FIELD_NUMBER: _ClassVar[int] + RATED_POWER_KW_FIELD_NUMBER: _ClassVar[int] + RATED_SPEED_RPM_FIELD_NUMBER: _ClassVar[int] + BSFC_FIELD_NUMBER: _ClassVar[int] + MAIN_FUEL_FIELD_NUMBER: _ClassVar[int] + ORDER_FROM_SWITCHBOARD_OR_SHAFTLINE_FIELD_NUMBER: _ClassVar[int] + PILOT_BSFC_FIELD_NUMBER: _ClassVar[int] + PILOT_FUEL_FIELD_NUMBER: _ClassVar[int] + NOX_CALCULATION_METHOD_FIELD_NUMBER: _ClassVar[int] + EMISSION_CURVES_FIELD_NUMBER: _ClassVar[int] + ENGINE_CYCLE_TYPE_FIELD_NUMBER: _ClassVar[int] + UNIT_PRICE_USD_FIELD_NUMBER: _ClassVar[int] + START_DELAY_S_FIELD_NUMBER: _ClassVar[int] + TURN_OFF_POWER_KW_FIELD_NUMBER: _ClassVar[int] + name: str + rated_power_kw: float + rated_speed_rpm: float + bsfc: BSFC + main_fuel: Fuel + order_from_switchboard_or_shaftline: int + pilot_bsfc: BSFC + pilot_fuel: Fuel + nox_calculation_method: Engine.NOxCalculationMethod + emission_curves: _containers.RepeatedCompositeFieldContainer[EmissionCurve] + engine_cycle_type: Engine.EngineCycleType + unit_price_usd: float + start_delay_s: float + turn_off_power_kw: float + def __init__( + self, + name: _Optional[str] = ..., + rated_power_kw: _Optional[float] = ..., + rated_speed_rpm: _Optional[float] = ..., + bsfc: _Optional[_Union[BSFC, _Mapping]] = ..., + main_fuel: _Optional[_Union[Fuel, _Mapping]] = ..., + order_from_switchboard_or_shaftline: _Optional[int] = ..., + pilot_bsfc: _Optional[_Union[BSFC, _Mapping]] = ..., + pilot_fuel: _Optional[_Union[Fuel, _Mapping]] = ..., + nox_calculation_method: _Optional[ + _Union[Engine.NOxCalculationMethod, str] + ] = ..., + emission_curves: _Optional[_Iterable[_Union[EmissionCurve, _Mapping]]] = ..., + engine_cycle_type: _Optional[_Union[Engine.EngineCycleType, str]] = ..., + unit_price_usd: _Optional[float] = ..., + start_delay_s: _Optional[float] = ..., + turn_off_power_kw: _Optional[float] = ..., + ) -> None: ... + +class ElectricMachine(_message.Message): + __slots__ = ( + "name", + "rated_power_kw", + "rated_speed_rpm", + "efficiency", + "order_from_switchboard_or_shaftline", + "unit_price_usd", + ) + NAME_FIELD_NUMBER: _ClassVar[int] + RATED_POWER_KW_FIELD_NUMBER: _ClassVar[int] + RATED_SPEED_RPM_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_FIELD_NUMBER: _ClassVar[int] + ORDER_FROM_SWITCHBOARD_OR_SHAFTLINE_FIELD_NUMBER: _ClassVar[int] + UNIT_PRICE_USD_FIELD_NUMBER: _ClassVar[int] + name: str + rated_power_kw: float + rated_speed_rpm: float + efficiency: Efficiency + order_from_switchboard_or_shaftline: int + unit_price_usd: float + def __init__( + self, + name: _Optional[str] = ..., + rated_power_kw: _Optional[float] = ..., + rated_speed_rpm: _Optional[float] = ..., + efficiency: _Optional[_Union[Efficiency, _Mapping]] = ..., + order_from_switchboard_or_shaftline: _Optional[int] = ..., + unit_price_usd: _Optional[float] = ..., + ) -> None: ... + +class Battery(_message.Message): + __slots__ = ( + "name", + "energy_capacity_kwh", + "rated_charging_rate_c", + "rated_discharging_rate_c", + "efficiency_charging", + "efficiency_discharging", + "initial_state_of_charge", + "order_from_switchboard_or_shaftline", + "unit_price_usd", + "self_discharge_percent_per_day", + "state_of_energy_minimum", + "state_of_energy_maximum", + ) + NAME_FIELD_NUMBER: _ClassVar[int] + ENERGY_CAPACITY_KWH_FIELD_NUMBER: _ClassVar[int] + RATED_CHARGING_RATE_C_FIELD_NUMBER: _ClassVar[int] + RATED_DISCHARGING_RATE_C_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_CHARGING_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_DISCHARGING_FIELD_NUMBER: _ClassVar[int] + INITIAL_STATE_OF_CHARGE_FIELD_NUMBER: _ClassVar[int] + ORDER_FROM_SWITCHBOARD_OR_SHAFTLINE_FIELD_NUMBER: _ClassVar[int] + UNIT_PRICE_USD_FIELD_NUMBER: _ClassVar[int] + SELF_DISCHARGE_PERCENT_PER_DAY_FIELD_NUMBER: _ClassVar[int] + STATE_OF_ENERGY_MINIMUM_FIELD_NUMBER: _ClassVar[int] + STATE_OF_ENERGY_MAXIMUM_FIELD_NUMBER: _ClassVar[int] + name: str + energy_capacity_kwh: float + rated_charging_rate_c: float + rated_discharging_rate_c: float + efficiency_charging: float + efficiency_discharging: float + initial_state_of_charge: float + order_from_switchboard_or_shaftline: int + unit_price_usd: float + self_discharge_percent_per_day: float + state_of_energy_minimum: float + state_of_energy_maximum: float + def __init__( + self, + name: _Optional[str] = ..., + energy_capacity_kwh: _Optional[float] = ..., + rated_charging_rate_c: _Optional[float] = ..., + rated_discharging_rate_c: _Optional[float] = ..., + efficiency_charging: _Optional[float] = ..., + efficiency_discharging: _Optional[float] = ..., + initial_state_of_charge: _Optional[float] = ..., + order_from_switchboard_or_shaftline: _Optional[int] = ..., + unit_price_usd: _Optional[float] = ..., + self_discharge_percent_per_day: _Optional[float] = ..., + state_of_energy_minimum: _Optional[float] = ..., + state_of_energy_maximum: _Optional[float] = ..., + ) -> None: ... + +class ElectricComponent(_message.Message): + __slots__ = ( + "name", + "rated_power_kw", + "efficiency", + "order_from_switchboard_or_shaftline", + "unit_price_usd", + ) + NAME_FIELD_NUMBER: _ClassVar[int] + RATED_POWER_KW_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_FIELD_NUMBER: _ClassVar[int] + ORDER_FROM_SWITCHBOARD_OR_SHAFTLINE_FIELD_NUMBER: _ClassVar[int] + UNIT_PRICE_USD_FIELD_NUMBER: _ClassVar[int] + name: str + rated_power_kw: float + efficiency: Efficiency + order_from_switchboard_or_shaftline: int + unit_price_usd: float + def __init__( + self, + name: _Optional[str] = ..., + rated_power_kw: _Optional[float] = ..., + efficiency: _Optional[_Union[Efficiency, _Mapping]] = ..., + order_from_switchboard_or_shaftline: _Optional[int] = ..., + unit_price_usd: _Optional[float] = ..., + ) -> None: ... + +class FuelCell(_message.Message): + __slots__ = ( + "name", + "rated_power_kw", + "efficiency", + "order_from_switchboard_or_shaftline", + "fuel", + "unit_price_usd", + "number_modules", + "power_minimum_specific", + "start_delay_s", + ) + NAME_FIELD_NUMBER: _ClassVar[int] + RATED_POWER_KW_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_FIELD_NUMBER: _ClassVar[int] + ORDER_FROM_SWITCHBOARD_OR_SHAFTLINE_FIELD_NUMBER: _ClassVar[int] + FUEL_FIELD_NUMBER: _ClassVar[int] + UNIT_PRICE_USD_FIELD_NUMBER: _ClassVar[int] + NUMBER_MODULES_FIELD_NUMBER: _ClassVar[int] + POWER_MINIMUM_SPECIFIC_FIELD_NUMBER: _ClassVar[int] + START_DELAY_S_FIELD_NUMBER: _ClassVar[int] + name: str + rated_power_kw: float + efficiency: Efficiency + order_from_switchboard_or_shaftline: int + fuel: Fuel + unit_price_usd: float + number_modules: int + power_minimum_specific: float + start_delay_s: float + def __init__( + self, + name: _Optional[str] = ..., + rated_power_kw: _Optional[float] = ..., + efficiency: _Optional[_Union[Efficiency, _Mapping]] = ..., + order_from_switchboard_or_shaftline: _Optional[int] = ..., + fuel: _Optional[_Union[Fuel, _Mapping]] = ..., + unit_price_usd: _Optional[float] = ..., + number_modules: _Optional[int] = ..., + power_minimum_specific: _Optional[float] = ..., + start_delay_s: _Optional[float] = ..., + ) -> None: ... + +class Propeller(_message.Message): + __slots__ = ( + "name", + "efficiency", + "propulsor_id", + "order_from_switchboard_or_shaftline", + ) + NAME_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_FIELD_NUMBER: _ClassVar[int] + PROPULSOR_ID_FIELD_NUMBER: _ClassVar[int] + ORDER_FROM_SWITCHBOARD_OR_SHAFTLINE_FIELD_NUMBER: _ClassVar[int] + name: str + efficiency: Efficiency + propulsor_id: int + order_from_switchboard_or_shaftline: int + def __init__( + self, + name: _Optional[str] = ..., + efficiency: _Optional[_Union[Efficiency, _Mapping]] = ..., + propulsor_id: _Optional[int] = ..., + order_from_switchboard_or_shaftline: _Optional[int] = ..., + ) -> None: ... + +class BusBreaker(_message.Message): + __slots__ = ("switchboard_to",) + SWITCHBOARD_TO_FIELD_NUMBER: _ClassVar[int] + switchboard_to: int + def __init__(self, switchboard_to: _Optional[int] = ...) -> None: ... + +class SuperCapacitor(_message.Message): + __slots__ = ( + "name", + "energy_capacity_wh", + "rated_power_kw", + "efficiency_charging", + "efficiency_discharging", + "initial_state_of_charge", + "order_from_switchboard_or_shaftline", + "unit_price_usd", + ) + NAME_FIELD_NUMBER: _ClassVar[int] + ENERGY_CAPACITY_WH_FIELD_NUMBER: _ClassVar[int] + RATED_POWER_KW_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_CHARGING_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_DISCHARGING_FIELD_NUMBER: _ClassVar[int] + INITIAL_STATE_OF_CHARGE_FIELD_NUMBER: _ClassVar[int] + ORDER_FROM_SWITCHBOARD_OR_SHAFTLINE_FIELD_NUMBER: _ClassVar[int] + UNIT_PRICE_USD_FIELD_NUMBER: _ClassVar[int] + name: str + energy_capacity_wh: float + rated_power_kw: float + efficiency_charging: float + efficiency_discharging: float + initial_state_of_charge: float + order_from_switchboard_or_shaftline: int + unit_price_usd: float + def __init__( + self, + name: _Optional[str] = ..., + energy_capacity_wh: _Optional[float] = ..., + rated_power_kw: _Optional[float] = ..., + efficiency_charging: _Optional[float] = ..., + efficiency_discharging: _Optional[float] = ..., + initial_state_of_charge: _Optional[float] = ..., + order_from_switchboard_or_shaftline: _Optional[int] = ..., + unit_price_usd: _Optional[float] = ..., + ) -> None: ... + +class MechanicalComponent(_message.Message): + __slots__ = ( + "name", + "rated_power_kw", + "efficiency", + "order_from_switchboard_or_shaftline", + "unit_price_usd", + ) + NAME_FIELD_NUMBER: _ClassVar[int] + RATED_POWER_KW_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_FIELD_NUMBER: _ClassVar[int] + ORDER_FROM_SWITCHBOARD_OR_SHAFTLINE_FIELD_NUMBER: _ClassVar[int] + UNIT_PRICE_USD_FIELD_NUMBER: _ClassVar[int] + name: str + rated_power_kw: float + efficiency: Efficiency + order_from_switchboard_or_shaftline: int + unit_price_usd: float + def __init__( + self, + name: _Optional[str] = ..., + rated_power_kw: _Optional[float] = ..., + efficiency: _Optional[_Union[Efficiency, _Mapping]] = ..., + order_from_switchboard_or_shaftline: _Optional[int] = ..., + unit_price_usd: _Optional[float] = ..., + ) -> None: ... + +class Subsystem(_message.Message): + __slots__ = ( + "gear", + "engine", + "electric_machine", + "transformer", + "converter1", + "converter2", + "battery", + "fuel_cell", + "propeller", + "bus_breaker", + "supercapacitor", + "other_load", + "power_type", + "component_type", + "name", + "rated_power_kw", + "rated_speed_rpm", + "ramp_up_rate_limit_percent_per_second", + "ramp_down_rate_limit_percent_per_second", + "base_load_order", + ) + + class PowerType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + NONE1: _ClassVar[Subsystem.PowerType] + POWER_SOURCE: _ClassVar[Subsystem.PowerType] + POWER_CONSUMER: _ClassVar[Subsystem.PowerType] + PTI_PTO: _ClassVar[Subsystem.PowerType] + ENERGY_STORAGE: _ClassVar[Subsystem.PowerType] + SHORE_CONNECTION: _ClassVar[Subsystem.PowerType] + + NONE1: Subsystem.PowerType + POWER_SOURCE: Subsystem.PowerType + POWER_CONSUMER: Subsystem.PowerType + PTI_PTO: Subsystem.PowerType + ENERGY_STORAGE: Subsystem.PowerType + SHORE_CONNECTION: Subsystem.PowerType + + class ComponentType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + NONE: _ClassVar[Subsystem.ComponentType] + MAIN_ENGINE: _ClassVar[Subsystem.ComponentType] + AUXILIARY_ENGINE: _ClassVar[Subsystem.ComponentType] + GENERATOR: _ClassVar[Subsystem.ComponentType] + PROPULSION_DRIVE: _ClassVar[Subsystem.ComponentType] + OTHER_LOAD: _ClassVar[Subsystem.ComponentType] + PTI_PTO_SYSTEM: _ClassVar[Subsystem.ComponentType] + BATTERY_SYSTEM: _ClassVar[Subsystem.ComponentType] + FUEL_CELL_SYSTEM: _ClassVar[Subsystem.ComponentType] + RECTIFIER: _ClassVar[Subsystem.ComponentType] + MAIN_ENGINE_WITH_GEARBOX: _ClassVar[Subsystem.ComponentType] + ELECTRIC_MOTOR: _ClassVar[Subsystem.ComponentType] + GENSET: _ClassVar[Subsystem.ComponentType] + TRANSFORMER: _ClassVar[Subsystem.ComponentType] + INVERTER: _ClassVar[Subsystem.ComponentType] + CIRCUIT_BREAKER: _ClassVar[Subsystem.ComponentType] + ACTIVE_FRONT_END: _ClassVar[Subsystem.ComponentType] + POWER_CONVERTER: _ClassVar[Subsystem.ComponentType] + SYNCHRONOUS_MACHINE: _ClassVar[Subsystem.ComponentType] + INDUCTION_MACHINE: _ClassVar[Subsystem.ComponentType] + GEARBOX: _ClassVar[Subsystem.ComponentType] + FUEL_CELL: _ClassVar[Subsystem.ComponentType] + PROPELLER_LOAD: _ClassVar[Subsystem.ComponentType] + OTHER_MECHANICAL_LOAD: _ClassVar[Subsystem.ComponentType] + BATTERY: _ClassVar[Subsystem.ComponentType] + SUPERCAPACITOR: _ClassVar[Subsystem.ComponentType] + SUPERCAPACITOR_SYSTEM: _ClassVar[Subsystem.ComponentType] + SHORE_POWER: _ClassVar[Subsystem.ComponentType] + + NONE: Subsystem.ComponentType + MAIN_ENGINE: Subsystem.ComponentType + AUXILIARY_ENGINE: Subsystem.ComponentType + GENERATOR: Subsystem.ComponentType + PROPULSION_DRIVE: Subsystem.ComponentType + OTHER_LOAD: Subsystem.ComponentType + PTI_PTO_SYSTEM: Subsystem.ComponentType + BATTERY_SYSTEM: Subsystem.ComponentType + FUEL_CELL_SYSTEM: Subsystem.ComponentType + RECTIFIER: Subsystem.ComponentType + MAIN_ENGINE_WITH_GEARBOX: Subsystem.ComponentType + ELECTRIC_MOTOR: Subsystem.ComponentType + GENSET: Subsystem.ComponentType + TRANSFORMER: Subsystem.ComponentType + INVERTER: Subsystem.ComponentType + CIRCUIT_BREAKER: Subsystem.ComponentType + ACTIVE_FRONT_END: Subsystem.ComponentType + POWER_CONVERTER: Subsystem.ComponentType + SYNCHRONOUS_MACHINE: Subsystem.ComponentType + INDUCTION_MACHINE: Subsystem.ComponentType + GEARBOX: Subsystem.ComponentType + FUEL_CELL: Subsystem.ComponentType + PROPELLER_LOAD: Subsystem.ComponentType + OTHER_MECHANICAL_LOAD: Subsystem.ComponentType + BATTERY: Subsystem.ComponentType + SUPERCAPACITOR: Subsystem.ComponentType + SUPERCAPACITOR_SYSTEM: Subsystem.ComponentType + SHORE_POWER: Subsystem.ComponentType + GEAR_FIELD_NUMBER: _ClassVar[int] + ENGINE_FIELD_NUMBER: _ClassVar[int] + ELECTRIC_MACHINE_FIELD_NUMBER: _ClassVar[int] + TRANSFORMER_FIELD_NUMBER: _ClassVar[int] + CONVERTER1_FIELD_NUMBER: _ClassVar[int] + CONVERTER2_FIELD_NUMBER: _ClassVar[int] + BATTERY_FIELD_NUMBER: _ClassVar[int] + FUEL_CELL_FIELD_NUMBER: _ClassVar[int] + PROPELLER_FIELD_NUMBER: _ClassVar[int] + BUS_BREAKER_FIELD_NUMBER: _ClassVar[int] + SUPERCAPACITOR_FIELD_NUMBER: _ClassVar[int] + OTHER_LOAD_FIELD_NUMBER: _ClassVar[int] + POWER_TYPE_FIELD_NUMBER: _ClassVar[int] + COMPONENT_TYPE_FIELD_NUMBER: _ClassVar[int] + NAME_FIELD_NUMBER: _ClassVar[int] + RATED_POWER_KW_FIELD_NUMBER: _ClassVar[int] + RATED_SPEED_RPM_FIELD_NUMBER: _ClassVar[int] + RAMP_UP_RATE_LIMIT_PERCENT_PER_SECOND_FIELD_NUMBER: _ClassVar[int] + RAMP_DOWN_RATE_LIMIT_PERCENT_PER_SECOND_FIELD_NUMBER: _ClassVar[int] + BASE_LOAD_ORDER_FIELD_NUMBER: _ClassVar[int] + gear: Gear + engine: Engine + electric_machine: ElectricMachine + transformer: ElectricComponent + converter1: ElectricComponent + converter2: ElectricComponent + battery: Battery + fuel_cell: FuelCell + propeller: Propeller + bus_breaker: BusBreaker + supercapacitor: SuperCapacitor + other_load: ElectricComponent + power_type: Subsystem.PowerType + component_type: Subsystem.ComponentType + name: str + rated_power_kw: float + rated_speed_rpm: float + ramp_up_rate_limit_percent_per_second: float + ramp_down_rate_limit_percent_per_second: float + base_load_order: int + def __init__( + self, + gear: _Optional[_Union[Gear, _Mapping]] = ..., + engine: _Optional[_Union[Engine, _Mapping]] = ..., + electric_machine: _Optional[_Union[ElectricMachine, _Mapping]] = ..., + transformer: _Optional[_Union[ElectricComponent, _Mapping]] = ..., + converter1: _Optional[_Union[ElectricComponent, _Mapping]] = ..., + converter2: _Optional[_Union[ElectricComponent, _Mapping]] = ..., + battery: _Optional[_Union[Battery, _Mapping]] = ..., + fuel_cell: _Optional[_Union[FuelCell, _Mapping]] = ..., + propeller: _Optional[_Union[Propeller, _Mapping]] = ..., + bus_breaker: _Optional[_Union[BusBreaker, _Mapping]] = ..., + supercapacitor: _Optional[_Union[SuperCapacitor, _Mapping]] = ..., + other_load: _Optional[_Union[ElectricComponent, _Mapping]] = ..., + power_type: _Optional[_Union[Subsystem.PowerType, str]] = ..., + component_type: _Optional[_Union[Subsystem.ComponentType, str]] = ..., + name: _Optional[str] = ..., + rated_power_kw: _Optional[float] = ..., + rated_speed_rpm: _Optional[float] = ..., + ramp_up_rate_limit_percent_per_second: _Optional[float] = ..., + ramp_down_rate_limit_percent_per_second: _Optional[float] = ..., + base_load_order: _Optional[int] = ..., + ) -> None: ... + +class Switchboard(_message.Message): + __slots__ = ("switchboard_id", "subsystems") + SWITCHBOARD_ID_FIELD_NUMBER: _ClassVar[int] + SUBSYSTEMS_FIELD_NUMBER: _ClassVar[int] + switchboard_id: int + subsystems: _containers.RepeatedCompositeFieldContainer[Subsystem] + def __init__( + self, + switchboard_id: _Optional[int] = ..., + subsystems: _Optional[_Iterable[_Union[Subsystem, _Mapping]]] = ..., + ) -> None: ... + +class ShaftLine(_message.Message): + __slots__ = ("shaft_line_id", "subsystems") + SHAFT_LINE_ID_FIELD_NUMBER: _ClassVar[int] + SUBSYSTEMS_FIELD_NUMBER: _ClassVar[int] + shaft_line_id: int + subsystems: _containers.RepeatedCompositeFieldContainer[Subsystem] + def __init__( + self, + shaft_line_id: _Optional[int] = ..., + subsystems: _Optional[_Iterable[_Union[Subsystem, _Mapping]]] = ..., + ) -> None: ... + +class MechanicalSystem(_message.Message): + __slots__ = ("shaft_lines",) + SHAFT_LINES_FIELD_NUMBER: _ClassVar[int] + shaft_lines: _containers.RepeatedCompositeFieldContainer[ShaftLine] + def __init__( + self, shaft_lines: _Optional[_Iterable[_Union[ShaftLine, _Mapping]]] = ... + ) -> None: ... + +class ElectricSystem(_message.Message): + __slots__ = ("switchboards",) + SWITCHBOARDS_FIELD_NUMBER: _ClassVar[int] + switchboards: _containers.RepeatedCompositeFieldContainer[Switchboard] + def __init__( + self, switchboards: _Optional[_Iterable[_Union[Switchboard, _Mapping]]] = ... + ) -> None: ... + +class FuelStorage(_message.Message): + __slots__ = ("fuel_type", "capacity_kg") + FUEL_TYPE_FIELD_NUMBER: _ClassVar[int] + CAPACITY_KG_FIELD_NUMBER: _ClassVar[int] + fuel_type: FuelType + capacity_kg: float + def __init__( + self, + fuel_type: _Optional[_Union[FuelType, str]] = ..., + capacity_kg: _Optional[float] = ..., + ) -> None: ... + +class MachinerySystem(_message.Message): + __slots__ = ( + "name", + "propulsion_type", + "fuel_storage", + "maximum_allowed_genset_load_percentage", + "mechanical_system", + "electric_system", + "maximum_allowed_fuel_cell_load_percentage", + "average_base_load_percentage", + ) + + class PropulsionType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + MECHANICAL: _ClassVar[MachinerySystem.PropulsionType] + ELECTRIC: _ClassVar[MachinerySystem.PropulsionType] + HYBRID: _ClassVar[MachinerySystem.PropulsionType] + + MECHANICAL: MachinerySystem.PropulsionType + ELECTRIC: MachinerySystem.PropulsionType + HYBRID: MachinerySystem.PropulsionType + NAME_FIELD_NUMBER: _ClassVar[int] + PROPULSION_TYPE_FIELD_NUMBER: _ClassVar[int] + FUEL_STORAGE_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_ALLOWED_GENSET_LOAD_PERCENTAGE_FIELD_NUMBER: _ClassVar[int] + MECHANICAL_SYSTEM_FIELD_NUMBER: _ClassVar[int] + ELECTRIC_SYSTEM_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_ALLOWED_FUEL_CELL_LOAD_PERCENTAGE_FIELD_NUMBER: _ClassVar[int] + AVERAGE_BASE_LOAD_PERCENTAGE_FIELD_NUMBER: _ClassVar[int] + name: str + propulsion_type: MachinerySystem.PropulsionType + fuel_storage: _containers.RepeatedCompositeFieldContainer[FuelStorage] + maximum_allowed_genset_load_percentage: float + mechanical_system: MechanicalSystem + electric_system: ElectricSystem + maximum_allowed_fuel_cell_load_percentage: float + average_base_load_percentage: float + def __init__( + self, + name: _Optional[str] = ..., + propulsion_type: _Optional[_Union[MachinerySystem.PropulsionType, str]] = ..., + fuel_storage: _Optional[_Iterable[_Union[FuelStorage, _Mapping]]] = ..., + maximum_allowed_genset_load_percentage: _Optional[float] = ..., + mechanical_system: _Optional[_Union[MechanicalSystem, _Mapping]] = ..., + electric_system: _Optional[_Union[ElectricSystem, _Mapping]] = ..., + maximum_allowed_fuel_cell_load_percentage: _Optional[float] = ..., + average_base_load_percentage: _Optional[float] = ..., + ) -> None: ... diff --git a/machinery-system-structure/MachSysS/utility.py b/machinery-system-structure/MachSysS/utility.py index 488f8cf..f7208fd 100644 --- a/machinery-system-structure/MachSysS/utility.py +++ b/machinery-system-structure/MachSysS/utility.py @@ -23,7 +23,9 @@ def retrieve_machinery_system_from_file( return system -def retrieve_gymir_result_from_file(file: Union[str, io.BytesIO]) -> proto_gymir.GymirResult: +def retrieve_gymir_result_from_file( + file: Union[str, io.BytesIO] +) -> proto_gymir.GymirResult: if isinstance(file, str): file = open(file, "rb") system = proto_gymir.GymirResult() diff --git a/machinery-system-structure/build_package.sh b/machinery-system-structure/build_package.sh deleted file mode 100644 index 6d7526b..0000000 --- a/machinery-system-structure/build_package.sh +++ /dev/null @@ -1,7 +0,0 @@ -protoc -I=proto --proto_path=proto --python_out=MachSysS proto/system_structure.proto proto/gymir_result.proto proto/feems_result.proto -sed -e 's/import system_structure_pb2/from . import system_structure_pb2/' MachSysS/feems_result_pb2.py > MachSysS/feems_result_pb2_1.py -mv MachSysS/feems_result_pb2_1.py MachSysS/feems_result_pb2.py -nbdev_export -nbdev_test -black . -python setup.py sdist bdist_wheel \ No newline at end of file diff --git a/machinery-system-structure/build_package_linux.sh b/machinery-system-structure/build_package_linux.sh new file mode 100644 index 0000000..c1f6748 --- /dev/null +++ b/machinery-system-structure/build_package_linux.sh @@ -0,0 +1,13 @@ +set -e +echo "Building protobuf files" +protoc -I=proto --proto_path=proto --python_out=MachSysS proto/system_structure.proto proto/gymir_result.proto proto/feems_result.proto +echo "Fixing imports in protobuf files" +sed -i 's/import system_structure_pb2/from . import system_structure_pb2/' MachSysS/feems_result_pb2.py +echo "Exporting notebooks" +nbdev_export +echo "Running tests" +nbdev_test +echo "Formatting code" +black . +echo "Building package" +python -m build diff --git a/machinery-system-structure/build_package_mac.sh b/machinery-system-structure/build_package_mac.sh new file mode 100644 index 0000000..6b23bd1 --- /dev/null +++ b/machinery-system-structure/build_package_mac.sh @@ -0,0 +1,13 @@ +set -e +echo "Building protobuf files" +protoc -I=proto --proto_path=proto --pyi_out=MachSysS --python_out=MachSysS proto/system_structure.proto proto/gymir_result.proto proto/feems_result.proto +echo "Fixing imports in protobuf files" +sed -i '' 's/import system_structure_pb2/from . import system_structure_pb2/' MachSysS/feems_result_pb2.py +echo "Exporting notebooks" +nbdev_export +echo "Running tests" +nbdev_test +echo "Formatting code" +black . +echo "Building package" +python -m build \ No newline at end of file diff --git a/machinery-system-structure/index.ipynb b/machinery-system-structure/index.ipynb index e904e9f..19768b5 100644 --- a/machinery-system-structure/index.ipynb +++ b/machinery-system-structure/index.ipynb @@ -20,7 +20,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| include: false" + "# | include: false" ] }, { @@ -80,7 +80,7 @@ } ], "source": [ - "1+1" + "1 + 1" ] }, { diff --git a/machinery-system-structure/proto/system_structure.proto b/machinery-system-structure/proto/system_structure.proto index d35ec21..07169ac 100644 --- a/machinery-system-structure/proto/system_structure.proto +++ b/machinery-system-structure/proto/system_structure.proto @@ -139,6 +139,8 @@ message Engine { repeated EmissionCurve emission_curves = 10; EngineCycleType engine_cycle_type = 11; double unit_price_usd = 12; + double start_delay_s = 13; + double turn_off_power_kw = 14; } message ElectricMachine { @@ -160,6 +162,9 @@ message Battery { double initial_state_of_charge = 7; uint32 order_from_switchboard_or_shaftline = 8; double unit_price_usd = 9; + double self_discharge_percent_per_day = 10; + double state_of_energy_minimum = 11; + double state_of_energy_maximum = 12; } message ElectricComponent { @@ -178,6 +183,8 @@ message FuelCell { Fuel fuel = 6; double unit_price_usd = 7; uint32 number_modules = 8; + double power_minimum_specific= 9; + double start_delay_s = 10; } message Propeller { diff --git a/machinery-system-structure/settings.ini b/machinery-system-structure/settings.ini index 4ddd2dc..79047de 100644 --- a/machinery-system-structure/settings.ini +++ b/machinery-system-structure/settings.ini @@ -12,7 +12,7 @@ user = keviny author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF Ocean -version = 0.6.2 +version = 0.6.4 min_python = 3.10 audience = Developers language = English diff --git a/machinery-system-structure/setup.py b/machinery-system-structure/setup.py index 606a281..5aa2cd4 100644 --- a/machinery-system-structure/setup.py +++ b/machinery-system-structure/setup.py @@ -10,7 +10,10 @@ cfg = config["DEFAULT"] cfg_keys = "version description keywords author author_email".split() -expected = cfg_keys + "lib_name user branch license status min_python audience language".split() +expected = ( + cfg_keys + + "lib_name user branch license status min_python audience language".split() +) for o in expected: assert o in cfg, "missing expected setting: {}".format(o) setup_cfg = {o: cfg[o] for o in cfg_keys} @@ -72,7 +75,9 @@ ) long_description = re.sub( r"src=\"(.*)\." + ext + '"', - 'src="https://raw.githubusercontent.com/{}/{}'.format(cfg["user"], cfg["lib_name"]) + 'src="https://raw.githubusercontent.com/{}/{}'.format( + cfg["user"], cfg["lib_name"] + ) + "/" + cfg["branch"] + "/\\1." diff --git a/machinery-system-structure/tests/utility.py b/machinery-system-structure/tests/utility.py index 8629656..d702295 100644 --- a/machinery-system-structure/tests/utility.py +++ b/machinery-system-structure/tests/utility.py @@ -34,7 +34,9 @@ ELECTRIC_MACHINE_EFF_CURVE = np.array([load, eff]).transpose() # Create an efficiency curve for an electric inverter -CONVERTER_EFF = np.array([[1.00, 0.75, 0.50, 0.25], [0.98, 0.972, 0.97, 0.96]]).transpose() +CONVERTER_EFF = np.array( + [[1.00, 0.75, 0.50, 0.25], [0.98, 0.972, 0.97, 0.96]] +).transpose() logger = get_logger(__name__) @@ -48,7 +50,9 @@ class PowerSummary(NamedTuple): # noinspection PyShadowingNames -def create_random_monotonic_eff_curve(min_efficiency_perc=0, max_efficiency_perc=1) -> np.ndarray: +def create_random_monotonic_eff_curve( + min_efficiency_perc=0, max_efficiency_perc=1 +) -> np.ndarray: assert ( max_efficiency_perc > min_efficiency_perc ), "maximum efficiency should be greater than minimum efficiency" @@ -58,7 +62,10 @@ def create_random_monotonic_eff_curve(min_efficiency_perc=0, max_efficiency_perc load_check = np.arange(0, 1.001, 0.001) while not monotonic: load = np.array([0.25, 0.50, 0.75, 1.00]) - eff = np.random.rand(4) * (max_efficiency_perc - min_efficiency_perc) + min_efficiency_perc + eff = ( + np.random.rand(4) * (max_efficiency_perc - min_efficiency_perc) + + min_efficiency_perc + ) eff.sort() # Check monotonic mapping interp_function = PchipInterpolator(load, eff, extrapolate=True) @@ -132,8 +139,12 @@ def create_components( for i in range(number_components): rated_power = np.random.rand() * rated_power_max rated_speed = np.random.rand() * rated_speed_max - type_ = TypeComponent(np.ceil(np.random.rand() * (len(TypeComponent.__members__) - 1))) - components.append(Component("{0}{1}".format(name, i), type_, rated_power, rated_speed)) + type_ = TypeComponent( + np.ceil(np.random.rand() * (len(TypeComponent.__members__) - 1)) + ) + components.append( + Component("{0}{1}".format(name, i), type_, rated_power, rated_speed) + ) if number_components == 1: components[0].name = name return components[0] @@ -144,7 +155,9 @@ def create_components( def create_basic_components( name, number_components, rated_power_max, rated_speed_max ) -> Union[BasicComponent, List[BasicComponent]]: - components = create_components(name, number_components, rated_power_max, rated_speed_max) + components = create_components( + name, number_components, rated_power_max, rated_speed_max + ) basic_components = [] if type(components) is list: for component in components: @@ -296,7 +309,9 @@ def create_a_propulsion_drive( pass -def create_engine_component(name, rated_power_max, rated_speed_max, bsfc_curve=None) -> Engine: +def create_engine_component( + name, rated_power_max, rated_speed_max, bsfc_curve=None +) -> Engine: # Create an engine component with a arbitrary bsfc curve rated_power = rated_power_max * np.random.rand() rated_speed = rated_speed_max * np.random.rand() @@ -306,7 +321,9 @@ def create_engine_component(name, rated_power_max, rated_speed_max, bsfc_curve=N np.random.rand(10, 1) * 200, axis=1, ) - logger.warning("Efficiency of engine is not supplied, using random monotonic curve") + logger.warning( + "Efficiency of engine is not supplied, using random monotonic curve" + ) return Engine( type_=TypeComponent.MAIN_ENGINE, name=name, @@ -329,7 +346,9 @@ def create_main_engine_component( # noinspection PyTypeChecker -def create_fuel_cell_system(name: str, rated_power: float, switchboard_id: int) -> FuelCellSystem: +def create_fuel_cell_system( + name: str, rated_power: float, switchboard_id: int +) -> FuelCellSystem: """ Create a fuel cell system with random monotonic efficiency :param name: name @@ -387,7 +406,9 @@ def create_genset_component( """ if eff_curve_gen is None: eff_curve_gen = create_random_monotonic_eff_curve() - logger.warning("Efficiency of generator is not supplied, using random monotonic curve") + logger.warning( + "Efficiency of generator is not supplied, using random monotonic curve" + ) # Create a generator component, if not provided or not proper component if generator is None or type(generator) is not ElectricMachine: @@ -422,7 +443,9 @@ def create_dataframe_save_and_return(name, filename, columns): # Create a DataFrame and save it to csv values = np.append(np.zeros([1, 1]), np.random.rand(1, len(columns) - 1), axis=1) eff_curve = create_random_monotonic_eff_curve() - columns_eff = ["Efficiency@{}%".format(each_load) for each_load in eff_curve[:, 0].tolist()] + columns_eff = [ + "Efficiency@{}%".format(each_load) for each_load in eff_curve[:, 0].tolist() + ] columns += columns_eff values = np.append(values, np.reshape(eff_curve[:, 1], (1, -1)), axis=1) df = pd.DataFrame(values, columns=columns, index=[name]) @@ -463,7 +486,9 @@ def create_switchboard_with_components( switchboard_id=switchboard_id, ) electric_components = power_sources + power_consumers + pti_ptos + battery_systems - return Switchboard(name="switchboard", idx=switchboard_id, components=electric_components) + return Switchboard( + name="switchboard", idx=switchboard_id, components=electric_components + ) def create_shaftline_with_components( @@ -506,7 +531,9 @@ def create_shaftline_with_components( pti_pto = [] components = power_sources + power_consumers + pti_pto + gear return ShaftLine( - name=f"shaftline {shaft_line_id}", shaft_line_id=shaft_line_id, component_list=components + name=f"shaftline {shaft_line_id}", + shaft_line_id=shaft_line_id, + component_list=components, ) @@ -543,7 +570,9 @@ def set_random_power_input_consumer_pti_pto_energy_storage( # Assign the power input for the consumers, pti/pto, energy storage devices # randomly within the total power produced no_electric_load_switchboard = ( - switchboard.no_consumers + switchboard.no_pti_pto + switchboard.no_energy_storage + switchboard.no_consumers + + switchboard.no_pti_pto + + switchboard.no_energy_storage ) count_electric_load = 0 remaining_power = total_power_produced.copy() @@ -571,7 +600,9 @@ def set_random_power_input_consumer_pti_pto_energy_storage( / 100 ) if i in [TypePower.PTI_PTO.value, TypePower.ENERGY_STORAGE.value]: - component.power_input *= component.load_sharing_mode * component.status + component.power_input *= ( + component.load_sharing_mode * component.status + ) remaining_power -= component.power_input index_overload = remaining_power < 0 component.power_input[index_overload] += remaining_power[index_overload] @@ -579,14 +610,18 @@ def set_random_power_input_consumer_pti_pto_energy_storage( sum_power_input_power_consumer += component.power_input * ( i == TypePower.POWER_CONSUMER.value ) - sum_power_input_pti_pto += component.power_input * (i == TypePower.PTI_PTO.value) + sum_power_input_pti_pto += component.power_input * ( + i == TypePower.PTI_PTO.value + ) sum_power_input_energy_storage += component.power_input * ( i == TypePower.ENERGY_STORAGE.value ) # noinspection PyUnresolvedReferences if not np.isclose( total_power_produced, - sum_power_input_power_consumer + sum_power_input_pti_pto + sum_power_input_energy_storage, + sum_power_input_power_consumer + + sum_power_input_pti_pto + + sum_power_input_energy_storage, ).all(): msg = "Power balance is not met between the produced power and consumed power" logger.error(msg) @@ -608,7 +643,9 @@ def set_random_power_input_consumer_pti_pto_energy_storage( load_perc_symmetric_loaded_power_source = np.zeros( sum_power_avail_from_equally_load_sharing_sources.shape ) - index_no_power_available = sum_power_avail_from_equally_load_sharing_sources == 0 + index_no_power_available = ( + sum_power_avail_from_equally_load_sharing_sources == 0 + ) if np.bitwise_and( sum_power_output_from_equally_load_sharing_sources > 0, index_no_power_available, @@ -698,7 +735,9 @@ def create_electric_components_for_switchboard( # Create a power source component if type_component == TypeComponent.FUEL_CELL_SYSTEM: # Create a fuel cell system - component = create_fuel_cell_system(name_component, rated_power[i], switchboard_id) + component = create_fuel_cell_system( + name_component, rated_power[i], switchboard_id + ) else: # Create a generator component component = ElectricMachine( diff --git a/machinery-system-structure/tests/utility_compare_proto.py b/machinery-system-structure/tests/utility_compare_proto.py index 86a39ed..3f659c4 100644 --- a/machinery-system-structure/tests/utility_compare_proto.py +++ b/machinery-system-structure/tests/utility_compare_proto.py @@ -13,6 +13,7 @@ Creator: Kevin K. Yum CopyRight: SINTEF Ocean """ + import re from dataclasses import dataclass from functools import reduce @@ -47,7 +48,8 @@ def convert_camel_case_list_to_snake_case_list(camel_case_list: List[str]) -> Li :return: list of strings in snake case """ return [ - convert_camel_case_to_snake_case(camel_case_string) for camel_case_string in camel_case_list + convert_camel_case_to_snake_case(camel_case_string) + for camel_case_string in camel_case_list ] @@ -56,6 +58,7 @@ class DiffSubsystems: """ Class to store the differences between two subsystems. """ + diff_attributes: DeepDiff components_removed: List[str] components_added: List[str] @@ -80,6 +83,7 @@ class DiffSwitchboardShaftLines: """ Class to store the differences between two switchboards. """ + subsystems_removed: List[str] subsystems_added: List[str] subsystems_modified: Dict[str, DiffSubsystems] @@ -133,7 +137,7 @@ def compare_proto_components(comp1: ProtoComponent, comp2: ProtoComponent) -> De t2=comp2_dict, ignore_order=True, report_repetition=True, - ignore_string_case=True + ignore_string_case=True, ) @@ -148,24 +152,37 @@ def compare_proto_subsystems( :return: dict of differences """ non_component_attribute_keys = [ - "powerType", "componentType", "name", "ratedPowerKw", "ratedSpeedRpm" + "powerType", + "componentType", + "name", + "ratedPowerKw", + "ratedSpeedRpm", ] subsystem1_dict = MessageToDict(subsystem1) subsystem2_dict = MessageToDict(subsystem2) subsystem1_dict_non_components = reduce( - lambda acc, key: {**acc, **{key: subsystem1_dict.pop(key)}} if key in subsystem1_dict else acc, + lambda acc, key: ( + {**acc, **{key: subsystem1_dict.pop(key)}} + if key in subsystem1_dict + else acc + ), non_component_attribute_keys, - {} + {}, ) subsystem2_dict_non_components = reduce( - lambda acc, key: {**acc, **{key: subsystem2_dict.pop(key)}} if key in subsystem2_dict else acc, + lambda acc, key: ( + {**acc, **{key: subsystem2_dict.pop(key)}} + if key in subsystem2_dict + else acc + ), non_component_attribute_keys, - {} + {}, ) diff_non_components = DeepDiff( - subsystem1_dict_non_components, subsystem2_dict_non_components, + subsystem1_dict_non_components, + subsystem2_dict_non_components, ignore_order=True, - report_repetition=True + report_repetition=True, ) components_list_subsystem1 = convert_camel_case_list_to_snake_case_list( list(subsystem1_dict.keys()) @@ -173,20 +190,25 @@ def compare_proto_subsystems( components_list_subsystem2 = convert_camel_case_list_to_snake_case_list( list(subsystem2_dict.keys()) ) - components_removed = list(set(components_list_subsystem1) - set(components_list_subsystem2)) - components_added = list(set(components_list_subsystem2) - set(components_list_subsystem1)) - components_common = list(set(components_list_subsystem1) & set(components_list_subsystem2)) + components_removed = list( + set(components_list_subsystem1) - set(components_list_subsystem2) + ) + components_added = list( + set(components_list_subsystem2) - set(components_list_subsystem1) + ) + components_common = list( + set(components_list_subsystem1) & set(components_list_subsystem2) + ) diff_components = {} for component_name in components_common: diff_components[component_name] = compare_proto_components( - getattr(subsystem1, component_name), - getattr(subsystem2, component_name) + getattr(subsystem1, component_name), getattr(subsystem2, component_name) ) return DiffSubsystems( diff_attributes=diff_non_components, components_removed=components_removed, components_added=components_added, - components_modified=diff_components + components_modified=diff_components, ) @@ -203,19 +225,23 @@ def compare_proto_switchboards_shaft_lines( diff = DiffSwitchboardShaftLines( subsystems_removed=[], subsystems_added=[subsystem.name for subsystem in switchboard2.subsystems], - subsystems_modified={} + subsystems_modified={}, ) for subsystem_ref in switchboard1.subsystems: try: - subsystem_to_compare = next(filter( - lambda subsystem: subsystem_ref.name == subsystem.name, - switchboard2.subsystems - )) + subsystem_to_compare = next( + filter( + lambda subsystem: subsystem_ref.name == subsystem.name, + switchboard2.subsystems, + ) + ) except StopIteration: diff.subsystems_removed.append(subsystem_ref.name) else: diff.subsystems_added.remove(subsystem_ref.name) - diff_subsystem = compare_proto_subsystems(subsystem_ref, subsystem_to_compare) + diff_subsystem = compare_proto_subsystems( + subsystem_ref, subsystem_to_compare + ) diff.subsystems_modified[subsystem_ref.name] = diff_subsystem return diff @@ -232,21 +258,30 @@ def compare_proto_electric_systems( """ diff = DiffElectricPowerSystem( switchboards_removed=[], - switchboards_added=[switchboard.switchboard_id for switchboard in eps2.switchboards], - switchboards_modified={} + switchboards_added=[ + switchboard.switchboard_id for switchboard in eps2.switchboards + ], + switchboards_modified={}, ) for switchboard_ref in eps1.switchboards: try: - switchboard_to_compare = next(filter( - lambda switchboard: switchboard_ref.switchboard_id == switchboard.switchboard_id, - eps2.switchboards - )) + switchboard_to_compare = next( + filter( + lambda switchboard: switchboard_ref.switchboard_id + == switchboard.switchboard_id, + eps2.switchboards, + ) + ) except StopIteration: diff.switchboards_removed.append(switchboard_ref.switchboard_id) else: diff.switchboards_added.remove(switchboard_ref.switchboard_id) - diff_switchboard = compare_proto_switchboards_shaft_lines(switchboard_ref, switchboard_to_compare) - diff.switchboards_modified[switchboard_ref.switchboard_id] = diff_switchboard + diff_switchboard = compare_proto_switchboards_shaft_lines( + switchboard_ref, switchboard_to_compare + ) + diff.switchboards_modified[switchboard_ref.switchboard_id] = ( + diff_switchboard + ) return diff @@ -262,20 +297,27 @@ def compare_proto_mechanical_system( """ diff = DiffMechanicalSystem( shaft_lines_removed=[], - shaft_lines_added=[shaft_line.shaft_line_id for shaft_line in shaft_lines2.shaft_lines], - shaft_lines_modified={} + shaft_lines_added=[ + shaft_line.shaft_line_id for shaft_line in shaft_lines2.shaft_lines + ], + shaft_lines_modified={}, ) for shaft_line_ref in shaft_lines1.shaft_lines: try: - shaft_line_to_compare = next(filter( - lambda shaft_line: shaft_line_ref.shaft_line_id == shaft_line.shaft_line_id, - shaft_lines2.shaft_lines - )) + shaft_line_to_compare = next( + filter( + lambda shaft_line: shaft_line_ref.shaft_line_id + == shaft_line.shaft_line_id, + shaft_lines2.shaft_lines, + ) + ) except StopIteration: diff.shaft_lines_removed.append(shaft_line_ref.shaft_line_id) else: diff.shaft_lines_added.remove(shaft_line_ref.shaft_line_id) - diff_shaft_line = compare_proto_switchboards_shaft_lines(shaft_line_ref, shaft_line_to_compare) + diff_shaft_line = compare_proto_switchboards_shaft_lines( + shaft_line_ref, shaft_line_to_compare + ) diff.shaft_lines_modified[shaft_line_ref.shaft_line_id] = diff_shaft_line return diff @@ -292,12 +334,16 @@ def compare_proto_machinery_system( """ machinery_system1_dict = MessageToDict(machinery1) machinery_system2_dict = MessageToDict(machinery2) - machinery_system1_dict.pop('electricSystem', None) - machinery_system2_dict.pop('electricSystem', None) - machinery_system1_dict.pop('mechanicalSystem', None) - machinery_system2_dict.pop('mechanicalSystem', None) + machinery_system1_dict.pop("electricSystem", None) + machinery_system2_dict.pop("electricSystem", None) + machinery_system1_dict.pop("mechanicalSystem", None) + machinery_system2_dict.pop("mechanicalSystem", None) return DiffMachinerySystem( diff_attributes=DeepDiff(machinery_system1_dict, machinery_system2_dict), - diff_electric_system=compare_proto_electric_systems(machinery1.electric_system, machinery2.electric_system), - diff_mechanical_system=compare_proto_mechanical_system(machinery1.mechanical_system, machinery2.mechanical_system), + diff_electric_system=compare_proto_electric_systems( + machinery1.electric_system, machinery2.electric_system + ), + diff_mechanical_system=compare_proto_mechanical_system( + machinery1.mechanical_system, machinery2.mechanical_system + ), ) diff --git a/requirements_dev.txt b/requirements_dev.txt index 51d0135..12a6498 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -12,6 +12,7 @@ nbdev deepdiff plotly poetry +build -e ./feems -e ./machinery-system-structure -e ./RunFeemsSim From f255a7a69ffa39e3b10379583163f5e47ffbf358 Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 26 Mar 2024 08:33:46 +0100 Subject: [PATCH 02/28] pipeline for testing added --- .github/workflows/test.yml | 56 ++++++++++++++++++++++++++++++++++++++ RunFEEMSSim/settings.ini | 4 +-- feems/pyproject.toml | 3 +- 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..aabcfa8 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,56 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Python package + +on: + push: + branches: ["*"] + pull_request: + branches: ["*"] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12"] + project: + - feems + - machinery-system-structure + - RunFEEMSSim + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + pip install -r requirements_dev.txt + + - name: Test with pytest if the project is feems else test with nbdev + run: | + cd ${{ matrix.project }} + if [ "${{ matrix.project }}" = "feems" ]; then + pytest + else + nbdev_test --do_print + fi + + - name: Lint with black + run: | + black --check . diff --git a/RunFEEMSSim/settings.ini b/RunFEEMSSim/settings.ini index 5efde60..5b28dfa 100644 --- a/RunFEEMSSim/settings.ini +++ b/RunFEEMSSim/settings.ini @@ -8,8 +8,8 @@ author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF branch = master -version = 0.2.1a -min_python = 3.9 +version = 0.2.2 +min_python = 3.10 audience = Developers language = English custom_sidebar = False diff --git a/feems/pyproject.toml b/feems/pyproject.toml index 6631d7b..f222900 100644 --- a/feems/pyproject.toml +++ b/feems/pyproject.toml @@ -8,7 +8,7 @@ include = ["feems/py.typed"] license = "Proprietary" [tool.poetry.dependencies] -python = ">=3.9,<3.13" +python = ">=3.10,<3.13" pandas = "^2.1.1" scipy = "^1.11.2" @@ -30,4 +30,3 @@ target-version = ['py37'] [build-system] requires = ["poetry>=1.4.0", "setuptools>=40.8.0"] build-backend = "poetry.core.masonry.api" - From d92bacfc9e717bd9cd80968117e6de5449458e63 Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 26 Mar 2024 08:36:32 +0100 Subject: [PATCH 03/28] fixed requirement --- requirements_dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index 12a6498..4c59531 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -15,5 +15,5 @@ poetry build -e ./feems -e ./machinery-system-structure --e ./RunFeemsSim +-e ./RunFEEMSSim -r requirements.txt From acbccdb5a606a91b760c8554f9b71ab0f797b4c7 Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 26 Mar 2024 09:37:06 +0100 Subject: [PATCH 04/28] linting --- .github/workflows/test.yml | 4 - RunFEEMSSim/00_machinery_calculation.ipynb | 85 ++++++--- RunFEEMSSim/01_pms_basic.ipynb | 25 +-- RunFEEMSSim/RunFeemsSim/__init__.py | 2 +- RunFEEMSSim/RunFeemsSim/_modidx.py | 169 ++++++++++++------ .../RunFeemsSim/machinery_calculation.py | 12 +- RunFEEMSSim/RunFeemsSim/pms_basic.py | 32 ++-- RunFEEMSSim/index.ipynb | 2 +- .../components_model/component_electric.py | 15 +- feems/feems/fuel.py | 21 ++- feems/feems/simulation_interface.py | 4 +- feems/tests/test_components.py | 2 +- feems/tests/test_node.py | 6 +- feems/tests/test_system.py | 6 +- .../MachSysS/__init__.py | 2 +- 15 files changed, 253 insertions(+), 134 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aabcfa8..88cf270 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -50,7 +50,3 @@ jobs: else nbdev_test --do_print fi - - - name: Lint with black - run: | - black --check . diff --git a/RunFEEMSSim/00_machinery_calculation.ipynb b/RunFEEMSSim/00_machinery_calculation.ipynb index b0c67e7..69a084e 100644 --- a/RunFEEMSSim/00_machinery_calculation.ipynb +++ b/RunFEEMSSim/00_machinery_calculation.ipynb @@ -19,7 +19,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| default_exp machinery_calculation\n", + "# | default_exp machinery_calculation\n", "%load_ext autoreload\n", "%autoreload 2" ] @@ -30,7 +30,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| include: false\n", + "# | include: false\n", "from nbdev.showdoc import *" ] }, @@ -40,7 +40,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| export\n", + "# | export\n", "from typing import List, Union, Type, TypeVar\n", "\n", "import MachSysS.gymir_result_pb2 as proto_gymir\n", @@ -148,7 +148,9 @@ " # set power load\n", " number_of_propulsors = len(self.electric_system.propulsion_drives)\n", " if self.system_is_not_electric:\n", - " number_of_propulsors = self.system_feems.mechanical_system.no_mechanical_loads\n", + " number_of_propulsors = (\n", + " self.system_feems.mechanical_system.no_mechanical_loads\n", + " )\n", " number_of_other_loads = len(self.electric_system.other_load)\n", " if number_of_other_loads == 0:\n", " assert np.all(\n", @@ -323,7 +325,7 @@ " df = convert_proto_timeseries_to_pd_dataframe(time_series)\n", " self._set_input_load_time_interval_from_propulsion_power_time_series(\n", " propulsion_power_time_series=df[\"propulsion_power_kw\"],\n", - " auxiliary_load_kw=df[\"auxiliary_power_kw\"].values\n", + " auxiliary_load_kw=df[\"auxiliary_power_kw\"].values,\n", " )\n", " return self._run_simulation(\n", " fuel_specified_by=fuel_specified_by,\n", @@ -386,7 +388,10 @@ "from MachSysS.convert_to_feems import convert_proto_propulsion_system_to_feems\n", "from MachSysS.utility import retrieve_machinery_system_from_file\n", "from MachSysS.convert_feems_result_to_proto import FEEMSResultConverter\n", - "from RunFeemsSim.machinery_calculation import MachineryCalculation, convert_gymir_result_to_propulsion_power_series\n", + "from RunFeemsSim.machinery_calculation import (\n", + " MachineryCalculation,\n", + " convert_gymir_result_to_propulsion_power_series,\n", + ")\n", "\n", "pd.options.plotting.backend = \"plotly\"" ] @@ -988,13 +993,14 @@ "def create_gymir_result() -> GymirResult:\n", " return GymirResult(\n", " name=\"test\",\n", - " auxiliary_load_kw = random.random() * 500,\n", + " auxiliary_load_kw=random.random() * 500,\n", " result=[\n", " SimulationInstance(epoch_s=100 * index + 1, power_kw=2000 * random.random())\n", " for index, _ in enumerate(range(10))\n", " ],\n", " )\n", "\n", + "\n", "# Testing convert gymir result to propulsion power series\n", "gymir_result = create_gymir_result()\n", "propulsion_power = convert_gymir_result_to_propulsion_power_series(gymir_result)\n", @@ -1012,18 +1018,20 @@ " gymir_result=gymir_result\n", ")\n", "if save_the_result:\n", - " with open(\"system_proto.mss\", 'wb') as file:\n", + " with open(\"system_proto.mss\", \"wb\") as file:\n", " file.write(system_proto.SerializeToString())\n", "average_power_consumption = 0\n", "running_hours_mean = 0\n", "for power_source in machinery_calculation.electric_system.power_sources:\n", " running_hours_mean += (power_source.power_output > 0).mean()\n", - " generator_run_point = \\\n", + " generator_run_point = (\n", " power_source.get_fuel_cons_load_bsfc_from_power_out_generator_kw()\n", + " )\n", "for propulsor in machinery_calculation.electric_system.propulsion_drives:\n", " average_power_consumption += propulsor.power_input.mean()\n", - "average_bsfc_for_engines = res.fuel_consumption_total_kg / \\\n", - " (res.duration_s / 3600000 * average_power_consumption / 0.95)\n", + "average_bsfc_for_engines = res.fuel_consumption_total_kg / (\n", + " res.duration_s / 3600000 * average_power_consumption / 0.95\n", + ")\n", "print(f\"Average bsfc for engines: {average_bsfc_for_engines} g/kWh\")\n", "assert 200 < average_bsfc_for_engines < 385" ] @@ -1045,14 +1053,12 @@ "# Testing MachineryCalculation with time series\n", "auxiliary_power_kw = 100\n", "res_scalar_aux = machinery_calculation.calculate_machinery_system_output_from_propulsion_power_time_series(\n", - " propulsion_power=propulsion_power,\n", - " auxiliary_power_kw=auxiliary_power_kw\n", + " propulsion_power=propulsion_power, auxiliary_power_kw=auxiliary_power_kw\n", ")\n", "print(len(propulsion_power))\n", "auxiliary_power_kw = np.ones(len(propulsion_power)) * 100\n", "res_array_aux = machinery_calculation.calculate_machinery_system_output_from_propulsion_power_time_series(\n", - " propulsion_power=propulsion_power,\n", - " auxiliary_power_kw=auxiliary_power_kw\n", + " propulsion_power=propulsion_power, auxiliary_power_kw=auxiliary_power_kw\n", ")" ] }, @@ -1094,21 +1100,48 @@ } ], "source": [ - "total_energy_consumption_kwh = np.array([\n", - " [prop_power_inst.propulsion_power_kw, prop_power_inst.auxiliary_power_kw]\n", - " for prop_power_inst in time_series_result.propulsion_power_timeseries\n", - "]) * 60 / 3600\n", + "total_energy_consumption_kwh = (\n", + " np.array(\n", + " [\n", + " [prop_power_inst.propulsion_power_kw, prop_power_inst.auxiliary_power_kw]\n", + " for prop_power_inst in time_series_result.propulsion_power_timeseries\n", + " ]\n", + " )\n", + " * 60\n", + " / 3600\n", + ")\n", "total_propulsion_energy_consumption_kwh = np.sum(total_energy_consumption_kwh[:, 0])\n", "total_auxiliary_energy_consumption_kwh = np.sum(total_energy_consumption_kwh[:, 1])\n", - "average_bsfc_for_main_engine = res.mechanical_system.multi_fuel_consumption_total_kg.natural_gas / total_propulsion_energy_consumption_kwh * 1000\n", - "average_pilot_bsfc_for_main_engine = res.mechanical_system.multi_fuel_consumption_total_kg.diesel / total_propulsion_energy_consumption_kwh * 1000\n", - "average_bsfc_for_auxiliary_engines = res.electric_system.multi_fuel_consumption_total_kg.natural_gas / total_auxiliary_energy_consumption_kwh * 1000 * 0.95\n", + "average_bsfc_for_main_engine = (\n", + " res.mechanical_system.multi_fuel_consumption_total_kg.natural_gas\n", + " / total_propulsion_energy_consumption_kwh\n", + " * 1000\n", + ")\n", + "average_pilot_bsfc_for_main_engine = (\n", + " res.mechanical_system.multi_fuel_consumption_total_kg.diesel\n", + " / total_propulsion_energy_consumption_kwh\n", + " * 1000\n", + ")\n", + "average_bsfc_for_auxiliary_engines = (\n", + " res.electric_system.multi_fuel_consumption_total_kg.natural_gas\n", + " / total_auxiliary_energy_consumption_kwh\n", + " * 1000\n", + " * 0.95\n", + ")\n", "print(f\"Average bsfc for main engine: {average_bsfc_for_main_engine} g/kWh\")\n", - "print(f\"Average bsfc for pilot fuel for main engine: {average_pilot_bsfc_for_main_engine} g/kWh\")\n", + "print(\n", + " f\"Average bsfc for pilot fuel for main engine: {average_pilot_bsfc_for_main_engine} g/kWh\"\n", + ")\n", "print(f\"Average bsfc for auxiliary engines: {average_bsfc_for_auxiliary_engines} g/kWh\")\n", - "assert 150 > average_bsfc_for_main_engine > 140, \"Average bsfc for main engine is not within expected range\"\n", - "assert 1.0 > average_pilot_bsfc_for_main_engine > 0.7, \"Average pilot bsfc for main engine is not within expected range\"\n", - "assert 224 > average_bsfc_for_auxiliary_engines > 210, \"Average bsfc for auxiliary engines is not within expected range\"" + "assert (\n", + " 150 > average_bsfc_for_main_engine > 140\n", + "), \"Average bsfc for main engine is not within expected range\"\n", + "assert (\n", + " 1.0 > average_pilot_bsfc_for_main_engine > 0.7\n", + "), \"Average pilot bsfc for main engine is not within expected range\"\n", + "assert (\n", + " 224 > average_bsfc_for_auxiliary_engines > 210\n", + "), \"Average bsfc for auxiliary engines is not within expected range\"" ] }, { diff --git a/RunFEEMSSim/01_pms_basic.ipynb b/RunFEEMSSim/01_pms_basic.ipynb index bdf344c..3fd9d5a 100644 --- a/RunFEEMSSim/01_pms_basic.ipynb +++ b/RunFEEMSSim/01_pms_basic.ipynb @@ -19,7 +19,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| default_exp pms_basic" + "# | default_exp pms_basic" ] }, { @@ -28,7 +28,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| include: false\n", + "# | include: false\n", "from nbdev.showdoc import *" ] }, @@ -38,7 +38,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| export\n", + "# | export\n", "import itertools\n", "from dataclasses import dataclass\n", "from itertools import chain\n", @@ -130,17 +130,14 @@ " electric_system = (\n", " system if not hasattr(system, \"electric_system\") else system.electric_system\n", " )\n", - " power_sources = [\n", - " component\n", - " for component in electric_system.power_sources\n", - " ]\n", + " power_sources = [component for component in electric_system.power_sources]\n", " if component_types is not None:\n", " power_sources = [\n", - " component for component in power_sources if component.type in component_types\n", + " component\n", + " for component in power_sources\n", + " if component.type in component_types\n", " ]\n", - " rated_power_all = [\n", - " power_source.rated_power for power_source in power_sources\n", - " ]\n", + " rated_power_all = [power_source.rated_power for power_source in power_sources]\n", " return min_load_table_dict(\n", " rated_power_all, maximum_allowed_genset_load_percentage / 100\n", " )\n", @@ -200,7 +197,11 @@ " n_datapoint_max = max(n_datapoints)\n", " if len(n_datapoints) > 1:\n", " for swb_id, power_kw in power_kw_per_switchboard.items():\n", - " if len(power_kw) < n_datapoint_max and len(power_kw) != 1 and power_kw[0] != 0:\n", + " if (\n", + " len(power_kw) < n_datapoint_max\n", + " and len(power_kw) != 1\n", + " and power_kw[0] != 0\n", + " ):\n", " raise ValueError(\n", " f\"Load vector for switchboard {swb_id} has length {len(power_kw)} \"\n", " f\"but should have length {n_datapoint_max} or 1 with 0 value.\"\n", diff --git a/RunFEEMSSim/RunFeemsSim/__init__.py b/RunFEEMSSim/RunFeemsSim/__init__.py index f4983e9..b5fdc75 100644 --- a/RunFEEMSSim/RunFeemsSim/__init__.py +++ b/RunFEEMSSim/RunFeemsSim/__init__.py @@ -1 +1 @@ -__version__ = "0.2.1a" +__version__ = "0.2.2" diff --git a/RunFEEMSSim/RunFeemsSim/_modidx.py b/RunFEEMSSim/RunFeemsSim/_modidx.py index 387440b..5fc3c1b 100644 --- a/RunFEEMSSim/RunFeemsSim/_modidx.py +++ b/RunFEEMSSim/RunFeemsSim/_modidx.py @@ -1,56 +1,117 @@ # Autogenerated by nbdev -d = { 'settings': { 'branch': 'master', - 'doc_baseurl': '/RunFeemsSim/', - 'doc_host': 'https://kevinkoosup.yum@sintef.no.github.io', - 'git_url': 'https://SintefOceanEnergySystem@dev.azure.com/SintefOceanEnergySystem/FEEMSService/_git/RunFEEMSSim', - 'lib_path': 'RunFeemsSim'}, - 'syms': { 'RunFeemsSim.machinery_calculation': { 'RunFeemsSim.machinery_calculation.MachineryCalculation': ( 'machinery_calculation.html#machinerycalculation', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation.__init__': ( 'machinery_calculation.html#machinerycalculation.__init__', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation._run_simulation': ( 'machinery_calculation.html#machinerycalculation._run_simulation', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation._set_equal_load_sharing_on_power_sources': ( 'machinery_calculation.html#machinerycalculation._set_equal_load_sharing_on_power_sources', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation._set_input_load_from_gymir_result': ( 'machinery_calculation.html#machinerycalculation._set_input_load_from_gymir_result', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation._set_input_load_time_interval_from_propulsion_power_time_series': ( 'machinery_calculation.html#machinerycalculation._set_input_load_time_interval_from_propulsion_power_time_series', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation._set_status_for_mechanical_system': ( 'machinery_calculation.html#machinerycalculation._set_status_for_mechanical_system', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation.calculate_machinery_system_output_from_gymir_result': ( 'machinery_calculation.html#machinerycalculation.calculate_machinery_system_output_from_gymir_result', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation.calculate_machinery_system_output_from_propulsion_power_time_series': ( 'machinery_calculation.html#machinerycalculation.calculate_machinery_system_output_from_propulsion_power_time_series', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation.calculate_machinery_system_output_from_statistics': ( 'machinery_calculation.html#machinerycalculation.calculate_machinery_system_output_from_statistics', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation.calculate_machinery_system_output_from_time_series_result': ( 'machinery_calculation.html#machinerycalculation.calculate_machinery_system_output_from_time_series_result', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation.electric_system': ( 'machinery_calculation.html#machinerycalculation.electric_system', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.MachineryCalculation.system_is_not_electric': ( 'machinery_calculation.html#machinerycalculation.system_is_not_electric', - 'RunFeemsSim/machinery_calculation.py'), - 'RunFeemsSim.machinery_calculation.convert_gymir_result_to_propulsion_power_series': ( 'machinery_calculation.html#convert_gymir_result_to_propulsion_power_series', - 'RunFeemsSim/machinery_calculation.py')}, - 'RunFeemsSim.pms_basic': { 'RunFeemsSim.pms_basic.PmsLoadTable': ('pms_basic.html#pmsloadtable', 'RunFeemsSim/pms_basic.py'), - 'RunFeemsSim.pms_basic.PmsLoadTable.__post_init__': ( 'pms_basic.html#pmsloadtable.__post_init__', - 'RunFeemsSim/pms_basic.py'), - 'RunFeemsSim.pms_basic.PmsLoadTable.on_pattern': ( 'pms_basic.html#pmsloadtable.on_pattern', - 'RunFeemsSim/pms_basic.py'), - 'RunFeemsSim.pms_basic.PmsLoadTable.sorted_load_table': ( 'pms_basic.html#pmsloadtable.sorted_load_table', - 'RunFeemsSim/pms_basic.py'), - 'RunFeemsSim.pms_basic.PmsLoadTableSimulationInterface': ( 'pms_basic.html#pmsloadtablesimulationinterface', - 'RunFeemsSim/pms_basic.py'), - 'RunFeemsSim.pms_basic.PmsLoadTableSimulationInterface.__init__': ( 'pms_basic.html#pmsloadtablesimulationinterface.__init__', - 'RunFeemsSim/pms_basic.py'), - 'RunFeemsSim.pms_basic.PmsLoadTableSimulationInterface.set_status': ( 'pms_basic.html#pmsloadtablesimulationinterface.set_status', - 'RunFeemsSim/pms_basic.py'), - 'RunFeemsSim.pms_basic.get_min_load_table_dict_from_feems_system': ( 'pms_basic.html#get_min_load_table_dict_from_feems_system', - 'RunFeemsSim/pms_basic.py'), - 'RunFeemsSim.pms_basic.get_min_load_table_dict_from_proto_system': ( 'pms_basic.html#get_min_load_table_dict_from_proto_system', - 'RunFeemsSim/pms_basic.py'), - 'RunFeemsSim.pms_basic.get_rated_power_from_power_source': ( 'pms_basic.html#get_rated_power_from_power_source', - 'RunFeemsSim/pms_basic.py'), - 'RunFeemsSim.pms_basic.min_load_table_dict': ( 'pms_basic.html#min_load_table_dict', - 'RunFeemsSim/pms_basic.py')}}} +d = { + "settings": { + "branch": "master", + "doc_baseurl": "/RunFeemsSim/", + "doc_host": "https://kevinkoosup.yum@sintef.no.github.io", + "git_url": "https://SintefOceanEnergySystem@dev.azure.com/SintefOceanEnergySystem/FEEMSService/_git/RunFEEMSSim", + "lib_path": "RunFeemsSim", + }, + "syms": { + "RunFeemsSim.machinery_calculation": { + "RunFeemsSim.machinery_calculation.MachineryCalculation": ( + "machinery_calculation.html#machinerycalculation", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation.__init__": ( + "machinery_calculation.html#machinerycalculation.__init__", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation._run_simulation": ( + "machinery_calculation.html#machinerycalculation._run_simulation", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation._set_equal_load_sharing_on_power_sources": ( + "machinery_calculation.html#machinerycalculation._set_equal_load_sharing_on_power_sources", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation._set_input_load_from_gymir_result": ( + "machinery_calculation.html#machinerycalculation._set_input_load_from_gymir_result", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation._set_input_load_time_interval_from_propulsion_power_time_series": ( + "machinery_calculation.html#machinerycalculation._set_input_load_time_interval_from_propulsion_power_time_series", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation._set_status_for_mechanical_system": ( + "machinery_calculation.html#machinerycalculation._set_status_for_mechanical_system", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation.calculate_machinery_system_output_from_gymir_result": ( + "machinery_calculation.html#machinerycalculation.calculate_machinery_system_output_from_gymir_result", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation.calculate_machinery_system_output_from_propulsion_power_time_series": ( + "machinery_calculation.html#machinerycalculation.calculate_machinery_system_output_from_propulsion_power_time_series", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation.calculate_machinery_system_output_from_statistics": ( + "machinery_calculation.html#machinerycalculation.calculate_machinery_system_output_from_statistics", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation.calculate_machinery_system_output_from_time_series_result": ( + "machinery_calculation.html#machinerycalculation.calculate_machinery_system_output_from_time_series_result", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation.electric_system": ( + "machinery_calculation.html#machinerycalculation.electric_system", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.MachineryCalculation.system_is_not_electric": ( + "machinery_calculation.html#machinerycalculation.system_is_not_electric", + "RunFeemsSim/machinery_calculation.py", + ), + "RunFeemsSim.machinery_calculation.convert_gymir_result_to_propulsion_power_series": ( + "machinery_calculation.html#convert_gymir_result_to_propulsion_power_series", + "RunFeemsSim/machinery_calculation.py", + ), + }, + "RunFeemsSim.pms_basic": { + "RunFeemsSim.pms_basic.PmsLoadTable": ( + "pms_basic.html#pmsloadtable", + "RunFeemsSim/pms_basic.py", + ), + "RunFeemsSim.pms_basic.PmsLoadTable.__post_init__": ( + "pms_basic.html#pmsloadtable.__post_init__", + "RunFeemsSim/pms_basic.py", + ), + "RunFeemsSim.pms_basic.PmsLoadTable.on_pattern": ( + "pms_basic.html#pmsloadtable.on_pattern", + "RunFeemsSim/pms_basic.py", + ), + "RunFeemsSim.pms_basic.PmsLoadTable.sorted_load_table": ( + "pms_basic.html#pmsloadtable.sorted_load_table", + "RunFeemsSim/pms_basic.py", + ), + "RunFeemsSim.pms_basic.PmsLoadTableSimulationInterface": ( + "pms_basic.html#pmsloadtablesimulationinterface", + "RunFeemsSim/pms_basic.py", + ), + "RunFeemsSim.pms_basic.PmsLoadTableSimulationInterface.__init__": ( + "pms_basic.html#pmsloadtablesimulationinterface.__init__", + "RunFeemsSim/pms_basic.py", + ), + "RunFeemsSim.pms_basic.PmsLoadTableSimulationInterface.set_status": ( + "pms_basic.html#pmsloadtablesimulationinterface.set_status", + "RunFeemsSim/pms_basic.py", + ), + "RunFeemsSim.pms_basic.get_min_load_table_dict_from_feems_system": ( + "pms_basic.html#get_min_load_table_dict_from_feems_system", + "RunFeemsSim/pms_basic.py", + ), + "RunFeemsSim.pms_basic.get_min_load_table_dict_from_proto_system": ( + "pms_basic.html#get_min_load_table_dict_from_proto_system", + "RunFeemsSim/pms_basic.py", + ), + "RunFeemsSim.pms_basic.get_rated_power_from_power_source": ( + "pms_basic.html#get_rated_power_from_power_source", + "RunFeemsSim/pms_basic.py", + ), + "RunFeemsSim.pms_basic.min_load_table_dict": ( + "pms_basic.html#min_load_table_dict", + "RunFeemsSim/pms_basic.py", + ), + }, + }, +} diff --git a/RunFEEMSSim/RunFeemsSim/machinery_calculation.py b/RunFEEMSSim/RunFeemsSim/machinery_calculation.py index 98c56ee..73b26ed 100644 --- a/RunFEEMSSim/RunFeemsSim/machinery_calculation.py +++ b/RunFEEMSSim/RunFeemsSim/machinery_calculation.py @@ -1,7 +1,11 @@ # AUTOGENERATED! DO NOT EDIT! File to edit: ../00_machinery_calculation.ipynb. # %% auto 0 -__all__ = ['Numeric', 'convert_gymir_result_to_propulsion_power_series', 'MachineryCalculation'] +__all__ = [ + "Numeric", + "convert_gymir_result_to_propulsion_power_series", + "MachineryCalculation", +] # %% ../00_machinery_calculation.ipynb 3 from typing import List, Union, Type, TypeVar @@ -111,7 +115,9 @@ def _set_input_load_time_interval_from_propulsion_power_time_series( # set power load number_of_propulsors = len(self.electric_system.propulsion_drives) if self.system_is_not_electric: - number_of_propulsors = self.system_feems.mechanical_system.no_mechanical_loads + number_of_propulsors = ( + self.system_feems.mechanical_system.no_mechanical_loads + ) number_of_other_loads = len(self.electric_system.other_load) if number_of_other_loads == 0: assert np.all( @@ -286,7 +292,7 @@ def calculate_machinery_system_output_from_time_series_result( df = convert_proto_timeseries_to_pd_dataframe(time_series) self._set_input_load_time_interval_from_propulsion_power_time_series( propulsion_power_time_series=df["propulsion_power_kw"], - auxiliary_load_kw=df["auxiliary_power_kw"].values + auxiliary_load_kw=df["auxiliary_power_kw"].values, ) return self._run_simulation( fuel_specified_by=fuel_specified_by, diff --git a/RunFEEMSSim/RunFeemsSim/pms_basic.py b/RunFEEMSSim/RunFeemsSim/pms_basic.py index e237fcb..636f324 100644 --- a/RunFEEMSSim/RunFeemsSim/pms_basic.py +++ b/RunFEEMSSim/RunFeemsSim/pms_basic.py @@ -1,9 +1,16 @@ # AUTOGENERATED! DO NOT EDIT! File to edit: ../01_pms_basic.ipynb. # %% auto 0 -__all__ = ['OnPattern', 'Load2OnPattern', 'PmsLoadTable', 'get_rated_power_from_power_source', - 'get_min_load_table_dict_from_proto_system', 'get_min_load_table_dict_from_feems_system', - 'min_load_table_dict', 'PmsLoadTableSimulationInterface'] +__all__ = [ + "OnPattern", + "Load2OnPattern", + "PmsLoadTable", + "get_rated_power_from_power_source", + "get_min_load_table_dict_from_proto_system", + "get_min_load_table_dict_from_feems_system", + "min_load_table_dict", + "PmsLoadTableSimulationInterface", +] # %% ../01_pms_basic.ipynb 3 import itertools @@ -97,17 +104,14 @@ def get_min_load_table_dict_from_feems_system( electric_system = ( system if not hasattr(system, "electric_system") else system.electric_system ) - power_sources = [ - component - for component in electric_system.power_sources - ] + power_sources = [component for component in electric_system.power_sources] if component_types is not None: power_sources = [ - component for component in power_sources if component.type in component_types + component + for component in power_sources + if component.type in component_types ] - rated_power_all = [ - power_source.rated_power for power_source in power_sources - ] + rated_power_all = [power_source.rated_power for power_source in power_sources] return min_load_table_dict( rated_power_all, maximum_allowed_genset_load_percentage / 100 ) @@ -167,7 +171,11 @@ def set_status( n_datapoint_max = max(n_datapoints) if len(n_datapoints) > 1: for swb_id, power_kw in power_kw_per_switchboard.items(): - if len(power_kw) < n_datapoint_max and len(power_kw) != 1 and power_kw[0] != 0: + if ( + len(power_kw) < n_datapoint_max + and len(power_kw) != 1 + and power_kw[0] != 0 + ): raise ValueError( f"Load vector for switchboard {swb_id} has length {len(power_kw)} " f"but should have length {n_datapoint_max} or 1 with 0 value." diff --git a/RunFEEMSSim/index.ipynb b/RunFEEMSSim/index.ipynb index 987afe0..cb17523 100644 --- a/RunFEEMSSim/index.ipynb +++ b/RunFEEMSSim/index.ipynb @@ -6,7 +6,7 @@ "metadata": {}, "outputs": [], "source": [ - "#| hide\n", + "# | hide\n", "from RunFeemsSim.machinery_calculation import *" ] }, diff --git a/feems/feems/components_model/component_electric.py b/feems/feems/components_model/component_electric.py index 243bf64..80d84ec 100644 --- a/feems/feems/components_model/component_electric.py +++ b/feems/feems/components_model/component_electric.py @@ -536,7 +536,10 @@ def get_power_output_from_bidirectional_input( self, power_input: Union[float, np.ndarray], strict_power_balance: bool = False ) -> Tuple[Union[float, np.ndarray], Union[float, np.ndarray]]: if self.converter is not None: - (battery_power_input, _,) = self.converter.get_power_output_from_bidirectional_input( + ( + battery_power_input, + _, + ) = self.converter.get_power_output_from_bidirectional_input( power_input=power_input, strict_power_balance=strict_power_balance ) else: @@ -810,7 +813,10 @@ def get_power_input_from_bidirectional_output( self, power_output: Union[float, np.ndarray], strict_power_balance: bool = False ) -> Tuple[Union[float, np.ndarray], Union[float, np.ndarray]]: load = self.get_load(power_output) - (supercap_power_input, _,) = self.supercapacitor.get_power_input_from_bidirectional_output( + ( + supercap_power_input, + _, + ) = self.supercapacitor.get_power_input_from_bidirectional_output( power_output=power_output, strict_power_balance=strict_power_balance ) if self.converter is None: @@ -825,7 +831,10 @@ def get_power_output_from_bidirectional_input( self, power_input: Union[float, np.ndarray], strict_power_balance: bool = False ) -> Tuple[Union[float, np.ndarray], Union[float, np.ndarray]]: if self.converter is not None: - (supercap_power_input, _,) = self.converter.get_power_output_from_bidirectional_input( + ( + supercap_power_input, + _, + ) = self.converter.get_power_output_from_bidirectional_input( power_input=power_input, strict_power_balance=strict_power_balance ) else: diff --git a/feems/feems/fuel.py b/feems/feems/fuel.py index 5d8d72d..7a6df1c 100644 --- a/feems/feems/fuel.py +++ b/feems/feems/fuel.py @@ -1,4 +1,5 @@ """This module provides classes for fuel consumption and emissions.""" + from functools import cache import os import warnings @@ -241,12 +242,14 @@ def copy(self) -> "Fuel": origin=self.origin, fuel_specified_by=self.fuel_specified_by, lhv_mj_per_g=self.lhv_mj_per_g if fuel_specified_by_user else None, - ghg_emission_factor_well_to_tank_gco2eq_per_mj=self.ghg_emission_factor_well_to_tank_gco2eq_per_mj - if fuel_specified_by_user - else None, - ghg_emission_factor_tank_to_wake=self.ghg_emission_factor_tank_to_wake - if fuel_specified_by_user - else None, + ghg_emission_factor_well_to_tank_gco2eq_per_mj=( + self.ghg_emission_factor_well_to_tank_gco2eq_per_mj + if fuel_specified_by_user + else None + ), + ghg_emission_factor_tank_to_wake=( + self.ghg_emission_factor_tank_to_wake if fuel_specified_by_user else None + ), mass_or_mass_fraction=self.mass_or_mass_fraction, ) @@ -326,9 +329,9 @@ def get_prescribed_factors( ghg_emission_factor_well_to_tank_gco2eq_per_mj = fuel_data["CO2_WtT"].values[0] ghg_emission_factor_tank_to_wake = [ GhgEmissionFactorTankToWake( - fuel_consumer_class=each_data["fuel_consumer_unit_class"] - if organization == "eu" - else None, + fuel_consumer_class=( + each_data["fuel_consumer_unit_class"] if organization == "eu" else None + ), co2_factor_gco2_per_gfuel=each_data["Cf_CO2"], ch4_factor_gch4_per_gfuel=each_data["Cf_CH4"], n2o_factor_gn2o_per_gfuel=each_data["Cf_N2O"], diff --git a/feems/feems/simulation_interface.py b/feems/feems/simulation_interface.py index ffe424b..b43cdb3 100644 --- a/feems/feems/simulation_interface.py +++ b/feems/feems/simulation_interface.py @@ -130,7 +130,9 @@ def filling_ratio_or_state_of_charge(self) -> float: class ElectricPowerPlantStatus(NamedTuple): - bus_tie_breaker_status: np.ndarray # First index is time index, second is bus_tie_breaker_index + bus_tie_breaker_status: ( + np.ndarray + ) # First index is time index, second is bus_tie_breaker_index genset_connection_status: Dict[SwbId, np.ndarray] # Dictionary where key is teh swbid, the value is a matrix where the first index is time, # and second is genset_index diff --git a/feems/tests/test_components.py b/feems/tests/test_components.py index 4cce041..c920d2f 100644 --- a/feems/tests/test_components.py +++ b/feems/tests/test_components.py @@ -422,7 +422,7 @@ def test_electric_component_with_file_input(self): os.unlink(filename) def test_serial_system(self): - + load_perc = 0.50 # np.random.rand() * 100 efficiency = 1 for component in self.components: diff --git a/feems/tests/test_node.py b/feems/tests/test_node.py index 0b3894a..c60b780 100644 --- a/feems/tests/test_node.py +++ b/feems/tests/test_node.py @@ -95,9 +95,9 @@ def set_status(self) -> StatusSummary: np.random.rand(self.no_points_to_test, self.switchboard.no_power_sources) ).astype(bool) index_all_power_source_off = np.bitwise_not(status_new_power_source).all(axis=1) - status_new_power_source[ - index_all_power_source_off, 0 - ] = True # Make sure at least one power source is on + status_new_power_source[index_all_power_source_off, 0] = ( + True # Make sure at least one power source is on + ) self.switchboard.set_status_components_by_power_type( type_=TypePower.POWER_SOURCE, status=status_new_power_source ) diff --git a/feems/tests/test_system.py b/feems/tests/test_system.py index 137d474..89ffc3b 100644 --- a/feems/tests/test_system.py +++ b/feems/tests/test_system.py @@ -754,9 +754,9 @@ def test_power_balance_calculation(self): _, switchboard, ) in self.power_system_for_diesel_electric_system.switchboards.items(): - sum_power_output_power_sources_switchboards[ - switchboard.id - ] = switchboard.get_sum_power_output_by_power_type(TypePower.POWER_SOURCE) + sum_power_output_power_sources_switchboards[switchboard.id] = ( + switchboard.get_sum_power_output_by_power_type(TypePower.POWER_SOURCE) + ) for i, switchboard2bus in enumerate( self.power_system_for_diesel_electric_system.switchboard2bus diff --git a/machinery-system-structure/MachSysS/__init__.py b/machinery-system-structure/MachSysS/__init__.py index 22049ab..364e7ba 100644 --- a/machinery-system-structure/MachSysS/__init__.py +++ b/machinery-system-structure/MachSysS/__init__.py @@ -1 +1 @@ -__version__ = "0.6.2" +__version__ = "0.6.4" From 52d6e88ebbde2697e1296a00fefe1e618fdb7da7 Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 26 Mar 2024 10:07:31 +0100 Subject: [PATCH 05/28] fixed test pipeline --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 88cf270..b7d4183 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,6 +40,7 @@ jobs: - name: Install dependencies run: | + python3 -m pip install --upgrade pip setuptools pip install -r requirements_dev.txt - name: Test with pytest if the project is feems else test with nbdev From 46ca58552867394173e639c57ef4ae37452d6f82 Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 26 Mar 2024 11:49:51 +0100 Subject: [PATCH 06/28] test publishing to pypi --- .github/workflows/release-please.yml | 69 +++++++++++++++++++++++++ RunFEEMSSim/settings.ini | 2 +- feems/pyproject.toml | 2 +- machinery-system-structure/settings.ini | 2 +- release-please-config.json | 40 ++++++++++++++ 5 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/release-please.yml create mode 100644 release-please-config.json diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..5228fda --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,69 @@ +on: + push: + branches: ["*"] + +permissions: + contents: write + pull-requests: write + id-token: write + +name: release-please + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: google-github-actions/release-please-action@v4 + id: release + with: + # this assumes that you have created a personal access token + # (PAT) and configured it as a GitHub action secret named + token: ${{ secrets.PYCOSIM_UPLOAD }} + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + include-component-in-tag: true + - name: Print the output + run: echo "The output was $ALLOUTPUT" + env: + ALLOUTPUT: ${{ toJSON(steps.release.outputs) }} + - uses: actions/checkout@v4 + if: ${{ steps.release.outputs.releases_created }} + - name: Set up Python + uses: actions/setup-python@v4 + if: ${{ steps.release.outputs.releases_created }} + with: + python-version: "3.12" + - name: Install pypa/build + if: ${{ steps.release.outputs.releases_created }} + run: >- + python3 -m + pip install + build + --user + - name: Build feems + if: ${{ steps.release.outputs.feems--release_created }} + run: python3 -m build + working-directory: feems + - name: Publish feems to PyPI + if: ${{ steps.release.outputs.feems--release_created }} + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: feems/dist + - name: Build MachSysS + if: ${{ steps.release.outputs.machinery-system-structure--release_created }} + run: python3 -m build + working-directory: machinery-system-structure + - name: Publish ship_model_lib to PyPI + if: ${{ steps.release.outputs.machinery-system-structure--release_created }} + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: machinery-system-structure/dist + - name: Build RunFEEMSSim + if: ${{ steps.release.outputs.RunFEEMSSim--release_created }} + run: python3 -m build + working-directory: RunFEEMSSim + - name: Publish RunFEEMSSim to PyPI + if: ${{ steps.release.outputs.RunFEEMSSim--release_created }} + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: RunFEEMSSim/dist diff --git a/RunFEEMSSim/settings.ini b/RunFEEMSSim/settings.ini index 5b28dfa..e5afab7 100644 --- a/RunFEEMSSim/settings.ini +++ b/RunFEEMSSim/settings.ini @@ -8,7 +8,7 @@ author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF branch = master -version = 0.2.2 +version = 0.2.2-test min_python = 3.10 audience = Developers language = English diff --git a/feems/pyproject.toml b/feems/pyproject.toml index f222900..8ca5953 100644 --- a/feems/pyproject.toml +++ b/feems/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "feems" -version = "0.10.5" +version = "0.10.5-test" description = "" authors = ["Kevin Koosup Yum "] readme = "readme.md" diff --git a/machinery-system-structure/settings.ini b/machinery-system-structure/settings.ini index 79047de..d23796c 100644 --- a/machinery-system-structure/settings.ini +++ b/machinery-system-structure/settings.ini @@ -12,7 +12,7 @@ user = keviny author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF Ocean -version = 0.6.4 +version = 0.6.4-test min_python = 3.10 audience = Developers language = English diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..598ec0a --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,40 @@ +{ + "include-component-in-tag": true, + "packages": { + "feems": { + "changelog-path": "CHANGELOG.md", + "release-type": "python", + "bump-minor-pre-major": false, + "bump-patch-for-minor-pre-major": false, + "draft": false, + "prerelease": false, + "include-component-in-tag": true, + "package-name": "feems", + "extra-files": [ + "pyproject.toml" + ] + }, + "machinery-system-structure": { + "changelog-path": "CHANGELOG.md", + "release-type": "python", + "bump-minor-pre-major": false, + "bump-patch-for-minor-pre-major": false, + "draft": false, + "prerelease": false, + "package-name": "MachSysS", + "extra-files": [ + "settings.ini" + ] + }, + "RunFEEMSSim": { + "changelog-path": "CHANGELOG.md", + "release-type": "python", + "bump-minor-pre-major": false, + "bump-patch-for-minor-pre-major": false, + "draft": false, + "prerelease": false, + "package-name": "RunFeemsSim" + } + }, + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" +} \ No newline at end of file From 3557f6a9a19d91438e5366fccfb8fafacd9cca14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Mar 2024 12:46:05 +0000 Subject: [PATCH 07/28] Bump urllib3 from 2.0.5 to 2.0.7 in /feems Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.5 to 2.0.7. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/v2.0.5...2.0.7) --- updated-dependencies: - dependency-name: urllib3 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- feems/poetry.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/feems/poetry.lock b/feems/poetry.lock index 5f304f4..4013776 100644 --- a/feems/poetry.lock +++ b/feems/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "alabaster" @@ -1180,13 +1180,13 @@ lxml = "*" [[package]] name = "urllib3" -version = "2.0.5" +version = "2.0.7" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.7" files = [ - {file = "urllib3-2.0.5-py3-none-any.whl", hash = "sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e"}, - {file = "urllib3-2.0.5.tar.gz", hash = "sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594"}, + {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, + {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, ] [package.extras] @@ -1213,4 +1213,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.13" -content-hash = "e175522e23be99c3903c44ff3c48b0ecd9384fbb7584d911a532268bf33c4263" +content-hash = "c3735fae9a8d6baac9a2329d6b03073a074169e90a49b68cf73af32b69d2a51d" From 415cd9642e1152c37922b7b828a6f0e1592dc45f Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 26 Mar 2024 16:46:09 +0100 Subject: [PATCH 08/28] fixes related to release pipeline --- .github/workflows/release-please.yml | 2 +- machinery-system-structure/settings.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 5228fda..0d456a5 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -1,6 +1,6 @@ on: push: - branches: ["*"] + branches: ["release"] permissions: contents: write diff --git a/machinery-system-structure/settings.ini b/machinery-system-structure/settings.ini index 4bc9088..4ddd2dc 100644 --- a/machinery-system-structure/settings.ini +++ b/machinery-system-structure/settings.ini @@ -12,7 +12,7 @@ user = keviny author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF Ocean -version = 0.6.2b +version = 0.6.2 min_python = 3.10 audience = Developers language = English From 75affc754dfcca72f70c9171fc6c4de6fb0b49a6 Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 26 Mar 2024 16:50:36 +0100 Subject: [PATCH 09/28] fixed version numbers --- RunFEEMSSim/settings.ini | 2 +- feems/pyproject.toml | 2 +- machinery-system-structure/settings.ini | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RunFEEMSSim/settings.ini b/RunFEEMSSim/settings.ini index e5afab7..5b28dfa 100644 --- a/RunFEEMSSim/settings.ini +++ b/RunFEEMSSim/settings.ini @@ -8,7 +8,7 @@ author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF branch = master -version = 0.2.2-test +version = 0.2.2 min_python = 3.10 audience = Developers language = English diff --git a/feems/pyproject.toml b/feems/pyproject.toml index 8ca5953..f222900 100644 --- a/feems/pyproject.toml +++ b/feems/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "feems" -version = "0.10.5-test" +version = "0.10.5" description = "" authors = ["Kevin Koosup Yum "] readme = "readme.md" diff --git a/machinery-system-structure/settings.ini b/machinery-system-structure/settings.ini index d23796c..79047de 100644 --- a/machinery-system-structure/settings.ini +++ b/machinery-system-structure/settings.ini @@ -12,7 +12,7 @@ user = keviny author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF Ocean -version = 0.6.4-test +version = 0.6.4 min_python = 3.10 audience = Developers language = English From cc038b552d67182f602d7277fbb269bf41f3a231 Mon Sep 17 00:00:00 2001 From: keviny Date: Wed, 27 Mar 2024 04:54:22 +0100 Subject: [PATCH 10/28] publish pipeline added --- .github/workflows/publish_MachSysS.yml | 49 +++++++++++++++++++++++ .github/workflows/publish_RunFeemsSim.yml | 49 +++++++++++++++++++++++ .github/workflows/publish_feems.yml | 49 +++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 .github/workflows/publish_MachSysS.yml create mode 100644 .github/workflows/publish_RunFeemsSim.yml create mode 100644 .github/workflows/publish_feems.yml diff --git a/.github/workflows/publish_MachSysS.yml b/.github/workflows/publish_MachSysS.yml new file mode 100644 index 0000000..26bd8bc --- /dev/null +++ b/.github/workflows/publish_MachSysS.yml @@ -0,0 +1,49 @@ +name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS + +on: + push: + branches: ["main"] + +jobs: + build: + name: Build distribution 📦 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build --user + - name: Build package + run: | + cd machinery-system-structure + python -m build + - name: Store the distribution packages 📦 + uses: actions/upload-artifact@v3 + with: + name: python-package-distributions-MachSysS + path: machinery-system-structure/dist/ + + publish-to-pypi: + name: >- + Publish Python 🐍 distribution 📦 to PyPI + needs: + - build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/MachSysS + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v3 + with: + name: python-package-distributions-MachSysS + path: machinery-system-structure/dist/ + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/publish_RunFeemsSim.yml b/.github/workflows/publish_RunFeemsSim.yml new file mode 100644 index 0000000..e658079 --- /dev/null +++ b/.github/workflows/publish_RunFeemsSim.yml @@ -0,0 +1,49 @@ +name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS + +on: + push: + branches: ["main"] + +jobs: + build: + name: Build distribution 📦 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build --user + - name: Build package + run: | + cd RunFEEMSSim + python -m build + - name: Store the distribution packages 📦 + uses: actions/upload-artifact@v3 + with: + name: python-package-distributions-RunFeemsSim + path: RunFEEMSSim/dist/ + + publish-to-pypi: + name: >- + Publish Python 🐍 distribution 📦 to PyPI + needs: + - build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/RunFeemsSim + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v3 + with: + name: python-package-distributions-RunFeemsSim + path: RunFEEMSSim/dist/ + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/publish_feems.yml b/.github/workflows/publish_feems.yml new file mode 100644 index 0000000..bd7f70d --- /dev/null +++ b/.github/workflows/publish_feems.yml @@ -0,0 +1,49 @@ +name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS + +on: + push: + branches: ["main"] + +jobs: + build: + name: Build distribution 📦 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install poetry --user + - name: Build package + run: | + cd feems + poetry build + - name: Store the distribution packages 📦 + uses: actions/upload-artifact@v3 + with: + name: python-package-distributions-feems + path: feems/dist/ + + publish-to-pypi: + name: >- + Publish Python 🐍 distribution 📦 to PyPI + needs: + - build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/feems + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v3 + with: + name: python-package-distributions-feems + path: feems/dist/ + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 From d33dda49ac3948808012f063514923d61b92b4cf Mon Sep 17 00:00:00 2001 From: keviny Date: Wed, 27 Mar 2024 05:04:59 +0100 Subject: [PATCH 11/28] fixed the pipeline for publishing --- .github/workflows/publish_MachSysS.yml | 2 +- .github/workflows/publish_RunFeemsSim.yml | 2 +- .github/workflows/publish_feems.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish_MachSysS.yml b/.github/workflows/publish_MachSysS.yml index 26bd8bc..fed95ba 100644 --- a/.github/workflows/publish_MachSysS.yml +++ b/.github/workflows/publish_MachSysS.yml @@ -44,6 +44,6 @@ jobs: - uses: actions/download-artifact@v3 with: name: python-package-distributions-MachSysS - path: machinery-system-structure/dist/ + path: dist/ - name: Publish distribution 📦 to PyPI uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/publish_RunFeemsSim.yml b/.github/workflows/publish_RunFeemsSim.yml index e658079..0bb6aa3 100644 --- a/.github/workflows/publish_RunFeemsSim.yml +++ b/.github/workflows/publish_RunFeemsSim.yml @@ -44,6 +44,6 @@ jobs: - uses: actions/download-artifact@v3 with: name: python-package-distributions-RunFeemsSim - path: RunFEEMSSim/dist/ + path: dist/ - name: Publish distribution 📦 to PyPI uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/publish_feems.yml b/.github/workflows/publish_feems.yml index bd7f70d..7996144 100644 --- a/.github/workflows/publish_feems.yml +++ b/.github/workflows/publish_feems.yml @@ -44,6 +44,6 @@ jobs: - uses: actions/download-artifact@v3 with: name: python-package-distributions-feems - path: feems/dist/ + path: dist/ - name: Publish distribution 📦 to PyPI uses: pypa/gh-action-pypi-publish@release/v1 From b95879633b3e70b17d262f9fc1e457996e011abb Mon Sep 17 00:00:00 2001 From: keviny Date: Wed, 27 Mar 2024 08:24:50 +0100 Subject: [PATCH 12/28] Fixed the pipeline to publish only with release tag --- .github/workflows/publish_MachSysS.yml | 1 + .github/workflows/publish_RunFeemsSim.yml | 1 + .github/workflows/publish_feems.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/publish_MachSysS.yml b/.github/workflows/publish_MachSysS.yml index fed95ba..8fb92dd 100644 --- a/.github/workflows/publish_MachSysS.yml +++ b/.github/workflows/publish_MachSysS.yml @@ -32,6 +32,7 @@ jobs: publish-to-pypi: name: >- Publish Python 🐍 distribution 📦 to PyPI + if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes needs: - build runs-on: ubuntu-latest diff --git a/.github/workflows/publish_RunFeemsSim.yml b/.github/workflows/publish_RunFeemsSim.yml index 0bb6aa3..fc2a530 100644 --- a/.github/workflows/publish_RunFeemsSim.yml +++ b/.github/workflows/publish_RunFeemsSim.yml @@ -32,6 +32,7 @@ jobs: publish-to-pypi: name: >- Publish Python 🐍 distribution 📦 to PyPI + if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes needs: - build runs-on: ubuntu-latest diff --git a/.github/workflows/publish_feems.yml b/.github/workflows/publish_feems.yml index 7996144..17b4eeb 100644 --- a/.github/workflows/publish_feems.yml +++ b/.github/workflows/publish_feems.yml @@ -32,6 +32,7 @@ jobs: publish-to-pypi: name: >- Publish Python 🐍 distribution 📦 to PyPI + if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes needs: - build runs-on: ubuntu-latest From ed3763196088799145c53d24458aea5545434940 Mon Sep 17 00:00:00 2001 From: keviny Date: Wed, 27 Mar 2024 14:58:38 +0100 Subject: [PATCH 13/28] COGAS, COGES implemented --- .../feems/components_model/component_base.py | 8 ++ .../components_model/component_electric.py | 76 +++++++++++++---- .../components_model/component_mechanical.py | 83 ++++++++++++++++++- feems/feems/types_for_feems.py | 2 + feems/tests/test_components.py | 46 ++++++++++ 5 files changed, 199 insertions(+), 16 deletions(-) diff --git a/feems/feems/components_model/component_base.py b/feems/feems/components_model/component_base.py index 30eb592..4a8fd77 100644 --- a/feems/feems/components_model/component_base.py +++ b/feems/feems/components_model/component_base.py @@ -1,4 +1,5 @@ from typing import Union, List, Tuple, Optional, TypeVar +from dataclasses import dataclass import numpy as np import pandas as pd @@ -19,6 +20,7 @@ Numeric, NumericT, ) +from ..fuel import FuelConsumption # Define logger logger = get_logger(__name__) @@ -27,6 +29,12 @@ T = TypeVar("T", float, np.ndarray) +@dataclass +class ComponentRunPoint: + load_ratio: np.ndarray + efficiency: np.ndarray + fuel_flow_rate_kg_per_s: FuelConsumption + class Component: """ class for a component that contains a basic information diff --git a/feems/feems/components_model/component_electric.py b/feems/feems/components_model/component_electric.py index 80d84ec..0abdc0a 100644 --- a/feems/feems/components_model/component_electric.py +++ b/feems/feems/components_model/component_electric.py @@ -6,8 +6,9 @@ from .. import get_logger -from .component_base import SerialSystem, Component, BasicComponent +from .component_base import SerialSystem, Component, BasicComponent, ComponentRunPoint from .component_mechanical import ( + COGAS, Engine, MainEngineForMechanicalPropulsion, MechanicalPropulsionComponent, @@ -17,7 +18,6 @@ from .utility import integrate_data, IntegrationMethod, integrate_data_accumulative from ..constant import hhv_hydrogen_mj_per_kg, lhv_hydrogen_mj_per_kg from ..fuel import ( - FuelByMassFraction, FuelConsumption, TypeFuel, FuelSpecifiedBy, @@ -340,13 +340,6 @@ def __init__( self.switchboard_id = switchboard_id -@dataclass -class FuelCellRunPoint: - load_ratio: np.ndarray - fuel_flow_rate_kg_per_s: FuelConsumption - efficiency: np.ndarray - - class FuelCell(BasicComponent): def __init__( self, @@ -373,7 +366,7 @@ def get_fuel_cell_run_point( lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, - ) -> FuelCellRunPoint: + ) -> ComponentRunPoint: """ Get the fuel cell run point @@ -392,7 +385,7 @@ def get_fuel_cell_run_point( fuel_specified_by is FuelSpecifiedBy.USER. Returns: - FuelCellRunPoint: fuel cell run point + ComponentRunPoint: fuel cell run point """ if power_out_kw is None: power_out_kw = self.power_output @@ -407,7 +400,7 @@ def get_fuel_cell_run_point( ) fuel.mass_or_mass_fraction = power_in_kw / fuel.lhv_mj_per_g / 1e6 efficiency = self.get_efficiency_from_load_percentage(load_ratio) - return FuelCellRunPoint( + return ComponentRunPoint( load_ratio=load_ratio, fuel_flow_rate_kg_per_s=FuelConsumption( fuels=[ @@ -451,7 +444,7 @@ def get_fuel_cell_run_point( lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, - ) -> FuelCellRunPoint: + ) -> ComponentRunPoint: """ Get the fuel cell run point @@ -470,7 +463,7 @@ def get_fuel_cell_run_point( fuel_specified_by is FuelSpecifiedBy.USER. Returns: - FuelCellRunPoint: fuel cell run point + ComponentRunPoint: fuel cell run point """ if power_out_kw is None: power_out_kw = self.power_output @@ -482,7 +475,7 @@ def get_fuel_cell_run_point( ghg_emission_factor_well_to_tank_gco2eq_per_mj=ghg_emission_factor_well_to_tank_gco2eq_per_mj, ghg_emission_factor_tank_to_wake=ghg_emission_factor_tank_to_wake, ) - return FuelCellRunPoint( + return ComponentRunPoint( load_ratio=result_per_module.load_ratio, fuel_flow_rate_kg_per_s=result_per_module.fuel_flow_rate_kg_per_s * self.number_modules, @@ -557,6 +550,11 @@ class GensetRunPoint(NamedTuple): engine: EngineRunPoint +class COGESRunPoint(NamedTuple): + coges_load_ratio: np.ndarray + cogas: ComponentRunPoint + + class Genset(Component): """ Class for serial config for genset. It is composed of an engine, a generator and optionally @@ -892,11 +890,59 @@ def __init__( self.converter = converter +class COGES(Component): + """ + Class for serial configuration for a COGES system. + """ + + def __init__( + self, + name: str, + cogas: COGAS, + generator: ElectricMachine, + ): + super().__init__( + name=name, + type_=TypeComponent.COGES, + power_type=TypePower.POWER_SOURCE, + rated_power=generator.rated_power, + rated_speed=generator.rated_speed, + ) + self.fuel_type = cogas.fuel_type + self.cogas = cogas + self.generator = generator + self.switchboard_id = generator.switchboard_id + self.status = np.ones(0).astype(bool) + self.load_sharing_mode = np.zeros(1) + + def get_system_run_point_from_power_output_kw(self, power_output_kw: np.ndarray = None) -> ComponentRunPoint: + """ + Get the run point of the COGES system based on the power output of the system + + Args: + power_output_kw (np.ndarray): power output of the COGES system in kW or None. If None, + it will take the value of power output of the COGES system. + + Returns: + ComponentRunPoint: run point of the COGES system + """ + if power_output_kw is None: + power_output_kw = self.power_output + + self.cogas.power_output, load_generator = self.generator.set_power_input_from_output(power_output_kw) + cogas_run_point = self.cogas.get_gas_turbine_run_point_from_power_output_kw() + return COGESRunPoint( + coges_load_ratio=load_generator, + cogas=cogas_run_point, + ) + + MechanicalComponent = Union[ MainEngineForMechanicalPropulsion, MainEngineWithGearBoxForMechanicalPropulsion, PTIPTO, MechanicalPropulsionComponent, + COGAS ] PowerSystemComponent = Union[ diff --git a/feems/feems/components_model/component_mechanical.py b/feems/feems/components_model/component_mechanical.py index e03a52a..b3fc341 100644 --- a/feems/feems/components_model/component_mechanical.py +++ b/feems/feems/components_model/component_mechanical.py @@ -4,7 +4,7 @@ import numpy as np import pandas as pd -from .component_base import Component, BasicComponent +from .component_base import Component, BasicComponent, ComponentRunPoint from .. import get_logger from ..constant import ( nox_tier_slow_speed_max_rpm, @@ -443,6 +443,87 @@ def get_engine_run_point_from_power_out_kw( ghg_emission_factor_tank_to_wake=ghg_emission_factor_tank_to_wake, ) +class COGAS(BasicComponent): + """Combined gas and steam component class for basic information and efficiency interpolation""" + + def __init__( + self, + name: str = "", + rated_power: Power_kW = Power_kW(0), + eff_curve: np.ndarray = np.array([1]), + rated_speed: Speed_rpm = Speed_rpm(0), + gas_turbine_power_curve: np.ndarray = None, + steam_turbine_power_curve: np.ndarray = None, + fuel_type: TypeFuel = TypeFuel.DIESEL, + fuel_origin: FuelOrigin = FuelOrigin.FOSSIL, + ): + """Constructor for COGES component""" + # Validate the inputs for curves. The length of the curves should be the same and the x values should be the same. + if gas_turbine_power_curve is not None and steam_turbine_power_curve is not None: + if gas_turbine_power_curve.shape != steam_turbine_power_curve.shape: + raise ValueError("The length of the gas turbine power curve and steam turbine power curve should be the same.") + if np.all(gas_turbine_power_curve[:, 0] == steam_turbine_power_curve[:, 0]): + raise ValueError("The x values of the gas turbine power curve and steam turbine power curve should be the same.") + + super().__init__( + type_=TypeComponent.COGAS, + power_type=TypePower.POWER_SOURCE, + name=name, + rated_power=rated_power, + eff_curve=eff_curve, + rated_speed=rated_speed + ) + self.gas_turbine_power_curve = gas_turbine_power_curve + self.steam_turbine_power_curve = steam_turbine_power_curve + self.total_power_curve = self.gas_turbine_power_curve.copy() + self.total_power_curve[:, 1] += self.steam_turbine_power_curve[:, 1] + self.power_ratio_gas_turbine_points = gas_turbine_power_curve.copy() + self.power_ratio_gas_turbine_points[:, 1] /= self.total_power_curve[:, 1] + self.power_ratio_gas_turbine_interpolator = get_efficiency_curve_from_points( + self.power_ratio_gas_turbine_points + ) + self.fuel_type = fuel_type + self.fuel_origin = fuel_origin + + @property + def power_output_gas_turbine(self): + """Power output of the gas turbine in kW""" + return self.power_ratio_gas_turbine_interpolator(self.power_output / self.rated_power) + + @property + def power_output_steam_turbine(self): + """Power output of the steam turbine in kW""" + return self.power_output - self.power_output_gas_turbine + + def get_gas_turbine_run_point_from_power_output_kw( + self, + power_kw: np.ndarray = None, + fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, + lhv_mj_per_g: Optional[float] = None, + ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, + ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ) -> ComponentRunPoint: + if power_kw is None: + power_kw = self.power_output + load_ratio = self.get_load(power_kw) + eff = self.get_efficiency_from_load_percentage(load_ratio) + fuel = Fuel( + origin=self.fuel_origin, + fuel_type=self.fuel_type, + fuel_specified_by=fuel_specified_by, + lhv_mj_per_g=lhv_mj_per_g, + ghg_emission_factor_tank_to_wake=ghg_emission_factor_tank_to_wake, + ghg_emission_factor_well_to_tank_gco2eq_per_mj=ghg_emission_factor_well_to_tank_gco2eq_per_mj + ) + fuel_power_kw = power_kw / eff + fuel_consumption_kg_per_s = fuel_power_kw / fuel.lhv_mj_per_g / 1000 + fuel.consumption = fuel_consumption_kg_per_s + return ComponentRunPoint( + load_ratio=load_ratio, + fuel_flow_rate_kg_per_s=FuelConsumption(fuels=[fuel]), + efficiency=eff, + ) + MechanicalComponent = Union[ MainEngineForMechanicalPropulsion, diff --git a/feems/feems/types_for_feems.py b/feems/feems/types_for_feems.py index de162d9..c0d7c5c 100644 --- a/feems/feems/types_for_feems.py +++ b/feems/feems/types_for_feems.py @@ -168,6 +168,8 @@ class TypeComponent(Enum): SUPERCAPACITOR = 25 SUPERCAPACITOR_SYSTEM = 26 SHORE_POWER = 27 + COGES = 28 + COGAS = 29 @unique diff --git a/feems/tests/test_components.py b/feems/tests/test_components.py index c920d2f..7350b1a 100644 --- a/feems/tests/test_components.py +++ b/feems/tests/test_components.py @@ -18,6 +18,7 @@ FuelCellSystem, ) from feems.components_model.component_mechanical import ( + COGAS, Engine, MainEngineWithGearBoxForMechanicalPropulsion, EngineDualFuel, @@ -657,3 +658,48 @@ def test_fuel_cell(self): fuel_cell_system_run_point.efficiency, fuel_cell_module_run_point.efficiency, ) + + """Test cogeneration system""" + #: Create an engine component + engine = create_engine_component("auxiliary engine 1", 1000, 1000) + #: Create a generator component + generator = ElectricMachine( + type_=TypeComponent.GENERATOR, + name="generator 1", + rated_power=engine.rated_power * 0.9, + rated_speed=engine.rated_speed, + power_type=TypePower.POWER_SOURCE, + switchboard_id=SwbId(0), + number_poles=4, + eff_curve=ELECTRIC_MACHINE_EFF_CURVE, + ) + rectifier = ElectricComponent( + type_=TypeComponent.RECTIFIER, + name="rectifier 1", + rated_power=generator.rated_power, + eff_curve=np.array([99]), + ) + coges_ac = Genset("coges 1", engine, generator) + coges_dc = Genset("coges 1", engine, generator, rectifier) + power_electric = np.random.rand(5) * coges_ac.rated_power + load_at_coges = generator.get_load(power_electric) + power_dc_at_generator = power_electric / rectifier.get_efficiency_from_load_percentage( + load_at_coges + ) + power_shaft_ac, load_perc = generator.get_shaft_power_load_from_electric_power( + power_electric + ) + power_shaft_dc, load_perc = generator.get_shaft_power_load_from_electric_power( + power_dc_at_generator + ) + res_engine_ac = engine.get_engine_run_point_from_power_out_kw(power_shaft_ac) + res_engine_dc = engine.get_engine_run_point_from_power_out_kw(power_shaft_dc) + res_coges_ac = coges_ac.get_fuel_cons_load_bsfc_from_power_out_generator_kw(power_electric) + res_coges_dc = coges_dc.get_fuel_cons_load_bsfc_from_power_out_generator_kw(power_electric) + np.testing.assert_allclose( + res_engine_ac.fuel_flow_rate_kg_per_s.total_fuel_consumption, + res_coges_ac.engine.fuel_flow_rate_kg_per_s.total_fuel_consumption, + ) + np.testing.assert_allclose( + res_engine_dc.fuel_flow_rate_kg_per_s.total_fuel_consumption, + res_coges_dc.engine \ No newline at end of file From 301f81c1c9db6fc3993c065b3bc6f513b5874e90 Mon Sep 17 00:00:00 2001 From: keviny Date: Thu, 28 Mar 2024 10:48:59 +0100 Subject: [PATCH 14/28] test for cogas, coges implemented --- .vscode/settings.json | 12 +++ .../components_model/component_electric.py | 2 +- .../components_model/component_mechanical.py | 78 +++++++++---------- feems/tests/test_components.py | 64 ++++++++------- feems/tests/utility.py | 35 ++++++++- 5 files changed, 121 insertions(+), 70 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9b0d66c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "python.testing.unittestArgs": [ + "-v", + "-s", + "./feems", + "-p", + "test*.py" + ], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true, + "python.testing.pytestArgs": ["feems"] +} diff --git a/feems/feems/components_model/component_electric.py b/feems/feems/components_model/component_electric.py index 0abdc0a..c39c292 100644 --- a/feems/feems/components_model/component_electric.py +++ b/feems/feems/components_model/component_electric.py @@ -915,7 +915,7 @@ def __init__( self.status = np.ones(0).astype(bool) self.load_sharing_mode = np.zeros(1) - def get_system_run_point_from_power_output_kw(self, power_output_kw: np.ndarray = None) -> ComponentRunPoint: + def get_system_run_point_from_power_output_kw(self, power_output_kw: np.ndarray = None) -> COGESRunPoint: """ Get the run point of the COGES system based on the power output of the system diff --git a/feems/feems/components_model/component_mechanical.py b/feems/feems/components_model/component_mechanical.py index b3fc341..ff0ccd0 100644 --- a/feems/feems/components_model/component_mechanical.py +++ b/feems/feems/components_model/component_mechanical.py @@ -462,7 +462,7 @@ def __init__( if gas_turbine_power_curve is not None and steam_turbine_power_curve is not None: if gas_turbine_power_curve.shape != steam_turbine_power_curve.shape: raise ValueError("The length of the gas turbine power curve and steam turbine power curve should be the same.") - if np.all(gas_turbine_power_curve[:, 0] == steam_turbine_power_curve[:, 0]): + if np.all(gas_turbine_power_curve[:, 0] != steam_turbine_power_curve[:, 0]): raise ValueError("The x values of the gas turbine power curve and steam turbine power curve should be the same.") super().__init__( @@ -485,44 +485,44 @@ def __init__( self.fuel_type = fuel_type self.fuel_origin = fuel_origin - @property - def power_output_gas_turbine(self): - """Power output of the gas turbine in kW""" - return self.power_ratio_gas_turbine_interpolator(self.power_output / self.rated_power) - - @property - def power_output_steam_turbine(self): - """Power output of the steam turbine in kW""" - return self.power_output - self.power_output_gas_turbine - - def get_gas_turbine_run_point_from_power_output_kw( - self, - power_kw: np.ndarray = None, - fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, - lhv_mj_per_g: Optional[float] = None, - ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, - ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, - ) -> ComponentRunPoint: - if power_kw is None: - power_kw = self.power_output - load_ratio = self.get_load(power_kw) - eff = self.get_efficiency_from_load_percentage(load_ratio) - fuel = Fuel( - origin=self.fuel_origin, - fuel_type=self.fuel_type, - fuel_specified_by=fuel_specified_by, - lhv_mj_per_g=lhv_mj_per_g, - ghg_emission_factor_tank_to_wake=ghg_emission_factor_tank_to_wake, - ghg_emission_factor_well_to_tank_gco2eq_per_mj=ghg_emission_factor_well_to_tank_gco2eq_per_mj - ) - fuel_power_kw = power_kw / eff - fuel_consumption_kg_per_s = fuel_power_kw / fuel.lhv_mj_per_g / 1000 - fuel.consumption = fuel_consumption_kg_per_s - return ComponentRunPoint( - load_ratio=load_ratio, - fuel_flow_rate_kg_per_s=FuelConsumption(fuels=[fuel]), - efficiency=eff, - ) + @property + def power_output_gas_turbine(self): + """Power output of the gas turbine in kW""" + return self.power_ratio_gas_turbine_interpolator(self.power_output / self.rated_power) + + @property + def power_output_steam_turbine(self): + """Power output of the steam turbine in kW""" + return self.power_output - self.power_output_gas_turbine + + def get_gas_turbine_run_point_from_power_output_kw( + self, + power_kw: np.ndarray = None, + fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, + lhv_mj_per_g: Optional[float] = None, + ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, + ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ) -> ComponentRunPoint: + if power_kw is None: + power_kw = self.power_output + load_ratio = self.get_load(power_kw) + eff = self.get_efficiency_from_load_percentage(load_ratio) + fuel = Fuel( + origin=self.fuel_origin, + fuel_type=self.fuel_type, + fuel_specified_by=fuel_specified_by, + lhv_mj_per_g=lhv_mj_per_g, + ghg_emission_factor_tank_to_wake=ghg_emission_factor_tank_to_wake, + ghg_emission_factor_well_to_tank_gco2eq_per_mj=ghg_emission_factor_well_to_tank_gco2eq_per_mj + ) + fuel_power_kw = power_kw / eff + fuel_consumption_kg_per_s = fuel_power_kw / (fuel.lhv_mj_per_g * 1000) / 1000 + fuel.consumption = fuel_consumption_kg_per_s + return ComponentRunPoint( + load_ratio=load_ratio, + fuel_flow_rate_kg_per_s=FuelConsumption(fuels=[fuel]), + efficiency=eff, + ) MechanicalComponent = Union[ diff --git a/feems/tests/test_components.py b/feems/tests/test_components.py index 7350b1a..a26e5b1 100644 --- a/feems/tests/test_components.py +++ b/feems/tests/test_components.py @@ -9,6 +9,7 @@ from feems.components_model.component_base import BasicComponent, SerialSystem from feems.components_model.component_electric import ( + COGES, ElectricMachine, ElectricComponent, PTIPTO, @@ -32,6 +33,7 @@ from feems.types_for_feems import Speed_rpm, NOxCalculationMethod, SwbId from feems.types_for_feems import TypeNode, TypeComponent, TypePower, Power_kW from tests.utility import ( + create_cogas_system, create_components, create_random_monotonic_eff_curve, create_basic_components, @@ -659,47 +661,51 @@ def test_fuel_cell(self): fuel_cell_module_run_point.efficiency, ) - """Test cogeneration system""" + def test_cogas(self): + """Test combined gas and steam system - mechanical output""" + cogas = create_cogas_system() + power_output_kw = np.random.rand(5) * cogas.rated_power + eff_cogas = cogas.get_efficiency_from_load_percentage( + cogas.get_load(power_output_kw) + ) + fuel = Fuel( + fuel_type=cogas.fuel_type, + origin=cogas.fuel_origin, + fuel_specified_by=FuelSpecifiedBy.IMO, + ) + fuel_consumption_kg_per_s_ref = power_output_kw / eff_cogas / (fuel.lhv_mj_per_g * 1000) / 1000 + gas_turbine_run_point = cogas.get_gas_turbine_run_point_from_power_output_kw(power_output_kw) + assert np.allclose(eff_cogas, gas_turbine_run_point.efficiency) + assert np.allclose(fuel_consumption_kg_per_s_ref, gas_turbine_run_point.fuel_flow_rate_kg_per_s.fuels[0].consumption) + + def test_coges(self): #: Create an engine component - engine = create_engine_component("auxiliary engine 1", 1000, 1000) + cogas = create_cogas_system() #: Create a generator component generator = ElectricMachine( type_=TypeComponent.GENERATOR, name="generator 1", - rated_power=engine.rated_power * 0.9, - rated_speed=engine.rated_speed, + rated_power=cogas.rated_power * 0.9, + rated_speed=cogas.rated_speed, power_type=TypePower.POWER_SOURCE, switchboard_id=SwbId(0), number_poles=4, eff_curve=ELECTRIC_MACHINE_EFF_CURVE, ) - rectifier = ElectricComponent( - type_=TypeComponent.RECTIFIER, - name="rectifier 1", - rated_power=generator.rated_power, - eff_curve=np.array([99]), + coges = COGES( + name="coges 1", + cogas=cogas, + generator=generator, ) - coges_ac = Genset("coges 1", engine, generator) - coges_dc = Genset("coges 1", engine, generator, rectifier) - power_electric = np.random.rand(5) * coges_ac.rated_power - load_at_coges = generator.get_load(power_electric) - power_dc_at_generator = power_electric / rectifier.get_efficiency_from_load_percentage( - load_at_coges - ) - power_shaft_ac, load_perc = generator.get_shaft_power_load_from_electric_power( + power_electric = np.random.rand(5) * coges.rated_power + power_shaft, load_at_generator = generator.get_shaft_power_load_from_electric_power( power_electric ) - power_shaft_dc, load_perc = generator.get_shaft_power_load_from_electric_power( - power_dc_at_generator - ) - res_engine_ac = engine.get_engine_run_point_from_power_out_kw(power_shaft_ac) - res_engine_dc = engine.get_engine_run_point_from_power_out_kw(power_shaft_dc) - res_coges_ac = coges_ac.get_fuel_cons_load_bsfc_from_power_out_generator_kw(power_electric) - res_coges_dc = coges_dc.get_fuel_cons_load_bsfc_from_power_out_generator_kw(power_electric) + res_cogas = cogas.get_gas_turbine_run_point_from_power_output_kw(power_shaft) + res_coges = coges.get_system_run_point_from_power_output_kw(power_electric) + np.testing.assert_allclose(load_at_generator, res_coges.coges_load_ratio) np.testing.assert_allclose( - res_engine_ac.fuel_flow_rate_kg_per_s.total_fuel_consumption, - res_coges_ac.engine.fuel_flow_rate_kg_per_s.total_fuel_consumption, + res_coges.cogas.fuel_flow_rate_kg_per_s.total_fuel_consumption, + res_cogas.fuel_flow_rate_kg_per_s.total_fuel_consumption, ) - np.testing.assert_allclose( - res_engine_dc.fuel_flow_rate_kg_per_s.total_fuel_consumption, - res_coges_dc.engine \ No newline at end of file + \ No newline at end of file diff --git a/feems/tests/utility.py b/feems/tests/utility.py index 50e1e66..95d8b2a 100644 --- a/feems/tests/utility.py +++ b/feems/tests/utility.py @@ -1,6 +1,7 @@ import random from typing import List, Union, NamedTuple +from feems.fuel import FuelOrigin, TypeFuel import numpy as np import pandas as pd from scipy.interpolate import PchipInterpolator @@ -18,7 +19,7 @@ Battery, PTIPTO, ) -from feems.components_model.component_mechanical import Engine +from feems.components_model.component_mechanical import COGAS, Engine from feems.components_model.node import Switchboard from feems.exceptions import ConfigurationError from feems.types_for_feems import ( @@ -748,3 +749,35 @@ def create_electric_components_for_switchboard( electric_components.append(component) return electric_components + +def create_cogas_system( + rated_power_kw: float = 1000, + rated_speed_rpm: float = 1000, + eff_curve: np.ndarray = None, + gas_turbine_power_curve: np.ndarray = None, + steam_turbine_power_curve: np.ndarray = None, + fuel_type: TypeFuel = TypeFuel.NATURAL_GAS, + fuel_origin: FuelOrigin = FuelOrigin.FOSSIL, + +) -> COGAS: + # Create a cogas system + if eff_curve is None: + eff_curve = create_random_monotonic_eff_curve() + if gas_turbine_power_curve is None: + gas_turbine_power_curve = create_random_monotonic_eff_curve() + gas_turbine_power_curve[:, 1] *= gas_turbine_power_curve[:, 0] * rated_power_kw + if steam_turbine_power_curve is None: + steam_turbine_power_curve = create_random_monotonic_eff_curve() + steam_turbine_power_curve[:, 1] = ( + steam_turbine_power_curve[:, 0] * rated_power_kw - gas_turbine_power_curve[:, 1] + ) + return COGAS( + name="COGAS", + rated_power=rated_power_kw, + rated_speed=rated_speed_rpm, + eff_curve=eff_curve, + gas_turbine_power_curve=gas_turbine_power_curve, + steam_turbine_power_curve=steam_turbine_power_curve, + fuel_type=fuel_type, + fuel_origin=fuel_origin, + ) \ No newline at end of file From 5eaa72a46bc4235e81eb60b74d724f39eea22c24 Mon Sep 17 00:00:00 2001 From: keviny Date: Thu, 28 Mar 2024 14:04:08 +0100 Subject: [PATCH 15/28] emission info added to cogas --- .../components_model/component_mechanical.py | 46 +++++++++++++++++++ feems/tests/test_components.py | 12 +++-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/feems/feems/components_model/component_mechanical.py b/feems/feems/components_model/component_mechanical.py index ff0ccd0..4ea4dba 100644 --- a/feems/feems/components_model/component_mechanical.py +++ b/feems/feems/components_model/component_mechanical.py @@ -456,6 +456,8 @@ def __init__( steam_turbine_power_curve: np.ndarray = None, fuel_type: TypeFuel = TypeFuel.DIESEL, fuel_origin: FuelOrigin = FuelOrigin.FOSSIL, + emissions_curves: List[EmissionCurve] = None, + NOx_calculation_method: NOxCalculationMethod = NOxCalculationMethod.TIER_3, ): """Constructor for COGES component""" # Validate the inputs for curves. The length of the curves should be the same and the x values should be the same. @@ -484,6 +486,50 @@ def __init__( ) self.fuel_type = fuel_type self.fuel_origin = fuel_origin + self._setup_emissions(emissions_curves) + self._setup_nox(NOx_calculation_method, rated_speed) + + + def _setup_emissions(self, emissions_curves: List[EmissionCurve] = None) -> None: + self.emission_curves = emissions_curves + self._emissions_per_kwh_interp: Dict[EmissionType, Callable[[T], T]] = {} + if emissions_curves is not None: + e: EmissionCurve + for e in emissions_curves: + if len(e.points_per_kwh) > 0: + self._emissions_per_kwh_interp[e.emission] = get_emission_curve_from_points( + e.points_per_kwh + ) + + @property + def fuel_consumer_type_fuel_eu_maritime(self) -> FuelConsumerClassFuelEUMaritime: + raise NotImplementedError("Fuel consumer type for COGAS is not defined in FuelEU Maritime regulation yet.") + + def emissions_g_per_kwh(self, emission_type: EmissionType, load_ratio: T) -> Optional[T]: + if emission_type in self._emissions_per_kwh_interp: + return self._emissions_per_kwh_interp[emission_type](load_ratio) + else: + return None + + def _setup_nox( + self, nox_calculation_method: NOxCalculationMethod, rated_speed: Speed_rpm + ) -> None: + self.nox_calculation_method = nox_calculation_method + if nox_calculation_method == NOxCalculationMethod.CURVE: + assert EmissionType.NOX in self._emissions_per_kwh_interp + return + + if rated_speed > nox_tier_slow_speed_max_rpm: + tier_class = nox_calculation_method.value + factor = nox_factor_imo_medium_speed_g_hWh[tier_class][0] + exponent = nox_factor_imo_medium_speed_g_hWh[tier_class][1] + nox_g_per_kwh = factor * np.power(self.rated_speed, exponent) + curve = lambda x: nox_g_per_kwh + else: + tier_class = nox_calculation_method.value + nox_factor_g_kwh = nox_factor_imo_slow_speed_g_kWh[tier_class] + curve = lambda x: nox_factor_g_kwh + self._emissions_per_kwh_interp[EmissionType.NOX] = curve @property def power_output_gas_turbine(self): diff --git a/feems/tests/test_components.py b/feems/tests/test_components.py index a26e5b1..b5b083f 100644 --- a/feems/tests/test_components.py +++ b/feems/tests/test_components.py @@ -30,7 +30,7 @@ get_efficiency_curve_from_dataframe, ) from feems.fuel import FuelByMassFraction, TypeFuel, Fuel, FuelSpecifiedBy, FuelOrigin -from feems.types_for_feems import Speed_rpm, NOxCalculationMethod, SwbId +from feems.types_for_feems import EmissionType, Speed_rpm, NOxCalculationMethod, SwbId from feems.types_for_feems import TypeNode, TypeComponent, TypePower, Power_kW from tests.utility import ( create_cogas_system, @@ -42,6 +42,7 @@ ELECTRIC_MACHINE_EFF_CURVE, create_electric_components_for_switchboard, ) +from feems.constant import nox_factor_imo_medium_speed_g_hWh CONVERTER_EFF = np.array([[1.00, 0.75, 0.50, 0.25], [0.98, 0.972, 0.97, 0.96]]).transpose() @@ -675,8 +676,13 @@ def test_cogas(self): ) fuel_consumption_kg_per_s_ref = power_output_kw / eff_cogas / (fuel.lhv_mj_per_g * 1000) / 1000 gas_turbine_run_point = cogas.get_gas_turbine_run_point_from_power_output_kw(power_output_kw) - assert np.allclose(eff_cogas, gas_turbine_run_point.efficiency) - assert np.allclose(fuel_consumption_kg_per_s_ref, gas_turbine_run_point.fuel_flow_rate_kg_per_s.fuels[0].consumption) + np.testing.assert_allclose(eff_cogas, gas_turbine_run_point.efficiency) + np.testing.assert_allclose(fuel_consumption_kg_per_s_ref, gas_turbine_run_point.fuel_flow_rate_kg_per_s.fuels[0].consumption) + + # Test if the default NOx emission curve is IMO Tier 3 + factor, exponent = nox_factor_imo_medium_speed_g_hWh[NOxCalculationMethod.TIER_3.value] + nox_g_per_kwh = factor * np.power(cogas.rated_speed, exponent) + np.testing.assert_equal(cogas._emissions_per_kwh_interp[EmissionType.NOX](np.random.rand()), nox_g_per_kwh) def test_coges(self): #: Create an engine component From 98dc8109c62c49c1a1f4350db478163e45b7ebe3 Mon Sep 17 00:00:00 2001 From: keviny Date: Thu, 28 Mar 2024 15:05:53 +0100 Subject: [PATCH 16/28] coges integrated for the system --- .../components_model/component_mechanical.py | 3 ++- feems/feems/components_model/node.py | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/feems/feems/components_model/component_mechanical.py b/feems/feems/components_model/component_mechanical.py index 4ea4dba..0b03356 100644 --- a/feems/feems/components_model/component_mechanical.py +++ b/feems/feems/components_model/component_mechanical.py @@ -503,7 +503,8 @@ def _setup_emissions(self, emissions_curves: List[EmissionCurve] = None) -> None @property def fuel_consumer_type_fuel_eu_maritime(self) -> FuelConsumerClassFuelEUMaritime: - raise NotImplementedError("Fuel consumer type for COGAS is not defined in FuelEU Maritime regulation yet.") + Warning("Fuel consumer type for COGAS is not defined in FuelEU Maritime regulation yet.") + return None def emissions_g_per_kwh(self, emission_type: EmissionType, load_ratio: T) -> Optional[T]: if emission_type in self._emissions_per_kwh_interp: diff --git a/feems/feems/components_model/node.py b/feems/feems/components_model/node.py index bba855c..6dc75a3 100644 --- a/feems/feems/components_model/node.py +++ b/feems/feems/components_model/node.py @@ -8,6 +8,7 @@ from .component_base import Component from .component_electric import ( + COGES, ElectricComponent, FuelCellSystem, Genset, @@ -310,6 +311,32 @@ def get_fuel_emission_energy_balance_for_component( ) / 1000 ) + elif component.type == TypeComponent.COGES: + component = cast(COGES, component) + coges_run_point = component.get_system_run_point_from_power_output_kw( + fuel_specified_by=fuel_specified_by, + ) + res.multi_fuel_consumption_total_kg = integrate_multi_fuel_consumption( + fuel_consumption_kg_per_s=coges_run_point.cogas.fuel_flow_rate_kg_per_s, + time_interval_s=time_interval_s, + integration_method=integration_method, + ) + res.co2_emission_total_kg = res.multi_fuel_consumption_total_kg.get_total_co2_emissions(component.cogas.fuel_consumer_type_fuel_eu_maritime) + + if ( + np.isscalar(coges_run_point.coges_load_ratio) + or coges_run_point.coges_load_ratio.size == 1 + ): + res.load_ratio_genset = genset_run_point.coges_load_ratio + + set_emission( + engine_out=coges_run_point.coges, + integration_method=integration_method, + result=res, + time_interval_s=time_interval_s + ) + + res.running_hours_genset_total_hr = running_hours else: raise TypeError( f"Component type {component.type} not supported for energy balance calculation" From 53726392aefcb562871c0bed7fc451d96eb2c8d0 Mon Sep 17 00:00:00 2001 From: keviny Date: Thu, 28 Mar 2024 16:56:47 +0100 Subject: [PATCH 17/28] system with coges tested --- .../feems/components_model/component_base.py | 7 +- .../components_model/component_electric.py | 16 ++- .../components_model/component_mechanical.py | 10 +- feems/feems/components_model/node.py | 4 +- feems/feems/fuel.py | 1 - feems/feems/system_model.py | 3 +- feems/tests/test_system.py | 110 +++++++++++++++++- feems/tests/utility.py | 1 - 8 files changed, 141 insertions(+), 11 deletions(-) diff --git a/feems/feems/components_model/component_base.py b/feems/feems/components_model/component_base.py index 4a8fd77..53e811e 100644 --- a/feems/feems/components_model/component_base.py +++ b/feems/feems/components_model/component_base.py @@ -1,5 +1,5 @@ -from typing import Union, List, Tuple, Optional, TypeVar -from dataclasses import dataclass +from typing import Union, List, Tuple, Optional, TypeVar, Dict +from dataclasses import dataclass, field import numpy as np import pandas as pd @@ -13,6 +13,7 @@ from .. import get_logger from ..exceptions import InputError from ..types_for_feems import ( + EmissionType, TypeComponent, TypePower, Power_kW, @@ -34,6 +35,8 @@ class ComponentRunPoint: load_ratio: np.ndarray efficiency: np.ndarray fuel_flow_rate_kg_per_s: FuelConsumption + emissions_g_per_s: Dict[EmissionType, np.ndarray] = field(default_factory=dict) + class Component: """ diff --git a/feems/feems/components_model/component_electric.py b/feems/feems/components_model/component_electric.py index c39c292..1ed1368 100644 --- a/feems/feems/components_model/component_electric.py +++ b/feems/feems/components_model/component_electric.py @@ -915,7 +915,14 @@ def __init__( self.status = np.ones(0).astype(bool) self.load_sharing_mode = np.zeros(1) - def get_system_run_point_from_power_output_kw(self, power_output_kw: np.ndarray = None) -> COGESRunPoint: + def get_system_run_point_from_power_output_kw( + self, + power_output_kw: np.ndarray = None, + fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, + lhv_mj_per_g: Optional[float] = None, + ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, + ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ) -> COGESRunPoint: """ Get the run point of the COGES system based on the power output of the system @@ -930,7 +937,12 @@ def get_system_run_point_from_power_output_kw(self, power_output_kw: np.ndarray power_output_kw = self.power_output self.cogas.power_output, load_generator = self.generator.set_power_input_from_output(power_output_kw) - cogas_run_point = self.cogas.get_gas_turbine_run_point_from_power_output_kw() + cogas_run_point = self.cogas.get_gas_turbine_run_point_from_power_output_kw( + fuel_specified_by=fuel_specified_by, + lhv_mj_per_g=lhv_mj_per_g, + ghg_emission_factor_well_to_tank_gco2eq_per_mj=ghg_emission_factor_well_to_tank_gco2eq_per_mj, + ghg_emission_factor_tank_to_wake=ghg_emission_factor_tank_to_wake, + ) return COGESRunPoint( coges_load_ratio=load_generator, cogas=cogas_run_point, diff --git a/feems/feems/components_model/component_mechanical.py b/feems/feems/components_model/component_mechanical.py index 0b03356..e86309c 100644 --- a/feems/feems/components_model/component_mechanical.py +++ b/feems/feems/components_model/component_mechanical.py @@ -550,6 +550,9 @@ def get_gas_turbine_run_point_from_power_output_kw( ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, ) -> ComponentRunPoint: + # GHG factors for FuelEU Maritime is not available for COGAS yet. It should raise an error if the user tries to use it. + if fuel_specified_by == FuelSpecifiedBy.FUEL_EU_MARITIME: + raise ValueError("GHG factors for FuelEU Maritime is not available for COGAS yet.") if power_kw is None: power_kw = self.power_output load_ratio = self.get_load(power_kw) @@ -564,11 +567,16 @@ def get_gas_turbine_run_point_from_power_output_kw( ) fuel_power_kw = power_kw / eff fuel_consumption_kg_per_s = fuel_power_kw / (fuel.lhv_mj_per_g * 1000) / 1000 - fuel.consumption = fuel_consumption_kg_per_s + fuel.mass_or_mass_fraction = fuel_consumption_kg_per_s + emissionn_per_s = {} + power_kwh_per_s = power_kw / 3600 + for e in self._emissions_per_kwh_interp: + emissionn_per_s[e] = self.emissions_g_per_kwh(emission_type=e, load_ratio=load_ratio) * power_kwh_per_s return ComponentRunPoint( load_ratio=load_ratio, fuel_flow_rate_kg_per_s=FuelConsumption(fuels=[fuel]), efficiency=eff, + emissions_g_per_s=emissionn_per_s ) diff --git a/feems/feems/components_model/node.py b/feems/feems/components_model/node.py index 6dc75a3..6191290 100644 --- a/feems/feems/components_model/node.py +++ b/feems/feems/components_model/node.py @@ -327,10 +327,10 @@ def get_fuel_emission_energy_balance_for_component( np.isscalar(coges_run_point.coges_load_ratio) or coges_run_point.coges_load_ratio.size == 1 ): - res.load_ratio_genset = genset_run_point.coges_load_ratio + res.load_ratio_genset = coges_run_point.coges_load_ratio set_emission( - engine_out=coges_run_point.coges, + engine_out=coges_run_point.cogas, integration_method=integration_method, result=res, time_interval_s=time_interval_s diff --git a/feems/feems/fuel.py b/feems/feems/fuel.py index 7a6df1c..b4e8020 100644 --- a/feems/feems/fuel.py +++ b/feems/feems/fuel.py @@ -162,7 +162,6 @@ class Fuel: lhv_mj_per_g: Optional[float] = None ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None ghg_emission_factor_tank_to_wake: Optional[List[GhgEmissionFactorTankToWake]] = None - consumption: float = 0.0 mass_or_mass_fraction: Union[np.array, float] = 0.0 def __init__( diff --git a/feems/feems/system_model.py b/feems/feems/system_model.py index aabd74b..81e77dd 100644 --- a/feems/feems/system_model.py +++ b/feems/feems/system_model.py @@ -14,6 +14,7 @@ from . import get_logger from .components_model.component_electric import ( + COGES, ElectricComponent, ElectricMachine, Genset, @@ -101,7 +102,7 @@ def __init__( #: Categorize the components for component in power_plant_components: if component.power_type == TypePower.POWER_SOURCE: - if isinstance(component, (ElectricMachine, Genset, FuelCellSystem)): + if isinstance(component, (ElectricMachine, Genset, FuelCellSystem, COGES)): self.power_sources.append(component) power_source2switchboard.append(component.switchboard_id) component2switchboard.append(component.switchboard_id) diff --git a/feems/tests/test_system.py b/feems/tests/test_system.py index 89ffc3b..62059fc 100644 --- a/feems/tests/test_system.py +++ b/feems/tests/test_system.py @@ -1,8 +1,12 @@ import copy +import pprint import random from typing import List, Dict from unittest import TestCase +from feems.components_model.component_electric import COGES, ElectricMachine, SerialSystemElectric +from feems.components_model.component_mechanical import COGAS +from feems.fuel import Fuel, FuelConsumption import numpy as np from feems.components_model import ( @@ -17,6 +21,7 @@ from feems.components_model.utility import IntegrationMethod from feems.system_model import ElectricPowerSystem, BusId, MechanicalPropulsionSystem from feems.types_for_feems import ( + SwbId, TypeComponent, TypePower, Power_kW, @@ -28,8 +33,10 @@ # import os from tests.utility import ( + ELECTRIC_MACHINE_EFF_CURVE, create_a_pti_pto, create_a_propulsion_drive, + create_cogas_system, create_genset_component, ) @@ -176,7 +183,7 @@ def setUp(self) -> None: ) energy_storage_for_diesel_electric = copy.deepcopy(energy_storage_for_hybrid) energy_storage_for_conventional = copy.deepcopy(energy_storage_for_hybrid) - + # Thruster self.no_thruster = 2 self.no_thruster_diesel_electric = self.no_switchboard_diesel_electric @@ -895,6 +902,107 @@ def test_battery_only_configuration(self): self.assertLess(result.energy_stored_total_mj, 0) +class TestCOGESSystem(TestCase): + def setUp(self) -> None: + # Create COGES systems + self.coges: List[COGES] = [] + self.propulsion_drive: List[SerialSystemElectric] = [] + self.other_load = ElectricComponent( + type_=TypeComponent.OTHER_LOAD, + name="other loads", + power_type=TypePower.POWER_CONSUMER, + rated_power=Power_kW(1000), + eff_curve=np.array([1]), + switchboard_id=1, + ) + for i in range(1, 3): + cogas = create_cogas_system() + generator = ElectricMachine( + type_=TypeComponent.GENERATOR, + name=f"generator {i}", + rated_power=cogas.rated_power * 0.9, + rated_speed=cogas.rated_speed, + power_type=TypePower.POWER_SOURCE, + switchboard_id=SwbId(i), + number_poles=4, + eff_curve=ELECTRIC_MACHINE_EFF_CURVE, + ) + self.coges.append(COGES( + name=f"COGES {i}", + cogas=cogas, + generator=generator, + )) + # Create a propulsion drive + self.propulsion_drive.append(create_a_propulsion_drive( + name=f"propulsion drive {i}", + rated_power=600, + rated_speed=750, + switchboard_id=i, + )) + self.system = ElectricPowerSystem( + name="COGES system", + power_plant_components=[ + *self.coges, *self.propulsion_drive, self.other_load + ], + bus_tie_connections=[(1, 2)], + ) + + def test_configuration(self): + # Test the configuration + self.assertEqual(self.system.no_power_sources, len(self.coges)) + self.assertEqual(self.system.no_propulsion_units, len(self.propulsion_drive)) + self.assertEqual(self.system.no_other_load, 1) + self.assertEqual(self.system.no_energy_storage, 0) + self.assertEqual(self.system.no_pti_pto, 0) + self.assertEqual(self.system.no_bus_tie_breakers, 1) + self.assertEqual(self.system.no_bus_configuration_change, 1) + self.assertEqual(self.system.no_switchboard, 2) + self.assertEqual(self.system.no_bus, [1]) + + def test_get_fuel_consumption(self): + propulsion_loads = [propulsion_drive.rated_power * np.random.random(1) for propulsion_drive in self.propulsion_drive] + other_loads = np.array([400 * np.random.random()]) + + # Set the power input for the propulsion drives and other loads + for propulsion_drive, load in zip(self.propulsion_drive, propulsion_loads): + propulsion_drive.set_power_input_from_output(load) + self.other_load.set_power_input_from_output(other_loads) + + # Set the bus tie status + self.system.bus_tie_breakers[0].status = np.ones(1).astype(bool) + + # Set the status and load sharing mode for the power sources + for coges in self.coges: + coges.status = np.ones(1).astype(bool) + coges.load_sharing_mode = np.zeros(1) + + # Set time interval + self.system.set_time_interval(time_interval_s=3600, integration_method=IntegrationMethod.sum_with_time) + + # Do power balance + self.system.do_power_balance_calculation() + + # Calculate the fuel consumption manually + cogas_fuel_consumption = 0 + for coges in self.coges: + cogas_power_output, _ = coges.generator.get_power_input_from_bidirectional_output(coges.power_output) + cogas_efficiency = coges.cogas.get_efficiency_from_load_percentage( + cogas_power_output / coges.cogas.rated_power + ) + lhv_fuel_mj_per_g = Fuel( + fuel_type=coges.cogas.fuel_type, + origin=coges.cogas.fuel_origin, + ).lhv_mj_per_g + cogas_fuel_consumption_rate = cogas_power_output / cogas_efficiency / (lhv_fuel_mj_per_g * 1000) / 1000 + cogas_fuel_consumption += cogas_fuel_consumption_rate * 3600 + + # Get the fuel consumption + result = self.system.get_fuel_energy_consumption_running_time() + fuel_consumption_result = result.fuel_consumption_total_kg + # Compare the results + self.assertAlmostEqual(cogas_fuel_consumption[0], fuel_consumption_result, 5) + + class TestMechanicalPropulsionSystemSetup(TestCase): def setUp(self) -> None: """Set up the test case with default system configuration""" diff --git a/feems/tests/utility.py b/feems/tests/utility.py index 95d8b2a..627dd2e 100644 --- a/feems/tests/utility.py +++ b/feems/tests/utility.py @@ -758,7 +758,6 @@ def create_cogas_system( steam_turbine_power_curve: np.ndarray = None, fuel_type: TypeFuel = TypeFuel.NATURAL_GAS, fuel_origin: FuelOrigin = FuelOrigin.FOSSIL, - ) -> COGAS: # Create a cogas system if eff_curve is None: From f50f8296bdce2e025cd39892f275dcb5897eb879 Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 2 Apr 2024 09:29:34 +0200 Subject: [PATCH 18/28] Coges tested for all libraries --- RunFEEMSSim/00_machinery_calculation.ipynb | 170 +- RunFEEMSSim/01_pms_basic.ipynb | 4 +- RunFEEMSSim/RunFeemsSim/__init__.py | 2 +- RunFEEMSSim/settings.ini | 2 +- ...anical_propulsion_with_electric_system.mss | Bin 3041 -> 3047 bytes RunFEEMSSim/tests/system_proto.mss | Bin 2796 -> 3529 bytes feems/feems/__init__.py | 4 +- .../feems/components_model/component_base.py | 51 +- .../components_model/component_electric.py | 76 +- .../components_model/component_mechanical.py | 103 +- feems/feems/components_model/node.py | 253 +- feems/feems/components_model/utility.py | 24 +- feems/feems/fuel.py | 60 +- feems/feems/runsimulation.py | 20 +- feems/feems/simulation_interface.py | 31 +- feems/feems/system_model.py | 184 +- feems/feems/types_for_feems.py | 30 +- feems/tests/test_battery.py | 12 +- feems/tests/test_components.py | 135 +- feems/tests/test_fuel.py | 28 +- .../test_mechanical_system_simulation.py | 53 +- feems/tests/test_node.py | 141 +- feems/tests/test_system.py | 273 +- feems/tests/test_system_simplified.py | 24 +- feems/tests/test_utility_for_test.py | 6 +- feems/tests/utility.py | 80 +- .../00_ConvertToFeems.ipynb | 119 +- .../01_ConvertToProtobuf.ipynb | 870 +- .../03_ConvertFEEMSResultToProto.ipynb | 139 +- ...ConvertTimeSeriesResultProtoToPandas.ipynb | 17929 +++++++++++++++- .../MachSysS/__init__.py | 2 +- .../MachSysS/_modidx.py | 12 +- .../MachSysS/convert_to_feems.py | 117 +- .../MachSysS/system_structure_pb2.py | 130 +- .../MachSysS/system_structure_pb2.pyi | 84 + .../proto/system_structure.proto | 40 +- machinery-system-structure/settings.ini | 2 +- .../tests/electric_propulsion_system.mss | Bin 3518 -> 3529 bytes .../tests/electric_system_with_pto.mss | Bin 2647 -> 2652 bytes .../tests/hybrid_propulsion_system.mss | Bin 3832 -> 3840 bytes ...anical_propulsion_with_electric_system.mss | Bin 3041 -> 3047 bytes .../tests/mechanical_system_with_pto.mss | Bin 1153 -> 1156 bytes .../tests/system_proto.mss | Bin 3518 -> 3529 bytes 43 files changed, 19971 insertions(+), 1239 deletions(-) diff --git a/RunFEEMSSim/00_machinery_calculation.ipynb b/RunFEEMSSim/00_machinery_calculation.ipynb index 69a084e..1ce15ea 100644 --- a/RunFEEMSSim/00_machinery_calculation.ipynb +++ b/RunFEEMSSim/00_machinery_calculation.ipynb @@ -17,7 +17,16 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The autoreload extension is already loaded. To reload it, use:\n", + " %reload_ext autoreload\n" + ] + } + ], "source": [ "# | default_exp machinery_calculation\n", "%load_ext autoreload\n", @@ -708,6 +717,83 @@ " name: \"Other load 1\"\n", " rated_power_kw: 1000\n", " }\n", + " subsystems {\n", + " converter1 {\n", + " name: \"Converter 1\"\n", + " rated_power_kw: 3150\n", + " efficiency {\n", + " curve {\n", + " x_label: \"power load\"\n", + " y_label: \"efficiency\"\n", + " curve {\n", + " points {\n", + " x: 0.1\n", + " y: 0.9\n", + " }\n", + " points {\n", + " x: 0.25\n", + " y: 0.95\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 0.96\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 0.97\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 0.96\n", + " }\n", + " }\n", + " }\n", + " }\n", + " order_from_switchboard_or_shaftline: 1\n", + " }\n", + " fuel_cell {\n", + " name: \"Fuel cell 1\"\n", + " rated_power_kw: 1000\n", + " efficiency {\n", + " curve {\n", + " x_label: \"power load\"\n", + " y_label: \"efficiency\"\n", + " curve {\n", + " points {\n", + " x: 0.1\n", + " y: 0.7\n", + " }\n", + " points {\n", + " x: 0.25\n", + " y: 0.85\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 0.96\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 0.97\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 0.96\n", + " }\n", + " }\n", + " }\n", + " }\n", + " order_from_switchboard_or_shaftline: 2\n", + " fuel {\n", + " fuel_type: HYDROGEN\n", + " fuel_origin: RENEWABLE_NON_BIO\n", + " }\n", + " number_modules: 3\n", + " }\n", + " power_type: POWER_SOURCE\n", + " component_type: FUEL_CELL_SYSTEM\n", + " name: \"Fuel cell system 1\"\n", + " rated_power_kw: 3150\n", + " }\n", " }\n", " switchboards {\n", " switchboard_id: 2\n", @@ -982,10 +1068,87 @@ " rated_power_kw: 2000\n", " rated_speed_rpm: 1000\n", " }\n", + " subsystems {\n", + " converter1 {\n", + " name: \"Converter 1\"\n", + " rated_power_kw: 3150\n", + " efficiency {\n", + " curve {\n", + " x_label: \"power load\"\n", + " y_label: \"efficiency\"\n", + " curve {\n", + " points {\n", + " x: 0.1\n", + " y: 0.9\n", + " }\n", + " points {\n", + " x: 0.25\n", + " y: 0.95\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 0.96\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 0.97\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 0.96\n", + " }\n", + " }\n", + " }\n", + " }\n", + " order_from_switchboard_or_shaftline: 1\n", + " }\n", + " fuel_cell {\n", + " name: \"Fuel cell 1\"\n", + " rated_power_kw: 1000\n", + " efficiency {\n", + " curve {\n", + " x_label: \"power load\"\n", + " y_label: \"efficiency\"\n", + " curve {\n", + " points {\n", + " x: 0.1\n", + " y: 0.7\n", + " }\n", + " points {\n", + " x: 0.25\n", + " y: 0.85\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 0.96\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 0.97\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 0.96\n", + " }\n", + " }\n", + " }\n", + " }\n", + " order_from_switchboard_or_shaftline: 2\n", + " fuel {\n", + " fuel_type: HYDROGEN\n", + " fuel_origin: RENEWABLE_NON_BIO\n", + " }\n", + " number_modules: 3\n", + " }\n", + " power_type: POWER_SOURCE\n", + " component_type: FUEL_CELL_SYSTEM\n", + " name: \"Fuel cell system 1\"\n", + " rated_power_kw: 3150\n", + " }\n", " }\n", "}\n", "\n", - "Average bsfc for engines: 305.69896408621025 g/kWh\n" + "Average bsfc for engines: 248.41624983126195 g/kWh\n" ] } ], @@ -1024,9 +1187,6 @@ "running_hours_mean = 0\n", "for power_source in machinery_calculation.electric_system.power_sources:\n", " running_hours_mean += (power_source.power_output > 0).mean()\n", - " generator_run_point = (\n", - " power_source.get_fuel_cons_load_bsfc_from_power_out_generator_kw()\n", - " )\n", "for propulsor in machinery_calculation.electric_system.propulsion_drives:\n", " average_power_consumption += propulsor.power_input.mean()\n", "average_bsfc_for_engines = res.fuel_consumption_total_kg / (\n", diff --git a/RunFEEMSSim/01_pms_basic.ipynb b/RunFEEMSSim/01_pms_basic.ipynb index 3fd9d5a..40a9818 100644 --- a/RunFEEMSSim/01_pms_basic.ipynb +++ b/RunFEEMSSim/01_pms_basic.ipynb @@ -251,7 +251,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "{0.0: (False, False, False, True), 800.0: (False, False, True, True), 1600.0: (False, True, True, True), 2400.0: (True, True, True, True)}\n" + "{0.0: (False, False, False, False, True, False), 800.0: (False, False, False, True, True, False), 1600.0: (False, True, False, True, True, False), 2400.0: (False, False, False, False, False, True), 2520.0: (True, True, False, True, True, False), 3200.0: (False, False, False, False, True, True), 3320.0: (False, False, False, True, True, True), 4120.0: (False, True, False, True, True, True), 4920.0: (False, False, True, False, False, True), 5040.0: (True, True, False, True, True, True), 5720.0: (False, False, True, False, True, True), 5840.0: (False, False, True, True, True, True), 6640.0: (False, True, True, True, True, True), 7440.0: (True, True, True, True, True, True)}\n" ] } ], @@ -260,7 +260,7 @@ "system_proto = retrieve_machinery_system_from_file(path)\n", "\n", "load_table_dict = get_min_load_table_dict_from_proto_system(system_proto)\n", - "assert len(load_table_dict) == 4\n", + "np.testing.assert_equal(len(load_table_dict), 14)\n", "print(load_table_dict)" ] }, diff --git a/RunFEEMSSim/RunFeemsSim/__init__.py b/RunFEEMSSim/RunFeemsSim/__init__.py index b5fdc75..d31c31e 100644 --- a/RunFEEMSSim/RunFeemsSim/__init__.py +++ b/RunFEEMSSim/RunFeemsSim/__init__.py @@ -1 +1 @@ -__version__ = "0.2.2" +__version__ = "0.2.3" diff --git a/RunFEEMSSim/settings.ini b/RunFEEMSSim/settings.ini index 5b28dfa..c7539b9 100644 --- a/RunFEEMSSim/settings.ini +++ b/RunFEEMSSim/settings.ini @@ -8,7 +8,7 @@ author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF branch = master -version = 0.2.2 +version = 0.2.3 min_python = 3.10 audience = Developers language = English diff --git a/RunFEEMSSim/tests/mechanical_propulsion_with_electric_system.mss b/RunFEEMSSim/tests/mechanical_propulsion_with_electric_system.mss index 404d0987bb51ce6508801aafae09424076fa59e0..5f066a49893ae0a8e9b292d202e6d26716321300 100644 GIT binary patch delta 271 zcmaDT{#<;54Ci-Nt}m<{j6!W2Ro$7`3K%OGn;0h-GO3AmGBSX`l#31%AuI+z2ch)I zYnhz&3YaRynix3)it-Cmb8=FPph~lDASpFEFUZx%12p*XW?ANiOsYVWd72nG+*9+4 zQ%e*Kp;{dJVOkV=9Dqt6v0^AS!m6}z@^X$aC7?rCn;5zLOEOZ66ms$tQ($V>J8+#~ VwNg360W0)#r%K=*;K-d5P delta 265 zcmaDZ{!n~^4Chx?u1~BSj6$s&Ro$6bGZ+gPt0osQsfjf*GJwF8iw>O-7K5LIP}<~m zOwPI)Oa)?9oB>7o1*thXsYOtgSvQbW8l4v8`o|44_RwZ|=7mfuKy!JjINVe7ic?Dz z452z4`e8a0dK`c%pR%H>G{UN~VDf5?Fh!s%SgW}FOEOZ66ms$tQ(#KhJ8&Im;+WJAqye)0ijNdNr2IS$%9F%pOK5(JvA@2D6u5JNWl<`D|5KA zP+ZBCnwFNCoSB-JTqzZR?AA0ecxI36R%0-DjSvI6b%$K*>%blF5Mn^La$R3sV9WL1 zUW2iKv4W?Gkpt+a;?xoa!%jw6a7~1>hERYS4YmL^!Wy70Oj@&n3Bfr(uPn8w1ehKX z2|=oXk*f}80zgTuXU~AZ8$`qc6DuT9AVoHT1OQJwz{CnmC<=^L&Rm>Mi6uanRU$bJ zl9L!d*h9122YXFOdV6ng2xC}6veHX?2c`m+3ic*O0hl?E{ED2ygnlwft!CsB3P5D) z+S$F6sz9jLej%+Y9Ica}ogFgTiW*EL)JXuh C(UPeE delta 417 zcmX>p{YG?x2InDBu9@5%j6!EO8tO2rWH1)+RB^bc<`t)wC>S;}GJt?Xze6XSC3JS8 z;mXO{OwFijjj*b1o}9=dKKT{XS)~k?0`@8ar^J$y)S^m-;>zNZ)Ldi>gnn$k#q7(d zm%&uPQY92nlwVMqQ=FNfr{GeQS(b`WIUm_6C6mKgBb0$!SgUyaOEOZ66ms$tQxJ;# l9k>>AaWFxg{FEKd$;Mcn4ECNGCz@IltZGU2o(?JA0|0agZ`uF= diff --git a/feems/feems/__init__.py b/feems/feems/__init__.py index 92e904b..3c01332 100644 --- a/feems/feems/__init__.py +++ b/feems/feems/__init__.py @@ -9,7 +9,9 @@ def get_logger(name: str) -> logging.Logger: ch = logging.StreamHandler() ch.setLevel(logging.INFO) - formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") + formatter = logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + ) ch.setFormatter(formatter) logger.addHandler(ch) diff --git a/feems/feems/components_model/component_base.py b/feems/feems/components_model/component_base.py index 53e811e..001be32 100644 --- a/feems/feems/components_model/component_base.py +++ b/feems/feems/components_model/component_base.py @@ -95,7 +95,9 @@ def __init__( rated_speed: Speed_rpm = Speed_rpm(0.0), file_name: str = None, ): - super(BasicComponent, self).__init__(name, type_, power_type, rated_power, rated_speed) + super(BasicComponent, self).__init__( + name, type_, power_type, rated_power, rated_speed + ) if file_name is not None: df = pd.read_csv(file_name, index_col=0) self.rated_power = df["Rated Power"].values[0] @@ -123,7 +125,9 @@ def __init__( raise InputError(err_msg) #: Make a mapping between the power in to out - power_out = np.arange(-self.rated_power, self.rated_power, self.rated_power * 0.01) + power_out = np.arange( + -self.rated_power, self.rated_power, self.rated_power * 0.01 + ) load = self.get_load(power_out) power_in = power_out / self.get_efficiency_from_load_percentage(load) @@ -154,7 +158,9 @@ def _get_power_output_and_load_from_input( power_output = self._power_out_interp(power_input) if strict_power_balance: if type(power_input) is not np.ndarray: - power_output = newton(self._power_balance, power_output, args=(power_input,)) + power_output = newton( + self._power_balance, power_output, args=(power_input,) + ) else: no_points_per_batch = 50 no_points = len(power_input) @@ -207,7 +213,9 @@ def get_power_input_from_bidirectional_output( ( power_input[idx_forward_power], load[idx_forward_power], - ) = self._get_power_input_and_load_from_output(power_output[idx_forward_power]) + ) = self._get_power_input_and_load_from_output( + power_output[idx_forward_power] + ) ( power_input[idx_reverse_power], load[idx_reverse_power], @@ -238,7 +246,9 @@ def get_power_output_from_bidirectional_input( ( power_output[idx_reverse_power], load[idx_reverse_power], - ) = self._get_power_input_and_load_from_output(power_input[idx_reverse_power]) + ) = self._get_power_input_and_load_from_output( + power_input[idx_reverse_power] + ) return power_output, load def set_power_input_from_output( @@ -257,7 +267,9 @@ def set_power_input_from_output( self.power_output = power_output #: Calculate the power input and %load considering the efficiency - self.power_input, load = self.get_power_input_from_bidirectional_output(power_output) + self.power_input, load = self.get_power_input_from_bidirectional_output( + power_output + ) #: Return the result return self.power_input, load @@ -278,7 +290,9 @@ def set_power_output_from_input( self.power_input = power_input #: Calculate the power output and %load considering the efficiency - self.power_output, load = self.get_power_output_from_bidirectional_input(power_input) + self.power_output, load = self.get_power_output_from_bidirectional_input( + power_input + ) #: Return the result return self.power_output, load @@ -322,10 +336,14 @@ def _d_power_balance(self, x: np.ndarray, power_input: Numeric) -> float: load = self.get_load(x) if not isinstance(power_input, np.ndarray): if power_input > 0: - power_output = power_input * self.get_efficiency_from_load_percentage(load) + power_output = power_input * self.get_efficiency_from_load_percentage( + load + ) d_power_output = power_input * self._get_d_efficiency(x, 0.001 * x) else: - power_output = power_input / self.get_efficiency_from_load_percentage(load) + power_output = power_input / self.get_efficiency_from_load_percentage( + load + ) d_power_output = ( -power_input * self._get_d_efficiency(x, 0.001 * x) @@ -341,19 +359,26 @@ def _d_power_balance(self, x: np.ndarray, power_input: Numeric) -> float: ] * self.get_efficiency_from_load_percentage(load[idx_forward_power]) d_power_output[idx_forward_power] = power_input[ idx_forward_power - ] * self._get_d_efficiency(x[idx_forward_power], 0.001 * x[idx_forward_power]) + ] * self._get_d_efficiency( + x[idx_forward_power], 0.001 * x[idx_forward_power] + ) power_output[idx_reverse_power] = power_input[ idx_reverse_power ] / self.get_efficiency_from_load_percentage(load[idx_reverse_power]) d_power_output[idx_reverse_power] = ( -power_input[idx_reverse_power] - * self._get_d_efficiency(x[idx_reverse_power], 0.001 * x[idx_reverse_power]) - / (self.get_efficiency_from_load_percentage(load[idx_reverse_power])) ** 2 + * self._get_d_efficiency( + x[idx_reverse_power], 0.001 * x[idx_reverse_power] + ) + / (self.get_efficiency_from_load_percentage(load[idx_reverse_power])) + ** 2 ) power_balance = x - power_output return (power_balance * (1 - d_power_output)).sum() - def _get_d_efficiency(self, power: np.ndarray, power_delta: np.ndarray) -> np.ndarray: + def _get_d_efficiency( + self, power: np.ndarray, power_delta: np.ndarray + ) -> np.ndarray: load = self.get_load(power) load_delta = self.get_load(power + power_delta) return ( diff --git a/feems/feems/components_model/component_electric.py b/feems/feems/components_model/component_electric.py index 1ed1368..5c09199 100644 --- a/feems/feems/components_model/component_electric.py +++ b/feems/feems/components_model/component_electric.py @@ -126,7 +126,8 @@ def get_shaft_power_load_from_electric_power( power_electric, strict_power_balance ) elif ( - self.power_type == TypePower.POWER_CONSUMER or self.power_type == TypePower.PTI_PTO_SYS + self.power_type == TypePower.POWER_CONSUMER + or self.power_type == TypePower.PTI_PTO_SYS ): power_shaft, load = self.get_power_output_from_bidirectional_input( power_electric, strict_power_balance @@ -134,7 +135,9 @@ def get_shaft_power_load_from_electric_power( else: raise TypeError( "The type of the component for {} is not properly assigned. " - "It should be either power source, power consumer or PTI/PTO.".format(self.name) + "It should be either power source, power consumer or PTI/PTO.".format( + self.name + ) ) return power_shaft, load @@ -158,14 +161,19 @@ def get_electric_power_load_from_shaft_power( power_electric, load = self.get_power_output_from_bidirectional_input( power_shaft, strict_power_balance ) - elif self.power_type == TypePower.POWER_CONSUMER or self.power_type == TypePower.PTI_PTO: + elif ( + self.power_type == TypePower.POWER_CONSUMER + or self.power_type == TypePower.PTI_PTO + ): power_electric, load = self.get_power_input_from_bidirectional_output( power_shaft, strict_power_balance ) else: raise TypeError( "The type of the component for {} is not properly assigned. " - "It should be either power source, power consumer or PTI/PTO.".format(self.name), + "It should be either power source, power consumer or PTI/PTO.".format( + self.name + ), ) return power_electric, load @@ -280,7 +288,9 @@ def get_power_input_from_bidirectional_output( idx_discharging = power_output < 0 power_input = power_output.copy() power_input[idx_charging] = power_output[idx_charging] / self.eff_charging - power_input[idx_discharging] = power_output[idx_discharging] * self.eff_discharging + power_input[idx_discharging] = ( + power_output[idx_discharging] * self.eff_discharging + ) return power_input, load def get_power_output_from_bidirectional_input( @@ -296,7 +306,9 @@ def get_power_output_from_bidirectional_input( idx_discharging = power_input < 0 power_output = power_input.copy() power_output[idx_charging] = power_output[idx_charging] * self.eff_charging - power_output[idx_discharging] = power_output[idx_discharging] / self.eff_discharging + power_output[idx_discharging] = ( + power_output[idx_discharging] / self.eff_discharging + ) load = self.get_load(power_output) return power_output, load @@ -365,7 +377,9 @@ def get_fuel_cell_run_point( fuel_specified_by=FuelSpecifiedBy.IMO, lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, - ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ghg_emission_factor_tank_to_wake: List[ + Optional[GhgEmissionFactorTankToWake] + ] = None, ) -> ComponentRunPoint: """ Get the fuel cell run point @@ -389,7 +403,9 @@ def get_fuel_cell_run_point( """ if power_out_kw is None: power_out_kw = self.power_output - power_in_kw, load_ratio = self.get_power_input_from_bidirectional_output(power_out_kw) + power_in_kw, load_ratio = self.get_power_input_from_bidirectional_output( + power_out_kw + ) fuel = Fuel( fuel_type=self.fuel_type, origin=self.fuel_origin, @@ -443,7 +459,9 @@ def get_fuel_cell_run_point( fuel_specified_by=FuelSpecifiedBy.IMO, lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, - ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ghg_emission_factor_tank_to_wake: List[ + Optional[GhgEmissionFactorTankToWake] + ] = None, ) -> ComponentRunPoint: """ Get the fuel cell run point @@ -467,7 +485,9 @@ def get_fuel_cell_run_point( """ if power_out_kw is None: power_out_kw = self.power_output - power_out_fuel_cell_kw, load_ratio = self.set_power_input_from_output(power_out_kw) + power_out_fuel_cell_kw, load_ratio = self.set_power_input_from_output( + power_out_kw + ) result_per_module = self.fuel_cell.get_fuel_cell_run_point( power_out_kw=power_out_fuel_cell_kw / self.number_modules, fuel_specified_by=fuel_specified_by, @@ -631,7 +651,9 @@ def get_fuel_cons_load_bsfc_from_power_out_generator_kw( engine_run_point = self.aux_engine.get_engine_run_point_from_power_out_kw( fuel_specified_by=fuel_specified_by ) - return GensetRunPoint(genset_load_ratio=load_ratio_generator, engine=engine_run_point) + return GensetRunPoint( + genset_load_ratio=load_ratio_generator, engine=engine_run_point + ) class PTIPTO(SerialSystemElectric): @@ -754,7 +776,9 @@ def get_power_input_from_bidirectional_output( idx_discharging = power_output < 0 power_input = power_output.copy() power_input[idx_charging] = power_output[idx_charging] / self.eff_charging - power_input[idx_discharging] = power_output[idx_discharging] * self.eff_discharging + power_input[idx_discharging] = ( + power_output[idx_discharging] * self.eff_discharging + ) return power_input, load def get_power_output_from_bidirectional_input( @@ -770,7 +794,9 @@ def get_power_output_from_bidirectional_input( idx_discharging = power_input < 0 power_output = power_input.copy() power_output[idx_charging] = power_output[idx_charging] * self.eff_charging - power_output[idx_discharging] = power_output[idx_discharging] / self.eff_discharging + power_output[idx_discharging] = ( + power_output[idx_discharging] / self.eff_discharging + ) load = self.get_load(power_output) return power_output, load @@ -854,7 +880,9 @@ class ShorePowerConnection(ElectricComponent): :param switchboard_id: Switchboard ID """ - def __init__(self, name: str, rated_power: Power_kW, switchboard_id: SwbId = SwbId(0)): + def __init__( + self, name: str, rated_power: Power_kW, switchboard_id: SwbId = SwbId(0) + ): super().__init__( TypeComponent.SHORE_POWER, name, @@ -916,12 +944,14 @@ def __init__( self.load_sharing_mode = np.zeros(1) def get_system_run_point_from_power_output_kw( - self, + self, power_output_kw: np.ndarray = None, fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, - ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ghg_emission_factor_tank_to_wake: List[ + Optional[GhgEmissionFactorTankToWake] + ] = None, ) -> COGESRunPoint: """ Get the run point of the COGES system based on the power output of the system @@ -935,8 +965,10 @@ def get_system_run_point_from_power_output_kw( """ if power_output_kw is None: power_output_kw = self.power_output - - self.cogas.power_output, load_generator = self.generator.set_power_input_from_output(power_output_kw) + + self.cogas.power_output, load_generator = ( + self.generator.set_power_input_from_output(power_output_kw) + ) cogas_run_point = self.cogas.get_gas_turbine_run_point_from_power_output_kw( fuel_specified_by=fuel_specified_by, lhv_mj_per_g=lhv_mj_per_g, @@ -947,14 +979,14 @@ def get_system_run_point_from_power_output_kw( coges_load_ratio=load_generator, cogas=cogas_run_point, ) - + MechanicalComponent = Union[ MainEngineForMechanicalPropulsion, MainEngineWithGearBoxForMechanicalPropulsion, PTIPTO, MechanicalPropulsionComponent, - COGAS + COGAS, ] PowerSystemComponent = Union[ @@ -973,4 +1005,6 @@ def get_system_run_point_from_power_output_kw( ShorePowerConnectionSystem, ] -EnergyStorageComponent = Union[Battery, BatterySystem, SuperCapacitor, SuperCapacitorSystem] +EnergyStorageComponent = Union[ + Battery, BatterySystem, SuperCapacitor, SuperCapacitorSystem +] diff --git a/feems/feems/components_model/component_mechanical.py b/feems/feems/components_model/component_mechanical.py index e86309c..7c2b9b1 100644 --- a/feems/feems/components_model/component_mechanical.py +++ b/feems/feems/components_model/component_mechanical.py @@ -94,8 +94,8 @@ def _setup_emissions(self, emissions_curves) -> None: e: EmissionCurve for e in emissions_curves: if len(e.points_per_kwh) > 0: - self._emissions_per_kwh_interp[e.emission] = get_emission_curve_from_points( - e.points_per_kwh + self._emissions_per_kwh_interp[e.emission] = ( + get_emission_curve_from_points(e.points_per_kwh) ) def _setup_bsfc(self, bsfc_curve, file_name) -> None: @@ -128,9 +128,13 @@ def fuel_consumer_type_fuel_eu_maritime(self) -> FuelConsumerClassFuelEUMaritime elif self.engine_cycle_type == EngineCycleType.LEAN_BURN_SPARK_IGNITION: return FuelConsumerClassFuelEUMaritime.LNG_LBSI else: - raise ValueError(f"Invalid engine cycle type {self.engine_cycle_type} for LNG engine") + raise ValueError( + f"Invalid engine cycle type {self.engine_cycle_type} for LNG engine" + ) - def emissions_g_per_kwh(self, emission_type: EmissionType, load_ratio: T) -> Optional[T]: + def emissions_g_per_kwh( + self, emission_type: EmissionType, load_ratio: T + ) -> Optional[T]: if emission_type in self._emissions_per_kwh_interp: return self._emissions_per_kwh_interp[emission_type](load_ratio) else: @@ -162,7 +166,9 @@ def get_engine_run_point_from_power_out_kw( fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, - ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ghg_emission_factor_tank_to_wake: List[ + Optional[GhgEmissionFactorTankToWake] + ] = None, ) -> EngineRunPoint: """ Calculate fuel consumption, percentage load and bsfc. If power value is not given, it will @@ -193,7 +199,8 @@ def get_engine_run_point_from_power_out_kw( emissions_per_s = {} for e in self._emissions_per_kwh_interp: emissions_per_s[e] = ( - self.emissions_g_per_kwh(emission_type=e, load_ratio=load_ratio) * power_kwh_per_s + self.emissions_g_per_kwh(emission_type=e, load_ratio=load_ratio) + * power_kwh_per_s ) fuel_consumption_component = Fuel( fuel_type=self.fuel_type, @@ -257,7 +264,9 @@ def get_engine_run_point_from_power_out_kw( fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, - ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ghg_emission_factor_tank_to_wake: List[ + Optional[GhgEmissionFactorTankToWake] + ] = None, ) -> EngineRunPoint: """ Calculate fuel consumption, percentage load and bsfc. If power value is not given, it will @@ -333,7 +342,9 @@ def get_engine_run_point_from_power_out_kw( fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, - ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ghg_emission_factor_tank_to_wake: List[ + Optional[GhgEmissionFactorTankToWake] + ] = None, ) -> EngineRunPoint: """ Calculate fuel consumption, percentage load and bsfc for the shaft power before the gearbox @@ -409,7 +420,9 @@ def get_engine_run_point_from_power_out_kw( fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, - ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ghg_emission_factor_tank_to_wake: List[ + Optional[GhgEmissionFactorTankToWake] + ] = None, ) -> EngineRunPoint: """ Calculate fuel consumption, percentage load and bsfc for the shaft power before the gearbox @@ -443,6 +456,7 @@ def get_engine_run_point_from_power_out_kw( ghg_emission_factor_tank_to_wake=ghg_emission_factor_tank_to_wake, ) + class COGAS(BasicComponent): """Combined gas and steam component class for basic information and efficiency interpolation""" @@ -461,19 +475,26 @@ def __init__( ): """Constructor for COGES component""" # Validate the inputs for curves. The length of the curves should be the same and the x values should be the same. - if gas_turbine_power_curve is not None and steam_turbine_power_curve is not None: + if ( + gas_turbine_power_curve is not None + and steam_turbine_power_curve is not None + ): if gas_turbine_power_curve.shape != steam_turbine_power_curve.shape: - raise ValueError("The length of the gas turbine power curve and steam turbine power curve should be the same.") + raise ValueError( + "The length of the gas turbine power curve and steam turbine power curve should be the same." + ) if np.all(gas_turbine_power_curve[:, 0] != steam_turbine_power_curve[:, 0]): - raise ValueError("The x values of the gas turbine power curve and steam turbine power curve should be the same.") - + raise ValueError( + "The x values of the gas turbine power curve and steam turbine power curve should be the same." + ) + super().__init__( - type_=TypeComponent.COGAS, - power_type=TypePower.POWER_SOURCE, - name=name, - rated_power=rated_power, - eff_curve=eff_curve, - rated_speed=rated_speed + type_=TypeComponent.COGAS, + power_type=TypePower.POWER_SOURCE, + name=name, + rated_power=rated_power, + eff_curve=eff_curve, + rated_speed=rated_speed, ) self.gas_turbine_power_curve = gas_turbine_power_curve self.steam_turbine_power_curve = steam_turbine_power_curve @@ -488,7 +509,6 @@ def __init__( self.fuel_origin = fuel_origin self._setup_emissions(emissions_curves) self._setup_nox(NOx_calculation_method, rated_speed) - def _setup_emissions(self, emissions_curves: List[EmissionCurve] = None) -> None: self.emission_curves = emissions_curves @@ -497,16 +517,20 @@ def _setup_emissions(self, emissions_curves: List[EmissionCurve] = None) -> None e: EmissionCurve for e in emissions_curves: if len(e.points_per_kwh) > 0: - self._emissions_per_kwh_interp[e.emission] = get_emission_curve_from_points( - e.points_per_kwh + self._emissions_per_kwh_interp[e.emission] = ( + get_emission_curve_from_points(e.points_per_kwh) ) - + @property def fuel_consumer_type_fuel_eu_maritime(self) -> FuelConsumerClassFuelEUMaritime: - Warning("Fuel consumer type for COGAS is not defined in FuelEU Maritime regulation yet.") + Warning( + "Fuel consumer type for COGAS is not defined in FuelEU Maritime regulation yet." + ) return None - - def emissions_g_per_kwh(self, emission_type: EmissionType, load_ratio: T) -> Optional[T]: + + def emissions_g_per_kwh( + self, emission_type: EmissionType, load_ratio: T + ) -> Optional[T]: if emission_type in self._emissions_per_kwh_interp: return self._emissions_per_kwh_interp[emission_type](load_ratio) else: @@ -535,24 +559,30 @@ def _setup_nox( @property def power_output_gas_turbine(self): """Power output of the gas turbine in kW""" - return self.power_ratio_gas_turbine_interpolator(self.power_output / self.rated_power) - + return self.power_ratio_gas_turbine_interpolator( + self.power_output / self.rated_power + ) + @property def power_output_steam_turbine(self): """Power output of the steam turbine in kW""" return self.power_output - self.power_output_gas_turbine - + def get_gas_turbine_run_point_from_power_output_kw( self, power_kw: np.ndarray = None, fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, - ghg_emission_factor_tank_to_wake: List[Optional[GhgEmissionFactorTankToWake]] = None, + ghg_emission_factor_tank_to_wake: List[ + Optional[GhgEmissionFactorTankToWake] + ] = None, ) -> ComponentRunPoint: # GHG factors for FuelEU Maritime is not available for COGAS yet. It should raise an error if the user tries to use it. if fuel_specified_by == FuelSpecifiedBy.FUEL_EU_MARITIME: - raise ValueError("GHG factors for FuelEU Maritime is not available for COGAS yet.") + raise ValueError( + "GHG factors for FuelEU Maritime is not available for COGAS yet." + ) if power_kw is None: power_kw = self.power_output load_ratio = self.get_load(power_kw) @@ -563,20 +593,23 @@ def get_gas_turbine_run_point_from_power_output_kw( fuel_specified_by=fuel_specified_by, lhv_mj_per_g=lhv_mj_per_g, ghg_emission_factor_tank_to_wake=ghg_emission_factor_tank_to_wake, - ghg_emission_factor_well_to_tank_gco2eq_per_mj=ghg_emission_factor_well_to_tank_gco2eq_per_mj + ghg_emission_factor_well_to_tank_gco2eq_per_mj=ghg_emission_factor_well_to_tank_gco2eq_per_mj, ) fuel_power_kw = power_kw / eff - fuel_consumption_kg_per_s = fuel_power_kw / (fuel.lhv_mj_per_g * 1000) / 1000 + fuel_consumption_kg_per_s = fuel_power_kw / (fuel.lhv_mj_per_g * 1000) / 1000 fuel.mass_or_mass_fraction = fuel_consumption_kg_per_s emissionn_per_s = {} power_kwh_per_s = power_kw / 3600 for e in self._emissions_per_kwh_interp: - emissionn_per_s[e] = self.emissions_g_per_kwh(emission_type=e, load_ratio=load_ratio) * power_kwh_per_s + emissionn_per_s[e] = ( + self.emissions_g_per_kwh(emission_type=e, load_ratio=load_ratio) + * power_kwh_per_s + ) return ComponentRunPoint( load_ratio=load_ratio, fuel_flow_rate_kg_per_s=FuelConsumption(fuels=[fuel]), efficiency=eff, - emissions_g_per_s=emissionn_per_s + emissions_g_per_s=emissionn_per_s, ) diff --git a/feems/feems/components_model/node.py b/feems/feems/components_model/node.py index 6191290..dbe8a45 100644 --- a/feems/feems/components_model/node.py +++ b/feems/feems/components_model/node.py @@ -126,10 +126,14 @@ def get_fuel_emission_energy_balance_for_component( energy_stored_total_mj=0, ) running_hours = ( - (np.atleast_1d(component.power_output)[0] != 0) * np.atleast_1d(time_interval_s)[0] / 3600 + (np.atleast_1d(component.power_output)[0] != 0) + * np.atleast_1d(time_interval_s)[0] + / 3600 ) if len(np.atleast_1d(component.power_output)) > 1: - running_hours = np.dot((component.power_output != 0), time_interval_s).sum() / 3600 + running_hours = ( + np.dot((component.power_output != 0), time_interval_s).sum() / 3600 + ) # Calculate fuel consumption for engines if component.type in [ TypeComponent.MAIN_ENGINE, @@ -144,8 +148,10 @@ def get_fuel_emission_energy_balance_for_component( time_interval_s=time_interval_s, integration_method=integration_method, ) - res.co2_emission_total_kg = res.multi_fuel_consumption_total_kg.get_total_co2_emissions( - fuel_consumer_class=component.fuel_consumer_type_fuel_eu_maritime + res.co2_emission_total_kg = ( + res.multi_fuel_consumption_total_kg.get_total_co2_emissions( + fuel_consumer_class=component.fuel_consumer_type_fuel_eu_maritime + ) ) set_emission( engine_out=engine_run_point, @@ -157,9 +163,11 @@ def get_fuel_emission_energy_balance_for_component( # Calculate fuel consumption for genset elif component.type == TypeComponent.GENSET: component = cast(Genset, component) - genset_run_point = component.get_fuel_cons_load_bsfc_from_power_out_generator_kw( - power=component.power_output, - fuel_specified_by=fuel_specified_by, + genset_run_point = ( + component.get_fuel_cons_load_bsfc_from_power_out_generator_kw( + power=component.power_output, + fuel_specified_by=fuel_specified_by, + ) ) res.multi_fuel_consumption_total_kg = integrate_multi_fuel_consumption( fuel_consumption_kg_per_s=genset_run_point.engine.fuel_flow_rate_kg_per_s, @@ -196,8 +204,10 @@ def get_fuel_emission_energy_balance_for_component( time_interval_s=time_interval_s, integration_method=integration_method, ) - res.co2_emission_total_kg = res.multi_fuel_consumption_total_kg.get_total_co2_emissions( - fuel_consumer_class=FuelConsumerClassFuelEUMaritime.FUEL_CELL, + res.co2_emission_total_kg = ( + res.multi_fuel_consumption_total_kg.get_total_co2_emissions( + fuel_consumer_class=FuelConsumerClassFuelEUMaritime.FUEL_CELL, + ) ) res.running_hours_fuel_cell_total_hr = running_hours @@ -274,7 +284,9 @@ def get_fuel_emission_energy_balance_for_component( #: Calculate electric energy input for shore power elif component.type == TypeComponent.SHORE_POWER: - component = cast(Union[ShorePowerConnection, ShorePowerConnectionSystem], component) + component = cast( + Union[ShorePowerConnection, ShorePowerConnectionSystem], component + ) res.energy_input_electric_total_mj = ( integrate_data( data_to_integrate=component.power_input, @@ -321,7 +333,11 @@ def get_fuel_emission_energy_balance_for_component( time_interval_s=time_interval_s, integration_method=integration_method, ) - res.co2_emission_total_kg = res.multi_fuel_consumption_total_kg.get_total_co2_emissions(component.cogas.fuel_consumer_type_fuel_eu_maritime) + res.co2_emission_total_kg = ( + res.multi_fuel_consumption_total_kg.get_total_co2_emissions( + component.cogas.fuel_consumer_type_fuel_eu_maritime + ) + ) if ( np.isscalar(coges_run_point.coges_load_ratio) @@ -330,10 +346,10 @@ def get_fuel_emission_energy_balance_for_component( res.load_ratio_genset = coges_run_point.coges_load_ratio set_emission( - engine_out=coges_run_point.cogas, - integration_method=integration_method, - result=res, - time_interval_s=time_interval_s + engine_out=coges_run_point.cogas, + integration_method=integration_method, + result=res, + time_interval_s=time_interval_s, ) res.running_hours_genset_total_hr = running_hours @@ -381,31 +397,44 @@ def __init__(self, name: str, idx: SwbId, components: Sequence[ElectricComponent #: Categorize the components by its power type for component in components: self.component_by_power_type[component.power_type.value].append(component) - self.name_component_by_power_type[component.power_type.value].append(component.name) + self.name_component_by_power_type[component.power_type.value].append( + component.name + ) #: Check if the names are duplicates in each category for i, name_list in enumerate(self.name_component_by_power_type): name_list_unique = list(set(name_list)) if len(name_list) != len(name_list_unique): raise NameError( "There are duplicates in the component name for {0} " - "category for the switchboard no. {1}".format(TypePower(i).name, self.id) + "category for the switchboard no. {1}".format( + TypePower(i).name, self.id + ) ) #: Rated power for the bus (summing all the rated power of the power sources) self.rated_power = sum( [ component.rated_power - for component in self.component_by_power_type[TypePower.POWER_SOURCE.value] + for component in self.component_by_power_type[ + TypePower.POWER_SOURCE.value + ] ] ) - self.no_power_sources = len(self.component_by_power_type[TypePower.POWER_SOURCE.value]) - self.no_consumers = len(self.component_by_power_type[TypePower.POWER_CONSUMER.value]) + self.no_power_sources = len( + self.component_by_power_type[TypePower.POWER_SOURCE.value] + ) + self.no_consumers = len( + self.component_by_power_type[TypePower.POWER_CONSUMER.value] + ) self.no_pti_pto = len(self.component_by_power_type[TypePower.PTI_PTO.value]) - self.no_energy_storage = len(self.component_by_power_type[TypePower.ENERGY_STORAGE.value]) + self.no_energy_storage = len( + self.component_by_power_type[TypePower.ENERGY_STORAGE.value] + ) def get_status_component_by_power_type(self, type_: TypePower) -> List[np.ndarray]: #: Check if the length of the values for different components are the same len_status = [ - len(component.status) for component in self.component_by_power_type[type_.value] + len(component.status) + for component in self.component_by_power_type[type_.value] ] if not len_status: return [False] @@ -416,9 +445,13 @@ def get_status_component_by_power_type(self, type_: TypePower) -> List[np.ndarra ) logger.error(err_msg) raise InputError(err_msg) - return [component.status for component in self.component_by_power_type[type_.value]] + return [ + component.status for component in self.component_by_power_type[type_.value] + ] - def get_load_sharing_mode_components_by_power_type(self, type_: TypePower) -> List[np.ndarray]: + def get_load_sharing_mode_components_by_power_type( + self, type_: TypePower + ) -> List[np.ndarray]: #: Check if the length of the values for different components are the same len_load_sharing = [ len(component.load_sharing_mode) @@ -434,18 +467,23 @@ def get_load_sharing_mode_components_by_power_type(self, type_: TypePower) -> Li logger.error(err_msg) raise InputError(err_msg) return [ - component.load_sharing_mode for component in self.component_by_power_type[type_.value] + component.load_sharing_mode + for component in self.component_by_power_type[type_.value] ] def get_power_rated_component_by_power_type(self, type_: TypePower) -> List[float]: return [ - power_source.rated_power for power_source in self.component_by_power_type[type_.value] + power_source.rated_power + for power_source in self.component_by_power_type[type_.value] ] - def get_power_avail_component_by_power_type(self, type_: TypePower) -> List[np.ndarray]: + def get_power_avail_component_by_power_type( + self, type_: TypePower + ) -> List[np.ndarray]: #: Check if the length of the values for different components are the same len_status = [ - len(component.status) for component in self.component_by_power_type[type_.value] + len(component.status) + for component in self.component_by_power_type[type_.value] ] if not len_status: return [] @@ -514,7 +552,9 @@ def _get_component_by_type_and_name( idx = self.name_component_by_power_type[power_type.value].index(name) return self.component_by_power_type[power_type.value][idx] except ValueError: - raise ValueError("The name does not match the components for the given type") + raise ValueError( + "The name does not match the components for the given type" + ) def set_power_load_component_from_power_input_by_type_and_name( self, name: str, power_type: TypePower, power_input: np.ndarray @@ -552,7 +592,9 @@ def set_power_load_component_from_power_output_by_type_and_name( else: return 0 - def set_status_components_by_power_type(self, type_: TypePower, status: np.ndarray) -> None: + def set_status_components_by_power_type( + self, type_: TypePower, status: np.ndarray + ) -> None: """ Set the status of all the power sources @@ -565,7 +607,9 @@ def set_status_components_by_power_type(self, type_: TypePower, status: np.ndarr raise ValueError("The status input should be a 2D matrix") elif status.shape[1] != no_components: if status.shape[0] == no_components: - raise ValueError("The dimension of the status input should be transposed") + raise ValueError( + "The dimension of the status input should be transposed" + ) else: raise ValueError( "The dimension of the status input does not match the number of power sources" @@ -573,7 +617,9 @@ def set_status_components_by_power_type(self, type_: TypePower, status: np.ndarr for i, component in enumerate(self.component_by_power_type[type_.value]): component.status = status[:, i] - def set_status_component_by_power_type_name(self, status: np.ndarray, name: str) -> int: + def set_status_component_by_power_type_name( + self, status: np.ndarray, name: str + ) -> int: """ Sets the status of the power source specified by the name :param status: 1d array of bool @@ -581,10 +627,16 @@ def set_status_component_by_power_type_name(self, status: np.ndarray, name: str) :return: 1 for success, 0 for error """ try: - index = self.name_component_by_power_type[TypePower.POWER_SOURCE.value].index(name) + index = self.name_component_by_power_type[ + TypePower.POWER_SOURCE.value + ].index(name) except ValueError: - raise ValueError("The name given for the power source is not found in the switchboard") - self.component_by_power_type[TypePower.POWER_SOURCE.value][index].status = status + raise ValueError( + "The name given for the power source is not found in the switchboard" + ) + self.component_by_power_type[TypePower.POWER_SOURCE.value][ + index + ].status = status return 1 def set_status_components_by_power_type_and_index( @@ -612,8 +664,14 @@ def set_load_sharing_mode_components_by_power_type( def get_sum_power_out_power_sources_asymmetric(self) -> np.ndarray: return ( - np.array(self.get_load_sharing_mode_components_by_power_type(TypePower.POWER_SOURCE)) - * np.array(self.get_power_avail_component_by_power_type(TypePower.POWER_SOURCE)) + np.array( + self.get_load_sharing_mode_components_by_power_type( + TypePower.POWER_SOURCE + ) + ) + * np.array( + self.get_power_avail_component_by_power_type(TypePower.POWER_SOURCE) + ) ).sum(axis=0) def get_sum_power_avail_for_power_sources_asymmetric_by_type( @@ -621,14 +679,18 @@ def get_sum_power_avail_for_power_sources_asymmetric_by_type( ) -> np.ndarray: return ( np.ceil( - np.absolute(np.array(self.get_load_sharing_mode_components_by_power_type(type_))) + np.absolute( + np.array(self.get_load_sharing_mode_components_by_power_type(type_)) + ) ) * np.array(self.get_power_avail_component_by_power_type(type_)) ).sum(axis=0) def get_sum_power_avail_for_power_sources_symmetric(self) -> np.ndarray: sum_power_avail_power_sources = ( - np.array(self.get_power_avail_component_by_power_type(TypePower.POWER_SOURCE)) + np.array( + self.get_power_avail_component_by_power_type(TypePower.POWER_SOURCE) + ) .sum(axis=0) .astype(float) ) @@ -638,18 +700,26 @@ def get_sum_power_avail_for_power_sources_symmetric(self) -> np.ndarray: .astype(float) ) sum_power_avail_energy_storage = ( - np.array(self.get_power_avail_component_by_power_type(TypePower.ENERGY_STORAGE)) + np.array( + self.get_power_avail_component_by_power_type(TypePower.ENERGY_STORAGE) + ) .sum(axis=0) .astype(float) ) sum_power_avail_power_source_asymm = ( - self.get_sum_power_avail_for_power_sources_asymmetric_by_type(TypePower.POWER_SOURCE) + self.get_sum_power_avail_for_power_sources_asymmetric_by_type( + TypePower.POWER_SOURCE + ) ) sum_power_avail_pti_pto_asymm = ( - self.get_sum_power_avail_for_power_sources_asymmetric_by_type(TypePower.PTI_PTO) + self.get_sum_power_avail_for_power_sources_asymmetric_by_type( + TypePower.PTI_PTO + ) ) sum_power_avail_energy_storage_asymm = ( - self.get_sum_power_avail_for_power_sources_asymmetric_by_type(TypePower.ENERGY_STORAGE) + self.get_sum_power_avail_for_power_sources_asymmetric_by_type( + TypePower.ENERGY_STORAGE + ) ) return np.round( sum_power_avail_power_sources @@ -666,11 +736,15 @@ def get_sum_load_kw_sources_symmetric(self) -> Numeric: Calculate the sum of power loads on the power sources in a symmetric load sharing mode :return: sum of the power loads """ - sum_power_consumption = self.get_sum_power_input_by_power_type(TypePower.POWER_CONSUMER) + sum_power_consumption = self.get_sum_power_input_by_power_type( + TypePower.POWER_CONSUMER + ) sum_power_pti_pto = self.get_sum_power_input_by_power_type(TypePower.PTI_PTO) if sum_power_pti_pto.size == 0: sum_power_pti_pto = 0 - sum_power_energy_storage = self.get_sum_power_input_by_power_type(TypePower.ENERGY_STORAGE) + sum_power_energy_storage = self.get_sum_power_input_by_power_type( + TypePower.ENERGY_STORAGE + ) if sum_power_energy_storage.size == 0: sum_power_energy_storage = 0 sum_power_power_source_asymm = self.get_sum_power_out_power_sources_asymmetric() @@ -692,7 +766,8 @@ def get_sum_power_output_by_power_type(self, type_: TypePower) -> np.ndarray: """ #: Check if the length of the values for different components are the same len_power_values = [ - len(component.power_output) for component in self.component_by_power_type[type_.value] + len(component.power_output) + for component in self.component_by_power_type[type_.value] ] if not len_power_values: return np.zeros(1) @@ -771,7 +846,9 @@ def set_power_out_power_sources( ( component.power_output, load_perc, - ) = component.get_power_output_from_bidirectional_input(component.power_input) + ) = component.get_power_output_from_bidirectional_input( + component.power_input + ) def get_fuel_energy_consumption_running_time( self, @@ -856,7 +933,9 @@ def get_fuel_energy_consumption_running_time( res.detail_result = pd.concat( [ res.detail_result, - pd.Series(data_to_add, index=column_names, name=component.name).to_frame().T, + pd.Series(data_to_add, index=column_names, name=component.name) + .to_frame() + .T, ] ) @@ -866,7 +945,9 @@ def get_fuel_energy_consumption_running_time( f"'{self.name}' for fuel calculation" ) - if isinstance(component.power_input, float) and isinstance(component.power_output, float): + if isinstance(component.power_input, float) and isinstance( + component.power_output, float + ): n_steps = 1 else: n_steps = max(len(component.power_input), len(component.power_output)) @@ -922,7 +1003,9 @@ def get_fuel_energy_consumption_running_time_without_details( ) res = res.sum_with_freeze_duration(res_component) - def get_length(v: Union[float, int, List[float], np.ndarray, np.float64]) -> int: + def get_length( + v: Union[float, int, List[float], np.ndarray, np.float64] + ) -> int: if isinstance(v, float) or isinstance(v, int) or np.isscalar(v): return 1 elif isinstance(v, np.ndarray): @@ -930,7 +1013,9 @@ def get_length(v: Union[float, int, List[float], np.ndarray, np.float64]) -> int else: return len(v) - n_steps = max(get_length(component.power_input), get_length(component.power_output)) + n_steps = max( + get_length(component.power_input), get_length(component.power_output) + ) res.duration_s = get_duration_s(integration_method, n_steps, time_interval_s) return res @@ -985,7 +1070,9 @@ class ShaftLine(Node): class for main interface for the mechanical propulsion system. """ - def __init__(self, name: str, shaft_line_id: int, component_list: List[MechanicalComponent]): + def __init__( + self, name: str, shaft_line_id: int, component_list: List[MechanicalComponent] + ): super(ShaftLine, self).__init__(name, TypeNode.SHAFTLINE, component_list) self.id = shaft_line_id self.component_by_power_type: Dict[TypePower, List[MechanicalComponent]] = { @@ -998,20 +1085,28 @@ def __init__(self, name: str, shaft_line_id: int, component_list: List[Mechanica #: Categorize the components by its power type for component in component_list: self.component_by_power_type[component.power_type].append(component) - self.name_component_by_power_type[component.power_type].append(component.name) + self.name_component_by_power_type[component.power_type].append( + component.name + ) #: Check if the names are duplicates in each category for power_type, name_list in self.name_component_by_power_type.items(): name_list_unique = list(set(name_list)) if len(name_list) != len(name_list_unique): - msg = "There are duplicates in the component name for %s" "category for the %s" % ( - power_type, - self.name, + msg = ( + "There are duplicates in the component name for %s" + "category for the %s" + % ( + power_type, + self.name, + ) ) raise NameError(msg) #: Get the summary of the system - self.no_power_sources = len(self.component_by_power_type[TypePower.POWER_SOURCE]) + self.no_power_sources = len( + self.component_by_power_type[TypePower.POWER_SOURCE] + ) self.no_consumers = len(self.component_by_power_type[TypePower.POWER_CONSUMER]) self.no_pti_pto = len(self.component_by_power_type[TypePower.PTI_PTO]) @@ -1021,7 +1116,9 @@ def get_component_by_name_power_type( #: Find the component by the given name. If not found, log it as error and return 0 name_component_list = self.name_component_by_power_type[power_type] try: - return self.component_by_power_type[power_type][name_component_list.index(name)] + return self.component_by_power_type[power_type][ + name_component_list.index(name) + ] except ValueError: raise ValueError( "The given name is not found among the power consumer components in the %s." @@ -1038,18 +1135,24 @@ def set_power_input_load_by_name( :return: 1 for success 0 for error """ #: Get the load component from the name - component = self.get_component_by_name_power_type(name, TypePower.POWER_CONSUMER) + component = self.get_component_by_name_power_type( + name, TypePower.POWER_CONSUMER + ) #: Set the power_input if component is not None: component.power_input = ( - np.array([power_input]) if type(component.power_input) is float else power_input + np.array([power_input]) + if type(component.power_input) is float + else power_input ) return 1 else: return 0 - def set_status_main_engine_by_name(self, name: str, status: Union[bool, np.ndarray]) -> int: + def set_status_main_engine_by_name( + self, name: str, status: Union[bool, np.ndarray] + ) -> int: """ Sets the status of main engine (0: off, 1: on) of the given name :param name: name of the main engine as in the component instance @@ -1061,7 +1164,9 @@ def set_status_main_engine_by_name(self, name: str, status: Union[bool, np.ndarr #: Set the status of the main engine if component is not None: - component.status = np.array([status]) if type(component.status) is bool else status + component.status = ( + np.array([status]) if type(component.status) is bool else status + ) return 1 else: return 0 @@ -1088,7 +1193,9 @@ def set_power_output_pti_pto( #: Set the power output if isinstance(pti_pto, PTIPTO): pti_pto.power_output = ( - np.array([power_output]) if type(power_output) is float else power_output + np.array([power_output]) + if type(power_output) is float + else power_output ) ( pti_pto.power_input, @@ -1165,7 +1272,9 @@ def do_power_balance(self) -> Tuple[np.ndarray, np.ndarray]: else: #: For full PTI mode, PTI covers all the load. Set the power input accordingly power_output_pti_pto = pti_pto.power_output - power_output_pti_pto[pti_pto.full_pti_mode] = total_power_load[pti_pto.full_pti_mode] + power_output_pti_pto[pti_pto.full_pti_mode] = total_power_load[ + pti_pto.full_pti_mode + ] pti_pto.set_power_input_from_output(power_output_pti_pto) #: Calculate the main engine power output @@ -1192,7 +1301,9 @@ def do_power_balance(self) -> Tuple[np.ndarray, np.ndarray]: # noinspection PyUnresolvedReferences load_perc = np.zeros(total_power_load.shape) is_power_available = total_power_avail > 0 - if np.bitwise_and(power_output_main_engine > 0, total_power_avail == 0).any(): + if np.bitwise_and( + power_output_main_engine > 0, total_power_avail == 0 + ).any(): logger.warning( "There are cases where the sum of power output of the main " "engines are greater than 0 when there is no available power." @@ -1219,7 +1330,9 @@ def do_power_balance(self) -> Tuple[np.ndarray, np.ndarray]: #: Set all the power output of the main engine for main_engine in self.component_by_power_type[TypePower.POWER_SOURCE]: - main_engine.power_output = main_engine.rated_power * load_perc * main_engine.status + main_engine.power_output = ( + main_engine.rated_power * load_perc * main_engine.status + ) #: Set the status false(off) if the power output is 0 main_engine.status[main_engine.power_output == 0] = False @@ -1317,7 +1430,9 @@ def get_fuel_calculation_running_hours( res.detail_result = pd.concat( [ res.detail_result, - pd.Series(data_to_add, index=column_names, name=component.name).to_frame().T, + pd.Series(data_to_add, index=column_names, name=component.name) + .to_frame() + .T, ] ) @@ -1327,7 +1442,9 @@ def get_fuel_calculation_running_hours( f"'{self.name}' for fuel calculation" ) - if isinstance(component.power_input, float) and isinstance(component.power_output, float): + if isinstance(component.power_input, float) and isinstance( + component.power_output, float + ): n_steps = 1 else: n_steps = max(len(component.power_input), len(component.power_output)) diff --git a/feems/feems/components_model/utility.py b/feems/feems/components_model/utility.py index 9083338..fed0c89 100644 --- a/feems/feems/components_model/utility.py +++ b/feems/feems/components_model/utility.py @@ -63,7 +63,10 @@ def integrate_data( time_interval_s_is_scalar_number = np.isscalar(time_interval_s) and isinstance( time_interval_s, (float, int) ) - if len(data_to_integrate) == 1 and integration_method != IntegrationMethod.sum_with_time: + if ( + len(data_to_integrate) == 1 + and integration_method != IntegrationMethod.sum_with_time + ): logger.warning( "The integration method is not 'sum_with_time' while the data to integrate " "has only one point. 'sum_with_time' will be used for integration to avoid " @@ -98,7 +101,10 @@ def integrate_data( result = result[0] return result else: - msg = "The given method (%s) for the integration is not valid" % integration_method + msg = ( + "The given method (%s) for the integration is not valid" + % integration_method + ) logging.error(msg) raise TypeError(msg) @@ -112,7 +118,10 @@ def integrate_multi_fuel_consumption( Integrates fuel consumption rate of each fuel component. """ fuel_consumption_kg = FuelConsumption( - fuels=[fuel.copy_except_mass_or_mass_fraction for fuel in fuel_consumption_kg_per_s.fuels] + fuels=[ + fuel.copy_except_mass_or_mass_fraction + for fuel in fuel_consumption_kg_per_s.fuels + ] ) for each_fuel_rate, each_fuel_mass in zip( fuel_consumption_kg_per_s.fuels, fuel_consumption_kg.fuels @@ -152,7 +161,10 @@ def integrate_data_accumulative( res = np.insert(res, 0, 0, axis=0) return res else: - msg = "The given method (%s) for the integration is not valid" % integration_method + msg = ( + "The given method (%s) for the integration is not valid" + % integration_method + ) logging.error(msg) raise TypeError(msg) @@ -215,7 +227,9 @@ def get_efficiency_curve_from_dataframe( curve_points = np.ravel(df[eff_columns].values) else: for i, eff_column in enumerate(eff_columns): - curve_points[i, 0] = float(eff_column[eff_column.find("@") + 1 : eff_column.find("%")]) + curve_points[i, 0] = float( + eff_column[eff_column.find("@") + 1 : eff_column.find("%")] + ) curve_points[i, 1] = df[eff_column].values[0] curve_points = curve_points[curve_points[:, 0].argsort()] return get_efficiency_curve_from_points(curve_points) diff --git a/feems/feems/fuel.py b/feems/feems/fuel.py index b4e8020..dcc86f1 100644 --- a/feems/feems/fuel.py +++ b/feems/feems/fuel.py @@ -171,7 +171,9 @@ def __init__( fuel_specified_by: FuelSpecifiedBy = FuelSpecifiedBy.IMO, lhv_mj_per_g: Optional[float] = None, ghg_emission_factor_well_to_tank_gco2eq_per_mj: Optional[float] = None, - ghg_emission_factor_tank_to_wake: Optional[List[GhgEmissionFactorTankToWake]] = None, + ghg_emission_factor_tank_to_wake: Optional[ + List[GhgEmissionFactorTankToWake] + ] = None, mass_or_mass_fraction: Union[np.array, float] = 0.0, ): """Constructor for FuelSpecifications class @@ -221,10 +223,14 @@ def __init__( elif fuel_specified_by == FuelSpecifiedBy.IMO: self._get_factors_for_imo() elif fuel_specified_by == FuelSpecifiedBy.USER: - self.ghg_emission_factor_well_to_tank = ghg_emission_factor_well_to_tank_gco2eq_per_mj + self.ghg_emission_factor_well_to_tank = ( + ghg_emission_factor_well_to_tank_gco2eq_per_mj + ) self.ghg_emission_factor_tank_to_wake = ghg_emission_factor_tank_to_wake else: - raise NotImplementedError(f"Fuel specified by {fuel_specified_by} is not implemented.") + raise NotImplementedError( + f"Fuel specified by {fuel_specified_by} is not implemented." + ) def __str__(self): return f"{self.fuel_type.name.lower()}_{self.origin.name.lower()}" @@ -247,7 +253,9 @@ def copy(self) -> "Fuel": else None ), ghg_emission_factor_tank_to_wake=( - self.ghg_emission_factor_tank_to_wake if fuel_specified_by_user else None + self.ghg_emission_factor_tank_to_wake + if fuel_specified_by_user + else None ), mass_or_mass_fraction=self.mass_or_mass_fraction, ) @@ -277,7 +285,9 @@ def get_ghg_emission_factor_tank_to_wake_gco2eq_per_gfuel( float: GHG emission factor from tank to wake in gCO2eq/gfuel """ if self.fuel_specified_by == FuelSpecifiedBy.IMO: - return self.ghg_emission_factor_tank_to_wake[0].ghg_emission_factor_gco2eq_per_gfuel + return self.ghg_emission_factor_tank_to_wake[ + 0 + ].ghg_emission_factor_gco2eq_per_gfuel return next( filter( lambda x: x.fuel_consumer_class == fuel_consumer_class, @@ -322,7 +332,9 @@ def get_prescribed_factors( f"pathway_name == '{fuel_type_eu}' and fuel_class == '{fuel_class}'" ) if len(fuel_data) == 0: - raise ValueError(f"The fuel type {fuel_type} and origin {origin} is not available.") + raise ValueError( + f"The fuel type {fuel_type} and origin {origin} is not available." + ) lhv_mj_per_g = fuel_data["LCV"].values[0] ghg_emission_factor_well_to_tank_gco2eq_per_mj = fuel_data["CO2_WtT"].values[0] @@ -353,7 +365,9 @@ def __post_init__(self): if len(self.fuels) > 0: total_fraction = sum([fuel.mass_or_mass_fraction for fuel in self.fuels]) total_fraction = np.atleast_1d(total_fraction) - assert np.allclose(total_fraction, 1.0, atol=1e-3), "The mass fraction must sum to 1." + assert np.allclose( + total_fraction, 1.0, atol=1e-3 + ), "The mass fraction must sum to 1." assert self.fuel_specified_by is not None @property @@ -373,7 +387,9 @@ def fuel_specified_by(self) -> FuelSpecifiedBy: elif FuelSpecifiedBy.USER in fuel_specified_by_list: return FuelSpecifiedBy.USER else: - raise ValueError("The fuel is not specified by any of the available options.") + raise ValueError( + "The fuel is not specified by any of the available options." + ) else: return self.fuels[0].fuel_specified_by else: @@ -384,7 +400,10 @@ def lhv_mj_per_kg(self): """ Returns the low heat value of fuel based on fuel mass fraction """ - return sum([fuel.lhv_mj_per_g * fuel.mass_or_mass_fraction for fuel in self.fuels]) * 1000 + return ( + sum([fuel.lhv_mj_per_g * fuel.mass_or_mass_fraction for fuel in self.fuels]) + * 1000 + ) def get_kg_co2_per_kg_fuel( self, fuel_consumer_class: Optional[FuelConsumerClassFuelEUMaritime] = None @@ -410,7 +429,9 @@ def get_kg_co2_per_kg_fuel( ): pass else: - raise ValueError("The fuel is not specified by properly for this calculation.") + raise ValueError( + "The fuel is not specified by properly for this calculation." + ) res = 0 for fuel in self.fuels: # If the fuel contains other fuel than LNG and the consumer is a gas engine, @@ -455,7 +476,9 @@ def get_kg_co2_per_kwh_fuel( def get_kg_co2_per_mj_fuel( self, fuel_consumer_class: FuelConsumerClassFuelEUMaritime = None ) -> float: - return self.get_kg_co2_per_kwh_fuel(fuel_consumer_class=fuel_consumer_class) / 3.6 + return ( + self.get_kg_co2_per_kwh_fuel(fuel_consumer_class=fuel_consumer_class) / 3.6 + ) @dataclass @@ -555,12 +578,16 @@ def fuel_by_mass_fraction(self) -> FuelByMassFraction: else: for fuel in self.fuels: fuel_fraction_to_add = fuel.copy - fuel_fraction_to_add.mass_or_mass_fraction /= self.total_fuel_consumption + fuel_fraction_to_add.mass_or_mass_fraction /= ( + self.total_fuel_consumption + ) fuel_by_mass_fraction.fuels.append(fuel_fraction_to_add) else: for fuel in self.fuels: fuel_fraction_new = fuel.copy - fuel_fraction_new.mass_or_mass_fraction[~index_fuel_consumption_zero] = ( + fuel_fraction_new.mass_or_mass_fraction[ + ~index_fuel_consumption_zero + ] = ( fuel.mass_or_mass_fraction[~index_fuel_consumption_zero] / self.total_fuel_consumption[~index_fuel_consumption_zero] ) @@ -584,6 +611,9 @@ def get_total_co2_emissions( Returns: total co2 emission: Total CO2 emissions in kg or kg/s depending on the context. """ - return self.total_fuel_consumption * self.fuel_by_mass_fraction.get_kg_co2_per_kg_fuel( - fuel_consumer_class=fuel_consumer_class + return ( + self.total_fuel_consumption + * self.fuel_by_mass_fraction.get_kg_co2_per_kg_fuel( + fuel_consumer_class=fuel_consumer_class + ) ) diff --git a/feems/feems/runsimulation.py b/feems/feems/runsimulation.py index a74ac3b..832d98d 100644 --- a/feems/feems/runsimulation.py +++ b/feems/feems/runsimulation.py @@ -25,7 +25,9 @@ def run_simulation( simulation_interface: SimulationInterface, energy_source_to_prioritize: EnergySourceType = None, ) -> None: - power_kw_per_switchboard = electric_power_system.get_sum_consumption_kw_sources_switchboard() + power_kw_per_switchboard = ( + electric_power_system.get_sum_consumption_kw_sources_switchboard() + ) simulation_interface.set_status( power_kw_per_switchboard=power_kw_per_switchboard, @@ -49,7 +51,9 @@ def __init__( self.n_gensets = sum([x for x in swb2n_gensets.values()]) self.n_bus_ties = n_bus_ties self.rated_power_gensets = rated_power_gensets - self.maximum_allowable_genset_load_percentage = maximum_allowable_genset_load_percentage + self.maximum_allowable_genset_load_percentage = ( + maximum_allowable_genset_load_percentage + ) def set_status( self, @@ -82,14 +86,20 @@ def set_status( def _make_genset_on_matrix( self, power_kw_per_switchboard: Dict[SwbId, np.ndarray], n_datapoints: int ) -> Dict[SwbId, np.ndarray]: - total_power_kw = self._sum_switchboard_power(n_datapoints, power_kw_per_switchboard) - ideal_number_genset = self._ideal_number_of_gensets_on(n_datapoints, total_power_kw) + total_power_kw = self._sum_switchboard_power( + n_datapoints, power_kw_per_switchboard + ) + ideal_number_genset = self._ideal_number_of_gensets_on( + n_datapoints, total_power_kw + ) return self._convert_number_of_engines_on_to_status_matrix( ideal_number_genset=ideal_number_genset, n_datapoints=n_datapoints ) @staticmethod - def _sum_switchboard_power(n_datapoints: int, power_kw_per_switchboard: dict) -> np.ndarray: + def _sum_switchboard_power( + n_datapoints: int, power_kw_per_switchboard: dict + ) -> np.ndarray: #: Calculate the total power load on all switchboards total_power_kw = np.zeros(shape=[n_datapoints]) for power_kw_on_swb in power_kw_per_switchboard.values(): diff --git a/feems/feems/simulation_interface.py b/feems/feems/simulation_interface.py index b43cdb3..89a5354 100644 --- a/feems/feems/simulation_interface.py +++ b/feems/feems/simulation_interface.py @@ -41,7 +41,9 @@ def set_remaining_capacity_from_feems_result( remaining capacity, returns the ratio of energy exceeding capacity to energy required and updated feems result. """ - co2_factor = feems_result.co2_emission_total_kg / feems_result.fuel_consumption_total_kg + co2_factor = ( + feems_result.co2_emission_total_kg / feems_result.fuel_consumption_total_kg + ) energy_exceeding_capacity = 0 if self.source_type == EnergySourceType.BATTERY: energy_consumption = -feems_result.energy_stored_total_mj / 3.6 @@ -51,19 +53,26 @@ def set_remaining_capacity_from_feems_result( energy_consumption = feems_result.fuel_consumption_total_kg else: raise TypeError( - "The energy source type is not valid. It should be " "EnergySourceType enum type." + "The energy source type is not valid. It should be " + "EnergySourceType enum type." ) - energy_consumption_actual = (1 - ratio_energy_used_in_previous_source) * energy_consumption + energy_consumption_actual = ( + 1 - ratio_energy_used_in_previous_source + ) * energy_consumption self.remaining_capacity -= energy_consumption_actual if self.remaining_capacity <= 0 and not is_last_energy_source: energy_exceeding_capacity = -self.remaining_capacity # type: ignore[assignment] self.remaining_capacity = 0 if self.source_type == EnergySourceType.BATTERY: - actual_energy_stored = -energy_consumption_actual + energy_exceeding_capacity + actual_energy_stored = ( + -energy_consumption_actual + energy_exceeding_capacity + ) feems_result.energy_stored_total_mj = actual_energy_stored * 3.6 feems_result.energy_consumption_electric_total_mj *= ( - (actual_energy_stored / energy_consumption) if energy_consumption != 0 else 0 + (actual_energy_stored / energy_consumption) + if energy_consumption != 0 + else 0 ) elif self.source_type == EnergySourceType.HYDROGEN: fuel = next( @@ -72,7 +81,9 @@ def set_remaining_capacity_from_feems_result( feems_result.multi_fuel_consumption_total_kg.fuels, ) ) - fuel.mass_or_mass_fraction = energy_consumption_actual - energy_exceeding_capacity + fuel.mass_or_mass_fraction = ( + energy_consumption_actual - energy_exceeding_capacity + ) elif self.source_type == EnergySourceType.LNG_DIESEL: if feems_result.multi_fuel_consumption_total_kg.diesel > 0: fuel = next( @@ -81,7 +92,9 @@ def set_remaining_capacity_from_feems_result( feems_result.multi_fuel_consumption_total_kg.fuels, ) ) - fuel.mass_or_mass_fraction = energy_consumption_actual - energy_exceeding_capacity + fuel.mass_or_mass_fraction = ( + energy_consumption_actual - energy_exceeding_capacity + ) feems_result.co2_emission_total_kg = ( energy_consumption_actual - energy_exceeding_capacity ) * co2_factor @@ -92,7 +105,9 @@ def set_remaining_capacity_from_feems_result( feems_result.multi_fuel_consumption_total_kg.fuels, ) ) - fuel.mass_or_mass_fraction = energy_consumption_actual - energy_exceeding_capacity + fuel.mass_or_mass_fraction = ( + energy_consumption_actual - energy_exceeding_capacity + ) feems_result.co2_emission_total_kg = ( energy_consumption_actual - energy_exceeding_capacity ) * co2_factor diff --git a/feems/feems/system_model.py b/feems/feems/system_model.py index 81e77dd..d604d53 100644 --- a/feems/feems/system_model.py +++ b/feems/feems/system_model.py @@ -89,7 +89,9 @@ def __init__( self.power_sources: List[ Union[ElectricComponent, Genset, SerialSystemElectric, ElectricMachine] ] = [] - self.propulsion_drives: List[Union[ElectricComponent, SerialSystemElectric]] = [] + self.propulsion_drives: List[Union[ElectricComponent, SerialSystemElectric]] = ( + [] + ) self.pti_pto: List[PTIPTO] = [] self.energy_storage: List[EnergyStorageComponent] = [] self.other_load: List[Union[ElectricComponent, SerialSystemElectric]] = [] @@ -102,7 +104,9 @@ def __init__( #: Categorize the components for component in power_plant_components: if component.power_type == TypePower.POWER_SOURCE: - if isinstance(component, (ElectricMachine, Genset, FuelCellSystem, COGES)): + if isinstance( + component, (ElectricMachine, Genset, FuelCellSystem, COGES) + ): self.power_sources.append(component) power_source2switchboard.append(component.switchboard_id) component2switchboard.append(component.switchboard_id) @@ -147,14 +151,22 @@ def __init__( ) component2switchboard.append(component.switchboard_id) else: - raise TypeError(f"Component - {component.name} - does have a proper type.") + raise TypeError( + f"Component - {component.name} - does have a proper type." + ) #: Create a list of Switchboard objects based on the switchboard information given - switchboard_id_from_power_sources = list(dict.fromkeys(power_source2switchboard).keys()) - switchboard_id_from_energy_storage = list(dict.fromkeys(energy_storage2switchboard).keys()) + switchboard_id_from_power_sources = list( + dict.fromkeys(power_source2switchboard).keys() + ) + switchboard_id_from_energy_storage = list( + dict.fromkeys(energy_storage2switchboard).keys() + ) switchboard_id_from_power_sources.sort() switchboard_id_from_energy_storage.sort() - self.switchboard_id: List[SwbId] = list(dict.fromkeys(component2switchboard).keys()) + self.switchboard_id: List[SwbId] = list( + dict.fromkeys(component2switchboard).keys() + ) self.switchboard_id.sort() for swb_id in self.switchboard_id: if ( @@ -223,7 +235,9 @@ def set_load_sharing_mode_power_sources_by_switchboard_id_power_type( power_type: TypePower, load_sharing_mode: np.ndarray, ) -> None: - self.switchboards[switchboard_id].set_load_sharing_mode_components_by_power_type( + self.switchboards[ + switchboard_id + ].set_load_sharing_mode_components_by_power_type( type_=power_type, load_sharing_mode=load_sharing_mode ) @@ -380,10 +394,14 @@ def get_sum_power_out_rated_buses_by_power_type( ).sum() sum_power_out_rated_bus = {} for index, _ in enumerate(self.switchboards): - sum_power_out_rated_bus[BusId(index + 1)] = np.zeros(self.no_bus_configuration_change) + sum_power_out_rated_bus[BusId(index + 1)] = np.zeros( + self.no_bus_configuration_change + ) for i, switchboard2bus in enumerate(self.switchboard2bus): for swb_id, bus_id in switchboard2bus.items(): - sum_power_out_rated_bus[bus_id][i] += sum_power_out_rated_switchboards[swb_id] + sum_power_out_rated_bus[bus_id][i] += sum_power_out_rated_switchboards[ + swb_id + ] return sum_power_out_rated_bus def _get_sum_buses( @@ -423,13 +441,13 @@ def _get_sum_buses( TypeValueBus.LOAD_KW_SOURCES, TypeValueBus.POWER_AVAIL_POWER_SOURCES_SYMMETRIC, ] - is_component_of_power_type = self.switchboards[swb_id].component_by_power_type[ - power_type.value - ] + is_component_of_power_type = self.switchboards[ + swb_id + ].component_by_power_type[power_type.value] if is_which_value_load_or_power_avail or is_component_of_power_type: - sum_buses[bus_id][index_start:index_end] += sum_switchboards[swb_id][ - index_start:index_end - ] + sum_buses[bus_id][index_start:index_end] += sum_switchboards[ + swb_id + ][index_start:index_end] return sum_buses @@ -455,9 +473,13 @@ def _get_sum_switchboard( else: if switchboard.component_by_power_type[power_type.value]: if which_value == TypeValueBus.POWER_IN_BY_POWER_TYPE: - sum_temp = switchboard.get_sum_power_input_by_power_type(power_type) + sum_temp = switchboard.get_sum_power_input_by_power_type( + power_type + ) elif which_value == TypeValueBus.POWER_OUT_BY_POWER_TYPE: - sum_temp = switchboard.get_sum_power_output_by_power_type(power_type) + sum_temp = switchboard.get_sum_power_output_by_power_type( + power_type + ) else: raise TypeError("The value name specified is not valid") if sum_temp is not None: @@ -485,22 +507,32 @@ def _get_sum_switchboard( return sum_switchboards - def get_sum_power_in_buses_by_power_type(self, type_: TypePower) -> Dict[BusId, np.ndarray]: - return self._get_sum_buses(TypeValueBus.POWER_IN_BY_POWER_TYPE, power_type=type_) + def get_sum_power_in_buses_by_power_type( + self, type_: TypePower + ) -> Dict[BusId, np.ndarray]: + return self._get_sum_buses( + TypeValueBus.POWER_IN_BY_POWER_TYPE, power_type=type_ + ) def get_sum_power_output_buses_by_power_type( self, type_: TypePower ) -> Dict[BusId, np.ndarray]: - return self._get_sum_buses(TypeValueBus.POWER_OUT_BY_POWER_TYPE, power_type=type_) + return self._get_sum_buses( + TypeValueBus.POWER_OUT_BY_POWER_TYPE, power_type=type_ + ) def get_sum_load_kw_sources_symmetric_buses(self) -> Dict[BusId, np.ndarray]: - return self._get_sum_buses(TypeValueBus.LOAD_KW_SOURCES, power_type=TypePower.POWER_SOURCE) + return self._get_sum_buses( + TypeValueBus.LOAD_KW_SOURCES, power_type=TypePower.POWER_SOURCE + ) def get_sum_consumption_kw_sources_switchboard(self) -> Dict[SwbId, np.ndarray]: sum_switchboards: Dict[SwbId, np.ndarray] = {} len_sum = set() for swb_id, switchboard in self.switchboards.items(): - sum_temp = switchboard.get_sum_power_input_by_power_type(TypePower.POWER_CONSUMER) + sum_temp = switchboard.get_sum_power_input_by_power_type( + TypePower.POWER_CONSUMER + ) sum_switchboards[swb_id] = sum_temp len_sum.add(len(sum_temp)) @@ -541,8 +573,10 @@ def validate_inputs_before_power_balance_calculation(self) -> None: raise InputError(msg) for swb_id, swb in self.switchboards.items(): - load_sharing_mode_energy_storage = swb.get_load_sharing_mode_components_by_power_type( - TypePower.ENERGY_STORAGE + load_sharing_mode_energy_storage = ( + swb.get_load_sharing_mode_components_by_power_type( + TypePower.ENERGY_STORAGE + ) ) if load_sharing_mode_energy_storage: if number_points != load_sharing_mode_energy_storage[0].size: @@ -554,15 +588,21 @@ def validate_inputs_before_power_balance_calculation(self) -> None: logger.error(msg) raise InputError(msg) - for i, load_sharing_mode_each in enumerate(load_sharing_mode_energy_storage): + for i, load_sharing_mode_each in enumerate( + load_sharing_mode_energy_storage + ): if load_sharing_mode_each.sum() == 0: swb.set_power_load_component_from_power_input_by_type_and_name( - name=swb.name_component_by_power_type[TypePower.ENERGY_STORAGE.value][i], + name=swb.name_component_by_power_type[ + TypePower.ENERGY_STORAGE.value + ][i], power_type=TypePower.ENERGY_STORAGE, power_input=np.zeros(number_points), ) else: - component = swb.component_by_power_type[TypePower.ENERGY_STORAGE.value][i] + component = swb.component_by_power_type[ + TypePower.ENERGY_STORAGE.value + ][i] if component.power_input.size != number_points: msg = ( f"The dimension of the power input of the energy storage " @@ -572,8 +612,8 @@ def validate_inputs_before_power_balance_calculation(self) -> None: logger.error(msg) raise InputError(msg) - load_sharing_mode_pti_pto = swb.get_load_sharing_mode_components_by_power_type( - TypePower.PTI_PTO + load_sharing_mode_pti_pto = ( + swb.get_load_sharing_mode_components_by_power_type(TypePower.PTI_PTO) ) if load_sharing_mode_pti_pto: if number_points != load_sharing_mode_pti_pto[0].size: @@ -587,7 +627,9 @@ def validate_inputs_before_power_balance_calculation(self) -> None: for i, load_sharing_mode_each in enumerate(load_sharing_mode_pti_pto): if load_sharing_mode_each.sum() == 0: swb.set_power_load_component_from_power_input_by_type_and_name( - name=swb.name_component_by_power_type[TypePower.PTI_PTO.value][i], + name=swb.name_component_by_power_type[TypePower.PTI_PTO.value][ + i + ], power_type=TypePower.PTI_PTO, power_input=np.zeros(number_points), ) @@ -609,7 +651,9 @@ def do_power_balance_calculation(self) -> None: """ self.validate_inputs_before_power_balance_calculation() - sum_load_kw_sources_symmetric_buses = self.get_sum_load_kw_sources_symmetric_buses() + sum_load_kw_sources_symmetric_buses = ( + self.get_sum_load_kw_sources_symmetric_buses() + ) sum_power_avail_power_sources_symmetric_buses = ( self.get_sum_power_avail_power_sources_symmetric_buses() ) @@ -639,10 +683,12 @@ def do_power_balance_calculation(self) -> None: else no_points ) bus_id = switchboard2bus[switchboard.id] - load_switchboard_symmetric_power_source[index_start:index_end] = load_buses[ - bus_id - ][index_start:index_end] - switchboard.set_power_out_power_sources(load_switchboard_symmetric_power_source) + load_switchboard_symmetric_power_source[index_start:index_end] = ( + load_buses[bus_id][index_start:index_end] + ) + switchboard.set_power_out_power_sources( + load_switchboard_symmetric_power_source + ) # noinspection DuplicatedCode def get_fuel_energy_consumption_running_time( @@ -663,7 +709,10 @@ def get_fuel_energy_consumption_running_time( Returns: FEEMSResult """ - if fuel_specified_by not in [FuelSpecifiedBy.IMO, FuelSpecifiedBy.FUEL_EU_MARITIME]: + if fuel_specified_by not in [ + FuelSpecifiedBy.IMO, + FuelSpecifiedBy.FUEL_EU_MARITIME, + ]: raise NotImplementedError( f"Fuel specified by {fuel_specified_by.name} is not implemented" ) @@ -672,10 +721,12 @@ def get_fuel_energy_consumption_running_time( logger.warning("There is no switchboard in the system") return FEEMSResult(duration_s=0) for _, switchboard in self.switchboards.items(): - result_swb: FEEMSResult = switchboard.get_fuel_energy_consumption_running_time( - time_interval_s=self.time_interval_s, - integration_method=self.integration_method, - fuel_specified_by=fuel_specified_by, + result_swb: FEEMSResult = ( + switchboard.get_fuel_energy_consumption_running_time( + time_interval_s=self.time_interval_s, + integration_method=self.integration_method, + fuel_specified_by=fuel_specified_by, + ) ) result_swb.detail_result["switchboard id"] = switchboard.id res = res.sum_with_freeze_duration(result_swb) @@ -700,7 +751,10 @@ def get_fuel_energy_consumption_running_time_scalar( Returns: FEEMSResult """ - if fuel_specified_by not in [FuelSpecifiedBy.IMO, FuelSpecifiedBy.FUEL_EU_MARITIME]: + if fuel_specified_by not in [ + FuelSpecifiedBy.IMO, + FuelSpecifiedBy.FUEL_EU_MARITIME, + ]: raise NotImplementedError( f"Fuel specified by {fuel_specified_by.name} is not implemented" ) @@ -732,7 +786,10 @@ class MechanicalPropulsionSystem(MachinerySystem): name: str main_engines: List[ - Union[MainEngineForMechanicalPropulsion, MainEngineWithGearBoxForMechanicalPropulsion] + Union[ + MainEngineForMechanicalPropulsion, + MainEngineWithGearBoxForMechanicalPropulsion, + ] ] pti_ptos: List[PTIPTO] mechanical_loads: List[MechanicalComponent] @@ -754,7 +811,9 @@ def __init__(self, name: str, components_list: List[MechanicalComponent]): if component.shaft_line_id not in self.component_by_shaft_line_id.keys(): self.component_by_shaft_line_id[component.shaft_line_id] = [component] else: - self.component_by_shaft_line_id[component.shaft_line_id].append(component) + self.component_by_shaft_line_id[component.shaft_line_id].append( + component + ) if component.type in [ TypeComponent.MAIN_ENGINE, TypeComponent.MAIN_ENGINE_WITH_GEARBOX, @@ -799,7 +858,9 @@ def get_component_by_name_shaft_line_id_power_type( self, name: str, shaft_line_id: int, power_type: TypePower ) -> MechanicalComponent: index_shaft_line = self.shaft_line_id.index(shaft_line_id) - return self.shaft_line[index_shaft_line].get_component_by_name_power_type(name, power_type) + return self.shaft_line[index_shaft_line].get_component_by_name_power_type( + name, power_type + ) def set_power_consumer_load_by_value_for_given_name_shaft_line_id( self, name: str, shaft_line_id: int, power_input: np.ndarray @@ -976,7 +1037,8 @@ def validate_inputs_before_power_balance_calculation(self) -> bool: "for the mechanical loads or PTI/PTOs." ) err_msg = reduce( - lambda acc, component: acc + f"\n\t{component.name}: {component.power_input.size}", + lambda acc, component: acc + + f"\n\t{component.name}: {component.power_input.size}", components, err_msg, ) @@ -1024,7 +1086,9 @@ def validate_inputs_before_power_balance_calculation(self) -> bool: return False # Check the size of the full pti mode of the pti_ptos - number_points_full_pti = [pti_pto.full_pti_mode.size for pti_pto in self.pti_ptos] + number_points_full_pti = [ + pti_pto.full_pti_mode.size for pti_pto in self.pti_ptos + ] if len(set(number_points_full_pti)) > 1: err_msg = ( f"There are mismatches in the number of points of the full pti mode " @@ -1048,7 +1112,8 @@ def validate_inputs_before_power_balance_calculation(self) -> bool: f"inputs of consumers ({number_points})." ) err_msg = reduce( - lambda acc, comp: acc + f"\n\t{comp.name}: {comp.full_pti_mode.size}", + lambda acc, comp: acc + + f"\n\t{comp.name}: {comp.full_pti_mode.size}", self.pti_ptos, err_msg, ) @@ -1072,7 +1137,10 @@ def get_fuel_energy_consumption_running_time( Returns: FEEMSResult """ - if fuel_specified_by not in [FuelSpecifiedBy.IMO, FuelSpecifiedBy.FUEL_EU_MARITIME]: + if fuel_specified_by not in [ + FuelSpecifiedBy.IMO, + FuelSpecifiedBy.FUEL_EU_MARITIME, + ]: raise NotImplementedError( f"Fuel specified by {fuel_specified_by.name} is not implemented" ) @@ -1089,10 +1157,12 @@ def get_fuel_energy_consumption_running_time( logger.warning("There is no switchboard in the system") return FEEMSResult(duration_s=0) for shaft_line in self.shaft_line: - result_shaft_line: FEEMSResult = shaft_line.get_fuel_calculation_running_hours( - time_step=self.time_interval_s, - integration_method=self.integration_method, - fuel_specified_by=fuel_specified_by, + result_shaft_line: FEEMSResult = ( + shaft_line.get_fuel_calculation_running_hours( + time_step=self.time_interval_s, + integration_method=self.integration_method, + fuel_specified_by=fuel_specified_by, + ) ) result_shaft_line.detail_result["shaftline id"] = shaft_line.id res = res.sum_with_freeze_duration(result_shaft_line) @@ -1180,7 +1250,10 @@ def get_fuel_energy_consumption_running_time( Returns: FEEMSResultForMachinerySystem """ - if fuel_specified_by not in [FuelSpecifiedBy.IMO, FuelSpecifiedBy.FUEL_EU_MARITIME]: + if fuel_specified_by not in [ + FuelSpecifiedBy.IMO, + FuelSpecifiedBy.FUEL_EU_MARITIME, + ]: raise NotImplementedError( f"Fuel specified by {fuel_specified_by.name} is not implemented" ) @@ -1244,7 +1317,10 @@ def get_fuel_energy_consumption_running_time( Returns: Tuple of FEEMSResult for mechanical system and electric system, respectively """ - if fuel_specified_by not in [FuelSpecifiedBy.IMO, FuelSpecifiedBy.FUEL_EU_MARITIME]: + if fuel_specified_by not in [ + FuelSpecifiedBy.IMO, + FuelSpecifiedBy.FUEL_EU_MARITIME, + ]: raise NotImplementedError( f"Fuel specified by {fuel_specified_by.name} is not implemented" ) diff --git a/feems/feems/types_for_feems.py b/feems/feems/types_for_feems.py index c0d7c5c..583ed06 100644 --- a/feems/feems/types_for_feems.py +++ b/feems/feems/types_for_feems.py @@ -45,13 +45,17 @@ class FEEMSResult: running_hours_pti_pto_total_hr: float = 0.0 total_emission_kg: Optional[DefaultDict[EmissionType, float]] = None detail_result: Optional[pd.DataFrame] = None - multi_fuel_consumption_total_kg: FuelConsumption = field(default_factory=FuelConsumption) + multi_fuel_consumption_total_kg: FuelConsumption = field( + default_factory=FuelConsumption + ) co2_emission_total_kg: float = 0.0 energy_input_mechanical_total_mj: float = ( 0.0 # Energy input for generator / PTO (electric side) or PTI (mechanical side) ) energy_input_electric_total_mj: float = 0.0 # Energy input for shore power - energy_consumption_propulsion_total_mj: float = 0.0 # Energy consumption of propulsion shaft + energy_consumption_propulsion_total_mj: float = ( + 0.0 # Energy consumption of propulsion shaft + ) energy_consumption_auxiliary_total_mj: float = ( 0.0 # Energy consumption of auxiliary (electric) or mechanical load (mechanical) ) @@ -63,7 +67,8 @@ def fuel_consumption_total_kg(self): @property def fuel_energy_total_mj(self): return reduce( - lambda acc, fuel: acc + fuel.lhv_mj_per_g * fuel.mass_or_mass_fraction * 1e3, + lambda acc, fuel: acc + + fuel.lhv_mj_per_g * fuel.mass_or_mass_fraction * 1e3, self.multi_fuel_consumption_total_kg.fuels, 0.0, ) @@ -97,9 +102,10 @@ def __merge(self, other: "FEEMSResult", *, freeze_duration: bool) -> "FEEMSResul elif other.duration_s is None: value = self_value else: - value = (self_value * self.duration_s + other_value * other.duration_s) / ( - self.duration_s + other.duration_s - ) + value = ( + self_value * self.duration_s + + other_value * other.duration_s + ) / (self.duration_s + other.duration_s) elif field_name == "total_emission_kg": value = {k: self_value[k] + other_value[k] for k in self_value} elif field_name == "duration_s" and freeze_duration: @@ -123,7 +129,11 @@ def to_list_for_electric_component(self) -> List[Optional[float]]: + (self.running_hours_pti_pto_total_hr or 0.0) + (self.running_hours_fuel_cell_total_hr or 0.0), self.co2_emission_total_kg, - self.total_emission_kg[EmissionType.NOX] if self.total_emission_kg else None, + ( + self.total_emission_kg[EmissionType.NOX] + if self.total_emission_kg + else None + ), ] def to_list_for_mechanical_component(self) -> List[Optional[float]]: @@ -134,7 +144,11 @@ def to_list_for_mechanical_component(self) -> List[Optional[float]]: (self.running_hours_main_engines_hr or 0.0) + (self.running_hours_pti_pto_total_hr or 0.0), self.co2_emission_total_kg, - self.total_emission_kg[EmissionType.NOX] if self.total_emission_kg else None, + ( + self.total_emission_kg[EmissionType.NOX] + if self.total_emission_kg + else None + ), ] diff --git a/feems/tests/test_battery.py b/feems/tests/test_battery.py index 55c3819..91bf2d9 100644 --- a/feems/tests/test_battery.py +++ b/feems/tests/test_battery.py @@ -39,7 +39,9 @@ def test_charging_battery(self): ) terminal_power = 100 internal_power = 90 - self.check_power_input_output_conversion_scalar(battery, internal_power, terminal_power) + self.check_power_input_output_conversion_scalar( + battery, internal_power, terminal_power + ) def test_charging_battery_system(self): eta = 0.9 @@ -72,7 +74,9 @@ def test_discharging_battery(self): ) terminal_power = -90 internal_power = -100 - self.check_power_input_output_conversion_scalar(battery, internal_power, terminal_power) + self.check_power_input_output_conversion_scalar( + battery, internal_power, terminal_power + ) def test_discharging_battery_system(self): eta = 0.9 @@ -92,7 +96,9 @@ def test_discharging_battery_system(self): battery_system, internal_power, terminal_power ) - def check_power_input_output_conversion_scalar(self, battery, internal_power, terminal_power): + def check_power_input_output_conversion_scalar( + self, battery, internal_power, terminal_power + ): with self.subTest("Internal power from terminal power"): ( internal_power_calculated, diff --git a/feems/tests/test_components.py b/feems/tests/test_components.py index b5b083f..71ab21f 100644 --- a/feems/tests/test_components.py +++ b/feems/tests/test_components.py @@ -44,7 +44,9 @@ ) from feems.constant import nox_factor_imo_medium_speed_g_hWh -CONVERTER_EFF = np.array([[1.00, 0.75, 0.50, 0.25], [0.98, 0.972, 0.97, 0.96]]).transpose() +CONVERTER_EFF = np.array( + [[1.00, 0.75, 0.50, 0.25], [0.98, 0.972, 0.97, 0.96]] +).transpose() class TestComponent(TestCase): @@ -144,7 +146,9 @@ def test_engine_bsfc_interpolation_with_points_input(self): "main engine 1", rated_power_max, rated_speed_max, bsfc_curve ) #: Make the bsfc interpolation function anc compare with the component method - interp_func = PchipInterpolator(bsfc_curve[:, 0], bsfc_curve[:, 1], extrapolate=True) + interp_func = PchipInterpolator( + bsfc_curve[:, 0], bsfc_curve[:, 1], extrapolate=True + ) np.testing.assert_allclose(bsfc_curve, eng.specific_fuel_consumption_points) power = np.random.rand(4) * eng.rated_power load = eng.get_load(power) @@ -171,7 +175,9 @@ def test_engine_bsfc_interpolation_with_a_single_point_input(self): bsfc_curve=bsfc_curve, nox_calculation_method=NOxCalculationMethod.TIER_2, ) - self.assertEqual(eng.specific_fuel_consumption_interp(np.random.rand()), bsfc_curve[0]) + self.assertEqual( + eng.specific_fuel_consumption_interp(np.random.rand()), bsfc_curve[0] + ) def test_engine_with_file_bsfc_curve(self): """ @@ -205,7 +211,8 @@ def test_engine_with_file_bsfc_curve(self): self.assertAlmostEqual(eng.rated_power, df["Rated Power"].values[0]) np.testing.assert_allclose(eng.specific_fuel_consumption_points, bsfc) np.testing.assert_allclose( - eng.specific_fuel_consumption_interp(load_points), bsfc_function(load_points) + eng.specific_fuel_consumption_interp(load_points), + bsfc_function(load_points), ) os.unlink(filename) @@ -225,7 +232,9 @@ def test_engine_with_file_bsfc_point(self): ) load_point = np.random.rand(5) np.testing.assert_allclose(eng.specific_fuel_consumption_points, bsfc) - np.testing.assert_allclose(eng.specific_fuel_consumption_interp(load_point), bsfc[0, 1]) + np.testing.assert_allclose( + eng.specific_fuel_consumption_interp(load_point), bsfc[0, 1] + ) os.unlink(filename) def test_basic_component(self): @@ -233,7 +242,9 @@ def test_basic_component(self): name = "basic_component" rated_power_max = 1000 rated_speed_max = 500 - basic_component = create_basic_components(name, 1, rated_power_max, rated_speed_max) + basic_component = create_basic_components( + name, 1, rated_power_max, rated_speed_max + ) interp_func = PchipInterpolator( basic_component._efficiency_points[:, 0], basic_component._efficiency_points[:, 1], @@ -242,12 +253,15 @@ def test_basic_component(self): # self.assertAlmostEqual((eff_curve - basic_component._efficiency_points).sum(), 0) load_perc = np.random.rand(5) np.testing.assert_allclose( - basic_component.get_efficiency_from_load_percentage(load_perc), interp_func(load_perc) + basic_component.get_efficiency_from_load_percentage(load_perc), + interp_func(load_perc), ) #: test the power conversions, forward power no_of_pts_to_test = 100000 - power_output = (2 * np.random.rand(no_of_pts_to_test) - 1) * basic_component.rated_power + power_output = ( + 2 * np.random.rand(no_of_pts_to_test) - 1 + ) * basic_component.rated_power power_input = np.zeros(len(power_output)) load_perc = basic_component.get_load(power_output) idx_forward_power = power_output > 0 @@ -255,10 +269,14 @@ def test_basic_component(self): power_input[idx_reverse_power] = power_output[idx_reverse_power] power_input[idx_forward_power] = power_output[ idx_forward_power - ] / basic_component.get_efficiency_from_load_percentage(load_perc[idx_forward_power]) + ] / basic_component.get_efficiency_from_load_percentage( + load_perc[idx_forward_power] + ) power_output[idx_reverse_power] = power_input[ idx_reverse_power - ] / basic_component.get_efficiency_from_load_percentage(load_perc[idx_reverse_power]) + ] / basic_component.get_efficiency_from_load_percentage( + load_perc[idx_reverse_power] + ) ( power_input_comp, load_perc, @@ -301,9 +319,14 @@ def test_electric_component(self): switchboard_id, ) switchboard_id_list_to_compare = np.array( - [electric_component.switchboard_id for electric_component in electric_components] + [ + electric_component.switchboard_id + for electric_component in electric_components + ] + ) + np.testing.assert_array_equal( + switchboard_id_list, switchboard_id_list_to_compare ) - np.testing.assert_array_equal(switchboard_id_list, switchboard_id_list_to_compare) # noinspection DuplicatedCode def test_electric_machine(self): @@ -332,7 +355,9 @@ def test_electric_machine(self): load = electric_machine.get_load(power_electric) efficiency = electric_machine.get_efficiency_from_load_percentage(load) # noinspection DuplicatedCode - power_shaft[idx_generator] = power_electric[idx_generator] / efficiency[idx_generator] + power_shaft[idx_generator] = ( + power_electric[idx_generator] / efficiency[idx_generator] + ) power_electric[idx_motor] = power_shaft[idx_motor] / efficiency[idx_motor] # Test for power input from the mechanical side ( @@ -345,7 +370,9 @@ def test_electric_machine(self): ( power_shaft_pred, load_pred, - ) = electric_machine.get_shaft_power_load_from_electric_power(power_electric, True) + ) = electric_machine.get_shaft_power_load_from_electric_power( + power_electric, True + ) np.testing.assert_allclose(power_shaft, power_shaft_pred) np.testing.assert_allclose(load, load_pred) @@ -373,7 +400,9 @@ def test_electric_machine(self): idx_motor = power_shaft > 0 idx_generator = np.bitwise_not(idx_motor) power_electric[idx_motor] = power_shaft[idx_motor] / efficiency[idx_motor] - power_shaft[idx_generator] = power_electric[idx_generator] / efficiency[idx_generator] + power_shaft[idx_generator] = ( + power_electric[idx_generator] / efficiency[idx_generator] + ) # Test for power input from the shaft side ( power_electric_pred, @@ -385,7 +414,9 @@ def test_electric_machine(self): ( power_shaft_pred, load, - ) = electric_machine.get_shaft_power_load_from_electric_power(power_electric, True) + ) = electric_machine.get_shaft_power_load_from_electric_power( + power_electric, True + ) np.testing.assert_allclose(power_shaft, power_shaft_pred) np.testing.assert_allclose(load, load_pred, rtol=2e-3) @@ -400,14 +431,18 @@ def test_electric_component_efficiency_interpolation_with_a_single_point_input( rated_speed=100, eff_curve=np.array([efficiency]), ) - self.assertAlmostEqual(generator.get_efficiency_from_load_percentage(0.45), efficiency) + self.assertAlmostEqual( + generator.get_efficiency_from_load_percentage(0.45), efficiency + ) def test_electric_component_with_file_input(self): name = "generator 1" filename = "info.csv" columns = ["Switchboard No", "Rated Power", "Rated Speed"] df = create_dataframe_save_and_return(name, filename, columns) - efficiency_function, efficiency = get_efficiency_curve_from_dataframe(df, "Efficiency") + efficiency_function, efficiency = get_efficiency_curve_from_dataframe( + df, "Efficiency" + ) #: Create an engine object and test_for_fuel_calculation_for_machinery_system gen = ElectricComponent( type_=TypeComponent.GENERATOR, @@ -486,15 +521,21 @@ def test_main_engine_with_gear_box(self): load = gearbox.get_load(power_at_gearbox_out) eff_gearbox = gearbox.get_efficiency_from_load_percentage(load) power_at_engine_shaft = power_at_gearbox_out / eff_gearbox - engine_run_point = engine.get_engine_run_point_from_power_out_kw(power_at_engine_shaft) - engine_run_point_comp = main_engine_with_gearbox.get_engine_run_point_from_power_out_kw( - power_at_gearbox_out + engine_run_point = engine.get_engine_run_point_from_power_out_kw( + power_at_engine_shaft + ) + engine_run_point_comp = ( + main_engine_with_gearbox.get_engine_run_point_from_power_out_kw( + power_at_gearbox_out + ) ) np.testing.assert_allclose( engine_run_point.fuel_flow_rate_kg_per_s.total_fuel_consumption, engine_run_point_comp.fuel_flow_rate_kg_per_s.total_fuel_consumption, ) - np.testing.assert_allclose(engine_run_point.load_ratio, engine_run_point_comp.load_ratio) + np.testing.assert_allclose( + engine_run_point.load_ratio, engine_run_point_comp.load_ratio + ) np.testing.assert_allclose( engine_run_point.bsfc_g_per_kWh, engine_run_point_comp.bsfc_g_per_kWh ) @@ -523,8 +564,9 @@ def test_genset(self): genset_dc = Genset("genset 1", engine, generator, rectifier) power_electric = np.random.rand(5) * genset_ac.rated_power load_at_genset = generator.get_load(power_electric) - power_dc_at_generator = power_electric / rectifier.get_efficiency_from_load_percentage( - load_at_genset + power_dc_at_generator = ( + power_electric + / rectifier.get_efficiency_from_load_percentage(load_at_genset) ) power_shaft_ac, load_perc = generator.get_shaft_power_load_from_electric_power( power_electric @@ -573,12 +615,16 @@ def test_dual_fuel_engine(self): ) power = np.random.rand(5) * engine.rated_power engine_run_point = engine.get_engine_run_point_from_power_out_kw(power) - natual_gas_consumption_kg_per_s = engine_run_point.bsfc_g_per_kWh * power / 3600 / 1000 + natual_gas_consumption_kg_per_s = ( + engine_run_point.bsfc_g_per_kWh * power / 3600 / 1000 + ) assert np.allclose( engine_run_point.fuel_flow_rate_kg_per_s.fuels[0].mass_or_mass_fraction, natual_gas_consumption_kg_per_s, ) - diesel_consumption_kg_per_s = engine_run_point.bpsfc_g_per_kWh * power / 3600 / 1000 + diesel_consumption_kg_per_s = ( + engine_run_point.bpsfc_g_per_kWh * power / 3600 / 1000 + ) assert np.allclose( engine_run_point.fuel_flow_rate_kg_per_s.fuels[1].mass_or_mass_fraction, diesel_consumption_kg_per_s, @@ -640,7 +686,9 @@ def test_fuel_cell(self): number_modules=2, ) power = np.random.rand(5) * fuel_cell_system.rated_power - power_after_converter, _ = converter.get_power_input_from_bidirectional_output(power) + power_after_converter, _ = converter.get_power_input_from_bidirectional_output( + power + ) fuel_cell_system_run_point = fuel_cell_system.get_fuel_cell_run_point(power) fuel_cell_module_run_point = fuel_cell_system.fuel_cell.get_fuel_cell_run_point( power_out_kw=power_after_converter / number_modules, @@ -674,16 +722,30 @@ def test_cogas(self): origin=cogas.fuel_origin, fuel_specified_by=FuelSpecifiedBy.IMO, ) - fuel_consumption_kg_per_s_ref = power_output_kw / eff_cogas / (fuel.lhv_mj_per_g * 1000) / 1000 - gas_turbine_run_point = cogas.get_gas_turbine_run_point_from_power_output_kw(power_output_kw) + fuel_consumption_kg_per_s_ref = ( + power_output_kw / eff_cogas / (fuel.lhv_mj_per_g * 1000) / 1000 + ) + gas_turbine_run_point = cogas.get_gas_turbine_run_point_from_power_output_kw( + power_output_kw + ) np.testing.assert_allclose(eff_cogas, gas_turbine_run_point.efficiency) - np.testing.assert_allclose(fuel_consumption_kg_per_s_ref, gas_turbine_run_point.fuel_flow_rate_kg_per_s.fuels[0].consumption) - + np.testing.assert_allclose( + fuel_consumption_kg_per_s_ref, + gas_turbine_run_point.fuel_flow_rate_kg_per_s.fuels[ + 0 + ].mass_or_mass_fraction, + ) + # Test if the default NOx emission curve is IMO Tier 3 - factor, exponent = nox_factor_imo_medium_speed_g_hWh[NOxCalculationMethod.TIER_3.value] + factor, exponent = nox_factor_imo_medium_speed_g_hWh[ + NOxCalculationMethod.TIER_3.value + ] nox_g_per_kwh = factor * np.power(cogas.rated_speed, exponent) - np.testing.assert_equal(cogas._emissions_per_kwh_interp[EmissionType.NOX](np.random.rand()), nox_g_per_kwh) - + np.testing.assert_equal( + cogas._emissions_per_kwh_interp[EmissionType.NOX](np.random.rand()), + nox_g_per_kwh, + ) + def test_coges(self): #: Create an engine component cogas = create_cogas_system() @@ -704,8 +766,8 @@ def test_coges(self): generator=generator, ) power_electric = np.random.rand(5) * coges.rated_power - power_shaft, load_at_generator = generator.get_shaft_power_load_from_electric_power( - power_electric + power_shaft, load_at_generator = ( + generator.get_shaft_power_load_from_electric_power(power_electric) ) res_cogas = cogas.get_gas_turbine_run_point_from_power_output_kw(power_shaft) res_coges = coges.get_system_run_point_from_power_output_kw(power_electric) @@ -714,4 +776,3 @@ def test_coges(self): res_coges.cogas.fuel_flow_rate_kg_per_s.total_fuel_consumption, res_cogas.fuel_flow_rate_kg_per_s.total_fuel_consumption, ) - \ No newline at end of file diff --git a/feems/tests/test_fuel.py b/feems/tests/test_fuel.py index 886d4c5..bf3c197 100644 --- a/feems/tests/test_fuel.py +++ b/feems/tests/test_fuel.py @@ -22,7 +22,9 @@ def test_fuel_class(): origin=FuelOrigin.FOSSIL, fuel_specified_by=FuelSpecifiedBy.IMO, ) - assert fuel_by_imo.ghg_emission_factor_well_to_tank_gco2_per_gfuel == pytest.approx(0) + assert fuel_by_imo.ghg_emission_factor_well_to_tank_gco2_per_gfuel == pytest.approx( + 0 + ) assert len(fuel_by_imo.ghg_emission_factor_tank_to_wake) == 1 assert fuel_by_imo.get_ghg_emission_factor_tank_to_wake_gco2eq_per_gfuel() == 3.206 assert fuel_by_imo.lhv_mj_per_g == 0.0427 @@ -32,11 +34,15 @@ def test_fuel_class(): origin=FuelOrigin.FOSSIL, fuel_specified_by=FuelSpecifiedBy.FUEL_EU_MARITIME, ) - assert fuel_by_eu.ghg_emission_factor_well_to_tank_gco2eq_per_mj == pytest.approx(18.5) + assert fuel_by_eu.ghg_emission_factor_well_to_tank_gco2eq_per_mj == pytest.approx( + 18.5 + ) assert len(fuel_by_eu.ghg_emission_factor_tank_to_wake) == 5 assert fuel_by_eu.get_ghg_emission_factor_tank_to_wake_gco2eq_per_gfuel( fuel_consumer_class=FuelConsumerClassFuelEUMaritime.LNG_OTTO_MEDIUM_SPEED, - ) == pytest.approx((1 - 3.1 / 100) * (2.75 + 0.00011 * _GWP100_N2O) + 3.1 / 100 * _GWP100_CH4) + ) == pytest.approx( + (1 - 3.1 / 100) * (2.75 + 0.00011 * _GWP100_N2O) + 3.1 / 100 * _GWP100_CH4 + ) for specified_by in [FuelSpecifiedBy.IMO, FuelSpecifiedBy.FUEL_EU_MARITIME]: print(f"Fuel specified by {specified_by.name}") @@ -106,7 +112,9 @@ def create_random_fuel_by_mass_fraction( ) fuel_list = [] fuel_origins = np.random.choice( - [FuelOrigin.FOSSIL, FuelOrigin.RENEWABLE_NON_BIO], size=number_fuel_type, replace=True + [FuelOrigin.FOSSIL, FuelOrigin.RENEWABLE_NON_BIO], + size=number_fuel_type, + replace=True, ) try: for fuel_type, fuel_origin in zip(fuel_types, fuel_origins): @@ -145,10 +153,14 @@ def test_fuel_by_mass_fraction_class(subtests: SubTests): fuel.ghg_emission_factor_well_to_tank_gco2_per_gfuel + fuel.get_ghg_emission_factor_tank_to_wake_gco2eq_per_gfuel() ) - assert fuel_by_mass_fraction.get_kg_co2_per_kg_fuel() == pytest.approx(ghg_factor) + assert fuel_by_mass_fraction.get_kg_co2_per_kg_fuel() == pytest.approx( + ghg_factor + ) assert fuel_by_mass_fraction.lhv_mj_per_kg == pytest.approx(lhv) - with subtests.test(msg="Test fuel with random components for FuelEU specified fuels"): + with subtests.test( + msg="Test fuel with random components for FuelEU specified fuels" + ): fuel_by_mass_fraction = create_random_fuel_by_mass_fraction( number_fuel_type=3, fuel_specified_by=FuelSpecifiedBy.FUEL_EU_MARITIME ) @@ -164,7 +176,9 @@ def test_fuel_by_mass_fraction_class(subtests: SubTests): for fuel in fuel_by_mass_fraction.fuels: lhv += fuel.mass_or_mass_fraction * fuel.lhv_mj_per_g * 1000 if fuel.fuel_type == TypeFuel.NATURAL_GAS: - fuel_consumption_class_each = FuelConsumerClassFuelEUMaritime.LNG_OTTO_MEDIUM_SPEED + fuel_consumption_class_each = ( + FuelConsumerClassFuelEUMaritime.LNG_OTTO_MEDIUM_SPEED + ) elif fuel.fuel_type == TypeFuel.HYDROGEN: fuel_consumption_class_each = FuelConsumerClassFuelEUMaritime.FUEL_CELL else: diff --git a/feems/tests/test_mechanical_system_simulation.py b/feems/tests/test_mechanical_system_simulation.py index 4ce105e..4f350dc 100644 --- a/feems/tests/test_mechanical_system_simulation.py +++ b/feems/tests/test_mechanical_system_simulation.py @@ -42,7 +42,9 @@ def _set_power_input_and_status_no_pti_pto(self, number_points) -> PowerSeries: def _set_power_input_output_with_pti_pto(self, number_points) -> PowerSeries: """Set power input and output for the mechanical system""" power_series = self._set_power_input_and_status_no_pti_pto(number_points) - total_power_pti_pto_mechanical_kw = np.zeros_like(power_series.total_power_load_kw) + total_power_pti_pto_mechanical_kw = np.zeros_like( + power_series.total_power_load_kw + ) full_pti_mode = np.zeros_like(power_series.total_power_load_kw).astype(bool) for pti_pto in self.system.pti_ptos: power_pti_pto_electric_kw = (np.random.random(number_points) - 0.5) * 2000 @@ -96,7 +98,9 @@ def test_run_simulation_without_pti_pto(self): # Check if the main engine has been correctly loaded for shaft_line in self.system.shaft_line: - main_engines = shaft_line.component_by_power_type[TypePower.POWER_SOURCE] + main_engines = shaft_line.component_by_power_type[ + TypePower.POWER_SOURCE + ] loads = shaft_line.component_by_power_type[TypePower.POWER_CONSUMER] total_rated_power = np.array( [each.rated_power * each.status for each in main_engines] @@ -111,9 +115,12 @@ def test_run_simulation_without_pti_pto(self): * power_source.rated_power / total_rated_power ).sum() - self.assertAlmostEqual(power_source.power_output.sum(), power_output_calc) + self.assertAlmostEqual( + power_source.power_output.sum(), power_output_calc + ) self.system.set_time_interval( - time_interval_s=time_interval_s, integration_method=IntegrationMethod.simpson + time_interval_s=time_interval_s, + integration_method=IntegrationMethod.simpson, ) feems_result = self.system.get_fuel_energy_consumption_running_time() @@ -129,7 +136,9 @@ def test_run_simulation_without_pti_pto(self): else total_power_kw * time_interval_s ) average_bsfc = ( - feems_result.fuel_consumption_total_kg * 1000 / (total_energy_kj / 3600) + feems_result.fuel_consumption_total_kg + * 1000 + / (total_energy_kj / 3600) ) self.assertTrue(300 > average_bsfc > 180) @@ -150,12 +159,15 @@ def test_run_simulation_with_incorrect_config(self): with self.subTest("Test for inconsistent number of points for power inputs"): component_with_wrong_input = random.choice(self.system.mechanical_loads) wrong_power_input = ( - np.random.random(number_points - random.randint(1, number_points - 1)) * 2000 + np.random.random(number_points - random.randint(1, number_points - 1)) + * 2000 ) component_with_wrong_input.set_power_input_from_output(wrong_power_input) # Test validation - self.assertFalse(self.system.validate_inputs_before_power_balance_calculation()) + self.assertFalse( + self.system.validate_inputs_before_power_balance_calculation() + ) for err_msg in self.system.errors_simulation_inputs: print(err_msg) component_with_wrong_input.set_power_input_from_output( @@ -176,12 +188,16 @@ def test_run_simulation_with_incorrect_config(self): comp.status = wrong_status # Test validation - self.assertFalse(self.system.validate_inputs_before_power_balance_calculation()) + self.assertFalse( + self.system.validate_inputs_before_power_balance_calculation() + ) for err_msg in self.system.errors_simulation_inputs: print(err_msg) comp.status = np.ones(number_points).astype(bool) - with self.subTest("Test for inconsistent number of points of full pti pto mode"): + with self.subTest( + "Test for inconsistent number of points of full pti pto mode" + ): component_with_wrong_input = random.choice(self.system.pti_ptos) wrong_full_pti_mode = np.ones( number_points - random.randint(1, number_points - 1) @@ -189,10 +205,14 @@ def test_run_simulation_with_incorrect_config(self): component_with_wrong_input.full_pti_mode = wrong_full_pti_mode # Test validation - self.assertFalse(self.system.validate_inputs_before_power_balance_calculation()) + self.assertFalse( + self.system.validate_inputs_before_power_balance_calculation() + ) for err_msg in self.system.errors_simulation_inputs: print(err_msg) - component_with_wrong_input.full_pti_mode = np.ones(number_points).astype(bool) + component_with_wrong_input.full_pti_mode = np.ones(number_points).astype( + bool + ) def test_run_simulation_with_pti_pto(self): """Test running simulation for the mechanical system with a single point""" @@ -200,7 +220,8 @@ def test_run_simulation_with_pti_pto(self): power_series = self._set_power_input_output_with_pti_pto(number_points) time_interval_s = 60 self.system.set_time_interval( - time_interval_s=time_interval_s, integration_method=IntegrationMethod.simpson + time_interval_s=time_interval_s, + integration_method=IntegrationMethod.simpson, ) self.system.do_power_balance() @@ -226,7 +247,9 @@ def test_run_simulation_with_pti_pto(self): total_rated_power = np.array( [each.rated_power * each.status for each in main_engines] ).sum(axis=0) - total_power_consumption = reduce(lambda acc, load: acc + load.power_input, loads, 0) + total_power_consumption = reduce( + lambda acc, load: acc + load.power_input, loads, 0 + ) total_pti_pto_power = reduce( lambda acc, pti_pto: acc + pti_pto.power_output, pti_ptos, 0 ) @@ -240,4 +263,6 @@ def test_run_simulation_with_pti_pto(self): * power_source.rated_power / total_rated_power[~index] ) - self.assertAlmostEqual(power_source.power_output.sum(), power_output_calc.sum()) + self.assertAlmostEqual( + power_source.power_output.sum(), power_output_calc.sum() + ) diff --git a/feems/tests/test_node.py b/feems/tests/test_node.py index c60b780..2e8365c 100644 --- a/feems/tests/test_node.py +++ b/feems/tests/test_node.py @@ -46,8 +46,10 @@ def __init__(self, *args, **kwargs): power_avail_total = 3000 #: Distribute number of components by types - number_of_components_list = get_list_random_distribution_numbers_for_total_number( - 4, number_of_components + number_of_components_list = ( + get_list_random_distribution_numbers_for_total_number( + 4, number_of_components + ) ) self.switchboard = create_switchboard_with_components( 1, @@ -120,7 +122,9 @@ def set_status(self) -> StatusSummary: ) def test_initialization(self): - power_types = [component.power_type for component in self.switchboard.components] + power_types = [ + component.power_type for component in self.switchboard.components + ] # Test initialization self.assertEqual( @@ -133,7 +137,9 @@ def test_initialization(self): power_types.count(TypePower.ENERGY_STORAGE), self.switchboard.no_energy_storage, ) - self.assertEqual(power_types.count(TypePower.PTI_PTO), self.switchboard.no_pti_pto) + self.assertEqual( + power_types.count(TypePower.PTI_PTO), self.switchboard.no_pti_pto + ) def test_setting_and_getting_status_power_source(self): # Test setting and getting the status of the power source @@ -148,7 +154,9 @@ def test_setting_and_getting_status_power_source(self): status_power_source = self.switchboard.get_status_component_by_power_type( TypePower.POWER_SOURCE ) - status_pti_pto = self.switchboard.get_status_component_by_power_type(TypePower.PTI_PTO) + status_pti_pto = self.switchboard.get_status_component_by_power_type( + TypePower.PTI_PTO + ) status_energy_storage = self.switchboard.get_status_component_by_power_type( TypePower.ENERGY_STORAGE ) @@ -159,7 +167,9 @@ def test_setting_and_getting_status_power_source(self): ).all() ) self.assertTrue( - np.equal(np.array(status_pti_pto).transpose(), new_status.status_pti_pto).all() + np.equal( + np.array(status_pti_pto).transpose(), new_status.status_pti_pto + ).all() ) self.assertTrue( np.equal( @@ -170,14 +180,18 @@ def test_setting_and_getting_status_power_source(self): def test_setting_getting_the_load_sharing_status(self): # Test setting and getting the load sharing status of the power source - load_sharing_status = self.switchboard.get_load_sharing_mode_components_by_power_type( - TypePower.POWER_SOURCE + load_sharing_status = ( + self.switchboard.get_load_sharing_mode_components_by_power_type( + TypePower.POWER_SOURCE + ) ) self.assertEqual(np.abs(np.array(load_sharing_status)).sum(), 0) load_sharing_summary = self.set_load_sharing_mode() - load_sharing_status = self.switchboard.get_load_sharing_mode_components_by_power_type( - TypePower.POWER_SOURCE + load_sharing_status = ( + self.switchboard.get_load_sharing_mode_components_by_power_type( + TypePower.POWER_SOURCE + ) ) self.assertTrue( np.equal( @@ -186,8 +200,10 @@ def test_setting_getting_the_load_sharing_status(self): ).all() ) - load_sharing_status = self.switchboard.get_load_sharing_mode_components_by_power_type( - TypePower.PTI_PTO + load_sharing_status = ( + self.switchboard.get_load_sharing_mode_components_by_power_type( + TypePower.PTI_PTO + ) ) self.assertTrue( np.equal( @@ -196,8 +212,10 @@ def test_setting_getting_the_load_sharing_status(self): ).all() ) - load_sharing_status = self.switchboard.get_load_sharing_mode_components_by_power_type( - TypePower.ENERGY_STORAGE + load_sharing_status = ( + self.switchboard.get_load_sharing_mode_components_by_power_type( + TypePower.ENERGY_STORAGE + ) ) self.assertTrue( np.equal( @@ -212,12 +230,16 @@ def test_get_power_avail_component_by_power_type(self): for component in self.switchboard.components: if component.power_type == TypePower.POWER_SOURCE: rated_power_list.append(component.rated_power * component.status) - rated_power_list_from_class = self.switchboard.get_power_avail_component_by_power_type( - TypePower.POWER_SOURCE + rated_power_list_from_class = ( + self.switchboard.get_power_avail_component_by_power_type( + TypePower.POWER_SOURCE + ) ) rated_power_array = np.array(rated_power_list).transpose() rated_power_array_from_class = np.array(rated_power_list_from_class).transpose() - self.assertEqual(np.sum(np.abs(rated_power_array - rated_power_array_from_class)), 0) + self.assertEqual( + np.sum(np.abs(rated_power_array - rated_power_array_from_class)), 0 + ) # noinspection PyTypeChecker def test_set_power_load_component_from_power_output_by_type_and_name(self): @@ -226,8 +248,12 @@ def test_set_power_load_component_from_power_output_by_type_and_name(self): # Gets a random component which is not a power source component: ElectricComponent = random.choice(self.switchboard.components) while isinstance(component, (Genset, FuelCellSystem)): - component = cast(ElectricComponent, random.choice(self.switchboard.components)) - power_output_ref = np.random.rand(self.no_points_to_test) * component.rated_power + component = cast( + ElectricComponent, random.choice(self.switchboard.components) + ) + power_output_ref = ( + np.random.rand(self.no_points_to_test) * component.rated_power + ) power_input_ref, load = component.get_power_input_from_bidirectional_output( power_output_ref ) @@ -279,28 +305,40 @@ def test_power_source_load_calculation(self): / sum_power_avail_for_power_sources_symmetric[power_is_available] ) - load_perc_symm_power_source = power_summary.load_perc_symmetric_loaded_power_source + load_perc_symm_power_source = ( + power_summary.load_perc_symmetric_loaded_power_source + ) load_perc_symm_power_source_ref[np.isinf(load_perc_symm_power_source_ref)] = 0 load_perc_symm_power_source[np.isinf(load_perc_symm_power_source)] = 0 load_perc_symm_power_source_ref[np.isnan(load_perc_symm_power_source_ref)] = 0 load_perc_symm_power_source[np.isnan(load_perc_symm_power_source)] = 0 - self.assertTrue(np.allclose(load_perc_symm_power_source, load_perc_symm_power_source_ref)) + self.assertTrue( + np.allclose(load_perc_symm_power_source, load_perc_symm_power_source_ref) + ) time_step = 1.0 self.switchboard.set_power_out_power_sources(load_perc_symm_power_source) result = self.switchboard.get_fuel_energy_consumption_running_time(time_step) - for power_source in self.switchboard.component_by_power_type[TypePower.POWER_SOURCE.value]: + for power_source in self.switchboard.component_by_power_type[ + TypePower.POWER_SOURCE.value + ]: index = power_source.load_sharing_mode > 0 power_output = power_source.rated_power * load_perc_symm_power_source power_output *= power_source.status - power_output[index] = power_source.rated_power * power_source.load_sharing_mode[index] + power_output[index] = ( + power_source.rated_power * power_source.load_sharing_mode[index] + ) power_output[index] = power_output[index] * power_source.status[index] self.assertTrue( - np.equal(np.round(power_output, 3), np.round(power_source.power_output, 3)).all() + np.equal( + np.round(power_output, 3), np.round(power_source.power_output, 3) + ).all() ) - results2 = self.switchboard.get_fuel_energy_consumption_running_time_without_details( - time_step + results2 = ( + self.switchboard.get_fuel_energy_consumption_running_time_without_details( + time_step + ) ) for key in results2.__dict__: if key == "detail_result": @@ -371,7 +409,9 @@ def test_shaft_line(self): #: Create a propeller load rated_power_propeller = ( - 0.5 * (random.random() + 1) * (total_rated_power_main_engine + pti_pto.rated_power) + 0.5 + * (random.random() + 1) + * (total_rated_power_main_engine + pti_pto.rated_power) ) propeller_load = MechanicalPropulsionComponent( TypeComponent.PROPELLER_LOAD, @@ -388,7 +428,9 @@ def test_shaft_line(self): ShaftLine("Shaft line with only engines", 1, main_engines + [propeller_load]) #: Create a shaft line component - shaft_line = ShaftLine("shaft line 1", 1, main_engines + [pti_pto, propeller_load]) + shaft_line = ShaftLine( + "shaft line 1", 1, main_engines + [pti_pto, propeller_load] + ) #: Test pure mechanical propulsion mode while True: @@ -427,14 +469,20 @@ def test_shaft_line(self): #: Calculate the reference fuel consumption fuel_consumption_rate_ref = 0 for main_engine in main_engines: - fuel_consumption_rate_temp = main_engine.get_engine_run_point_from_power_out_kw( - main_engine.rated_power * total_load_percentage_ref * main_engine.status - ).fuel_flow_rate_kg_per_s.total_fuel_consumption + fuel_consumption_rate_temp = ( + main_engine.get_engine_run_point_from_power_out_kw( + main_engine.rated_power + * total_load_percentage_ref + * main_engine.status + ).fuel_flow_rate_kg_per_s.total_fuel_consumption + ) fuel_consumption_rate_ref += fuel_consumption_rate_temp fuel_consumption_ref = simpson(fuel_consumption_rate_ref) * time_step #: Set the PTI/PTO power 0 - pti_pto.power_input = pti_pto.set_power_output_from_input(np.zeros(number_test_points)) + pti_pto.power_input = pti_pto.set_power_output_from_input( + np.zeros(number_test_points) + ) pti_pto.full_pti_mode = np.zeros(number_test_points).astype(bool) #: Do the power balance calculation shaft_line.do_power_balance() @@ -443,7 +491,9 @@ def test_shaft_line(self): result = shaft_line.get_fuel_calculation_running_hours(time_step) #: Check the result - self.assertAlmostEqual(result.running_hours_main_engines_hr, total_running_hours_ref) + self.assertAlmostEqual( + result.running_hours_main_engines_hr, total_running_hours_ref + ) self.assertAlmostEqual(result.fuel_consumption_total_kg, fuel_consumption_ref) #: Test the hybrid propulsion @@ -476,28 +526,38 @@ def test_shaft_line(self): #: Check power balance max_power_output_pti_pto = propeller_load.power_input - power_output_pti_pto = np.minimum(power_output_pti_pto, max_power_output_pti_pto) + power_output_pti_pto = np.minimum( + power_output_pti_pto, max_power_output_pti_pto + ) min_power_output_pti_pto = -( total_power_available_main_engines - propeller_load.power_input ) - power_output_pti_pto = np.maximum(power_output_pti_pto, min_power_output_pti_pto) + power_output_pti_pto = np.maximum( + power_output_pti_pto, min_power_output_pti_pto + ) pti_pto.full_pti_mode = power_output_pti_pto == max_power_output_pti_pto #: Get the reference value for running hours and fuel consumption - total_power_output_main_engines = propeller_load.power_input - power_output_pti_pto + total_power_output_main_engines = ( + propeller_load.power_input - power_output_pti_pto + ) status = total_power_output_main_engines > 0 total_load_percentage_ref = np.zeros(number_test_points) total_load_percentage_ref[status] = ( - total_power_output_main_engines[status] / total_power_available_main_engines[status] + total_power_output_main_engines[status] + / total_power_available_main_engines[status] ) total_running_hours_ref = 0 fuel_consumption_ref = 0 for engine in main_engines: engine.status[np.bitwise_not(status)] = False - engine.power_output = total_load_percentage_ref * engine.rated_power * engine.status + engine.power_output = ( + total_load_percentage_ref * engine.rated_power * engine.status + ) res_engine = engine.get_engine_run_point_from_power_out_kw() fuel_consumption_ref += ( - simpson(res_engine.fuel_flow_rate_kg_per_s.total_fuel_consumption) * time_step + simpson(res_engine.fuel_flow_rate_kg_per_s.total_fuel_consumption) + * time_step ) total_running_hours_ref += engine.status.sum() * time_step / 3600 @@ -514,6 +574,7 @@ def test_shaft_line(self): result = shaft_line.get_fuel_calculation_running_hours(time_step) self.assertAlmostEqual(result.fuel_consumption_total_kg, fuel_consumption_ref) self.assertAlmostEqual( - result.running_hours_main_engines_hr + result.running_hours_pti_pto_total_hr, + result.running_hours_main_engines_hr + + result.running_hours_pti_pto_total_hr, total_running_hours_ref, ) diff --git a/feems/tests/test_system.py b/feems/tests/test_system.py index 62059fc..f5ec93c 100644 --- a/feems/tests/test_system.py +++ b/feems/tests/test_system.py @@ -4,7 +4,11 @@ from typing import List, Dict from unittest import TestCase -from feems.components_model.component_electric import COGES, ElectricMachine, SerialSystemElectric +from feems.components_model.component_electric import ( + COGES, + ElectricMachine, + SerialSystemElectric, +) from feems.components_model.component_mechanical import COGAS from feems.fuel import Fuel, FuelConsumption import numpy as np @@ -123,7 +127,9 @@ def setUp(self) -> None: no_of_genset_per_switchboard_diesel_electric = 2 self.no_gensets_for_conventional = int(np.round(np.random.rand() * 3)) + 1 self.no_gensets_for_hybrid = int(np.round(np.random.rand() * 3)) + 1 - self.no_gensets_for_diesel_electric = (int(np.round(np.random.rand() * 3)) + 2) * 2 + self.no_gensets_for_diesel_electric = ( + int(np.round(np.random.rand() * 3)) + 2 + ) * 2 self.rated_power_aux_engine = Power_kW(2700) self.rated_power_generator = Power_kW(2500) self.rated_speed_genset = Speed_rpm(1500) @@ -135,7 +141,9 @@ def setUp(self) -> None: efficiency_curve_for_generator_motor, no_of_genset_per_switchboard, ) - self.no_switchboard_conventional = self.gensets_for_conventional[-1].switchboard_id + self.no_switchboard_conventional = self.gensets_for_conventional[ + -1 + ].switchboard_id self.gensets_for_hybrid = TestElectricPowerSystem.get_gensets( self.no_gensets_for_hybrid, self.rated_power_generator, @@ -153,7 +161,9 @@ def setUp(self) -> None: efficiency_curve_for_generator_motor, no_of_genset_per_switchboard_diesel_electric, ) - self.no_switchboard_diesel_electric = self.gensets_for_diesel_electric[-1].switchboard_id + self.no_switchboard_diesel_electric = self.gensets_for_diesel_electric[ + -1 + ].switchboard_id # PTI PTO self.no_pti_pto = 1 @@ -183,7 +193,7 @@ def setUp(self) -> None: ) energy_storage_for_diesel_electric = copy.deepcopy(energy_storage_for_hybrid) energy_storage_for_conventional = copy.deepcopy(energy_storage_for_hybrid) - + # Thruster self.no_thruster = 2 self.no_thruster_diesel_electric = self.no_switchboard_diesel_electric @@ -202,23 +212,29 @@ def setUp(self) -> None: self.switchboard_id_thrusters_for_diesel_electric = np.arange( 1, self.no_switchboard_diesel_electric + 1 ).tolist() - self.propulsion_drives_for_hybrid = TestElectricPowerSystem.get_propulsion_drives( - self.no_thruster, - self.rated_power_thruster, - self.rated_speed_thruster, - self.switchboard_id_thrusters_for_hybrid, + self.propulsion_drives_for_hybrid = ( + TestElectricPowerSystem.get_propulsion_drives( + self.no_thruster, + self.rated_power_thruster, + self.rated_speed_thruster, + self.switchboard_id_thrusters_for_hybrid, + ) ) - self.propulsion_drives_for_conventional = TestElectricPowerSystem.get_propulsion_drives( - self.no_thruster, - self.rated_power_thruster, - self.rated_speed_thruster, - self.switchboard_id_thrusters_for_conventional, + self.propulsion_drives_for_conventional = ( + TestElectricPowerSystem.get_propulsion_drives( + self.no_thruster, + self.rated_power_thruster, + self.rated_speed_thruster, + self.switchboard_id_thrusters_for_conventional, + ) ) - self.propulsion_drives_for_diesel_electric = TestElectricPowerSystem.get_propulsion_drives( - self.no_thruster_diesel_electric, - self.rated_power_thruster, - self.rated_speed_thruster, - self.switchboard_id_thrusters_for_diesel_electric, + self.propulsion_drives_for_diesel_electric = ( + TestElectricPowerSystem.get_propulsion_drives( + self.no_thruster_diesel_electric, + self.rated_power_thruster, + self.rated_speed_thruster, + self.switchboard_id_thrusters_for_diesel_electric, + ) ) # Other load @@ -405,7 +421,9 @@ def test_configuration(self): self.power_system_for_conventional_system.bus_tie_breakers ): for switchboard_id in bus_tie_breaker.switchboard_ids: - self.assertTrue(switchboard_id in self.bus_tie_connections_conventional[i]) + self.assertTrue( + switchboard_id in self.bus_tie_connections_conventional[i] + ) # Test for the hybrid system # # Check if the components are all included in the system @@ -486,7 +504,9 @@ def test_configuration(self): self.power_system_for_diesel_electric_system.bus_tie_breakers ): for switchboard_id in bus_tie_breaker.switchboard_ids: - self.assertTrue(switchboard_id in self.bus_tie_connections_diesel_electric[i]) + self.assertTrue( + switchboard_id in self.bus_tie_connections_diesel_electric[i] + ) def test_power_balance_calculation(self): if self.power_balance_test_complete: @@ -523,7 +543,9 @@ def test_power_balance_calculation(self): switch2bus_configuration.append([]) while True: switch2bus_configuration[i] = [1] - for j in range(self.power_system_for_diesel_electric_system.no_switchboard - 1): + for j in range( + self.power_system_for_diesel_electric_system.no_switchboard - 1 + ): bus_tie_configuration_at_change[i, j] = bool(random.getrandbits(1)) switch2bus_configuration[i].append( int(not (bus_tie_configuration_at_change[i, j])) @@ -544,7 +566,9 @@ def test_power_balance_calculation(self): * 1 / no_different_bus_tie_configuration * self.no_points_to_test - + (i - 1) * self.no_points_to_test / no_different_bus_tie_configuration + + (i - 1) + * self.no_points_to_test + / no_different_bus_tie_configuration ) if index_next != index_bus_config_change[i - 1]: index_bus_config_change.append(index_next) @@ -554,8 +578,12 @@ def test_power_balance_calculation(self): index_bus_config_change[i - 1] : index_bus_config_change[i], : ] = bus_tie_configuration_at_change[i - 1, :] # noinspection PyUnboundLocalVariable - bus_tie_configuration[index_bus_config_change[i] :] = bus_tie_configuration_at_change[i] - self.power_system_for_diesel_electric_system.set_bus_tie_status_all(bus_tie_configuration) + bus_tie_configuration[index_bus_config_change[i] :] = ( + bus_tie_configuration_at_change[i] + ) + self.power_system_for_diesel_electric_system.set_bus_tie_status_all( + bus_tie_configuration + ) self.assertEqual( self.power_system_for_diesel_electric_system.bus_configuration_change_index, index_bus_config_change, @@ -590,15 +618,16 @@ def test_power_balance_calculation(self): for i, switchboard2bus in enumerate( self.power_system_for_diesel_electric_system.switchboard2bus ): - index_start = ( - self.power_system_for_diesel_electric_system.bus_configuration_change_index[i] - ) - if i + 1 < self.power_system_for_diesel_electric_system.no_bus_configuration_change: - index_end = ( - self.power_system_for_diesel_electric_system.bus_configuration_change_index[ - i + 1 - ] - ) + index_start = self.power_system_for_diesel_electric_system.bus_configuration_change_index[ + i + ] + if ( + i + 1 + < self.power_system_for_diesel_electric_system.no_bus_configuration_change + ): + index_end = self.power_system_for_diesel_electric_system.bus_configuration_change_index[ + i + 1 + ] else: index_end = self.no_points_to_test for _, bus_id in switchboard2bus.items(): @@ -612,7 +641,9 @@ def test_power_balance_calculation(self): _, switchboard, ) in self.power_system_for_diesel_electric_system.switchboards.items(): - for component in switchboard.component_by_power_type[TypePower.POWER_CONSUMER.value]: + for component in switchboard.component_by_power_type[ + TypePower.POWER_CONSUMER.value + ]: first_loading = True for i, switchboard2bus in enumerate( self.power_system_for_diesel_electric_system.switchboard2bus @@ -652,33 +683,35 @@ def test_power_balance_calculation(self): ) first_loading = False sum_power_input += component.power_input - sum_power_input_switchboard += switchboard.get_sum_power_input_by_power_type( - TypePower.POWER_CONSUMER + sum_power_input_switchboard += ( + switchboard.get_sum_power_input_by_power_type(TypePower.POWER_CONSUMER) ) # Test the energy conservation and methods for summing the power input/output for buses - sum_power_input_buses_comp_tmp = ( - self.power_system_for_diesel_electric_system.get_sum_power_in_buses_by_power_type( - TypePower.POWER_CONSUMER - ) + sum_power_input_buses_comp_tmp = self.power_system_for_diesel_electric_system.get_sum_power_in_buses_by_power_type( + TypePower.POWER_CONSUMER ) sum_power_input_buses_comp = self.sum_bus(sum_power_input_buses_comp_tmp) - sum_power_output_buses_comp = ( - self.power_system_for_diesel_electric_system.get_sum_power_output_buses_by_power_type( - TypePower.POWER_CONSUMER - ) + sum_power_output_buses_comp = self.power_system_for_diesel_electric_system.get_sum_power_output_buses_by_power_type( + TypePower.POWER_CONSUMER + ) + self.assertAlmostEqual( + np.abs(sum_power_input - sum_power_input_switchboard).sum(), 0 ) - self.assertAlmostEqual(np.abs(sum_power_input - sum_power_input_switchboard).sum(), 0) self.assertAlmostEqual( np.abs(sum_power_input_switchboard - sum_power_input_buses_comp).sum(), 0 ) for bus in sum_power_output_buses: # noinspection PyTypeChecker - np.array_equal(sum_power_output_buses[bus], sum_power_output_buses_comp[bus]) + np.array_equal( + sum_power_output_buses[bus], sum_power_output_buses_comp[bus] + ) # noinspection PyTypeChecker self.assertAlmostEqual( - np.abs(sum_power_output_buses[bus] - sum_power_output_buses_comp[bus]).sum(), + np.abs( + sum_power_output_buses[bus] - sum_power_output_buses_comp[bus] + ).sum(), 0, ) @@ -726,10 +759,8 @@ def test_power_balance_calculation(self): ) # Sum all the power input for the buses - sum_power_input_buses_comp = ( - self.power_system_for_diesel_electric_system.get_sum_power_in_buses_by_power_type( - TypePower.POWER_CONSUMER - ) + sum_power_input_buses_comp = self.power_system_for_diesel_electric_system.get_sum_power_in_buses_by_power_type( + TypePower.POWER_CONSUMER ) sum_power_input_buses_comp = self.add_bus( @@ -768,21 +799,24 @@ def test_power_balance_calculation(self): for i, switchboard2bus in enumerate( self.power_system_for_diesel_electric_system.switchboard2bus ): - index_start = ( - self.power_system_for_diesel_electric_system.bus_configuration_change_index[i] - ) - if i + 1 < self.power_system_for_diesel_electric_system.no_bus_configuration_change: - index_end = ( - self.power_system_for_diesel_electric_system.bus_configuration_change_index[ - i + 1 - ] - ) + index_start = self.power_system_for_diesel_electric_system.bus_configuration_change_index[ + i + ] + if ( + i + 1 + < self.power_system_for_diesel_electric_system.no_bus_configuration_change + ): + index_end = self.power_system_for_diesel_electric_system.bus_configuration_change_index[ + i + 1 + ] else: index_end = self.no_points_to_test for swb_id, bus_id in switchboard2bus.items(): sum_power_output_power_sources_buses[bus_id][ index_start:index_end - ] += sum_power_output_power_sources_switchboards[swb_id][index_start:index_end] + ] += sum_power_output_power_sources_switchboards[swb_id][ + index_start:index_end + ] for bus_id in sum_power_output_power_sources_buses: self.assertAlmostEqual( np.abs( @@ -822,7 +856,10 @@ def test_fuel_consumption_calculation(self): "Mechanical energy consumption (kJ): %s" % result.energy_consumption_mechanical_total_mj ) - print("Electric energy consumption (kJ): %s" % result.energy_consumption_electric_total_mj) + print( + "Electric energy consumption (kJ): %s" + % result.energy_consumption_electric_total_mj + ) print("Running time (s):") print("\t" + "Gensets: %s" % result.running_hours_genset_total_hr) print("\t" + "Fuel cell: %s" % result.running_hours_fuel_cell_total_hr) @@ -892,7 +929,9 @@ def test_battery_only_configuration(self): electric_system.do_power_balance_calculation() self.assertAlmostEqual( - np.power(battery_system.power_input + propulsion_drive.power_input, 2).sum(), + np.power( + battery_system.power_input + propulsion_drive.power_input, 2 + ).sum(), 0, 5, ) @@ -927,26 +966,32 @@ def setUp(self) -> None: number_poles=4, eff_curve=ELECTRIC_MACHINE_EFF_CURVE, ) - self.coges.append(COGES( - name=f"COGES {i}", - cogas=cogas, - generator=generator, - )) + self.coges.append( + COGES( + name=f"COGES {i}", + cogas=cogas, + generator=generator, + ) + ) # Create a propulsion drive - self.propulsion_drive.append(create_a_propulsion_drive( - name=f"propulsion drive {i}", - rated_power=600, - rated_speed=750, - switchboard_id=i, - )) + self.propulsion_drive.append( + create_a_propulsion_drive( + name=f"propulsion drive {i}", + rated_power=600, + rated_speed=750, + switchboard_id=i, + ) + ) self.system = ElectricPowerSystem( name="COGES system", power_plant_components=[ - *self.coges, *self.propulsion_drive, self.other_load + *self.coges, + *self.propulsion_drive, + self.other_load, ], bus_tie_connections=[(1, 2)], ) - + def test_configuration(self): # Test the configuration self.assertEqual(self.system.no_power_sources, len(self.coges)) @@ -958,34 +1003,43 @@ def test_configuration(self): self.assertEqual(self.system.no_bus_configuration_change, 1) self.assertEqual(self.system.no_switchboard, 2) self.assertEqual(self.system.no_bus, [1]) - + def test_get_fuel_consumption(self): - propulsion_loads = [propulsion_drive.rated_power * np.random.random(1) for propulsion_drive in self.propulsion_drive] + propulsion_loads = [ + propulsion_drive.rated_power * np.random.random(1) + for propulsion_drive in self.propulsion_drive + ] other_loads = np.array([400 * np.random.random()]) - + # Set the power input for the propulsion drives and other loads for propulsion_drive, load in zip(self.propulsion_drive, propulsion_loads): propulsion_drive.set_power_input_from_output(load) self.other_load.set_power_input_from_output(other_loads) - + # Set the bus tie status self.system.bus_tie_breakers[0].status = np.ones(1).astype(bool) - + # Set the status and load sharing mode for the power sources for coges in self.coges: coges.status = np.ones(1).astype(bool) coges.load_sharing_mode = np.zeros(1) - + # Set time interval - self.system.set_time_interval(time_interval_s=3600, integration_method=IntegrationMethod.sum_with_time) - + self.system.set_time_interval( + time_interval_s=3600, integration_method=IntegrationMethod.sum_with_time + ) + # Do power balance self.system.do_power_balance_calculation() - + # Calculate the fuel consumption manually cogas_fuel_consumption = 0 for coges in self.coges: - cogas_power_output, _ = coges.generator.get_power_input_from_bidirectional_output(coges.power_output) + cogas_power_output, _ = ( + coges.generator.get_power_input_from_bidirectional_output( + coges.power_output + ) + ) cogas_efficiency = coges.cogas.get_efficiency_from_load_percentage( cogas_power_output / coges.cogas.rated_power ) @@ -993,15 +1047,20 @@ def test_get_fuel_consumption(self): fuel_type=coges.cogas.fuel_type, origin=coges.cogas.fuel_origin, ).lhv_mj_per_g - cogas_fuel_consumption_rate = cogas_power_output / cogas_efficiency / (lhv_fuel_mj_per_g * 1000) / 1000 + cogas_fuel_consumption_rate = ( + cogas_power_output + / cogas_efficiency + / (lhv_fuel_mj_per_g * 1000) + / 1000 + ) cogas_fuel_consumption += cogas_fuel_consumption_rate * 3600 - + # Get the fuel consumption result = self.system.get_fuel_energy_consumption_running_time() fuel_consumption_result = result.fuel_consumption_total_kg # Compare the results self.assertAlmostEqual(cogas_fuel_consumption[0], fuel_consumption_result, 5) - + class TestMechanicalPropulsionSystemSetup(TestCase): def setUp(self) -> None: @@ -1083,7 +1142,9 @@ def setUp(self) -> None: self.propeller_load.append(propeller_load) # noinspection PyTypeChecker - self.components = self.main_engine_component + self.pti_pto + self.propeller_load + self.components = ( + self.main_engine_component + self.pti_pto + self.propeller_load + ) # Create a system model self.system = MechanicalPropulsionSystem( name="Mechanical Propulsion", components_list=self.components @@ -1099,7 +1160,9 @@ def test_configuration(self): self.assertTrue( component in self.system.component_by_shaft_line_id[shaftline_list[-1]] ) - self.assertTrue(component in self.system.shaft_line[shaftline_list[-1] - 1].components) + self.assertTrue( + component in self.system.shaft_line[shaftline_list[-1] - 1].components + ) # make shaft line list unique number_shaft_line_given = len(list(dict.fromkeys(shaftline_list))) @@ -1135,8 +1198,12 @@ def test_set_full_pti_mode_for_name_shaft_line_id(self): def test_set_power_input_output_pti_pto(self): for pti_pto in self.pti_pto: number_points = np.random.randint(10, 10000) - power_output = (2 * np.random.random(number_points) - 1) * pti_pto.rated_power - power_input, load = pti_pto.get_power_input_from_bidirectional_output(power_output) + power_output = ( + 2 * np.random.random(number_points) - 1 + ) * pti_pto.rated_power + power_input, load = pti_pto.get_power_input_from_bidirectional_output( + power_output + ) self.assertEqual( self.system.set_power_input_pti_pto_by_power_output_value_for_name_shaft_line_id( pti_pto.name, pti_pto.shaft_line_id, power_output @@ -1151,15 +1218,21 @@ def test_set_power_input_output_pti_pto(self): ), 1, ) - power_output, load = pti_pto.get_power_output_from_bidirectional_input(power_input) + power_output, load = pti_pto.get_power_output_from_bidirectional_input( + power_input + ) self.assertTrue(np.equal(power_input, pti_pto.power_input).all()) self.assertTrue(np.equal(power_output, pti_pto.power_output).all()) def test_set_power_consumer_load(self): for component in self.propeller_load: number_points = np.random.randint(10, 10000) - power_output = (2 * np.random.random(number_points) - 1) * component.rated_power - power_input, load = component.get_power_input_from_bidirectional_output(power_output) + power_output = ( + 2 * np.random.random(number_points) - 1 + ) * component.rated_power + power_input, load = component.get_power_input_from_bidirectional_output( + power_output + ) self.assertEqual( self.system.set_power_consumer_load_by_power_output_for_given_name_shaft_line_id( component.name, component.shaft_line_id, power_output @@ -1176,7 +1249,9 @@ def test_set_power_consumer_load(self): ) self.assertTrue(np.equal(power_input, component.power_input).all()) self.assertTrue( - np.equal(np.round(power_output, 3), np.round(component.power_output, 3)).all() + np.equal( + np.round(power_output, 3), np.round(component.power_output, 3) + ).all() ) def test_set_status_main_engine_for_name_shaft_line_id(self): diff --git a/feems/tests/test_system_simplified.py b/feems/tests/test_system_simplified.py index d94b812..e8b6e3a 100644 --- a/feems/tests/test_system_simplified.py +++ b/feems/tests/test_system_simplified.py @@ -71,7 +71,9 @@ def __init__(self, *args, **kwargs): # type: ignore[no-untyped-def] switchboard_id=self.switchboard_id, eff_curve=np.array([efficiency_generator]), ) - self.genset = Genset(name="genset", aux_engine=aux_engine_object, generator=self.generator) + self.genset = Genset( + name="genset", aux_engine=aux_engine_object, generator=self.generator + ) # Battery self.rated_capacity_battery_kwh = 1200.0 @@ -157,8 +159,12 @@ def test_power_balance_calculation(self) -> None: dt = duration.sum() power_other = load_other[0] - gen_shaft_power, _ = self.generator.get_shaft_power_load_from_electric_power(power_other) - res_engine = self.genset.aux_engine.get_engine_run_point_from_power_out_kw(gen_shaft_power) + gen_shaft_power, _ = self.generator.get_shaft_power_load_from_electric_power( + power_other + ) + res_engine = self.genset.aux_engine.get_engine_run_point_from_power_out_kw( + gen_shaft_power + ) fc_kg = res_engine.fuel_flow_rate_kg_per_s.total_fuel_consumption * dt res = self.power_system.get_fuel_energy_consumption_running_time() self.assertAlmostEqual(fc_kg, res.fuel_consumption_total_kg) @@ -203,7 +209,9 @@ def test_run_simulation(self) -> None: time_interval_s=self.power_system.time_interval_s, integration_method=self.power_system.integration_method, ) - self.assertEqual(res.fuel_consumption_total_kg, hyd_consumption.total_fuel_consumption) + self.assertEqual( + res.fuel_consumption_total_kg, hyd_consumption.total_fuel_consumption + ) run_simulation( electric_power_system=self.power_system, @@ -220,7 +228,9 @@ def test_run_simulation(self) -> None: time_interval_s=self.power_system.time_interval_s, integration_method=self.power_system.integration_method, ) - self.assertEqual(res.fuel_consumption_total_kg, fuel_cons.total_fuel_consumption) + self.assertEqual( + res.fuel_consumption_total_kg, fuel_cons.total_fuel_consumption + ) def test_time_single_input_vs_multi_input(self) -> None: # Sets the load @@ -255,6 +265,8 @@ def sim_one_step(self, load_other: Union[float, np.ndarray], n: int) -> None: self.battery.load_sharing_mode = equal_load_sharing_vector # noinspection PyUnusedLocal - def sim_one_step_part_two(self, load_other: Union[float, np.ndarray], n: int) -> None: + def sim_one_step_part_two( + self, load_other: Union[float, np.ndarray], n: int + ) -> None: self.power_system.set_bus_tie_status_all(np.array([])) self.power_system.do_power_balance_calculation() diff --git a/feems/tests/test_utility_for_test.py b/feems/tests/test_utility_for_test.py index 86f1e18..a0cfcde 100644 --- a/feems/tests/test_utility_for_test.py +++ b/feems/tests/test_utility_for_test.py @@ -45,8 +45,10 @@ def test_create_switchboard_with_components(self): for _ in range(100): #: Set the random parameters for creating the switchboard component number_components = random.randint(4, 100) - number_components_list = get_list_random_distribution_numbers_for_total_number( - 4, number_components + number_components_list = ( + get_list_random_distribution_numbers_for_total_number( + 4, number_components + ) ) rated_power_avail = random.random() * 5000 rated_speed_max = random.random() * 1000 diff --git a/feems/tests/utility.py b/feems/tests/utility.py index 627dd2e..85f8523 100644 --- a/feems/tests/utility.py +++ b/feems/tests/utility.py @@ -36,7 +36,9 @@ ELECTRIC_MACHINE_EFF_CURVE = np.array([load, eff]).transpose() # Create an efficiency curve for an electric inverter -CONVERTER_EFF = np.array([[1.00, 0.75, 0.50, 0.25], [0.98, 0.972, 0.97, 0.96]]).transpose() +CONVERTER_EFF = np.array( + [[1.00, 0.75, 0.50, 0.25], [0.98, 0.972, 0.97, 0.96]] +).transpose() logger = get_logger(__name__) @@ -50,7 +52,9 @@ class PowerSummary(NamedTuple): # noinspection PyShadowingNames -def create_random_monotonic_eff_curve(min_efficiency_perc=0, max_efficiency_perc=1) -> np.ndarray: +def create_random_monotonic_eff_curve( + min_efficiency_perc=0, max_efficiency_perc=1 +) -> np.ndarray: assert ( max_efficiency_perc > min_efficiency_perc ), "maximum efficiency should be greater than minimum efficiency" @@ -60,7 +64,10 @@ def create_random_monotonic_eff_curve(min_efficiency_perc=0, max_efficiency_perc load_check = np.arange(0, 1.001, 0.001) while not monotonic: load = np.array([0.25, 0.50, 0.75, 1.00]) - eff = np.random.rand(4) * (max_efficiency_perc - min_efficiency_perc) + min_efficiency_perc + eff = ( + np.random.rand(4) * (max_efficiency_perc - min_efficiency_perc) + + min_efficiency_perc + ) eff.sort() # Check monotonic mapping interp_function = PchipInterpolator(load, eff, extrapolate=True) @@ -134,8 +141,12 @@ def create_components( for i in range(number_components): rated_power = np.random.rand() * rated_power_max rated_speed = np.random.rand() * rated_speed_max - type_ = TypeComponent(np.ceil(np.random.rand() * (len(TypeComponent.__members__) - 1))) - components.append(Component("{0}{1}".format(name, i), type_, rated_power, rated_speed)) + type_ = TypeComponent( + np.ceil(np.random.rand() * (len(TypeComponent.__members__) - 1)) + ) + components.append( + Component("{0}{1}".format(name, i), type_, rated_power, rated_speed) + ) if number_components == 1: components[0].name = name return components[0] @@ -146,7 +157,9 @@ def create_components( def create_basic_components( name, number_components, rated_power_max, rated_speed_max ) -> Union[BasicComponent, List[BasicComponent]]: - components = create_components(name, number_components, rated_power_max, rated_speed_max) + components = create_components( + name, number_components, rated_power_max, rated_speed_max + ) basic_components = [] if type(components) is list: for component in components: @@ -298,7 +311,9 @@ def create_a_propulsion_drive( pass -def create_engine_component(name, rated_power_max, rated_speed_max, bsfc_curve=None) -> Engine: +def create_engine_component( + name, rated_power_max, rated_speed_max, bsfc_curve=None +) -> Engine: # Create an engine component with a arbitrary bsfc curve rated_power = rated_power_max * np.random.rand() rated_speed = rated_speed_max * np.random.rand() @@ -308,7 +323,9 @@ def create_engine_component(name, rated_power_max, rated_speed_max, bsfc_curve=N np.random.rand(10, 1) * 200, axis=1, ) - logger.warning("Efficiency of engine is not supplied, using random monotonic curve") + logger.warning( + "Efficiency of engine is not supplied, using random monotonic curve" + ) return Engine( type_=TypeComponent.MAIN_ENGINE, name=name, @@ -320,7 +337,9 @@ def create_engine_component(name, rated_power_max, rated_speed_max, bsfc_curve=N # noinspection PyTypeChecker -def create_fuel_cell_system(name: str, rated_power: float, switchboard_id: int) -> FuelCellSystem: +def create_fuel_cell_system( + name: str, rated_power: float, switchboard_id: int +) -> FuelCellSystem: """ Create a fuel cell system with random monotonic efficiency :param name: name @@ -378,7 +397,9 @@ def create_genset_component( """ if eff_curve_gen is None: eff_curve_gen = create_random_monotonic_eff_curve() - logger.warning("Efficiency of generator is not supplied, using random monotonic curve") + logger.warning( + "Efficiency of generator is not supplied, using random monotonic curve" + ) # Create a generator component, if not provided or not proper component if generator is None or type(generator) is not ElectricMachine: @@ -413,7 +434,9 @@ def create_dataframe_save_and_return(name, filename, columns): # Create a DataFrame and save it to csv values = np.append(np.zeros([1, 1]), np.random.rand(1, len(columns) - 1), axis=1) eff_curve = create_random_monotonic_eff_curve() - columns_eff = ["Efficiency@{}%".format(each_load) for each_load in eff_curve[:, 0].tolist()] + columns_eff = [ + "Efficiency@{}%".format(each_load) for each_load in eff_curve[:, 0].tolist() + ] columns += columns_eff values = np.append(values, np.reshape(eff_curve[:, 1], (1, -1)), axis=1) df = pd.DataFrame(values, columns=columns, index=[name]) @@ -454,7 +477,9 @@ def create_switchboard_with_components( switchboard_id=switchboard_id, ) electric_components = power_sources + power_consumers + pti_ptos + battery_systems - return Switchboard(name="switchboard", idx=switchboard_id, components=electric_components) + return Switchboard( + name="switchboard", idx=switchboard_id, components=electric_components + ) def set_random_power_input_consumer_pti_pto_energy_storage( @@ -490,7 +515,9 @@ def set_random_power_input_consumer_pti_pto_energy_storage( # Assign the power input for the consumers, pti/pto, energy storage devices # randomly within the total power produced no_electric_load_switchboard = ( - switchboard.no_consumers + switchboard.no_pti_pto + switchboard.no_energy_storage + switchboard.no_consumers + + switchboard.no_pti_pto + + switchboard.no_energy_storage ) count_electric_load = 0 remaining_power = total_power_produced.copy() @@ -518,7 +545,9 @@ def set_random_power_input_consumer_pti_pto_energy_storage( / 100 ) if i in [TypePower.PTI_PTO.value, TypePower.ENERGY_STORAGE.value]: - component.power_input *= component.load_sharing_mode * component.status + component.power_input *= ( + component.load_sharing_mode * component.status + ) remaining_power -= component.power_input index_overload = remaining_power < 0 component.power_input[index_overload] += remaining_power[index_overload] @@ -526,14 +555,18 @@ def set_random_power_input_consumer_pti_pto_energy_storage( sum_power_input_power_consumer += component.power_input * ( i == TypePower.POWER_CONSUMER.value ) - sum_power_input_pti_pto += component.power_input * (i == TypePower.PTI_PTO.value) + sum_power_input_pti_pto += component.power_input * ( + i == TypePower.PTI_PTO.value + ) sum_power_input_energy_storage += component.power_input * ( i == TypePower.ENERGY_STORAGE.value ) # noinspection PyUnresolvedReferences if not np.isclose( total_power_produced, - sum_power_input_power_consumer + sum_power_input_pti_pto + sum_power_input_energy_storage, + sum_power_input_power_consumer + + sum_power_input_pti_pto + + sum_power_input_energy_storage, ).all(): msg = "Power balance is not met between the produced power and consumed power" logger.error(msg) @@ -555,7 +588,9 @@ def set_random_power_input_consumer_pti_pto_energy_storage( load_perc_symmetric_loaded_power_source = np.zeros( sum_power_avail_from_equally_load_sharing_sources.shape ) - index_no_power_available = sum_power_avail_from_equally_load_sharing_sources == 0 + index_no_power_available = ( + sum_power_avail_from_equally_load_sharing_sources == 0 + ) if np.bitwise_and( sum_power_output_from_equally_load_sharing_sources > 0, index_no_power_available, @@ -619,6 +654,7 @@ def create_electric_components_for_switchboard( TypeComponent.GENERATOR, TypeComponent.FUEL_CELL_SYSTEM, TypeComponent.GENSET, + TypeComponent.COGES, ] type_electric_power_consumer = [ TypeComponent.PROPULSION_DRIVE, @@ -645,7 +681,9 @@ def create_electric_components_for_switchboard( # Create a power source component if type_component == TypeComponent.FUEL_CELL_SYSTEM: # Create a fuel cell system - component = create_fuel_cell_system(name_component, rated_power[i], switchboard_id) + component = create_fuel_cell_system( + name_component, rated_power[i], switchboard_id + ) else: # Create a generator component component = ElectricMachine( @@ -750,6 +788,7 @@ def create_electric_components_for_switchboard( return electric_components + def create_cogas_system( rated_power_kw: float = 1000, rated_speed_rpm: float = 1000, @@ -768,7 +807,8 @@ def create_cogas_system( if steam_turbine_power_curve is None: steam_turbine_power_curve = create_random_monotonic_eff_curve() steam_turbine_power_curve[:, 1] = ( - steam_turbine_power_curve[:, 0] * rated_power_kw - gas_turbine_power_curve[:, 1] + steam_turbine_power_curve[:, 0] * rated_power_kw + - gas_turbine_power_curve[:, 1] ) return COGAS( name="COGAS", @@ -779,4 +819,4 @@ def create_cogas_system( steam_turbine_power_curve=steam_turbine_power_curve, fuel_type=fuel_type, fuel_origin=fuel_origin, - ) \ No newline at end of file + ) diff --git a/machinery-system-structure/00_ConvertToFeems.ipynb b/machinery-system-structure/00_ConvertToFeems.ipynb index 19d348f..f3d21c0 100644 --- a/machinery-system-structure/00_ConvertToFeems.ipynb +++ b/machinery-system-structure/00_ConvertToFeems.ipynb @@ -63,9 +63,10 @@ " PTIPTO,\n", " SuperCapacitor,\n", " FuelCell,\n", + " COGES,\n", ")\n", "from feems.components_model.component_electric import SerialSystemElectric, Genset\n", - "from feems.components_model.component_mechanical import EngineDualFuel\n", + "from feems.components_model.component_mechanical import COGAS, EngineDualFuel\n", "from feems.fuel import FuelOrigin, TypeFuel\n", "from feems.system_model import (\n", " ElectricPowerSystem,\n", @@ -97,15 +98,15 @@ " return np.array(list(map(convert_proto_point_to_list, curve.points)))\n", "\n", "\n", - "def convert_proto_efficiency_bsfc_to_np_array(\n", - " efficiency_bsfc: Union[proto.Efficiency, proto.BSFC]\n", + "def convert_proto_efficiency_bsfc_power_to_np_array(\n", + " efficiency_bsfc_power: Union[proto.Efficiency, proto.BSFC, proto.PowerCurve]\n", ") -> np.ndarray:\n", " \"\"\"Converts protobuf efficiency or bsfc to numpy array\"\"\"\n", - " if efficiency_bsfc.HasField(\"value\"):\n", - " if efficiency_bsfc.value > 0:\n", - " return np.array([efficiency_bsfc.value])\n", - " if efficiency_bsfc.HasField(\"curve\"):\n", - " return convert_proto_curve1d_to_np_array(efficiency_bsfc.curve.curve)\n", + " if efficiency_bsfc_power.HasField(\"value\"):\n", + " if efficiency_bsfc_power.value > 0:\n", + " return np.array([efficiency_bsfc_power.value])\n", + " if efficiency_bsfc_power.HasField(\"curve\"):\n", + " return convert_proto_curve1d_to_np_array(efficiency_bsfc_power.curve.curve)\n", " else:\n", " raise TypeError(\"The efficiency value or curve is not properly set.\")\n", "\n", @@ -120,7 +121,9 @@ " type_=component_type,\n", " name=proto_component.name,\n", " rated_power=proto_component.rated_power_kw,\n", - " eff_curve=convert_proto_efficiency_bsfc_to_np_array(proto_component.efficiency),\n", + " eff_curve=convert_proto_efficiency_bsfc_power_to_np_array(\n", + " proto_component.efficiency\n", + " ),\n", " power_type=power_type,\n", " switchboard_id=switchboard_id,\n", " )\n", @@ -138,7 +141,9 @@ " rated_power=proto_component.rated_power_kw,\n", " rated_speed=proto_component.rated_speed_rpm,\n", " power_type=power_type,\n", - " eff_curve=convert_proto_efficiency_bsfc_to_np_array(proto_component.efficiency),\n", + " eff_curve=convert_proto_efficiency_bsfc_power_to_np_array(\n", + " proto_component.efficiency\n", + " ),\n", " switchboard_id=switchboard_id,\n", " )\n", "\n", @@ -153,7 +158,7 @@ " fuel_cell = FuelCell(\n", " name=subsystem.fuel_cell.name,\n", " rated_power=subsystem.fuel_cell.rated_power_kw,\n", - " eff_curve=convert_proto_efficiency_bsfc_to_np_array(\n", + " eff_curve=convert_proto_efficiency_bsfc_power_to_np_array(\n", " subsystem.fuel_cell.efficiency\n", " ),\n", " fuel_type=TypeFuel(subsystem.fuel_cell.fuel.fuel_type),\n", @@ -188,13 +193,18 @@ " )\n", "\n", "\n", - "def convert_nox_calculation_method(proto_engine: proto.Engine) -> NOxCalculationMethod:\n", + "def convert_nox_calculation_method(\n", + " proto_comp: Union[proto.Engine, proto.COGAS]\n", + ") -> NOxCalculationMethod:\n", " \"\"\"Converts protobuf nox calculation type to feems nox calculation method\"\"\"\n", - " nox_calculation_method = NOxCalculationMethod.TIER_2\n", - " if proto_engine.nox_calculation_method is not None:\n", - " name = proto.Engine.NOxCalculationMethod.Name(\n", - " proto_engine.nox_calculation_method\n", - " )\n", + " if isinstance(proto_comp, proto.Engine):\n", + " nox_calculation_method = NOxCalculationMethod.TIER_2\n", + " elif isinstance(proto_comp, proto.COGAS):\n", + " nox_calculation_method = NOxCalculationMethod.TIER_3\n", + " else:\n", + " raise TypeError(\"The component should be either an engine or COGAS\")\n", + " if proto_comp.nox_calculation_method is not None:\n", + " name = proto.Engine.NOxCalculationMethod.Name(proto_comp.nox_calculation_method)\n", " nox_calculation_method = NOxCalculationMethod[name]\n", " return nox_calculation_method\n", "\n", @@ -219,8 +229,10 @@ " name=proto_engine.name,\n", " rated_power=proto_engine.rated_power_kw,\n", " rated_speed=proto_engine.rated_speed_rpm,\n", - " bsfc_curve=convert_proto_efficiency_bsfc_to_np_array(proto_engine.bsfc),\n", - " bspfc_curve=convert_proto_efficiency_bsfc_to_np_array(\n", + " bsfc_curve=convert_proto_efficiency_bsfc_power_to_np_array(\n", + " proto_engine.bsfc\n", + " ),\n", + " bspfc_curve=convert_proto_efficiency_bsfc_power_to_np_array(\n", " proto_engine.pilot_bsfc\n", " ),\n", " fuel_type=TypeFuel(proto_engine.main_fuel.fuel_type),\n", @@ -235,7 +247,7 @@ " name=proto_engine.name,\n", " rated_power=proto_engine.rated_power_kw,\n", " rated_speed=proto_engine.rated_speed_rpm,\n", - " bsfc_curve=convert_proto_efficiency_bsfc_to_np_array(proto_engine.bsfc),\n", + " bsfc_curve=convert_proto_efficiency_bsfc_power_to_np_array(proto_engine.bsfc),\n", " fuel_type=TypeFuel(proto_engine.main_fuel.fuel_type),\n", " fuel_origin=FuelOrigin(proto_engine.main_fuel.fuel_origin),\n", " nox_calculation_method=nox_calculation_method,\n", @@ -243,6 +255,39 @@ " )\n", "\n", "\n", + "def convert_proto_cogas_to_feems(\n", + " proto_cogas: proto.COGAS,\n", + ") -> Engine:\n", + " \"\"\"Converts protobuf COGAS message to feems COGAS component\"\"\"\n", + " nox_calculation_method = convert_nox_calculation_method(proto_cogas)\n", + " emission_curves = (\n", + " [\n", + " convert_emission_curve_to_feems(emission_curve)\n", + " for emission_curve in proto_cogas.emission_curves\n", + " ]\n", + " if proto_cogas.emission_curves\n", + " else None\n", + " )\n", + " return COGAS(\n", + " name=proto_cogas.name,\n", + " rated_power=proto_cogas.rated_power_kw,\n", + " rated_speed=proto_cogas.rated_speed_rpm,\n", + " eff_curve=convert_proto_efficiency_bsfc_power_to_np_array(\n", + " proto_cogas.efficiency\n", + " ),\n", + " gas_turbine_power_curve=convert_proto_efficiency_bsfc_power_to_np_array(\n", + " proto_cogas.gas_turbine_power_curve\n", + " ),\n", + " steam_turbine_power_curve=convert_proto_efficiency_bsfc_power_to_np_array(\n", + " proto_cogas.steam_turbine_power_curve\n", + " ),\n", + " fuel_type=TypeFuel(proto_cogas.fuel.fuel_type),\n", + " fuel_origin=FuelOrigin(proto_cogas.fuel.fuel_origin),\n", + " nox_calculation_method=nox_calculation_method,\n", + " emissions_curves=emission_curves,\n", + " )\n", + "\n", + "\n", "def convert_proto_genset_to_feems(\n", " subsystem: proto.Subsystem, switchboard_id: int\n", ") -> Genset:\n", @@ -267,6 +312,20 @@ " )\n", "\n", "\n", + "def convert_proto_coges_to_feems(\n", + " subsystem: proto.Subsystem, switchboard_id: int\n", + ") -> COGES:\n", + " \"\"\"Converts protobuf subsystem message to feems component\"\"\"\n", + " cogas = convert_proto_cogas_to_feems(proto_cogas == subsystem.cogas)\n", + " generator = convert_proto_electric_machine_to_feems(\n", + " proto_component=subsystem.electric_machine,\n", + " component_type=TypeComponent.SYNCHRONOUS_MACHINE,\n", + " power_type=TypePower.POWER_SOURCE,\n", + " switchboard_id=switchboard_id,\n", + " )\n", + " return COGES(name=subsystem.name, cogas=cogas, generator=generator)\n", + "\n", + "\n", "def convert_proto_battery_to_feems(\n", " proto_component: proto.Battery, switchboard_id: int = 0\n", ") -> Battery:\n", @@ -486,6 +545,12 @@ " subsystem=subsystem, switchboard_id=switchboard_id\n", " )\n", " )\n", + " elif subsystem.component_type == proto.Subsystem.ComponentType.COGES:\n", + " components.append(\n", + " convert_proto_coges_to_feems(\n", + " subsystem=subsystem, switchboard_id=switchboard_id\n", + " )\n", + " )\n", " elif subsystem.component_type == proto.Subsystem.ComponentType.BATTERY_SYSTEM:\n", " components.append(\n", " convert_proto_battery_system_to_feems(\n", @@ -565,8 +630,8 @@ " power_type=TypePower.POWER_TRANSMISSION,\n", " rated_power=sub_system.gear.rated_power_kw,\n", " rated_speed=sub_system.gear.rated_speed_rpm,\n", - " eff_curve=convert_proto_efficiency_bsfc_to_np_array(\n", - " efficiency_bsfc=sub_system.gear.efficiency\n", + " eff_curve=convert_proto_efficiency_bsfc_power_to_np_array(\n", + " efficiency_bsfc_power=sub_system.gear.efficiency\n", " ),\n", " ),\n", " shaft_line_id=shaft_line_id,\n", @@ -611,8 +676,8 @@ " shaft_line_id=shaft_line_id,\n", " rated_power=sub_system.rated_power_kw,\n", " rated_speed=sub_system.rated_speed_rpm,\n", - " eff_curve=convert_proto_efficiency_bsfc_to_np_array(\n", - " efficiency_bsfc=sub_system.propeller.efficiency\n", + " eff_curve=convert_proto_efficiency_bsfc_power_to_np_array(\n", + " efficiency_bsfc_power=sub_system.propeller.efficiency\n", " ),\n", " )\n", " )\n", @@ -659,10 +724,8 @@ "name": "stderr", "output_type": "stream", "text": [ - "2023-11-27 15:04:41,445 - tests.utility - WARNING - Efficiency of generator is not supplied, using random monotonic curve\n", - "2023-11-27 15:04:41,445 - tests.utility - WARNING - Efficiency of engine is not supplied, using random monotonic curve\n", - "2023-11-27 15:04:41,448 - tests.utility - WARNING - Efficiency of generator is not supplied, using random monotonic curve\n", - "2023-11-27 15:04:41,448 - tests.utility - WARNING - Efficiency of engine is not supplied, using random monotonic curve\n" + "2024-04-02 08:59:14,254 - tests.utility - WARNING - Efficiency of generator is not supplied, using random monotonic curve\n", + "2024-04-02 08:59:14,255 - tests.utility - WARNING - Efficiency of engine is not supplied, using random monotonic curve\n" ] } ], diff --git a/machinery-system-structure/01_ConvertToProtobuf.ipynb b/machinery-system-structure/01_ConvertToProtobuf.ipynb index 18465af..8593028 100644 --- a/machinery-system-structure/01_ConvertToProtobuf.ipynb +++ b/machinery-system-structure/01_ConvertToProtobuf.ipynb @@ -487,8 +487,8 @@ "subsystems {\n", " engine {\n", " name: \"Main engine 1\"\n", - " rated_power_kw: 5859.0016556055216\n", - " rated_speed_rpm: 994.47618733206048\n", + " rated_power_kw: 8928.5891111281962\n", + " rated_speed_rpm: 757.25205223143359\n", " bsfc {\n", " curve {\n", " x_label: \"power load\"\n", @@ -496,43 +496,43 @@ " curve {\n", " points {\n", " x: 0.1\n", - " y: 19.319933023361479\n", + " y: 6.2063818073176069\n", " }\n", " points {\n", " x: 0.2\n", - " y: 112.16731626254233\n", + " y: 147.44930059614524\n", " }\n", " points {\n", " x: 0.30000000000000004\n", - " y: 23.099504235318278\n", + " y: 80.3767374313949\n", " }\n", " points {\n", " x: 0.4\n", - " y: 60.638884895192049\n", + " y: 168.68185788463742\n", " }\n", " points {\n", " x: 0.5\n", - " y: 48.678858766795628\n", + " y: 91.67216439330204\n", " }\n", " points {\n", " x: 0.6\n", - " y: 77.979773772621641\n", + " y: 27.734180858941947\n", " }\n", " points {\n", " x: 0.70000000000000007\n", - " y: 33.609600342009728\n", + " y: 178.96619554803775\n", " }\n", " points {\n", " x: 0.8\n", - " y: 47.867957805787853\n", + " y: 40.071011135441182\n", " }\n", " points {\n", " x: 0.9\n", - " y: 29.022355258388167\n", + " y: 150.89138436839542\n", " }\n", " points {\n", " x: 1\n", - " y: 126.53478643090675\n", + " y: 183.40404671675364\n", " }\n", " }\n", " }\n", @@ -546,14 +546,14 @@ " power_type: POWER_SOURCE\n", " component_type: MAIN_ENGINE\n", " name: \"Main engine 1\"\n", - " rated_power_kw: 5859.0016556055216\n", - " rated_speed_rpm: 994.47618733206048\n", + " rated_power_kw: 8928.5891111281962\n", + " rated_speed_rpm: 757.25205223143359\n", "}\n", "subsystems {\n", " engine {\n", " name: \"Main engine 2\"\n", - " rated_power_kw: 4140.9983443944784\n", - " rated_speed_rpm: 730.75337196848716\n", + " rated_power_kw: 1071.410888871804\n", + " rated_speed_rpm: 277.5402084780776\n", " bsfc {\n", " curve {\n", " x_label: \"power load\"\n", @@ -561,43 +561,43 @@ " curve {\n", " points {\n", " x: 0.1\n", - " y: 99.481697364420427\n", + " y: 7.1034772854899009\n", " }\n", " points {\n", " x: 0.2\n", - " y: 0.75849419767459736\n", + " y: 54.196599242811729\n", " }\n", " points {\n", " x: 0.30000000000000004\n", - " y: 72.561045615745925\n", + " y: 191.49531882477234\n", " }\n", " points {\n", " x: 0.4\n", - " y: 8.8059955528814413\n", + " y: 106.06567400661282\n", " }\n", " points {\n", " x: 0.5\n", - " y: 61.617747183877135\n", + " y: 139.09154958668273\n", " }\n", " points {\n", " x: 0.6\n", - " y: 136.75447792989968\n", + " y: 2.7341335186296334\n", " }\n", " points {\n", " x: 0.70000000000000007\n", - " y: 158.08253549593388\n", + " y: 53.274249103030428\n", " }\n", " points {\n", " x: 0.8\n", - " y: 196.49408174353528\n", + " y: 7.6576675627555879\n", " }\n", " points {\n", " x: 0.9\n", - " y: 12.318035652507398\n", + " y: 76.363701229970673\n", " }\n", " points {\n", " x: 1\n", - " y: 24.045199398216077\n", + " y: 113.37653306310338\n", " }\n", " }\n", " }\n", @@ -611,13 +611,13 @@ " power_type: POWER_SOURCE\n", " component_type: MAIN_ENGINE\n", " name: \"Main engine 2\"\n", - " rated_power_kw: 4140.9983443944784\n", - " rated_speed_rpm: 730.75337196848716\n", + " rated_power_kw: 1071.410888871804\n", + " rated_speed_rpm: 277.5402084780776\n", "}\n", "subsystems {\n", " gear {\n", " name: \"Gear 1\"\n", - " rated_power_kw: 9999.9999999999982\n", + " rated_power_kw: 10000\n", " rated_speed_rpm: 1000\n", " efficiency {\n", " curve {\n", @@ -683,7 +683,7 @@ " electric_machine {\n", " name: \"synchronous machine\"\n", " rated_power_kw: 10000\n", - " rated_speed_rpm: 408.34215035368794\n", + " rated_speed_rpm: 268.85769655199942\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -783,8 +783,9 @@ " component_type: PTI_PTO_SYSTEM\n", " name: \"PTI/PTO 1\"\n", " rated_power_kw: 10000\n", - " rated_speed_rpm: 408.34215035368794\n", - "}\n" + " rated_speed_rpm: 268.85769655199942\n", + "}\n", + "\n" ] } ], @@ -918,18 +919,6 @@ "execution_count": null, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2023-11-27 15:04:20,468 - tests.utility - WARNING - Efficiency of generator is not supplied, using random monotonic curve\n", - "2023-11-27 15:04:20,468 - tests.utility - WARNING - Efficiency of engine is not supplied, using random monotonic curve\n", - "2023-11-27 15:04:20,482 - tests.utility - WARNING - Efficiency of generator is not supplied, using random monotonic curve\n", - "2023-11-27 15:04:20,483 - tests.utility - WARNING - Efficiency of engine is not supplied, using random monotonic curve\n", - "2023-11-27 15:04:20,485 - tests.utility - WARNING - Efficiency of generator is not supplied, using random monotonic curve\n", - "2023-11-27 15:04:20,485 - tests.utility - WARNING - Efficiency of engine is not supplied, using random monotonic curve\n" - ] - }, { "name": "stdout", "output_type": "stream", @@ -943,7 +932,7 @@ " engine {\n", " name: \"Main engine 1\"\n", " rated_power_kw: 10000\n", - " rated_speed_rpm: 952.98559560399542\n", + " rated_speed_rpm: 616.299232833948\n", " bsfc {\n", " curve {\n", " x_label: \"power load\"\n", @@ -951,43 +940,43 @@ " curve {\n", " points {\n", " x: 0.1\n", - " y: 41.572729151082008\n", + " y: 158.66714790551916\n", " }\n", " points {\n", " x: 0.2\n", - " y: 105.88714628085762\n", + " y: 154.41330499203636\n", " }\n", " points {\n", " x: 0.30000000000000004\n", - " y: 150.11478926479333\n", + " y: 196.625139992027\n", " }\n", " points {\n", " x: 0.4\n", - " y: 197.5465115992514\n", + " y: 96.345260976504576\n", " }\n", " points {\n", " x: 0.5\n", - " y: 67.932055130502533\n", + " y: 114.8119354266663\n", " }\n", " points {\n", " x: 0.6\n", - " y: 142.10722200377813\n", + " y: 123.10509932525309\n", " }\n", " points {\n", " x: 0.70000000000000007\n", - " y: 141.59564830141608\n", + " y: 199.78791423581728\n", " }\n", " points {\n", " x: 0.8\n", - " y: 88.486030034168266\n", + " y: 191.52941614115804\n", " }\n", " points {\n", " x: 0.9\n", - " y: 4.71289627725322\n", + " y: 154.02757904149783\n", " }\n", " points {\n", " x: 1\n", - " y: 156.85995053720987\n", + " y: 31.905281061288161\n", " }\n", " }\n", " }\n", @@ -1002,7 +991,7 @@ " component_type: MAIN_ENGINE\n", " name: \"Main engine 1\"\n", " rated_power_kw: 10000\n", - " rated_speed_rpm: 952.98559560399542\n", + " rated_speed_rpm: 616.299232833948\n", " }\n", " subsystems {\n", " gear {\n", @@ -1066,14 +1055,14 @@ " power_type: POWER_CONSUMER\n", " component_type: PROPELLER_LOAD\n", " name: \"Propeller 1\"\n", - " rated_power_kw: 7999.9999999999991\n", + " rated_power_kw: 8000\n", " rated_speed_rpm: 1000\n", " }\n", " subsystems {\n", " electric_machine {\n", " name: \"synchronous machine\"\n", " rated_power_kw: 10000\n", - " rated_speed_rpm: 932.0083985240334\n", + " rated_speed_rpm: 306.53749338761281\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1173,7 +1162,7 @@ " component_type: PTI_PTO_SYSTEM\n", " name: \"PTI/PTO 1\"\n", " rated_power_kw: 10000\n", - " rated_speed_rpm: 932.0083985240334\n", + " rated_speed_rpm: 306.53749338761281\n", " }\n", " }\n", "}\n", @@ -1181,10 +1170,9 @@ " switchboards {\n", " switchboard_id: 1\n", " subsystems {\n", - " electric_machine {\n", - " name: \"GENERATOR 1\"\n", - " rated_power_kw: 4246.7830711147508\n", - " rated_speed_rpm: 1.9718733686283629\n", + " converter1 {\n", + " name: \"converter\"\n", + " rated_power_kw: 2478.360583366918\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1192,93 +1180,69 @@ " curve {\n", " points {\n", " x: 0.25\n", - " y: 0.9298900684\n", + " y: 0.39658962019277733\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.9533974336\n", + " y: 0.539599941033186\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.9595580564\n", + " y: 0.70817786684293083\n", " }\n", " points {\n", " x: 1\n", - " y: 0.9585018015\n", + " y: 0.82374339944754993\n", " }\n", " }\n", " }\n", " }\n", " order_from_switchboard_or_shaftline: 1\n", " }\n", - " power_type: POWER_SOURCE\n", - " component_type: GENERATOR\n", - " name: \"GENERATOR 1\"\n", - " rated_power_kw: 4246.7830711147508\n", - " rated_speed_rpm: 1.9718733686283629\n", - " }\n", - " subsystems {\n", - " engine {\n", - " name: \"engine for GENERATOR 2\"\n", - " rated_power_kw: 762.72043121497654\n", - " rated_speed_rpm: 82.181891969488746\n", - " bsfc {\n", + " fuel_cell {\n", + " name: \"fuel cell\"\n", + " rated_power_kw: 3008.6560754587535\n", + " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", - " y_label: \"bsfc\"\n", + " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " x: 0.1\n", - " y: 122.24760431508813\n", - " }\n", - " points {\n", - " x: 0.2\n", - " y: 4.5207785314941962\n", - " }\n", - " points {\n", - " x: 0.30000000000000004\n", - " y: 40.561080066859169\n", - " }\n", - " points {\n", - " x: 0.4\n", - " y: 94.047744437945127\n", + " x: 0.25\n", + " y: 0.42407002602039845\n", " }\n", " points {\n", " x: 0.5\n", - " y: 2.9474651983155686\n", + " y: 0.63525308468590069\n", " }\n", " points {\n", - " x: 0.6\n", - " y: 164.77139339094191\n", - " }\n", - " points {\n", - " x: 0.70000000000000007\n", - " y: 91.890382564920642\n", - " }\n", - " points {\n", - " x: 0.8\n", - " y: 101.41924625609195\n", - " }\n", - " points {\n", - " x: 0.9\n", - " y: 57.496785670449469\n", + " x: 0.75\n", + " y: 0.730976185427855\n", " }\n", " points {\n", " x: 1\n", - " y: 7.3867204776746576\n", + " y: 0.8851266070777779\n", " }\n", " }\n", " }\n", " }\n", - " main_fuel {\n", - " fuel_origin: FOSSIL\n", - " }\n", " order_from_switchboard_or_shaftline: 2\n", + " fuel {\n", + " fuel_type: HYDROGEN\n", + " fuel_origin: RENEWABLE_NON_BIO\n", + " }\n", + " number_modules: 1\n", " }\n", + " power_type: POWER_SOURCE\n", + " component_type: FUEL_CELL_SYSTEM\n", + " name: \"FUEL_CELL_SYSTEM 1\"\n", + " rated_power_kw: 2478.360583366918\n", + " }\n", + " subsystems {\n", " electric_machine {\n", - " name: \"GENERATOR 2\"\n", - " rated_power_kw: 1746.4751655242026\n", - " rated_speed_rpm: 260.66525583762126\n", + " name: \"FUEL_CELL_SYSTEM 2\"\n", + " rated_power_kw: 2837.2745920810949\n", + " rated_speed_rpm: 587.751846606595\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1306,16 +1270,16 @@ " order_from_switchboard_or_shaftline: 1\n", " }\n", " power_type: POWER_SOURCE\n", - " component_type: GENSET\n", - " name: \"GENERATOR 2\"\n", - " rated_power_kw: 1746.4751655242026\n", - " rated_speed_rpm: 260.66525583762126\n", + " component_type: GENERATOR\n", + " name: \"FUEL_CELL_SYSTEM 2\"\n", + " rated_power_kw: 2837.2745920810949\n", + " rated_speed_rpm: 587.751846606595\n", " }\n", " subsystems {\n", " electric_machine {\n", " name: \"electric motor for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1355.6780844933076\n", - " rated_speed_rpm: 549.24684270995385\n", + " rated_power_kw: 1304.5108462673925\n", + " rated_speed_rpm: 247.59339459832464\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1344,7 +1308,7 @@ " }\n", " transformer {\n", " name: \"transformer for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1355.6780844933076\n", + " rated_power_kw: 1304.5108462673925\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1364,7 +1328,7 @@ " }\n", " converter1 {\n", " name: \"frequency converter for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1355.6780844933076\n", + " rated_power_kw: 1304.5108462673925\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1394,186 +1358,66 @@ " power_type: POWER_CONSUMER\n", " component_type: PROPULSION_DRIVE\n", " name: \"PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1355.6780844933076\n", - " rated_speed_rpm: 549.24684270995385\n", + " rated_power_kw: 1304.5108462673925\n", + " rated_speed_rpm: 247.59339459832464\n", " }\n", " subsystems {\n", - " electric_machine {\n", - " name: \"electric motor for PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 1524.8394415027562\n", - " rated_speed_rpm: 630.89107543934745\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 3\n", - " }\n", - " transformer {\n", - " name: \"transformer for PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 1524.8394415027562\n", + " other_load {\n", + " name: \"PROPULSION_DRIVE 2\"\n", + " rated_power_kw: 1965.5775291856264\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " y: 98.5\n", + " y: 1\n", " }\n", " points {\n", " x: 1\n", - " y: 98.5\n", + " y: 1\n", " }\n", " }\n", " }\n", " }\n", " order_from_switchboard_or_shaftline: 1\n", " }\n", - " converter1 {\n", - " name: \"frequency converter for PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 1524.8394415027562\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.96\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.97\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.972\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.98\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", " power_type: POWER_CONSUMER\n", - " component_type: PROPULSION_DRIVE\n", + " component_type: OTHER_LOAD\n", " name: \"PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 1524.8394415027562\n", - " rated_speed_rpm: 630.89107543934745\n", + " rated_power_kw: 1965.5775291856264\n", " }\n", " subsystems {\n", - " electric_machine {\n", - " name: \"electric motor for PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 1913.4824740039364\n", - " rated_speed_rpm: 388.69906817541823\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 3\n", - " }\n", - " transformer {\n", - " name: \"transformer for PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 1913.4824740039364\n", + " other_load {\n", + " name: \"PROPULSION_DRIVE 3\"\n", + " rated_power_kw: 981.91162454698087\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " y: 98.5\n", + " y: 1\n", " }\n", " points {\n", " x: 1\n", - " y: 98.5\n", + " y: 1\n", " }\n", " }\n", " }\n", " }\n", " order_from_switchboard_or_shaftline: 1\n", " }\n", - " converter1 {\n", - " name: \"frequency converter for PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 1913.4824740039364\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.96\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.97\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.972\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.98\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", " power_type: POWER_CONSUMER\n", - " component_type: PROPULSION_DRIVE\n", + " component_type: OTHER_LOAD\n", " name: \"PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 1913.4824740039364\n", - " rated_speed_rpm: 388.69906817541823\n", + " rated_power_kw: 981.91162454698087\n", " }\n", " subsystems {\n", " electric_machine {\n", " name: \"synchronous machine\"\n", - " rated_power_kw: 5385.4781447722225\n", - " rated_speed_rpm: 14.1221339982166\n", + " rated_power_kw: 3299.5955115740144\n", + " rated_speed_rpm: 601.56852217300229\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1602,7 +1446,7 @@ " }\n", " transformer {\n", " name: \"transformer\"\n", - " rated_power_kw: 5385.4781447722225\n", + " rated_power_kw: 3299.5955115740144\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1622,7 +1466,7 @@ " }\n", " converter1 {\n", " name: \"inverter\"\n", - " rated_power_kw: 5385.4781447722225\n", + " rated_power_kw: 3299.5955115740144\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1672,13 +1516,13 @@ " power_type: PTI_PTO\n", " component_type: PTI_PTO_SYSTEM\n", " name: \"PTI/PTO 1\"\n", - " rated_power_kw: 5385.4781447722225\n", - " rated_speed_rpm: 14.1221339982166\n", + " rated_power_kw: 3299.5955115740144\n", + " rated_speed_rpm: 601.56852217300229\n", " }\n", " subsystems {\n", " converter1 {\n", " name: \"converter\"\n", - " rated_power_kw: 5006.4327652411384\n", + " rated_power_kw: 4613.0155516838131\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1686,19 +1530,19 @@ " curve {\n", " points {\n", " x: 0.25\n", - " y: 0.57373711859618759\n", + " y: 0.5518640554898997\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.65808239216730369\n", + " y: 0.67070500646476172\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.7728533048132753\n", + " y: 0.67421411362430506\n", " }\n", " points {\n", " x: 1\n", - " y: 0.84908371184265941\n", + " y: 0.69163273193574792\n", " }\n", " }\n", " }\n", @@ -1707,7 +1551,7 @@ " }\n", " battery {\n", " name: \"battery\"\n", - " energy_capacity_kwh: 1668.8109217470462\n", + " energy_capacity_kwh: 1537.671850561271\n", " rated_charging_rate_c: 3\n", " rated_discharging_rate_c: 3\n", " efficiency_charging: 0.975\n", @@ -1718,7 +1562,7 @@ " power_type: ENERGY_STORAGE\n", " component_type: BATTERY_SYSTEM\n", " name: \"ENERGY_STORAGE_SYSTEM 1\"\n", - " rated_power_kw: 5006.4327652411384\n", + " rated_power_kw: 4613.0155516838131\n", " }\n", " }\n", " switchboards {\n", @@ -1726,7 +1570,7 @@ " subsystems {\n", " converter1 {\n", " name: \"converter\"\n", - " rated_power_kw: 178.42495105323133\n", + " rated_power_kw: 350.92845355013145\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1734,19 +1578,19 @@ " curve {\n", " points {\n", " x: 0.25\n", - " y: 0.47579388165032177\n", + " y: 0.39234020323749053\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.76628226758532292\n", + " y: 0.4445901241124709\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.81270033442339251\n", + " y: 0.58466686732150608\n", " }\n", " points {\n", " x: 1\n", - " y: 0.97311997368776393\n", + " y: 0.68170315983594909\n", " }\n", " }\n", " }\n", @@ -1755,7 +1599,7 @@ " }\n", " fuel_cell {\n", " name: \"fuel cell\"\n", - " rated_power_kw: 183.35349790125764\n", + " rated_power_kw: 514.78190835228327\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1763,19 +1607,19 @@ " curve {\n", " points {\n", " x: 0.25\n", - " y: 0.38804739713355241\n", + " y: 0.18588681520327377\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.57069416595018008\n", + " y: 0.30448788802681792\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.80957826677556533\n", + " y: 0.44492898642703704\n", " }\n", " points {\n", " x: 1\n", - " y: 0.90184721158818681\n", + " y: 0.54462828184152035\n", " }\n", " }\n", " }\n", @@ -1790,13 +1634,12 @@ " power_type: POWER_SOURCE\n", " component_type: FUEL_CELL_SYSTEM\n", " name: \"FUEL_CELL_SYSTEM 1\"\n", - " rated_power_kw: 178.42495105323133\n", + " rated_power_kw: 350.92845355013145\n", " }\n", " subsystems {\n", - " electric_machine {\n", - " name: \"FUEL_CELL_SYSTEM 2\"\n", - " rated_power_kw: 94.142390992004351\n", - " rated_speed_rpm: 112.95285394398869\n", + " converter1 {\n", + " name: \"converter\"\n", + " rated_power_kw: 97.31378768437628\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1804,62 +1647,155 @@ " curve {\n", " points {\n", " x: 0.25\n", - " y: 0.9298900684\n", + " y: 0.63360764741943176\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.9533974336\n", + " y: 0.7745552768635372\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.9595580564\n", + " y: 0.87698385048591632\n", " }\n", " points {\n", " x: 1\n", - " y: 0.9585018015\n", + " y: 0.99686680463166943\n", " }\n", " }\n", " }\n", " }\n", " order_from_switchboard_or_shaftline: 1\n", " }\n", + " fuel_cell {\n", + " name: \"fuel cell\"\n", + " rated_power_kw: 97.619649116847242\n", + " efficiency {\n", + " curve {\n", + " x_label: \"power load\"\n", + " y_label: \"efficiency\"\n", + " curve {\n", + " points {\n", + " x: 0.25\n", + " y: 0.58116482316103946\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 0.70209436632147126\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 0.85810821076510113\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 0.93084143159087518\n", + " }\n", + " }\n", + " }\n", + " }\n", + " order_from_switchboard_or_shaftline: 2\n", + " fuel {\n", + " fuel_type: HYDROGEN\n", + " fuel_origin: RENEWABLE_NON_BIO\n", + " }\n", + " number_modules: 1\n", + " }\n", " power_type: POWER_SOURCE\n", - " component_type: GENERATOR\n", + " component_type: FUEL_CELL_SYSTEM\n", " name: \"FUEL_CELL_SYSTEM 2\"\n", - " rated_power_kw: 94.142390992004351\n", - " rated_speed_rpm: 112.95285394398869\n", + " rated_power_kw: 97.31378768437628\n", " }\n", " subsystems {\n", - " other_load {\n", - " name: \"OTHER_LOAD 1\"\n", - " rated_power_kw: 67.298436423081611\n", + " electric_machine {\n", + " name: \"electric motor for PROPULSION_DRIVE 1\"\n", + " rated_power_kw: 139.5828857931466\n", + " rated_speed_rpm: 410.18228386091351\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " y: 1\n", + " x: 0.25\n", + " y: 0.9298900684\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 0.9533974336\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 0.9595580564\n", " }\n", " points {\n", " x: 1\n", - " y: 1\n", + " y: 0.9585018015\n", + " }\n", + " }\n", + " }\n", + " }\n", + " order_from_switchboard_or_shaftline: 3\n", + " }\n", + " transformer {\n", + " name: \"transformer for PROPULSION_DRIVE 1\"\n", + " rated_power_kw: 139.5828857931466\n", + " efficiency {\n", + " curve {\n", + " x_label: \"power load\"\n", + " y_label: \"efficiency\"\n", + " curve {\n", + " points {\n", + " y: 98.5\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 98.5\n", " }\n", " }\n", " }\n", " }\n", " order_from_switchboard_or_shaftline: 1\n", " }\n", + " converter1 {\n", + " name: \"frequency converter for PROPULSION_DRIVE 1\"\n", + " rated_power_kw: 139.5828857931466\n", + " efficiency {\n", + " curve {\n", + " x_label: \"power load\"\n", + " y_label: \"efficiency\"\n", + " curve {\n", + " points {\n", + " x: 0.25\n", + " y: 0.96\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 0.97\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 0.972\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 0.98\n", + " }\n", + " }\n", + " }\n", + " }\n", + " order_from_switchboard_or_shaftline: 2\n", + " }\n", " power_type: POWER_CONSUMER\n", - " component_type: OTHER_LOAD\n", - " name: \"OTHER_LOAD 1\"\n", - " rated_power_kw: 67.298436423081611\n", + " component_type: PROPULSION_DRIVE\n", + " name: \"PROPULSION_DRIVE 1\"\n", + " rated_power_kw: 139.5828857931466\n", + " rated_speed_rpm: 410.18228386091351\n", " }\n", " subsystems {\n", " electric_machine {\n", - " name: \"electric motor for OTHER_LOAD 2\"\n", - " rated_power_kw: 66.204242666538363\n", - " rated_speed_rpm: 798.03854172043464\n", + " name: \"electric motor for PROPULSION_DRIVE 2\"\n", + " rated_power_kw: 160.0693093051575\n", + " rated_speed_rpm: 276.35372580530827\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1887,8 +1823,8 @@ " order_from_switchboard_or_shaftline: 3\n", " }\n", " transformer {\n", - " name: \"transformer for OTHER_LOAD 2\"\n", - " rated_power_kw: 66.204242666538363\n", + " name: \"transformer for PROPULSION_DRIVE 2\"\n", + " rated_power_kw: 160.0693093051575\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1907,8 +1843,8 @@ " order_from_switchboard_or_shaftline: 1\n", " }\n", " converter1 {\n", - " name: \"frequency converter for OTHER_LOAD 2\"\n", - " rated_power_kw: 66.204242666538363\n", + " name: \"frequency converter for PROPULSION_DRIVE 2\"\n", + " rated_power_kw: 160.0693093051575\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1937,15 +1873,15 @@ " }\n", " power_type: POWER_CONSUMER\n", " component_type: PROPULSION_DRIVE\n", - " name: \"OTHER_LOAD 2\"\n", - " rated_power_kw: 66.204242666538363\n", - " rated_speed_rpm: 798.03854172043464\n", + " name: \"PROPULSION_DRIVE 2\"\n", + " rated_power_kw: 160.0693093051575\n", + " rated_speed_rpm: 276.35372580530827\n", " }\n", " subsystems {\n", " electric_machine {\n", - " name: \"electric motor for OTHER_LOAD 3\"\n", - " rated_power_kw: 84.497320910380026\n", - " rated_speed_rpm: 258.60326181565296\n", + " name: \"electric motor for PROPULSION_DRIVE 3\"\n", + " rated_power_kw: 58.347804901695874\n", + " rated_speed_rpm: 814.990008599895\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1973,8 +1909,8 @@ " order_from_switchboard_or_shaftline: 3\n", " }\n", " transformer {\n", - " name: \"transformer for OTHER_LOAD 3\"\n", - " rated_power_kw: 84.497320910380026\n", + " name: \"transformer for PROPULSION_DRIVE 3\"\n", + " rated_power_kw: 58.347804901695874\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -1993,8 +1929,8 @@ " order_from_switchboard_or_shaftline: 1\n", " }\n", " converter1 {\n", - " name: \"frequency converter for OTHER_LOAD 3\"\n", - " rated_power_kw: 84.497320910380026\n", + " name: \"frequency converter for PROPULSION_DRIVE 3\"\n", + " rated_power_kw: 58.347804901695874\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2023,15 +1959,15 @@ " }\n", " power_type: POWER_CONSUMER\n", " component_type: PROPULSION_DRIVE\n", - " name: \"OTHER_LOAD 3\"\n", - " rated_power_kw: 84.497320910380026\n", - " rated_speed_rpm: 258.60326181565296\n", + " name: \"PROPULSION_DRIVE 3\"\n", + " rated_power_kw: 58.347804901695874\n", + " rated_speed_rpm: 814.990008599895\n", " }\n", " subsystems {\n", " electric_machine {\n", " name: \"synchronous machine\"\n", - " rated_power_kw: 131.84085521853956\n", - " rated_speed_rpm: 7.1460824103999343\n", + " rated_power_kw: 72.625012684428867\n", + " rated_speed_rpm: 986.50786379117676\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2060,7 +1996,7 @@ " }\n", " transformer {\n", " name: \"transformer\"\n", - " rated_power_kw: 131.84085521853956\n", + " rated_power_kw: 72.625012684428867\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2080,7 +2016,7 @@ " }\n", " converter1 {\n", " name: \"inverter\"\n", - " rated_power_kw: 131.84085521853956\n", + " rated_power_kw: 72.625012684428867\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2130,13 +2066,13 @@ " power_type: PTI_PTO\n", " component_type: PTI_PTO_SYSTEM\n", " name: \"PTI/PTO 1\"\n", - " rated_power_kw: 131.84085521853956\n", - " rated_speed_rpm: 7.1460824103999343\n", + " rated_power_kw: 72.625012684428867\n", + " rated_speed_rpm: 986.50786379117676\n", " }\n", " subsystems {\n", " converter1 {\n", " name: \"converter\"\n", - " rated_power_kw: 32.202835907757169\n", + " rated_power_kw: 45.693712045406443\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2144,19 +2080,19 @@ " curve {\n", " points {\n", " x: 0.25\n", - " y: 0.55814944337323635\n", + " y: 0.49644053235563845\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.72674232945433692\n", + " y: 0.649135448857771\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.91265270793736264\n", + " y: 0.8029874550411582\n", " }\n", " points {\n", " x: 1\n", - " y: 0.98200537083746542\n", + " y: 0.82088292986119216\n", " }\n", " }\n", " }\n", @@ -2165,7 +2101,7 @@ " }\n", " battery {\n", " name: \"battery\"\n", - " energy_capacity_kwh: 10.734278635919056\n", + " energy_capacity_kwh: 15.231237348468815\n", " rated_charging_rate_c: 3\n", " rated_discharging_rate_c: 3\n", " efficiency_charging: 0.975\n", @@ -2176,73 +2112,16 @@ " power_type: ENERGY_STORAGE\n", " component_type: BATTERY_SYSTEM\n", " name: \"ENERGY_STORAGE_SYSTEM 1\"\n", - " rated_power_kw: 32.202835907757169\n", + " rated_power_kw: 45.693712045406443\n", " }\n", " }\n", " switchboards {\n", " switchboard_id: 3\n", " subsystems {\n", - " engine {\n", - " name: \"engine for GENSET 1\"\n", - " rated_power_kw: 1038.3838718684081\n", - " rated_speed_rpm: 32.558144879215313\n", - " bsfc {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"bsfc\"\n", - " curve {\n", - " points {\n", - " x: 0.1\n", - " y: 154.14442128334628\n", - " }\n", - " points {\n", - " x: 0.2\n", - " y: 120.68216012178561\n", - " }\n", - " points {\n", - " x: 0.30000000000000004\n", - " y: 155.95454069997837\n", - " }\n", - " points {\n", - " x: 0.4\n", - " y: 66.726009725380038\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 104.9722658588184\n", - " }\n", - " points {\n", - " x: 0.6\n", - " y: 48.418645500327706\n", - " }\n", - " points {\n", - " x: 0.70000000000000007\n", - " y: 53.135165424066777\n", - " }\n", - " points {\n", - " x: 0.8\n", - " y: 44.666755079490741\n", - " }\n", - " points {\n", - " x: 0.9\n", - " y: 110.96437100258412\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 63.6100509381871\n", - " }\n", - " }\n", - " }\n", - " }\n", - " main_fuel {\n", - " fuel_origin: FOSSIL\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", " electric_machine {\n", - " name: \"GENSET 1\"\n", - " rated_power_kw: 1081.0036574897281\n", - " rated_speed_rpm: 323.64324956298896\n", + " name: \"GENERATOR 1\"\n", + " rated_power_kw: 3550.0781297114218\n", + " rated_speed_rpm: 557.855996224465\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2270,73 +2149,16 @@ " order_from_switchboard_or_shaftline: 1\n", " }\n", " power_type: POWER_SOURCE\n", - " component_type: GENSET\n", - " name: \"GENSET 1\"\n", - " rated_power_kw: 1081.0036574897281\n", - " rated_speed_rpm: 323.64324956298896\n", + " component_type: GENERATOR\n", + " name: \"GENERATOR 1\"\n", + " rated_power_kw: 3550.0781297114218\n", + " rated_speed_rpm: 557.855996224465\n", " }\n", " subsystems {\n", - " engine {\n", - " name: \"engine for GENSET 2\"\n", - " rated_power_kw: 1253.7481954490083\n", - " rated_speed_rpm: 14.188671548567033\n", - " bsfc {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"bsfc\"\n", - " curve {\n", - " points {\n", - " x: 0.1\n", - " y: 90.864604244845992\n", - " }\n", - " points {\n", - " x: 0.2\n", - " y: 75.551906614092118\n", - " }\n", - " points {\n", - " x: 0.30000000000000004\n", - " y: 89.007572085071374\n", - " }\n", - " points {\n", - " x: 0.4\n", - " y: 9.57842718769295\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 58.054683450306513\n", - " }\n", - " points {\n", - " x: 0.6\n", - " y: 27.274943600691071\n", - " }\n", - " points {\n", - " x: 0.70000000000000007\n", - " y: 12.719758944447079\n", - " }\n", - " points {\n", - " x: 0.8\n", - " y: 167.22996723949731\n", - " }\n", - " points {\n", - " x: 0.9\n", - " y: 179.63970203545497\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 10.786215441462321\n", - " }\n", - " }\n", - " }\n", - " }\n", - " main_fuel {\n", - " fuel_origin: FOSSIL\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", " electric_machine {\n", - " name: \"GENSET 2\"\n", - " rated_power_kw: 1841.5572144979835\n", - " rated_speed_rpm: 887.51613806861474\n", + " name: \"GENERATOR 2\"\n", + " rated_power_kw: 4286.7328846113805\n", + " rated_speed_rpm: 618.65695022029115\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2364,16 +2186,16 @@ " order_from_switchboard_or_shaftline: 1\n", " }\n", " power_type: POWER_SOURCE\n", - " component_type: GENSET\n", - " name: \"GENSET 2\"\n", - " rated_power_kw: 1841.5572144979835\n", - " rated_speed_rpm: 887.51613806861474\n", + " component_type: GENERATOR\n", + " name: \"GENERATOR 2\"\n", + " rated_power_kw: 4286.7328846113805\n", + " rated_speed_rpm: 618.65695022029115\n", " }\n", " subsystems {\n", " electric_machine {\n", " name: \"electric motor for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 686.85771386931913\n", - " rated_speed_rpm: 502.1483048834715\n", + " rated_power_kw: 1536.6482828656267\n", + " rated_speed_rpm: 273.38089702409417\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2402,7 +2224,7 @@ " }\n", " transformer {\n", " name: \"transformer for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 686.85771386931913\n", + " rated_power_kw: 1536.6482828656267\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2422,7 +2244,7 @@ " }\n", " converter1 {\n", " name: \"frequency converter for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 686.85771386931913\n", + " rated_power_kw: 1536.6482828656267\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2452,14 +2274,40 @@ " power_type: POWER_CONSUMER\n", " component_type: PROPULSION_DRIVE\n", " name: \"PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 686.85771386931913\n", - " rated_speed_rpm: 502.1483048834715\n", + " rated_power_kw: 1536.6482828656267\n", + " rated_speed_rpm: 273.38089702409417\n", + " }\n", + " subsystems {\n", + " other_load {\n", + " name: \"PROPULSION_DRIVE 2\"\n", + " rated_power_kw: 539.11065501196254\n", + " efficiency {\n", + " curve {\n", + " x_label: \"power load\"\n", + " y_label: \"efficiency\"\n", + " curve {\n", + " points {\n", + " y: 1\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 1\n", + " }\n", + " }\n", + " }\n", + " }\n", + " order_from_switchboard_or_shaftline: 1\n", + " }\n", + " power_type: POWER_CONSUMER\n", + " component_type: OTHER_LOAD\n", + " name: \"PROPULSION_DRIVE 2\"\n", + " rated_power_kw: 539.11065501196254\n", " }\n", " subsystems {\n", " electric_machine {\n", - " name: \"electric motor for PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 954.64412117539189\n", - " rated_speed_rpm: 3.8629660705404856\n", + " name: \"electric motor for PROPULSION_DRIVE 3\"\n", + " rated_power_kw: 4193.2410621224117\n", + " rated_speed_rpm: 329.28206483221788\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2487,8 +2335,8 @@ " order_from_switchboard_or_shaftline: 3\n", " }\n", " transformer {\n", - " name: \"transformer for PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 954.64412117539189\n", + " name: \"transformer for PROPULSION_DRIVE 3\"\n", + " rated_power_kw: 4193.2410621224117\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2507,8 +2355,8 @@ " order_from_switchboard_or_shaftline: 1\n", " }\n", " converter1 {\n", - " name: \"frequency converter for PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 954.64412117539189\n", + " name: \"frequency converter for PROPULSION_DRIVE 3\"\n", + " rated_power_kw: 4193.2410621224117\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2537,41 +2385,15 @@ " }\n", " power_type: POWER_CONSUMER\n", " component_type: PROPULSION_DRIVE\n", - " name: \"PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 954.64412117539189\n", - " rated_speed_rpm: 3.8629660705404856\n", - " }\n", - " subsystems {\n", - " other_load {\n", - " name: \"PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 696.49816495528864\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 1\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 1\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " power_type: POWER_CONSUMER\n", - " component_type: OTHER_LOAD\n", " name: \"PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 696.49816495528864\n", + " rated_power_kw: 4193.2410621224117\n", + " rated_speed_rpm: 329.28206483221788\n", " }\n", " subsystems {\n", " electric_machine {\n", " name: \"synchronous machine\"\n", - " rated_power_kw: 2128.2386829561478\n", - " rated_speed_rpm: 25.685443725241285\n", + " rated_power_kw: 2818.129072565167\n", + " rated_speed_rpm: 230.92596118234056\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2600,7 +2422,7 @@ " }\n", " transformer {\n", " name: \"transformer\"\n", - " rated_power_kw: 2128.2386829561478\n", + " rated_power_kw: 2818.129072565167\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2620,7 +2442,7 @@ " }\n", " converter1 {\n", " name: \"inverter\"\n", - " rated_power_kw: 2128.2386829561478\n", + " rated_power_kw: 2818.129072565167\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2670,13 +2492,13 @@ " power_type: PTI_PTO\n", " component_type: PTI_PTO_SYSTEM\n", " name: \"PTI/PTO 1\"\n", - " rated_power_kw: 2128.2386829561478\n", - " rated_speed_rpm: 25.685443725241285\n", + " rated_power_kw: 2818.129072565167\n", + " rated_speed_rpm: 230.92596118234056\n", " }\n", " subsystems {\n", " converter1 {\n", " name: \"converter\"\n", - " rated_power_kw: 2280.0179186624978\n", + " rated_power_kw: 5756.9832524014491\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -2684,19 +2506,19 @@ " curve {\n", " points {\n", " x: 0.25\n", - " y: 0.31886821369318941\n", + " y: 0.38614390652279795\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.54626713274197225\n", + " y: 0.57482256146291422\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.64534415581854354\n", + " y: 0.62573078860901121\n", " }\n", " points {\n", " x: 1\n", - " y: 0.75933921644229241\n", + " y: 0.74101150969848006\n", " }\n", " }\n", " }\n", @@ -2705,7 +2527,7 @@ " }\n", " battery {\n", " name: \"battery\"\n", - " energy_capacity_kwh: 760.0059728874993\n", + " energy_capacity_kwh: 1918.9944174671498\n", " rated_charging_rate_c: 3\n", " rated_discharging_rate_c: 3\n", " efficiency_charging: 0.975\n", @@ -2716,10 +2538,11 @@ " power_type: ENERGY_STORAGE\n", " component_type: BATTERY_SYSTEM\n", " name: \"ENERGY_STORAGE_SYSTEM 1\"\n", - " rated_power_kw: 2280.0179186624978\n", + " rated_power_kw: 5756.9832524014491\n", " }\n", " }\n", - "}\n" + "}\n", + "\n" ] } ], @@ -3317,7 +3140,8 @@ " rated_power_kw: 25000\n", " rated_speed_rpm: 60\n", " }\n", - "}\n" + "}\n", + "\n" ] } ], @@ -3978,7 +3802,8 @@ " rated_speed_rpm: 900\n", " }\n", " }\n", - "}\n" + "}\n", + "\n" ] } ], @@ -4818,7 +4643,8 @@ " rated_speed_rpm: 900\n", " }\n", " }\n", - "}\n" + "}\n", + "\n" ] } ], diff --git a/machinery-system-structure/03_ConvertFEEMSResultToProto.ipynb b/machinery-system-structure/03_ConvertFEEMSResultToProto.ipynb index 2eb887c..dee147e 100644 --- a/machinery-system-structure/03_ConvertFEEMSResultToProto.ipynb +++ b/machinery-system-structure/03_ConvertFEEMSResultToProto.ipynb @@ -510,7 +510,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "FEEMSResult(duration_s=900.0, energy_consumption_electric_total_mj=0.0, energy_consumption_mechanical_total_mj=0.0, energy_stored_total_mj=0.0, load_ratio_genset=None, running_hours_main_engines_hr=0.0, running_hours_genset_total_hr=0.41666666666666663, running_hours_fuel_cell_total_hr=0.0, running_hours_pti_pto_total_hr=0.0, total_emission_kg={: 0.6326375444452783}, detail_result= multi fuel consumption [kg] \\\n", + "FEEMSResult(duration_s=900.0, energy_consumption_electric_total_mj=0.0, energy_consumption_mechanical_total_mj=0.0, energy_stored_total_mj=0.0, load_ratio_genset=None, running_hours_main_engines_hr=0.0, running_hours_genset_total_hr=0.4444444444444444, running_hours_fuel_cell_total_hr=0.0, running_hours_pti_pto_total_hr=0.0, total_emission_kg={: 0.7017041801880399}, detail_result= multi fuel consumption [kg] \\\n", "Genset 1 FuelConsumption(fuels=[, ]), co2_emission_total_kg=190.28127237235447, energy_input_mechanical_total_mj=0.0, energy_input_electric_total_mj=0.0, energy_consumption_propulsion_total_mj=517.7388296715692, energy_consumption_auxiliary_total_mj=255.6994485825417)\n", + "Battery system 1 2 , multi_fuel_consumption_total_kg=FuelConsumption(fuels=[, ]), co2_emission_total_kg=209.98940945205828, energy_input_mechanical_total_mj=0.0, energy_input_electric_total_mj=0.0, energy_consumption_propulsion_total_mj=656.092425019843, energy_consumption_auxiliary_total_mj=224.49986081828763)\n", "electric_system {\n", " duration_s: 900\n", " multi_fuel_consumption_total_kg {\n", " fuels {\n", " fuel_origin: FOSSIL\n", " fuel_specified_by: IMO\n", - " mass_or_mass_fraction: 59.35161334134574\n", + " mass_or_mass_fraction: 65.498880053667577\n", " lhv_mj_per_g: 0.0427\n", " }\n", " fuels {\n", @@ -585,9 +585,9 @@ " lhv_mj_per_g: 0.12\n", " }\n", " }\n", - " running_hours_genset_total_hr: 0.41666666666666663\n", - " co2_emission_total_kg: 190.28127237235447\n", - " nox_emission_total_kg: 0.63263754444527831\n", + " running_hours_genset_total_hr: 0.44444444444444442\n", + " co2_emission_total_kg: 209.98940945205828\n", + " nox_emission_total_kg: 0.70170418018803993\n", " detailed_result {\n", " component_name: \"Genset 1\"\n", " multi_fuel_consumption_kg {\n", @@ -773,14 +773,14 @@ " fuels {\n", " fuel_origin: FOSSIL\n", " fuel_specified_by: IMO\n", - " mass_or_mass_fraction: 23.399451168972767\n", + " mass_or_mass_fraction: 29.153718323281648\n", " lhv_mj_per_g: 0.0427\n", " }\n", " }\n", - " mechanical_energy_consumption_mj: 396.47734123672222\n", - " running_hours_h: 0.16666666666666666\n", - " co2_emissions_kg: 75.0186404477267\n", - " nox_emissions_kg: 0.24897651346337912\n", + " mechanical_energy_consumption_mj: 498.32069418257811\n", + " running_hours_h: 0.19444444444444445\n", + " co2_emissions_kg: 93.466820944440968\n", + " nox_emissions_kg: 0.31293124756441332\n", " component_type: \"GENSET\"\n", " rated_capacity: 1000\n", " rated_capacity_unit: \"kW\"\n", @@ -795,28 +795,28 @@ " time: 700\n", " time: 800\n", " time: 900\n", - " power_output_kw: 624.16260731908642\n", - " power_output_kw: 709.0303643944826\n", + " power_output_kw: 683.92893211087858\n", " power_output_kw: 0\n", - " power_output_kw: 495.3573385920626\n", - " power_output_kw: 620.61432627067211\n", + " power_output_kw: 738.54405509152014\n", + " power_output_kw: 702.6261150338114\n", + " power_output_kw: 650.06250565444566\n", + " power_output_kw: 650.13415067040171\n", + " power_output_kw: 737.78351346392412\n", " power_output_kw: 0\n", - " power_output_kw: 762.84347215581829\n", - " power_output_kw: 0\n", - " power_output_kw: 622.7809887036268\n", + " power_output_kw: 666.53223349131645\n", " fuel_consumption_kg_per_s {\n", " fuels {\n", " fuel_origin: FOSSIL\n", " fuel_specified_by: IMO\n", - " mass_or_mass_fraction: 0.038078276802129538\n", - " mass_or_mass_fraction: 0.042671325022706992\n", - " mass_or_mass_fraction: 0\n", - " mass_or_mass_fraction: 0.031420199766761081\n", - " mass_or_mass_fraction: 0.0378945948978267\n", + " mass_or_mass_fraction: 0.04125853027049009\n", " mass_or_mass_fraction: 0\n", - " mass_or_mass_fraction: 0.0459234031795802\n", + " mass_or_mass_fraction: 0.044419677299932771\n", + " mass_or_mass_fraction: 0.042304977431948505\n", + " mass_or_mass_fraction: 0.039432784895904294\n", + " mass_or_mass_fraction: 0.039436572794960746\n", + " mass_or_mass_fraction: 0.044373504827140926\n", " mass_or_mass_fraction: 0\n", - " mass_or_mass_fraction: 0.038006712020723171\n", + " mass_or_mass_fraction: 0.04031113571243912\n", " lhv_mj_per_g: 0.0427\n", " }\n", " }\n", @@ -828,14 +828,14 @@ " fuels {\n", " fuel_origin: FOSSIL\n", " fuel_specified_by: IMO\n", - " mass_or_mass_fraction: 35.952162172372972\n", + " mass_or_mass_fraction: 36.345161730385932\n", " lhv_mj_per_g: 0.0427\n", " }\n", " }\n", - " mechanical_energy_consumption_mj: 610.95282998336609\n", + " mechanical_energy_consumption_mj: 619.09316877830963\n", " running_hours_h: 0.25\n", - " co2_emissions_kg: 115.26263192462775\n", - " nox_emissions_kg: 0.38366103098189924\n", + " co2_emissions_kg: 116.5225885076173\n", + " nox_emissions_kg: 0.38877293262362667\n", " component_type: \"GENSET\"\n", " rated_capacity: 1000\n", " rated_capacity_unit: \"kW\"\n", @@ -850,28 +850,28 @@ " time: 700\n", " time: 800\n", " time: 900\n", - " power_output_kw: 624.16260731908642\n", - " power_output_kw: 709.0303643944826\n", - " power_output_kw: 686.85184307084444\n", - " power_output_kw: 495.3573385920626\n", - " power_output_kw: 620.61432627067211\n", - " power_output_kw: 749.21339861719446\n", - " power_output_kw: 762.84347215581829\n", - " power_output_kw: 642.49446943541807\n", - " power_output_kw: 622.7809887036268\n", + " power_output_kw: 683.92893211087858\n", + " power_output_kw: 582.27458720942548\n", + " power_output_kw: 738.54405509152014\n", + " power_output_kw: 702.6261150338114\n", + " power_output_kw: 650.06250565444566\n", + " power_output_kw: 650.13415067040171\n", + " power_output_kw: 737.78351346392412\n", + " power_output_kw: 583.52455649136141\n", + " power_output_kw: 666.53223349131645\n", " fuel_consumption_kg_per_s {\n", " fuels {\n", " fuel_origin: FOSSIL\n", " fuel_specified_by: IMO\n", - " mass_or_mass_fraction: 0.038078276802129538\n", - " mass_or_mass_fraction: 0.042671325022706992\n", - " mass_or_mass_fraction: 0.041420032617961136\n", - " mass_or_mass_fraction: 0.031420199766761081\n", - " mass_or_mass_fraction: 0.0378945948978267\n", - " mass_or_mass_fraction: 0.045072995467720596\n", - " mass_or_mass_fraction: 0.0459234031795802\n", - " mass_or_mass_fraction: 0.039034081948320365\n", - " mass_or_mass_fraction: 0.038006712020723171\n", + " mass_or_mass_fraction: 0.04125853027049009\n", + " mass_or_mass_fraction: 0.035925226506613582\n", + " mass_or_mass_fraction: 0.044419677299932771\n", + " mass_or_mass_fraction: 0.042304977431948505\n", + " mass_or_mass_fraction: 0.039432784895904294\n", + " mass_or_mass_fraction: 0.039436572794960746\n", + " mass_or_mass_fraction: 0.044373504827140926\n", + " mass_or_mass_fraction: 0.035989207564429249\n", + " mass_or_mass_fraction: 0.04031113571243912\n", " lhv_mj_per_g: 0.0427\n", " }\n", " }\n", @@ -956,8 +956,8 @@ " power_output_kw: -0\n", " }\n", " }\n", - " energy_consumption_propulsion_total_mj: 517.73882967156919\n", - " energy_consumption_auxiliary_total_mj: 255.69944858254169\n", + " energy_consumption_propulsion_total_mj: 656.092425019843\n", + " energy_consumption_auxiliary_total_mj: 224.49986081828763\n", "}\n", "\n", "electric_system {\n", @@ -966,7 +966,7 @@ " fuels {\n", " fuel_origin: FOSSIL\n", " fuel_specified_by: IMO\n", - " mass_or_mass_fraction: 59.35161334134574\n", + " mass_or_mass_fraction: 65.498880053667577\n", " lhv_mj_per_g: 0.0427\n", " }\n", " fuels {\n", @@ -976,9 +976,9 @@ " lhv_mj_per_g: 0.12\n", " }\n", " }\n", - " running_hours_genset_total_hr: 0.41666666666666663\n", - " co2_emission_total_kg: 190.28127237235447\n", - " nox_emission_total_kg: 0.63263754444527831\n", + " running_hours_genset_total_hr: 0.44444444444444442\n", + " co2_emission_total_kg: 209.98940945205828\n", + " nox_emission_total_kg: 0.70170418018803993\n", " detailed_result {\n", " component_name: \"Genset 1\"\n", " multi_fuel_consumption_kg {\n", @@ -1035,14 +1035,14 @@ " fuels {\n", " fuel_origin: FOSSIL\n", " fuel_specified_by: IMO\n", - " mass_or_mass_fraction: 23.399451168972767\n", + " mass_or_mass_fraction: 29.153718323281648\n", " lhv_mj_per_g: 0.0427\n", " }\n", " }\n", - " mechanical_energy_consumption_mj: 396.47734123672222\n", - " running_hours_h: 0.16666666666666666\n", - " co2_emissions_kg: 75.0186404477267\n", - " nox_emissions_kg: 0.24897651346337912\n", + " mechanical_energy_consumption_mj: 498.32069418257811\n", + " running_hours_h: 0.19444444444444445\n", + " co2_emissions_kg: 93.466820944440968\n", + " nox_emissions_kg: 0.31293124756441332\n", " component_type: \"GENSET\"\n", " rated_capacity: 1000\n", " rated_capacity_unit: \"kW\"\n", @@ -1054,14 +1054,14 @@ " fuels {\n", " fuel_origin: FOSSIL\n", " fuel_specified_by: IMO\n", - " mass_or_mass_fraction: 35.952162172372972\n", + " mass_or_mass_fraction: 36.345161730385932\n", " lhv_mj_per_g: 0.0427\n", " }\n", " }\n", - " mechanical_energy_consumption_mj: 610.95282998336609\n", + " mechanical_energy_consumption_mj: 619.09316877830963\n", " running_hours_h: 0.25\n", - " co2_emissions_kg: 115.26263192462775\n", - " nox_emissions_kg: 0.38366103098189924\n", + " co2_emissions_kg: 116.5225885076173\n", + " nox_emissions_kg: 0.38877293262362667\n", " component_type: \"GENSET\"\n", " rated_capacity: 1000\n", " rated_capacity_unit: \"kW\"\n", @@ -1089,9 +1089,10 @@ " rated_capacity_unit: \"kWh\"\n", " switchboard_id: 2\n", " }\n", - " energy_consumption_propulsion_total_mj: 517.73882967156919\n", - " energy_consumption_auxiliary_total_mj: 255.69944858254169\n", - "}\n" + " energy_consumption_propulsion_total_mj: 656.092425019843\n", + " energy_consumption_auxiliary_total_mj: 224.49986081828763\n", + "}\n", + "\n" ] } ], diff --git a/machinery-system-structure/05_ConvertTimeSeriesResultProtoToPandas.ipynb b/machinery-system-structure/05_ConvertTimeSeriesResultProtoToPandas.ipynb index 2039f0e..25aa264 100644 --- a/machinery-system-structure/05_ConvertTimeSeriesResultProtoToPandas.ipynb +++ b/machinery-system-structure/05_ConvertTimeSeriesResultProtoToPandas.ipynb @@ -18,16 +18,7 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], + "outputs": [], "source": [ "# | default_exp convert_proto_timeseries\n", "%load_ext autoreload\n", @@ -169,35 +160,8949 @@ "name": "stderr", "output_type": "stream", "text": [ - "2023-11-06 22:59:11,856 - MachSysS.convert_proto_timeseries - WARNING - Time in operation profile is not the same as in propulsion power.The operation profile will be interpolated to match the propulsion power time.\n" + "2024-04-02 09:00:34,706 - MachSysS.convert_proto_timeseries - WARNING - Time in operation profile is not the same as in propulsion power.The operation profile will be interpolated to match the propulsion power time.\n" ] }, { "data": { - "text/plain": [ - "" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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wZA4jAAjSElJCW688UaUlJREXZR2j6nrcDD1HA6mnsPB1HN4RF3X7daJ12AwGAwGQ/vFaGAMBoPBYDAkDiPAGAwGg8FgSBxGgDEYDAaDwZA4jABjMBgMBoMhcRgBRpB77rkHAwcORGlpKUaPHo158+ZFXaREMWnSJBx88MHo0qULevXqhTPOOAPLly93nFNfX4/x48ejR48e6Ny5M8466yysX7/ecc7q1atxyimnoGPHjujVqxeuuuoqNDc3h3krieG2225DKpXChAkTcr+ZOlbH2rVrce6556JHjx7o0KEDhg8fjg8++CB33LIsTJw4Eb1790aHDh0wZswYrFy50pHGli1bMG7cOJSVlaG8vBwXXXQRtm3bFvatxJaWlhbccMMNGDRoEDp06IA999wTN998s2OvHFPPcsyaNQunnXYa+vTpg1Qqheeee85xXFW9fvzxxzjyyCNRWlqKfv36YfLkycELbxm4efrpp63i4mLroYcespYuXWpdfPHFVnl5ubV+/fqoi5YYxo4daz388MPWkiVLrIULF1onn3yy1b9/f2vbtm25cy699FKrX79+1owZM6wPPvjAOvTQQ63DDjssd7y5udkaNmyYNWbMGOujjz6yXnnlFatnz57WddddF8UtxZp58+ZZAwcOtPbff3/r8ssvz/1u6lgNW7ZssQYMGGD95Cc/sebOnWt98cUX1muvvWZ99tlnuXNuu+02q2vXrtZzzz1nLVq0yPrud79rDRo0yNq5c2funBNPPNE64IADrDlz5ljvvPOOtddee1nnnHNOFLcUS2699VarR48e1ksvvWStWrXKeuaZZ6zOnTtbf/3rX3PnmHqW45VXXrF+97vfWc8++6wFwJo6darjuIp6ra2ttSoqKqxx48ZZS5YssZ566imrQ4cO1gMPPBCo7EaAEeCQQw6xxo8fn/ve0tJi9enTx5o0aVKEpUo2GzZssABYb7/9tmVZllVTU2MVFRVZzzzzTO6cTz75xAJgzZ4927Ks1hcunU5b1dXVuXPuu+8+q6yszGpoaAj3BmLM1q1brb333tuaPn269Z3vfCcnwJg6Vsc111xjHXHEEdTjmUzGqqystG6//fbcbzU1NVZJSYn11FNPWZZlWcuWLbMAWPPnz8+d8+qrr1qpVMpau3atvsIniFNOOcX66U9/6vjtzDPPtMaNG2dZlqlnVbgFGFX1eu+991rdunVz9B3XXHONte+++wYqrzEhcdLY2IgFCxZgzJgxud/S6TTGjBmD2bNnR1iyZFNbWwsA6N69OwBgwYIFaGpqctTz4MGD0b9//1w9z549G8OHD0dFRUXunLFjx6Kurg5Lly4NsfTxZvz48TjllFMcdQmYOlbJCy+8gFGjRuEHP/gBevXqhREjRuDvf/977viqVatQXV3tqOuuXbti9OjRjrouLy/HqFGjcueMGTMG6XQac+fODe9mYsxhhx2GGTNmYMWKFQCARYsW4d1338VJJ50EwNSzLlTV6+zZs3HUUUehuLg4d87YsWOxfPlyfPvtt9Lla7ebOapm06ZNaGlpcXToAFBRUYFPP/00olIlm0wmgwkTJuDwww/HsGHDAADV1dUoLi5GeXm549yKigpUV1fnziE9h+wxA/D000/jww8/xPz58z3HTB2r44svvsB9992HK6+8Er/97W8xf/58/OpXv0JxcTEuuOCCXF2R6tJe17169XIcLywsRPfu3U1dt3Httdeirq4OgwcPRkFBAVpaWnDrrbdi3LhxAGDqWROq6rW6uhqDBg3ypJE91q1bN6nyGQHGEBnjx4/HkiVL8O6770ZdlHbFmjVrcPnll2P69OkoLS2Nujjtmkwmg1GjRuGPf/wjAGDEiBFYsmQJ7r//flxwwQURl6798J///AdPPPEEnnzySey3335YuHAhJkyYgD59+ph63oUxJiROevbsiYKCAs9KjfXr16OysjKiUiWXyy67DC+99BLefPNN7L777rnfKysr0djYiJqaGsf59nqurKwkPofssV2dBQsWYMOGDTjooINQWFiIwsJCvP3225gyZQoKCwtRUVFh6lgRvXv3xtChQx2/DRkyBKtXrwaQrytWv1FZWYkNGzY4jjc3N2PLli2mrtu46qqrcO211+Lss8/G8OHDcd555+GKK67ApEmTAJh61oWqetXVnxgBhpPi4mKMHDkSM2bMyP2WyWQwY8YMVFVVRViyZGFZFi677DJMnToVM2fO9KgVR44ciaKiIkc9L1++HKtXr87Vc1VVFRYvXux4aaZPn46ysjLPYLIrctxxx2Hx4sVYuHBh7m/UqFEYN25c7rOpYzUcfvjhnjAAK1aswIABAwAAgwYNQmVlpaOu6+rqMHfuXEdd19TUYMGCBblzZs6ciUwmg9GjR4dwF/Fnx44dSKedw1VBQQEymQwAU8+6UFWvVVVVmDVrFpqamnLnTJ8+Hfvuu6+0+QiAWUYtwtNPP22VlJRYjzzyiLVs2TLrkksuscrLyx0rNQxsfv7zn1tdu3a13nrrLeubb77J/e3YsSN3zqWXXmr179/fmjlzpvXBBx9YVVVVVlVVVe54donvCSecYC1cuNCaNm2atdtuu5klvgzsq5Asy9SxKubNm2cVFhZat956q7Vy5UrriSeesDp27Gg9/vjjuXNuu+02q7y83Hr++eetjz/+2Dr99NOJy1BHjBhhzZ0713r33Xetvffee5df3mvnggsusPr27ZtbRv3ss89aPXv2tK6++urcOaae5di6dav10UcfWR999JEFwLrzzjutjz76yPrqq68sy1JTrzU1NVZFRYV13nnnWUuWLLGefvppq2PHjmYZddjcfffdVv/+/a3i4mLrkEMOsebMmRN1kRIFAOLfww8/nDtn586d1i9+8QurW7duVseOHa3vfe971jfffONI58svv7ROOukkq0OHDlbPnj2tX//611ZTU1PId5Mc3AKMqWN1vPjii9awYcOskpISa/DgwdaDDz7oOJ7JZKwbbrjBqqiosEpKSqzjjjvOWr58ueOczZs3W+ecc47VuXNnq6yszLrwwgutrVu3hnkbsaaurs66/PLLrf79+1ulpaXWHnvsYf3ud79zLMs19SzHm2++SeyTL7jgAsuy1NXrokWLrCOOOMIqKSmx+vbta912222By56yLFsoQ4PBYDAYDIYEYHxgDAaDwWAwJA4jwBgMBoPBYEgcRoAxGAwGg8GQOIwAYzAYDAaDIXEYAcZgMBgMBkPiMAKMwWAwGAyGxGEEGIPBYDAYDInDCDAGg8FgMBgShxFgDAaDwWAwJA4jwBgMBoPBYEgcRoAxGAwGg8GQOIwAYzAYDAaDIXH8P+DiOYgEGH0IAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hovertemplate": "variable=propulsion_power_kw
index=%{x}
value=%{y}", + "legendgroup": "propulsion_power_kw", + "line": { + "color": "#636efa", + "dash": "solid" + }, + "marker": { + "symbol": "circle" + }, + "mode": "lines", + "name": "propulsion_power_kw", + "showlegend": true, + "type": "scattergl", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + "xaxis": "x", + "y": [ + 563.9759930760054, + 953.512916481576, + 946.6100163315633, + 484.93717347363753, + 458.3719528074156, + 221.60214154229175, + 284.3951323632581, + 804.3420045213549, + 642.949108588533, + 596.8818434409849, + 138.48962522385665, + 428.45044151826295, + 942.3220495968263, + 915.3043865616193, + 214.42974825944927, + 153.1754125540946, + 204.04007771089928, + 792.615747013655, + 28.199199110149674, + 102.87346719325008, + 444.7470491709606, + 0.9574745220979342, + 779.3593266020018, + 212.21431180302665, + 541.8606488112348, + 653.7807730306628, + 623.8603326048066, + 753.5190378685234, + 9.055950218868404, + 905.4052177985634, + 213.431369473429, + 477.29900978805387, + 363.94970299810615, + 333.9201963044575, + 478.5255336760115, + 640.925416703976, + 151.87679618183824, + 138.8890256849279, + 62.14246593790818, + 726.5959153698675, + 594.5250968552672, + 577.8454283877999, + 66.57628049579434, + 846.4503119938707, + 49.23026535929398, + 478.91385893890856, + 153.35823090455182, + 42.91691396310993, + 23.131914478040304, + 445.8645646594639, + 55.310665867404964, + 182.21337184369614, + 751.2240008322896, + 649.5440440284633, + 868.3977670613855, + 182.9649731638515, + 522.6586165618705, + 971.2621351092232, + 116.56622743822531, + 508.9993402792996, + 564.6003683669546, + 750.0815294271798, + 298.38484874472726, + 546.01312108703, + 217.54710630994677, + 237.49175417843261, + 853.3835510364353, + 269.78928786702147, + 41.19364441423945, + 597.0857717330559, + 430.34661201267386, + 243.57958416749014, + 481.3250281027279, + 734.3034594733808, + 658.883652226202, + 37.8045297456886, + 840.5814611667523, + 776.8018716046746, + 140.3914130234639, + 948.976263227848, + 185.28832201360234, + 384.85468277790847, + 219.80428263335938, + 748.7641669049096, + 509.0577637972482, + 816.5245701954881, + 50.48552958668784, + 915.772316486219, + 224.9160508731046, + 98.78298791260976, + 608.8898096620902, + 736.8522582400354, + 130.02227879202633, + 10.310798167459168, + 114.69125356299415, + 233.96400326746868, + 508.2718917601373, + 568.8379865657778, + 118.72915457518596, + 491.74338730096247, + 561.0185113426477, + 776.719323137999, + 725.2955234349658, + 34.74933703036909, + 373.29734834289064, + 469.3678539927221, + 862.789884369077, + 951.4513245229269, + 119.76838654122979, + 434.27278042785986, + 568.0083766508843, + 94.67077423879367, + 645.5367774398363, + 171.1635069592854, + 678.8192091680521, + 57.91132956527356, + 655.3278047615945, + 112.93904289752032, + 201.24642656022928, + 414.6550665492671, + 927.9606545391603, + 619.4227705721008, + 896.5618392791116, + 879.5186931221515, + 163.9805707698433, + 783.6183277571407, + 460.40267891443887, + 439.2289627982562, + 719.1902740545362, + 219.46864124742737, + 910.5854897366046, + 504.00711509753904, + 907.3859234752584, + 594.3570795548005, + 67.65427013935388, + 618.0389826425463, + 548.0825675053206, + 31.486720129800695, + 555.353614310121, + 985.47040577778, + 875.6777314610995, + 518.9011032127662, + 943.7975448935375, + 72.62972143001667, + 874.4587389346717, + 281.1984232532441, + 363.422659905779, + 450.76012932392973, + 254.09887507397565, + 108.13233777003761, + 822.7206770665878, + 147.42844855175306, + 987.42587613894, + 483.2482987239146, + 933.2321109854208, + 55.21270560506497, + 834.792044970125, + 310.43843574984976, + 41.67266546097959, + 84.34916150509375, + 206.37324922188438, + 909.3293448797297, + 457.0488598527915, + 287.2603216150915, + 161.105504043881, + 860.6809826907202, + 193.09147766711433, + 829.7426304910448, + 42.28578596567678, + 656.263386766855, + 614.2746351997207, + 204.56163006267946, + 420.97647028445664, + 857.8211616586958, + 174.94212681137589, + 338.74907190588476, + 525.3302558445065, + 658.2151214683716, + 673.328455130536, + 158.0194185936883, + 49.599431760584565, + 696.7103416049023, + 339.994279461834, + 461.6604666186628, + 871.3130572502912, + 14.073744744056537, + 68.09547770977498, + 910.1775773858648, + 73.74099004902723, + 377.4525239332116, + 785.7297770549301, + 432.61752305373955, + 637.9495268516196, + 157.25343958944993, + 15.838718889192638, + 519.3184545455149, + 924.826370733523, + 377.7884088236855, + 14.991988519439614, + 292.06277797193724, + 187.8540721681683, + 372.80610179000473, + 167.78691522107593, + 472.7005570210656, + 892.4856114334082, + 265.803574305881, + 166.52165459969027, + 614.1917357575586, + 900.5190135033898, + 899.3747104721606, + 656.9267139872615, + 328.43298394765606, + 338.82124817675754, + 496.8641496095136, + 176.0971881210962, + 32.55177779047214, + 404.82496337997406, + 228.5741125631493, + 798.3437508185514, + 375.74069497095184, + 360.048534488654, + 203.07127785194257, + 249.23367774988213, + 95.30139070211186, + 741.6531350709987, + 226.77589511931438, + 814.5342157576865, + 384.2758879906899, + 380.44181633358477, + 945.6642289212218, + 358.9790197442838, + 747.9151039551954, + 701.4513487028096, + 92.42761612464334, + 692.4059332464648, + 348.7290317208863, + 105.28106989526975, + 490.2394316339895, + 432.8312080103771, + 905.6400503730179, + 365.0616433284088, + 868.0629264142444, + 646.9020245427051, + 863.2114637181164, + 200.5036281594248, + 570.8732862076017, + 233.0059898923138, + 963.5382405921442, + 41.22752352417047, + 781.4762239146239, + 329.67052516954175, + 457.1962748420185, + 34.041639952540834, + 252.88404380359754, + 60.35606861331322, + 446.9787084634993, + 148.83319577608168, + 899.8779958278933, + 284.04195994321867, + 819.3758562532954, + 857.6698049866518, + 583.4032317781775, + 528.8186801415922, + 330.4777237403096, + 902.2328095426144, + 924.76540861749, + 906.3999218056277, + 871.3383586579317, + 314.7605137442556, + 341.2690038876256, + 799.2202265075522, + 542.4479812795058, + 476.2432912153348, + 698.4684290841036, + 238.42335052147223, + 176.29265455641286, + 487.9926504142694, + 9.826000462162977, + 325.869523675983, + 428.98296835968097, + 895.1323172797956, + 589.9914838087038, + 687.3246549687171, + 431.45197708295115, + 993.5811422975061, + 605.50642513048, + 942.2923934571353, + 940.7568792603284, + 74.90045114677102, + 718.1206005866804, + 636.920523035394, + 246.50191760381745, + 82.3705490002774, + 337.42494183603003, + 662.007194427554, + 842.457737362819, + 511.55776787270236, + 775.9272496661672, + 806.5341343408763, + 387.2122473240164, + 990.8804811954718, + 517.8241386380316, + 995.1433829291113, + 214.8933447399175, + 822.8670987036514, + 894.8560434349287, + 737.4604671686131, + 842.8829164391466, + 795.6546030377076, + 822.7169769414418, + 86.0055009331716, + 987.1783778957565, + 478.23271878219185, + 446.1609343973426, + 938.2717117082956, + 893.0626803540996, + 865.1467796157236, + 19.14671992416661, + 545.9264009779218, + 658.4302594457782, + 468.9979773974593, + 403.58779169166905, + 870.84691093992, + 139.53995727267244, + 408.5411958303423, + 939.5647736828245, + 234.6381300477075, + 338.5398723030404, + 723.0409440633533, + 705.6881366549077, + 878.0050510744378, + 815.863198381462, + 966.3714978297041, + 68.68983585980205, + 412.7040201934361, + 556.4364205325564, + 717.0487509862845, + 337.73768413873773, + 119.72198413306867, + 515.0960460728569, + 693.8781205780275, + 870.7149451763313, + 677.0841434126661, + 766.7931237437354, + 197.62371246795962, + 257.07897669224076, + 3.8634996853921244, + 536.0605537909854, + 630.1061251404882, + 279.62551095651435, + 756.7734169159943, + 67.50834940169459, + 937.7860886677752, + 550.2425485924433, + 955.8225938521343, + 215.3303476657277, + 612.2506570419529, + 32.432655522872444, + 414.1575533532808, + 346.6963619619392, + 736.095462572559, + 856.8947599098996, + 358.5116989729548, + 761.8793022079335, + 618.3632847321592, + 857.4575261254985, + 538.9817545580879, + 33.91470727653279, + 666.4237500928482, + 587.3952049675191, + 378.7893017469336, + 861.2255978767059, + 335.39610035875666, + 307.83108397786697, + 801.1547061588328, + 983.8654793993225, + 825.0034219720916, + 36.78127250805496, + 577.1904298842489, + 902.6236209813521, + 467.9210404343297, + 456.7645705460599, + 101.41068916866614, + 346.5954797076137, + 105.19126574582349, + 128.5757194667394, + 863.7238471722, + 196.22983688496188, + 734.0477339988657, + 61.144700633035676, + 334.7177189324039, + 107.9606500401029, + 567.1955208335875, + 806.7971286781899, + 882.2968360595563, + 690.1155330363383, + 909.592567348208, + 947.564574720157, + 720.2862064488919, + 478.6935987793369, + 144.2273610940723, + 238.30745880762626, + 438.44089847881827, + 785.9011227565404, + 503.9885653992906, + 429.6150653717539, + 466.3611471133738, + 352.6803897043666, + 60.84245969481217, + 130.41769877606745, + 151.84526321996117, + 241.37964882036545, + 793.3314002534519, + 245.21279743093405, + 92.31807926439583, + 568.7134101364129, + 131.09906454121423, + 866.5924977381142, + 24.30485812366623, + 910.6618299774641, + 314.14669119952043, + 332.2888738314505, + 911.9707901353732, + 286.95073044941734, + 195.06056479297328, + 101.70382887993745, + 386.0484036586663, + 805.4939080129994, + 871.1171873793043, + 361.8091933118313, + 836.5888335488231, + 192.90834117896216, + 119.27453471506023, + 431.0342233850416, + 47.18493663891088, + 111.33721257531803, + 793.9640077048819, + 322.56437403131144, + 377.90007821508755, + 120.81874397116277, + 552.2184712495066, + 954.6191456983845, + 980.4244716462197, + 821.578512771939, + 922.6615586647126, + 72.94910774283636, + 629.5271237941532, + 154.1649108683828, + 833.6662465720692, + 922.3643406991622, + 190.18032567262054, + 331.58656420469043, + 360.39482269940237, + 961.3568274754628, + 492.31646383181294, + 134.50000043460398, + 634.6118942197493, + 374.37717850997143, + 647.9399450354921, + 779.8168946580118, + 633.0400178942893, + 815.2372078166389, + 981.6551267169804, + 815.868098402561, + 41.148307688494754, + 132.10943650935448, + 901.2673462693494, + 610.2453463905439, + 325.7064479921561, + 580.6896174639909, + 867.0560024367142, + 277.9881213049403, + 705.1074689053216, + 916.1448632334377, + 331.64607089312216, + 327.5755274627236, + 249.00425258841474, + 176.4317856692801, + 580.8687106743502, + 879.0085930908945, + 166.65063312086104, + 645.9309527912864, + 968.2339214587076, + 316.0525467082583, + 318.0734817834335, + 219.74438832184927, + 982.8645833743471, + 186.628472068315, + 291.2167730728825, + 221.58097129947697, + 508.29383792133564, + 88.2995760885934, + 358.6007035423865, + 819.5945795176175, + 693.1423486340593, + 948.2140393540627, + 649.6489357101281, + 183.11993841231723, + 352.37790799301337, + 555.9815964842976, + 674.4754436262598, + 633.8180407145184, + 382.96488919920114, + 570.0982050560617, + 356.509928296028, + 873.4470141896142, + 168.6241165549819, + 430.65257026623016, + 723.0093645190846, + 606.8712966815332, + 68.88129817910715, + 170.5967478255931, + 591.814560861869, + 624.1737370066257, + 622.5459372991814, + 550.0260934728963, + 855.050394318347, + 745.5474850610664, + 304.02807033754743, + 800.4563796961435, + 403.7079740883316, + 206.06989661881082, + 483.82005267168995, + 296.51525954352434, + 873.0113803505785, + 847.1969825272756, + 391.0888471122147, + 173.34301495683212, + 756.9190793032523, + 457.5768288304627, + 506.9847102801466, + 55.28045641797319, + 91.02448040575506, + 422.99998422313666, + 392.02035041820295, + 765.0022430851889, + 120.50711843558481, + 98.70912360892747, + 930.7652601233773, + 962.7238052818775, + 441.0519585602538, + 724.53836852816, + 457.77292110267297, + 265.0597108494653, + 482.4122016725968, + 402.6747835938017, + 746.2870589195765, + 247.19850087250106, + 155.60691616486045, + 40.00790563108458, + 191.34842738176349, + 363.71827514515144, + 705.5001836299232, + 995.9584825969353, + 343.08253114560114, + 631.0881491757481, + 388.7489912483153, + 255.30097059902522, + 856.4104972491323, + 923.7537407091412, + 87.66478338015449, + 427.4819889957785, + 456.519492163894, + 132.00604412550086, + 758.4359797327477, + 695.9632656629391, + 146.80771307042718, + 596.2543518965306, + 775.5021243088215, + 262.7126812445536, + 754.2310680138572, + 274.40046444144605, + 396.3034387994192, + 862.0770643389793, + 311.5616780767285, + 528.8297107262257, + 69.13591023088861, + 480.9240100196333, + 698.4183136262374, + 61.118013094283, + 636.2805401972397, + 168.5472811967701, + 698.4247029973772, + 399.37055912448994, + 346.9701405187121, + 504.60247257546376, + 150.5010189285274, + 617.0340058331526, + 955.2400262449523, + 725.7729303869528, + 855.0624489251626, + 335.15249273878356, + 670.2628304692737, + 419.2484084434963, + 339.8532654732336, + 970.5738935519483, + 575.047656290856, + 370.02402009035796, + 896.6528834061031, + 131.4695363575954, + 896.4450586926051, + 544.3134056373821, + 629.2436844544187, + 493.9887217496909, + 568.7520922319488, + 449.15203009695824, + 181.44849282205755, + 744.3357521663089, + 677.5903571345076, + 373.337153521312, + 580.9977789160042, + 140.13485748085418, + 583.9534665883407, + 299.20715187545665, + 231.14610519838786, + 448.8258254785876, + 445.3130385632668, + 934.1499971352292, + 385.2312321606729, + 452.8224168925061, + 215.31433363989305, + 119.5559893973781, + 506.86891112974587, + 381.0854332859629, + 345.61846934061913, + 420.76583560741096, + 509.787771622106, + 759.7431440263483, + 861.2244707084373, + 53.35207408656451, + 169.7950610714224, + 918.5825710259129, + 559.8792646386081, + 474.18133074144976, + 591.4360053538437, + 484.5666161168315, + 676.5094806509376, + 357.69643800725635, + 283.5539118767375, + 872.7676603744906, + 584.3023122227747, + 159.0535099332001, + 731.1948706874738, + 887.1345319350103, + 821.8716682698914, + 113.41177292104699, + 945.3743601466607, + 219.53159416885026, + 732.3419011293774, + 97.59978261236857, + 700.9179236087858, + 834.0659107677806, + 503.4263668869626, + 222.98178009032054, + 48.96848355816941, + 772.264673730954, + 31.672166141304526, + 770.4906313511923, + 872.7635741303483, + 192.09455224008843, + 709.9299399916072, + 261.2950073371882, + 179.05454644097807, + 986.9895219872127, + 65.86327534780534, + 696.1287916192823, + 159.35197292322346, + 500.0251336742411, + 129.2461061514847, + 861.3373368208249, + 924.5418198344596, + 753.0805859893619, + 656.1951735636197, + 613.0489850513222, + 269.7749635561074, + 728.3501188609713, + 785.89505542132, + 4.39701568175499, + 270.81243102586484, + 338.3210508131954, + 981.407704051375, + 642.4980608070149, + 168.21616340522772, + 888.6698506806048, + 803.0400138831722, + 436.7244761990483, + 271.67925550530936, + 445.7642006992734, + 424.76705899899866, + 419.47546863124484, + 911.2948401007224, + 428.89802995317496, + 630.153354231101, + 515.8117941998893, + 937.7763755748449, + 378.3133645000554, + 328.4756811187651, + 775.6738689120593, + 429.5550750936615, + 197.34647738178046, + 703.9513240952684, + 940.1867285278814, + 869.4839821759608, + 376.8868885789508, + 258.0416717992878, + 432.55180630714176, + 848.6518241213475, + 887.1778575221218, + 81.05378919630301, + 106.50482988280918, + 313.3548423014305, + 861.5341163997657, + 619.6316485861502, + 84.06046669188095, + 186.774267839665, + 588.600798684984, + 437.43776556062863, + 524.2315163837671, + 875.094843503842, + 381.5994271084281, + 356.01511746824133, + 69.27462431628439, + 894.7580889876208, + 322.8025771285863, + 645.4978320035054, + 425.41948602836254, + 103.95354220122299, + 210.38900511095815, + 117.33796899200699, + 65.47262195542002, + 197.31929029908213, + 39.660802845025266, + 534.3181373046996, + 151.71084227514808, + 707.0895352897876, + 742.7102847351508, + 571.2088927088074, + 697.7167317011279, + 265.5589471595701, + 331.81592652834513, + 447.75069932757805, + 713.3637458272674, + 35.9271947360923, + 690.1658982987628, + 671.3328390749663, + 946.2796077054636, + 20.50793442512855, + 322.34592896615413, + 301.5348686388508, + 577.4183047752675, + 575.7386150497235, + 709.3472096984588, + 268.6510090306609, + 336.95423409026927, + 597.6894243809714, + 429.92884618775315, + 574.2775756278097, + 493.63954821231715, + 602.6192030933195, + 85.16282548327925, + 279.18692229559304, + 785.7425874250439, + 467.3524646348153, + 261.63623495974156, + 123.68620992472424, + 106.85587786880757, + 704.4744053506904, + 518.1663061839511, + 699.7410622606025, + 718.1685903821766, + 518.7652922327808, + 384.95225592435503, + 666.0455808602828, + 92.09327860447591, + 713.0583269354323, + 703.7976629536882, + 773.1950970496242, + 598.4243255378105, + 159.6369171708274, + 922.9144679136749, + 150.48852174634698, + 615.9163333811676, + 661.8814586199722, + 780.6249778751131, + 976.8671056947301, + 273.6872496037833, + 479.4040419735979, + 736.3183454827983, + 975.1279338778514, + 108.16794258943186, + 23.93229039657596, + 290.77394837557523, + 602.0666930429574, + 227.26254252660883, + 851.5390757470417, + 262.48886786970473, + 151.472505357356, + 227.85507551190122, + 762.6758835594978, + 280.0696114383431, + 527.7730175393076, + 285.10040624781664, + 84.40337611386184, + 367.79793126337137, + 655.1667852401479, + 874.9867987337897, + 118.12093990767781, + 239.6495378963185, + 169.62356249370058, + 723.1340167626915, + 645.2142658139277, + 290.3087663715012, + 831.852408518591, + 272.49276900873696, + 124.60023817548004, + 3.311975272190737, + 527.9386969863723, + 413.7711521572296, + 223.5228269859122, + 6.10571357727574, + 299.9533818308279, + 49.57880953328131, + 456.23946315731854, + 361.74657423271304, + 877.5605051078323, + 282.4348029253874, + 5.844479317592688, + 567.4983630295242, + 136.7611142599836, + 833.0576683733934, + 555.5009590279454, + 996.5690121749279, + 799.7589945362965, + 542.5349405392533, + 283.7048374964244, + 297.695231310366, + 566.3853743554927, + 665.4044506282155, + 814.7358381931654, + 285.5366437172383, + 355.6518471787073, + 406.95454724203495, + 185.20518621701189, + 557.5054723816321, + 97.03195108153383, + 73.44405598892234, + 70.51174863584086, + 559.3771777353215, + 717.126905061601, + 248.37183745602587, + 413.2342432790439, + 83.78293543813575, + 574.118261215213, + 36.00441679401889, + 64.18802984845517, + 851.1985085136262, + 874.5702228951003, + 718.9360216756398, + 563.7841966530445, + 478.31990981061756, + 317.45755261498243, + 394.9542348177366, + 687.3424174834047, + 541.6080073818115, + 609.7731700104093, + 686.1320276415877, + 177.30807238536616, + 658.959973343272, + 318.09034737024876, + 944.4818116092766, + 12.441130475407181, + 163.47373906341255, + 929.8030476496999, + 132.87669738227314, + 327.9093450590188, + 888.3919739366945, + 604.7545315226565, + 437.62161755341975, + 961.3015098162545, + 682.6765793254605, + 334.80586342765207, + 323.62437224388583, + 870.767232854674, + 94.01594058572893, + 292.6148490535354, + 706.9742481650951, + 972.4191250879263, + 824.3688040800554, + 955.5557575153504, + 211.88942197988925, + 213.13717770756102, + 513.61227313629, + 423.02460421344256, + 803.7611649326221, + 322.37591539281607, + 430.56579518344904, + 679.0081289956289, + 50.283774129619815, + 826.459683263573, + 44.40057389207808, + 636.4307962874378, + 766.6442699973943, + 133.15060881321483, + 144.36757668063905, + 355.2519029209088, + 236.69067419092528, + 254.05234939051059, + 719.7850961005768, + 292.13651556542254, + 750.8815401759532, + 331.77151800392323, + 272.69503161430816, + 164.48322718111243, + 542.636669797445, + 292.4496176486276, + 770.6028220862052, + 504.71216992399223, + 81.5602550723059, + 131.31787516673853, + 153.1266288826205, + 409.1660758625184, + 733.0756056583455, + 298.23136972121966, + 837.5475289844959, + 835.8933569812572, + 452.4143396999175, + 593.7559551145422, + 413.7094157777811, + 814.9571598241487, + 144.9718574184441, + 614.9602776827563, + 480.87336813394535, + 168.39992346787946, + 673.5114395460117, + 759.0316985515063, + 423.82623720442723, + 509.9324579994481, + 80.63814293461846, + 137.8287747794702, + 662.7838144404594, + 872.8325315338114, + 386.4637537697182, + 193.16552029903866, + 784.6720104351514, + 621.0884650056569, + 669.3194116485051, + 348.1388889307992, + 792.4537246941328, + 450.6943275254314, + 61.54990911697655, + 412.0834029995607, + 571.3923671545957, + 919.4152284004073, + 670.6342280318704, + 704.0322072762208, + 30.834877312645336, + 554.0548818731858, + 286.64596028346244, + 66.34638566109186, + 112.78262315017517, + 328.49699120554254, + 904.811908244425, + 307.7082495625574, + 292.476480185065, + 281.88956709277744, + 493.47580492240263, + 543.6238564473343, + 27.542481067342695, + 175.96951869170297, + 897.9895425781405, + 412.07286468727955, + 953.0461601905062, + 624.7220259613125, + 599.5524272987242, + 227.41020796392664, + 140.89294079960158, + 331.366448090177, + 23.82744087530886, + 180.99617116738386, + 530.4523565879744, + 456.58596993329917, + 722.4294830940376, + 758.1667836029984, + 994.1999067942988, + 705.7628047988632, + 986.5574678335613, + 855.2924903661784, + 683.6236450960189, + 530.7335077818451, + 671.6687534341876, + 254.337089410567, + 566.112017135454, + 26.07020937794946, + 192.0024674291466, + 686.3150284161869, + 328.64233008962117, + 788.6603562271135, + 867.0969299117345, + 133.72586238225793, + 901.1520688124095 + ], + "yaxis": "y" + }, + { + "hovertemplate": "variable=auxiliary_power_kw
index=%{x}
value=%{y}", + "legendgroup": "auxiliary_power_kw", + "line": { + "color": "#EF553B", + "dash": "solid" + }, + "marker": { + "symbol": "circle" + }, + "mode": "lines", + "name": "auxiliary_power_kw", + "showlegend": true, + "type": "scattergl", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + "xaxis": "x", + "y": [ + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300, + 300 + ], + "yaxis": "y" + }, + { + "hovertemplate": "variable=speed_kn
index=%{x}
value=%{y}", + "legendgroup": "speed_kn", + "line": { + "color": "#00cc96", + "dash": "solid" + }, + "marker": { + "symbol": "circle" + }, + "mode": "lines", + "name": "speed_kn", + "showlegend": true, + "type": "scattergl", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + "xaxis": "x", + "y": [ + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.2332677169117443, + 2.6852035377866406, + 3.137139358661537, + 3.589075179536433, + 4.041011000411329, + 4.492946821286226, + 4.944882642161122, + 5.396818463036018, + 5.848754283910914, + 6.30069010478581, + 6.752625925660707, + 7.204561746535603, + 7.656497567410499, + 8.108433388285395, + 8.560369209160292, + 9.012305030035188, + 9.464240850910084, + 9.91617667178498, + 10.368112492659876, + 10.820048313534773, + 11.271984134409669, + 11.723919955284565, + 12.175855776159462, + 12.627791597034358, + 13.079727417909254, + 13.53166323878415, + 13.983599059659046, + 14.435534880533943, + 14.887470701408839, + 15.339406522283735, + 15.791342343158632, + 16.24327816403353, + 16.695213984908424, + 17.14714980578332, + 17.599085626658216, + 18.051021447533113, + 18.502957268408007, + 18.954893089282905, + 19.406828910157802, + 17.84531747787087, + 16.28380604558394, + 14.72229461329701, + 13.160783181010078, + 11.599271748723147, + 10.037760316436218, + 8.476248884149287, + 10.55917554519834, + 12.642102206247392, + 14.725028867296444, + 16.807955528345495, + 18.89088218939455, + 18.936881298091727, + 18.9828804067889, + 19.02887951548608, + 19.074878624183256, + 19.12087773288043, + 19.166876841577608, + 19.212875950274782, + 19.25887505897196, + 19.201589361150347, + 19.14430366332873, + 19.08701796550712, + 19.029732267685507, + 18.97244656986389, + 18.91516087204228, + 18.857875174220666, + 18.800589476399054, + 18.743303778577438, + 18.686018080755826, + 18.628732382934214, + 18.571446685112598, + 18.514160987290985, + 18.456875289469373, + 18.399589591647757, + 18.342303893826145, + 18.285018196004533, + 18.227732498182917, + 18.170446800361304, + 18.113161102539692, + 18.05587540471808, + 17.998589706896464, + 17.94130400907485, + 17.88401831125324, + 17.826732613431624, + 17.76944691561001, + 17.7121612177884, + 17.654875519966783, + 17.59758982214517, + 16.650205171078532, + 15.70282052001189, + 14.755435868945252, + 13.808051217878612, + 13.435576824272061, + 13.063102430665511, + 12.69062803705896, + 12.318153643452408, + 11.945679249845858, + 11.573204856239308, + 11.200730462632757, + 10.828256069026207, + 10.455781675419654, + 10.083307281813104, + 9.710832888206554, + 9.338358494600003, + 8.965884100993453, + 8.5934097073869, + 8.22093531378035, + 7.8484609201738, + 7.475986526567249, + 7.103512132960698, + 6.731037739354147, + 6.358563345747596, + 5.986088952141046, + 5.613614558534495, + 5.241140164927945, + 4.868665771321394, + 4.496191377714842, + 4.123716984108292, + 4.705665514377078, + 5.2876140446458635, + 5.869562574914649, + 6.451511105183435, + 7.033459635452221, + 7.615408165721007, + 8.197356695989793, + 8.779305226258579, + 9.361253756527365, + 9.94320228679615, + 10.525150817064937, + 11.107099347333723, + 11.689047877602508, + 12.270996407871294, + 12.66721137892468, + 13.063426349978066, + 13.459641321031452, + 13.85585629208484, + 14.252071263138225, + 14.64828623419161, + 15.044501205244996, + 15.440716176298382, + 15.83693114735177, + 16.233146118405156, + 16.62936108945854, + 17.025576060511927, + 17.421791031565313, + 17.8180060026187, + 13.33133048989264, + 8.844654977166579, + 11.6065134058278, + 14.368371834489022, + 17.130230263150242, + 17.166078075838687, + 17.201925888527136, + 17.23777370121558, + 17.27362151390403, + 17.309469326592474, + 17.345317139280922, + 17.381164951969367, + 17.417012764657816, + 17.45286057734626, + 17.48870839003471, + 17.524556202723154, + 17.5604040154116, + 17.596251828100048, + 17.632099640788493, + 17.66794745347694, + 17.703795266165386, + 17.739643078853835, + 17.77549089154228, + 17.811338704230728, + 17.847186516919173, + 17.88303432960762, + 17.918882142296066, + 17.954729954984515, + 17.99057776767296, + 18.026425580361405, + 18.062273393049853, + 18.0981212057383, + 18.133969018426747, + 18.16981683111519, + 18.20566464380364, + 18.241512456492085, + 18.277360269180534, + 18.31320808186898, + 18.349055894557427, + 18.384903707245872, + 18.420751519934317, + 18.456599332622766, + 18.49244714531121, + 18.52829495799966, + 18.564142770688104, + 18.599990583376552, + 18.635838396064997, + 18.671686208753446, + 18.70753402144189, + 18.74338183413034, + 18.779229646818784, + 18.81507745950723, + 18.850925272195678, + 18.886773084884123, + 18.92262089757257, + 18.958468710261016, + 18.994316522949465, + 19.03016433563791, + 19.066012148326358, + 19.101859961014803, + 19.13770777370325, + 19.173555586391696, + 18.18524552723358, + 17.19693546807546, + 16.208625408917342, + 15.220315349759225, + 14.232005290601107, + 13.243695231442988, + 12.255385172284871, + 11.267075113126753, + 10.278765053968634, + 9.290454994810517, + 8.302144935652398, + 11.313201935541182, + 14.324258935429963, + 17.335315935318746, + 16.313038620785058, + 15.290761306251367, + 14.268483991717677, + 13.246206677183988, + 12.2239293626503, + 11.201652048116609, + 10.179374733582918, + 9.15709741904923, + 8.31990967341297, + 7.482721927776712, + 6.645534182140453, + 5.808346436504195, + 4.971158690867936, + 4.1339709452316775, + 3.296783199595419, + 2.4595954539591602, + 1.6224077083229016, + 0.785219962686643, + 0.7414868342233519, + 0.697753705760061, + 0.65402057729677, + 0.8576323219872859, + 1.0612440666778018, + 1.2648558113683177, + 1.4684675560588336, + 1.6720793007493495, + 1.8756910454398654, + 2.0793027901303813, + 2.2829145348208972, + 2.486526279511413, + 2.690138024201929, + 2.893749768892445, + 3.097361513582961, + 3.3009732582734768, + 3.5045850029639927, + 3.7081967476545086, + 2.5870630755530275, + 1.4659294034515469, + 1.9541396382728318, + 2.4423498730941167, + 2.930560107915402, + 3.4187703427366865, + 3.906980577557971, + 4.395190812379257, + 4.883401047200541, + 5.371611282021826, + 5.859821516843111, + 6.348031751664395, + 6.836241986485681, + 7.324452221306966, + 7.81266245612825, + 8.300872690949536, + 8.78908292577082, + 9.277293160592105, + 9.76550339541339, + 11.445428854431471, + 13.125354313449552, + 14.805279772467633, + 16.485205231485715, + 14.926449436089039, + 13.367693640692362, + 11.808937845295684, + 10.250182049899008, + 11.319401638287147, + 12.388621226675285, + 13.457840815063424, + 14.527060403451562, + 15.596279991839701, + 16.665499580227838, + 17.734719168615978, + 15.993300513622577, + 14.251881858629176, + 12.510463203635776, + 10.769044548642375, + 17.800881858460112, + 11.7652194814976, + 9.147226190014706, + 6.529232898531811, + 3.911239607048917, + 1.2932463155660234, + 1.4638780557410453, + 1.634509795916067, + 1.8051415360910887, + 1.9757732762661107, + 3.3972707744108783, + 4.818768272555646, + 6.240265770700414, + 7.661763268845181, + 9.083260766989948, + 10.504758265134717, + 13.104262392640567, + 15.703766520146416, + 15.410642303264563, + 15.11751808638271, + 14.824393869500856, + 14.531269652619002, + 14.238145435737147, + 13.945021218855294, + 13.65189700197344, + 13.358772785091586, + 13.065648568209733, + 11.836870220879286, + 10.608091873548837, + 9.37931352621839, + 8.150535178887942, + 6.921756831557495, + 5.692978484227047, + 4.464200136896599, + 5.8630829454923274, + 7.261965754088056, + 8.660848562683784, + 10.059731371279511, + 11.45861417987524, + 12.857496988470968, + 14.256379797066698, + 15.655262605662426, + 15.846643569100683, + 16.03802453253894, + 16.2294054959772, + 16.420786459415456, + 16.612167422853716, + 16.803548386291975, + 16.99492934973023, + 17.18631031316849, + 17.377691276606747, + 17.569072240045006, + 17.760453203483266, + 17.951834166921522, + 18.14321513035978, + 18.334596093798037, + 18.525977057236297, + 16.91512923257244, + 15.304281407908583, + 13.693433583244726, + 12.08258575858087, + 10.471737933917012, + 8.860890109253155, + 7.2500422845892984, + 5.6391944599254415, + 4.028346635261585, + 2.4174988105977278, + 0.8066509859338722, + 15.838721665167657, + 16.842520711483925, + 17.030794452045917, + 17.219068192607907, + 17.4073419331699, + 17.595615673731892, + 17.783889414293885, + 17.972163154855878, + 18.160436895417867, + 18.34871063597986, + 15.850827412092023, + 13.352944188204187, + 10.85506096431635, + 11.909460378942686, + 12.963859793569021, + 14.018259208195358, + 15.072658622821695, + 15.635813605284302, + 16.198968587746908, + 16.762123570209514, + 15.430685177249288, + 14.099246784289061, + 12.767808391328835, + 11.436369998368608, + 10.104931605408382, + 8.773493212448157, + 7.442054819487931, + 6.110616426527704, + 4.779178033567478, + 3.447739640607251, + 2.1163012476470247, + 0.7848628546867986, + 0.6891816681788032, + 0.5935004816708078, + 0.9730709828190964, + 1.352641483967385, + 2.4630841334783327, + 3.5735267829892807, + 4.683969432500229, + 5.794412082011176, + 6.904854731522125, + 8.015297381033072, + 9.12574003054402, + 10.236182680054968, + 10.949243845486217, + 11.662305010917466, + 12.375366176348715, + 13.088427341779964, + 13.801488507211213, + 14.51454967264246, + 15.227610838073709, + 15.940672003504957, + 16.653733168936206, + 17.366794334367455, + 18.079855499798704, + 16.7380288469383, + 15.39620219407789, + 14.054375541217484, + 12.712548888357077, + 11.37072223549667, + 10.028895582636263, + 8.687068929775856, + 7.3452422769154495, + 6.003415624055043, + 4.661588971194637, + 4.789837606564621, + 4.918086241934605, + 5.046334877304589, + 5.174583512674573, + 5.3028321480445575, + 5.431080783414542, + 5.559329418784526, + 5.6875780541545105, + 5.815826689524494, + 5.944075324894478, + 6.0723239602644625, + 6.200572595634447, + 6.328821231004431, + 6.457069866374415, + 6.585318501744399, + 6.713567137114383, + 6.841815772484368, + 6.922697088549814, + 5.022089330749108, + 3.121481572948403, + 1.2208738151476983, + 14.07435298445593, + 13.858132546117748, + 13.641912107779568, + 13.425691669441386, + 13.209471231103207, + 12.993250792765025, + 12.777030354426845, + 12.560809916088663, + 12.344589477750482, + 12.128369039412302, + 11.91214860107412, + 11.69592816273594, + 11.479707724397759, + 6.382017524585829, + 1.2843273247738995, + 2.821706543969057, + 4.359085763164215, + 4.315166087927821, + 4.271246412691427, + 4.227326737455034, + 4.18340706221864, + 4.139487386982246, + 4.639037061372659, + 5.138586735763073, + 5.638136410153486, + 6.137686084543899, + 6.637235758934312, + 7.136785433324725, + 7.636335107715139, + 8.135884782105553, + 8.635434456495965, + 9.134984130886378, + 9.634533805276792, + 10.134083479667204, + 10.633633154057618, + 11.133182828448032, + 11.632732502838444, + 12.132282177228857, + 12.631831851619271, + 13.131381526009683, + 13.630931200400097, + 14.13048087479051, + 18.688834917006965, + 18.42387170632224, + 18.158908495637522, + 17.8939452849528, + 17.62898207426808, + 17.364018863583357, + 17.099055652898635, + 16.834092442213915, + 16.569129231529192, + 16.304166020844473, + 16.03920281015975, + 15.77423959947503, + 15.509276388790308, + 15.244313178105585, + 14.979349967420866, + 14.714386756736143, + 14.449423546051422, + 14.184460335366701, + 13.919497124681978, + 13.654533913997259, + 13.389570703312536, + 13.606659115935074, + 13.823747528557613, + 13.593847662286962, + 13.36394779601631, + 13.13404792974566, + 12.90414806347501, + 12.674248197204358, + 12.145070294610097, + 11.615892392015835, + 11.086714489421574, + 10.557536586827313, + 10.028358684233051, + 9.499180781638788, + 8.970002879044529, + 8.440824976450266, + 7.911647073856005, + 7.382469171261744, + 6.8532912686674825, + 6.32411336607322, + 5.794935463478959, + 5.265757560884698, + 4.736579658290436, + 4.207401755696175, + 3.6782238531019136, + 3.1490459505076522, + 2.619868047913391, + 2.0906901453191296, + 1.5615122427248682, + 1.0323343401306073, + 1.17377505845274, + 1.3152157767748727, + 1.4566564950970051, + 1.5980972134191378, + 1.7395379317412705, + 1.880978650063403, + 2.0224193683855356, + 2.1638600867076683, + 2.305300805029801, + 2.4467415233519336, + 2.5881822416740663, + 2.729622959996199, + 2.8710636783183316, + 3.012504396640464, + 3.1539451149625966, + 3.2953858332847292, + 3.436826551606862, + 3.5782672699289946, + 3.7197079882511273, + 3.86114870657326, + 4.002589424895392, + 4.144030143217525, + 4.2854708615396575, + 4.46981089564485, + 4.654150929750042, + 4.838490963855234, + 5.022830997960427, + 5.207171032065619, + 5.391511066170811, + 5.575851100276004, + 5.760191134381196, + 5.944531168486389, + 6.128871202591581, + 6.313211236696773, + 6.497551270801965, + 6.6818913049071575, + 6.15407935599891, + 5.626267407090663, + 5.098455458182416, + 4.570643509274168, + 4.663646965537902, + 4.756650421801636, + 4.849653878065371, + 4.9426573343291045, + 5.035660790592838, + 5.128664246856572, + 5.221667703120307, + 5.314671159384041, + 5.407674615647775, + 7.631180004853132, + 9.854685394058489, + 12.078190783263846, + 11.712617477544677, + 11.347044171825509, + 10.981470866106342, + 10.615897560387173, + 10.250324254668005, + 9.884750948948838, + 9.51917764322967, + 9.153604337510501, + 8.166311536582256, + 7.1790187356540125, + 6.191725934725769, + 5.204433133797524, + 4.21714033286928, + 3.2298475319410365, + 2.2425547310127913, + 4.561858690490009, + 6.8811626499672265, + 9.200466609444446, + 11.519770568921663, + 13.83907452839888, + 16.1583784878761, + 18.477682447353317, + 18.482837078688704, + 18.487991710024087, + 18.493146341359473, + 18.498300972694857, + 18.503455604030243, + 18.508610235365627, + 18.513764866701013, + 17.814552495215647, + 17.11534012373028, + 16.416127752244915, + 15.716915380759549, + 15.017703009274182, + 14.318490637788818, + 13.619278266303452, + 12.920065894818086, + 12.22085352333272, + 11.521641151847353, + 10.822428780361989, + 10.123216408876623, + 9.424004037391256, + 8.72479166590589, + 8.025579294420524, + 7.326366922935158, + 6.627154551449792, + 5.927942179964425, + 5.228729808479059, + 4.529517436993693, + 3.830305065508326, + 3.916261416749062, + 4.002217767989798, + 4.088174119230534, + 4.17413047047127, + 4.260086821712006, + 4.346043172952742, + 4.431999524193478, + 4.517955875434215, + 4.60391222667495, + 4.689868577915687, + 4.775824929156422, + 4.8617812803971585, + 4.947737631637894, + 5.0336939828786305, + 5.119650334119367, + 5.205606685360102, + 5.291563036600838, + 5.377519387841574, + 5.463475739082311, + 5.549432090323046, + 5.635388441563783, + 5.721344792804519, + 5.807301144045255, + 5.89325749528599, + 5.979213846526727, + 6.065170197767463, + 6.1511265490081986, + 6.237082900248935, + 6.323039251489671, + 6.408995602730407, + 6.4949519539711424, + 6.580908305211879, + 6.666864656452615, + 6.752821007693351, + 6.4102242717066655, + 6.06762753571998, + 5.725030799733295, + 5.38243406374661, + 5.039837327759924, + 4.697240591773239, + 4.354643855786554, + 4.012047119799869, + 4.779478013083063, + 5.546908906366257, + 6.314339799649451, + 7.081770692932645, + 7.849201586215839, + 8.616632479499032, + 9.384063372782226, + 10.15149426606542, + 10.918925159348614, + 11.686356052631808, + 12.453786945915002, + 13.221217839198196, + 13.98864873248139, + 14.756079625764585, + 15.523510519047779, + 16.290941412330973, + 17.058372305614167, + 17.82580319889736, + 18.593234092180555, + 19.36066498546375, + 16.72726230080137, + 14.093859616138996, + 11.460456931476617, + 8.82705424681424, + 6.193651562151864, + 3.5602488774894847, + 5.598358033477427, + 7.636467189465369, + 9.674576345453312, + 11.712685501441255, + 13.750794657429198, + 15.78890381341714, + 17.827012969405082, + 16.94145169494629, + 16.0558904204875, + 15.170329146028708, + 14.284767871569917, + 13.399206597111126, + 12.513645322652334, + 11.628084048193543, + 10.742522773734752, + 9.856961499275961, + 8.97140022481717, + 8.085838950358378, + 7.200277675899587, + 9.720531762058583, + 12.240785848217577, + 14.761039934376573, + 17.28129402053557, + 17.636050073161446, + 17.990806125787323, + 18.3455621784132, + 18.700318231039077, + 19.055074283664954, + 19.40983033629083, + 19.764586388916708, + 19.69455089506622, + 19.624515401215735, + 19.55447990736525, + 19.484444413514762, + 19.414408919664275, + 19.344373425813785, + 19.2743379319633, + 19.204302438112812, + 19.134266944262325, + 19.06423145041184, + 17.699388935282613, + 16.334546420153387, + 14.969703905024163, + 13.604861389894937, + 12.240018874765711, + 10.875176359636487, + 9.510333844507262, + 8.145491329378036, + 6.780648814248811, + 7.623856052914168, + 8.467063291579525, + 9.310270530244882, + 9.947290051018589, + 10.584309571792295, + 11.221329092566002, + 11.126852058406302, + 11.032375024246603, + 10.937897990086903, + 10.843420955927204, + 10.748943921767504, + 10.654466887607803, + 10.559989853448105, + 10.465512819288405, + 9.673509035819858, + 8.88150525235131, + 8.089501468882764, + 7.297497685414217, + 6.50549390194567, + 5.713490118477123, + 4.921486335008576, + 4.129482551540029, + 3.8683396910712498, + 3.607196830602471, + 3.3460539701336915, + 3.0849111096649127, + 2.8237682491961333, + 2.562625388727354, + 2.3014825282585747, + 2.040339667789796, + 1.7791968073210165, + 1.5180539468522376, + 1.2569110863834583, + 0.995768225914679, + 0.7346253654459001, + 0.47348250497712074, + 0.21233964450834142, + 4.533298227020678, + 8.854256809533016, + 13.175215392045352, + 12.596472220200047, + 12.017729048354742, + 11.438985876509436, + 10.860242704664131, + 10.281499532818826, + 9.70275636097352, + 9.124013189128217, + 8.54527001728291, + 7.966526845437605, + 7.3877836735923, + 6.809040501746995, + 12.301219808802744, + 13.385434644781892, + 14.46964948076104, + 15.553864316740189, + 16.63807915271934, + 17.722293988698485, + 18.806508824677636, + 18.2146616520322, + 17.62281447938676, + 17.03096730674132, + 16.439120134095884, + 15.847272961450447, + 15.255425788805008, + 14.663578616159569, + 14.071731443514132, + 13.479884270868695, + 12.888037098223256, + 12.296189925577817, + 11.70434275293238, + 10.912902647846371, + 10.121462542760364, + 9.330022437674355, + 8.538582332588348, + 7.747142227502339, + 6.95570212241633, + 6.164262017330322, + 6.709543221246008, + 7.254824425161695, + 7.800105629077382, + 8.345386832993068, + 8.890668036908753, + 9.43594924082444, + 9.981230444740127, + 10.526511648655813, + 11.0717928525715, + 12.961542382630086, + 14.851291912688673, + 16.74104144274726, + 18.630790972805844, + 15.973061846962175, + 13.315332721118505, + 12.051811290999698, + 10.78828986088089, + 9.524768430762084, + 8.261247000643277, + 6.997725570524469, + 5.734204140405662, + 4.470682710286855, + 3.207161280168048, + 1.943639850049241, + 0.6801184199304333, + 0.6403025622604933, + 0.6004867045905533, + 0.5606708469206133, + 0.5208549892506733, + 0.4810391315807333, + 0.44122327391079336, + 0.40140741624085335, + 0.36159155857091335, + 0.32177570090097335, + 0.28195984323103335, + 0.24214398556109334, + 0.2023281278911534, + 0.1625122702212134, + 0.6879682716954958, + 1.2134242731697782, + 1.7388802746440606, + 2.264336276118343, + 2.789792277592625, + 3.3152482790669078, + 3.8407042805411904, + 4.366160282015473, + 4.891616283489755, + 5.417072284964037, + 5.9425282864383195, + 6.467984287912602, + 6.993440289386884, + 7.518896290861168, + 8.04435229233545, + 8.569808293809732, + 9.095264295284014, + 9.620720296758297, + 10.146176298232579, + 10.671632299706861, + 11.197088301181145, + 11.722544302655427, + 12.24800030412971, + 12.773456305603991, + 13.298912307078274, + 13.824368308552556, + 14.34982431002684, + 10.822817855471989, + 7.295811400917137, + 3.7688049463622852, + 9.02661148855985, + 14.284418030757415, + 19.54222457295498, + 17.373257272006413, + 15.204289971057847, + 13.03532267010928, + 12.531442565048161, + 12.027562459987042, + 11.52368235492592, + 11.019802249864801, + 10.515922144803682, + 10.01204203974256, + 9.508161934681441, + 9.004281829620322, + 8.920941047585536, + 8.837600265550751, + 8.754259483515966, + 8.670918701481183, + 8.587577919446398, + 8.504237137411613, + 8.420896355376827, + 8.337555573342042, + 8.254214791307257, + 8.170874009272472, + 8.087533227237687, + 8.004192445202904, + 7.9208516631681185, + 7.837510881133333, + 7.754170099098548, + 7.670829317063763, + 7.587488535028978, + 7.504147752994194, + 7.420806970959409, + 7.3374661889246235, + 7.254125406889839, + 7.170784624855054, + 7.087443842820269, + 7.004103060785484, + 6.920762278750699, + 6.837421496715915, + 6.7540807146811295, + 6.670739932646345, + 6.58739915061156, + 6.504058368576775, + 8.6184748115973, + 10.732891254617826, + 12.847307697638353, + 14.961724140658879, + 17.076140583679404, + 19.19055702669993, + 18.333210194098363, + 17.475863361496796, + 16.618516528895228, + 15.761169696293656, + 14.903822863692088, + 14.04647603109052, + 13.189129198488953, + 12.331782365887383, + 11.474435533285813, + 10.617088700684246, + 9.759741868082678, + 8.90239503548111, + 8.04504820287954, + 7.187701370277972, + 6.330354537676403, + 5.473007705074835, + 4.615660872473267, + 3.7583140398716974, + 2.900967207270128, + 2.04362037466856, + 1.1862735420669934, + 1.1862735420669934, + 1.1862735420669934, + 1.1862735420669934, + 1.1862735420669934, + 1.1862735420669934, + 1.1862735420669934, + 1.1862735420669934 + ], + "yaxis": "y" + }, + { + "hovertemplate": "variable=draft_m
index=%{x}
value=%{y}", + "legendgroup": "draft_m", + "line": { + "color": "#ab63fa", + "dash": "solid" + }, + "marker": { + "symbol": "circle" + }, + "mode": "lines", + "name": "draft_m", + "showlegend": true, + "type": "scattergl", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + "xaxis": "x", + "y": [ + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8582253195976086, + 0.8926042766232962, + 0.9269832336489837, + 0.9613621906746712, + 0.9957411477003588, + 1.0301201047260464, + 1.064499061751734, + 1.0988780187774214, + 1.133256975803109, + 1.1676359328287966, + 1.202014889854484, + 1.2363938468801716, + 1.2707728039058592, + 1.3051517609315468, + 1.3395307179572344, + 1.3739096749829218, + 1.4082886320086094, + 1.442667589034297, + 1.4770465460599844, + 1.511425503085672, + 1.5458044601113596, + 1.5801834171370472, + 1.6145623741627348, + 1.6489413311884222, + 1.6833202882141098, + 1.7176992452397974, + 1.7520782022654848, + 1.7864571592911724, + 1.82083611631686, + 1.8552150733425476, + 1.889594030368235, + 1.9239729873939226, + 1.9583519444196102, + 1.9927309014452979, + 2.0271098584709852, + 2.0614888154966726, + 2.0958677725223605, + 2.1302467295480483, + 2.1646256865737357, + 3.13656883151367, + 4.108511976453604, + 5.080455121393538, + 6.052398266333473, + 7.024341411273406, + 7.9962845562133404, + 8.968227701153275, + 8.270351786631949, + 7.572475872110621, + 6.874599957589295, + 6.176724043067968, + 5.478848128546641, + 5.90694579666293, + 6.335043464779218, + 6.763141132895507, + 7.191238801011796, + 7.6193364691280845, + 8.047434137244373, + 8.475531805360662, + 8.90362947347695, + 8.820816061363988, + 8.738002649251026, + 8.655189237138064, + 8.572375825025102, + 8.48956241291214, + 8.406749000799177, + 8.323935588686215, + 8.241122176573255, + 8.158308764460292, + 8.07549535234733, + 7.992681940234368, + 7.909868528121406, + 7.827055116008443, + 7.744241703895481, + 7.661428291782519, + 7.578614879669557, + 7.4958014675565945, + 7.412988055443632, + 7.330174643330671, + 7.247361231217709, + 7.1645478191047465, + 7.081734406991784, + 6.998920994878822, + 6.916107582765861, + 6.8332941706528985, + 6.750480758539936, + 6.667667346426974, + 6.584853934314012, + 6.5020405222010496, + 5.610023173889897, + 4.718005825578745, + 3.8259884772675923, + 2.93397112895644, + 2.9210739293231036, + 2.908176729689767, + 2.8952795300564307, + 2.882382330423094, + 2.8694851307897578, + 2.8565879311564215, + 2.843690731523085, + 2.8307935318897486, + 2.8178963322564123, + 2.8049991326230757, + 2.7921019329897394, + 2.7792047333564027, + 2.7663075337230665, + 2.7534103340897302, + 2.7405131344563936, + 2.7276159348230573, + 2.714718735189721, + 2.7018215355563844, + 2.688924335923048, + 2.6760271362897114, + 2.663129936656375, + 2.650232737023039, + 2.6373355373897023, + 2.624438337756366, + 2.6115411381230293, + 2.598643938489693, + 2.4830862146564674, + 2.3675284908232412, + 2.2519707669900155, + 2.13641304315679, + 2.020855319323564, + 1.905297595490338, + 1.7897398716571122, + 1.6741821478238865, + 1.5586244239906606, + 1.4430667001574347, + 1.327508976324209, + 1.211951252490983, + 1.0963935286577573, + 0.9808358048245314, + 1.4161798299187451, + 1.851523855012959, + 2.286867880107173, + 2.7222119052013865, + 3.1575559302956004, + 3.5928999553898144, + 4.028243980484028, + 4.4635880055782415, + 4.898932030672456, + 5.3342760557666695, + 5.769620080860883, + 6.2049641059550975, + 6.640308131049311, + 7.075652156143525, + 6.183586152145367, + 5.29152014814721, + 4.325290584212272, + 3.359061020277334, + 2.392831456342396, + 2.3679415132606403, + 2.3430515701788845, + 2.318161627097129, + 2.293271684015373, + 2.2683817409336173, + 2.2434917978518616, + 2.2186018547701054, + 2.1937119116883497, + 2.168821968606594, + 2.143932025524838, + 2.1190420824430825, + 2.0941521393613267, + 2.069262196279571, + 2.0443722531978152, + 2.0194823101160595, + 1.9945923670343035, + 1.9697024239525478, + 1.944812480870792, + 1.9199225377890363, + 1.8950325947072804, + 1.8701426516255246, + 1.8452527085437689, + 1.8203627654620131, + 1.7954728223802574, + 1.7705828792985017, + 1.745692936216746, + 1.7208029931349902, + 1.6959130500532342, + 1.6710231069714785, + 1.6461331638897228, + 1.6212432208079668, + 1.596353277726211, + 1.5714633346444553, + 1.5465733915626996, + 1.5216834484809438, + 1.496793505399188, + 1.4719035623174324, + 1.4470136192356766, + 1.4221236761539209, + 1.397233733072165, + 1.3723437899904092, + 1.3474538469086534, + 1.3225639038268977, + 1.2976739607451417, + 1.272784017663386, + 1.2478940745816303, + 1.2230041314998745, + 1.1981141884181188, + 1.173224245336363, + 1.148334302254607, + 1.1234443591728513, + 1.0985544160910956, + 1.0736644730093399, + 1.0487745299275841, + 1.0238845868458284, + 0.9989946437640724, + 0.9741047006823167, + 1.6711814403571794, + 2.368258180032042, + 3.065334919706905, + 3.7624116593817676, + 4.45948839905663, + 5.156565138731493, + 5.853641878406355, + 6.550718618081218, + 7.247795357756081, + 7.9448720974309435, + 8.641948837105806, + 7.882778235188616, + 7.123607633271427, + 6.364437031354237, + 6.090827435982179, + 5.817217840610121, + 5.543608245238063, + 5.269998649866005, + 4.996389054493947, + 4.722779459121888, + 4.44916986374983, + 4.175560268377772, + 4.448829496009066, + 4.722098723640359, + 4.995367951271652, + 5.268637178902945, + 5.541906406534238, + 5.815175634165532, + 6.088444861796825, + 6.3617140894281174, + 6.634983317059412, + 6.908252544690704, + 7.0354630075600495, + 7.162673470429396, + 7.289883933298741, + 7.467546379521587, + 7.645208825744433, + 7.822871271967278, + 8.000533718190125, + 8.17819616441297, + 8.355858610635817, + 8.533521056858662, + 8.711183503081507, + 8.888845949304354, + 9.0665083955272, + 9.244170841750044, + 9.421833287972891, + 9.599495734195736, + 9.777158180418583, + 9.954820626641428, + 9.69051251324914, + 9.426204399856848, + 9.424788722839441, + 9.423373045822036, + 9.421957368804629, + 9.420541691787221, + 9.419126014769814, + 9.417710337752409, + 9.416294660735002, + 9.414878983717594, + 9.413463306700189, + 9.412047629682782, + 9.410631952665375, + 9.40921627564797, + 9.407800598630562, + 9.406384921613155, + 9.404969244595748, + 9.403553567578342, + 9.402137890560935, + 7.236173850236409, + 5.0702098099118835, + 2.904245769587358, + 0.7382817292628319, + 2.0811954594833293, + 3.4241091897038265, + 4.767022919924324, + 6.109936650144822, + 6.0273557375503675, + 5.944774824955914, + 5.86219391236146, + 5.779612999767005, + 5.697032087172551, + 5.614451174578098, + 5.531870261983643, + 5.307587256080655, + 5.083304250177667, + 4.85902124427468, + 4.634738238371692, + 9.743632146034928, + 4.316679298208071, + 4.695476878051263, + 5.074274457894455, + 5.4530720377376465, + 5.831869617580838, + 5.678796689721181, + 5.525723761861524, + 5.372650834001867, + 5.219577906142209, + 5.407779244302302, + 5.595980582462393, + 5.784181920622485, + 5.972383258782577, + 6.160584596942669, + 6.348785935102761, + 3.3359497055560334, + 0.32311347600930573, + 0.62128894209607, + 0.9194644081828343, + 1.2176398742695986, + 1.5158153403563628, + 1.8139908064431272, + 2.1121662725298913, + 2.4103417386166557, + 2.70851720470342, + 3.0066926707901844, + 3.790945875718649, + 4.5751990806471134, + 5.359452285575578, + 6.143705490504043, + 6.927958695432507, + 7.712211900360972, + 8.496465105289436, + 7.865532136843386, + 7.234599168397336, + 6.603666199951285, + 5.972733231505235, + 5.341800263059185, + 4.710867294613134, + 4.079934326167084, + 3.449001357721034, + 3.724080647321446, + 3.9991599369218576, + 4.274239226522269, + 4.549318516122681, + 4.824397805723093, + 5.099477095323505, + 5.374556384923917, + 5.649635674524328, + 5.924714964124741, + 6.199794253725152, + 6.474873543325564, + 6.749952832925976, + 7.025032122526387, + 7.3001114121268, + 7.575190701727211, + 6.992443365204008, + 6.409696028680806, + 5.826948692157604, + 5.2442013556344005, + 4.661454019111199, + 4.078706682587996, + 3.4959593460647937, + 2.913212009541591, + 2.3304646730183887, + 1.7477173364951861, + 1.1649699999719831, + 4.836321670576375, + 9.683555185724487, + 8.546716128282341, + 7.409877070840196, + 6.27303801339805, + 5.136198955955905, + 3.9993598985137595, + 2.862520841071614, + 1.7256817836294687, + 0.588842726187323, + 2.8130254400950623, + 5.037208154002801, + 7.26139086791054, + 7.824478607196127, + 8.387566346481714, + 8.950654085767301, + 9.513741825052888, + 8.828814683317828, + 8.14388754158277, + 7.458960399847711, + 7.657155769867287, + 7.855351139886864, + 8.05354650990644, + 8.251741879926016, + 8.449937249945592, + 8.64813261996517, + 8.846327989984745, + 9.044523360004321, + 9.242718730023897, + 9.440914100043475, + 9.639109470063051, + 9.837304840082627, + 6.699444692335723, + 3.5615845445888183, + 6.305769963280408, + 9.049955381971998, + 9.156325016777938, + 9.262694651583876, + 9.369064286389815, + 9.475433921195755, + 9.581803556001695, + 9.688173190807634, + 9.794542825613572, + 9.900912460419512, + 9.208187533968092, + 8.515462607516671, + 7.8227376810652505, + 7.13001275461383, + 6.437287828162409, + 5.744562901710989, + 5.051837975259568, + 4.3591130488081475, + 3.666388122356727, + 2.9736631959053064, + 2.280938269453886, + 2.9645379538229863, + 3.648137638192087, + 4.331737322561188, + 5.015337006930288, + 5.698936691299389, + 6.38253637566849, + 7.06613606003759, + 7.749735744406691, + 8.433335428775791, + 9.116935113144892, + 8.860162097728931, + 8.603389082312972, + 8.346616066897012, + 8.08984305148105, + 7.833070036065091, + 7.576297020649131, + 7.31952400523317, + 7.062750989817209, + 6.805977974401249, + 6.549204958985289, + 6.292431943569328, + 6.035658928153368, + 5.778885912737408, + 5.522112897321447, + 5.265339881905486, + 5.008566866489526, + 4.751793851073566, + 6.62162516272793, + 5.1507033129489574, + 3.679781463169985, + 2.208859613391012, + 5.426216727314604, + 5.177624736031982, + 4.9290327447493585, + 4.680440753466735, + 4.431848762184113, + 4.18325677090149, + 3.934664779618867, + 3.686072788336244, + 3.437480797053621, + 3.1888888057709983, + 2.9402968144883754, + 2.6917048232057526, + 2.4431128319231297, + 4.637524210199659, + 6.831935588476188, + 6.182417824357369, + 5.53290006023855, + 5.394879614314893, + 5.256859168391236, + 5.1188387224675775, + 4.98081827654392, + 4.842797830620263, + 4.642656386456943, + 4.442514942293623, + 4.242373498130302, + 4.042232053966982, + 3.8420906098036616, + 3.6419491656403413, + 3.441807721477021, + 3.241666277313701, + 3.0415248331503806, + 2.8413833889870603, + 2.64124194482374, + 2.4411005006604194, + 2.240959056497099, + 2.040817612333779, + 1.8406761681704586, + 1.6405347240071384, + 1.4403932798438182, + 1.240251835680498, + 1.0401103915171777, + 0.8399689473538574, + 3.174953345788254, + 3.058774292973673, + 2.942595240159092, + 2.826416187344511, + 2.71023713452993, + 2.5940580817153496, + 2.4778790289007686, + 2.3616999760861876, + 2.2455209232716067, + 2.1293418704570257, + 2.0131628176424448, + 1.8969837648278638, + 1.7808047120132828, + 1.6646256591987019, + 1.5484466063841211, + 1.4322675535695402, + 1.3160885007549592, + 1.1999094479403782, + 1.0837303951257975, + 0.9675513423112165, + 0.8513722894966358, + 4.12194328237634, + 7.392514275256044, + 6.642085582685381, + 5.891656890114716, + 5.141228197544053, + 4.390799504973389, + 3.6403708124027254, + 3.7197254465798104, + 3.799080080756896, + 3.878434714933981, + 3.9577893491110663, + 4.037143983288151, + 4.116498617465236, + 4.195853251642322, + 4.275207885819407, + 4.354562519996492, + 4.433917154173577, + 4.513271788350663, + 4.592626422527747, + 4.6719810567048325, + 4.751335690881918, + 4.8306903250590025, + 4.910044959236088, + 4.989399593413173, + 5.068754227590258, + 5.148108861767343, + 5.227463495944429, + 5.306818130121513, + 5.386172764298599, + 5.294036821519336, + 5.201900878740075, + 5.109764935960812, + 5.0176289931815505, + 4.925493050402288, + 4.833357107623026, + 4.741221164843764, + 4.649085222064502, + 4.55694927928524, + 4.464813336505978, + 4.372677393726716, + 4.280541450947454, + 4.1884055081681915, + 4.09626956538893, + 4.004133622609667, + 3.9119976798304057, + 3.819861737051143, + 3.7277257942718816, + 3.635589851492619, + 3.5434539087133574, + 3.451317965934095, + 3.359182023154833, + 3.2670460803755708, + 3.5034985507752547, + 3.7399510211749387, + 3.9764034915746227, + 4.212855961974307, + 4.449308432373991, + 4.685760902773675, + 4.922213373173359, + 5.158665843573043, + 5.395118313972727, + 5.6315707843724105, + 5.868023254772095, + 6.104475725171779, + 6.340928195571463, + 6.128223869920678, + 5.915519544269893, + 5.702815218619107, + 5.490110892968322, + 5.643451085816266, + 5.796791278664209, + 5.950131471512153, + 6.103471664360096, + 6.25681185720804, + 6.4101520500559825, + 6.563492242903926, + 6.71683243575187, + 6.870172628599813, + 5.569400461002628, + 4.268628293405442, + 2.967856125808257, + 2.852269761461652, + 2.7366833971150477, + 2.621097032768443, + 2.505510668421838, + 2.3899243040752336, + 2.2743379397286287, + 2.1587515753820243, + 2.0431652110354195, + 2.750348450266851, + 3.4575316894982833, + 4.164714928729715, + 4.871898167961147, + 5.579081407192579, + 6.286264646424011, + 6.993447885655443, + 6.180027710111795, + 5.366607534568148, + 4.5531873590245, + 3.739767183480853, + 2.9263470079372054, + 2.1129268323935575, + 1.2995066568499103, + 1.9776994201894824, + 2.6558921835290548, + 3.334084946868627, + 4.012277710208199, + 4.690470473547771, + 5.368663236887343, + 6.046856000226915, + 6.074394268444375, + 6.101932536661835, + 6.129470804879294, + 6.157009073096754, + 6.184547341314214, + 6.212085609531673, + 6.239623877749133, + 6.2671621459665925, + 6.294700414184052, + 6.322238682401512, + 6.3497769506189705, + 6.37731521883643, + 6.40485348705389, + 6.432391755271349, + 6.459930023488809, + 6.487468291706269, + 6.515006559923728, + 6.542544828141188, + 6.570083096358648, + 6.597621364576107, + 6.625159632793567, + 6.4730432400406475, + 6.320926847287729, + 6.1688104545348095, + 6.016694061781891, + 5.8645776690289715, + 5.712461276276052, + 5.560344883523133, + 5.408228490770214, + 5.2561120980172955, + 5.103995705264376, + 4.951879312511457, + 4.799762919758537, + 4.647646527005619, + 4.495530134252699, + 4.343413741499781, + 4.191297348746861, + 4.039180955993942, + 3.8870645632410232, + 3.734948170488104, + 3.582831777735185, + 3.430715384982266, + 3.2785989922293464, + 3.1264825994764274, + 2.9743662067235084, + 2.8222498139705894, + 2.6701334212176704, + 2.518017028464751, + 2.3659006357118315, + 2.213784242958913, + 2.0616678502059935, + 1.909551457453075, + 1.7574350647001555, + 1.605318671947236, + 1.4532022791943178, + 1.6867558401840683, + 1.9203094011738189, + 2.1538629621635694, + 2.38741652315332, + 2.620970084143071, + 2.8545236451328213, + 3.0880772061225716, + 3.3216307671123224, + 3.4044081434642854, + 3.487185519816248, + 3.569962896168211, + 3.652740272520174, + 3.7355176488721367, + 3.8182950252240997, + 3.9010724015760623, + 3.9838497779280253, + 4.066627154279988, + 4.149404530631951, + 4.232181906983914, + 4.314959283335877, + 4.3977366596878396, + 4.480514036039803, + 4.563291412391766, + 4.646068788743729, + 4.728846165095691, + 4.811623541447654, + 4.894400917799617, + 4.97717829415158, + 4.6267157343807535, + 4.276253174609928, + 3.9257906148391015, + 3.575328055068275, + 3.224865495297449, + 2.874402935526623, + 3.817209852670384, + 4.760016769814145, + 5.702823686957906, + 6.645630604101667, + 7.588437521245428, + 8.531244438389189, + 9.47405135553295, + 9.260337352860487, + 9.046623350188026, + 8.832909347515564, + 8.619195344843103, + 8.40548134217064, + 8.19176733949818, + 7.978053336825717, + 7.764339334153255, + 7.550625331480793, + 7.336911328808331, + 7.12319732613587, + 6.909483323463408, + 6.349954323378863, + 5.790425323294317, + 5.230896323209771, + 4.671367323125226, + 5.10161203765507, + 5.531856752184914, + 5.962101466714758, + 6.392346181244601, + 6.822590895774446, + 7.25283561030429, + 7.683080324834133, + 7.48490168816959, + 7.286723051505045, + 7.088544414840501, + 6.890365778175957, + 6.692187141511413, + 6.494008504846869, + 6.295829868182325, + 6.097651231517781, + 5.899472594853236, + 5.701293958188693, + 5.341534844099044, + 4.981775730009397, + 4.622016615919748, + 4.262257501830101, + 3.9024983877404527, + 3.5427392736508043, + 3.1829801595611564, + 2.8232210454715085, + 2.4634619313818606, + 4.938054040471705, + 7.412646149561549, + 9.887238258651394, + 8.734600987990662, + 7.581963717329931, + 6.4293264466692, + 6.6491149566272885, + 6.868903466585376, + 7.088691976543465, + 7.308480486501553, + 7.528268996459641, + 7.748057506417729, + 7.967846016375818, + 8.187634526333905, + 7.480660957266011, + 6.773687388198116, + 6.0667138191302215, + 5.359740250062327, + 4.652766680994432, + 3.9457931119265375, + 3.238819542858643, + 2.531845973790748, + 2.4207000577586357, + 2.309554141726523, + 2.1984082256944104, + 2.087262309662298, + 1.9761163936301853, + 1.8649704775980727, + 1.7538245615659602, + 1.6426786455338476, + 1.531532729501735, + 1.4203868134696225, + 1.3092408974375098, + 1.1980949814053972, + 1.0869490653732847, + 0.9758031493411721, + 0.8646572333090596, + 3.465733617424215, + 6.066810001539371, + 8.667886385654526, + 8.013182985176176, + 7.358479584697827, + 6.7037761842194765, + 6.049072783741128, + 5.394369383262777, + 4.739665982784428, + 4.084962582306078, + 3.4302591818277284, + 2.7755557813493787, + 2.120852380871029, + 1.4661489803926786, + 1.802251829785222, + 2.420332399881167, + 3.038412969977112, + 3.6564935400730567, + 4.274574110169002, + 4.892654680264947, + 5.5107352503608915, + 5.567095492898183, + 5.623455735435474, + 5.6798159779727655, + 5.736176220510057, + 5.792536463047348, + 5.8488967055846395, + 5.905256948121932, + 5.961617190659223, + 6.017977433196514, + 6.074337675733806, + 6.130697918271097, + 6.187058160808388, + 6.047182057823234, + 5.907305954838079, + 5.767429851852924, + 5.627553748867769, + 5.487677645882615, + 5.34780154289746, + 5.207925439912305, + 5.074299070437606, + 4.940672700962907, + 4.807046331488207, + 4.673419962013508, + 4.539793592538809, + 4.406167223064109, + 4.27254085358941, + 4.138914484114711, + 4.005288114640011, + 5.098926517004358, + 6.192564919368704, + 7.2862033217330495, + 8.379841724097396, + 8.734565078785955, + 9.089288433474517, + 8.310820896289862, + 7.5323533591052065, + 6.753885821920552, + 5.975418284735897, + 5.196950747551242, + 4.418483210366588, + 3.6400156731819333, + 2.8615481359972783, + 2.0830805988126233, + 1.3046130616279694, + 1.3925906085384634, + 1.4805681554489574, + 1.5685457023594513, + 1.6565232492699455, + 1.7445007961804393, + 1.8324783430909335, + 1.9204558900014275, + 2.0084334369119214, + 2.096410983822415, + 2.1843885307329094, + 2.2723660776434036, + 2.360343624553898, + 2.4483211714643915, + 2.682038597183949, + 2.915756022903506, + 3.1494734486230636, + 3.3831908743426204, + 3.616908300062178, + 3.850625725781735, + 4.084343151501292, + 4.31806057722085, + 4.551778002940407, + 4.785495428659964, + 5.019212854379521, + 5.252930280099079, + 5.486647705818636, + 5.720365131538193, + 5.954082557257751, + 6.187799982977308, + 6.4215174086968645, + 6.655234834416422, + 6.88895226013598, + 7.122669685855536, + 7.356387111575094, + 7.590104537294652, + 7.823821963014208, + 8.057539388733765, + 8.291256814453323, + 8.524974240172881, + 8.758691665892437, + 6.955985301912452, + 5.153278937932466, + 3.3505725739524794, + 2.3530617437439574, + 1.355550913535435, + 0.3580400833269126, + 2.495253161133558, + 4.632466238940203, + 6.769679316746848, + 6.727122180334159, + 6.684565043921469, + 6.64200790750878, + 6.599450771096089, + 6.5568936346834, + 6.51433649827071, + 6.471779361858021, + 6.429222225445331, + 6.231948115428519, + 6.034674005411708, + 5.837399895394897, + 5.6401257853780855, + 5.442851675361274, + 5.245577565344463, + 5.048303455327652, + 4.85102934531084, + 4.653755235294028, + 4.456481125277217, + 4.259207015260406, + 4.061932905243594, + 3.864658795226783, + 3.6673846852099716, + 3.4701105751931602, + 3.272836465176349, + 3.0755623551595375, + 2.878288245142726, + 2.6810141351259147, + 2.4837400251091033, + 2.2864659150922915, + 2.0891918050754805, + 1.8919176950586696, + 1.6946435850418577, + 1.497369475025046, + 1.300095365008235, + 1.102821254991424, + 0.9055471449746122, + 0.7082730349578004, + 0.5109989249409896, + 1.4591861387509013, + 2.407373352560813, + 3.355560566370725, + 4.303747780180637, + 5.251934993990548, + 6.20012220780046, + 6.0225739064200825, + 5.845025605039705, + 5.667477303659328, + 5.48992900227895, + 5.312380700898573, + 5.134832399518196, + 4.9572840981378175, + 4.779735796757441, + 4.602187495377063, + 4.424639193996686, + 4.247090892616308, + 4.069542591235931, + 3.8919942898555533, + 3.714445988475176, + 3.5368976870947986, + 3.359349385714421, + 3.181801084334044, + 3.0042527829536665, + 2.826704481573289, + 2.6491561801929118, + 2.471607878812534, + 2.471607878812534, + 2.471607878812534, + 2.471607878812534, + 2.471607878812534, + 2.471607878812534, + 2.471607878812534, + 2.471607878812534 + ], + "yaxis": "y" + } + ], + "layout": { + "legend": { + "title": { + "text": "variable" + }, + "tracegroupgap": 0 + }, + "margin": { + "t": 60 + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 1 + ], + "title": { + "text": "index" + } + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ], + "title": { + "text": "value" + } + } + } + } }, "metadata": {}, "output_type": "display_data" @@ -242,25 +9147,8949 @@ "name": "stderr", "output_type": "stream", "text": [ - "2023-11-06 22:59:13,066 - MachSysS.convert_proto_timeseries - WARNING - Time in operation profile is not the same as in propulsion power.The operation profile will be interpolated to match the propulsion power time.\n" + "2024-04-02 09:00:34,840 - MachSysS.convert_proto_timeseries - WARNING - Time in operation profile is not the same as in propulsion power.The operation profile will be interpolated to match the propulsion power time.\n" ] }, { "data": { - "text/plain": [ - "" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjAAAAGdCAYAAAAMm0nCAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAADyuklEQVR4nOxdd5wURdp+emfzLrvLgiwsLAICEiSDkkFEUcxyZ9ZTUQygIuaEivFQgU/FnPDMeuaAcCgZQYmSQcmw5M15pr8/Zmemu6e6u6q6uqcH+7kf52x31VtvV1dXvfWmkmRZluHBgwcPHjx48BBHSIg1Ax48ePDgwYMHD6zwBBgPHjx48ODBQ9zBE2A8ePDgwYMHD3EHT4Dx4MGDBw8ePMQdPAHGgwcPHjx48BB38AQYDx48ePDgwUPcwRNgPHjw4MGDBw9xB0+A8eDBgwcPHjzEHRJjzYBdCAQC2Lt3Lxo0aABJkmLNjgcPHjx48OCBArIso7S0FPn5+UhI0NezHLMCzN69e1FQUBBrNjx48ODBgwcPHNi1axdatGihe/+YFWAaNGgAINgBWVlZMebGgwcPHjx48ECDkpISFBQUhNdxPRyzAkzIbJSVleUJMB48ePDgwUOcwcz9w3Pi9eDBgwcPHjzEHTwBxoMHDx48ePAQd/AEGA8ePHjw4MFD3OGY9YHx4MGDB7dAlmXU1dXB7/fHmhUPHmIOn8+HxMREyylOPAHGgwcPHmxETU0N9u3bh4qKiliz4sGDa5Ceno5mzZohOTmZm4YnwHjw4MGDTQgEAti2bRt8Ph/y8/ORnJzsJdb08LeGLMuoqanBwYMHsW3bNrRr184wWZ0RPAHGgwcPHmxCTU0NAoEACgoKkJ6eHmt2PHhwBdLS0pCUlIQdO3agpqYGqampXHQ8J14PHjx4sBm8O0wPHo5ViPgmvK/KgwcPHjx48BB3YBZg5s+fj3PPPRf5+fmQJAlfffWV6r4sy5g4cSKaNWuGtLQ0DB8+HFu2bFGVOXLkCK644gpkZWUhJycHo0ePRllZmarMmjVrMGjQIKSmpqKgoACTJ09mfzoPHjx48ODBwzEJZgGmvLwc3bp1w/Tp04n3J0+ejBdeeAGvvvoqli5dioyMDIwYMQJVVVXhMldccQXWrVuH2bNn47vvvsP8+fMxZsyY8P2SkhKcccYZOP7447F8+XI8++yzePTRR/H6669zPKIHDx48eDhWMHfuXEiShKKiIqFlPUSwfft2SJKEVatWxZoVQzA78Z511lk466yziPdkWca0adPw0EMP4fzzzwcAvPfee8jLy8NXX32FSy+9FBs2bMDMmTPx22+/oXfv3gCAF198ESNHjsRzzz2H/Px8fPDBB6ipqcHbb7+N5ORkdO7cGatWrcKUKVNUgo4HDx48ePCgh/79+2Pfvn3Izs6ONSsebIBQH5ht27ahsLAQw4cPD1/Lzs7GKaecgiVLlgAAlixZgpycnLDwAgDDhw9HQkICli5dGi4zePBgVXz4iBEjsGnTJhw9epTYdnV1NUpKSlT/PMQea3YX4d1F2xAIyLFmJSaQ5WP3uatqY5+UTZZl/LxxP3Yd8XKsxBI1NTWxZoGI5ORkNG3a1Atd18Ct74sVQgWYwsJCAEBeXp7qel5eXvheYWEhmjRporqfmJiI3NxcVRkSDWUbWjz99NPIzs4O/ysoKLD+QB6iUFxZiy9W7EZpVS1V+fNeWoRHv12Pb9fstZkzMo6U16DWHzAsU1njx8bCEuHCRmWNH6c9Pw/3fL6aq/6a3UUorqDrZ6fxwdId6PDwTHy1ck9M+Zi76SCue/d3DJr8S0z5oIUsy6ioqaP+V15di4OlVSiprGGqR/rHMr6HDh2KcePGYdy4ccjOzkbjxo3x8MMPh2m0atUKjz/+OK6++mpkZWWFNeP//e9/0blzZ6SkpKBVq1Z4/vnnVXRD9S677DJkZGSgefPmKncEkumiqKgIkiRh7ty5RF537NiBc889Fw0bNkRGRgY6d+6MH374AQDZhETD41NPPYXrrrsODRo0QMuWLandF0L8f/zxx+jfvz9SU1Nx0kknYd68eapy8+bNw8knn4yUlBQ0a9YM9913H+rq6gAA3333HXJycsJZm1etWgVJknDfffeF619//fW48sorw38vXLgQgwYNQlpaGgoKCnDbbbehvLxc9Uyk90ULv9+P6667Dh06dMDOnTtx11134ZxzzgnfnzZtGiRJwsyZM8PX2rZtizfffJOpHVYcM3lg7r//fkyYMCH8d0lJyd9GiNlXXIlZ6/bjH71aICPF3lc67sMVWLDlEEZ0zsNrV/U2r1CPrQfKzAsJxs7DFRj87C84Ma8BfrpjsG65C19ehI2FpXjz6t4Y3ilPtxwrZq0vxF+HyvHXoXJM/kc3proLtxzClW8tRU56ElZNPEMYT6Lw4JdrAQDjP1mFC3o0jxkfy7YfiVnbPKis9aPTxJ9i0vb6SSOQnkw/P8yYMQOjR4/GwkVL8OPcxXj03tvRsmVL3HDDDQCA5557DhMnTsQjjzwCAFi+fDkuvvhiPProo7jkkkuwePFi3HLLLWjUqBGuueaaMN1nn30WDzzwAB577DH89NNPuP3229G+fXucfvrpXM81duxY1NTUYP78+cjIyMD69euRmZlJLEvL4/PPP4/HH38cDzzwAD7//HPcfPPNGDJkCE488UQqnu6++25MmzYNnTp1wpQpU3Duuedi27ZtaNSoEfbs2YORI0fimmuuwXvvvYeNGzfihhtuQGpqKh599FEMGjQIpaWlWLlyJXr37o158+ahcePGKgFu3rx5uPfeewEAf/75J84880w88cQTePvtt3Hw4MGw8PnOO++E62jfFy2qq6tx2WWXYfv27ViwYAGOO+44DBkyBG+++Sb8fj98Pp+KxzPPPBN79uzBn3/+iaFDhzK1xQqhq13Tpk0BAPv370ezZs3C1/fv34/u3buHyxw4cEBVr66uDkeOHAnXb9q0Kfbv368qE/o7VEaLlJQUpKSkCHmOeMMF0xdhf0k1NuwrwTOjutra1oIthwAAP63bb1JSDV+C8yrc7//YBwDYtL/UsNzGwuD9L1ftESrAWFFbz14f1DQWuVQD4xZ4hgH7UFBQgKlTp2LH4QqceUE+Nm5Yi6lTp4YFmGHDhuHOO+8Ml7/iiitw2mmn4eGHHwYAtG/fHuvXr8ezzz6rEg4GDBgQ1ia0b98eixYtwtSpU7kFmJ07d2LUqFHo0qULAKBNmza6ZadMmULF48iRI3HLLbcAAO69915MnToVv/zyC7UAM27cOIwaNQoA8Morr2DmzJl46623cM899+Dll19GQUEBXnrpJUiShA4dOmDv3r249957MXHiRGRnZ6N79+6YO3cuevfujblz5+KOO+7AY489hrKyMhQXF2Pr1q0YMmQIgKD14YorrsD48eMBAO3atcMLL7yAIUOG4JVXXgknidO+LxqUlZXh7LPPRnV1NX755ZewL5FSyOrVqxfmz5+Pu+++OxyVPHfuXDRv3hxt27Zlao8VQgWY1q1bo2nTppgzZ05YYCkpKcHSpUtx8803AwD69euHoqIiLF++HL169QIA/PzzzwgEAjjllFPCZR588EHU1tYiKSkJADB79myceOKJaNiwoUiWjwnsL6kGAMzbfDDGnOjDFwMbdIDRJJTIKGRt2V+KhVsP4cq+xyPJF22NZaXngR3x5tqQluTD+kkjqMvvPVqJIxVBf4WTmrM5oq7dUwwAaJqVhsYNkpGW5DMsL8uySuju27ev6u9uPU/Gf16fHjZtKP0YAWDDhg3h4I0QBgwYgGnTpoV36kBwfleiX79+mDZtGtOzKXHbbbfh5ptvxqxZszB8+HCMGjUKXbuSN3K0PCrrS5JE3HgbQfmMiYmJ6N27NzZs2BDmoV+/fqq+HTBgAMrKyrB281/o1K4NhgwZgrlz5+LOO+/EggUL8PTTT+PTTz/FwoULceTIEeTn56Ndu3YAgNWrV2PNmjX44IMPwvRkWQ4fY9GxY0cA0e+LBpdddhlatGiBn3/+GWlpaeHrOTk56NatG+bOnYvk5GQkJydjzJgxeOSRR1BWVoZ58+aFBSw7wewDU1ZWhlWrVoVtlNu2bcOqVauwc+dOSJKE8ePH44knnsA333yDP/74A1dffTXy8/NxwQUXAAA6duyIM888EzfccAOWLVuGRYsWYdy4cbj00kuRn58PALj88suRnJyM0aNHY926dfjkk0/wf//3fyoTkYdouHkuT3BoMZdlGWt2F6Gyxs/sOMyqJTp96nw89u16zFi8XQg9JY5d11+xkFw96qMhSRLSkxOp/6Ul+5CaFPzHUi89OTFcLzU5AenJxif/FlfWYv2+EmrfNgDIyMgQ0SUqhLKzKv11amuNebr++uvx119/4aqrrsIff/yB3r1748UXX7TER2jjHIIkSQgEjH3pRGBfcSV2HqnA0KFDsXDhQqxevRpJSUno0KEDhg4dirlz50YJB2VlZbjxxhvD6/KqVauwevVqbNmyBSeccEK4HM/7GjlyJNasWRMOwlFCy09ubi46duyIhQsXuleA+f3339GjRw/06NEDADBhwgT06NEDEydOBADcc889uPXWWzFmzBj06dMHZWVlmDlzpuqsgw8++AAdOnTAaaedhpEjR2LgwIEqJ6ns7GzMmjUL27ZtQ69evXDnnXdi4sSJrgmh9gdkvLVwW3iH48EcCQ5tlT9bvhvnvbQIl7/5K1gDn3i1RCt2RiLjtuwvxcfLdiIQkD0NjAOINw2MW7HjcDn8ARnbDkUcP0NRoSGsWfkb2rVrF9ZSaNGxY0csWrQIu49WYE9RJQBg0aJFaN++varOr7/+qqr366+/okOHDigsrkJ2w0YAgH379oXv0+QiKSgowE033YQvvvgCd955J9544w1DHpUg8WgVymesq6vD8uXLw5qQjh07YsmSJSohbdGiRcjIbIC8Zs1RVl0XNtFMnTo1LAiEBIb/zfkFXXpHNDw9e/bE+vXr0bZt26h/Vk56BoCbb74ZzzzzDM4777woR+QhQ4Zg4cKFmDNnTtjXZejQofjoo4+wefNm2/1fAA4T0tChQw292SVJwqRJkzBp0iTdMrm5ufjwww8N2+natSsWLFjAyp4j+Pi3nXj8u/UAgO3PnB1jbiJwc6ggwcJiCz75bRcAYOXOIgxudxxT3UQfX//5FZLS6VPn19NKQKPMyOShVc8fKa/Bsz9twiV9CtC9IIer3XjH3qJKPPjlH7huYGsMYnxXHuzHzp07MWHCBJxz8VX47ffl+OidNzB1yvO65e+880706dMHTz/5JEacdyFm/bkWL730El5++WVVuUWLFmHy5Mm44IILMHv2bHz22Wd444PPcaC0CimJCejbty+eeeYZtG7dGgcOHMBDDz1kyOf48eNx1llnoX379jh69Ch++eWXsLCgx+Pjjz+OSy65BEuWLCHyaBXTp09Hu3bt0LFjR0ydOhVHjx7FddddBwC45ZZbMG3aNNx6660YN24cNm3ahEceeQRX3XBLWAPVsGFDdO3aFR988AFeeuklAMDgwYNx8cUXo7a2Fp179UWdP4BEXwLuvfde9O3bF+PGjcP1118fdmSePXt2uK4V3HrrrfD7/TjnnHPw448/YuDAgWF+SktL8d133+GZZ54BEJQP/vGPf6BZs2Zo37695bbN4J2FxIH1e70cM6xwSgOjbIXVB4aXRz9B1bN2T7FKA6MtMvHrtfho2U5cMH0R3ILdRyuwaOshx9q7979r8Mumg7jqrWXcNNwgtBdX1GL5jiOuzfnD20NXX301KisrccEZQ/HUQ3fjiutuNNSC9+zZEx9+9DFmfvsFRg3vj0cffQSTJk1SOccCQSEipMl/4oknMGXKFPQaMBQAUF0XwNtvv426ujr06tUr7JJgBL/fj7Fjx4bdE9q3b68rkPTs2ROffvopPv74Y5x00kmYOHEikUereOaZZ/DMM8+gW7duWLhwIb755hs0btwYANC8eXP88MMPWLZsGbp164abbroJo0ePxg233aWiMWTIEPj9/ojSICUTHTp2ROMmeWh1Qrtwua5du2LevHnYvHkzBg0aFLaIhFwyQpBlGXuOVuBQWTXz84wfPx6PPfYYRo4cicWLFwMIClldunTBcccdhw4dOgAICjWBQMAR8xFwDIVRO4lYTFM7Dpdj26FyDD2xiXlhFyIWUUgkwcIIvCYfUjuJCZLqmWv9AfgSIirqWISVm2Hgv4O5VD69sR9Obp1re3uFxVXmhUwQe/EFOGPaPOwvqcarV/bEmSc1M68QJ0hKSsK0adNw3xPPobgy6IcSEhi3b99OrHPhRaPQsX8wmqhzfjbxu8/KysKnn36qurZmd1H4d8eOHbFg4SIcrajB4bJqpCUlqoRDrRXAyN+FZDEYNWpUOEJIi4Ol1Vi1fjNy0tWmFxozlnIe6NixY5QJTokhQ4Zg2TK14K7sAyCYWyXk3Hy0vAa7j1bg/e/VZpwQ+vTpg1mzZum2t337dpRV1+Gvg8F5p3GmccRuq1atovptwoQJUX6o2n7Jzc11xFcoBE8DEycY8uxcXPPOb/jNJXkvWDe+TgkwSi0Kqw8Mr6NxHaEhn09CouK4eFZhKpb4fYc7xli8IBQFOHMtOcmmNdj/3diXUZl/zO8tqsTeokpU1wVQVOlM1tiqWn/YiZYV+0uqsG5vMcqq7Ul7UCngHR2L2dA9ASbOsGpnke49J7XprOYWp0xIyvne7jDqEEjCSVJCgsrvRyvkuMH0cSzA7d1olgXaDdhx2H3HMBytcD7VPc0m46mnnkJmZmbUv9bNGuOWq/6BfUXWtYokiB7nes+RmZmpe9ahG+GZkOIMRouyk5M5q70/FiYk1h0HrwaGNPElJEjwGWhg3OovAbCFJsdagHBTGLX2jS7eegh3f/I7po60P1NxQJZR55eRnMi+JyUJWXpp+82gfBukEa5neooX3HTTTbj44oujrm/cV4KU1FTkNcu35dsWvQHUew4AqnwvJBRX1MAvA7kZ1iKcRMATYDgQy7XHaE0mTeZbD5Tir4PlOKOzOoOxNiqGh4/xH6/EtEt7UJV3KpGd2omXre7hsho89u06XNX3eLQ5jpyKnASSUJmYoH4bdYw7cRfLNyrEWnzgHVZbD5Rh3uaDuOKUlkg1SfDGizs+XYVEIOw/wgXK59u6vwxVdX60a5KJtKjjAoyJCB1qZhKMi0HDbm5uLnJzo/3DKlKLhPOjhOj9n95zmEGWZeyoN7E1SElEEofALBKeCSnOwGoWGT5lPsb8Z7nKd2blzqPo8+T/8MWK3ZZ4+WqV8QGNSg2IU4nsVO0z9tXny3fjnUXbmSODSD4w2pBsUpljAUZC8K4jFdhicoyD5fY56w2fMg+Pf7ceX68Sdxildrg5ZjYFUFUX9JEo4hGW4mBoulljCdBrmGVZRnFlDWrq2Hxa3Ghy9rvgnXgCTJzBOAePfr11iqR7N7+/AofKajDhU75TkmmhXLSdkl+UfcAqwIRQUlXHVJ5kqkpMkFTrgtaE5MYJiQdG73XQ5F9w+tT5rjtR+0h5xL/iUJl9vhbx8obleJBgGFFRU4ddRypc54NUXFmLHYcrwuev0cJJYdgIbhspngkpzkC7kd+yv1T3ZGqnJGelAOGUD4zScONU5A+pP5X+L4C5BiYQkFFaVYfs9CTDcm6Dng+Ksu/3lVTa9lw88/qB0oijZdOsVIOSbNC+YTcLqYGAjK0Hy5CRbG4+c+9T6COUpsAfkNGqsfgjD3hRXs22OQrBS+pNhqeBcRDl1XUY9+EKzFy7z7ywDrSL8r7iyvDv0Bg/UFqF06fOR/9nfo7ci8FkqtbAOCTAqDQwjjSJOr+OBkYh2FTWGKuMr3n3N3SbNAubGHdmdmDptsNY+tdhusI6r7WmLrLztfNIBTcLCW7EgdIqbDtUjuLKWlTV+nG4nKyBOlxWrZpbYg3eT7m6ziENjIC5xmgku2acu0wF4wkwXOB7i6/O+xPfrdmHm95fwd+yZrd/7Tu/RZUhJUmLxfj3+53XwChBE4UkwrYeEiqVtLQ+MCNfWIBp/9usS2N+/UniHy3baZkfq5i76SAuef1Xqvwgem9VKcDoCa+xmpOVr1zkfKwdSwk2z661/gD2l1Sp+toMhcVVKK2qNfWV2VNUiYOl1aioqQOvDsYda50zXNC2YlzOJUKKAdzxTiPwBBgHcbCUPYWzFto1WWlLdY2UXg+laSU2Ghjzz02EmSn0nEpaWh8YAJj2vy2W23ISVAKMngZG4XugNy5FWDLdNOSjTEg2L0g7Dldgf0kVtisOYKQFrX+YncnPtm/fDkmSwtlcf1uyEN0KGqKoqAgA8PWnH2Jg5+MtteG2BdcQhsPF+pN06dAO77/5ikUq7upRT4CJM9BMPG7JjVEXUC5izrSpfHaauVdEdFBoklfS0vrAsMINjpU0ArHeWFMKMHb6IvGMdZUGxkZ/MLvHfFA7EolAYkLshxcKCgqwb98+nHTSScT7I869EF/P+z34hwv49eC+9A6eAMMB9+aB4btnF5RHYljps6d/3IAZi7ezt++QBqaOIMAEfWAsk44paBZgXQ1MnbkAI2KBd5MGRrvIuoU1y3zwEjAZ/z6fD02bNkViIjnYIDUtDY0a659SXlPnx18Hy1BapW8Oq6lxPqMvL6y8p3h6TpHwBBgHIWKy5d4xxsSJV2mb5+N77Z5ivDbvLzzyzTqq8qwmJBEamNACrUxWZ+bzY/Y23KBFo+GAxgfGXg0MO2i1W7uPVuDDpTu5zwoimk1lGagpp/4n1ZZDqq2AVFuBv/YcgFxdprhXQfhXHnUfoWuMc8eiX/6H04cNRZfW+RjcpQ3GXXMJ/vzzTwDBTL2SJIXNPUDwYL/kRB/27Ar6cd1w/Wh07doV1dVB03lNTQ169OiBq6++GkC0CUkLpQlJBvDnn3/i/PPPR15eHjIzM9G7z8n43//+h20KE1qrVq3w+OOP48HxN6F/x5Z45O7bMWzYMIwbN05F++DBg0hOTsacOXMU74bcDyGal112GTIyMtC8eXNMnz5dVWbvnl24/brL0ffEFsjKysLFF1+M/fv3AwCKi4vh8/nw++9BbVIgEMCgk1qjb9++4frvv/8+hvfpHP57165duPjii5GTk4Pc3Fxc9s9R4X4FgIfvuAWjLroQTz75JPLz83HiiSeSmUfQFLypsDRqPnzzzTeRk5ODOXPm4LvvvkNOTg78/uBYX7VqFSRJwn333Rcuf/311+Pqq6/SbScW8MKo4wyGi3Ls1zwVlAsXr9xVxhl2qG3fShlaGrVRTsv6tPXuhNa8uDEh6ZSpdciEZBVGnJ0+ZT4qa/3YW1SJu0boLxARWhQqmNoK4Kl8av7y6/+R0MWkbtT9B4wTT2pRWVmBcbfdjoK2HVF4uAgvP/cULrzwQqqTmQFgyrT/Q59ePXDfffdh6tSpePDBB1FUVISXXnqJiY8QysrKMHLkSDz55JNISUnB1JffwG3XXoav5y1D1xY54XLPPfccrr/tbtw0/l4k+SQc2rYe48aNw/PPP4+UlOApzO+//z6aN2+OYcOGEdvSZip/9tln8cADD+Cxxx7DTz/9hNtvvx3t27fH6aefjkAggNuvuxxp6Rl4+7PvkJoIPHz3BFxyySWYO3cusrOz0b17d8ydOxeXntAJWzaugyRJWLlyJcrKypCZmYl58+ahd98BAIDa2lqMOHsE+vXrhwULFiAxMRGPPDoJt1z1D3w+ayGSkoMp/H/++WdkZ2dj9uzZhv22+2glquv8qrVj8uTJmDx5MmbNmoWTTz4ZxcXFKC0txcqVK9G7d2/MmzcPjRs3Vh0pMW/ePNx1991M78xueAJMnIFmLXCLWj0WC5dy0tETmnYcLkeTBqlIS/Yxp/gnIayBcfAYeSdApYHRKaQMX7Uz75CdYz10AvCiPw/hLpgLMD/8UYhAQA5nnXbJZ0gEzRsZPvI8tG6cgaKKWuQ0rcFjz7+Eod3aYv369VRtZGZm4P3338eQIUPQoEEDTJs2Db/88guysrK4OO7WrRu6desWvnL7vQ9j1g/fYu7sHzHilIi4NmzYMPzrxqDGJdmXgME9OmDcuHH4+uuvw+f/vPvuu7jmmmuoAx8GDBgQ1ka0b98eixYtwtSpU3H66adjzpw52LJxPX5YvApN81sAACZNfRkXndYPv/32G/r06YOhQ4cGBZjRt+D3JYvQd9BQFO78CwsXLsSZZ56JuXPn4sobbgUA/PTtFwgEAnj9jTfCvnTTX3sDLZs1wW9LFqL/kKDQlZGRgTfffBPJycZnEmk3vVOfegQ/ffUZ5s2bh86dg1ofpZDVu3dvzJ07F3fccQcee+wxlJWVobi4GFu3bsWgQUMQ2lK6wUTuCTAC8MKcLWjRMA0X9Wxhe1uGhzlq/ku65yRUGpgYtx/Cmt1FOO+lRcjPTsXi+08TY0KSQyYktcYpjpRl3KAzIfEJdlW1ftNziqw68YoemD+s3YdzugZ1JkQTUlI6kyZkX3GlKlvw8bnpyEoLJgX8Q5FdO4QmDZKRl5Wmut8sOxWNM1OCbSO6jh52bPsTkyZMxrJly3Dk8GEE6t/jzp07kZ6eTkWjX79+uOuuu/D444/j3nvvxcCBA6nb16KsrAyPPvoovv/+e+zbtw+1tXWoqqpE4Z7gkSjl1XWo9QfQvnM3Vb3U1FRcddVVePvtt3HxxRdjxYoVWLt2Lb755hvqtvv16xf197Rp0wAAGzZsQF5+87DwAgAntO+AnJwcbNiwAX369MGQIUPw1ltvwe/34/dfF6Hf4FNR1qYl5s6di65du2Lr1q3o0y/YN5vXr8XWrVvRoEGWKoFddXUVdu/YFv77pJNOMhVeAKjG+Huvv4TKigqsXLEcbdq0URUbMmQI5s6dizvvvBMLFizA008/jU8//RQLFy7EkSNHkJ+fj7bt2mFjYUk04RjBE2A4oJwA1+wuwpTZwfweIgQYf0DGWwv/wsmtG6F7QY5h225HnQATEivUhzlGN/rj2kIAwN7iYDZWkSakY+28I5qnoTMhsbc9/ZetePanTXj32j4YemITg/bZafOizh/AmP8sR4+CHNx6WjtimcLiSJZfIm+SBCTTZ4aVkxIgJ0WmaTk5A0hOqr8X7bwqJ6UAyWnq+8lpQHIKdZsh3HbtZWjTuhX+PfUlpOU0RiAQwKjh/VFTU4PMzOBhp0qfvNpaNT8ygv4eixYtgs/nw9atW5l5UNK66667MHv2bDz33HNo27YtCsv8uPX6q8LtFpYE+15OjH7W66+/Ht27d8fu3bvxzjvvYNiwYTj+eG2Itn3f7+DBg1FaWoo/Vq/CiqWLcdu9D0Mu2otnnnkG3bp1Q35+Po4/4QT4AzIqysvRsUt3PP3C68jNTEaTBqkorazBnqIqNGzUKEwzI4NuHCmfqufJ/bDg51n49NNPVf4tADB06FC8/fbbWL16NZKSktChQ4ew5ujo0aMYMmSIitr2wxXwB2QUNExDdnpsTqb2nHgt4ohOJktefL58F576YaPugYJGC66ROtTuiX76L1ujDsaLte8DqXltN9jlxCu7wovFfliJQjLCsz9tAgA8+OVaLr5oQfOWQo84a/1+/LzxAJ6frZ+QUPkNusERmxdFR49g+59bcM+992PgkFPRpt2JKCkuCt8/7rhgdNC+fZGs4iTfmGeffRYbN27EvHnzMHPmTLzzzjt8DMnAokWLcM011+DCCy9Ely5d0DgvD3t371SVIVQDAHTp0gW9e/fGG2+8gQ8//BDXXXcdU/O//vpr1N8dO3YEAHTs2BH79+5B4d7I4bh/bt6IoqIidOrUCQCQk5ODrl27YsabryIxKQmt27bH4MGDsXLlSnz33Xf1wkEQHbt0w85tfyK3cWO0bnMC2rZti9YntEXL1m3QICubiW8tTureC9Pf+wxPPfUUnnvuOdW9QYMGobS0FFOnTg3zExJg5s6di6FDh0ad7xaQYzvPeQKMozCf0DYVRmfRVYLGhOQ01uwuwrM/bcLtH69SXVebkGSs2HkUEz5dpTqLRjSUKle6MGrrfit1BCdeXrhp0dOLeFMei6DH7fd/RBY2K4LsnqJKFBtkjXUyeSNrZmJbWHNIlZmVnYOchrl45+03sf2vP7F00Xw8N+mh8P22bduioKAAjz76KLZs2YLvv/8ezz//vIrGqhUrMXHiRLz55psYMGAApkyZgttvvx1//fUXF0/t2rXDF198gVWrVmH16tW48+bRqkR7Zj1z/fXX45lnnoEsy7jwwgsNy4ZoheaHRYsWYfLkydi8eTOmT5+Ozz77DLfffjsAYPjw4WjboRPuv3UMNvyxGn+sXI6Hxt+MgYMGo3fv3mGaQ4cOxZeffYJep/QHAOTm5qJjx4745JNPMGTIkPDYGXnhP5GT2wi3j74CSxcvwrZt27Bw/jw8M/Fe7N+nf3q6PyBTRal2730KfvjhBzz22GNhMxgANGzYEF27dsUHH3yAoUOHAghqjlasWIHNmzdj8ODBqKjmi8izC54AYxFOS5+GeWCk0H+jZ047F0a981S0JqSLXl6ML1bswQNf0O+qWedr5bOTBBht1/BqYKoVycNCk6g26iqezH0s6P1EJOpBT4D4cmVkorXqxDtl1ibde1xh1DL5t275UFuMjbktMzYLEhIS8O/pb2HVyhU4fWAfPPfYA5jw4KTw/aSkJHz00UfYuHEjunbtin//+9944oknwverq6pw7TX/wjXXXINzzz0XADBmzBiceuqpuOqqq8LhuiyYMmUKGjZsiP79++Pcc8/FoKGnoeNJXcP3zXQBl112GRITE3HZZZchNdX8EM+ALGPd3hLU+gOYMGECfv/9d/To0QNPPPEEpkyZghEjRgAIvuf/e+sDZGXn4Np/nI0bL78QLY5vhXfe+0BFb8iQIfD7/ejdL+IHNHToUPj9/nqBIThe0tLS8c7n36NZ8xYYfdVl6NixI2695UbUVFcjI7MBkdc6fwDr9hZjC+EYGdIqNXDgQHz//fd46KGH8OKLL0bxGBJgcnNz0alTJzRt2hR5Ldtg19GKKKqxHOWeD4zLYPYR2pk5VDSUAoSS622HjLVMokCz8ycdxGiGqlo/ej0eWcRDC3RtQGlCsgY3v+ZyCg2MEla1XPuK7dPYiYZSZrHj+C9xw8KcUt9BQ7Fs5RoUV9TiaEVwk6KcfwYMGIA1a9ao6lTX+sNOnitWr4lywv7666/Dv1u1ahWmt2Z3Efr0G4jVu44iJycHO8uKcP7Fl+P8iy9Xlf/558gBtVv2l2LUVaNVj/TjEjU/Shw6dAhVVVUYPXq0bhkllHNDg6wsfPrpp7plmzUvwP+9/aHq2nGN1D4qF1xwAXYdKVe5HUybNi2sBVm/tyR8vXGTPDwx9RU0aZCKptmpKKqowc4jEeHh8akvo1OzSDRXaX26CZKWMPQU2r4ZPHgwysrUc7GSnxBCpsE/D6rLumEt8jQwcQZjE5K1GXPtnmLc/P5y/HVQjIDBIxxowbzrVfwmdZW2j2jPhFFi3d5i1SIeIqF9Xjd84Hqg4Y3Oide8jIBIdUvtG4HmGUMaNtbvy80KGOqR6ZIhTMOGXpna2loUFhbioYceQt++fdGzZ0+RrBkw5GDnOdCU7pwRw4HuCTAcUGlJHP7AefPA0IyxWz9aiR/XFuKfry5hZ4wAlQZG8dsp1TqNBoZnjtEjq/e8JJh1gZ1d9OaCv9Dnyf8RTy1nhzmjIvyM+FuPBqvb4erdxdil2P3S8qMn8FTV+rH7SAVqeM4wYuJA74q7secoZV9rHkzvk1u0aBGaNWuG3377Da+++qrq3oIFC5CZmYnMzEw0bdwQfU9sEcym26ABcnMiGg6eaZ65joUXtWTRwjDvoecJ/et1An3iRCO4Mc2VZ0JyECIWJUMNjAF9mqZDp2Xr+bSwotxCFl1eGB0lUF3nx0u/8IdyhunqSDDaV2NFtrVz8/bE9xsAAI9+sw7vX3+KJVqx18Cwf1Qz60PpAfp+fm3+n+h9fC4TP3qs/XmwDP6AjPIaP05sSvZp0IOwYWHb+LJOmH7+0XZwdNsygn4mehuK3r17h00k5dW12HWkEgDQPq8B/LKMWgRNL0pzjV0gDhfK4d29Zy98OnM+AKCDhtetB0qtMVYPvbXH84GJYzgdRGbnwtahaQP8vuOoMHrKBFzOQT8T788bDkSV5ulOO6PDndTGmmmoaMaaHruZKYnhYyDszFDM2l97iyrx8tw/HWlLr3io36tt0cCIh01nOQonRhyvJvXS0tLQtm1bAEBZVS2k7OC5Sm3zs+GXZWzYV2JUnZ0fRtD2fWpaGlq2Diama6s4VgEAajNKVHmZeOHGNFeeCYkDNANzwZaDuO2jlTgqOE8Mjc8G74STnCh2OBwqqw7/VrJtxF+AMhRQD8pFRhv9QoqG4WlLr45WmHWxCwwAPv8fLfQWdSVtEe2IQiSLaBCiNyCq/rBDGnVBV5ZX12FfcaW5iVYgryRSyt6trvVbd5y3WN9ueiyo8wdwuLxaqPnWTd9xCJ4GxiL03ulVby0DAKQl+fDvf3QlF2KgFwKvFGzrzl6Hp5BJKljEnHF/QMbI/1uAhhlJ+HhMP9PyZtB+cKK+P5p3oNeW9pC4WML0Mag0MORnUS5utJu/D5buwLer9+KNq3ubFw63z4bdRytNy2zeXypk4+HuKCR+KKNRmmWnGZR0jtu/DpULbU0ErVg68e84XIHymjqUVtYJnPf0nHjF0OeBJ8DYjL3F5hMmC4x9YAwy8VKMMtHfm54GRg9bDpRi035r9lrVUQIaSYNDw0yE7juI8oGJLlcXkJHkc4kAY6MGRkn6s9934f1fd+C1q3ohLyuSf0M7JkNZd9+Yz5DojFEYpBFgzpg6n4mmHtzxlgVA78DOWie9OokhhWHU+gNITHCXQYH162IdL0b0y2uC5tuSqlrb+yWW49xdbzwO4bSQLWTR0bnOrSLUIVim48RLs+bwPqeRCYlEky8KiSYEmVwm1scrKCFi7BIPLIS675duO4JVu4rwZL3zcLh9nT4qY8j2qQ6bN3+g0ir1mBT9/aotSLak4nWUirac1gRnVN7pkS7cHKiizQ4752oPQXgCjIMQMRiNTJoh+mbzpvKzuuadZeEQUZGf/9o9xdiyP6Jqdu4wR0UmXps2iDQKGFkGsUNDmX/13pGTE5aZIGZlQSDR1hNotdD2TUBWn62kVzaY/VjGSz9vwS8box22SbRZQCWQKMociyYk5XuItSU0qnmnvYbNKNitglG3xnkvvuEJMBxgGQ6iF27RWpK5mw7i3v/WZ2jkIL18x1HMWleoulZcUYtzXlwYPh2WhzT3YzKehcTz0HoLO01zdZQOIU5MOSKUQaRFTJZlYl9od6S0ieH+t2E/uk+aZRqWLyM4np+btRnXvvsbFW3R/UyTB8ZSwsljdy0yROixhw4divHjxxuWCeGsfl3x7hvTYxbtRfuqyqvrdAV0ETsaMz4Ol1VTby5I8MKoPVCD5iwks2RW2ruH68OdeXbco15ZHHXN7LBGmoldjBOd8d9618xAo9mRZfIzhDQwbnDot8sHRm+MWmmtosaPpdsOY1iHPNV1pQlLlmXhPmcR2nQT9YHS6oijtp6WTXLH+xcFWZZxtKIWqUkJ8Kneh8hGOIvIwKbCUrTPaxB1rIEZaA7vNOSHogPKq+vCTtEpiWz8qdrirFdeXYc9RcFvpqsm/Doe4GlgLMJs4Ii2y9oRypaaHPxw7IzS4V0saavV+QMY++EK/KhIUmb1EMGNhSWYuXZf1HW9d0AbaRUL7C+pwviPV2L5jiPha6ZRsJxRSHrPaMeibdVPQTRTL8zZgqmzNwPQF3hibXphhe5z1N8pq67D7qMVgjI700Nr0jOaY7S+T2aQEYxssgKaoUWb7NNSxKDBPV3NDxO8owTiCurTbJ1dkHgz8RohLSk4DPQoL9hyELd/TJ/ThrSQs5uQ2Gr8tG4/vl+jFjaiwqgZ+Tpz2gLc9P4K1aIfpGvOjwzyBBZKKOX0Ivb4d+vx1aq9GPVK5JgIEcI1WQOjJ+BR0uTkxS15Kl74OZjtmeTgLMsyqv1VqPJXospfiYraCsN/VXWV4bJV/kpU1EXqKK+H/lX6o+9X1tdh/aZmf/81+vfpgRPyG2FwlzYYc9kFqKgox8N33ILxo6/AtGefwnHHHYf8Jo3w+P13oLYmMj8EAgE8N/nfaN26NdLS0tCtWzd8/vnnKvpr167FWWedhczMTJzaoz0euP1GHD1yOHy/oqIcD46/CX1PbIFWLVvg+eefZ+JfiQQJePPNN5GTk4M5c+YACJqjbrvtNtxzzz3Izc1F21YFeGXKM8EK2q7iGFoiDNiFxVWqwx95YPtX4YVRe6CFoQmpfiSxOPECCKtW9Sa4UE6bFMpEd0QTi4K0rgOr0iETwJ6iSqzbW0zVJmknExVGzfklbywsRS9FGnndRHYU9M00MHYJNgcUOXlCMDOF0XQXiV1dAcaigEE8nFMyvm9Kk6EscyZeQvnKukr86+fhbIQEYenlSyN/mDz4wf2FuG/c9Xjsiacw7MxzsOfAEaxYtiTcyUsXzUdmRjrmzp2L1eu3YNzNNyAnJxcvTZkMAHjrpSmY9c1/8eqrr6Jdu3aYP38+rrzyShx33HEYMmQIioqKMGzYMFx//fWYOnUqVm8/gGlPPYq7b74Wb37yDQBg6hMTsfzXRfi/tz5Aj/bH47FHHsaKFSvQvXt3AGzr5ovTnsdL06Zg1qxZOPnkk8PXZ8yYgQkTJmDp0qX4ef4C3HzD9eje+xR0uuR8VX2uKCRBZXYfrUBBbjoHB87A84GJY9g5ARLb4z0LyeBmWkiAMWk7ZCs1A8/Ofv7mg/h29V7VtQHP/MxMR4noMOroMjSLnrYMXSI7mdgPtZQndItWJjTOTI5ug5FGICDj0993qa6RxpWTZjKrJ7DbCTebigwtDrKMQwf2o66uDueefwFy85ojvVEztOvYOVwmKSkJz73wCtq3aIwmLdviljvvx9QnH8ELzz2DmupqvPnSVHz/40wMGzIIANCmTRssXLgQr732GoYMGYKXXnoJPXr0wFNPPQUAqMlsiknPv4gzTj4J2//aiiZ5TfHlJ+/jqf97DacMHIL2eQ0wY8YMtGjRgsizZPBMU596BDO//Azz5s1D586dVfe6du2KRx55BADQtKAVXnxxOpYumofRGgGG1Ed1fhlJRps6RgnGyfGyqbAEjTJT4LMjVM5BeAKMzXBLFJKRE29YgDEhTRuW/MMf0X4jZkLN1W8vU5cX0G90zrbmDWlLWDGRhNpzauGVZRmvz/9LFdKu5YUW367Zi/u++EN1jayB0eOFqTk6WNXAMNRhfWek8mmJaXj/tDmo9gcdRE/KzzakUVhchUPlEe1Z06y0sDC6lqCdPK5BKvIapKjuN89JQ8P0ZKQlpgGgM0e073QSThk4BANO7oXBpw5HrwFDcPrI85GVkxO+n5Ye0Qp069UHFeVl2LlrF3bu2I+qygqcd/ZZKpo1NTXo0aMHAGD16tX45ZdfkJmZCUA9Znbv2IbqqkrU1tSgS49e4eu5ubk48cQTyQzreEa/9/pLqKyowLxFS9C5c4eo+127qrOkH9ckD0cOHdLvmHpsP1yB0qpatG6cgQapScQyAVlGQJZ1cyUB4n0kyW1Eo7ougL1FldSanf0lxoEZsYInwNgM1knVbFEJBIKOV4kJEhI00rOk+S8twk68ZrxRfmzTf4k+LI+5H4TkYdD6wIgBXSI742c2ez5Ru7GZawvx9I8bifdM88Bo7q/ZHb1gEn1g9Jx4Kd8ATXbfcFkO+k6B9BySJCEtKQ0SggJMepLxApKaKCHVF9nlpyWmIT0pKKCk+qKFkbTEVKQnparuK+vQwufz4bUPv8S+zavx06xZ+Oid1/Hi5Cfw/jf/izyLTt2KiqDz6+dffoO2rVuq7qWkBPkoKyvDsDPOwrh7H0HT7FQUFkcWyMZ5edi13Twbs7J/9TQwPU/uhwU/z8JXX/wX3Ts/GHU/KUktfEiSBNnMBg6gtKoWQDCCU0+AOVpRg8paP9rnsZ04ToRNQ5t2mvEEmGMULLtYox0c7Rk5pdW16PbYLHTKz8J/b+5P3bYRQhoYMykj1klkDfvIJJw3mJuE07mY8kwlFX29MjTtGbTBiu2HK3Tvsb5Psg9KdMfrCUaHy2rw18EytDkuk61hSvCMTzud8PV23iyyKcENmLE8PyRJQt9+/dGl1ym4+pY7cWbfrvh55ncAgM3r16KyqhJAOiQAa1b8jvSMTBQUFOBIXRKSU1Kwa9cOnHn6MCLtnj174sNPPkN+QUs0SEtBcq46ZLng+NZITErCHyuXo1nzAsgAjh49is2bN2PIkCHUz3BS91649JobMO7qfyIzLQV33XUXZ2/wwSwU2+rwq67zY/fRSlX4enQj1towQyxNpV4UkkWIWNTv/+IPDH1uLipqzEPq1u4pQWWtH8t3HI2+aXQWksEgo/WBsfIhsEch8bcVgtIHZuC/fyEmaxJ5lABN4IJZe04e9GieiVf7d3R5Erd64esbC0sx7Pl52EvpSxXVFqExbR4YPVj1y5EJ7f+y6UBUEkcl9J3V7X/HVgWzNSt/x5svPo+VK5Zjz65dmPPjtzh65BDatGsPAKitrcXdt92M9evXY/ZPM/HKlGdw6TXXIyEhARmZDfCvMeNw3z13Y8aMGfjzzz+xYsUKvPjii5gxYwYAYOzYsSguOor7xl2P1SuXY9f2bVg0dw4enjAWfr8f6RmZuPCSKzH1yYlYumg+1q1di2uuuQYJ9ef6aN+nUZd2730KPv3iazz22GOYNm0aV384sXfjGRW7jlSivLoOJfUaITLcpZkUCU8DwwHlRC4idPOjZTsBIMqJ1SmkhsKoTR7Fiore7ghXoi+GYpLbU1SJr1eJ6V+6MGpjM4ornE+FaGDoyimxelcR8nOMTjHma1+v2SPlNRj67C8Y0bmpsdMlA2rqArj2HeNsv3bkgbHuAUeHzMwGWL50CT56+zWUlpagafMC3Pnw4xh46un46ZsvccqAwWjdpi0GDx6MqupqnHneKNx8x33h+mPvfhAntMzH008/jb/++gs5OTno2bMnHnjgAQBAfn4+Znw5E9OeehSjL70QNdXVaNaiAAOGnBYWUiY8NAkVFeW47drLkJXVAHfdeSeKi4tRXl2HdXuLVYcUSoZuvEDf/gPw/fffY+TIkfD5fLj11lsNn9+pJd/SvCjTZfY+dsUXT4CxDNIAVIb0OmmXD/vAEGZIo0nTlxDKA2OfCUmMTwvbrlYrXJI87mn4itJE0ByGpFPO6VQlRu+dVfgmPQ9LIrsQak1DyflW+GC23Oi6Hy3biZKqOny2fDcuP0Xtk8HSA0rKdRQe4nrP4QLR1RRt2p2IV97/HC1z01FR41edLB/CXQ88jKmTn8KhsuoorZokSbhl3K24964Jum0c3/oETH3jP0hN8hFNLekZmXjq/14D/g9o1yQTacmJuPvuu7FmdxEA83fw45I1qr8HDx6MsrKIM/vcuXNV92UA0976gEzMpu/WbX5bPIjlePZMSBahXQSqav3o/MhPMeKGD6GPyGxOdjJRmBATkmahTNQIMJ/9votrYuIJvWapKxLGjsRsdUnlWRLZhUB7HhQN1HlgyKHrqvLCWjaHLW0JGz/WCblJEDPNfUXzuLGWJRjdWPTYpc3ueyzA08BYhPbD2H7YWvppKzDMA0Mx3bAuaCxQ1qXZYdNkzd1TVIlGGclITfIRn65Ekz48yaeW1+/+fA3uHqETlqlsV9Mw7VEC5EnH3lmyqtaPR75eh9M75WF4pzzDsuwaGLpyZoJwLacAQxSglOdn2SSM8kKIq4uGRqzXWCVkGGvbRPKqpbVi6WLccvXF4b+1BqRfN+0Wyotd/W7H+AudrUQDMUJo7ERZT4DhgWLQaReB6lr15KxeuI3JivKLYKUS4tHM8c+iuVYo1u8twcgXFqBlbjrm33MqVZ1EX3TP7DqiH6WjB9qjBIjXbV6B3l60DZ/8vguf/L4L258527AsbV4fAFi7pxj/+XVH1HWWKKQQQsn8RCzwND4wosCeiTdSobC4Es2TkqOEaLtguhmxUPfxqS8DCJ5ifLisGnlZqUyE9E4rZ0Gnrj3w6cz54b+TEiXU1rE9VWlVLfaXVKNFwzTmgx7dAlcIZt5RAvEL7YdYbfFwLCsDymgc2Z0FmAUb9pXg09934eLeBQZtGdP4sf6QxZ31AgjN8ymd/mjbCZZRF9JPlR/5vfVAGZ74br05cf1WuWodKIn2VdBtwVRgjdw/58WFxDIsUUjh+2Y+MIZ39cGTlJDav4kRX67crTrcsLiyFvLRSrRunCGEvpvAarLYeqAMVZzzZMj8mJqWhpat24SvJycmGB5MSHqt2+oPa9x5pMJSrhYrYybWGjURw93zgYljaBczMad7WgOvsGKaiZdmgaB0/rjn8zXkcqHihGtTZm8ybd8ISQQNDA9oJqy3Fm5DeU20Y2KtP4A7P12NP/bQnfHEimSGKBsRKQDW7yuJThhY/7delnJeE5IZAjpOvCwQpSG745PV4QUyBLOcIG6EHQtsZa2fKmeSlpGALGP9vhLibStvvY70IQh+8IOl1cFkcEaO/jGQZgIxF6GswRNgLEI1/mQ5apJiGh4W11f+6A06Li35wPBXDYOU4TcEmkcnRSHxdJkV89A3q/fivyt2mxfkHAwsQpqpP0797bs+W21Y7L0latNSSD7RO2eFuGBQorC4Cue8uADvE8xZNP5FWo5oszUHi8XebZX6G7RiQ7IAWed3+BpnMkkZ+hmeacDqw2umqWNqW5axr7gS+0uqUGOT8K4FrSDvdFCBaHgCjEVE+cBYNSHFYECFfWBMPlMno2/0hKqQzwrPUqKNQgq2Q8GL5m/9VPnmOFpufBbNR0t34uW5WympRYPFxyIgA2XVdfjhj32GSRQ/X24scL27eDsAYOfhCjz30yYcrD/5Wi8TrZUopNs+Wom1e0rw0Fdro2/a+u3E+UzvFOhkYsdheV41qM9CWjt12DbfU06QIkymngkpzqB85ep09cHUzrqFbUbkLCT2ISXLsqlJwdEwap3rgyb/QrxuZ2K46CgkC7RM7pdW12HyzE3Yr+PL8ufBMpw5bT6+W0NOyqcVYAwzjMvA+I9X4pYPVpia9IwQ8mm56JXFeOmXrbj945UA9DUwpidy656FJGPZ9iO61USMTt7T3llgLRMv+1PGboGJ5tW+OcTupxQkwbgMsT4exio8AcYiRGpgYjXRPD97M/o+PQdFFXQn1RpBXwUv9kvRUqNZE0R9rPpOvOKeUe9xJny6GhsLSzHuw5XE+yQtkx5kWcb/NhwAAHy3hnSCOB1CAkwo2dnhei2T3vksNEngzJCeHH2Cuojup7bQxGjid7xZ2cK8RHItiVm/0QggzjNnrUUDYdsSXUZ4ZyHFL7SLVnUMHfWsbOz2l1TjUJmxAGPFiZf1Q7VjouPd/UXZw61oYIiTOj1Bs4gPNhOSmE7Wo6M9LT2EOjMNjA6KKiPnvRzfKDqah+d5opL1UZJw+8bVkgtM1O4g8nP0P8/B5Efv5+YhNNY//+BdnHFyZ3RvmYsZr0/nosUEVicYyhZlipJG9+08TJQVvLx4JqQ4g/JFax2/jDQwdr9o49OurdPn8Rfhb8z4Nk9fiporaA9zpC1DFGp06ps9t/KsH7NwZTONFG1/6bXDbULSwU7FydppSdHHX9i9FCifxk0Lj53gEAkN7wZkoKy0BE8/fA+uveV2zP5tPS6+8lo6wcjxM6Ro67NQ5+XEnvEW76PYE2A4oPKB0UzeWgGGJfOq5VNqDVNRWx+qVAu0TiE3zPeisuCKthuTBCLeBTJJITSYhfTbroHhNCHpCeJmERyLtx7CA1/+EU2P4bugHSMix0B1rR+7jlTQhVnztOvQFrm2xtwEHZBl7NuzG3W1tRg0bASOy2uKtPR0c+IMpizuPEKc9VgIR2lzbWrSWa1I7HQwwgUYv9+Phx9+GK1bt0ZaWhpOOOEEPP7442qthSxj4sSJaNasGdLS0jB8+HBs2bJFRefIkSO44oorkJWVhZycHIwePVp1EFcsoZyv1U68hDBqGxfupX8dJl63K109lQlJp21mE5INz2C7BoZGQ0UZRqqrgTGZK5QmpJq6gDFPgvpDLyxaz5rFq4FRIkShTHFcxN06jsgs792orGRT2t/thytwtKJGlfhOD5ZMQ4yoqCjHzTdch7bNj8NpvTpgxmsvqe6f1a8rXpv2LO4cOwb9O7bEpHvHAwCmPvUIzh3cG/mNc9CmTRs8/PDDqK0Nmv/+M2MG/nH6AADA2QO6o1tBQ9x3+034/ddF+OCtV9GtoCG6FTTEnl07DZ/styUL0a2gIRbNnYOLzxyMbq2b4PpLzsPhQwex4Jf/4YJTT0H/ji1x37jrUVlZwR4FaXpBcctMk2lEJ9YSjIFwFQ8Qnon33//+N1555RXMmDEDnTt3xu+//45rr70W2dnZuO222wAAkydPxgsvvIAZM2agdevWePjhhzFixAisX78eqanBtNRXXHEF9u3bh9mzZ6O2thbXXnstxowZgw8//FA0y8xQLmAsTryWNSwajP9klZq+QVmeMGYtv9bCqNkYMC3O0ZdETQfFZ6uXqI0H1CYknSbMoq2UxyWYaSzMBFJqbYSeACM4jFq9CQKOlNfg4a/XMdHQsrRyZxHKq+uQkcI2FfIK2LIsQ66sBKqCC7q/PAnVpUHBJQAgUJGkLl9ZBVRGItJkXwCB5Pq2K9UnQAOAnCgjkBhAIBAI3w9UAgHUQUpLY+J16hMTsXjhArzz4afwpWXjhcmPY8PaNTixc5dwmfdefxG33nkfrr/t7vC1jIwGeHzKdHQ/sTV2bN2EG264AQ0aNMA999yDC//xTyQ0aIwxl12AD76dg6b5zZGSmoptf25B2xM74ZY7g2akho0aU/H46tR/4/7HJ6NJwyzcdO1VuOfma5GcnIKnX3wDleVluOOGq/DRO6/jvnvvZXp27eu1a3GPR6FBi1j6wAgXYBYvXozzzz8fZ58dPIelVatW+Oijj7Bs2TIAwQ942rRpeOihh3D++ecDAN577z3k5eXhq6++wqWXXooNGzZg5syZ+O2339C7d28AwIsvvoiRI0fiueeeQ35+vmi2maDye9FIsFZyXAQPJKMf0noqehLE+MA497mxOr5RHRApTAOj24J5ZaK/C51WBmA7dddcgDGmRQs9OnrvhDeRnfZbW/InWQMZzYf+vR/XFmLboXLMHD+Yum3S37SQKytRffoghMSUzQCUIgsp17Tyfkn9P+31EIrq/ynvH6j/d+KK5dR8VpSX4ctP3sdrb76LQUNOxcHSajwx5RWccXJnVbk+/Qfj+ltuQ5nCuXzM7XcBAApy09G1Y3vcdddd+Pjjj3HPPfcgNTUN2Q1zAQSFlMZNggeOJiUlIzUtLfy3FnrdPe7uB9GjT180TE/GBZdeiReemYQfFq1C85bHAwCGn30eflu8EDIYBRiBMJ7TrX2E+r5y2uMtKYnxSCPHUhRS//79MWfOHGzevBkAsHr1aixcuBBnnXUWAGDbtm0oLCzE8OHDw3Wys7NxyimnYMmSJQCAJUuWICcnJyy8AMDw4cORkJCApUuXimaZGWonXvUgiWVcfWiiZnEK1QMvDVFCgpGwVBeQuRoivRue/DFWTEgi6xFpKd5STV2Ayf+DWIaCOT2fFn0nXhMfGL08MKac8GFjYWmkDSMTkgO8uAW7dmxDbU0NevXpE76W3bAhjj+hrapc567dVX/LAGZ+8wX+deEIdGjdEpmZmXjooYewc2fQJCQ6D0y7jhGBqlHjJkhNS0eL41uprh05fNC6CclKWQvmJyMSYnoyvkeycA3Mfffdh5KSEnTo0AE+nw9+vx9PPvkkrrjiCgBAYWEhACAvTy1p5+Xlhe8VFhaiSZMmakYTE5Gbmxsuo0V1dTWqqyOq1pIS8pkZIqCcr7WJ7LQH2cX38FDDkg8M4XIgIOuG2hoJgiQzHWXibMIVmkXc+G8WELUtRBMSuREzTZNybJo78Rrepn5OPTq6Rwlw+sCo+LFJG0jvxMvXvpSWhpTZC1BWb0LqnJ+FdXsjc9VJzbNV5QtLqnCoNDKv5WakID8naGZfSzhP67gGKcjLSkWdPxAWzFrkpiEnLbnehBR0tKXXCRg/Z1q6Opx96a9L8MBtY3DzhPtwwblno2XTxvj444/x/PPPAxCfBDIxMSl8T5IkJCWplzRJkiALyDtkFyyPYn0VjDBSboZwAebTTz/FBx98gA8//BCdO3fGqlWrMH78eOTn5+Nf//qX6ObCePrpp/HYY4/ZRl8J5SSnncisnNdhPQgpSIDsZ8Hog0KkQVFPzweGQLEuICNZZ5Ez4re61s/pA8NchQgruW7Imi06oQYwn5eU1cwEGKrTmykeSm/M6+XU4zYhORAybezES1fOCJIkBQUJKTj1JqSnA2mR/DYJmogcqVYC6iKKciktOVImjRD1k5aChPQ0JPgDQFrQrJOQlo6E9GR1ORP+C45vjcSkJCz/7TecdV4LAEBJURF2/PUnevcdoFvv1yW/olnzAtxw211o0TAduRnJ2LEjcm6VnoCYmJQMv19MDi2S8YTq2+Rt0Gwj4EAbWnD48HLjmPKBufvuu3Hffffh0ksvBQB06dIFO3bswNNPP41//etfaNq0KQBg//79aNasWbje/v370b17dwBA06ZNceDAARXduro6HDlyJFxfi/vvvx8TJkwI/11SUoKCggKRjxaGVuuihFnujViBh6sj5TX4r+IcHNF5YOoCASTrWDGN6BA1MFSZeMW8GyuvmBwyHV3OipNoCDUmC4KpBoayTf0opNgffmgXrETJWTFFOTW7pGdk4sJLrsQjD92PBtkNIaVn46XJTyAhwdjroG3btijcuxs/fv1fDB/cH+//MhtffvllpIDOAzQvaIk/Vi7Hnl07kZ6Rgeychqq2ZFm/LhUsfvv0Gqt4Bq8TTOwg3AemoqIiapD7fL6gVzyA1q1bo2nTppgzZ074fklJCZYuXYp+/foBAPr164eioiIsXx5xOvv5558RCARwyimnENtNSUlBVlaW6p9dUKcvV/vDRJmQbHR81S7ahos4BxvjPlyBJ3/YEP7bUiZewmWjcFqjtsgmJPuceKP9nAT7wDDQMnXiVfyu88vYeaRCvyyVSZAfek7mZs+gd1v93fHxZAZqssfOqqWLCQ9NQt/+A3D1Zf/AjZdfiB4n90WnLt0M65x97rm48vqb8czD92BI/5OxePFiPPzww+H7et129Y3j4PP5cNGwvhjarS327aE5sV0BEcK4TVLK7qPR0WIexEC4Bubcc8/Fk08+iZYtW6Jz585YuXIlpkyZguuuuw5AUIU6fvx4PPHEE2jXrl04jDo/Px8XXHABAKBjx44488wzccMNN+DVV19FbW0txo0bh0svvTTmEUiAeuLXbj6tmpDcEi0kyzIWa6I8rGhgSNeNIraMfWD4VM2izGKW7PiU/i7cAoyi4sGyany4VJtPIwK7lYV2amDk+v8Jp2swIGxKA8MTL+II0jMy8cqb7+CFOhkHSqsAANfcdFv4/o9LyHl37nhwEu54cBJaNExDbkYKAGD8+PEAguO6Q+cuWL3rqKpOqzZt8Z+vZ1Hz1qffwCga5198Oc6/+HLVtZsn3IebJ9wX7uC6QAA+STL1JSN8kUyllSitqjW8zw2DZnmWAO5lI4ZKG+ECzIsvvoiHH34Yt9xyCw4cOID8/HzceOONmDhxYrjMPffcg/LycowZMwZFRUUYOHAgZs6cGc4BAwAffPABxo0bh9NOOw0JCQkYNWoUXnjhBdHsckG5A9fuCrVKBScnJqsRJ2bgcXg1gpG5zWghqaoNRH0zNCYk2iRyPHSCtPg0GqRu0KNlpmlSsrZxX6l+QQrIsmxJGBYtwDgRxk/bgrBoGhkQKsKI7iLBwroTMyJp1MkIbnw2FZYiPTkRbZtkGnPGwKYbhU8RB6bS4pjygWnQoAGmTZuGadOm6ZaRJAmTJk3CpEmTdMvk5ua6ImkdCcoBqzUZ2XdcPD14NQ1mNKh27DpliCYkQwFGvwl/IMApeERf43lfwt8xUStDLqoU1EZMnY/nL+6milyJ/eiLgCVPEQ2Uz+b0ZybLauFRaPsG8gtrD8qa/zoBZQ4YIaYcAI/ffwe+/+Kz8N8hWTggA2df9E88/PRUZspFFUFNSEWN8YGoJHrC+tNIayKqDccROxFGuADzd4D2+ADVPSsmJMJA8Adk3WgOEtbuKUZ1bbT0LeLjoDMh0WsnjExIxgKMOR8kkAQPmvcVKnGgtAp3froa2w+Xk8txmKOC9OnfjnIobNpfihve+x1L7j+NSN+q/CDLVn1g6Msqj+DQzQPD6APjD8hYtasItXX0T2ElL0d8gcUkYu1pK2v82F9ShbysVOr+veXOB/CvMbeG/27eMA1pST5sPVCGjAYNjCsTBMKgAGoT4lxbE8/wBBgOqH1g1ENSaxaxslOrrvPjtOfnoXXjDOJ97US/aOthnPPiQtOFg87cQrzKWU+sE68/IEdNRrzCA4u8+fh3G7BgyyF9+lRUCGYsBg2M9uUpzwIC3KEBDEHPz4B09fI3fjWlx2oGfX7WJrw890+mOrRNxPtp1HZxT6L758EyBGQZ5TV1aJyZQkWnUePj0KjxceG/j2+UgYxkH2oyyPm9zJ6HdezE99tlgEz8yYRjyoT0d4DeTlCWjRcQKsFB8Xv5jqPYfbSS2Yud6FPBuHulpRvVDgM9Ix8YMwEmul3zlkk0tSZAEkJFlAnFtFi58yhu+2glNS3VNdNa9FDSEjGxWFmnWdpfsbPItIzMONm+Oo9ReDEDRx6Y4FCVdSvIYPSAiaOVNcRq6LvzB2T+8SRCYDQdkHHUuWFY41lZu6LGj71FZcjPTkW2Nm+QDRCxCfAEGA6onHg191jywGzeX4of/tgX/lsr4BgdDMkKGUGHzKMV/B7xVsKoSTBKKW9EhSR0cJtvqEKJzctc+PJicwZ0QOrXZduPEMuaz8HumYT1BHZe05baB4ZGYCXQMPXRENt/RVUB1PplyHU1ANgOU3QLxArYsRmfVk1I+pplticS+fwyxL6bHfWm8R1HKtCVRYDh7NiKimCKh6Qk0qledPAEGA4oB3OUCYlhRJ0xdb7hfZIvCy8e/HItXpyzFYUlVVTlWbLDquvpXCdUNsrIatQWyW+FpttJz+R0lnESnywyB0seGBGwlrCNb2bjrScCRu9ClYCOslsq62TM+asM5yT70DhBQmVlEvy11ZDrgqa/qqoqBOpqwt9HVZX6+6ytqa4XfoKoq5FRVRXMs6W8HikPVFVJqPUHwvdrqhNQlRBQ1QkkSJB1vr/KqipV3dpAgNgWCdXVkbq11QmoSpRVdWtryHyb002AT07UrVtXEwj3qUx4Nn9tALWSL1y/SvGMgYQEVFVVobq6JnytWnEfAGqqfaiSIn5aoXv+BD+qqyTqZwrICZDrN25VVVXw19ZArk8L4Zd9kHWST9ZUJ0S1sWkP3WGmRtB7H9pxaPR8VVVVjAcLy6ioqMCBAweQk5MDn89Hz7AGngDDAd0washRi6uVBYU334keaIUXPdBpYOjp+Q2kB6Mdtj8gRy3kvDtyGhOSSJBDuel5MJsmrDiRC4eeBoZTQHHiVdE2weJr9MWG4M72jLYBJNaU4nBZNSrrNyeJFak4WFwVHpvJlWotTXFlLUoVfk7lKT5UHg3ujg8QTMsVKT5UpCfDH5BxoDj4vdcVJyE9OVFVJ0HSNwknVqTiQFGwbk16EvwBWcWDEeTSFBysN7XWpCWhKDVRxWdFamKU3xYN6oqTkZKYEH4mLUqTfKisdwT3SdEbydKkBCQn+lBcGdRAJ1emhfnyJUjwlaeivLouoqEuTcEBhck4UJKM1KTIQhuqm5qUgMq0JBwo0TcvK5GYIIU3bsmVadhfUhX2BUzySbp+gTXpSeEoKpGoSPGhrDp6ndGOQ9JYCyGpIo1Lq5qTk6ObWZ8WngDDAeUQ0y4YUfH3FmZdkRoYVhDZptLA6Nj6GdX5ZiYkvkRNJK0SPSExuXRoL5LBlIDLYhiSrO+6QQXxehTyxoGPgihO6Mr+d0M5lu/3Y+ZtnfHOV2ux6M+gM/g34wbgjh+Worw+FHnOnUNVdd9a+Bc+XLo3/PeIzk1xz5mtAQDXfzE3qq3zuuXj9uGtcaC0Cjd+FXSMfmBkR5zWOk9VJz05UTec+KuxAzDmy0UAgFuHtcP+0ip8+tteYlktpl3aHY9+swoAcNOQE/DPjgUqPi/s0RxfrjxArmyAB8/uhB5Nc3DjV2RTbf8TGmPxn/oO9n3bNEKPlpl4Ze4eAMF+DvGVk56M/97cH9+u3oNpv2wBALxwaQ88+k3Ep23S+SdhQOvG4b9DdXsd3xC3DC3Ao1//RvUcTTJTcKCsOszDE+8uw/bDQVNKi9x07NbJnH3bsHZ4oZ43kTinaz6+WxP9PrTjkDTWQph9xxDdQ3n1kJSUZEnzEoInwHBALxOvLIs9C0m0BsYqqJ5Mz1bMSM9oh0s0IXGat2jel907f1ryJVW1pjt/F7nAiPeBcUIDY5CkUCk88kR7VfuB1NRUFNUAe0qD33ZSSioKy/woqQr+rUzmCQAV/oRwWQAorZXCZZTXw/frgvcTq+Tw/TopMapOZopE3HkDQHJyarhcDXxRPBghICWFy1YFfEhNTVXVVT47C2rhQ1JKim7dI4rnJeFodZBGqIySr2o5gNTUVFTLieFrsi9JRc+v6EMg8gxtqoGEpGTqZ/JLARQqeDhUGaGVkhLQpVOt4F0kSmolIl3tODRqOy0t1XRjZReEn4X0d4ChD4zBgsh6Xo9IJ14RoDIh6V1n1MAY+ab45WgTEg1vpFdDI2/O23zQvBAleJPp7SmqRNdHZ2GlSbSOmxwuuX1gaPLAcPJm1NWrdhXh+dmbmeuxQnuqNevu1Qih8bypMJKFmdd5PVyX4dlVjtaEilY2eIbzhalgL5v6acg6v4P0+fjSwojPWOw9aMdBkk+/72IlvACeBoYLah8YxW9Y+0C1A8FtAgxvpI9+WaOP2dgHhqtdUiI7iorLth1BYXGVkEWM9jRqLb5fQ6fCd1N+EtHzmizAhGSEC6YvMryvfJynFYecWoJsbGrTCoFmjx3ql2vfpTNpkFlSapjZOlpZnuhzxjk/mvFBc7K66XhU8h5FkG+u0sJYEDJow6bPmvb9dm2Rg+U7jkZdj/WB854GhgMqs5Hi+pPfb8Dq3cWqslbGXXWtscrQ6WgNurN+9FXw0dcM6BjcJOeBMQdZA0P3hkKH2dkBXt6JtARPdC6Sh1yF/21g9+MIQXUkgcY0ZR2UmhXhFOvLyuTfIRhFHprRNZp/aEyrLP5jUeKLIA2M8abNefBmNQ9B9HEhzO3HtPU4hXKgKT+cj5ZFn/xrZQGIpQaGbOrgq6d3nVclTNbA8AlXtDtCO4VFuggq2oVJ3DRotmiYwU4fGAuGCO6adoA1P4lpHhvSd8aYEkErhDA5uiuKEhNHWhBgjGAqwMBcW2AkfIkyIRlFPcZis0BvSiSXi7H84gkwPNBz4rUK7VhwnwmJRkhgoGe4o9KvF5BlZtU6QPar0WtH+6yiPlRWQY6ljLZcjOcWU6GP5agBQLNDjsFsb0eLQdOGkX8BIz1KJitNtLu80DOvh8ArwCzYctDwBSzaapwTxdgHRg6XUZZXl9DRLMtsZjajNAdG86Fd493q0SOx9H8BPB8YLqgldfoBwPqujTLV2g3uRHa6URy0F4Mw8kfwBwj8UfBG9j8hV9ypCWeUJDELGG+/0kI5P1o+zBHWeDNNusdIXKuB4eHNjSYxlvdkphEz8rHiWQRZ+1lZlDR98QowX63ai075WVx1ATpNl5EJSdRGVZQpShSoTdM612O9SfI0MBzQS2THgv+t329axuxjd1r4tZTIjjSxcvKhVcMG03nzUdPr4yHPzlX9baetl8q3KAYmJLvAncguxs8mahesjkKKPpjUCsQI2fxQO/FGU+L1gQGA/63n9zuSYR6FpE2JoaovyPRjGIVkJNzQN8EEqxoYzwcmDqEc6Oa2V/L969/7PeqadiwYndZsN8i2dL56enV5v52obMcyvxmGdj6NpQlJluXYOfFaqGumXmZWPxttkW2GXc3JELsIiN7hM5/1YyLAWIvS5K5a78RrVkaxMaV2hmbbPLkpUTZgfb7wopDiEMqBLt7KE6EdldU3xhC/OPIRrAvImkgOSh8YBhOSFqIWGR7B0ExA2320Ajf9ZzmW71AfAGnV8diqxkG3dTO2dPpahPziNhMSzcKqrmB227qJMsr/g8WEpChLElasCDBWvkFZZquvZZNXcxJN14iO84OT9n3osRZrHxhPgOGAU+OsLoYaGF6IOkrACFoNTECmO1qANHlQa2AAIdtw8gJjTtho4rv1o5WYua4Qo15ZouobIUcfWBjswvPAxFj6ENW62pdHbUL656uL8eaCv8J/M3dhjKcM5fdEirixkhTSZ2G7HwxXV/xt4CsERH9vosw72rJKnkRFOrHAuhOvIEY44QkwHFAl1DIZvizjQ7tjjq0TL2c9XROSnT4wlH4kJFq0YdQ2fqk0SbiMivx5oExV1i2wc26LtTAjDLJ6bP22/Sie+F4/SZ6pts7gGm2PqTRdlN9WpLzChCTYXmLVhKTUwJA1oSrJMqq+Pm2+/tHStSpM8MBz4v0bQvXSmQQUcyjH8CwKR1+3gddezgLtadQyKA93JJShnTRE2XrJzVEIX7o6XLWvlDqM2qIJiYozfYgW+oSYkKw8kaD1RcuDyG4SvQiyZ+Il/xYBqyYkZXWSdkirGVNC1BEAxukh9O/ZJdpY3QiIPAaDq/2Yth6nUEUhxZAPO8E7sHXDqAmXH/lmHVc7gYBaYAnuEinqEU1I9BoYu06jpnHiNSqj1NTFOlKHCiYs6k2JsdRI2gUZjGHUJoNl++EKTPx6LVfdSDnFb5iPT03t8C+RB9sC1jYR2igkoj+c8rdWA6NHV45vHxhqAVWnnBeFFI9QLZ5xsGA4CN0PnXBtx+EKrNxVxNwGyYREM4vwHuYICPS2J6quzasYTTTK0FSRawbr5KyF6Knthz8Kw795+dKr99/lu/kIWoQsi83yvHpXEd5bskPTBv9LZK3KEqHJCks+MBoNjJlPnvY7Mu5DFhOS+m+1D4x7TUh6iLUJyUtkxwGzA8uUYPKBifVoEABdHxid66VVdcxtBAKyajKjDWQklaK100uQhDjScScIpG4gNgL1vZ+voS4rRpMl9jnv/Gy1Y21qTRWG67LIEGuuOqwmJPs0MFZMkr/vOIo2x2WE/yZrYJSmWMImSQdWPjkjoUldzp7vOt4z8XoaGA6w2OLjVT9jYc/GVLqOwyxQp/WBodQUkMrQm5AombOBB1lmOQtJ+VuIxEWFT37fFXVNr8/iUWlpF89BzQD94HKi67Snfos8C8kKfBY/wk9/j2jZzE60197eX1KNRVsPkaOXLHGlbNO9JiS9UrHedHsCDAfMzvtwCm5U2OieLaTzCfD4NWhNSMEwavP3QBYe6NoU9Zp5fGB0K5rQsr4Btv7QPBMcTR1uExJfNUttGvEgw/7vWEa035hdsFMDkyBwtTJnTV1g6v8244o3l2KO5hRyy2ZW5cuPwVJiNdVYrBPZeSYkDmid3GgRa2mVBaJ9DPQ6iifbcFQmXn3y6noE5kRPsmYg7+BMNDCQqXdKondx1rQ4OgnpRCiGZOBoRY11QjGGHHSCIaKwuAofLtX6s7C3UVMXwGlT5qFVo3RKptT8sTT51A+REHDRn5ZIcwU5D4xa80TC3M0HMLxTniktHrhaA6NTTKT/Fg88AYYDqpcpcMyxjt9Y2x9JYF3weLIN+wPqOT9oYjGvZyUTL/9pSxS0TQiz7PJUxSxOiCLmUwn2bCyr6/yY+PU65npuNF/pRXKc+9JCHCqzLqQt23YE2w6VY9uhcua6rBqG/SXV4d+i88CIjHghsUajvayts9OEJIgQA6x+D1Ycq0XAMyFxgEVSDi2Q+4or8eHSnRTludkSCtEhq3qPxaWB0e4KKe30pCKkfBB2grc12npiTUgC1eNKmgKmfBELOyuEmZBk9W9SN323Zi8OllZHXedhISWRbZoXtT8T/W2JXCtNw6gpTd7UOag4eQq3Y9M0Re8DQy4X6z20J8BwgMdR7dwXF6K8xm9M10Uuvy/M2cJVTz8KiXyD57gErdnHiiMarZxmx+IVgqVTvrXllA6YLhhPPFrCWKul7cK+4iqiUELqonEfrhTWbmqSj7uuLPOPI9HmWatOvEqQtENawZKEGsKEYUd0mlPQm3vmUx754OWBiUOonXjp6tDsGN2ifQGA79fs46rHGkbNZULShjga0DfjwUoacB6QKNCQpRFyEhMkqkmYFrS+RXrQm9pCfMVi6rOy2Ij4PAdN/llFSZbtXwRYNTBK0J4zpldXJESazIkmJJXwTwZRMy1qc2NAyK7NiJ6MefXby6jqx9qJ1xNgOKB857FwvHIC/KYOtpo1dQHsPlrBVCcQkDU+MHQeKiQBxGoYoQicP32RcduUJrIkX4LaEdEyZx5Eo6o2oNJMsH4vPEI0qymHN0hBC6sRLlr4OFarsaeeQLxO2oSqhX89E9Kx5QNj1Yk31kcJeE68HLBrkTgWFhxdDYxO+Se+32B4eB0JdQH1tE+tgSFcczoKiWc7S+tAnORTa2BECNdWT6MmTW8xHecu+Mi2H44I7LJsvzP+O4u281dmjEJSwooPTIIUvaDzaKr06pj5wOh9OyQNjBM+MHbBapueCSkOofywzCZ4lvHhpmMJRPMikpw2p0WUU69ePWIUEl2bovqDlwrNRJOcmBDl3GwFdg9HPfKxdgwkIeisKaZDDpRUqf5m2cQ6MUPQmFJoYCUKaeiJTaKu8flTkUHUDlG4BtTUxcYHxjYnXos+gJ4JKQ5Bky+Am7YbtoiwYEJygH2/1mQkU/qRECZUpogy6pJiQRvKmuRLEH7QqDUfGIkojLhITqeHQJ612sNY72KNwBpGrYRVDQzNNTPoCT2shzmGYKcGJhbwNDB/QwTUa6cHBfQEMJGCmV97GjUlfVIJ6ky8dMXM6XASouEz6AOjbMsa13YJ0//bsB+vz/8zRk68samroqN5R0xrgAMTjvrbkrkbtWKeJQkePIulXhUzbawe51ofGFl2xvRjVwv00Y1kxDoXmSfAcEC5MPy88YBBSbZFwE2SvOiFVqgJSZajtGC8UUjO54Hh8YGJ/L8REjVbVBGPZoWG0dz21A8b+QnHObQmGvfqX6y9fysLO0nbwpM0Td8HJvqa8r0w+cBo/m7TOCOqjFthXQMjiBHe9mPbfHzCTYKG2+CEH08gwBcJRipHa6e3Mw+MeR2ZzlYtiXcwt6qF4cnpYuec6AY/M22oO9thjs7u9mVY2MxYiEIiCR48m329BZZ8lIDyD3I9Uh4YbVkXWwSjYHUD52XijUOwZeKlp+sW/xcrcOIJtLkpgpOsectEAcamdymaBu3YCGgWRyuwWj+eJnIaCBNiNX+5uZ+sPLM1HxhRJiRyHRJvavmFRQOjLmuHWcUuudtqEINnQopD2GmPZBmo8bRTFUkvIGvU8BqBxqgezTUyxPDPQ0UGHZ/Bc4fM1eDMjVuByxZnV2wRtDt2HhIOaZKspMq3EoUkyvlb14SkkEMOl9fg7BcWoLSq1rQtbeZwkobKZUPeEMbHF5h3eKxNSF4eGA64JnmdjYOH9wlZ88BwthKlhqehL/pwOR7wLjx61bRDQOTQtKyBceFUbu2ZRAmxGv8tlrqy+r92IMq/jNeJV7AGhocPWifedXtLsG5vieI+uR5NFJIdkTn/nmmPz5jZ+Utmj+JFIcUh2MxC9tB1LxzwgdFM+rSaK6uCZ6xeD8siou4X6xzHQgFj55zILZiL5EFBbOXOIqzcWcRMw6lNlJUxZGXDQNrZ82lgyNfNaOn1LzkPjBpuNglqYeSnRNPdsdbAeAIMB2yzR9pD1lHoamAEPly0DwzlUQIW2oy5cMlhq441yy5UwLgCyvdyz3/XsNUNaWDEsaPbRui3naH/eiBqYDgY0dMCmmmH9O5GHSUgR/MVa78QFhj1Kc2Zf54GJg5xLDjbmoLzEW/8z3IdcoJ9YASFUTsNLh5kuh23JIk+zJHf/8GtsKJREBeJZp2QYxoYC3VF54HhocaSB0bdGPk+TRh1/IgvxkImzRDzBJg4hF2uFG4I8bSKw+XkU7fF+maoxSHaowQstSmMDjsl2rOQAERppmIJCe5Tp3NHgQkcwJY0gaGsQA69WlYfHSVE54Hhoae3wJoeAaNzneY4EreNeSMYaaJo5o+EGEsQngDDAbbQW4aycIHavx6i+RDtQ6A1lTgi/MVQwKSNQlKOTRGCdiyEIDtV8LzPI/LbjGU4PnM7FrRwVjQwZBMSDx3ydTPW9Px3yJe1JiRzvtwCo3mTZjPkaWDiEHY58R7LsNUHxoKdnhZVtX4xAgEHDa3AZljWYlvadq1AkiTXRSLxa2DE8mEVzjnx8te1FIVEWJn4TEg6PjAmHzNLW9rHZFofYjyurM5psfb38cKoGWHrTp+R9N83D4x2P8BiZOHDeS8tEkKHl0va7lOXs94nsZ5g3QK3dEPofdgpwEQtyLxaKwssEn1ghGpgjImxLOwiTIKxglE/0Djxxnp74mlgGGGv/OKWaRIor/ELpSdywg1oNC7av90MHkFOBn3/aXOMxBJmk1ss2OPtk6KKGuwvqRLLjAU4ldLIysaD1oTUMD0p6ho5jJqDF10fGONq9BpPa47usf5GjULdqQIjBPLCA0+AYYTTSezO6drM0fbsgngnXvVCHesPiRZ8JiS6SVKStIKdAA2MxfpGGuZYOK3z9smCLYfw2LfrBXPDDjnqhx1tqP3LeNuiFWBojw1wUgPDAjdtPFlh1A2yzm91/dg+uyfAMIJ552PRHhprG6MoiNwxan1e4incl5dNag2MizrCjUPXPb1jDU5tpKxE+NHySJrjRGXiZTmNWn2fvi0rkW2xHo+GUUgUDxbr6cYTYBjBOuSYnMEI11y4BnBBuA+MNg9MzKcCOvAsPDLoxpEESbgTr9X3ZjR+YzH5xXrCtQqnfWBIhy/TglYDQ5IxSNd4NkG6GhgzJ14GnzNtUTYnXjf7wFir7wQ8J15GOP2+3LiL5YHIbtMeJRCIIxsS7wdPM9EdKqvG16tKFW1xNSUM5j4wMfGCiUGb4uHUUwQCMvciSzvWSUKGKBOSXhSc2dhj2nhyf9Nc1YSiqpbuLAG9Z4z1M3gaGEbY6sRLcEY1irOPJ/OS0ERgpDBqYdTthdHZI3qgDRPXJhG0KiCIMM0ZjVHdyAY7z0KKl4FiAls1MJp2+E1IdOXIPjDR5UQe5mjuxKt/75W5f3K1SWyHvqjjoDuexfOBiSvYO3FE044fEcUYIrUBAYLJKNaqWDvBHSQeaw2MyUzu6V94EHwCp4a7lVwu9BoYOh8YnpentwH8YsUew3pGvCtPhpZBCDunNT+F/8+dUPsZmpeJBTwBhhGsAoxlHwKDRWDrgTJLtJ2EaK9/bbRNrD8kWthpQoqqw9XSsY1jRdB16jGCJiS+uqLzwPB8O3rT5/d/7DOsx5ZBXV22WXYqknx0W083j0aa/o715+QJMIyw832RnFHjyEpkCKE+MAFNiF88mZC44qj5NFhWF2vL5iOYOfE6/9biZZzowRkn3ght7eHLvHSMQJrjyCYkdvCmumfpXq1ZOMmXgD8eHUHRhrtHo6z7h/KyZ0KKK8gWvPJNaROuHSPyi71RSIj9ToAW3LtZneslVXXMdZjajUG/2nn8QLyMEzPEQxg1LWhNSDxCPO8GkMmJl3AtNclHV9fFA5Iqkd2xqIHZs2cPrrzySjRq1AhpaWno0qULfv/99/B9WZYxceJENGvWDGlpaRg+fDi2bNmionHkyBFcccUVyMrKQk5ODkaPHo2ystibTOwMoyYh1odliQKP86oeovLAyNxeIo6DS5MCvonOqt9RXUDGwbJqfgImKhjPB4YdIf5tDSZQ/LYShURbi1oDw8GHExoYK/3j5vFI58QbWwgXYI4ePYoBAwYgKSkJP/74I9avX4/nn38eDRs2DJeZPHkyXnjhBbz66qtYunQpMjIyMGLECFRVRVJ1X3HFFVi3bh1mz56N7777DvPnz8eYMWNEs8sMW0NTCR/CMSK/CD5KQOsDE/udAC24fFk4n8/q7u6KN3/FqFcWW6JhBD327BRG3bzjZYFjTrxWJjzKqiQhg3gWEgcLvPNnRa2+ZlMLLV+h8fvouZ34GncLKJx4j7k8MP/+979RUFCAd955J3ytdevW4d+yLGPatGl46KGHcP755wMA3nvvPeTl5eGrr77CpZdeig0bNmDmzJn47bff0Lt3bwDAiy++iJEjR+K5555Dfn6+aLapwToBMknyhGvxFCptBJHDPLhzkTVX4gO8nPImwLMCwxwRFHDbSdRA8EiAYwFOJbLT5lyyA6QpzifICYZXA/PavL+oyskGDnindmiCRw2On+DdmDgFGtk11vwL18B888036N27N/75z3+iSZMm6NGjB954443w/W3btqGwsBDDhw8PX8vOzsYpp5yCJUuWAACWLFmCnJycsPACAMOHD0dCQgKWLl1KbLe6uholJSWqf3bATg0MaTAcI/KLDT4wStrxs7PmiybijARxQZfwOPHGyauMCUJ95lQXWRGUqE1IlNe48sAw12BHVOBFfas0ArybTd/q8+b0vtVjzIn3r7/+wiuvvIJ27drhp59+ws0334zbbrsNM2bMAAAUFhYCAPLy8lT18vLywvcKCwvRpEkT1f3ExETk5uaGy2jx9NNPIzs7O/yvoKBA9KMBcP6FHSPyi/izkJR/wxVrNRV4+4FPAxPbXjETvuPlnbkRTqnu/RZUMLRzJdGJl6CB4fGjc0KDzZuQ0e1nuNHwFuts38IFmEAggJ49e+Kpp55Cjx49MGbMGNxwww149dVXRTelwv3334/i4uLwv127dtnSDuv7YllESB+8p4GJRpQPTECOuS2WFlyCCOca4oYu4cnE60EfESdeW53xwr8CFhzkaWuRfWBI9HiceJmrMCGeNk+soDHSx3qTJFyAadasGTp1UjsvdezYETt37gQANG3aFACwf/9+VZn9+/eH7zVt2hQHDhxQ3a+rq8ORI0fCZbRISUlBVlaW6p8dsD2Ft4b8MROFJLDb/m5h1MHn4xN8Ygl3noV0bMCxRHaEhk44LkNoG+QoJDFh1E7Mn9waGLf7wFB0eKz5Fy7ADBgwAJs2bVJd27x5M44//ngAQYfepk2bYs6cOeH7JSUlWLp0Kfr16wcA6NevH4qKirB8+fJwmZ9//hmBQACnnHKKaJaZ4PQLo/n8stOSbOfDKoRm4tWakBxwNBQF/oPxeOq4u1d0o5BczncsEUlkZ38bQNCEpH0dtGYZ2tdIoucTdZijA/s/PUH8WAnAMEKsP1XhUUh33HEH+vfvj6eeegoXX3wxli1bhtdffx2vv/46gOBLHT9+PJ544gm0a9cOrVu3xsMPP4z8/HxccMEFAIIamzPPPDNseqqtrcW4ceNw6aWXxjQCCXDO+z8Emo8gKy0RxZW1NnAkDiK7Teu063ZbshK8GXXj8SgBmh2oBz44lsiO4HdCuyzTathIZh7y2OExIcVQA2N7y/ZCGyhBQqw3ScIFmD59+uDLL7/E/fffj0mTJqF169aYNm0arrjiinCZe+65B+Xl5RgzZgyKioowcOBAzJw5E6mpqeEyH3zwAcaNG4fTTjsNCQkJGDVqFF544QXR7DKD9X1ZD6M2r+fGcFUtRJoLtNlBZZLtzaXg/eD5BB+upmKOeOXbCYS6xqnTqP0ySQMjtj0SPWIeGJ5HdkQDo9M0Rdtu1jbGg4lXuAADAOeccw7OOecc3fuSJGHSpEmYNGmSbpnc3Fx8+OGHdrBnCXYKMCTQCCfxoKkUmYmXHEYtjr6d4EtIxyuexTgKCZLhBK1379dth+1i6ZiBkz4w2oWMVqtBbUIizHGxPguJFrKBA55Z2243favmWB1OYz3vemchMcKpQ9RCoPGijwP5RXAmXq2HfPyYkLh3NRwPGOsQRzPosbdoqyfAmMHO8a6N8OOmQ1mONMeRnXjZeSH50oiGlqtQkzQtu3neCvX316v2YNeRSmKZWGtpPAGGEXa/Lr2PwQjx4Cwmst+0PjBBgcbFM4ECvOsBT7VYq6c9HxjxCL1Tx/LAEE1IlPMNLYuUeWBc68Qr6/xNkQfGzQhxd/vHq3TLxHqT5AkwjHDaaYlmsnC/+CJ2MZWjTEjxo4HhzQPDA7d3idsncDfDqZ6z4sRLC6ITL4kXjg/BGQFGJwop3jPxUrAW602SJ8Awws4XRoxCoqkYBxKM8DwwUcm24gNOfu9b9sf29HZPA2Mf7HXiNf626BUwtFFIdInseGB3gIMMAxNSnOeBoRGTY82/J8AwwlbbM2HAHCsaGOE+MApydf740cDwgEU88yVIGNSuMQBgTxHZbu0kjDg/hl+Z7XBq50vOA0NXl96JNxqi8sDYnYkXOHbDqKkOc7SfDUN4AgwjnLb5HTM+MKI1MLLm75h/SvaBZafmkyQcl5liL0PUcP+4jDeExoFTTrx+QkOitRp2HiXgyFlInG2XV9e5etbyTEjHIFg/Ij+DxKN1TgWOnSgkoQNd47RbZ+HAuWMOEuJjQCD26ud4hlMbKVKOJQd8eImLP08qBts1MAZJJs2avuT1X139DdCsdbFm3xNgGMH6ERWWVOFASRVVWdJgOGbywNiogfEHjmX9C9sk4aahYD4uj+W3Zi+cyghu7SgBOh5pz0JyqwZGv23j+9sOlcPN3wDN64t1Jl5PgGEEz0f01sJt3O15mXijoVW4BCdZ904ETkKSXDYeDF6L98rYEfqOnOo7kgaZ/igBOhBNSCR6cecD46LvkAN0JiT7+TCCJ8AwgueF1fjp1DbEKCQaJ16Hv5PmOWnMdcT7wKhNSPuK6bRc8QiZ0cfHLRo5CZ4Tr11wSmCXLUQh0YJsQiLxwkPb/o9BVwtBdZSAWF5Egka7Emv+PQGGESw+LSHU0gowpCgk5tbsx3e3DkTXFtlMdUSakLROrWVVdVi+46i4BuIY8bTr87Rm7Ah1ma2nUSvmIbITLyUdSh5JGpgESUJmSvCkm4LctCi+aOGIBkbnOtVZSEI5cQ5tjssAAPx7VNeY8mHLWUjHMqrr2D3Jauv4hynNWR5O23l5mhOayE4zle0tqgw68h6jYPKBkdwj9JrmwXCGjWMSTnl9+QPR364T840kAW/9qzcqavxYuu0IXp33J58GxoGvQY8vJ07CthNG/X3j4Da4oEdzpCT6nGOIAE+AYURlrZ+5DrUGhhBMQ+cD4ywkjmlBrAlJPakeKqsWR9yFYAmjluAeE5IZPAUMOxzRwESlKFBDfCZeUhi1hFPaNAIALNt+JMgXB21HMvHqcEZ3FpJ7PwIzITnWwgvgmZCYUcUjwFiYbWg+AscXLI5VUmwiO1mlcTlUViOMdrzDTTmBzMRcN0/ebodT0R+kdliGGM07NjPzhG7zPLPtp1HDwIk3zk1I8aDU9gQYRnAJMBxmpxDoEtlxk+cCj5lC5IQry8HsuyEcLD22NTBgOG07mAbGPUKMEeJgfnQvHIxCigqjZhhfNOOWJHRLqvv0tLRIiOEKR3UWkos/AiPh0y1zjCfAMIJLgKE2IZF2OzRHCTjsA8NRR/R3WqdIyBMyIblI+RBTuKUfJMlkB+7iydutCKn1HdPAkMKoWTQwFGWIhzkqroXmNx6NnRN+KLqJ7FzyHfIiHj5PT4BhRGUNuwBjLYzavJ7zGhj2BkXPtzUKDczh8qAJqVFGsthGXAKmvpPif+L0YA6nfGD8joRRkzQwpER2HLQ56rCC96yoYF33igkuZi0MT4BhRGUtRxQSpQADAF+v2qv6myoTLzNH1sDTnugdYw3BLJeWHHunMhIapCTinK7NuOszyi+ugRkvcTA/ug6Rs5Cc8oEhRCExjLLJMzealjGjZsWEZLdPGCnwItI2RX2h3IiGu7kDvCgkZvCZkOgGwspdRVHXqL6/GIRRsw5t0QIMSShMjKXB2wDn98hHboa1AxZpey84YbtHjDFMZBcPWzyXwikHS6smpNfm/2VaxiyRnTUnXuYqzDhWM/EajjGXPJo7Z3wXg0eAqaPUwATPxlDDjYc5SpCYt0Oi1yqyAOOSr0oDnrBzJVj6TnKRCclNEVFGiCfTY2go2Cn8mSayE21CInwdqitSyAeGnbYjPjB6YdRUcdRieRGJeNhfeAIMI3gEGNrkd6TxTpfIjpEhi+BLZCeWB1Jkl8+lAowHMtwyPybE4bhx8jRqK1FIZqARuEO33ZgHRjaIEIxz+SUuNKSeAMMInkR2diMepl/hPjAEs1yij74nnBT6rGpFmM5BgrvGg9Frj/VJtiG4qb9oYWcmXu1r0b4nkd+OHimVCSnsA+PSKCSd6zQaSDcLCe7lLAJPgGEEjxOvFc0A3WGO8XCUgFgeSCYkHwNjTqf5trJrfWfhduqJTpIk15iQ4gVGYyE/O9VBTijgQCZeLew+poPc/ZLiF78JyRHohVE7zIZouGWDYQRPgGHEoHaNcWXflkx1qBdLkjMbXzVbIUGKuRMvKQqJxRTgZJ9xJC5W4ZPfdzG15RaYnoXkkvnRiM+kRPdNkbIsY93eYvvoa/7WHmArcsMkSWQPMeJp1DyHOTpgHjxmo5BczVwQXhQSIy7uXYCLexdg8/4yLNt2hKqOlY+Iyok3DnxgRG/irGpgHO8zp9qR4if6wS3zo9EGI9nnLgFGhoz/bTiA1+aZR/cIazMqjFocWIIseeaQWOSBCbdNZUISzIxAuJi1MNz1dR6jsLIJOGYy8Qr+UklqbRazkJN95rRZxy0mJNM+joMZMsllAgwA/Hf5bkfb035qQn1gdJy2JMJvnjkkloc5xjvcLFyF4L6vM17A8HKt+FtQCT+Oa2A4TqO2hRM13ByF5JyfUrzoX9wz8ceTCUmW1cdo2NOGbPi3WA0Mebwqv5ewEy8nfTvBclI8sb5LvgESjHhzyxzjrq/zGAXtukr2ZaPRwDgLCWDe2jjhEMYkwMSB2U2Jsuo6R9oRiWDCQ/337pYdnlGfJTNEtjkFUgSendDmghEqjOuQUmlgrEgwDsAKW275BkjwTqM+lsHwDVvRwLDYiJ0C12nUDnwNLP3gtLImM8Wau9mR+vOezBB0GHbfokuCW+ZHo+/TbdmdZdAnxrTShhJahY/Ib4dlvLoxDwxgVQPjXrg5xDsEd32d8QTG7Ki8oDrM0WkfGA6fDreZkJz1gQEapFoTYEhRV3ptuQVmrLhlgjTi02XyCwCgzmENTLT2VGQUEpkaaRy7Maw3eBYS/1lRbob7ejsaLvw8jz3QfneknYjbMvGG2mL2gXHga3BzFFKDlCRL9Wknb7dNnkZsu2WCNPrGnM4XRINa231gjP8Wa0EiEyMnsuOhbz+i+otlZLvlIyDBgDe3aHk9AcYBWBmjbvNLDbHDOoCd2D25Nw+MZFkDw2KBc8ncEjd5YIwGg9sEGFmWHdfARGsYxIHuKIFgAa45xBETEv/7cLMTrxs1Xlp4AowTsDAOaHbUzmpg+BpzRIBh8eF1eGFqkGpNA0OLeMoD4xYYa2AcZIQSyhxIOel2jCv1txqdyE5cSzpR1KoxbEUD4wTsPCuKFSLHq1v7WwlPgHE7XOYDI2n+SwsnPgYWh0unzW5WNTDUbTnSCh0kiT1jsx6Ob5QuiFI0jPrMbaH5MtQ5kFrm2tcv4TZjsUBLxJ8cZOzn1S1RSCc1z8I34wYKo2fEmlu+Ck+AcQBW1IRui0IK+8CwOvE6IMC41YQEAFmOaWCOzbOQstPs6z+j/nKLrV8JpQbGCROXrYc5ShKxj9Vh1MH/usXpWwkZ7olCEi2subG/tfAEGAdgZRy4zQYf+khYPxYnbL0u2yyHIQFIS/Y52p7q7xj1i1BfCYG0omnHjwlJltVRSHZoiKJPo1b/7YQJSV0mWCLERgpDckG3Z+J1s5BgxJlbuPYEGAdA+7JpwwmjyzipgtH8lxJui0Jy4pA3VXsxXAhdtgbzwcYxbkTabSYkQK2BYRnzvIjWwNgvwZDaCPGhNJvRvJ7n/9mNlzsquEYDI3gouFm4CsETYBwA7UAglaLLA+MceH1g/tZRSJJzmjRSVEfMtHgS3LNVM4DRguw2DSig9oGxgz3tK4v2gREHPVpkE5L67+BvY24kAC1t9J+yCtHTosjxYMSbW74KT4DhBIvakLYkaZF3XxQSXz0n0lKz5YFx9hN0qrmgACNFXYt32PkIRnKv2wQYGRoNjAMaoj1Flaq/RX47wXPV6OiR5hAqH0E2lpggy7JrNBWin9MdT2UMZ0IjPFCB9B24TwPjrgldCZasqc5qYMiOira0RXhDUoxUISLHip3dZ0TbhRYkx31gtBCqgSFoDEPXI79Df8j17UeHWOvTt9epfWNhKTYWltrXACNEfnMukcsM4WlgOMEyUGgHAlEDQ5WJ17lZljcKyQkwHSUQA/6dWAzNFgOn4eZEXSEY5oFxmwQjy6rTqO349h/5Zp3hfQfOclQLKfX/JW7w3LihciFLPPAS2R3DsMOEpE0YBdAterHxgXHfV8rm0Oig0Bf6r2N2JM2fsXKBcWChs5u220xIAFCr0MDYIV9t2FdieF+sBoY8kxCPEjC4p0tf8f+OIVbrvmBtk2EeGJd8Fp4A4wRonXg5dxixyMTrlgGsBIuAcMxqYBA9Zty4CLPCTuHPiLYTUT4s0E4RsXi3ItuUQCuE6GmoKdpw1yuMGxj59rRo6A7HaM8HxgFYcuKl+vhioU1wrEldJCZIqogMttOoHUTI7OaAL4pZUjAn4YIhQgVDHxiXb/FiIpyK1Kzp0CJd5tngBY/W+HuARhi0iqcv6gJ/QMbJrXPtbYgSngDjIpBMSFRe9jGwIbnBhJSW5ENpdV34b7f6wIST/zmlgYkyIcX+XVlFrExIbu+7WLjoiP32daKQCE68JI0AlYnd5e/QrSAJjP3aNEKrxhnOM6MDl+8vjg3QO/FGX3NfFFL9f10wJ6QkqbPbsvAU76p3XRB2nDHTwDiwUxdDO45MSJo5IhaJ9kR3CdHxnBBpRI7SNNHAxGKr5a4hww3PidcDAHqHX7LN0Z0+MG5Akk9STeBMeWDsYEivLUn9X1vbMmg/FoiDOdBwF+/GTLxKxEIQF+vES99exIlXirpnVNlFU5bt8MKoPQiHtTBqwcxYhJv4kaA+FyWRyYTkbg3MG1f35m7HCRNSkwYp5nyIzANjo8hpRNtN4x2I3gzFIsxb+EkCJA2MFP0HaYPntvcTS4iWN3gzwzsJT4BxAFZMSG5DaBF2gyZGkiSVAOO6nB31kDT/NcOz/+iK0zvl8bVFyGxK6hYWYY/cjqXqHA3aSNrIidcF4xwAWumkw493H5hg9xo7nkdpYFT1aZx43fEOnYDYowTcvyB5AowDsHaUgLvAuhjbCUkCknwKAcblYdTaNvu2IXvyW1k0aZ14rZpGaMP73T8FGo8Ft5iQstOTAURvhmJiQhKqgaEn5oVRO4t4SBzoCTCcsEM4DZCikFz29bkpE2+CJnGTa6OQwn0WabRvm1yc2y3ftraUIHWLUvAT1Y6dsLM5IyHADeMc0H/+2AjiYjUwZBOSvhOvsryZACe6ey7oLv6bFQZZFvq8cZFFO9YM/B1Aq4rjPazMWU2fpPj/2EKS1BMYkwYmBk+gFCQGtTtOl18r6wM56sIODYyYMtTtxciE5JYoJD02YsGfcB8YkzZCI5qsEaBoQyC/Z3d1sQAjGLxn8zkJT4DhhB0vMp6ceK3uwjJTrKcgSpDUizXLmhyLPDC0ApZl3jQESPSSfFZ9YOjqx4Md3UiYdYsPTAiuCKMWSUuSyM6iqjLB/4Y0AirhxoQZltOuaeASi6IuhPrAiCNlGzwBhhMs87KVKCS3QdT38fGYvpZpBP09Ihy5NhNvqE3NxGvGwzldm1lqI3yNUM6RhU+kqcHOKCRDJ17bmmWCvgkpvjUwAP3p1zx5YETDrYECdiAOliNPgHECtLZE3kR2TiKsgYktGwCi7ecsu2Und9YkrZUE/YPXQov1i5f1QJ9WDdnb02lfiUS358jXIFaJ7NyyYIWz0WquHxtRSMaa54gGhsSLCX2IHTtu08hZwczxgwzvx8OGOr5msTiFpTwwrhAVIhCVFl/EPCBJkmpCYdIqxGTi1/5t4oAoSUjVZBs2bYPQsaRJN9GiCYmKF4G0NhaWCqSmhhGfblmw9LiI90y8kqQ3P6qFfSBijiRl6TVrQxTc4hOlD3r+OjTNMrzvfvHFAQHmmWeegSRJGD9+fPhaVVUVxo4di0aNGiEzMxOjRo3C/v37VfV27tyJs88+G+np6WjSpAnuvvtu1NXV4VgGZyJeRxH5fq06gVp/sAStBsalJqRQW8rF0GgeVO8+2TiVEO13QqLgloWZFkfKa2yjbTRsXKKAUUTiaBLZxcKEJJgerbMoSUNtGoUkid0EUp29JKw1NggXOOLAJ9NWAea3337Da6+9hq5du6qu33HHHfj222/x2WefYd68edi7dy8uuuii8H2/34+zzz4bNTU1WLx4MWbMmIF3330XEydOtJNd22BlYLlsvAg7C0mIBgYaDQxTHpjY7lyl8P8Zg2cB1U70pGetqQuwE2aE2yY7PcSFCUlnsMR9GDUkcxO7prmo78isDZEmJJeMBz14TryCUFZWhiuuuAJvvPEGGjaM2PGLi4vx1ltvYcqUKRg2bBh69eqFd955B4sXL8avv/4KAJg1axbWr1+P999/H927d8dZZ52Fxx9/HNOnT0dNjX07MbsQD5EYRjjhuMjpo6HJy+p3IsaEpOaDJbWJo9NQ/cNqNTA0PLDusCUp2hRJIlHtgAADxMkkaNDFrjEZ6LAR94nsdExIks7v6PomGhjBRvh401xaQSAgR2tzXfb8tgkwY8eOxdlnn43hw4erri9fvhy1tbWq6x06dEDLli2xZMkSAMCSJUvQpUsX5OVF0qmPGDECJSUlWLduHbG96upqlJSUqP65BZY0MC4YMAPbNo66ZlkDI2BakSSJ29wSm52r9m9zJlg3fEEBRkuDpIHxsxEmtGNaxnX6Qz0YaGBc8P0ZIRbciT3jSu/MHYn4O1QnVrCY/9F2iOwbGe6PRLKejIOAjz/+GCtWrMBvv/0Wda+wsBDJycnIyclRXc/Ly0NhYWG4jFJ4Cd0P3SPh6aefxmOPPSaAextgYRC4YfokZcW0TlMADah5YzrM0cGeJZndjHaGRpO3eVsSYdcUXa7G74wGJh5gGEbtEpOB/lhxqH2FpkSsBkaiDqMmwSyYThupaBVu2FA6BVl2fySScHly165duP322/HBBx8gNTVVNHld3H///SguLg7/27Vrl2Ntm8GaBkYYG0IQCaPmZ6x7QY4Q8SEhQa2hcOtRAiHQOvGq67C1QTIhkbQITpiQ9CNM3AXDBdIl31/EiVd73RkGVWNXIN2gBsb4DDhDh3eHc0K7xqRIgCyLHQ8yotcutz29cAFm+fLlOHDgAHr27InExEQkJiZi3rx5eOGFF5CYmIi8vDzU1NSgqKhIVW///v1o2rQpAKBp06ZRUUmhv0NltEhJSUFWVpbqn51wal52gxpeqznQXmNBp2ZZ+OLm/sKceNUhle504tXLnaOfByYCZh8YEJx4CeXiQbBwCkZ97BYTkq4Tr0PtKwU5oV2iY0Mi5YEhXaCKChLIr1vGgxOQZfnvp4E57bTT8Mcff2DVqlXhf71798YVV1wR/p2UlIQ5c+aE62zatAk7d+5Ev379AAD9+vXDH3/8gQMHDoTLzJ49G1lZWejUqZNolm1HvDvxkjQHvN9xZkpivVre+kSgDaNmikKy3Do7tJOfrgCjuM4zYUZNOjY8LJ0PTHwgLkxIIQ2MdrV3yoTEuVEwp6uXoI6uDVMnXklsF8VZ/kdLkGWSxi82vOhBuA9MgwYNcNJJJ6muZWRkoFGjRuHro0ePxoQJE5Cbm4usrCzceuut6NevH/r2DaaXP+OMM9CpUydcddVVmDx5MgoLC/HQQw9h7NixSElJEc0yF1jeY7ybkCTCb27NkEUBSE1LUk1gTFFIDvZruK9Uu0q6+AhmPgk+BSQSwzo0wc8bDxDu/P1grIFxkBED6LHolEaANXSZnm60z1ZUGU2LpPnIrA1RcLsGRiR3MmTXa2pjIk9OnToV55xzDkaNGoXBgwejadOm+OKLL8L3fT4fvvvuO/h8PvTr1w9XXnklrr76akyaNCkW7BLB8l6tDAI3fC7KXWh4MrAmv4jxgdHsrphOo461D4xBOeWEzWdCMg99vKBHcya60e3YIHzFCkYaGJc8hN6JzE5xJ7FKDbR0YX6EiqEPjAkvok3wbjepiATJidcNLg1K2BKFpMXcuXNVf6empmL69OmYPn26bp3jjz8eP/zwg82cOQPas5CIcMF4IWtgOGmFNTDWH0yCWqXLJMA4GYVU35TWj4CGXTFOvIRyCDpTr9pVxNbAMQijceNmp03AOSFR2Udm31m7JpnYcqCMii4P/6ypE0R2UZ2fby5PTkyIu+SRMtwvsP2NLHrxCZEL7UNnd8RFPDtvgbuvkso6EWQABCdSZf/4HDjfxwro7fqR3zwamOhdejQNSbL/HJ14CTk14tJtPjBR1x0SxFmmANYlz6y80Tgy40V0GHUdSV1EgRQHEshY2igT8MyPGzFv80GhNEXDE2AcgFuE2OY5aVySA8mkwbs4lVbX1tfnqq7mS9KEUTMQdXJdCmutNH4EVLtHLideLQ0ST5Il7UI8yCZ5WXT+coZOvC57zqiw1hhoYERCgkQ+xNbA50bSKWfUhii0PS6Tq15yojNLrWiBdtyHK9X0XfY9eAKMA7DkAyPS3izxDXDSZMJtQgqFYQv40CTN9oppko3Bl6hNUKfHgdqvh70NmvTfkmQtosItQrkRqDVeBvdicdozCxzjjqEhlqhLSQI5jFoV9aRf3/QwR5P6rEj0Sbjs5ALjNhUNdmmeDQC4qKc1nzMPZDjiA+OBH26YPn1S9GRidVIQkwdGvcCzLMiOamAIPjC0EOHEq9euWxxU7QLt4xn1g1vMYCE+ooQDh/hT9pFo2ZWYyI7ysZx+P6ym1//e3B+Hy6vx2/ajNnIVRDCRnb1tuONriMDTwDgAK3lgxH6gEtcAT1LYbyMaFE4OBD5OgkaLEU95YLQ5bJSQOIWyUF06E5ITPjDiaL12VS/29gUUdIsCRo8Np/izN4zapIw2jFrBTJKJ31usBdDkxAQ0y05z3cJ/rMATYByA3XlgWOjzfEgpSQoBJqyB4fskSf4gvAj6wCiEAqajBJybUsIneCuaTPIlUIYis2pgon0KSBoGbd+xwul1oXlOGnMd2r6LhyikEBvRqd3dp4FhnY+Ip1FL5N9aJFM4xwo1w0P0+dZxBpc9uifA/I3A+yGTJgmr41iEAJEgqTVKbGHU9uLaAa2i21TtHBMM3odaU8MKulwhkv0aGIG9bKccYUQ61jv4EHT9pZzSwNhFV9I7C0lhtjbgJdFMAwN3vEMeFvq1aYQHRnYQz8wxBE+A4QSLWWhfcRV3O6I/PZ4PSa2BscZRWBthiUqIlpofptOobZzT+rVphMtPbhndpuI3bVQCs5ZEoveTiCcfGB5hiNb8Fh+ZePXE0Ni2b52uNQ1MIsVLFmvyclb7+LfW9lDAE2BcDrHqT74PIlnlAyOIFyEmJI0PDIsAY+PEIEMmPp+SvaAJyRysXEoAtLm2SDSCzoiMxE1oktoQBR5aPHl3tHBdFFKMzqZhaofBhiRBoiiu9YEh/z6peVYUn3YIHDzkeOcb5v2LzePBbQKVJ8Bwwjm1pNh2eNhWagvC9TnZilS3/lwSyAdNOgmW03CVYyY5kc6hmtkHRqLPxBtXGhg7TUgGtF2TyE7vumNRSPRlmXxg9DQwDDRCaNM4k3D44N/HZyUeUhuIhifAcMKpE6bF7mL5iKUoBJjQY7vhMMeo06hZZllB/Urq02AfRV/XamBomGAPo5YIu/RoGpIk2b44x3rZoO86IxNSrJ8iCF0nXofYY3FmZsoDo1PeyISkN/fUBZxJ1c8zj/K+J/YNjM3ftDs+hzA8AeZvBi4fmERf+HdokuAeyGEByDokSVItMO7NxFvv90PtxBuZ0HnOQvIHzDUwgLUIG8fzb/AkYKQsZ9THLlHAQN8V2xkGbXvfFHRpW67VOafIbYsuC+KYdUfgCTAuh1AHNE6KShNSaJKwKL8IeTCtBoZlkhW1s9ZX7Uf/VpalduLlWEFpTpCVEF95YLh8YCgrGfrAuGT1C2tgorIsO9u+HdAROxRt6zeuvFfnJ2tgaFinfT5uXxauWhw+MJztuIU+KzwBxoMplInsanUmCVqEJmAxO0dJNYGxLsgTTm8vgIdo6CnQlUJTMq0TL4cGJqp9kg+M5B7zCA14OKXXwNAtkLGErqDsVPuKhswsRKx5YFjPQoLOPd2DFik6SaSgSqLEbUKyxMmxD0+AcTloDj9lccfh+ZCUckFIgOH9IEOsiolCUn/grJOQGDOWOe3Qb2XZoAnJHh8Y7S6d6MQrORCFFOs8MNS7an24JQpJd5w5xJ5thzlK5k68RpHSSrZq6vQ0MOa8075nmqgmkd6RLAL039CH1xNg3A6RzsLaBZ+lXgghE9IJnKeyygJ9YBIk/rOQbIVMnniUi0CST39aVb5yHh+YqKMEdFqKJw0Mz4ihfT6jRcIl8kv4HcYqE69KIBdpGoT5wqt9P3rN62lgaPi1X1DlND1xfP92wi0ayRDcMuXHHZySdmk0MCywOv5q63c51wxohZuGnIBPxvRlqh/KuiniQ5AsmpCEaIEoJqZIGHXkWhKl+oNHyIjygSFpYCA+CmnqJd1M2+UFlw+MANpumbBjrYFRnaRuUpZNIxytMdS2Z2jiU/zW84GhAa321unRwNKeU5GxboJ3GrXLIVoDw1kz/Ku2PgopJdGH+85iT3MtVAOTACQo5ixmE5JNs78MWccOrvCBSTSKQiLXoQXNYY6QLNr9CVVz0pL56dkAEY6ZbjEhhUDKc+IE7GqFxrdH+wr0HPd1o5Ao+GA6R40nIo63A3nSKNgId30NngaGG069SNEytdUBrjdJ0CIswNig/YhJ0jGKJkM7SKUwmmwYRq2sy8gOYUdLPMwR4hdn0pk2osDnAkPv16AHt0UhRV13lo1gm6Y+IAx5YPR8YJSmYcp3oJcHhkbIo/eBodC4UlGigztGn3vhCTAuB8lDnxdBkwtHPUUdbY4RK7xYpqGZ/FjOQgrVtwskc5Gy75IS6U6jZnfipR8z8eQDw6NpaNU4naqc0bBxSxdFfGD4vr8r+0afzWWVFwA4vVNe1H0mExIk02fSvgO9gx4taWAY3rOd5kwrbcmyEz4w9tJnhSfAcMIxa+MxZtYMCLQhSZL6HBVWDYyo4wy0kGU17dCJuUonwySfpNsHqmficOLTLiBEDYwkWYpCouNF3GzHQ+nWYe3oaBs68bpkxrbIxm2n0fUFK0j5jNKSfISSOtDTwCgemFYLppfigU7T6VYfGPoW7dSAuhWeAONyCHXi1V8zzaoJg0gTUoKk1jaw+8BY54GGRlJ9eJTSyTCJMmSKOZU4orVkZCdeFy3OFGBltWOzLKQn0y2khiYkl/jAhLjgVciKfNdmpFo0TKOnBQoTksE7UJar09XAiDQhcc6hnP3PHIXE1Ur8whNgOOHUQBFpQgJiH1UR2iXoTTYs0E5+zFFIljkgQ4Z64gnxpdTAJCTQ7a14Fh46DYw1nyGammJ9AdiosTi/G/WxS+QXy7ArURuJanMTAeaGQa0j9SVzzYGRE6+Sg9Qk/uWM5Ttz1ITEUNaJICS3HYzpCTCccEpZR2qHZYejBL8dVtygDX1kDdOTLNNK0JiQ7M6Z8POdQ6JpUPRq2ITk12pGaHxgKJlT0NQuCHok3OKgaheojxIwuOea06gtvivLGhiG6j1bNjQmpeHFbOE1PkoAeO2qXjjhuAy8dHlPnULG9AGxTryiIEmMPjD2seJaeAKMy2GWZtsJSLC2u1EikolXwvUDWxuWNYWk3mnbvSA3SKUTurS7/5ATrzZKQo9bdSI7ESYkggbGhjwwUW0IJG/nrtdYA+MSAab+vwdKq6nrNM1KDf8WmuRRmRNG8fuhszvitmFtcUH35sbVVb8l4sJrFIWkfSUjOjfFnDuH4qTm2arr53bLJ5Yngc2Jl31M8A4jJh+YoPOdvXDH5xCGJ8C4HRRi9Rmd8qh2EJLEF4UEABnJYlIGqRZniwuodmJjNyFZ/xpp+jORYEKircujVaLJAyNJ4gU+N+XREnW8hksUMGFo0+Ub8d45Pyv8W6Qvj54J6bSOeZhwxonm37XitiSBOMepE9nxcAm8eFmPKB714BZBNQqeBsYQngDjchA1MJpRnZ2ehPWTRlDR403ClJ7CEFlgiMjzWJ0ytD4wzA6vNs1ZWh+YsAaGw++HfWKV0KeVsQo/WMriWUhO58NgJCZDZkhkpw+nFrabhpxgeN8qG048B62goQqDlsz9/KI0MDph1Lrt0YxVFg0MfVEu+txtyXzzOwvcJud5AozLQYpCis6LEMyMawYrYy89SbwGxqo9mWbyEwm9aB5y2cidsBOvX2tCssMHBphw+om4oHu+KQ3R9nx78+qwEWcaFga0nYpCGtyuseF9q1zYFYVkZOrR50VRX+fJVFoeA7I0TSZTSOqxDm7Qg3eYozE8AcblIJ4TYoEeny+BJFADY40XJcpr/JbMFnZNWlpzW8iJt5bShKR0wuUxs6Ul+zBmcGRHT1wkJBsy8dqY5p6Vkgz63ajRGTqOmRbMrC6WnXgtVaczwzCEIit/s/rAqPkybzM5McE0yaXdGyFezQiz/tWdcpht8AQYlyMzJVrzEXU6K220hcQv/PQoMDdL0EAVNWSVlixzJ2/q0DSLfXIgXdP0fadmWXjqwi6qsqRMvHr0zOjT8qjOo0EqJ7nOv8MIkgTcc+aJ1BM0Sxh1Va2+AOOc/GLckFU2xPrAkE04vE0wm5A4NDJplDmBqGAqbApsisUHxgFttNumDE+AcTn6ndBIKD2ej0uGjLtGtMeNQ9rgm3EDLLWv/Mis7m5lmc9x9PqBrXHnGe3FJLLT/P3D7YPQspE6hX2ijgmJBjwmJOV/AfLiGBRm+TuATvjiJk/ELUPbYvMTZ6mcU/XAklY9w0C76JQJyZRXqxoU20xIClMpddi60gdGMs3EK+KoB6bswHaA1weGRYDhbyZu4Z1G7WJc1KO5Tgis8d96sLJgpScn4v6zOnLXD8FK3hYtArLMJcDcNeJEpCb5ONSz9E4wRCfeqPAg8zbZw6gl1X+1vOjx6HaEnifJlyDcrHN8oww8dl5nvL1oG3YcrgAAvHR5D/gkCakOLXzm8ou5r4hT0GuTRROspGVmQjLLA6PljUTPNCsz4/lNrOB9T2xh1JyNMMBtvkKeAMMJR3xHbRgrsR6AKidei7T8Afee/6E6yyWsgdGakMx7QIgGhkIItgMi29BzHNUD66j4V/9W2F9ShZfn/gkAGHlSMyQkSCivrmOkZA/4NKf2QI8uj7IqGEZt7OdnqIGhHGVpgtJAOA2XyQuug2dCcjF0P07troNykFvxgREFWR2GZImWPxDgEiRT6g+g4/UvMbumRVLYiZcuh4fISC2AvABIkmRJk8GbDVoPZqYaSee3HmSZPYxapHaQFbHeWLBAOT5VZ5HROvFqfpt9wtE+MOx9lWaSiFNQ0JpBHfvfbzB1gL3tuG2UegIMJ5yYb3TDX+1v2jZYOWlZi7oAu/7li1v6hz9yIT4wOkSUlxPrvWijonQo6DObkEIaGJN2JMna8zfNTsOH159CxwwF3vxXb1zZt6UBLSVZc7pWtQ8ixwhdeyb3nWFDv30dBq0K23o+MMoHZvFD0uMh3UQDw+IA6+S7YAqjdqcy2lZ4AgwnnLE36l3X7kgo6YX/L4ZQmZCsMROQZebwR+Up0E51RSiMmhZWhLywDwxFPavP37+tOneJpZB2k/o0Pj1KnNYhj8snw6hdO2HqAxPr71YB5bYhoHLKpySgeRjSNsTofUu6f+jDzJfJ7umc3weGHk6cJOA2xKdh8G8COybPWJ8mKlJNX+dnd+JVtcmp3TC7BqgnkkSdg2joDnNklmCiONDzgbH9LCTG8qSkjax0r+p7PLq0yMZ53fJxuLyGkQNCW67RwLhzabJyGjygL7jS54Ghg5kTr6ijJ0TDTYIr4D5+PAHGxaBZHIN/06tgYj0AReYqCMjWXHhjrYGh0pJwyi+mC6JFfyh7xpH+26Rd0Jo0SMHFvQuCdShbDZGLrQrexAfIRQuHsp9USRepw6gVvyXzfjcUYLTaaJ1yplFINoP3/bEe5uimceIEPBOSB0chMpFdXUC2JBCxCwdkTQYJfgVfSXoaGIo2eR1tzXxgnJBmteRbafLjqMvq+EKE7hvQVUKpVXJyMv94TF9L9WkETvJ1501cytek9EtnCSZQUiaf9xaBVrHD88hm2kaWrZBVbdilfQro22JoypnAWHdJSJ4A42JQ5+9gGFOxHn4Cg5AQCPDlgQm3r9Mb/QUkD1SGTDP7wFhI9hdxPjWvZ0kDw1Hn05v6Gd43FGAUz2M0iXJFiNTTI/piUNKzP1FarL9cBWSyDwzP6eY0gplhHhhKembWLbu1b8oxO3pgazTKSKasRw/ZgcMc3QZPgHE19PbOvLtyKeYqRpF5W4JRSGz0aAQoXaGB6ANDLqtMWmfFhETjVnBcg5QITc1/9SBJ9p/zox2nZuPWyCGbWgNDKejQgpaG1b6041048amrHc5pTUjKd2SOKA2M8nfUPbFzJpEWj5AskX+LbMuJnFixXj+08AQYF4M1j4VdELk7EZnjxG9RA2Mn/ArdesiJN2SHb54TyqGiJ9jQ7T5DOD43YpohFicJXnplKUGq26dVLj9BGKvAaRcA7mRqHPd4yunBTHvBQ9+JRHZKbSHvwm5uQqLXwOgh1hqYqPaoS7pMYnAZPAHGxRA9dIOOm7H9IETOE/6ATB25QgJrTxCjkHTKtmqUgVaN0tGleXZ48vzspn4466SmmHHdybr0AK0JyZwvtdZBn1cV35L4kZCdnoTJ/+iqaEPbpgE/YAijNjIhMYZbi4LVtnTcpCL0da47cYBfdJuR3wGODYlKGIXOWUiKMiIS2TmZKNB8D0HPC5MG5m94GJIXheRi0O/+7PkgrNTRhUAfGH9Ahi+B0YQE8x2jiOdN9CVgzp1D6zUdQYKd87PxypW9Iu1Q0KFSyxMFK+MFX6KlrdskuW5WKv+UQqsCN1rsLb074qGCdLAqDjp1aCQvlP2qlweGFj4KR2vV+GXZZnN2o2sT2TGUdaky2lZ4GhhOxKPHNy81oSYkwT4wzO1bSKRH3FkZkPAlSJZzrZjtzAG1loYpg6zNM7GWvFlzhuNMs2vXA0kbZQW0mwOa92QEXhOSEX9OaGd4mtAKMMxHCSh/074fTbkzOuVR1RMGbh8Y+sJ6J7C7zW9FJDwBxsWwwwcm1mPZigChhWUfmBh3Bl2kEFsZWiHLah4YI264aknGCy6XDwyjBtMko70xDYu9aSboxtr0q4TeWUi0SFQKMCCHUSsf1/gwRzoox8wdw9vjH71aqO4zPYVFicC++Zr8FCIdxN0mDHkCDCeceI/ifWCkmI/AgEWnPyWCPjCsJqQIxPSEFTMMRRkaCxJh0Tb1gYG1wxxpzG/RPjDG7VEqYAzpiM4uTNtFVpu1w4lXpN+HngBV6w8QrxtBay5L9kUvQ0Y+MBrGjP5U0FDT1vaNk2HUwfboGmT1gSFuYOhJxB08AYYTjpiQdEYvi3NkVF0L/IiASAHCz5GJVx01wWhCIpQXHcmjBY2QoXWKDF4z18o4LctaMSGZPQ/pHq3WwklTkx5YTuOONZSvqaqWXYBJVEkTwLRLu0eVUQusmns2CHNsieyswS6fxXh0a7AKT4D5G8EN6j+ROx2/1Uy8etdj3FHKR6IRYFR+H0z2dRauNHUprrNOdiLywIh+dyIOhKSBqQnJoIFJ53dWhObbD+Vrqqr1M9f3aQ5U7dA0C7/cNVS/vGEYNfv7kWBNCHEyEILZT0/wJsvt8AQYF4PeB8Yeid5uiDAhWXKB0TOD6JVnKEvVPkVtXtMEzYLv9G7K2BIgUb9LI6GOR5gLlbMiDFv1M+DJYhvC1f1aYdF9w9Agxb6gUr0opOo6axqYsNN5VHuRK9F9q/+Oace6tpz9JiTyb6aKJtAbv27TmoiEJ8C4GLpZJTknO8mAphHs+ratfliJCRIzc24KNaTzb2HUwFDStmpC0jdvara6LDA0IdGRjVU0stVmrUYxCWGCA3waGHNzILXGjbLNaB8Y9X2WecHqvEUTeRVpix66NAWOCzdtgAFPgHE1WHeQfze8fnVvWzQwLOXt7nuaBZnkOGueB0YiCiEn5jVg5lFN1+gevx8CbYI6njDq8FlIFgaT3RoYGqdpx2DRhKQ8WiM8Xk3MgrRRaPo0jO/broFx4EV5TrweXAXRA493123XB2D1m+51fEPmKKSURKX9XU+LQE/Pym5Mrx3lQk4TVaNWT0uGtPXqhXDjkDYY0VlMjgyWnpEk9cnGpPuR3wY+EZTlRMNqU+ZOvO5Zhqw68VJpYDQ3eM5Z0rseFIjEf7fU9ZlM/tbfu8jPwD2jMAhPgHExaH00mBYKDj7cZHbRgkV+ufyUlujULCv8N7MGhqTJcIEGhuT3YVZNksiLguXJ2VgFYwhajybDJjgeQMQ7tN+J1xp9kVD6WlTVcWhgCD4wWmi/NU3gkqI+XZtGB0KKhpkjrV3vUpZlspbYdWKHOHgCDCdGD2xtexvid5CxP41aCRHPR7vojerZAk9d2CXmEUZKUCWpYwyjVhA3vK+njZPq/ycCrH1tlFiZdgGIlQ+M7SYkDpp2ZeJVkuXLxKuOQgr+V/2E0c65dIKOLkzfj5u3aXTQewKhGhgXzZ+AJ8Bw47xu+ba3QatePYYFbFNYmaP1J0UGGvzNC8wDQ+cfoqqjM/XbqYGx4oeg5JY2CokWoRpO+lNpYWpCOoa+cW0eGBrodQ9tFFKUBkZT0M9wLAnPq9DWoZ23mNqS9fzdjl0IF2Cefvpp9OnTBw0aNECTJk1wwQUXYNOmTaoyVVVVGDt2LBo1aoTMzEyMGjUK+/fvV5XZuXMnzj77bKSnp6NJkya4++67UVdXJ5pdS2ialWpvA4JHXnDX7Z7hLIIT7UQwemBr5GfTvRfW9vW6Li8rhZGSMT0lqJx4CX/ROL2SNTN0WjpeHxvjstazk8ZqeFvVwIhM9243rOoqfJqjBGjAm+uI1I4kRY9NK6faa0Gj+bJDO6avgXHe9O0UhAsw8+bNw9ixY/Hrr79i9uzZqK2txRlnnIHy8vJwmTvuuAPffvstPvvsM8ybNw979+7FRRddFL7v9/tx9tlno6amBosXL8aMGTPw7rvvYuLEiaLZtQSec0BYQJ9JND5Ho4iPSDsRPHxOJyy6bxhVW3rtj+zSDADQtkmmafuSJOHda0/Gya1y8emN/cwZpoCIRHZm1fSEWd5XElqTjMaiqRKfOoxasAZGMm/flAZ/VQA0GhgKTZzmb7tmJ6vTXiLhWc00KXrvldsHRvN3gEUDwyNAxdQHhu4aDdy20ggXYGbOnIlrrrkGnTt3Rrdu3fDuu+9i586dWL58OQCguLgYb731FqZMmYJhw4ahV69eeOedd7B48WL8+uuvAIBZs2Zh/fr1eP/999G9e3ecddZZePzxxzF9+nTU1NSIZpkbIqV2EkQPdLcNPhEgHsBnMWKhdeMM/P7QcPx4+yAqOh2bZeHTm/rh5Na5VOXN2leVYdSGSJr/6retM7ExmKCUSAz5NRhM1GbvxWgRV96h1cA4cRpzpF2rGhgT+hTXzZ6WJDjQQvl8Sr+z16/qhcaZyXh/9CnUtLSnUdO1r/jNISSb1T+n3iXAahqBYFvGIoPjRwkQaMSTxs8ItvvAFBcXAwByc4OT+/Lly1FbW4vhw4eHy3To0AEtW7bEkiVLAABLlixBly5dkJcXCeccMWIESkpKsG7dOmI71dXVKCkpUf2zH3ZrYHSuU9p9aeo6jX5tGoV/87CSluRT/W3XGtU4MwVJhEPmREKcDwzpmtmOnlwmgdOEZDkRmwQ8dHYng/boFgC+idn6R2Hdd4hTgjGA9tsQfdAlAJzRuSl+e3A4BrZrTF1HlQdGp0x0FJL67xsGtUZGsg+3DG1L1aa2f7X0J57TCVMv6Yb/XH8yMy23g3aj8vGYvua0XPbots7QgUAA48ePx4ABA3DSSScBAAoLC5GcnIycnBxV2by8PBQWFobLKIWX0P3QPRKefvppZGdnh/8VFBQIfppouE0DM3lUV8McHpIkLsKEFy9d3iP8m3UiaNskE+nJagFm7LDgBHZ+d3anahbfEL3rVj5omqpUAgzB30W1M9cZp6T1TJknhwWhKBojTYnZk7RslI7PbiKb4SSd31qoM646N9bt3tGK+G6taGCU0I4n1n5WRSFRfmvaTLoPnt0Jax4dgYLcdKo2tSYcLf20ZB8u7NECjTL4/NmY2gdLJl76vtX7zsmmYvW1Fg3TqPvSTbBVgBk7dizWrl2Ljz/+2M5mAAD3338/iouLw/927dple5t2+8DQIjQUL+5TgNeu6m1cNobyy2kdmqBRZmSC4OFF2+NXntISc+4cgikXd2emFevNhN7zq31g2OjQJ7Ija1qSOQUYUbt7Gq2jUVMqUwfl9ynim7A7fJvHaVr79FbOW1Likj7BzSGryTSERAonXu1VkoBIMjnShlvTmOTiDXopJUwsWkaXCLTc1UO2nf41btw4fPfdd5g/fz5atGgRvt60aVPU1NSgqKhIpYXZv38/mjZtGi6zbNkyFb1QlFKojBYpKSlISbFHetaD3fKL3m6AdzcW66Fnh9OuJEk44ThzZ1sR/MQikR1dHhg+nwLS8yT7ErjGV2gxUfFikttDdY9a8OI3ISUnJqDG4PBBK0eD2q3Z5KGu/VZ8PjE8dmyWhRUPn47stCSu+iQfGLP3blVApo3cFhWBF1XHYn0ayLKOltiEn1DdeIRwDYwsyxg3bhy+/PJL/Pzzz2jdurXqfq9evZCUlIQ5c+aEr23atAk7d+5Ev35B9XG/fv3wxx9/4MCBA+Eys2fPRlZWFjp10reTOw27NDC3DWuLC7rn44q+LanKMzmFRdVlYMwy6HZBRhDb47Heh5HbUT4jXSbeaIpmC6oE8rtP0fgYGdVXIrSrtt5zOjtolWDEWjuISed1Zq5DC4kwk6YmJeBKym9Yi9ev6mWRo2iI0sAAQG5GsmnklB4SKZx4tXOa1oSkBxoNnlFBJzQM1NGlBFOXEVjCqO3Iwh0LCNfAjB07Fh9++CG+/vprNGjQIOyzkp2djbS0NGRnZ2P06NGYMGECcnNzkZWVhVtvvRX9+vVD375BJ6IzzjgDnTp1wlVXXYXJkyejsLAQDz30EMaOHeu4lsUIdkmtF/RojjacWgUzkPwSzB5DVDSHGA0MZ9uka6waGOLuhv+hhDnxqmhKURdZbOPJvgSuFZ1mQhQXdaVfyKi+WV+KDqPu0yoXl/Zpifd/3clEq/8JjdAsO01Nn3pl1gevwAGIFenVfERr7kjticyzo6d9pAVPXUdMLwyJ7OJRWCFBuAbmlVdeQXFxMYYOHYpmzZqF/33yySfhMlOnTsU555yDUaNGYfDgwWjatCm++OKL8H2fz4fvvvsOPp8P/fr1w5VXXomrr74akyZNEs2uJdgVpmn2sfJGIfFEq9DgFEpbeFRLHG2L7PNYf8M0+h/WTLyRa5HfJNNI0KE7GrQ+MNomwxoYi51KU523DdrdPg/c6MSr/VREOfFaRSKXE69SAydAzxfDrpAMdo03DTlBXVZUe9prpHIxnxHZIVwDQ7PApKamYvr06Zg+fbpumeOPPx4//PCDSNaEw64oJFMBxgJtWmc2Frzxr97o+ugsDl7YIVJm1HX4Y2DMjolQ+Yg8zpt617T3iSYkG514rWpXwmVoGOKkzQsS6Vj6FXQvyIkSXO0Io+aBjyKMWgvqV0chpMZioaZt8b6zOuDVeX9ytSGDnMiO1LqXB8aDbT4w7M6ltOWiI09EDOSsVH1nPlrbNQ1ozF12QvQnr7egKkPF6QQDkgYmco00TCWJ/O5TEhO4ohHCTrwGtWk+F5q2jcasURt6XSlCq0fiyYpTsBaswt8XN/d3sQZGbc4Bot97tA+MciJhb9PoNOrWjTPYCTLCIvthnNO1me4mQ99UTLpIWc7lsC0K6e8AuxZT00VL5EizedAmSFJY0GOJSiFBhjMmJBa2rGnD1GiWnYoeLXNwRqdILh/WMGoWvkhlUhLpnHi1COeBUQms6haMFvRQUd7EfZE29KFHW4Qm1fZoNMbypDnEigZG5PPx+OJYlb2U1YPOsZEr3946kI2W1b6wMMEkJyYgMyUR1XXRGelZhnEcyipEeAKMBdjnA8NW3pIPDFtTzEhQGHx5nDpFgez/w0pDLL9actcPaoPRA1urrtGdhcTRNiTiy09OTOB6TrPFUZLMTpuOlDODoQCjaETrz6NXT4QmlTSWhU4POsyfeuJxivbUDcaDBoZWeFT7wOhD7552fCq7kzU6i8Y8G31NXN/7dQaWLMvU5uSozYVOXbfDMyFZwHUDWpsX4oDpomVhZozy9mdUTbM3qN8WD1kH1gRGGhZ2taKickiRB5pLc+4cgn/1O151nzTOeBPZkcKotdRF2d2N+lw5PhqkJmFkl0jeKL32/fWrqJUNie2J7AjXVjx8Olo0pM+e6rN83oMYKDUwtIcopqfQaQaz08nmbEOhx+GVW4JkKROv368jwOjROEbMRSS4Y0THKe4ecSI+GdMXeVmR0O4mDVLQsVmWJbqmg8vSoqn9W59Wkk/Cya1y0aV5tindPq0aEq+rc5RohCdTqtEQ6sRLkXNEXT6CTs2ykJggYfI/ugrkJxqsJhWSKSYgAyccl4mhHZqYtker3mcVTiQE07VfN6A1Lj9FPzcKr9NyCNrxcXW/VqY8CtHAkHxghDqcR1/LzUg25EFrsrP5aC9qKKOQ6igFmAYpdEnzXr+qNzo1y8I71/RRXTcL02YBz/QrTGCQjTQw5HFITHFAIhCHQo1LhnR8ItGXgFPaNFLtWpc+cBr+0auFQS1zsO9U+Uee0Xo15eLu+PSmflSL2n9Gn0IU3Jo0SI38YVEDEzRG8a0K2rwaJH5YMHpga2x8/Ez0acWXTp0W/Ic5Rn6H+ixKeKUQ1AD1AZx6CB/Qp6NxC7U18dxOeOrCLrp0RGmlIvQi0BvGfgFOMCTaIp14eaBd59yigUlSRCHR9n2D1Ii3g5EGrmOzLPxw+yCcqhXWBWh/RSFoTuUbGzLYxyuNCSle4Y4RfQxBL78GC2wNo9ZUFqXWT03yoUvziADzn9En4+RWuXjlyp5C2+L57i/tU4Abh7SJus4sJmoqJFrc0tJMqnROvEr/gOBvpV0/pKaPSuZF2QEnNm1AaFTLZ8iExPeOQ89Aw5PxODJyFDY2IVmB7RoYAdtjQScJWIZyQ1TrDx7tYNZVWZzHFoSgHvsSrMyiVt8FS23SkDXSGNIKK8RycaiC8Zx4BSAxgc5ZkBZ2OfEChIErcMwqv6tB7Y7DoHbHoarWH74mwk+AdU1IkIBnRpHNPLQaCKfAu1MyMwWF1metRsTK+9BOdsSD9RRlzJo6Ma9BPV80bevD6KRkvecNLQhuPg5GhL+Ydp4yw+WntMSHS9myCNNA+U7qdPw5tFBpYHjajOKBg4hLYJfAHY/wNDACINq732xwWfKpZbAFh3ZHtDD7rLQ7Z1aJX6ZphAHx8AnTnYVEEB5UPjAEDYzi/0MY3P64+rrMbIY1Pokc2/ypl3QLO1/SmZD0yxjN7crn//KW/uHfjMOcGjLELZRcZDR9wWpBykyJCA12JeWrC9B1fgODXFM0UAnvBvdYafHxQu/ES4LRGKd12NVeEzlWnYSngREArSnBugmJrbw1k5J+bVYBhkyf/Dt4gZ1eLP0K7N610DrgRdcj/w4htPgYTdwzxw8Ka0FoEGWKrP8E9A7qM3oM5anrVsOojcoqF/A0RbLAkFOkm0/k5dPAqB+IVQOjfJciuubsLs3Q8/iGqmu1lBqYLJUPDHvbIp14nYSWT2Hn0gmhEnt4AowAJGl2nVYXOjvTPEf7wOiXpZ1cDNtTfCrRGhhWWvZHdhhdtxtkHxhzZpRlSNrAsMpZI1Ao66Um+iJ+KJT8KhFaHJN0/IJotW1UPj8GtIyT5ZHr0YbyMsOBYy8Mm49y4mWjodyYiVg4p1/RM+oarQYmI8XaUqV88qD/l1Ib6ewHb6U1nrdAe/J0PAo1nglJALSLhnUfGBMTkvZvhgZZ6taxmpBMvi7WhFHENgSWt/skaRFgbYeUUM5PNCGJnbZD7SoFGBV96sbYNE5aRPnAKH7rfVehUF5e7Z6e5oo2d4kW3Ceum3QdjQBzy9DIYYJOJL4LbZLMBCSVZo+jHaubJ1Vdix8/mwaRrS2zg13D1zQ94GbtoxE8AUYARJuQnNQAGPvAiHAWI/8O/h1bmV9XAxOjvQipVZrDFZXPQVp0QotD9C6UTIMHoXb1fGCMyLPyYbSuGh8lQL5uVQPz1jW9VX9fO6AVTmqehcfPP4mq/ty7hlpqPwTtIqR9KhoBRjWWHAhbot0kWeVFpA9MLMEjaJAejzQUYj0f88ATYARAa0KyClMNjJXdhLaukQmJUr0bAmkHq140re+CnDgLyU2QJAmTzu9sWEY5XkhjJxKFpO1/HWGDI/Ip1G6Sws+Cy1eBpowBYe34UC9c5Hp6icFoEcqGe/eIE3FJ7wJMPKcTvrt1EApy6bLktqI4TJDLB0bzXCEnbcN2FH2kfJd27dBpN0lWc9hEaWAsfPyWN6iQHNV4mB32Gs/wfGAEIMo5zrIPjKXqupBl0sen31htHeNXRjz1WLm4au+xkddpgh9u+4Z1OkQZQkqspvhN0sBEopDUdWgWd1qElJC6GhgD8qpwa86w8RAGtG2se8/ORHYAMPbUtkLokCAiwd/lJ7dEVmoiGqYn4+q3l5nSU75LVvPa+6NPwUe/7cTsdftRY6BlCeeBMSGflMA2RrTQphBgCfGPJdyijXcrPA2MADitgdGCNyoj2JZ+WRFRSErwnEKrhTNHCYhrgwV6zWaZhJAq/V58hLFIygMDSf85aR6/WXaq6m+fiQmJFrwamJNb5WL1I2egcWaKtnT4l96Bk4HwWUi0XDoPmjHZrUUOgMh8RDIhnd+9OZo3JGSlJkDtxEtVJYyB7Rpj+uU90TDDeOzSHiUgYu5QwtZv3Iy2hbZ5hugVhKM7tHvuWGeN5oWngRGAqER2Fuk5KnULNSER6Ov8NmtbFAxPQLaiRnbwHfVo2dDwvpkGJuwDE+XEq9zVGtBX3JtycTes3lWES09WT4ohFb/S7KBcm2g1PLxh1Ik+Cdkm2Vr1SFs1ITkBLe/tmmRGlXn+4m54de6fuPTkAu52lH2R5IATL60PjK5zOCW0WaiVYHeU5WCAs76Vpp6+qAva5zVA94IcPPH9Bg3deNS3RMPTwAiASGe3Cae3N09kF/U3ffvRByrq16XNkmnYnkZ1S9N285w0DGqnbwoQBbd9wnqvPTcjGcseOM2gnrEPTMhEEuW3Qvn1K9f30zrm4bHzTwovKBf1bA4AuHFw8KgG5beg1ODRCkhUphIapgm0lRoY5TOFNTAMdGON167qFXWtcWYKHjqnE9o2CUZF6cllRv2nNKepNDBcXJq/T3ofGIuaPZd97LwaDxYfwLQkH3od31DHYdf42suEkHc3whNgBECb+8LKxzLQxoVbhmyrCcns46KdhGRZxnvXnYx1j41gaj/ewDJOmmSl6t4zi0IKkDQwksHiQilsAMDz/+yGtY+NwEn1J5YrvwUe3xK6KKToQjT+J7o+MCbjdsLp7THQwLfGCSgf+fELTkKb46I1MFrwLJHKd6Y0jYt0nleCNg+MapPIMb9qs1AbRSWZwbKG3WJ95vZITryav1s1UjuSt1Vo+HLSrWVBthOeCUkAovLAWBiiPEnsaKuQ5iAjbU96MtvwIJqQOJx45fp6VpNXmcFtnvi8zqTKpyAJiYQ8dlGTOC8kSVKlnFd+C0oNHm1TrCakf/RqgQdHdkTDjGRyWQ2vWjqyDAw4wVg4ue20dgCAVvd9b86cTaioiZwpJiKfkh6UY1A5lnjFFzNNA62WlzWLsBZWtNaiwZS3yyY2Qzx8NXYA3lm0Dfee2UHXsdlds6QangAjAFZPJVaCzolRHH0jWjcPOUH/JgdohTOj01ZFItbyi3YiK6uu46QT+U0KN434wKjb5tHKm1VRLnq0DppGQoZpeUBXeNFCOf5kGVj6wGnYfqgCJ7fOpaofSxRV1IZ/U783ne/I+CwphQnJotBAA1otr3Jc8QgfknrwW8qBFMuNj6iZMfQE3Qty8H+X9gAAFCvGmJHp303wTEgCEH2UgFj62l21yAyyerw2zkwJH7BHCzO5I3oHTG5c13YvAed2ywcA9G1jfdHR60UqLYCAfYlWLV9WxSfA0B4lEM2z2qQUuWplfCkFmADxuhbKXqAT4Fl2sPoawCYNUlXCi5t9eY+U14R/028E2NtRamBUzdh2mCMdYauRnrTzHg8t5voW6p7RKc9a40ZMsFuUYw5PgBEA0VFIWmhDVmkTZFmBHWnEaUnqzWmyDDxzURdMvaQbXruqN7kQA9y2sSjn1cAofhuakDR2f65EcwyVaM0Dyl0/qwmJ5RnsPGPMbhytUAgwVh1aDe6p3oXiul2yHY8GhgdRPjAxXpbpheUInx9efwrOq9/AUdU0eETzb0G5uXHvd+MJMALAooH57KZ+zPS1AsyFPZqrQkapfWAQ/eHqDWSeCcPsm6Q9j8TIYTAjJREX9mhhGjJLBzIHTk1u0SYkv05Jejqk90bqz6ATL5mGqN2qSgNjUE7JHl0UEoMGRvnbtJp7VTCjerYI/6b9NHkiXZRCZ6YigaJdTry0fl+qMGrBpk/mMGr25jXt8Y20/m0bQ5IkIXnHiAoYHbIORNNzwxNgBEAbRm00wXZtkc1Mv1+bRqq/ExKCkRFc0C5OOsV4QsPNJjkWJ14n4LaNRVl1rXkhAtQ+MAQTEkmAgUStkeAV6OrUiWB0waqBUWcUpuctXjUw/5swGP1PiMwBtM/RVidSyai6cqz0a9MI/+zVAg+M7CD8m3zp8h5okJqIGdedDIDiIFiBYdSSBLR0QIutywttTiRIxHf1zbiB4fQF3DyYsGDFR8hJeE68AsDj7OaDH37QnVY7dlhbVNcF8Nr8v8LX1KGz6vZP75SH2ev3E2lpx6JIDYwZaHc6Ipx4Lz+lJT5cujMcQULkx3IrYlHOq4FRPAnRhETS0kvRJiU9KH3UWfqMNgqJ3QeGngdVHhilE28MtC0SApA59owtczNQVBkxIdE+/yPndkZaciL+2buFeeF6qLRhkoRn/9kNAPD+rzuNK1aVAMkZQALdnHZO13yMPKlZ0BxWWQTIxhpV1RlbRgX9dYAvelmLvHsZkGWkJfuwauLppgEYPvghQ0JA+d50XkAi6lDnwJLasVkWplzcHV+s2ENdJxtlKEdqmD+SEKXXr24W/D0NjABEqfQkoAEq0FPajC75WZpbEoYmrMTalNG4IGFhFC3SWElJ9OH+kR1129d+gy9c2gPvXNuHivcEkBfNKB+Ykn3AOyOBtf+NXPPXAuu/AcoPAeAxIZE/DOXpwM1wGM1xMFheArXx+PHzT8LM2/rhjooXgdWfEMvoCVSpRzYAcx4PTso6aLv1bWDVh+aMVB4FXhsMLHrBtOg1/VsFfwT8wFe3AMveIJbrLm3FD8n3o1/COgBA85KVaIxiAEAi4X0GCFFIgH7/Rwm5nMJsnZ/SiVem09SQaLH5wAT/m4pq+kqCkIcjWJ5yEx5I/IC6Tg5KkYFKoLoEviN/hq/Tbi4aZiTj6Yu6oKcmk7ORBoArlL94D/BMAfDu2cDil4Af71V9p22kvXgu6VXg0FZVtYQECSj8A/j38Wg0a6xhE6QjMqKwfx3w7+OBuf8GincD5Ycj9+qrP5T4Pkb9fCpQWoic1ERkVugLAQkI4Ifk+/Ft8oOQUD+Wty3AeQvOQ9+E9QCABvUpBG70fYsNKdeih7RFTUTHfKtEK2kfLkqYH2lDNLYvxOrUMfgp+V4koY7IQxSPOr/dBk+AsYJtC4DVn+Cy+kPSLlbsdP6T/BS+SHkUX51RjicuOElV7d3kZ5Em1WBa8suq6wMT/kCb7y4BDm4Gdi4FZj8SXEg1yN35E07/7QY0RfAD1YbOpiX7cOqJTaLqybKsmvyv9M3Gt2WXobe0MapsVDjurAeBHYuAz6+LXFvyEvDpVcAbp0bVBxDcWb1+Kkb7gvkzqE1IoW++rhpLUm/FotTbkYQ63Fz5BvBiT2DP8uAkWVpIJoDgJN9h/4+QVr4HfDlGtxwJbT4/A1jwHDD3aeL9ttJunLTuOeCrm82JLZwG7FsNzH7YsNjM8YMwPBRhsO5LYNUHwA93Ect+kPwkOiXswEfJT+IS3y/4x5obMCvlbtyd+DGGf9EN2PmrqnxYgNFEHUX1f1VxuPOb4yAu981BCmpUwiyNwHBBwkK8kfQ8pNoy88IAmm79HFj9MQC63Z6henvzLODtM4H5zwLf3g4pUKcoK+HshF+xMfVaNNwQLUiYycbJqEV3aatqoTk74Vfg5f7Bb9YAYxK/R65UhjGJ+rlkJARwjW8mTqjZCKmuEqtSb8SalOuR9HJvNHqnP06UgloQVR8d/hP436PqxdoCVObGiiNBIb2m3FhjFdrU7FwSnCeWvgp8PwGY2gUt5T14P/kp/MM3H3jv/Oi6S6YDADI2fxl9r2hXcA4s3kM3Bn95CqgpA+Y+BUztDDzbJnwrQZKQjTJcn/gjUmuOAFv/B8x6CPi/rsBKslDZWtqHExN2o3PCDjRE/ViecQ6yy7fj4+QnVGXvT/oISZIfTyW9pX62yW2AA+o0/gBUu725KXdiSvKruIiwoT0u6mwvMhqiJLghrq2MvrkxOOZOSNiHQQlrMNb3Fa6rfBeYcS5QFxHmJUnCsIQVWJwyDml7lqiuuxWeCckKZpwDAGg0tjtW3NYBie+dCyy+AQmJ56B7QtDc49v4LdJbRgQYo7HwfvLTQCGA6RrtSc+rgIatwn92mHcLAOCWxGxMrLuWPrGVHFBJ008kvQMAeCn5RfStnq4qek7XZuq69VoWFTZ8F/xvUb16WTvHLXkJ2LsCDyetwFv+s4M7rm0LgI3fAcMf1ZXswyak/evC1zJRgQtrvgWOAHhjWPBi4Vrg2u+BmnIgUAekavyLyjRmNFlWvQDTXjuwHsDAqMvHScW6NKNQVRx9bf03QON2SMuI5Nk5PleRCfOQYhfnrwPqqoCUiD9DhhSZdC7x/QIAyJXKMDbxm+A7WPEfoGXfcBnSplpCkO0TpD1Igh9JhzcA/zkV6HIxgHGYmXIfGkiVyJcOoSahs/7zERASzJP3fgxgaLA9nS7KRQk6/f4A8DuAzhdBCviRhipUQj/zcEptGSYkfoqv/QMAaM79+fCfwf/uDE7ADdNOBHA8gKAAPT05qAnLX3A/cNot+g9xdDtQWxVc5NqPAE6+AdOSpmOkbxmeqb0Ur/rPA1BP7wCCQvKYubrkainMxSMTluHRpPeAQ+9hc9nPAACfJAPlQQ3kgIR12ORvqd4IvH4qUF0MHNgIXP6xaRuA8XBVaj/xwT+BPb8D2xdBlkcZVCJEz/3+NgDgDukd5EtHgtdKdkeXS9R/z/jPhcDhLcCOxUi89LvwZV1BM6WBLikJQMcEhRksNQf4tX7O+7p+HHS/XNU5c1LuDv8+17cEs/3q4xsmJb6DX9ELP6Br+FoAijPGfnog+N//Xg+c90OElyN/4ofEO/GyfC6+CAwOX++VEC0EF+Sm4/l/dsNxSQTBRIG3kp9Dz4StwP8CAAarb+5bHf75dvJzwR/VALYBWP810PXi6Ptf/QMAhYY5xvA0MDyoLALeOTvyd/lBJM6fDBTtAGY9hOaFcyL3svKtO0GV7Av/VO7+/PWvj0a9emHCAnT5oBsaH1oGIKjtCSEVEfv6lIu74bWremHM4DYaCoRZQ2nv/vw6nHV4hvp+TbnqT0lCUOhb+irwZFPk7ZkVvueDH0MSVqMBKiItKQQYH6n9HQuDppmn8oFnWkbvPmSFSnbrHGBya2DDt8G/i3ZCkiMTb7+EdbjF95VajasViAAMS1iBm33fRC4ECCa4QCCoQautAvw16nvbFwW1Vi/3RW5GMh46uyMeO68z0pIVfVl+IPL7lX7A082DY46ABiBMbOnqHDlKE1Ii6tBZ2g4JMiTImJNyd1BYWfhUsPAfn0KSgAZSkO7AhD+4Q+qT6iIaGD0KOZJCSxOoQ9bH52FD6nVoCH3z3cnbX8FtiV/VLzDGvKWU7or8PkzYCSsQWhhTUAP8Xzfg5VOArbPDmrCRvuC3c1/Sx9H8kQT8g5vQ+svzcGrCStQq9oqDE1ZjTvKd6CVtCmpVts0HSvaGTYIAEPBF77xLETxFWqWBqa4XkHfVa93+mge8dDKwYwmI2LcGzd7pTTRfAxoT0p7fg/9d+zlkGTheKsSLSS8ETZsVR4C9K+uZ1ffdSiCZRcoPA0fq/fmSDJxpD9cL8ruXqfz8VFqiqmKgLCjgIY2QG8of/MYTJEltOtQKXV/fEpkbAGjnu8eSZmBx6m2qa1cnzsbL0jOqawFIQW3V/vWRiwfVGu6kHyagrbQHU5JfjaobhUAAo468jsFf9AY2/hB9vx49E+rNc0tfxeOJb4dNRQCC5jQ91JSF5xZdHxgE8FTim7jGN1OfTozgCTA8WPxCcPEMITFNtVj2W3Fn5F5VcVQOAmYoNAktpIPh3zvloJmIRgMzNfkVJNaUot/vtwOo1/bUIwXB6JeTmmfh3G75GNG5adT5TsRtT4JCgbf2vzjnyLsAEPTHmPcsULpPXVzDZ89fbwvbjEf7fsCM5H/j7eTJaCbvD05MChNRIgi7PEBtminaqb6n5Pn9i4L+KJ9cCfw1F5jWBa1mj0Foovoo+Unck/Qpzkz4LVInRe2/hNoqvJ38HAb/f3tnHh5Fkffxb/dcSQg5SEjCkXCIXHITiAE8iRwieK2rCIh4oqDiCd7vrougrr4Csp4rXigLKqio8LIBUQQChFsUEBEQCFcICSSZzFHvHzU900d1T/dkkjBYn+fJk5nu6u7qmu6qX/2usoWEP+bsc80s4N1BwJf3KVS0AIDDmxVf77ioLcZKvi8Sp2UCzPHArGxmD/wedzNG2goVRV1QCUgA4K5QfPX7CVBdDgEELzvewNeuJ+Aomg2xJiQ82Mv2as8ToO3JHzBcXA3AWtRPVhNGxB0hwNInMc72LQDAKf9da87AcYi2/0DbJt3zNjnzK3vHr4WaTYI3JOC1mFdgotYI+hMZ8Yh9gXKDt1pb6LPbkXBsM+Y4X4KHhN6VD5wv4DzxMD5z/Q1LXVOoKv+VThhtD9VfYAgF2QJ9LthmtsC2D0YAx3dSfxQWn94Ge8VBhfn6QnEHbrB9B4Cg/6nF6CWoNAGB9+hW21IMt62lAt2M7sBblwIH1rHfgQAelpJ/dh9gZk9qInKENDDS5GHqtUqTO0RHMCoyEZXweWVtMz0H+Gc76q+WwBJg6PshCKF+DgC7zr99F/yoKBuGpigLfibS7/C6LF2G7FpJOANx3w/M8/hUw3EH91bq0/PjDLpB0uiEYYz9vxgirpOdmNFHSBQ+R6+x+7+6RfqRjbjZvpxqB88yuAkpElQDBGx2wK5jq6wq1bUheolJ+bE85GjWSQgN0tJZg5OTVa9S88yYhbrqVIFoZ0TSy7r4vov068AUYFhqcYLZzhnACq1fDWsiv9D1LNpXv49rbT8CAPqIu1CI+4EPPwDahVZgtgsmInQEG+A+DVSeAFJbKTUwcoreAgAkHSjEl87fcISEOr4cQSY8uBrjCnEDDpMmuETcCsx4SHsuvwdQmzuWPUP/b5sPdBqh3LfFQM3vPk0FN5bZqeokAGCa3MYOwCkwOmJ3OXBiDwrEYnQT9yDHXQ1MX4Jm7a9HRxsVRJxrZ8LWdnjwELGqNPhZLqS0Fw6ix/YHcZUT2OQOv2CinDaZKQhmH5LegT/WA2tew7MOYI5vKJzygeKN/qH6GDg0VrpC/l3BV+u3lVRIVZH+0xxMte/HVO8o9sl+nEF/ryEvAOgHAHAJ4QevpkKZcoNaUAUUfinMgdwIon3e77cvwjzv5bD7q+ngnyIzn6n7GOILaAJXA0umAFc8ByS1UPQlEpI/x1P2j5B8ohJjXcAuvzZMV9LKAaDPGADs/j9D5yHmfVcG2mXXEsARH9w887p2sMWn4MquKvO1IwE2UcAI8UfMdM4GdgH49TPgPNkK7Sd2s81RK6cDf2yALf8NpVDC6huqy4IfG4EhkOrQVQxFhxK5CYnBRPsi3X1SpNNNfbIxb/0BTCl/PtTOgbNbIfjOGQkw0nu/ZAqEu9cyi+SQQ6Evc4YBN82lk9PNc4H+DwKN0pjH1QdcgIkE9ezI79O35VadVOatkHU0VQgJPcyZtMTGD4E86jDaUQipxG2BiBNn6W7Akwj891m6Y8McoP/9mtNQtC+BKKi2nfqDqmOdMvUu6yUQtAKMAz7kiVrhBQBySlcztzvhwXGi0nYc3AC0CdlyTc2I/F5qb971LXDrN8xBgF4w5G/STdwLagymxMv8S7D2X3hbvswOyyfVYPYJAPhZZm4q/DtQsjX0/eBGoEVg2Xr3aeCVztQkkJhlfE4ZzHapLgdm9cI7Ut0DVUzeJYsgE0SInpAgLlaHBBg5CbL2yBV2WQth3vsDil2v4RHPeGxBHt14cp+sBFHWX6ZptBkJMHEhAcbpq6Qq8A9G6JYfZS9EsZ8RTu/zhITNJZOR2GERAKVJNYjqndf4tLA0MLLGqjGZMkFC1Bl0Oov70HPFLcCJzcCEdcqdZQeU3+f+BdgT0Op8eE3YayYLlcHP7UWloDPGs4A64qohfkMTklew64+73zwC5N4e/Dq8fSMgpZm2nCMedlGgwovER9cDT4W00SBgv+8B7UWztLmIE2RtynpvA5MEAEgQzAswQb8R6N+q4zRtT7kGXY2kgZl2XVc8OawTHDNUZ9ObkDGohqzj8hqMLRKJ+ksUpJFQu1Cz/at0sgwCVBwBrmdHS9YH3IRklcpSYINyFkwFGB0NTGUpBJ0ZilyAYfoySBz7GXihFdoKh3CpbXNwsx1+JOE0UuYMAGb2CJVnzQbD8LbjZaCmknaCr3YDXssN+ZSUHwb+WKc9SNTKv8zOH0BL4SiGbJ7I3GeDH6VI0u7whwY3UzMibzUVXgDaOeq98Nvm654i3mqIrc9L2237Z2zNiZwfXlZ+f/syGkZ6eCvwSqeQP8Np/eiqGqIcCJ0sAUYxa9NBEBUmJDN0EvdpN/r9VKt0IhDm65PVZ98qpAkVmON8KTQnPRPqwJ3wKgQkOUYCjE8MvTeJ3pNUMAyD2t8AAHBsp+KrndBnjPkMqNpKk+/DVwPsWc6OAoF1DYxcuJTTUjiG5BOb6Zd9P8r2CMDC8crCewoRHnOz+vE+HYdOQgyFeC9R3be6L5T3pVVldL/Kdw6OeDDd/NRCnkE9XGcOaU1Iah+3wLPbXfgVbQWl+dssBCIEhiDV4ZN8ZOAkknCGcVSgSoHhWBAENI5zQONwYEEBY4cPqaWbqXO3kQZGIjFDV3OURsqUG079EaqMzEG4IeACjFV2LNJu83v1BZhDGzHoq774i20lAOUjWUlCx+j6eEi4y7Hc9UjIWQvAZMc8bI1jhAgbzpLZO6+wFQPPNwNe7UJnMuUHacQQAKx7U3tA6V7q4KhCT4CRm77UOOFFKWGYvHyhNmlkZkYkf1ErSizNWCLG76Who5/eBvxnjPXjf/6KOjabEToAOFWmtEYsAaCSrU1RYCDA6GlZmL/tlo+BhXfT8HYA8FRqyyjqFnJ2dcKjKzAamZBsMufrvBMLNX5Fptmn1Ah2bUlV4cxnTTWoMgWSD68F/tlBE8YOMASeMNhq2AKMwg8hXpbfRRCo74tFHDp5oBT4DIR64rfmA2OksSz9jQqjzzcH/tggq2QChK0M06tGgNG/F4f7pFaA8QR+5yEBR1yvGyjdiy9cz+AD5wv69TSAAMioOcDc11PcrTTDBY8IVEk9HGsmouYlmJbCMVy0ciR1RDf6/SQaNdVsagz6LtvVkyS5C4XMBNgQcAHGKixtypmjTAdCCYf3NP7peFNzfJVMzWcXojjY/vKNbhI2SxFRkkpVYDwmco2PjPfGdAVhlFdEm6iwwwc3GJk4ZRqYRCMNlYRcje+riUiAseK8B4A6dAdCRrF3JQ3ttsJv34XX3FhFHT7OQhAg1pgTmiQcLCFbJQToaSCCz53sXjsL+9BEYA/URhoYefLFi47No3mBImHvSsXXYcffwcxr2uClEQxfH7fy+f2L7XsksLSC7lPAu4M1g4+RQMZC1BFgFMgEfJw5ptBumaFALEYvdeI1q4QTYASVACMXTNQc2Q6seoV+/nZyaLvdRRPkqZG3MfEZ1sPuLlUK4F53aGCXopd8NSFNYoT0En/FI3tuZe6rgUOjgZEnnhxv/wpY/BAdIw5uBDwqbY2FDOUdRf0JI5PACyrX8G6LuwMdhf3a7NHysUVmjm8IuA9MNJh/i+migj/00slNSDYzMyGzHNoIfP0wgGtYNQAAeIgNjnCOscEZukrqeUU/L8gFGS5qWlLNjlKh3yE7BC97JvhryDPenAnJrfwcgQBjxXkPALBWmYxQ7ohqivLIVNWGmDYhsX8TvX5Srf1holb/hy5I/3lC7TvfpU3SKGEkwMg1MBq6jwS2fGJUwxCyqBMAELb+ByPscYocOkEYbXWXfbG2nMTW+QqHWasCjM2McBnO/yoM7zhfDl8oHFY1MHOG6J/rhCy6TC7UH9oINGaswizXBHjdhvVwuE/CJci0DPK0BFL0ks+jmDRFit5v3RhVSFRpYPLFHcpCG/4N5I7TMYuaF2BSmQ57BgT6Tg/scMr64iWuKdDMW+T9C9fA/MmQvXTVRKaBiaYAAwTzeWihL4HXjFOhJMCoNSqshFQSnipA1GpTUg00MA542Sa0k78HP6pffCbyDs3viUiAseK8FxXMzLTrAsGma0LSW4vKAS/jmVJtCGdC8pr4HaEUYJ61v0+jHw5vBb6dgmalDH8sCQNnRA2s+/9jPVsIc2vLXiD8joNEJwLjS6W/19DOWhW9EeYEmNoPtlHByAfGivOyTLjVaCUrDkGDLGoIvhrDegh+j1K7Kp3f5gppEXzu8M9vLUgSzsCl6uc+dE7XFnRXsLXexK9xyG2O49qwdwCXy3wlTVF+CI7PxrJN0mrk6TEaWIDhGph6RpANsvLon6gLMEktsfr2y7H9YDnu/ECutqUDjjkBJtCRW7E7LZmiVX3CWLPRKSMOjhPG929KM1I8R/l99azwx6gYZjMYHOsCXY1FHWOkgdE5hOkwLKeqTNeE1I9sAlCgHKQMeNzxCS4Qf8e73qEYZ18K7APwJg3zTzU6UJaxOCLsLrZg46kEEWwKB81M4WQo70cY8lsnAxasNaZMSFIEVUMSJgrJ7IK1tLBs8JQnc9RDFjVEtSf69RB8NUoTkiT8uBIBW2Ai6auhDvkyDpMmaCaY8CkzQRIqzfXzZ46zU1RUHAb+0RS47CngEpolWJ1czzR97gDWvxP6vnupeWFACoMHmJGo9QnXwNQ3MvWbXNUYdQGmcRaaJcfjis7KGanNW4V/2P/NcCZjEBRgLDwm+9kZQI0Gv6YJtrD338hMffcywjzPdsxECNQFgqgQpuXomZAc8Bonsnt/uK4A85QvYGozqYEBgBG2NVjksjhIG2V2NYPNpU2ICABeN4QmyuzUVN1u0oyjF9KvVw0zAox8ANdQT+vX+I19TyyZzsyE+8qRa2kWjFVGwKmIq9iHYTaZc7VkQnImAraAxtjn0WhgivwdrdXJgCSh0pyrwOkjxoLBin/o7zNLtHxXWOkD6hEuwNQ3skFDPmhHXYDRyUsjEK8i46chwbrWvjOMF/Q7Jxvxhk1Ud79BAihOBAgiBF0fGPagwxys5Y9GyVZds0YGSqlAbFIDEzE2Z/gyRtiddBkINTsWhVLbB/BBDB89KCEN8mmMfDQMbDph1KaxMumoDd4qQwHGkm+fxbB+hR+Lt5oZFSknTe4wLgk/TpkGpuIw8O1jimNW+HpYqxOLHqMB0Cy8pqK+zhzTSRIaRRxREmDq0ORmBi7AWCaMI1VamGylMgFGsvMnmlUtWsEe6sitOhAGiaJ5I8Egv4odXnaEC0fBjz5riyoaYiDAsPJYADTkNqw1cbfBILLieUsamIiorQDjrggs4qniJ+1qyU54zb+3knkj3tAAFsSUCcmI+lpBeOMHuhGPANCcmDAFSchNE2ZQa6Ck9ZXMIAkwchMSgzLoLxBpmvgU+k9wa5OGsjhzzNTvF3G/DiiTlNaGup6QhIELMNEm3AxL9rInu0RcIOzF9rg78Jnrb9Gth2QH2Lcad9sMoiWMkGZEUTBzxBv4sNiJJ/oCXKzD6FSZoeaRYmBCEnRm1A7BC3HdW8B7V2mX05AoYiSMkzi0qZ40MLUYvA9tgtlojx7iHiSZMW0CwHeBtccCg1k4bO5T4QsZUescSBbacM9y3V2XEQs+ZawFMY2oTfoByQfGaSzAVJAoOKkGzJqmtC8A1SyF8y2Zf4thbq2wRM2EVMcTkjBwJ95ok96OrtWhh0xNmugEJti/qJt6SIPQnKGYHOm4Jw1SVuycmV2BI9s0mwfYfmIUpjxyZDL2CIwU4n9mEjOBU8qEWDXRFGBEEYJOuLVNVwPjhW1pID/H9y9RbcKmj8xfs+Z0PWhgHNR8YtHnpN5QLxCqQ61NSLUVYJyJFiLkrK3Ro4vVZ0MehWQVkxqYM+p1ziIhoO0I6wQvUXWSvTClnB1f4FPnt5HXKWompIYVYLgGxiq+MKaOlFbANa/TPxayXCWi36fNvhgtouEcKq2tYuVcAe94q5wn1kE+lFiiaScgp1/oO2OmXqMz3/i15bWWLycYmJAe3jeeub27bNE6/DgD+O//WLvo4S2K0Pg6QRDq3H9gsufOyA+uLxOSHsNnmCvXwAnKTCH3gbGKNJF0NlaY29WcQTQ0MLQtB9lMJlysOmnKh8nIrzAs3IT0JyVc7gWbE+hxM9DtRvZ+mTZDgE+zhLoGK8546e1Dn30eQ698U5w6QAUusxqY5BwaxWEGZy3DXc81fDXKTiUuRVPETbQamNW+zijq8j/WrycIEBi5TQAgo0apmjYbKnxWQEidO7DWyqzgTABuXwa33di3wl5XAkzLvubK6Q1wjc8iTWlVFMKbnY0MNTDyXF2RX8OisFB1EnUeRVbbaD2JBjYhcQHGKuG0EVJInt4sUKaBSa3aj6tt7BWaQ+dTCQRdbwCGvsQu2yi0Si/8njBhlmYgdPVgs4tDEp/hbCaIzQk8cTB8OSsMeNDyIQcGRLbeSZ3gVwmcjBkwy4R0BnEQBBEYNNX6NU0Okj6nObNHXVFK2MLucr0IkTrOTVFZG7OCaAey++JQqrEgIXr0I3Kq0rtGeG0HcwFWJnYdIe2BrezttWHoi5Edp5OywRLOBEMBRk/raQmrwkJVmbn1i2pDtDRsXAMTY4QzIYWLgrAaN68WCFrkAg6dDrT32NDnkm3AL19buxaLqpPmBRifRzd8W4Fe51gb1CvLmuBU66HRr0ek+LzKcFRGp8dy4vXCRgMW+k0EHlWu41Kd3kX/ep4qCCbDVn3OKERi1IIDJIO5Xb6WmII61sDIF2G1TECA8DGyVZuFRDx7JoDN5IBs06mfmQmKVeLD+HvUJfY4Q6EuOgKMxf7OfQo4bSF6KxIiEWB6jgZuW0rNbpc9Rbd5Ki2t0RRtuABjFbMaGD3CCQPqjk2tgTHqgLreAAyRaRUWTzK+lhk8leZfJr/XnAmpLtJPRzAg+M0IW/WFWgPDGKRYGhgvbCFlc6N0xb64zlfqX0++7kwYGloD8wdJZ26v0tOEiHUswMDgGdfzfZOQBBghckGARPrcEmJeA+OqR6G1Pq+lxh5nGLLMXHXcKlb6pqad6P9oaJeMiEQIzr2NrhP2xB9A3l2BjaThknGCCzDWCecDY/CwXiWuoWutGKGOnlB3VqJDP2W2IAAtc43Pr+Kr5vczfSuCFP4d2B/GzCXhN2lCMunIaIkIZt1EjHwQOZaRb+2ArG7G+30epQaG0Y4sDYwHdv3+99LHgU7DgQEPWaioFn8DCzAVhN3Z6mpC6kLDJ7+ukQmp2030T4/Ac9o0NfI2JZHe3w3vmRdgGqXTWfbAZ4B2V0R2PbOYFWDqwjQYRhi0tBSCnNTWoc/hJrVy1AuJnnd5ZNcPRyQ+iPJnR/4MNmAkEhdgrBLOMbaR/qJtrzln0ZVVjVCHP9rVGhiH8Sq0ZjuoAH/Ed8Ir3r/oFwhXXzl+rzkT0nVvmT+nWYwEGD2tUC2SfflFi2aEcFonu0slHGvr5iba39ZD7Oz0/ucPopqIGz8CCp61VlcVfpOhv6axKMBW6Wg8mCakln1qvx5SGAxNSKJoHAUVeD+bJEWudYjIhDTqU6DzCAvaAIFGFF70cN0nxYuTPV+prfVNSnq/63XvsLebQd2/RoNOI4ArZKtJW0muqI4+tPrutblE+T3gF0nUQSWRaMHlz46UrgDgAkxMEU6ASW4R3etpHn7BWICxmImUiDY0FcosV4uJ3xP++hOLgWZhtBGAsgOQaNxcv7y8k219EZDeIfRdp06CAEz30NnyUp81zRUz2duFE/QPCPfc3PiR0r+KMWjomZDYAQvRG3RItAUYAyGfRbWOr4siOiqpJXDfRiC1lTX7fgQz3LBOvEbCtDTBqIUviWUNTLuC0H3WdYp6s7S5OPRZrg0QbEqh4h6Z9levXVv2Vn6/ejbQoje7rJq6MGff8D5w3kAgIZ22vYk++VHPXbjU/bLWl89k4sMgam3W6E+BicUQ2g9Wbg830b3lC1zu/qf+MYIQMkM1YCQSF2CsEs7el5hpvN8Md64IfVbPEIjPeDC0oq4EkJnSCK0Ekz4uyTlASo7+/kseCz+jMdtx596u3aZ+CeXIOzebA2g/SPmdASHAG74R6FD9Hl72Gaj9Gdi9DAfY9oOVuVzkGP1mfe4EsvuGNU+yTUg6A1IUZ81iQpRNfuEEmLu+U6QEqCIu4E5ttleXPDFYWlsg7Tz6uY5D9PU0QkEMNTCBfWbTDbCwOuiO/kx2XZP9Q11rXS57MvRZfj+CqBzwMzqHPuu1WZO2QN49oe/xqUD3kebqEakGpr1BAIAoUm3Rw79QzZeJNl/guxS/k2ZaAabVAP2D+twJXCkTMvpPAoZMU5aJS6bJVdVCbzgBJqMzytTRf2r/S0nb3oCRSFyAsYqR9gOIzgynRa/Q54Q07fWjaEIa3iMHpR10ctaoGfkxcP8WYJwqA+SNHwHjVwEDHg4/25ALGqM+0y/HeultTmDEazrnlXW4gk1ppghTJzecmD/xMsMycipIPA60vp5+USwdQYBBz7EPMpqlSKpxxe+qHUAGdsnWnhY2xDtYz5zJAciESaFxGkPz9civwEO/mLuGGvUzraZ5T+CyJ4Jfq+CkM+oOwxTFbPK1YOTnNNDAbPS3w5iaKQbX7qW/768fAqM/0xcaJYx8NVgaGJfFCDo9AcbRCHiyxPhYi/0DRedZSmoZwbmkU8onHLK2cFcohQr5e53IjkYDoPQdEe36Tqr97lN+lwb2AotLuRQ8q4n602Bz0Pob9D8nSGMMc8tSIMjzP93wvrF/UO5tQJ87gLtWUgF/4DNASg4+9sq0ipKQoY5cDfccEIKEOIb/pRzpOeQmpBjCSAOjzmcQQW6SIENeAHrdQkPX5Ph9+k68gGUTktPhwI2j7wbuXQs8HiY3i7MRnV206geMmBXabo8DsrrSfeF8YOQdy/kFwKM6C7CJDuCq/1U6v9ocQK8xwGN7GQfIBRiRhvoF68dok9GfK76mNDbnkzCp5l4Mcr+IA62uB0bOA/76QWhnamvqRD35d+2BNbJVW0fMoksuSEidVBhnxkvbazUXPojo3Jxh4jHr1Nw4K3wZlkYjsSmQFGFSM1W0FBPZbDuo8fjr+8CEdfB2H41DpAm+8MkzF8v8Jgw0MFv9bfGD38CEedtSKpzd8D6dvV70MJDZhT6LnUdQk4B6QFcPBkaDgzTBkf/+D/+sX56BbhSSsxEdVIzMJ2YFGCPBdvgMqhm56hXtPrOaJXkfJhdYKk/onyMuGbh/M9D3bu0+udAq2PRTTTRpq/wuXbvf/WGrrMCRwBaU2xVotxloYN73DsZPpE1og9wfKL298e9ld1EBqXkP+psHni3FIo+SkKHRwMj6B1cSvf+bFyiOW/rIQNUxOhoYbkKKIYwG6J5jlN8vfzry61w4ng50nUbQTlSC+IEU7Uw8iEUTUvChzOgU3vlRPjDIOzi51slIJXvTJ9o1PhqFZs4feK+gAlu/++kLlnsbcPN87XVY64TIB2zRpuxc1J1xowygnerl1Kv3sJcVg80i/wAcRhrtODoMBTI7A3f/AIxZFIo8YDmpyoWTXrcoTSKSj8m1bwEZF1CNFkuFz1j7JU2oQJs0RkeqPl4u2Pa+NfQ5pZX2WDV6g0GkmMnZIxM6gz4wNgfQtAP8w2ehv3smdhHZeyD//eURICpE9bo96hwWdicVzi64Bpi8j85q7/mRPot6qAUmIy2spJ1pP5g+W7cvs5yTQ9ATLqSMr2O0K2eH6sYeEH23fEUnCx2vApJaAJc/pX+O3rcC964B0tpp9w2YRJ/fHIMoPUFUBivIBRa/R78Pc8QDTdoASTKNYP5E+l8efZnYFPDrrAVVc0b5XerPzYbe21zAFc9RXyvWZHHUp4xjVOVkmqutcuEFUPrBNWlj/CzpjEXJguwepb7FyOzo91HNcftBwC1fUM14XBIaxauOUf8uQQ1Mw5mQzurFHGfPno2XXnoJJSUl6N69O2bNmoW+fU2mwq4DCCGouvJFoNNVwM9fAju/VWa7JV6aN0VOJLZk9TkufgRYFZjteKuB7iPxfyk3Yf6xlnjH+bLyOL9H/5pxydoVXP0e5fUaZQCVx9jHC4KsLAldh/iU51Bfv3kvmh8jJVt7bwD8Wd0gHtmG9kNvRWXfy0P3AlChSjpf9anQdvU1iJea3g5toss4yNtBFJXlm7QGPJWo9lUBgfVEKgXGOQG6LERSc2DezYHr0vJefzUqpbqktwPQTnlvk7YBmz8CVga0clfPBL6aBFz6RCj5k3Q9u4tua9IauPO/dNvvP2jr0/lqYPtnQLe/Av9HB5iLM07S+5AmtMHfxK+sjzMeqA74jHQYAmx8n35Oahb+GSVeZZmR8/R/BzM07aB/3ICHNecuhSvU1qDvIRG8qIAdldJ5Kg6Gjsu/Fzj+C9BpBPbu34c2G6cHj/UKXkCoCR1H/Mq6MJ5PDfLjASqcSqtHeyq151Qg+1163Bw6JlDeTwSIgn5isCJfR3Sy2WFnnT+xKT2XzUF9qqSUDXp90vXvAp/dRgWX7Fzg9qV0u/Rsst51vXONmA2c2kcFCtEOHN0BHFjLvon4FDprl47111AT0IEiGkUmCMrrpbYGyvbR599TCXS5Fvj+RaBVf+DyJ+k2uwuYsA44+jOQfj5wqDh0jqEvAN9OBi5+FKgoUf42ouw+W/cH9qlSRgg1GFzzdyx0BSL5et4M9L1D//lnaSOIT2XiFoDBU/HRN9/hO9I52KcAQGWzvlTgSW0NgGiPVZ6Y+bzGC6dDz6dUH3mbAopnDr7q0Hmy+4b2y/sogP5O8us5qAYovuZMgy02IhDSgGn0DPjPf/6DW265BW+88Qby8vLw6quvYsGCBdi5cycyMgxsoQHKy8uRnJyMU6dOISkpOlEUZ2rO4JL386JyLg6Hw+FwYp2VvSejUa8x4QtawOz4fdYKMHl5eejTpw9ee406bfr9fmRnZ+O+++7DlCkGTngB6kKAOX3qBA7kGXiFczgcDofzJyL7h2+Q2LRN+IIWMDt+n5U+MDU1NSguLkZBQcghShRFFBQUYM0adoplt9uN8vJyxV+0iT+bUs9zOBwOh9PAxCeEt4jUFWelD8zx48fh8/mQmanMqZKZmYlffmGHbk6bNg1/+5vFUDiLiAkJ6LCxWLmx6iTwvxcACU2BSVu0B/28GDi+i0YkGfkL+H3AkZ+AzAushWJXlwE/fw10GqYMwZM4sA6Y+xeaTj7vHuDrB2mSpa8C4YSP7KH+EXrnfiWQh2HcEnMJ6OqCJU8AG98DbpoLtFWFO795CXBiN/DAFssJ0jS4K4AF4+jSCfkTFaG85zR7VtBQ3l3fAmtn04ieB7cryxzbBWyeS8NQjaKIXmwHeCvp83bxI9SOvv5t6pfQ6iK6Fpgr4LR6eCvwyU00f5DcsTjKuL0+OEQRoqjz/i0YB+xeClxwHXC1Tpi+jCcXbsPX2w5jdc9CJIge4MqXle92TSWw4Fbqa2Tk/Kui9z+WobLGh0kF7XH3xW3DH2CEzwuseY1mZm3Rs3bnOrwVmDOEBikMNbmC+8nfgdf70bxIowOOrb98DWz+BBgxk+2IX59snU/77jxGRFOAqhofVu46hv7np6Gxi+1YvPPAEfxz8Ubc3a8Fcrt1ZffxhADTAglOJ23TpBGYW7Qf//h6BwDg578P0R7v91HHZ0EAng84MN+9iuY+YuGtAfYU0mhRucP8HwG/IClNx6k/gPX/BvrcDiRHHhIvqJ1965Gz0oR06NAhtGjRAqtXr0Z+fsib/bHHHsPKlStRVFSkOcbtdsPtDi2UWF5ejuzs7KiakHSpLKUe4VIUwNmGp1obSVJdTvOOhOtI9q2mTmUW11iKKoTQNm6Upt3n89DIAqsZK/XwuqkjcItc8yv3nit4qoFNH9JlCFJNRCexOLkP2LOcOqiaSRKmdhRsCNwVwK+FwPlXmI4I8vj8cNiiq8A+fKoKa/acwPDuzaN+7lpTU2m9f6sqo1Ewdby4ZkywvwjwnGFmfvb6/Ph800H0bd0ErdPDPH8l22moedtLjMvFODHtA1NTU4OEhAR8+umnuOaaa4Lbx44di7KyMnzxxRdhz1EXPjAcDofD4XDqlpj2gXE6nejduzcKCwuD2/x+PwoLCxUaGQ6Hw+FwOH9Ozlod+UMPPYSxY8ciNzcXffv2xauvvoozZ85g3LhxDV01DofD4XA4DcxZK8DceOONOHbsGJ555hmUlJSgR48eWLJkicaxl8PhcDgczp+Ps9IHJhpwHxgOh8PhcGKPmPaB4XA4HA6HwzGCCzAcDofD4XBiDi7AcDgcDofDiTm4AMPhcDgcDifm4AIMh8PhcDicmIMLMBwOh8PhcGIOLsBwOBwOh8OJObgAw+FwOBwOJ+bgAgyHw+FwOJyY46xdSqC2SAmGy8vLG7gmHA6Hw+FwzCKN2+EWCjhnBZiKigoAQHZ2dgPXhMPhcDgcjlUqKiqQnJysu/+cXQvJ7/fj0KFDaNy4MQRBiNp5y8vLkZ2djQMHDvA1luoY3tb1A2/n+oG3c/3A27n+qKu2JoSgoqICzZs3hyjqe7qcsxoYURTRsmXLOjt/UlISfznqCd7W9QNv5/qBt3P9wNu5/qiLtjbSvEhwJ14Oh8PhcDgxBxdgOBwOh8PhxBxcgLGIy+XCs88+C5fL1dBVOefhbV0/8HauH3g71w+8neuPhm7rc9aJl8PhcDgczrkL18BwOBwOh8OJObgAw+FwOBwOJ+bgAgyHw+FwOJyYgwswHA6Hw+FwYg4uwFhk9uzZaN26NeLi4pCXl4d169Y1dJViimnTpqFPnz5o3LgxMjIycM0112Dnzp2KMtXV1ZgwYQLS0tKQmJiI66+/HkeOHFGU2b9/P4YNG4aEhARkZGTg0Ucfhdfrrc9biRmmT58OQRAwadKk4DbextHj4MGDGD16NNLS0hAfH4+uXbtiw4YNwf2EEDzzzDNo1qwZ4uPjUVBQgN27dyvOUVpailGjRiEpKQkpKSm4/fbbcfr06fq+lbMWn8+Hp59+Gm3atEF8fDzOO+88PPfcc4q1cng7R8b333+P4cOHo3nz5hAEAYsWLVLsj1a7bt26FRdddBHi4uKQnZ2NF198sfaVJxzTzJs3jzidTvLuu++Sn376idx5550kJSWFHDlypKGrFjMMHjyYzJkzh2zfvp1s3ryZXHnllSQnJ4ecPn06WGb8+PEkOzubFBYWkg0bNpALL7yQ9OvXL7jf6/WSLl26kIKCArJp0ybyzTffkPT0dPL44483xC2d1axbt460bt2adOvWjTzwwAPB7byNo0NpaSlp1aoVufXWW0lRURH57bffyNKlS8mvv/4aLDN9+nSSnJxMFi1aRLZs2UJGjBhB2rRpQ6qqqoJlhgwZQrp3707Wrl1LfvjhB9KuXTsycuTIhrils5KpU6eStLQ0snjxYrJ3716yYMECkpiYSGbMmBEsw9s5Mr755hvy5JNPks8//5wAIAsXLlTsj0a7njp1imRmZpJRo0aR7du3k08++YTEx8eTN998s1Z15wKMBfr27UsmTJgQ/O7z+Ujz5s3JtGnTGrBWsc3Ro0cJALJy5UpCCCFlZWXE4XCQBQsWBMv8/PPPBABZs2YNIYS+cKIokpKSkmCZ119/nSQlJRG3212/N3AWU1FRQc4//3yybNkycskllwQFGN7G0WPy5MlkwIABuvv9fj/JysoiL730UnBbWVkZcblc5JNPPiGEELJjxw4CgKxfvz5Y5ttvvyWCIJCDBw/WXeVjiGHDhpHbbrtNse26664jo0aNIoTwdo4WagEmWu36r3/9i6Smpir6jsmTJ5MOHTrUqr7chGSSmpoaFBcXo6CgILhNFEUUFBRgzZo1DViz2ObUqVMAgCZNmgAAiouL4fF4FO3csWNH5OTkBNt5zZo16Nq1KzIzM4NlBg8ejPLycvz000/1WPuzmwkTJmDYsGGKtgR4G0eTL7/8Erm5ubjhhhuQkZGBnj174u233w7u37t3L0pKShRtnZycjLy8PEVbp6SkIDc3N1imoKAAoiiiqKio/m7mLKZfv34oLCzErl27AABbtmzBqlWrMHToUAC8neuKaLXrmjVrcPHFF8PpdAbLDB48GDt37sTJkycjrt85u5hjtDl+/Dh8Pp+iQweAzMxM/PLLLw1Uq9jG7/dj0qRJ6N+/P7p06QIAKCkpgdPpREpKiqJsZmYmSkpKgmVYv4O0jwPMmzcPGzduxPr16zX7eBtHj99++w2vv/46HnroITzxxBNYv3497r//fjidTowdOzbYVqy2lLd1RkaGYr/dbkeTJk14WweYMmUKysvL0bFjR9hsNvh8PkydOhWjRo0CAN7OdUS02rWkpARt2rTRnEPal5qaGlH9uADDaTAmTJiA7du3Y9WqVQ1dlXOKAwcO4IEHHsCyZcsQFxfX0NU5p/H7/cjNzcXzzz8PAOjZsye2b9+ON954A2PHjm3g2p07zJ8/H3PnzsXHH3+MCy64AJs3b8akSZPQvHlz3s5/YrgJySTp6emw2WyaSI0jR44gKyurgWoVu0ycOBGLFy/GihUr0LJly+D2rKws1NTUoKysTFFe3s5ZWVnM30Ha92enuLgYR48eRa9evWC322G327Fy5UrMnDkTdrsdmZmZvI2jRLNmzdC5c2fFtk6dOmH//v0AQm1l1G9kZWXh6NGjiv1erxelpaW8rQM8+uijmDJlCm666SZ07doVY8aMwYMPPohp06YB4O1cV0SrXeuqP+ECjEmcTid69+6NwsLC4Da/34/CwkLk5+c3YM1iC0IIJk6ciIULF2L58uUatWLv3r3hcDgU7bxz507s378/2M75+fnYtm2b4qVZtmwZkpKSNIPJn5GBAwdi27Zt2Lx5c/AvNzcXo0aNCn7mbRwd+vfvr0kDsGvXLrRq1QoA0KZNG2RlZSnaury8HEVFRYq2LisrQ3FxcbDM8uXL4ff7kZeXVw93cfZTWVkJUVQOVzabDX6/HwBv57oiWu2an5+P77//Hh6PJ1hm2bJl6NChQ8TmIwA8jNoK8+bNIy6Xi7z33ntkx44d5K677iIpKSmKSA2OMffccw9JTk4m3333HTl8+HDwr7KyMlhm/PjxJCcnhyxfvpxs2LCB5Ofnk/z8/OB+KcR30KBBZPPmzWTJkiWkadOmPMTXAHkUEiG8jaPFunXriN1uJ1OnTiW7d+8mc+fOJQkJCeSjjz4Klpk+fTpJSUkhX3zxBdm6dSu5+uqrmWGoPXv2JEVFRWTVqlXk/PPP/9OH98oZO3YsadGiRTCM+vPPPyfp6enkscceC5bh7RwZFRUVZNOmTWTTpk0EAHnllVfIpk2byL59+wgh0WnXsrIykpmZScaMGUO2b99O5s2bRxISEngYdX0za9YskpOTQ5xOJ+nbty9Zu3ZtQ1cppgDA/JszZ06wTFVVFbn33ntJamoqSUhIINdeey05fPiw4jy///47GTp0KImPjyfp6enk4YcfJh6Pp57vJnZQCzC8jaPHV199Rbp06UJcLhfp2LEjeeuttxT7/X4/efrpp0lmZiZxuVxk4MCBZOfOnYoyJ06cICNHjiSJiYkkKSmJjBs3jlRUVNTnbZzVlJeXkwceeIDk5OSQuLg40rZtW/Lkk08qwnJ5O0fGihUrmH3y2LFjCSHRa9ctW7aQAQMGEJfLRVq0aEGmT59e67oLhMhSGXI4HA6Hw+HEANwHhsPhcDgcTszBBRgOh8PhcDgxBxdgOBwOh8PhxBxcgOFwOBwOhxNzcAGGw+FwOBxOzMEFGA6Hw+FwODEHF2A4HA6Hw+HEHFyA4XA4HA6HE3NwAYbD4XA4HE7MwQUYDofD4XA4MQcXYDgcDofD4cQcXIDhcDgcDocTc/w/pTztsxX2GeUAAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hovertemplate": "variable=propulsion_power_kw
index=%{x}
value=%{y}", + "legendgroup": "propulsion_power_kw", + "line": { + "color": "#636efa", + "dash": "solid" + }, + "marker": { + "symbol": "circle" + }, + "mode": "lines", + "name": "propulsion_power_kw", + "showlegend": true, + "type": "scattergl", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + "xaxis": "x", + "y": [ + 540.6934718539693, + 713.9701584745893, + 202.42412530880983, + 242.27275451192665, + 208.88798256419926, + 523.7452876591317, + 445.9383990991941, + 557.3197237289359, + 777.7384268923843, + 275.94873931142706, + 82.11912552315326, + 193.29261420545296, + 275.30068528925744, + 435.28705496107733, + 70.63630912084362, + 776.6648525599293, + 804.2372661066968, + 315.07562030820014, + 958.7712133761182, + 415.7561011104782, + 638.1178870999904, + 845.1594053490761, + 535.6778225167794, + 932.643315227085, + 168.42332146406335, + 210.3304087555856, + 323.53700440937916, + 103.95488111286755, + 642.0105020579767, + 867.5005419275778, + 464.23697314351506, + 132.86859774477554, + 983.7627618463188, + 704.5155355119084, + 178.54782150586013, + 161.7675328752637, + 361.91985658407623, + 648.2133719923919, + 757.0704622972665, + 324.24525914086246, + 548.5814125484229, + 54.111151124553444, + 538.7119747251473, + 210.36715884002854, + 850.5067891545299, + 737.1216721530274, + 169.11344086430412, + 149.4683006593893, + 376.93756100124176, + 500.45944936329477, + 433.8670231360843, + 816.0518947983769, + 792.8885694214352, + 485.91659007171216, + 793.2757520140672, + 282.8588552889537, + 158.52103413469965, + 118.07662813487052, + 212.94955895211365, + 307.46823548693317, + 915.3575243203967, + 285.4062068326012, + 696.510347858048, + 139.21913016025388, + 432.65972128442365, + 850.4494802180426, + 700.4023620079619, + 126.35694079769266, + 15.771516899773964, + 788.6504312743054, + 770.7225608343097, + 76.24469253918409, + 170.46599019352394, + 859.3799486296489, + 443.26391965266146, + 722.34754305892, + 761.7485052257143, + 211.3665505018798, + 977.5692883412135, + 659.4904737648816, + 580.7347443445782, + 527.606157846684, + 682.2486390650818, + 204.24332022618842, + 641.5429083531669, + 424.8946810276193, + 776.4829629009964, + 500.3723210242201, + 624.4798144063841, + 20.188118165495595, + 874.9507274655864, + 255.96873920888342, + 818.0677254246682, + 736.0165910731408, + 263.2175546118219, + 529.0958234793006, + 613.5974849286035, + 222.67845318591284, + 504.02926510417745, + 194.69750405865915, + 987.5446699570416, + 225.80618850518908, + 660.6376661391381, + 565.0529197368764, + 321.65544773059617, + 0.5378123275814328, + 594.2522707939924, + 684.4388617885219, + 614.3004687792853, + 192.3780491496063, + 337.54714750047776, + 787.7720004573212, + 504.01975326578474, + 535.3182354042015, + 592.8975462503411, + 908.5748015072528, + 613.8481224815943, + 182.00984283590404, + 963.1321751386972, + 291.81226205601183, + 858.3051505218258, + 333.58613601749335, + 38.2490167613232, + 948.5261443299895, + 765.2720767717184, + 577.3641745625284, + 217.8798497412383, + 553.7973446727779, + 59.246762011263776, + 623.903071167922, + 979.8802203246926, + 285.1618683004489, + 574.7597501064898, + 466.40727307717344, + 702.3964240592629, + 95.0348629970722, + 907.7711575990106, + 608.4270064115785, + 444.9800770117107, + 999.9565247431192, + 770.0792513292042, + 583.9123380626746, + 484.0533520868404, + 543.5897038444363, + 739.4167075566072, + 85.5067100344139, + 380.22144133550705, + 329.83187042440585, + 379.7320251574947, + 371.57841196247364, + 184.74732089575474, + 963.2283974168175, + 938.8966190974588, + 152.2998596818279, + 422.9110747072878, + 63.620584093385226, + 131.11221317529387, + 766.0839286212437, + 461.3949365731732, + 375.9952252571838, + 577.1300885273752, + 907.7559247692221, + 191.5139698120868, + 565.2073408509407, + 704.6817389310053, + 7.190902193846438, + 449.42146316271123, + 573.4490271052476, + 981.021902319385, + 497.2649073403732, + 820.627367760284, + 973.2032373462134, + 697.4783444990281, + 222.19125646267025, + 990.9869234310777, + 458.15820506911007, + 671.099353885548, + 366.436158115666, + 710.3358910765171, + 49.83010149201761, + 263.9335081324115, + 582.1681808980577, + 751.7690419002487, + 604.6385815268447, + 771.1297348710517, + 979.2193647474583, + 514.9394498752117, + 966.2331767475561, + 98.31056050295051, + 981.4596556012348, + 871.0921705319921, + 602.1017452089454, + 555.8289622760254, + 924.2163576321959, + 309.43528388751815, + 888.1407468609566, + 242.93667352192915, + 638.519274818505, + 369.4571075220531, + 570.7295800918067, + 25.18721040406802, + 521.870706931879, + 70.52631542531674, + 506.7311934641115, + 224.0322804450594, + 412.620025334378, + 827.6884198533166, + 439.33227934127626, + 604.2949240083965, + 582.7150756561101, + 577.8514570005195, + 231.82485371292861, + 927.7753885845343, + 676.7674570519622, + 980.2446029794343, + 546.5825961754352, + 698.7737397087571, + 588.3070296851099, + 850.3827886587261, + 866.0501346463138, + 826.7409741423344, + 950.3712562779159, + 428.4274415447128, + 271.1851863716451, + 219.77193687574436, + 587.809004186185, + 229.67893778013902, + 612.5971663466156, + 697.3243821461388, + 676.1503519330457, + 76.85225609286384, + 558.0750861890218, + 758.2349605696835, + 224.44945997323074, + 792.568113774861, + 322.3889363981742, + 884.224872973804, + 842.8546388490065, + 444.2482404506094, + 938.8943249511595, + 629.4633297535103, + 619.8186429022682, + 707.93148559999, + 803.9854228457086, + 735.8348779094206, + 595.0316638578606, + 205.27576038689145, + 583.1901319159821, + 353.3965251005248, + 425.43072805173387, + 444.4977970244517, + 226.63958651270278, + 477.3340578448918, + 330.61809853799804, + 376.45507357965533, + 329.95819809333346, + 173.8722221009982, + 971.5782847313468, + 451.62226861925114, + 446.21316441247274, + 315.3599179426951, + 7.89095272065099, + 587.0335193645518, + 137.23428762674172, + 954.7144366711392, + 436.5766719074822, + 279.26303841073144, + 921.280578431684, + 656.4204046847483, + 60.26134696139218, + 48.21570981137535, + 648.4989045160407, + 605.0362702330929, + 755.383738557868, + 675.5961058532415, + 430.4248161950589, + 582.5411966263767, + 295.65124864430106, + 46.84796169500349, + 92.87597425641658, + 303.843238985411, + 958.4890605619847, + 205.18613097501094, + 483.38220347192606, + 996.161023730509, + 740.1972987001213, + 785.8540823816104, + 974.0591580199598, + 44.188839002269106, + 459.4642426152726, + 744.3787545788621, + 212.1956377053884, + 699.0038240504417, + 14.518876977660744, + 813.4315409712457, + 388.71915216242115, + 65.82967023243336, + 984.8493011625335, + 754.4835475742949, + 643.4904536452754, + 865.4972407468928, + 381.349915248968, + 119.16935004454999, + 342.1718475800364, + 332.66346634672516, + 858.2295395059298, + 294.88128699690395, + 468.3414134251918, + 921.3609965794453, + 64.47989382042896, + 840.2145818446917, + 822.2624895399416, + 60.63293569015249, + 414.5721494339614, + 859.8450655274253, + 521.4225456259879, + 347.7856856452586, + 147.44076735413026, + 234.8768895597232, + 944.7115502341217, + 773.4726960630446, + 333.5706303261785, + 783.3227639203526, + 731.1955991243358, + 165.24943820101856, + 883.7395026224896, + 592.136685695238, + 3.5772341542590347, + 638.5146529854629, + 130.62330290110737, + 414.83869418884535, + 294.57374451853036, + 178.1640519525607, + 949.5851251576019, + 374.3187983105878, + 526.8961097303549, + 147.53964375654172, + 626.0923652306766, + 545.6459239125721, + 564.1062099362, + 299.4419220117762, + 886.8510397215961, + 608.4369735362408, + 843.5350766981645, + 241.7785119457181, + 718.7748235464842, + 637.1909330004572, + 92.18725656397642, + 905.5307589898814, + 14.475789540621232, + 352.68029932098887, + 604.5262200351417, + 287.2576865247565, + 337.70972916698014, + 596.1529439508658, + 527.2474007088312, + 101.49366922111925, + 211.8303064626168, + 294.6524390801992, + 123.45880503501516, + 831.7392121202728, + 157.2697651723437, + 598.6880348892091, + 930.9688790333347, + 370.9968756846045, + 477.5635105296141, + 16.94755085465427, + 572.0814833431992, + 665.4800147462314, + 542.891999801038, + 265.84390745789386, + 594.5765079190821, + 855.8054153631282, + 563.0120100529558, + 44.53332389020559, + 558.2224383697005, + 670.6746602218839, + 895.4428724285162, + 649.0980440696204, + 695.3555897129486, + 771.2981154612193, + 402.822959239574, + 541.8637674990497, + 209.28738009863102, + 827.153706299542, + 141.3750041044367, + 405.40985991573507, + 368.40560556875914, + 179.04304382252744, + 841.9674624244628, + 165.21139385520877, + 276.49548770452293, + 181.99650300578497, + 919.3151281402658, + 276.8719492588242, + 825.4547322479805, + 545.4520780841443, + 794.5680135585626, + 374.25108053238296, + 527.2601875099242, + 432.0860534739719, + 433.3567844653701, + 409.76064792416236, + 821.1971519251872, + 287.5859793204679, + 904.4647638673651, + 550.6414850574859, + 451.9257713306323, + 100.69513512046623, + 612.4232944604605, + 278.58993436770083, + 810.1783250084801, + 136.71217005566837, + 454.3761903864928, + 985.8195136142014, + 616.7606959424106, + 361.9347287091067, + 437.2292469693989, + 537.9814714369571, + 513.4107725112648, + 504.04159216193045, + 970.9492524001591, + 681.0256126728949, + 917.3548801135088, + 221.255662696334, + 323.0335810393626, + 661.5075242102862, + 614.9365088253775, + 27.377962063211413, + 238.08469548910404, + 70.99378253780087, + 549.2635834683571, + 905.9020881729587, + 36.61949068489123, + 134.28155050750647, + 617.0299339727665, + 617.0873461653395, + 964.1677804882728, + 27.39770831489652, + 138.5151413238769, + 602.711265365115, + 812.7810157381017, + 904.7872921355885, + 333.7924060935521, + 641.2283961335586, + 513.1520160179147, + 648.896648166653, + 240.80300253042896, + 390.45649733054876, + 141.0783945050409, + 894.9346178703307, + 774.1557253533834, + 629.2809831531719, + 771.0479616281423, + 651.6076865516911, + 157.2123368170525, + 712.0901952962744, + 503.5132542265632, + 399.4316114590444, + 582.5437948235364, + 539.1202569023271, + 952.1301514329531, + 158.38018012244737, + 318.418766039005, + 710.2183037106563, + 477.6358243126375, + 323.5508251985254, + 911.8424208282385, + 107.9158986717299, + 487.49833814666397, + 973.7352764725963, + 596.2559655448565, + 138.97128855090156, + 28.316137180909973, + 386.01334380562315, + 845.8472122400326, + 160.3389236693208, + 955.1366627830287, + 168.050948425424, + 540.3314265980346, + 227.17775627540559, + 503.1369645284466, + 660.683501699845, + 147.29003999352096, + 200.46296920211938, + 154.40072387517313, + 719.0277494633262, + 436.02473686269394, + 464.71359860964446, + 252.63517230931166, + 931.6227460581188, + 677.3013344286899, + 792.4060741172025, + 61.92401182757612, + 688.7744284318366, + 539.1639187487624, + 162.93326622802718, + 550.9399316819225, + 642.8463948194698, + 157.92681866162073, + 90.2939022514202, + 382.2029361483417, + 550.569189404405, + 746.3006767902172, + 915.8092575104504, + 47.91438274768056, + 633.9772049425595, + 30.889264893434575, + 87.81956996321006, + 395.3322948894938, + 489.26866512463096, + 294.700913864943, + 349.0662164269825, + 999.1236969129055, + 60.5941411429064, + 550.7024500240797, + 67.69195126672389, + 981.7570601749015, + 175.85027704215884, + 783.8279610231754, + 874.8637854718544, + 525.4047660317623, + 410.1250829630994, + 464.3275186584366, + 442.09023475734733, + 608.1576956978975, + 500.86659074855265, + 208.15294044216458, + 291.2421783048439, + 505.734162745054, + 65.88869000259967, + 814.3327150721601, + 414.3213423065669, + 476.09193957570074, + 822.686816002338, + 409.62200187931285, + 930.9030796025312, + 551.2608919873032, + 386.85404907963283, + 381.5292643818124, + 633.0623715934025, + 299.43975480140796, + 578.6102533581208, + 217.02717755009093, + 351.6188697989262, + 104.94695649877816, + 164.8007589136433, + 636.7533759687818, + 182.03747683485872, + 828.7877044570537, + 570.4578770255191, + 250.88854008604557, + 561.9862313111116, + 27.67970294089872, + 350.0287775243868, + 986.0767283280104, + 340.6795245401435, + 773.8240397138724, + 23.469500198699976, + 674.3724627882095, + 911.8449270413502, + 336.64292809464024, + 712.3523745313582, + 421.88370138262246, + 557.2014935000426, + 865.8677418918782, + 57.62504167472338, + 228.69630939502628, + 332.9711919902133, + 434.342435651224, + 42.3155537624359, + 613.9500273598285, + 35.0979154110026, + 237.2810655341122, + 676.8744903957515, + 602.8550849920503, + 232.576038420511, + 466.6294538972884, + 539.1265947212747, + 42.22653694040657, + 790.6866119098854, + 745.6690682665146, + 211.53142369357926, + 26.005377556019727, + 272.6679667318209, + 486.4720542074765, + 19.910780211278013, + 748.5068960535755, + 942.287672870331, + 357.944740843907, + 836.9268912324271, + 25.968435756772323, + 749.3829427347043, + 654.4105820128517, + 785.2422833713466, + 446.724007444026, + 861.5403551311712, + 775.2397271714237, + 434.1468509295391, + 115.76050962602702, + 822.2591987853933, + 798.7291257584743, + 119.43837166460347, + 213.9733462335255, + 246.6978618161505, + 840.484268787765, + 817.8815411658239, + 910.6976870260175, + 806.8208455621204, + 647.49904767322, + 84.66499996289234, + 986.6931412255311, + 995.2221542642441, + 667.5909165402795, + 713.8848243694268, + 3.261369159733851, + 411.5394217177617, + 936.9465761606914, + 0.5152993626696967, + 65.02906205690829, + 702.3593763257002, + 46.92369279567299, + 765.1765942239301, + 825.51272559606, + 441.54085760354144, + 956.0588428343714, + 5.504699482021036, + 397.75247127322046, + 592.5151020603088, + 333.1504856156059, + 888.02387867843, + 40.83775220717245, + 928.1909602686914, + 662.9628930185631, + 515.348731217734, + 812.1226943682856, + 814.0712053553088, + 483.0016941952041, + 834.9485615552535, + 774.1878473693673, + 889.9151167095781, + 990.9081790613823, + 78.26296845235092, + 252.50179123274708, + 916.091448799098, + 780.9519762174149, + 843.2199518281781, + 195.2134708089426, + 303.2693488185115, + 324.3832855087324, + 714.8953936134074, + 945.5184196743752, + 925.3884505569786, + 458.42735278040936, + 384.85929474021185, + 497.24325195403776, + 478.61950746882366, + 582.7905291343482, + 823.621936970551, + 359.8275729414405, + 298.03429447320275, + 636.4133460659637, + 850.0341345075319, + 107.28745914783356, + 891.905707465438, + 824.8272816769189, + 145.1075406446468, + 310.67080263885504, + 130.07382070683482, + 357.45776167588616, + 269.05964465161844, + 188.29743336503867, + 243.1845731367469, + 768.7514444018723, + 571.6555113802771, + 4.205412329277847, + 147.53319453286883, + 706.3971842586576, + 365.16883474988083, + 930.639581422919, + 679.556758024133, + 993.7116267561738, + 637.7022829001339, + 843.1191650807814, + 88.05201835016196, + 547.0029495781738, + 498.6241696398213, + 777.8355910433522, + 620.8321045970971, + 577.7028484279563, + 2.308301615629005, + 682.818027694465, + 339.250792582343, + 587.6884946321867, + 99.72887545859655, + 415.4145254285484, + 566.2859354272947, + 51.241829034045615, + 952.8137104988391, + 728.1466797258184, + 668.3197847683745, + 866.4946885983073, + 962.9045942018505, + 326.0647937136041, + 916.3831691608724, + 793.3603130686034, + 373.5440522831234, + 639.4025606941265, + 353.1307269146817, + 948.0819283258684, + 68.13843119323914, + 68.15568156415142, + 412.0225973439293, + 178.06933876048004, + 474.43524845730735, + 657.2794298921289, + 32.36157740605605, + 403.44995476313306, + 27.20743885735366, + 801.1272440504849, + 677.9355663316658, + 663.8038065075446, + 925.774299969238, + 316.6975103658826, + 296.20450568781484, + 78.29723997449022, + 456.4352703824964, + 199.95501300249884, + 73.51409255950037, + 824.3811207511795, + 360.27393381445404, + 225.90151980345473, + 77.26573580247454, + 53.03054655192019, + 667.8376720834826, + 951.4690370817162, + 316.38832930843273, + 973.1681467517866, + 981.1315928823345, + 28.92561969898044, + 733.2167402337252, + 884.9831277096572, + 312.3242687524996, + 750.7835578452666, + 958.6352514220155, + 136.56105656217034, + 908.952693029541, + 110.2422674486736, + 10.845947720172555, + 5.253931578988125, + 583.4341319220786, + 639.2111677898644, + 501.55099233531797, + 326.88119880394015, + 348.5417060439199, + 736.4767753673426, + 439.18112574793054, + 888.4268488675372, + 737.3059140029322, + 231.95780490230078, + 565.8794705792678, + 995.0921474867516, + 718.9458259117313, + 720.8103576341217, + 890.261590560316, + 500.2953606009476, + 615.0389018175264, + 695.8957962124117, + 984.5243785128224, + 965.9388293601851, + 737.5957418198541, + 873.4363375289732, + 215.037012540792, + 29.542594453797697, + 509.5677295559993, + 468.8182128437195, + 259.72828180027983, + 632.5862650795501, + 321.1202071756739, + 775.2103201793021, + 902.6166523077699, + 758.1846278345186, + 347.639444947075, + 240.42352743462303, + 60.5213532651796, + 733.919955847459, + 851.1760693898906, + 873.809560858498, + 348.0173460693461, + 710.1995865717463, + 672.9017745038323, + 155.87445951684288, + 828.3674585620786, + 822.6435257566446, + 347.9335788328064, + 405.91372823420056, + 103.09563667479516, + 834.9390529684533, + 234.7267738566887, + 373.5730445684932, + 729.9115978818954, + 577.2861796005066, + 870.0080986389123, + 393.0641499682072, + 904.2791186262127, + 223.34596900559555, + 217.24583179057723, + 822.1827264657206, + 796.2747277643746, + 476.98970177275544, + 983.6077027161764, + 39.92798714625445, + 354.90547093863, + 360.0295346735194, + 231.7207401861723, + 102.10958774307144, + 837.0502714167453, + 77.811408369717, + 911.3157090746932, + 256.1795666292704, + 494.16204508977523, + 149.20278518296658, + 799.4105240564622, + 960.325076684068, + 860.517330164996, + 466.2624433741013, + 514.4746321362526, + 190.9928859567528, + 302.3485933228207, + 935.362387833064, + 466.6811204917172, + 601.2520574606632, + 231.88771898604955, + 696.8529657249848, + 409.1789771327747, + 480.9544860635997, + 641.4881358497825, + 571.5780962201209, + 392.81823252280145, + 557.5577985057905, + 642.9695179460632, + 103.97973895350732, + 318.6131407298808, + 762.3790462776856, + 500.94996184594606, + 278.2025641890568, + 617.1089081399211, + 432.85129978302206, + 223.2174886112085, + 842.111203339756, + 925.0229261808192, + 339.7970585507781, + 622.7119502207998, + 646.5079908699399, + 251.25659989360938, + 870.4401816669172, + 579.026279196908, + 691.7762097652444, + 808.8935329501167, + 244.71605172012056, + 635.9730880114704, + 995.311427477562, + 85.63599219203589, + 175.43679406227218, + 983.5945770977152, + 816.0983235550044, + 233.63450472198022, + 916.394741205239, + 428.771648016526, + 680.2910444663843, + 250.67542773805397, + 347.6878720338289, + 746.2215643325169, + 117.46715661160533, + 400.5592684087357, + 480.7842293052634, + 412.52589644687333, + 516.4564604557712, + 875.0184715774976, + 328.67976345563255, + 66.07652178057066, + 709.7765629174346, + 478.4816369834324, + 922.888622005696, + 388.64103101233474, + 158.762893913751, + 513.4335734417181, + 715.8364688399106, + 827.0328356915161, + 58.51441985929085, + 347.6978166584256, + 614.1952694281568, + 223.51573295532378, + 640.1498440564143, + 645.1830986054089, + 528.3326829638753, + 175.89448821619024, + 411.2583279515999, + 305.6145768698724, + 371.617548464657, + 797.7312261888156, + 472.7169101015317, + 456.5416114527625, + 662.5556238284697, + 867.146015636539, + 318.26655629769454, + 509.19120162723874, + 237.81320514032234, + 886.3268483540236, + 474.55941303160307, + 748.5289644145538, + 639.7106863795684, + 504.61091580470276, + 349.09689922138074, + 510.09564335177646, + 315.04973720391126, + 241.4936245625665, + 602.2367087541782, + 229.80619166775097, + 242.73872892677383, + 81.77401131555196, + 575.1917079997768, + 833.7524082762485, + 374.1374953590151, + 887.1316669821678, + 816.0806436200833, + 736.9337262796034, + 987.7604982311968, + 521.5435317976599, + 339.0895226814967, + 982.6929385274794, + 887.03283279962, + 870.0694083299978, + 53.258711358220026, + 583.6992650814776, + 527.2454685484036, + 852.9394890220829, + 119.70068426885238, + 788.6649973566274, + 491.61309354323845, + 942.1650580186099, + 214.6095909880016, + 741.4596473173107, + 854.6370232361485, + 786.9758129939889, + 503.6973990434219, + 913.6706916785486, + 205.6841436929616, + 470.5176222483362, + 173.65532128080375, + 37.17066968511329, + 43.95233123912013, + 160.7391484442895, + 833.0179740626502, + 316.2702246913905, + 425.24056438694157, + 827.4116452321866, + 400.60017844304974, + 686.4470417949144, + 785.2687630873719, + 930.1896559786604, + 284.5690921906282, + 889.1508807151827, + 392.00232017974554, + 836.4666486876123, + 953.4735848122082, + 272.01604144182045, + 651.2767215725681, + 14.066066989292025, + 771.7770538535982, + 383.71029361672294, + 707.4108584970876, + 969.2682696650427, + 404.81821133242056, + 741.6944162295263, + 665.8401979153291, + 196.62974289180224, + 321.10363980970493, + 340.00819239260585, + 463.5512018554462, + 274.4116471065796, + 536.0440386077219, + 296.04259466165007, + 134.96857628771298, + 8.619826171223366, + 905.635330738256, + 766.6633187813171, + 110.1069063034953, + 317.3567617455988, + 857.9659386835862, + 155.17147626843453, + 469.7978773579118, + 382.3060062690933, + 68.48924027448433, + 254.13193557553848, + 381.6909246907858, + 864.9930976447602, + 868.5560664866805, + 452.2210212421225, + 267.3720140032303 + ], + "yaxis": "y" + }, + { + "hovertemplate": "variable=auxiliary_power_kw
index=%{x}
value=%{y}", + "legendgroup": "auxiliary_power_kw", + "line": { + "color": "#EF553B", + "dash": "solid" + }, + "marker": { + "symbol": "circle" + }, + "mode": "lines", + "name": "auxiliary_power_kw", + "showlegend": true, + "type": "scattergl", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + "xaxis": "x", + "y": [ + 72.09561167797679, + 71.8403960405219, + 72.80026677400858, + 4.8347215175235885, + 60.742036415226806, + 56.34192707992357, + 48.08803587980961, + 85.01416698512902, + 80.90476840328668, + 40.50907363677211, + 29.018834165275777, + 26.051638533860853, + 62.35371599844376, + 88.77398826636073, + 75.78541853773578, + 6.378500487780991, + 19.871264317858227, + 24.18698940068813, + 6.947152747455821, + 93.2900076466584, + 88.12931342334504, + 45.95078671377573, + 93.05406525987553, + 37.80042154388982, + 21.094496909949633, + 83.740118364559, + 30.187354915756302, + 74.65241745246051, + 16.560214345180245, + 70.07774877225907, + 99.16757460870265, + 97.03116634439239, + 62.46281621983941, + 84.6431281815753, + 46.57759639184601, + 27.575508391853496, + 34.44183752983272, + 47.556909043492745, + 69.43454521853668, + 9.192509498608336, + 64.27132900162826, + 2.1184352257557215, + 51.79573033444752, + 92.08492726051627, + 91.55430957600291, + 84.95267574697222, + 56.51537734143288, + 97.99045318064401, + 45.24300342180304, + 44.0436655795048, + 38.564966002282006, + 50.956411315229154, + 5.452276293930847, + 14.78968572363738, + 27.552089805378245, + 12.946589196852775, + 90.39356239409804, + 69.69304217203577, + 63.22217811345725, + 68.24160785391506, + 30.130636101372865, + 95.71257432969067, + 39.586869817667115, + 67.24260818085156, + 69.56478816929834, + 17.82709144372978, + 18.812474171268867, + 61.70654716911582, + 21.302977501013398, + 8.898151564353618, + 8.479121183946848, + 28.886075405176893, + 97.73042470632858, + 51.5472974614026, + 76.98703222789315, + 32.83227290188506, + 99.77357746635849, + 22.303170005541052, + 56.60144985348688, + 51.37729924706797, + 18.897139015594465, + 96.84747179692663, + 6.266375517937572, + 75.32378825847196, + 54.712454591666635, + 74.77083247368948, + 41.52035697097932, + 78.48475850954888, + 5.800390476575856, + 92.80603717352939, + 86.95906824951044, + 49.369359302041325, + 10.811285882264288, + 78.40139914161169, + 71.80003472589146, + 52.26579814911217, + 59.54430513630843, + 43.83041919954178, + 53.92825802159138, + 96.60417655888854, + 71.32316698560052, + 42.14302887291201, + 43.95939527291851, + 70.64740156759754, + 4.166792411999398, + 61.33621274245873, + 51.298560101384325, + 63.65958421348973, + 89.26596582356812, + 80.58881565841031, + 20.175963912338357, + 11.32301010703035, + 80.81619604205505, + 62.56884561935245, + 50.863091054121014, + 56.34456126274847, + 22.265286089661828, + 50.35846170068409, + 25.21079960015199, + 97.42602541293998, + 43.57972293798562, + 3.5758248335987286, + 8.482466106051989, + 0.9542082740596314, + 23.182536461722247, + 48.565367368655146, + 0.3100162406879159, + 9.366539479344071, + 24.679496757534736, + 17.02722739608078, + 93.76053768250088, + 53.606069782589984, + 7.9329463303049685, + 70.66153363577378, + 18.880778585032264, + 43.74077343346362, + 57.37067246230612, + 2.690350348790338, + 98.90924162730633, + 43.64703458673945, + 39.693361770360426, + 46.197796143143364, + 34.335201839832706, + 52.21044274511421, + 7.655704483224934, + 10.557922314447477, + 79.1803305834132, + 42.79677862462334, + 85.91092991191536, + 8.535827475993052, + 78.55477764519534, + 43.7961766931275, + 87.64921762341766, + 83.42929155309376, + 75.05730695671275, + 80.29446762956857, + 36.975535796640735, + 85.44797213581377, + 87.33632107406348, + 87.12077097886025, + 44.66479656017172, + 4.757865686401774, + 16.054283665627334, + 3.0728162587403074, + 40.165697933461864, + 25.5252615934646, + 50.135629471282115, + 36.28529513217066, + 20.537569692677728, + 12.64254379800277, + 96.69369806921748, + 58.71871761335545, + 49.425452643232205, + 49.2741223255573, + 92.62597902293143, + 13.534610459761842, + 16.38737596401346, + 57.809388500590586, + 72.64889424716684, + 19.383327888528935, + 30.51651396240499, + 77.18768117740997, + 70.25851636984108, + 77.1081875408383, + 98.24074942193704, + 86.1337626835976, + 57.86538016650012, + 29.982727642408015, + 67.11622172877176, + 42.53028969345175, + 9.328335926018916, + 84.7589011613025, + 76.18523981808558, + 87.08602962909984, + 36.732663659960785, + 91.6193422907818, + 83.0309687484918, + 65.54766812092858, + 85.99031855549806, + 94.00023007864536, + 90.52621489188004, + 72.35526048213734, + 25.64425266415108, + 76.92894612385092, + 69.7451964204911, + 4.807883037816074, + 88.4474184041278, + 87.03276894288702, + 74.56650725105713, + 98.58961153447046, + 24.382468336858707, + 67.16333858728994, + 65.98884922384649, + 73.37149979526505, + 75.43176966502597, + 40.45277199012223, + 9.810723743982507, + 4.362746727846534, + 88.6920403181324, + 6.122017235601406, + 7.141593874520269, + 92.50371620887653, + 53.3711907782653, + 10.533821618098106, + 42.65730414992469, + 39.17265775684942, + 70.02244322982101, + 66.99704139784124, + 55.61364990020715, + 23.485808724414138, + 56.61521899613239, + 70.13032548901556, + 89.56025970769264, + 63.98570210969303, + 42.80339264256732, + 5.921074005116999, + 9.335444796006687, + 23.171756818106225, + 14.77946431214141, + 13.38826496568677, + 1.7824552241064162, + 96.9547812215823, + 60.94510193514447, + 5.4198503467875465, + 72.61899088921407, + 21.113679989718882, + 15.203208291092473, + 41.24143690518854, + 35.082398266027084, + 6.758406462278533, + 23.833279642782777, + 51.02810047367042, + 27.471925847373356, + 11.403231914620193, + 1.3409509882749027, + 63.52946649300303, + 65.61057564352238, + 82.81716949822955, + 45.04814127694791, + 82.65586108710941, + 42.4193885895115, + 60.76237420459554, + 60.559503748534446, + 69.98312514869234, + 83.2021684067929, + 53.5557831750574, + 57.62657351873256, + 69.70738497556593, + 84.30045393440733, + 26.354480023685657, + 62.37782230632683, + 90.8437078330216, + 83.22253881814117, + 24.565540419893317, + 59.876263822628204, + 48.628855113074856, + 64.33805547170515, + 12.76572050359761, + 11.559667310854927, + 53.29121864197454, + 45.507720951614886, + 37.568164397249106, + 64.94282826483027, + 86.95403709052327, + 64.33132234319018, + 66.99776484190704, + 72.11387528646101, + 42.47704273841313, + 59.14392514304511, + 25.157578694067595, + 90.5083986848715, + 70.75743384035592, + 98.54216990197409, + 6.6446383890249265, + 60.49852888183962, + 5.187639841893088, + 93.62901137473848, + 93.31520563962772, + 96.00183442943548, + 33.58506950060632, + 12.101636813794503, + 76.4088077693049, + 62.93620301512316, + 82.78062352147614, + 19.463683305352674, + 66.42727644113782, + 49.901906887557715, + 30.900971737520578, + 45.13827931317634, + 34.72607299287071, + 56.38679364253579, + 26.907874845685743, + 50.32126953860687, + 79.59047139782189, + 39.33101640635017, + 14.568133855777099, + 11.113047840822542, + 6.005722470413755, + 86.08003663952766, + 31.5716719540441, + 32.03129188480474, + 25.02483093944776, + 89.73977270345213, + 65.94264320446274, + 44.27455869003762, + 56.75817768410214, + 14.215179493504614, + 69.92955406901022, + 71.38180946172143, + 79.58787664172058, + 34.422604051702564, + 79.83890965498092, + 5.6422947943654655, + 21.563380167009626, + 93.23290652639207, + 56.43158281692743, + 4.637348220833404, + 73.04857932114312, + 78.2868114552931, + 39.82346104541544, + 11.096834147845346, + 7.988357842637961, + 8.642438076374559, + 78.00403815901633, + 6.576274651600622, + 18.333998030851973, + 86.33348641512893, + 86.27899513198662, + 11.93495016372813, + 13.790727284026405, + 50.351965950333465, + 62.89236003795514, + 93.29161921762895, + 82.24821980508914, + 64.51261372982798, + 76.54719508003059, + 59.99116509323108, + 11.93442789579352, + 40.98186904281088, + 64.51376507893033, + 60.89174001033412, + 80.99863336067153, + 89.41488719248095, + 62.30301506189534, + 91.22933644616108, + 68.74032104723791, + 99.9781574494383, + 42.36471212974583, + 40.12652061830258, + 40.074813075833994, + 35.545235058756795, + 39.1111337664176, + 4.415473652776825, + 0.5077378925820719, + 24.78154289699659, + 21.481028117663538, + 40.02739624009235, + 42.71180722800396, + 21.45069157433934, + 9.836548147027813, + 5.122352216568682, + 58.42796403720624, + 67.70360453055622, + 62.133604057347384, + 40.68730456590449, + 81.58014935313798, + 79.4299423835717, + 17.994443073347078, + 74.76147019505909, + 89.01774926461924, + 76.42727676408686, + 49.15241298379848, + 59.51836908535736, + 5.907978757181165, + 29.406092483946168, + 70.61397660404019, + 17.063088004890304, + 45.133323798392745, + 32.32629250148745, + 42.20746200161757, + 53.84435599024122, + 57.243957028246314, + 45.068483933832034, + 54.986490851104584, + 11.578526473019545, + 48.088766237200645, + 44.196051548293134, + 59.50314737731174, + 75.89066604680964, + 37.41883701100761, + 44.35822320677376, + 76.87717228647993, + 16.451776693090036, + 97.3860347551575, + 16.53012976224626, + 63.93278168396629, + 4.9035540193610565, + 31.643632580451264, + 79.2110436356929, + 98.76714835880932, + 94.10259499229794, + 73.38561688969979, + 42.59990428199336, + 97.85560692652783, + 60.92347329020029, + 95.06373555901035, + 10.459076785200573, + 38.39652806389496, + 93.98754752235924, + 2.674097763393879, + 55.13317581670067, + 7.582301863762164, + 90.09806831662421, + 58.14514233480025, + 21.943385602076205, + 27.92932198593363, + 74.47566475745501, + 14.17542596670296, + 15.389561103069639, + 41.3642203979707, + 88.59438854970502, + 88.44688860334703, + 41.153482806783, + 50.2290864945343, + 34.10564260603943, + 0.7424034693464421, + 61.12097393887227, + 76.37373840771609, + 80.8991284817294, + 47.42705320689268, + 28.569134063031377, + 68.80291780727555, + 6.536885696492634, + 99.42809667237239, + 26.556208653101297, + 71.57687317052836, + 91.36534014188913, + 32.79993959241312, + 86.37805535794408, + 86.92450485084261, + 35.928662360576006, + 38.117696258615275, + 37.17221959172431, + 95.04526977428316, + 81.51493159199833, + 78.1117600086244, + 23.855495304981734, + 14.249250030048232, + 85.34248556022068, + 54.11462641423464, + 41.94585409527539, + 61.360745526505156, + 10.202604593829879, + 85.59873910211499, + 1.1433096003252263, + 49.133044244585065, + 5.33807899658073, + 84.37593732205157, + 89.42694042115187, + 86.24444439199198, + 86.87943580063641, + 3.0371223103348943, + 57.990001803332504, + 36.42117115589164, + 82.30049871877813, + 11.537389940230213, + 2.509126719361099, + 74.41623867825336, + 62.084585352357934, + 42.75893110954671, + 18.88644163253499, + 14.518493698456114, + 82.66213840508154, + 1.9275778545741917, + 30.427285392258074, + 52.03609691289676, + 26.06998379475979, + 10.92230621343978, + 62.955762425602614, + 2.4270522294637775, + 68.6641402946546, + 65.49760315510792, + 28.497633956578028, + 90.60145587701412, + 53.71157720425989, + 17.53557934909914, + 58.64905674217455, + 82.43390795827756, + 87.82488039796571, + 99.01301413346881, + 55.28165393133199, + 34.431889213947144, + 6.323901151215217, + 56.94142959743016, + 10.249302116919623, + 2.8799263392111474, + 92.84520615746294, + 43.497949135082735, + 67.62304817464877, + 72.782963214927, + 87.62871282610479, + 64.14984241657884, + 39.30565524725675, + 35.58431350187402, + 9.663830741133228, + 1.3088268826258576, + 64.23181154701581, + 77.64591250935298, + 72.91632379363837, + 41.41837356713317, + 7.3562077326598025, + 93.90535576204974, + 42.90018756551315, + 18.626914593947852, + 78.811466444488, + 66.10209378179441, + 36.87343403984721, + 3.2797618222736413, + 18.105440053382992, + 11.214557418548976, + 95.84081920547837, + 82.50006083794057, + 8.964683148556219, + 81.13629890594473, + 71.11421704056077, + 74.16841444778932, + 12.368578373240846, + 36.23700968028151, + 19.62845142160984, + 25.012590674317924, + 40.60963298486795, + 97.67051488857919, + 16.693547982558997, + 96.87354152448792, + 14.627121216479722, + 89.44693750209464, + 39.51765682534695, + 55.26735408770266, + 79.01808378588527, + 22.8331922382237, + 95.16003510574137, + 13.026991873485017, + 31.001962639949376, + 28.195306836215885, + 53.99121306634911, + 27.103715042373466, + 12.028092698833415, + 91.65268208596046, + 4.076018273679938, + 13.789655511116461, + 92.11773645102372, + 17.518511500738654, + 86.06546161124385, + 4.217039396939793, + 34.79804069129575, + 23.18187816674192, + 37.44968290630716, + 83.80355791343179, + 15.869494995516131, + 57.87737396606523, + 20.442521754015985, + 41.90857912691563, + 95.2478569213477, + 34.678311972972466, + 7.793784557575956, + 91.83891212604826, + 49.762532901003084, + 77.1823740248659, + 20.99270377630118, + 73.97321549600382, + 10.067105272572563, + 90.77862288111608, + 51.333108459158105, + 11.5375311496841, + 68.57014778589479, + 76.23575480177827, + 48.434822180654265, + 37.63511652936173, + 17.9938446612816, + 25.89141478180631, + 10.83591192350889, + 56.70665030057931, + 58.2148020248683, + 94.95560630282687, + 0.24966375867493396, + 36.40697010455677, + 26.769109722992756, + 77.00419810256179, + 52.692259614182646, + 25.05617068141206, + 15.98386807081489, + 69.91570543662029, + 46.71484544285482, + 9.536452198715617, + 84.12715330181393, + 3.308385413061987, + 20.815929180614678, + 0.8341104306612834, + 90.01486022956574, + 95.61494163944116, + 3.5433615670734886, + 71.05993480381362, + 62.9928664875294, + 65.14277972902185, + 48.34721184945663, + 12.118301235628682, + 81.73013777597532, + 6.791269479503315, + 90.35364860658976, + 69.28563683748855, + 52.143206786933696, + 88.60409144682586, + 49.86494458397031, + 20.02365639075736, + 55.803961555379544, + 16.497947197881192, + 44.45150439552269, + 46.21576363894878, + 78.05094272470497, + 29.797562102348262, + 17.16813577131706, + 33.25443077999534, + 6.8277977703903865, + 65.71335308697243, + 75.65967226639236, + 15.000833642024347, + 71.62157980611583, + 8.587979480877294, + 99.68504655539087, + 54.060540205298715, + 22.99472798977761, + 21.85523507468494, + 44.0438621205276, + 83.56682060830694, + 56.66567741448808, + 39.19715330215858, + 54.06753560497853, + 54.92251744769386, + 56.25265943754316, + 68.40249046254637, + 86.704584852095, + 74.2566214079486, + 26.793375629817028, + 98.18413148981917, + 61.360381111923836, + 90.90446806290667, + 44.89342252950358, + 60.07155948641994, + 96.21029150146185, + 24.26209806655605, + 83.22316500389242, + 1.0234458994706985, + 17.451478452423018, + 80.03326488750226, + 35.29524913508343, + 13.726767429722786, + 71.5416278952078, + 14.001820212778792, + 27.955137649604268, + 20.120416532063945, + 82.59264842405298, + 73.28998065107852, + 64.41331658846539, + 16.23011447028645, + 6.889732688791373, + 36.16902708851997, + 49.14771741524725, + 49.373663929596404, + 66.39426428238544, + 30.31273529065055, + 34.35843089820653, + 36.53949917939029, + 24.04502414947457, + 54.17692370697191, + 21.180384476550763, + 89.14718278333365, + 29.693914777653298, + 1.847290172401106, + 84.9995311079775, + 67.64181228432484, + 96.25172968583604, + 38.33238646791588, + 91.944152651139, + 82.91883542786097, + 41.041577465980005, + 63.192620043139335, + 12.840047731207182, + 9.7693766408536, + 92.74591317717055, + 74.01523811724842, + 5.154603468860309, + 65.7461778231845, + 68.20071824755276, + 28.547987312906244, + 10.69051734997325, + 96.36247158065441, + 30.023438086780907, + 39.6974284171408, + 52.26105573684929, + 25.186151435144822, + 67.05552381346156, + 22.412167057860945, + 16.103601238978182, + 74.0560218630752, + 57.65007450229215, + 14.630655292238382, + 68.15031869781808, + 23.440854223926223, + 15.143141052842113, + 31.944925946330592, + 43.297306630114896, + 54.907904050721044, + 36.20521023815005, + 22.37545157388481, + 70.03789968689807, + 97.81582789588076, + 21.09267863093649, + 1.83672874166676, + 63.94707794521685, + 37.2350292941416, + 74.69687054819639, + 86.90547216089102, + 59.760759498261415, + 65.39545601990633, + 7.878933604434235, + 42.35959078239898, + 0.7479287548004421, + 72.59363968913144, + 61.116822277709616, + 24.023854724047233, + 81.79577016797812, + 37.07335998520279, + 43.35541092240377, + 70.58620343366887, + 40.19312495333431, + 31.967526037420445, + 76.9629157359946, + 33.17690359887706, + 97.42041275026632, + 40.50272772884858, + 28.823921664759023, + 55.993242945029564, + 40.21674866549335, + 16.5425722576097, + 0.6857252335768727, + 38.737066488698076, + 60.43971540525065, + 17.043099392708804, + 53.56848240280645, + 87.96425642264374, + 79.98686465476082, + 51.7166877785481, + 3.597470740348996, + 79.8871709412187, + 58.708506393240455, + 12.332960727209485, + 7.138572617057138, + 54.31246966911423, + 13.46974299775373, + 44.97302066217532, + 54.83668930750611, + 84.52684314207201, + 92.93775050356858, + 75.22398274520239, + 43.848742204183026, + 27.30894158976358, + 23.774889678523348, + 39.074812469348664, + 85.59905750478102, + 47.14444723373064, + 38.50729751302696, + 32.94139243218599, + 45.973067112135226, + 77.9385646564837, + 53.343121922234914, + 41.67947581239676, + 40.079313052941416, + 43.61479645621801, + 68.66798566808251, + 30.421935701498814, + 29.503294200126962, + 93.82566686500475, + 79.85782192964129, + 86.45323944051567, + 28.599365794341423, + 78.40649402523512, + 22.394590807278647, + 24.888507009336802, + 15.228037717341703, + 30.776485120922427, + 69.07830559363144, + 25.05378442985464, + 24.378748071246747, + 93.37193315999652, + 87.1210086667831, + 11.526734309566622, + 67.47123836589635, + 90.96890311579536, + 94.88151214738872, + 24.55522069997379, + 53.700425680030406, + 42.33495805746209, + 2.664372171138707, + 98.19955823422507, + 63.868805156584884, + 96.19950047680243, + 55.46153646887717, + 55.682448720902244, + 4.964966984416675, + 23.890127972683594, + 29.80276916748069, + 73.4467272127541, + 67.97892358819524, + 33.588263017353896, + 53.01383534157171, + 55.044859132708446, + 48.92996607980458, + 63.715325192525576, + 18.256421503363207, + 48.69001009944371, + 11.148511624665536, + 71.64927176070634, + 65.28366177023246, + 78.0903423262976, + 54.559776742895295, + 84.22759730170813, + 50.29633271037598, + 95.94525498801681, + 24.81795464959561, + 91.65604588326667, + 4.0643662036592865, + 85.6957161334284, + 89.57305273276819, + 20.555954873674843, + 79.41545391600441, + 34.48836403004534, + 55.4457138555014, + 82.8733957706798, + 53.37186291663867, + 15.611577638689667, + 91.07127376122158, + 19.464378699577757, + 61.38901810757369, + 94.53747763589675, + 36.823990432095854, + 92.11977212874464, + 41.084754170352056, + 62.92779296944009, + 2.621497241399351, + 13.597569548367815, + 61.05619935527435, + 76.40830220552252, + 55.69546420937795, + 36.89388642600503, + 68.60841259078822, + 47.262834746625984, + 7.265368383281845, + 93.86562297406826, + 43.59840096990071, + 7.110070635501808, + 14.663560831567768, + 98.95298734726397, + 5.7765875305137, + 98.46305959611685, + 85.64269807872566, + 45.167571436935226, + 95.88142446063647, + 23.226685940961378, + 19.29049832423012, + 68.46768490755646, + 76.0038531078043, + 2.7360336704267962, + 45.66442026204987, + 79.03943950851736, + 36.59974273585187, + 92.57666718430869, + 54.79863643264454, + 28.933613556596505, + 27.559991556652285, + 76.95747114097725, + 98.51573970856772, + 68.63104230971561, + 58.1092676826803, + 32.70311569848222, + 3.9472574838376073, + 64.99045073473746, + 11.227200881259359, + 81.96516140793531, + 14.727161696093338, + 39.6826953633971, + 45.521072794117146, + 44.34923653961804, + 56.033067987737105, + 2.7653047477482318, + 68.30615846083509, + 9.206589019281608, + 78.20783997287528, + 91.21794142241151, + 83.32879356682375, + 41.394520390940585, + 55.334752585427594, + 90.44507735321183, + 48.50158962000957, + 60.172591999652056, + 72.61203681682068, + 96.0703387553538, + 30.128955417218073, + 30.87313451480529, + 32.54505968277089, + 47.09529742546212, + 70.85593265528088, + 81.54222991424653, + 3.981036397307458, + 89.48291418073553, + 12.221056102590744, + 77.62001183843422, + 56.60998603060657, + 61.240543592555326, + 42.66213612057, + 82.57561143700694, + 65.1021975094917, + 33.44907912829827, + 94.42010541731372, + 24.993361552001815, + 70.42415878133085, + 53.18942821231432, + 79.95622916871, + 46.1525767715532, + 5.56961112406057, + 7.077628398112412, + 47.036938436638955, + 89.06350863955389, + 87.97346020627104, + 4.872621257802767, + 71.18116398376853, + 77.12359296351374, + 49.8738200280472, + 88.60429808924573, + 69.30599646035851, + 69.3782983366783, + 35.14652676358969, + 0.8354067262629328, + 34.70505186206596, + 32.41624004588483, + 14.594855471450085, + 26.9958644494548, + 32.14753073305735, + 30.157518146371054, + 18.93336112636499, + 23.286118374507303, + 49.451069665896476, + 54.27565588805133, + 17.10617921589247, + 96.58796725717075, + 36.7710245140606, + 95.49969083606445, + 11.827242824457507, + 5.530369668414004, + 94.8569307312123, + 50.60225178076551, + 21.818029153053175, + 22.526718316623196, + 35.7781706086556, + 99.59745010493336, + 54.96769069261802, + 91.72446234469069, + 33.664526712418166, + 41.73520555894811, + 8.631736870476503, + 23.234185592831725, + 99.66424405956391, + 10.06149610316358, + 78.81329784823875, + 9.607021689808072, + 47.995257725212184, + 22.080857516297204, + 63.76565525210718, + 32.082690178244455, + 99.32423240118635, + 16.861926299365837 + ], + "yaxis": "y" + }, + { + "hovertemplate": "variable=speed_kn
index=%{x}
value=%{y}", + "legendgroup": "speed_kn", + "line": { + "color": "#00cc96", + "dash": "solid" + }, + "marker": { + "symbol": "circle" + }, + "mode": "lines", + "name": "speed_kn", + "showlegend": true, + "type": "scattergl", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + "xaxis": "x", + "y": [ + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398, + 15.743817095192398 + ], + "yaxis": "y" + }, + { + "hovertemplate": "variable=draft_m
index=%{x}
value=%{y}", + "legendgroup": "draft_m", + "line": { + "color": "#ab63fa", + "dash": "solid" + }, + "marker": { + "symbol": "circle" + }, + "mode": "lines", + "name": "draft_m", + "showlegend": true, + "type": "scattergl", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + "xaxis": "x", + "y": [ + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274, + 4.548970786869274 + ], + "yaxis": "y" + } + ], + "layout": { + "legend": { + "title": { + "text": "variable" + }, + "tracegroupgap": 0 + }, + "margin": { + "t": 60 + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 1 + ], + "title": { + "text": "index" + } + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ], + "title": { + "text": "value" + } + } + } + } }, "metadata": {}, "output_type": "display_data" diff --git a/machinery-system-structure/MachSysS/__init__.py b/machinery-system-structure/MachSysS/__init__.py index 364e7ba..7bbb2ef 100644 --- a/machinery-system-structure/MachSysS/__init__.py +++ b/machinery-system-structure/MachSysS/__init__.py @@ -1 +1 @@ -__version__ = "0.6.4" +__version__ = "0.6.5" diff --git a/machinery-system-structure/MachSysS/_modidx.py b/machinery-system-structure/MachSysS/_modidx.py index 767d6ca..66b81eb 100644 --- a/machinery-system-structure/MachSysS/_modidx.py +++ b/machinery-system-structure/MachSysS/_modidx.py @@ -124,12 +124,20 @@ "converttofeems.html#convert_proto_battery_to_feems", "MachSysS/convert_to_feems.py", ), + "MachSysS.convert_to_feems.convert_proto_cogas_to_feems": ( + "converttofeems.html#convert_proto_cogas_to_feems", + "MachSysS/convert_to_feems.py", + ), + "MachSysS.convert_to_feems.convert_proto_coges_to_feems": ( + "converttofeems.html#convert_proto_coges_to_feems", + "MachSysS/convert_to_feems.py", + ), "MachSysS.convert_to_feems.convert_proto_curve1d_to_np_array": ( "converttofeems.html#convert_proto_curve1d_to_np_array", "MachSysS/convert_to_feems.py", ), - "MachSysS.convert_to_feems.convert_proto_efficiency_bsfc_to_np_array": ( - "converttofeems.html#convert_proto_efficiency_bsfc_to_np_array", + "MachSysS.convert_to_feems.convert_proto_efficiency_bsfc_power_to_np_array": ( + "converttofeems.html#convert_proto_efficiency_bsfc_power_to_np_array", "MachSysS/convert_to_feems.py", ), "MachSysS.convert_to_feems.convert_proto_electric_component_to_feems": ( diff --git a/machinery-system-structure/MachSysS/convert_to_feems.py b/machinery-system-structure/MachSysS/convert_to_feems.py index 031f40e..466f120 100644 --- a/machinery-system-structure/MachSysS/convert_to_feems.py +++ b/machinery-system-structure/MachSysS/convert_to_feems.py @@ -4,14 +4,16 @@ __all__ = [ "convert_proto_point_to_list", "convert_proto_curve1d_to_np_array", - "convert_proto_efficiency_bsfc_to_np_array", + "convert_proto_efficiency_bsfc_power_to_np_array", "convert_proto_electric_component_to_feems", "convert_proto_electric_machine_to_feems", "convert_proto_fuel_cell_system_to_feems", "convert_emission_curve_to_feems", "convert_nox_calculation_method", "convert_proto_engine_to_feems", + "convert_proto_cogas_to_feems", "convert_proto_genset_to_feems", + "convert_proto_coges_to_feems", "convert_proto_battery_to_feems", "convert_proto_battery_system_to_feems", "convert_proto_supercapacitor_to_feems", @@ -53,9 +55,10 @@ PTIPTO, SuperCapacitor, FuelCell, + COGES, ) from feems.components_model.component_electric import SerialSystemElectric, Genset -from feems.components_model.component_mechanical import EngineDualFuel +from feems.components_model.component_mechanical import COGAS, EngineDualFuel from feems.fuel import FuelOrigin, TypeFuel from feems.system_model import ( ElectricPowerSystem, @@ -87,15 +90,15 @@ def convert_proto_curve1d_to_np_array(curve: proto.Curve1D) -> np.ndarray: return np.array(list(map(convert_proto_point_to_list, curve.points))) -def convert_proto_efficiency_bsfc_to_np_array( - efficiency_bsfc: Union[proto.Efficiency, proto.BSFC] +def convert_proto_efficiency_bsfc_power_to_np_array( + efficiency_bsfc_power: Union[proto.Efficiency, proto.BSFC, proto.PowerCurve] ) -> np.ndarray: """Converts protobuf efficiency or bsfc to numpy array""" - if efficiency_bsfc.HasField("value"): - if efficiency_bsfc.value > 0: - return np.array([efficiency_bsfc.value]) - if efficiency_bsfc.HasField("curve"): - return convert_proto_curve1d_to_np_array(efficiency_bsfc.curve.curve) + if efficiency_bsfc_power.HasField("value"): + if efficiency_bsfc_power.value > 0: + return np.array([efficiency_bsfc_power.value]) + if efficiency_bsfc_power.HasField("curve"): + return convert_proto_curve1d_to_np_array(efficiency_bsfc_power.curve.curve) else: raise TypeError("The efficiency value or curve is not properly set.") @@ -110,7 +113,9 @@ def convert_proto_electric_component_to_feems( type_=component_type, name=proto_component.name, rated_power=proto_component.rated_power_kw, - eff_curve=convert_proto_efficiency_bsfc_to_np_array(proto_component.efficiency), + eff_curve=convert_proto_efficiency_bsfc_power_to_np_array( + proto_component.efficiency + ), power_type=power_type, switchboard_id=switchboard_id, ) @@ -128,7 +133,9 @@ def convert_proto_electric_machine_to_feems( rated_power=proto_component.rated_power_kw, rated_speed=proto_component.rated_speed_rpm, power_type=power_type, - eff_curve=convert_proto_efficiency_bsfc_to_np_array(proto_component.efficiency), + eff_curve=convert_proto_efficiency_bsfc_power_to_np_array( + proto_component.efficiency + ), switchboard_id=switchboard_id, ) @@ -143,7 +150,7 @@ def convert_proto_fuel_cell_system_to_feems( fuel_cell = FuelCell( name=subsystem.fuel_cell.name, rated_power=subsystem.fuel_cell.rated_power_kw, - eff_curve=convert_proto_efficiency_bsfc_to_np_array( + eff_curve=convert_proto_efficiency_bsfc_power_to_np_array( subsystem.fuel_cell.efficiency ), fuel_type=TypeFuel(subsystem.fuel_cell.fuel.fuel_type), @@ -178,13 +185,18 @@ def convert_emission_curve_to_feems( ) -def convert_nox_calculation_method(proto_engine: proto.Engine) -> NOxCalculationMethod: +def convert_nox_calculation_method( + proto_comp: Union[proto.Engine, proto.COGAS] +) -> NOxCalculationMethod: """Converts protobuf nox calculation type to feems nox calculation method""" - nox_calculation_method = NOxCalculationMethod.TIER_2 - if proto_engine.nox_calculation_method is not None: - name = proto.Engine.NOxCalculationMethod.Name( - proto_engine.nox_calculation_method - ) + if isinstance(proto_comp, proto.Engine): + nox_calculation_method = NOxCalculationMethod.TIER_2 + elif isinstance(proto_comp, proto.COGAS): + nox_calculation_method = NOxCalculationMethod.TIER_3 + else: + raise TypeError("The component should be either an engine or COGAS") + if proto_comp.nox_calculation_method is not None: + name = proto.Engine.NOxCalculationMethod.Name(proto_comp.nox_calculation_method) nox_calculation_method = NOxCalculationMethod[name] return nox_calculation_method @@ -209,8 +221,10 @@ def convert_proto_engine_to_feems( name=proto_engine.name, rated_power=proto_engine.rated_power_kw, rated_speed=proto_engine.rated_speed_rpm, - bsfc_curve=convert_proto_efficiency_bsfc_to_np_array(proto_engine.bsfc), - bspfc_curve=convert_proto_efficiency_bsfc_to_np_array( + bsfc_curve=convert_proto_efficiency_bsfc_power_to_np_array( + proto_engine.bsfc + ), + bspfc_curve=convert_proto_efficiency_bsfc_power_to_np_array( proto_engine.pilot_bsfc ), fuel_type=TypeFuel(proto_engine.main_fuel.fuel_type), @@ -225,7 +239,7 @@ def convert_proto_engine_to_feems( name=proto_engine.name, rated_power=proto_engine.rated_power_kw, rated_speed=proto_engine.rated_speed_rpm, - bsfc_curve=convert_proto_efficiency_bsfc_to_np_array(proto_engine.bsfc), + bsfc_curve=convert_proto_efficiency_bsfc_power_to_np_array(proto_engine.bsfc), fuel_type=TypeFuel(proto_engine.main_fuel.fuel_type), fuel_origin=FuelOrigin(proto_engine.main_fuel.fuel_origin), nox_calculation_method=nox_calculation_method, @@ -233,6 +247,39 @@ def convert_proto_engine_to_feems( ) +def convert_proto_cogas_to_feems( + proto_cogas: proto.COGAS, +) -> Engine: + """Converts protobuf COGAS message to feems COGAS component""" + nox_calculation_method = convert_nox_calculation_method(proto_cogas) + emission_curves = ( + [ + convert_emission_curve_to_feems(emission_curve) + for emission_curve in proto_cogas.emission_curves + ] + if proto_cogas.emission_curves + else None + ) + return COGAS( + name=proto_cogas.name, + rated_power=proto_cogas.rated_power_kw, + rated_speed=proto_cogas.rated_speed_rpm, + eff_curve=convert_proto_efficiency_bsfc_power_to_np_array( + proto_cogas.efficiency + ), + gas_turbine_power_curve=convert_proto_efficiency_bsfc_power_to_np_array( + proto_cogas.gas_turbine_power_curve + ), + steam_turbine_power_curve=convert_proto_efficiency_bsfc_power_to_np_array( + proto_cogas.steam_turbine_power_curve + ), + fuel_type=TypeFuel(proto_cogas.fuel.fuel_type), + fuel_origin=FuelOrigin(proto_cogas.fuel.fuel_origin), + nox_calculation_method=nox_calculation_method, + emissions_curves=emission_curves, + ) + + def convert_proto_genset_to_feems( subsystem: proto.Subsystem, switchboard_id: int ) -> Genset: @@ -257,6 +304,20 @@ def convert_proto_genset_to_feems( ) +def convert_proto_coges_to_feems( + subsystem: proto.Subsystem, switchboard_id: int +) -> COGES: + """Converts protobuf subsystem message to feems component""" + cogas = convert_proto_cogas_to_feems(proto_cogas == subsystem.cogas) + generator = convert_proto_electric_machine_to_feems( + proto_component=subsystem.electric_machine, + component_type=TypeComponent.SYNCHRONOUS_MACHINE, + power_type=TypePower.POWER_SOURCE, + switchboard_id=switchboard_id, + ) + return COGES(name=subsystem.name, cogas=cogas, generator=generator) + + def convert_proto_battery_to_feems( proto_component: proto.Battery, switchboard_id: int = 0 ) -> Battery: @@ -476,6 +537,12 @@ def convert_proto_switchboard_to_feems(switchboard: proto.Switchboard) -> Switch subsystem=subsystem, switchboard_id=switchboard_id ) ) + elif subsystem.component_type == proto.Subsystem.ComponentType.COGES: + components.append( + convert_proto_coges_to_feems( + subsystem=subsystem, switchboard_id=switchboard_id + ) + ) elif subsystem.component_type == proto.Subsystem.ComponentType.BATTERY_SYSTEM: components.append( convert_proto_battery_system_to_feems( @@ -555,8 +622,8 @@ def convert_proto_shaftline_to_feems( power_type=TypePower.POWER_TRANSMISSION, rated_power=sub_system.gear.rated_power_kw, rated_speed=sub_system.gear.rated_speed_rpm, - eff_curve=convert_proto_efficiency_bsfc_to_np_array( - efficiency_bsfc=sub_system.gear.efficiency + eff_curve=convert_proto_efficiency_bsfc_power_to_np_array( + efficiency_bsfc_power=sub_system.gear.efficiency ), ), shaft_line_id=shaft_line_id, @@ -601,8 +668,8 @@ def convert_proto_shaftline_to_feems( shaft_line_id=shaft_line_id, rated_power=sub_system.rated_power_kw, rated_speed=sub_system.rated_speed_rpm, - eff_curve=convert_proto_efficiency_bsfc_to_np_array( - efficiency_bsfc=sub_system.propeller.efficiency + eff_curve=convert_proto_efficiency_bsfc_power_to_np_array( + efficiency_bsfc_power=sub_system.propeller.efficiency ), ) ) diff --git a/machinery-system-structure/MachSysS/system_structure_pb2.py b/machinery-system-structure/MachSysS/system_structure_pb2.py index 621cfb3..2a6c613 100644 --- a/machinery-system-structure/MachSysS/system_structure_pb2.py +++ b/machinery-system-structure/MachSysS/system_structure_pb2.py @@ -14,7 +14,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x16system_structure.proto\x12\x18machinerySystemStructure"\x1d\n\x05Point\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01":\n\x07\x43urve1D\x12/\n\x06points\x18\x01 \x03(\x0b\x32\x1f.machinerySystemStructure.Point"_\n\tBSFCCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"e\n\x0f\x45\x66\x66iciencyCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"X\n\x04\x42SFC\x12\x32\n\x05\x63urve\x18\x01 \x01(\x0b\x32#.machinerySystemStructure.BSFCCurve\x12\x12\n\x05value\x18\x02 \x01(\x01H\x00\x88\x01\x01\x42\x08\n\x06_value"s\n\nEfficiency\x12=\n\x05\x63urve\x18\x01 \x01(\x0b\x32).machinerySystemStructure.EfficiencyCurveH\x00\x88\x01\x01\x12\x12\n\x05value\x18\x02 \x01(\x01H\x01\x88\x01\x01\x42\x08\n\x06_curveB\x08\n\x06_value"\x85\x01\n\x19PropulsionPowerTimeSeries\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x14\n\x0cpropulsor_id\x18\x03 \x01(\r\x12\x30\n\x05\x63urve\x18\x04 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"\x85\x01\n\x17\x41uxiliaryLoadTimeSeries\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x16\n\x0eswitchboard_id\x18\x03 \x01(\r\x12\x30\n\x05\x63urve\x18\x04 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"8\n\rAuxiliaryLoad\x12\x16\n\x0eswitchboard_id\x18\x01 \x01(\r\x12\x0f\n\x07load_kw\x18\x02 \x01(\x01"\xa2\x01\n\rEmissionCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D\x12=\n\remission_type\x18\x04 \x01(\x0e\x32&.machinerySystemStructure.EmissionType"\xd8\x01\n\x04Gear\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\ngear_ratio\x18\x02 \x01(\x01\x12\x16\n\x0erated_power_kw\x18\x03 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x04 \x01(\x01\x12\x38\n\nefficiency\x18\x05 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x06 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x07 \x01(\x01"x\n\x04\x46uel\x12\x35\n\tfuel_type\x18\x01 \x01(\x0e\x32".machinerySystemStructure.FuelType\x12\x39\n\x0b\x66uel_origin\x18\x02 \x01(\x0e\x32$.machinerySystemStructure.FuelOrigin"\x85\x06\n\x06\x45ngine\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x03 \x01(\x01\x12,\n\x04\x62sfc\x18\x04 \x01(\x0b\x32\x1e.machinerySystemStructure.BSFC\x12\x31\n\tmain_fuel\x18\x05 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12+\n#order_from_switchboard_or_shaftline\x18\x06 \x01(\r\x12\x32\n\npilot_bsfc\x18\x07 \x01(\x0b\x32\x1e.machinerySystemStructure.BSFC\x12\x32\n\npilot_fuel\x18\x08 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12U\n\x16nox_calculation_method\x18\t \x01(\x0e\x32\x35.machinerySystemStructure.Engine.NOxCalculationMethod\x12@\n\x0f\x65mission_curves\x18\n \x03(\x0b\x32\'.machinerySystemStructure.EmissionCurve\x12K\n\x11\x65ngine_cycle_type\x18\x0b \x01(\x0e\x32\x30.machinerySystemStructure.Engine.EngineCycleType\x12\x16\n\x0eunit_price_usd\x18\x0c \x01(\x01\x12\x15\n\rstart_delay_s\x18\r \x01(\x01\x12\x19\n\x11turn_off_power_kw\x18\x0e \x01(\x01"E\n\x14NOxCalculationMethod\x12\n\n\x06TIER_2\x10\x00\x12\n\n\x06TIER_1\x10\x01\x12\n\n\x06TIER_3\x10\x02\x12\t\n\x05\x43URVE\x10\x03"O\n\x0f\x45ngineCycleType\x12\x08\n\x04NONE\x10\x00\x12\n\n\x06\x44IESEL\x10\x01\x12\x08\n\x04OTTO\x10\x02\x12\x1c\n\x18LEAN_BURN_SPARK_IGNITION\x10\x03"\xcf\x01\n\x0f\x45lectricMachine\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x03 \x01(\x01\x12\x38\n\nefficiency\x18\x04 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x06 \x01(\x01"\x82\x03\n\x07\x42\x61ttery\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1b\n\x13\x65nergy_capacity_kwh\x18\x02 \x01(\x01\x12\x1d\n\x15rated_charging_rate_c\x18\x03 \x01(\x01\x12 \n\x18rated_discharging_rate_c\x18\x04 \x01(\x01\x12\x1b\n\x13\x65\x66\x66iciency_charging\x18\x05 \x01(\x01\x12\x1e\n\x16\x65\x66\x66iciency_discharging\x18\x06 \x01(\x01\x12\x1f\n\x17initial_state_of_charge\x18\x07 \x01(\x01\x12+\n#order_from_switchboard_or_shaftline\x18\x08 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\t \x01(\x01\x12&\n\x1eself_discharge_percent_per_day\x18\n \x01(\x01\x12\x1f\n\x17state_of_energy_minimum\x18\x0b \x01(\x01\x12\x1f\n\x17state_of_energy_maximum\x18\x0c \x01(\x01"\xb8\x01\n\x11\x45lectricComponent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x04 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x05 \x01(\x01"\xac\x02\n\x08\x46uelCell\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r\x12,\n\x04\x66uel\x18\x06 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12\x16\n\x0eunit_price_usd\x18\x07 \x01(\x01\x12\x16\n\x0enumber_modules\x18\x08 \x01(\r\x12\x1e\n\x16power_minimum_specific\x18\t \x01(\x01\x12\x15\n\rstart_delay_s\x18\n \x01(\x01"\x96\x01\n\tPropeller\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x38\n\nefficiency\x18\x02 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12\x14\n\x0cpropulsor_id\x18\x03 \x01(\r\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r"$\n\nBusBreaker\x12\x16\n\x0eswitchboard_to\x18\x01 \x01(\x05"\xf5\x01\n\x0eSuperCapacitor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1a\n\x12\x65nergy_capacity_wh\x18\x02 \x01(\x01\x12\x16\n\x0erated_power_kw\x18\x03 \x01(\x01\x12\x1b\n\x13\x65\x66\x66iciency_charging\x18\x04 \x01(\x01\x12\x1e\n\x16\x65\x66\x66iciency_discharging\x18\x05 \x01(\x01\x12\x1f\n\x17initial_state_of_charge\x18\x06 \x01(\x01\x12+\n#order_from_switchboard_or_shaftline\x18\x07 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x08 \x01(\x01"\xba\x01\n\x13MechanicalComponent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x04 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x05 \x01(\x01"\xba\r\n\tSubsystem\x12,\n\x04gear\x18\x01 \x01(\x0b\x32\x1e.machinerySystemStructure.Gear\x12\x30\n\x06\x65ngine\x18\x02 \x01(\x0b\x32 .machinerySystemStructure.Engine\x12\x43\n\x10\x65lectric_machine\x18\x03 \x01(\x0b\x32).machinerySystemStructure.ElectricMachine\x12@\n\x0btransformer\x18\x04 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12?\n\nconverter1\x18\x05 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12?\n\nconverter2\x18\x06 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12\x32\n\x07\x62\x61ttery\x18\x07 \x01(\x0b\x32!.machinerySystemStructure.Battery\x12\x35\n\tfuel_cell\x18\x08 \x01(\x0b\x32".machinerySystemStructure.FuelCell\x12\x36\n\tpropeller\x18\t \x01(\x0b\x32#.machinerySystemStructure.Propeller\x12\x39\n\x0b\x62us_breaker\x18\n \x01(\x0b\x32$.machinerySystemStructure.BusBreaker\x12@\n\x0esupercapacitor\x18\x0b \x01(\x0b\x32(.machinerySystemStructure.SuperCapacitor\x12?\n\nother_load\x18\x0c \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12\x41\n\npower_type\x18\r \x01(\x0e\x32-.machinerySystemStructure.Subsystem.PowerType\x12I\n\x0e\x63omponent_type\x18\x0e \x01(\x0e\x32\x31.machinerySystemStructure.Subsystem.ComponentType\x12\x0c\n\x04name\x18\x0f \x01(\t\x12\x16\n\x0erated_power_kw\x18\x10 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x11 \x01(\x01\x12-\n%ramp_up_rate_limit_percent_per_second\x18\x12 \x01(\x01\x12/\n\'ramp_down_rate_limit_percent_per_second\x18\x13 \x01(\x01\x12\x17\n\x0f\x62\x61se_load_order\x18\x14 \x01(\r"s\n\tPowerType\x12\t\n\x05NONE1\x10\x00\x12\x10\n\x0cPOWER_SOURCE\x10\x01\x12\x12\n\x0ePOWER_CONSUMER\x10\x02\x12\x0b\n\x07PTI_PTO\x10\x03\x12\x12\n\x0e\x45NERGY_STORAGE\x10\x04\x12\x14\n\x10SHORE_CONNECTION\x10\x05"\xa7\x04\n\rComponentType\x12\x08\n\x04NONE\x10\x00\x12\x0f\n\x0bMAIN_ENGINE\x10\x01\x12\x14\n\x10\x41UXILIARY_ENGINE\x10\x02\x12\r\n\tGENERATOR\x10\x03\x12\x14\n\x10PROPULSION_DRIVE\x10\x04\x12\x0e\n\nOTHER_LOAD\x10\x05\x12\x12\n\x0ePTI_PTO_SYSTEM\x10\x06\x12\x12\n\x0e\x42\x41TTERY_SYSTEM\x10\x07\x12\x14\n\x10\x46UEL_CELL_SYSTEM\x10\x08\x12\r\n\tRECTIFIER\x10\t\x12\x1c\n\x18MAIN_ENGINE_WITH_GEARBOX\x10\n\x12\x12\n\x0e\x45LECTRIC_MOTOR\x10\x0b\x12\n\n\x06GENSET\x10\x0c\x12\x0f\n\x0bTRANSFORMER\x10\r\x12\x0c\n\x08INVERTER\x10\x0e\x12\x13\n\x0f\x43IRCUIT_BREAKER\x10\x0f\x12\x14\n\x10\x41\x43TIVE_FRONT_END\x10\x10\x12\x13\n\x0fPOWER_CONVERTER\x10\x11\x12\x17\n\x13SYNCHRONOUS_MACHINE\x10\x12\x12\x15\n\x11INDUCTION_MACHINE\x10\x13\x12\x0b\n\x07GEARBOX\x10\x14\x12\r\n\tFUEL_CELL\x10\x15\x12\x12\n\x0ePROPELLER_LOAD\x10\x16\x12\x19\n\x15OTHER_MECHANICAL_LOAD\x10\x17\x12\x0b\n\x07\x42\x41TTERY\x10\x18\x12\x12\n\x0eSUPERCAPACITOR\x10\x19\x12\x19\n\x15SUPERCAPACITOR_SYSTEM\x10\x1a\x12\x0f\n\x0bSHORE_POWER\x10\x1b"^\n\x0bSwitchboard\x12\x16\n\x0eswitchboard_id\x18\x01 \x01(\r\x12\x37\n\nsubsystems\x18\x02 \x03(\x0b\x32#.machinerySystemStructure.Subsystem"[\n\tShaftLine\x12\x15\n\rshaft_line_id\x18\x01 \x01(\r\x12\x37\n\nsubsystems\x18\x02 \x03(\x0b\x32#.machinerySystemStructure.Subsystem"L\n\x10MechanicalSystem\x12\x38\n\x0bshaft_lines\x18\x01 \x03(\x0b\x32#.machinerySystemStructure.ShaftLine"M\n\x0e\x45lectricSystem\x12;\n\x0cswitchboards\x18\x01 \x03(\x0b\x32%.machinerySystemStructure.Switchboard"Y\n\x0b\x46uelStorage\x12\x35\n\tfuel_type\x18\x01 \x01(\x0e\x32".machinerySystemStructure.FuelType\x12\x13\n\x0b\x63\x61pacity_kg\x18\x02 \x01(\x01"\xfe\x03\n\x0fMachinerySystem\x12\x0c\n\x04name\x18\x01 \x01(\t\x12Q\n\x0fpropulsion_type\x18\x02 \x01(\x0e\x32\x38.machinerySystemStructure.MachinerySystem.PropulsionType\x12;\n\x0c\x66uel_storage\x18\x03 \x03(\x0b\x32%.machinerySystemStructure.FuelStorage\x12.\n&maximum_allowed_genset_load_percentage\x18\x04 \x01(\x01\x12\x45\n\x11mechanical_system\x18\x05 \x01(\x0b\x32*.machinerySystemStructure.MechanicalSystem\x12\x41\n\x0f\x65lectric_system\x18\x06 \x01(\x0b\x32(.machinerySystemStructure.ElectricSystem\x12\x31\n)maximum_allowed_fuel_cell_load_percentage\x18\x07 \x01(\x01\x12$\n\x1c\x61verage_base_load_percentage\x18\x08 \x01(\x01":\n\x0ePropulsionType\x12\x0e\n\nMECHANICAL\x10\x00\x12\x0c\n\x08\x45LECTRIC\x10\x01\x12\n\n\x06HYBRID\x10\x02*T\n\x0c\x45missionType\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03SOX\x10\x01\x12\x07\n\x03NOX\x10\x02\x12\x06\n\x02\x43O\x10\x03\x12\x06\n\x02PM\x10\x04\x12\x06\n\x02HC\x10\x05\x12\x07\n\x03\x43H4\x10\x06\x12\x07\n\x03N2O\x10\x07*\x90\x01\n\x08\x46uelType\x12\n\n\x06\x44IESEL\x10\x00\x12\x07\n\x03HFO\x10\x01\x12\x0f\n\x0bNATURAL_GAS\x10\x02\x12\x0c\n\x08HYDROGEN\x10\x03\x12\x0b\n\x07\x41MMONIA\x10\x04\x12\x0f\n\x0bLPG_PROPANE\x10\x05\x12\x0e\n\nLPG_BUTANE\x10\x06\x12\x0b\n\x07\x45THANOL\x10\x07\x12\x0c\n\x08METHANOL\x10\x08\x12\x07\n\x03LFO\x10\t*C\n\nFuelOrigin\x12\t\n\x05NONE1\x10\x00\x12\n\n\x06\x46OSSIL\x10\x01\x12\x07\n\x03\x42IO\x10\x02\x12\x15\n\x11RENEWABLE_NON_BIO\x10\x03*E\n\x0f\x46uelSpecifiedBy\x12\t\n\x05NONE2\x10\x00\x12\x14\n\x10\x46UEL_EU_MARITIME\x10\x01\x12\x07\n\x03IMO\x10\x02\x12\x08\n\x04USER\x10\x03\x62\x06proto3' + b'\n\x16system_structure.proto\x12\x18machinerySystemStructure"\x1d\n\x05Point\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01":\n\x07\x43urve1D\x12/\n\x06points\x18\x01 \x03(\x0b\x32\x1f.machinerySystemStructure.Point"_\n\tBSFCCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"e\n\x0f\x45\x66\x66iciencyCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"X\n\x04\x42SFC\x12\x32\n\x05\x63urve\x18\x01 \x01(\x0b\x32#.machinerySystemStructure.BSFCCurve\x12\x12\n\x05value\x18\x02 \x01(\x01H\x00\x88\x01\x01\x42\x08\n\x06_value"s\n\nEfficiency\x12=\n\x05\x63urve\x18\x01 \x01(\x0b\x32).machinerySystemStructure.EfficiencyCurveH\x00\x88\x01\x01\x12\x12\n\x05value\x18\x02 \x01(\x01H\x01\x88\x01\x01\x42\x08\n\x06_curveB\x08\n\x06_value"`\n\nPowerCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"\x85\x01\n\x19PropulsionPowerTimeSeries\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x14\n\x0cpropulsor_id\x18\x03 \x01(\r\x12\x30\n\x05\x63urve\x18\x04 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"\x85\x01\n\x17\x41uxiliaryLoadTimeSeries\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x16\n\x0eswitchboard_id\x18\x03 \x01(\r\x12\x30\n\x05\x63urve\x18\x04 \x01(\x0b\x32!.machinerySystemStructure.Curve1D"8\n\rAuxiliaryLoad\x12\x16\n\x0eswitchboard_id\x18\x01 \x01(\r\x12\x0f\n\x07load_kw\x18\x02 \x01(\x01"\xa2\x01\n\rEmissionCurve\x12\x0f\n\x07x_label\x18\x01 \x01(\t\x12\x0f\n\x07y_label\x18\x02 \x01(\t\x12\x30\n\x05\x63urve\x18\x03 \x01(\x0b\x32!.machinerySystemStructure.Curve1D\x12=\n\remission_type\x18\x04 \x01(\x0e\x32&.machinerySystemStructure.EmissionType"\xd8\x01\n\x04Gear\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\ngear_ratio\x18\x02 \x01(\x01\x12\x16\n\x0erated_power_kw\x18\x03 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x04 \x01(\x01\x12\x38\n\nefficiency\x18\x05 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x06 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x07 \x01(\x01"x\n\x04\x46uel\x12\x35\n\tfuel_type\x18\x01 \x01(\x0e\x32".machinerySystemStructure.FuelType\x12\x39\n\x0b\x66uel_origin\x18\x02 \x01(\x0e\x32$.machinerySystemStructure.FuelOrigin"\x85\x06\n\x06\x45ngine\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x03 \x01(\x01\x12,\n\x04\x62sfc\x18\x04 \x01(\x0b\x32\x1e.machinerySystemStructure.BSFC\x12\x31\n\tmain_fuel\x18\x05 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12+\n#order_from_switchboard_or_shaftline\x18\x06 \x01(\r\x12\x32\n\npilot_bsfc\x18\x07 \x01(\x0b\x32\x1e.machinerySystemStructure.BSFC\x12\x32\n\npilot_fuel\x18\x08 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12U\n\x16nox_calculation_method\x18\t \x01(\x0e\x32\x35.machinerySystemStructure.Engine.NOxCalculationMethod\x12@\n\x0f\x65mission_curves\x18\n \x03(\x0b\x32\'.machinerySystemStructure.EmissionCurve\x12K\n\x11\x65ngine_cycle_type\x18\x0b \x01(\x0e\x32\x30.machinerySystemStructure.Engine.EngineCycleType\x12\x16\n\x0eunit_price_usd\x18\x0c \x01(\x01\x12\x15\n\rstart_delay_s\x18\r \x01(\x01\x12\x19\n\x11turn_off_power_kw\x18\x0e \x01(\x01"E\n\x14NOxCalculationMethod\x12\n\n\x06TIER_2\x10\x00\x12\n\n\x06TIER_1\x10\x01\x12\n\n\x06TIER_3\x10\x02\x12\t\n\x05\x43URVE\x10\x03"O\n\x0f\x45ngineCycleType\x12\x08\n\x04NONE\x10\x00\x12\n\n\x06\x44IESEL\x10\x01\x12\x08\n\x04OTTO\x10\x02\x12\x1c\n\x18LEAN_BURN_SPARK_IGNITION\x10\x03"\xce\x04\n\x05\x43OGAS\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x03 \x01(\x01\x12\x38\n\nefficiency\x18\x04 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12\x45\n\x17gas_turbine_power_curve\x18\x05 \x01(\x0b\x32$.machinerySystemStructure.PowerCurve\x12G\n\x19steam_turbine_power_curve\x18\x06 \x01(\x0b\x32$.machinerySystemStructure.PowerCurve\x12,\n\x04\x66uel\x18\x07 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12+\n#order_from_switchboard_or_shaftline\x18\x08 \x01(\r\x12U\n\x16nox_calculation_method\x18\t \x01(\x0e\x32\x35.machinerySystemStructure.Engine.NOxCalculationMethod\x12@\n\x0f\x65mission_curves\x18\n \x03(\x0b\x32\'.machinerySystemStructure.EmissionCurve\x12\x16\n\x0eunit_price_usd\x18\x0b \x01(\x01\x12\x15\n\rstart_delay_s\x18\x0c \x01(\x01\x12\x19\n\x11turn_off_power_kw\x18\r \x01(\x01"\xcf\x01\n\x0f\x45lectricMachine\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x03 \x01(\x01\x12\x38\n\nefficiency\x18\x04 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x06 \x01(\x01"\x82\x03\n\x07\x42\x61ttery\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1b\n\x13\x65nergy_capacity_kwh\x18\x02 \x01(\x01\x12\x1d\n\x15rated_charging_rate_c\x18\x03 \x01(\x01\x12 \n\x18rated_discharging_rate_c\x18\x04 \x01(\x01\x12\x1b\n\x13\x65\x66\x66iciency_charging\x18\x05 \x01(\x01\x12\x1e\n\x16\x65\x66\x66iciency_discharging\x18\x06 \x01(\x01\x12\x1f\n\x17initial_state_of_charge\x18\x07 \x01(\x01\x12+\n#order_from_switchboard_or_shaftline\x18\x08 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\t \x01(\x01\x12&\n\x1eself_discharge_percent_per_day\x18\n \x01(\x01\x12\x1f\n\x17state_of_energy_minimum\x18\x0b \x01(\x01\x12\x1f\n\x17state_of_energy_maximum\x18\x0c \x01(\x01"\xb8\x01\n\x11\x45lectricComponent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x04 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x05 \x01(\x01"\xac\x02\n\x08\x46uelCell\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r\x12,\n\x04\x66uel\x18\x06 \x01(\x0b\x32\x1e.machinerySystemStructure.Fuel\x12\x16\n\x0eunit_price_usd\x18\x07 \x01(\x01\x12\x16\n\x0enumber_modules\x18\x08 \x01(\r\x12\x1e\n\x16power_minimum_specific\x18\t \x01(\x01\x12\x15\n\rstart_delay_s\x18\n \x01(\x01"\x96\x01\n\tPropeller\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x38\n\nefficiency\x18\x02 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12\x14\n\x0cpropulsor_id\x18\x03 \x01(\r\x12+\n#order_from_switchboard_or_shaftline\x18\x05 \x01(\r"$\n\nBusBreaker\x12\x16\n\x0eswitchboard_to\x18\x01 \x01(\x05"\xf5\x01\n\x0eSuperCapacitor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1a\n\x12\x65nergy_capacity_wh\x18\x02 \x01(\x01\x12\x16\n\x0erated_power_kw\x18\x03 \x01(\x01\x12\x1b\n\x13\x65\x66\x66iciency_charging\x18\x04 \x01(\x01\x12\x1e\n\x16\x65\x66\x66iciency_discharging\x18\x05 \x01(\x01\x12\x1f\n\x17initial_state_of_charge\x18\x06 \x01(\x01\x12+\n#order_from_switchboard_or_shaftline\x18\x07 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x08 \x01(\x01"\xba\x01\n\x13MechanicalComponent\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x02 \x01(\x01\x12\x38\n\nefficiency\x18\x03 \x01(\x0b\x32$.machinerySystemStructure.Efficiency\x12+\n#order_from_switchboard_or_shaftline\x18\x04 \x01(\r\x12\x16\n\x0eunit_price_usd\x18\x05 \x01(\x01"\x80\x0e\n\tSubsystem\x12,\n\x04gear\x18\x01 \x01(\x0b\x32\x1e.machinerySystemStructure.Gear\x12\x30\n\x06\x65ngine\x18\x02 \x01(\x0b\x32 .machinerySystemStructure.Engine\x12\x43\n\x10\x65lectric_machine\x18\x03 \x01(\x0b\x32).machinerySystemStructure.ElectricMachine\x12@\n\x0btransformer\x18\x04 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12?\n\nconverter1\x18\x05 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12?\n\nconverter2\x18\x06 \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12\x32\n\x07\x62\x61ttery\x18\x07 \x01(\x0b\x32!.machinerySystemStructure.Battery\x12\x35\n\tfuel_cell\x18\x08 \x01(\x0b\x32".machinerySystemStructure.FuelCell\x12\x36\n\tpropeller\x18\t \x01(\x0b\x32#.machinerySystemStructure.Propeller\x12\x39\n\x0b\x62us_breaker\x18\n \x01(\x0b\x32$.machinerySystemStructure.BusBreaker\x12@\n\x0esupercapacitor\x18\x0b \x01(\x0b\x32(.machinerySystemStructure.SuperCapacitor\x12?\n\nother_load\x18\x0c \x01(\x0b\x32+.machinerySystemStructure.ElectricComponent\x12.\n\x05\x63ogas\x18\r \x01(\x0b\x32\x1f.machinerySystemStructure.COGAS\x12\x41\n\npower_type\x18\x0e \x01(\x0e\x32-.machinerySystemStructure.Subsystem.PowerType\x12I\n\x0e\x63omponent_type\x18\x0f \x01(\x0e\x32\x31.machinerySystemStructure.Subsystem.ComponentType\x12\x0c\n\x04name\x18\x10 \x01(\t\x12\x16\n\x0erated_power_kw\x18\x11 \x01(\x01\x12\x17\n\x0frated_speed_rpm\x18\x12 \x01(\x01\x12-\n%ramp_up_rate_limit_percent_per_second\x18\x13 \x01(\x01\x12/\n\'ramp_down_rate_limit_percent_per_second\x18\x14 \x01(\x01\x12\x17\n\x0f\x62\x61se_load_order\x18\x15 \x01(\r"s\n\tPowerType\x12\t\n\x05NONE1\x10\x00\x12\x10\n\x0cPOWER_SOURCE\x10\x01\x12\x12\n\x0ePOWER_CONSUMER\x10\x02\x12\x0b\n\x07PTI_PTO\x10\x03\x12\x12\n\x0e\x45NERGY_STORAGE\x10\x04\x12\x14\n\x10SHORE_CONNECTION\x10\x05"\xbd\x04\n\rComponentType\x12\x08\n\x04NONE\x10\x00\x12\x0f\n\x0bMAIN_ENGINE\x10\x01\x12\x14\n\x10\x41UXILIARY_ENGINE\x10\x02\x12\r\n\tGENERATOR\x10\x03\x12\x14\n\x10PROPULSION_DRIVE\x10\x04\x12\x0e\n\nOTHER_LOAD\x10\x05\x12\x12\n\x0ePTI_PTO_SYSTEM\x10\x06\x12\x12\n\x0e\x42\x41TTERY_SYSTEM\x10\x07\x12\x14\n\x10\x46UEL_CELL_SYSTEM\x10\x08\x12\r\n\tRECTIFIER\x10\t\x12\x1c\n\x18MAIN_ENGINE_WITH_GEARBOX\x10\n\x12\x12\n\x0e\x45LECTRIC_MOTOR\x10\x0b\x12\n\n\x06GENSET\x10\x0c\x12\x0f\n\x0bTRANSFORMER\x10\r\x12\x0c\n\x08INVERTER\x10\x0e\x12\x13\n\x0f\x43IRCUIT_BREAKER\x10\x0f\x12\x14\n\x10\x41\x43TIVE_FRONT_END\x10\x10\x12\x13\n\x0fPOWER_CONVERTER\x10\x11\x12\x17\n\x13SYNCHRONOUS_MACHINE\x10\x12\x12\x15\n\x11INDUCTION_MACHINE\x10\x13\x12\x0b\n\x07GEARBOX\x10\x14\x12\r\n\tFUEL_CELL\x10\x15\x12\x12\n\x0ePROPELLER_LOAD\x10\x16\x12\x19\n\x15OTHER_MECHANICAL_LOAD\x10\x17\x12\x0b\n\x07\x42\x41TTERY\x10\x18\x12\x12\n\x0eSUPERCAPACITOR\x10\x19\x12\x19\n\x15SUPERCAPACITOR_SYSTEM\x10\x1a\x12\x0f\n\x0bSHORE_POWER\x10\x1b\x12\t\n\x05\x43OGAS\x10\x1c\x12\t\n\x05\x43OGES\x10\x1d"^\n\x0bSwitchboard\x12\x16\n\x0eswitchboard_id\x18\x01 \x01(\r\x12\x37\n\nsubsystems\x18\x02 \x03(\x0b\x32#.machinerySystemStructure.Subsystem"[\n\tShaftLine\x12\x15\n\rshaft_line_id\x18\x01 \x01(\r\x12\x37\n\nsubsystems\x18\x02 \x03(\x0b\x32#.machinerySystemStructure.Subsystem"L\n\x10MechanicalSystem\x12\x38\n\x0bshaft_lines\x18\x01 \x03(\x0b\x32#.machinerySystemStructure.ShaftLine"M\n\x0e\x45lectricSystem\x12;\n\x0cswitchboards\x18\x01 \x03(\x0b\x32%.machinerySystemStructure.Switchboard"Y\n\x0b\x46uelStorage\x12\x35\n\tfuel_type\x18\x01 \x01(\x0e\x32".machinerySystemStructure.FuelType\x12\x13\n\x0b\x63\x61pacity_kg\x18\x02 \x01(\x01"\xfe\x03\n\x0fMachinerySystem\x12\x0c\n\x04name\x18\x01 \x01(\t\x12Q\n\x0fpropulsion_type\x18\x02 \x01(\x0e\x32\x38.machinerySystemStructure.MachinerySystem.PropulsionType\x12;\n\x0c\x66uel_storage\x18\x03 \x03(\x0b\x32%.machinerySystemStructure.FuelStorage\x12.\n&maximum_allowed_genset_load_percentage\x18\x04 \x01(\x01\x12\x45\n\x11mechanical_system\x18\x05 \x01(\x0b\x32*.machinerySystemStructure.MechanicalSystem\x12\x41\n\x0f\x65lectric_system\x18\x06 \x01(\x0b\x32(.machinerySystemStructure.ElectricSystem\x12\x31\n)maximum_allowed_fuel_cell_load_percentage\x18\x07 \x01(\x01\x12$\n\x1c\x61verage_base_load_percentage\x18\x08 \x01(\x01":\n\x0ePropulsionType\x12\x0e\n\nMECHANICAL\x10\x00\x12\x0c\n\x08\x45LECTRIC\x10\x01\x12\n\n\x06HYBRID\x10\x02*T\n\x0c\x45missionType\x12\x08\n\x04NONE\x10\x00\x12\x07\n\x03SOX\x10\x01\x12\x07\n\x03NOX\x10\x02\x12\x06\n\x02\x43O\x10\x03\x12\x06\n\x02PM\x10\x04\x12\x06\n\x02HC\x10\x05\x12\x07\n\x03\x43H4\x10\x06\x12\x07\n\x03N2O\x10\x07*\x90\x01\n\x08\x46uelType\x12\n\n\x06\x44IESEL\x10\x00\x12\x07\n\x03HFO\x10\x01\x12\x0f\n\x0bNATURAL_GAS\x10\x02\x12\x0c\n\x08HYDROGEN\x10\x03\x12\x0b\n\x07\x41MMONIA\x10\x04\x12\x0f\n\x0bLPG_PROPANE\x10\x05\x12\x0e\n\nLPG_BUTANE\x10\x06\x12\x0b\n\x07\x45THANOL\x10\x07\x12\x0c\n\x08METHANOL\x10\x08\x12\x07\n\x03LFO\x10\t*C\n\nFuelOrigin\x12\t\n\x05NONE1\x10\x00\x12\n\n\x06\x46OSSIL\x10\x01\x12\x07\n\x03\x42IO\x10\x02\x12\x15\n\x11RENEWABLE_NON_BIO\x10\x03*E\n\x0f\x46uelSpecifiedBy\x12\t\n\x05NONE2\x10\x00\x12\x14\n\x10\x46UEL_EU_MARITIME\x10\x01\x12\x07\n\x03IMO\x10\x02\x12\x08\n\x04USER\x10\x03\x62\x06proto3' ) _globals = globals() @@ -22,14 +22,14 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "system_structure_pb2", _globals) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None - _globals["_EMISSIONTYPE"]._serialized_start = 6554 - _globals["_EMISSIONTYPE"]._serialized_end = 6638 - _globals["_FUELTYPE"]._serialized_start = 6641 - _globals["_FUELTYPE"]._serialized_end = 6785 - _globals["_FUELORIGIN"]._serialized_start = 6787 - _globals["_FUELORIGIN"]._serialized_end = 6854 - _globals["_FUELSPECIFIEDBY"]._serialized_start = 6856 - _globals["_FUELSPECIFIEDBY"]._serialized_end = 6925 + _globals["_EMISSIONTYPE"]._serialized_start = 7315 + _globals["_EMISSIONTYPE"]._serialized_end = 7399 + _globals["_FUELTYPE"]._serialized_start = 7402 + _globals["_FUELTYPE"]._serialized_end = 7546 + _globals["_FUELORIGIN"]._serialized_start = 7548 + _globals["_FUELORIGIN"]._serialized_end = 7615 + _globals["_FUELSPECIFIEDBY"]._serialized_start = 7617 + _globals["_FUELSPECIFIEDBY"]._serialized_end = 7686 _globals["_POINT"]._serialized_start = 52 _globals["_POINT"]._serialized_end = 81 _globals["_CURVE1D"]._serialized_start = 83 @@ -42,58 +42,62 @@ _globals["_BSFC"]._serialized_end = 431 _globals["_EFFICIENCY"]._serialized_start = 433 _globals["_EFFICIENCY"]._serialized_end = 548 - _globals["_PROPULSIONPOWERTIMESERIES"]._serialized_start = 551 - _globals["_PROPULSIONPOWERTIMESERIES"]._serialized_end = 684 - _globals["_AUXILIARYLOADTIMESERIES"]._serialized_start = 687 - _globals["_AUXILIARYLOADTIMESERIES"]._serialized_end = 820 - _globals["_AUXILIARYLOAD"]._serialized_start = 822 - _globals["_AUXILIARYLOAD"]._serialized_end = 878 - _globals["_EMISSIONCURVE"]._serialized_start = 881 - _globals["_EMISSIONCURVE"]._serialized_end = 1043 - _globals["_GEAR"]._serialized_start = 1046 - _globals["_GEAR"]._serialized_end = 1262 - _globals["_FUEL"]._serialized_start = 1264 - _globals["_FUEL"]._serialized_end = 1384 - _globals["_ENGINE"]._serialized_start = 1387 - _globals["_ENGINE"]._serialized_end = 2160 - _globals["_ENGINE_NOXCALCULATIONMETHOD"]._serialized_start = 2010 - _globals["_ENGINE_NOXCALCULATIONMETHOD"]._serialized_end = 2079 - _globals["_ENGINE_ENGINECYCLETYPE"]._serialized_start = 2081 - _globals["_ENGINE_ENGINECYCLETYPE"]._serialized_end = 2160 - _globals["_ELECTRICMACHINE"]._serialized_start = 2163 - _globals["_ELECTRICMACHINE"]._serialized_end = 2370 - _globals["_BATTERY"]._serialized_start = 2373 - _globals["_BATTERY"]._serialized_end = 2759 - _globals["_ELECTRICCOMPONENT"]._serialized_start = 2762 - _globals["_ELECTRICCOMPONENT"]._serialized_end = 2946 - _globals["_FUELCELL"]._serialized_start = 2949 - _globals["_FUELCELL"]._serialized_end = 3249 - _globals["_PROPELLER"]._serialized_start = 3252 - _globals["_PROPELLER"]._serialized_end = 3402 - _globals["_BUSBREAKER"]._serialized_start = 3404 - _globals["_BUSBREAKER"]._serialized_end = 3440 - _globals["_SUPERCAPACITOR"]._serialized_start = 3443 - _globals["_SUPERCAPACITOR"]._serialized_end = 3688 - _globals["_MECHANICALCOMPONENT"]._serialized_start = 3691 - _globals["_MECHANICALCOMPONENT"]._serialized_end = 3877 - _globals["_SUBSYSTEM"]._serialized_start = 3880 - _globals["_SUBSYSTEM"]._serialized_end = 5602 - _globals["_SUBSYSTEM_POWERTYPE"]._serialized_start = 4933 - _globals["_SUBSYSTEM_POWERTYPE"]._serialized_end = 5048 - _globals["_SUBSYSTEM_COMPONENTTYPE"]._serialized_start = 5051 - _globals["_SUBSYSTEM_COMPONENTTYPE"]._serialized_end = 5602 - _globals["_SWITCHBOARD"]._serialized_start = 5604 - _globals["_SWITCHBOARD"]._serialized_end = 5698 - _globals["_SHAFTLINE"]._serialized_start = 5700 - _globals["_SHAFTLINE"]._serialized_end = 5791 - _globals["_MECHANICALSYSTEM"]._serialized_start = 5793 - _globals["_MECHANICALSYSTEM"]._serialized_end = 5869 - _globals["_ELECTRICSYSTEM"]._serialized_start = 5871 - _globals["_ELECTRICSYSTEM"]._serialized_end = 5948 - _globals["_FUELSTORAGE"]._serialized_start = 5950 - _globals["_FUELSTORAGE"]._serialized_end = 6039 - _globals["_MACHINERYSYSTEM"]._serialized_start = 6042 - _globals["_MACHINERYSYSTEM"]._serialized_end = 6552 - _globals["_MACHINERYSYSTEM_PROPULSIONTYPE"]._serialized_start = 6494 - _globals["_MACHINERYSYSTEM_PROPULSIONTYPE"]._serialized_end = 6552 + _globals["_POWERCURVE"]._serialized_start = 550 + _globals["_POWERCURVE"]._serialized_end = 646 + _globals["_PROPULSIONPOWERTIMESERIES"]._serialized_start = 649 + _globals["_PROPULSIONPOWERTIMESERIES"]._serialized_end = 782 + _globals["_AUXILIARYLOADTIMESERIES"]._serialized_start = 785 + _globals["_AUXILIARYLOADTIMESERIES"]._serialized_end = 918 + _globals["_AUXILIARYLOAD"]._serialized_start = 920 + _globals["_AUXILIARYLOAD"]._serialized_end = 976 + _globals["_EMISSIONCURVE"]._serialized_start = 979 + _globals["_EMISSIONCURVE"]._serialized_end = 1141 + _globals["_GEAR"]._serialized_start = 1144 + _globals["_GEAR"]._serialized_end = 1360 + _globals["_FUEL"]._serialized_start = 1362 + _globals["_FUEL"]._serialized_end = 1482 + _globals["_ENGINE"]._serialized_start = 1485 + _globals["_ENGINE"]._serialized_end = 2258 + _globals["_ENGINE_NOXCALCULATIONMETHOD"]._serialized_start = 2108 + _globals["_ENGINE_NOXCALCULATIONMETHOD"]._serialized_end = 2177 + _globals["_ENGINE_ENGINECYCLETYPE"]._serialized_start = 2179 + _globals["_ENGINE_ENGINECYCLETYPE"]._serialized_end = 2258 + _globals["_COGAS"]._serialized_start = 2261 + _globals["_COGAS"]._serialized_end = 2851 + _globals["_ELECTRICMACHINE"]._serialized_start = 2854 + _globals["_ELECTRICMACHINE"]._serialized_end = 3061 + _globals["_BATTERY"]._serialized_start = 3064 + _globals["_BATTERY"]._serialized_end = 3450 + _globals["_ELECTRICCOMPONENT"]._serialized_start = 3453 + _globals["_ELECTRICCOMPONENT"]._serialized_end = 3637 + _globals["_FUELCELL"]._serialized_start = 3640 + _globals["_FUELCELL"]._serialized_end = 3940 + _globals["_PROPELLER"]._serialized_start = 3943 + _globals["_PROPELLER"]._serialized_end = 4093 + _globals["_BUSBREAKER"]._serialized_start = 4095 + _globals["_BUSBREAKER"]._serialized_end = 4131 + _globals["_SUPERCAPACITOR"]._serialized_start = 4134 + _globals["_SUPERCAPACITOR"]._serialized_end = 4379 + _globals["_MECHANICALCOMPONENT"]._serialized_start = 4382 + _globals["_MECHANICALCOMPONENT"]._serialized_end = 4568 + _globals["_SUBSYSTEM"]._serialized_start = 4571 + _globals["_SUBSYSTEM"]._serialized_end = 6363 + _globals["_SUBSYSTEM_POWERTYPE"]._serialized_start = 5672 + _globals["_SUBSYSTEM_POWERTYPE"]._serialized_end = 5787 + _globals["_SUBSYSTEM_COMPONENTTYPE"]._serialized_start = 5790 + _globals["_SUBSYSTEM_COMPONENTTYPE"]._serialized_end = 6363 + _globals["_SWITCHBOARD"]._serialized_start = 6365 + _globals["_SWITCHBOARD"]._serialized_end = 6459 + _globals["_SHAFTLINE"]._serialized_start = 6461 + _globals["_SHAFTLINE"]._serialized_end = 6552 + _globals["_MECHANICALSYSTEM"]._serialized_start = 6554 + _globals["_MECHANICALSYSTEM"]._serialized_end = 6630 + _globals["_ELECTRICSYSTEM"]._serialized_start = 6632 + _globals["_ELECTRICSYSTEM"]._serialized_end = 6709 + _globals["_FUELSTORAGE"]._serialized_start = 6711 + _globals["_FUELSTORAGE"]._serialized_end = 6800 + _globals["_MACHINERYSYSTEM"]._serialized_start = 6803 + _globals["_MACHINERYSYSTEM"]._serialized_end = 7313 + _globals["_MACHINERYSYSTEM_PROPULSIONTYPE"]._serialized_start = 7255 + _globals["_MACHINERYSYSTEM_PROPULSIONTYPE"]._serialized_end = 7313 # @@protoc_insertion_point(module_scope) diff --git a/machinery-system-structure/MachSysS/system_structure_pb2.pyi b/machinery-system-structure/MachSysS/system_structure_pb2.pyi index 95db015..661cd59 100644 --- a/machinery-system-structure/MachSysS/system_structure_pb2.pyi +++ b/machinery-system-structure/MachSysS/system_structure_pb2.pyi @@ -149,6 +149,21 @@ class Efficiency(_message.Message): value: _Optional[float] = ..., ) -> None: ... +class PowerCurve(_message.Message): + __slots__ = ("x_label", "y_label", "curve") + X_LABEL_FIELD_NUMBER: _ClassVar[int] + Y_LABEL_FIELD_NUMBER: _ClassVar[int] + CURVE_FIELD_NUMBER: _ClassVar[int] + x_label: str + y_label: str + curve: Curve1D + def __init__( + self, + x_label: _Optional[str] = ..., + y_label: _Optional[str] = ..., + curve: _Optional[_Union[Curve1D, _Mapping]] = ..., + ) -> None: ... + class PropulsionPowerTimeSeries(_message.Message): __slots__ = ("x_label", "y_label", "propulsor_id", "curve") X_LABEL_FIELD_NUMBER: _ClassVar[int] @@ -349,6 +364,67 @@ class Engine(_message.Message): turn_off_power_kw: _Optional[float] = ..., ) -> None: ... +class COGAS(_message.Message): + __slots__ = ( + "name", + "rated_power_kw", + "rated_speed_rpm", + "efficiency", + "gas_turbine_power_curve", + "steam_turbine_power_curve", + "fuel", + "order_from_switchboard_or_shaftline", + "nox_calculation_method", + "emission_curves", + "unit_price_usd", + "start_delay_s", + "turn_off_power_kw", + ) + NAME_FIELD_NUMBER: _ClassVar[int] + RATED_POWER_KW_FIELD_NUMBER: _ClassVar[int] + RATED_SPEED_RPM_FIELD_NUMBER: _ClassVar[int] + EFFICIENCY_FIELD_NUMBER: _ClassVar[int] + GAS_TURBINE_POWER_CURVE_FIELD_NUMBER: _ClassVar[int] + STEAM_TURBINE_POWER_CURVE_FIELD_NUMBER: _ClassVar[int] + FUEL_FIELD_NUMBER: _ClassVar[int] + ORDER_FROM_SWITCHBOARD_OR_SHAFTLINE_FIELD_NUMBER: _ClassVar[int] + NOX_CALCULATION_METHOD_FIELD_NUMBER: _ClassVar[int] + EMISSION_CURVES_FIELD_NUMBER: _ClassVar[int] + UNIT_PRICE_USD_FIELD_NUMBER: _ClassVar[int] + START_DELAY_S_FIELD_NUMBER: _ClassVar[int] + TURN_OFF_POWER_KW_FIELD_NUMBER: _ClassVar[int] + name: str + rated_power_kw: float + rated_speed_rpm: float + efficiency: Efficiency + gas_turbine_power_curve: PowerCurve + steam_turbine_power_curve: PowerCurve + fuel: Fuel + order_from_switchboard_or_shaftline: int + nox_calculation_method: Engine.NOxCalculationMethod + emission_curves: _containers.RepeatedCompositeFieldContainer[EmissionCurve] + unit_price_usd: float + start_delay_s: float + turn_off_power_kw: float + def __init__( + self, + name: _Optional[str] = ..., + rated_power_kw: _Optional[float] = ..., + rated_speed_rpm: _Optional[float] = ..., + efficiency: _Optional[_Union[Efficiency, _Mapping]] = ..., + gas_turbine_power_curve: _Optional[_Union[PowerCurve, _Mapping]] = ..., + steam_turbine_power_curve: _Optional[_Union[PowerCurve, _Mapping]] = ..., + fuel: _Optional[_Union[Fuel, _Mapping]] = ..., + order_from_switchboard_or_shaftline: _Optional[int] = ..., + nox_calculation_method: _Optional[ + _Union[Engine.NOxCalculationMethod, str] + ] = ..., + emission_curves: _Optional[_Iterable[_Union[EmissionCurve, _Mapping]]] = ..., + unit_price_usd: _Optional[float] = ..., + start_delay_s: _Optional[float] = ..., + turn_off_power_kw: _Optional[float] = ..., + ) -> None: ... + class ElectricMachine(_message.Message): __slots__ = ( "name", @@ -614,6 +690,7 @@ class Subsystem(_message.Message): "bus_breaker", "supercapacitor", "other_load", + "cogas", "power_type", "component_type", "name", @@ -670,6 +747,8 @@ class Subsystem(_message.Message): SUPERCAPACITOR: _ClassVar[Subsystem.ComponentType] SUPERCAPACITOR_SYSTEM: _ClassVar[Subsystem.ComponentType] SHORE_POWER: _ClassVar[Subsystem.ComponentType] + COGAS: _ClassVar[Subsystem.ComponentType] + COGES: _ClassVar[Subsystem.ComponentType] NONE: Subsystem.ComponentType MAIN_ENGINE: Subsystem.ComponentType @@ -699,6 +778,8 @@ class Subsystem(_message.Message): SUPERCAPACITOR: Subsystem.ComponentType SUPERCAPACITOR_SYSTEM: Subsystem.ComponentType SHORE_POWER: Subsystem.ComponentType + COGAS: Subsystem.ComponentType + COGES: Subsystem.ComponentType GEAR_FIELD_NUMBER: _ClassVar[int] ENGINE_FIELD_NUMBER: _ClassVar[int] ELECTRIC_MACHINE_FIELD_NUMBER: _ClassVar[int] @@ -711,6 +792,7 @@ class Subsystem(_message.Message): BUS_BREAKER_FIELD_NUMBER: _ClassVar[int] SUPERCAPACITOR_FIELD_NUMBER: _ClassVar[int] OTHER_LOAD_FIELD_NUMBER: _ClassVar[int] + COGAS_FIELD_NUMBER: _ClassVar[int] POWER_TYPE_FIELD_NUMBER: _ClassVar[int] COMPONENT_TYPE_FIELD_NUMBER: _ClassVar[int] NAME_FIELD_NUMBER: _ClassVar[int] @@ -731,6 +813,7 @@ class Subsystem(_message.Message): bus_breaker: BusBreaker supercapacitor: SuperCapacitor other_load: ElectricComponent + cogas: COGAS power_type: Subsystem.PowerType component_type: Subsystem.ComponentType name: str @@ -753,6 +836,7 @@ class Subsystem(_message.Message): bus_breaker: _Optional[_Union[BusBreaker, _Mapping]] = ..., supercapacitor: _Optional[_Union[SuperCapacitor, _Mapping]] = ..., other_load: _Optional[_Union[ElectricComponent, _Mapping]] = ..., + cogas: _Optional[_Union[COGAS, _Mapping]] = ..., power_type: _Optional[_Union[Subsystem.PowerType, str]] = ..., component_type: _Optional[_Union[Subsystem.ComponentType, str]] = ..., name: _Optional[str] = ..., diff --git a/machinery-system-structure/proto/system_structure.proto b/machinery-system-structure/proto/system_structure.proto index 07169ac..ff063d9 100644 --- a/machinery-system-structure/proto/system_structure.proto +++ b/machinery-system-structure/proto/system_structure.proto @@ -33,6 +33,11 @@ message Efficiency { optional double value = 2; } +message PowerCurve { + string x_label = 1; + string y_label = 2; + Curve1D curve = 3; +} message PropulsionPowerTimeSeries { string x_label = 1; @@ -143,6 +148,22 @@ message Engine { double turn_off_power_kw = 14; } +message COGAS { + string name = 1; + double rated_power_kw = 2; + double rated_speed_rpm = 3; + Efficiency efficiency = 4; + PowerCurve gas_turbine_power_curve = 5; + PowerCurve steam_turbine_power_curve = 6; + Fuel fuel = 7; + uint32 order_from_switchboard_or_shaftline = 8; + Engine.NOxCalculationMethod nox_calculation_method = 9; + repeated EmissionCurve emission_curves = 10; + double unit_price_usd = 11; + double start_delay_s = 12; + double turn_off_power_kw = 13; +} + message ElectricMachine { string name = 1; double rated_power_kw = 2; @@ -230,6 +251,7 @@ message Subsystem { BusBreaker bus_breaker = 10; SuperCapacitor supercapacitor = 11; ElectricComponent other_load = 12; + COGAS cogas = 13; enum PowerType { // Make sure that this enum has the same order as in feems.type_for_feems.TypePower NONE1 = 0; // NONE1 is used instead of NONE to avoid conflict with the NONE in the ComponentType enum POWER_SOURCE = 1; @@ -267,15 +289,17 @@ message Subsystem { SUPERCAPACITOR = 25; SUPERCAPACITOR_SYSTEM = 26; SHORE_POWER = 27; + COGAS = 28; + COGES = 29; } - PowerType power_type = 13; - ComponentType component_type = 14; - string name = 15; - double rated_power_kw = 16; - double rated_speed_rpm = 17; - double ramp_up_rate_limit_percent_per_second = 18; - double ramp_down_rate_limit_percent_per_second = 19; - uint32 base_load_order = 20; // The order of the power source in the base load calculation. 1 is the primary base load, 2 is the secondary base load, etc. + PowerType power_type = 14; + ComponentType component_type = 15; + string name = 16; + double rated_power_kw = 17; + double rated_speed_rpm = 18; + double ramp_up_rate_limit_percent_per_second = 19; + double ramp_down_rate_limit_percent_per_second = 20; + uint32 base_load_order = 21; // The order of the power source in the base load calculation. 1 is the primary base load, 2 is the secondary base load, etc. } message Switchboard { diff --git a/machinery-system-structure/settings.ini b/machinery-system-structure/settings.ini index 79047de..d6ec4ad 100644 --- a/machinery-system-structure/settings.ini +++ b/machinery-system-structure/settings.ini @@ -12,7 +12,7 @@ user = keviny author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF Ocean -version = 0.6.4 +version = 0.6.5 min_python = 3.10 audience = Developers language = English diff --git a/machinery-system-structure/tests/electric_propulsion_system.mss b/machinery-system-structure/tests/electric_propulsion_system.mss index e84ce5dea8df55cdd8709b68b7fc0eadd0d91a95..5aa5733f66a0a2f82cfe63a8bb2a84593388567a 100644 GIT binary patch delta 482 zcmdldeNuXY2IqWft`0s9Mxk>X4Rsh*3m7YSnix6UQ}c>bOB4({85uypq2FO5oF#N_ zb0Z^$QX{NNTP9y*dZJvwQo-KDDBzS>Qj%I!sZd;5T#}lLY`Dpy-#|A2ImxMt|mSXMxnDC4Rsh*G8hYZsyN(J^NLeT6bu^~89>0H-=P!E5;{B4 zaOGrere;*NMp)H0Pfp|!pZtpHtWpL`0eh8zQ({R;YEh*^ab%(#$A zwScjLr-_lnJvFa5wM4-XL#aZK15jxM3x-l7tV#HZgMfmt>?CDdglQ grohy$ci=j~%E1IQaSHoFCS_F1jbWXXRi5nm2=eA(Ik{&BicAa5n;N1^{B;GEe{j diff --git a/machinery-system-structure/tests/hybrid_propulsion_system.mss b/machinery-system-structure/tests/hybrid_propulsion_system.mss index 8bcab49131b43a36dd74204f06a0fe6f7e776395..9e916dc733bac3d083bc88690634d2a89459db07 100644 GIT binary patch delta 362 zcmew%+aNbVnzMzItC5p~QK)P43YJVpl>+7pwkAgQfDliGfDr#qMg|aY=y#Y1X9=}! z-oWV2#8$vq!Pvw&`46+2Bvjdyi!fyjehxzEUXDT&{cVgS7&Vv*m@34Y7&!xq@(WUP za#D++8nSL6X)wAY!qvx5l1mP6Hep-HqzZHiPZJ}Ddum>BYKej&hNBgF9E1*U{>g!% z)CjB6!pZx%!<2wdW^H2R@-N9qEmFwIPfUTSUGKnkf|Y{_Xrd|4LMCNY%Z*{G;2{RI F9027eR8jx{ delta 354 zcmZpW`yo3)nzNCU>mLUPqfqDO)hwBe${EZBY*p+5A)X2WA^wew3?Sgp@6ZWn3AJwC z$mq_*n!#AWST*?{vzjDS)s%}cRSbR(LTO%(LKFRM3?&#fm@=3O#Hu(0it-Cmb8=FP zpz5=3AgMRHF2dEtPl_`RZMI-r$fN>v22T}-dum>BYKej&hJzJ)9E1*S{>Oo?(g>@{ zg2_j?!xVweWv$}!FUd$PQpm|qOo1s~@4$7Om4gXro(<1JCM6V`jbV!5K?SrK0940Q AkN^Mx diff --git a/machinery-system-structure/tests/mechanical_propulsion_with_electric_system.mss b/machinery-system-structure/tests/mechanical_propulsion_with_electric_system.mss index 404d0987bb51ce6508801aafae09424076fa59e0..5f066a49893ae0a8e9b292d202e6d26716321300 100644 GIT binary patch delta 271 zcmaDT{#<;54Ci-Nt}m<{j6!W2Ro$7`3K%OGn;0h-GO3AmGBSX`l#31%AuI+z2ch)I zYnhz&3YaRynix3)it-Cmb8=FPph~lDASpFEFUZx%12p*XW?ANiOsYVWd72nG+*9+4 zQ%e*Kp;{dJVOkV=9Dqt6v0^AS!m6}z@^X$aC7?rCn;5zLOEOZ66ms$tQ($V>J8+#~ VwNg360W0)#r%K=*;K-d5P delta 265 zcmaDZ{!n~^4Chx?u1~BSj6$s&Ro$6bGZ+gPt0osQsfjf*GJwF8iw>O-7K5LIP}<~m zOwPI)Oa)?9oB>7o1*thXsYOtgSvQbW8l4v8`o|44_RwZ|=7mfuKy!JjINVe7ic?Dz z452z4`e8a0dK`c%pR%H>G{UN~VDf5?Fh!s%SgW}FOEOZ66ms$tQ(#KhJ8&Im000IvE4in)lp|;JF8Qq!K z3K%OGn;0kGXI2w~Dw}cfxJ0aJxo6C-CpQGP*cPEKkORB6@?B&7hB C5FG6Q delta 130 zcmZqSY~*C;`p3b+DAc);J(E#6gSmjMiaj92Qz0P4zmbsv1RVMuI^is#*3DBG-I-W3 z7z-GyCO>3W6N9RnauKGA!OuY`ZL%zjvvLMgfmju1Kv8}{YEDjS5maT?4J4HSi6|WH diff --git a/machinery-system-structure/tests/system_proto.mss b/machinery-system-structure/tests/system_proto.mss index e84ce5dea8df55cdd8709b68b7fc0eadd0d91a95..5aa5733f66a0a2f82cfe63a8bb2a84593388567a 100644 GIT binary patch delta 482 zcmdldeNuXY2IqWft`0s9Mxk>X4Rsh*3m7YSnix6UQ}c>bOB4({85uypq2FO5oF#N_ zb0Z^$QX{NNTP9y*dZJvwQo-KDDBzS>Qj%I!sZd;5T#}lLY`Dpy-#|A2ImxMt|mSXMxnDC4Rsh*G8hYZsyN(J^NLeT6bu^~89>0H-=P!E5;{B4 zaOGrere;*NMp)H0Pfp|!pZtpHtWpL`0eh8zQ({R;YEh*^ab Date: Thu, 4 Apr 2024 10:36:58 +0000 Subject: [PATCH 19/28] feat: add py.typed to packages --- .devcontainer/devcontainer.json | 22 ++++++++++++++++++++ RunFEEMSSim/RunFeemsSim/py.typed | 0 RunFEEMSSim/setup.py | 1 + machinery-system-structure/MachSysS/py.typed | 0 machinery-system-structure/setup.py | 1 + 5 files changed, 24 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 RunFEEMSSim/RunFeemsSim/py.typed create mode 100644 machinery-system-structure/MachSysS/py.typed diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..7cc41a0 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,22 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/python +{ + "name": "Python 3", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/python:1-3.10-buster", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "pip3 install --user -r requirements_dev.txt" + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/RunFEEMSSim/RunFeemsSim/py.typed b/RunFEEMSSim/RunFeemsSim/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/RunFEEMSSim/setup.py b/RunFEEMSSim/setup.py index 0ca45f2..dd48930 100644 --- a/RunFEEMSSim/setup.py +++ b/RunFEEMSSim/setup.py @@ -101,6 +101,7 @@ + (["License :: " + lic[1]] if lic[1] else []), url=cfg["git_url"], packages=setuptools.find_packages(), + package_data={cfg["lib_name"]: ["py.typed", "*.pyi", "**/*.pyi"]}, include_package_data=True, install_requires=requirements, extras_require={"dev": dev_requirements}, diff --git a/machinery-system-structure/MachSysS/py.typed b/machinery-system-structure/MachSysS/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/machinery-system-structure/setup.py b/machinery-system-structure/setup.py index 5aa2cd4..de90c2d 100644 --- a/machinery-system-structure/setup.py +++ b/machinery-system-structure/setup.py @@ -100,6 +100,7 @@ + (["License :: " + lic[1]] if lic[1] else []), url=cfg["git_url"], packages=setuptools.find_packages(), + package_data={cfg["lib_name"]: ["py.typed", "*.pyi", "**/*.pyi"]}, include_package_data=True, install_requires=requirements, extras_require={"dev": dev_requirements}, From c6f8be18dad35343282e880cd4d8402090ec5d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torstein=20I=2E=20B=C3=B8?= Date: Thu, 4 Apr 2024 11:10:52 +0000 Subject: [PATCH 20/28] chore: bump version --- RunFEEMSSim/settings.ini | 4 ++-- feems/pyproject.toml | 2 +- machinery-system-structure/settings.ini | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/RunFEEMSSim/settings.ini b/RunFEEMSSim/settings.ini index 5b28dfa..34b7d72 100644 --- a/RunFEEMSSim/settings.ini +++ b/RunFEEMSSim/settings.ini @@ -8,7 +8,7 @@ author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF branch = master -version = 0.2.2 +version = 0.2.3 min_python = 3.10 audience = Developers language = English @@ -20,7 +20,7 @@ nbs_path = . doc_path = docs recursive = False doc_baseurl = /RunFeemsSim/ -git_url = https://SintefOceanEnergySystem@dev.azure.com/SintefOceanEnergySystem/FEEMSService/_git/RunFEEMSSim +git_url = https://github.com/SINTEF/FEEMS lib_path = RunFeemsSim title = RunFeemsSim doc_host = https://kevinkoosup.yum@sintef.no.github.io diff --git a/feems/pyproject.toml b/feems/pyproject.toml index f222900..b20069e 100644 --- a/feems/pyproject.toml +++ b/feems/pyproject.toml @@ -5,7 +5,7 @@ description = "" authors = ["Kevin Koosup Yum "] readme = "readme.md" include = ["feems/py.typed"] -license = "Proprietary" +license = "MIT" [tool.poetry.dependencies] python = ">=3.10,<3.13" diff --git a/machinery-system-structure/settings.ini b/machinery-system-structure/settings.ini index 79047de..2d7828b 100644 --- a/machinery-system-structure/settings.ini +++ b/machinery-system-structure/settings.ini @@ -12,7 +12,7 @@ user = keviny author = Kevin Koosup Yum author_email = kevinkoosup.yum@sintef.no copyright = SINTEF Ocean -version = 0.6.4 +version = 0.6.5 min_python = 3.10 audience = Developers language = English @@ -52,7 +52,7 @@ doc_baseurl = /%(lib_name)s/ # For Enterprise Github pages docs use: # doc_baseurl = /%(repo_name)s/%(lib_name)s/ -git_url = https://SintefOceanEnergySystem@dev.azure.com/SintefOceanEnergySystem/MachinerySystemStucture/_git/MachinerySystemStucture +git_url = https://github.com/SINTEF/FEEMS # For Enterprise Github use: #git_url = https://github.%(company_name)s.com/%(repo_name)s/%(lib_name)s/tree/%(branch)s/ branch = master From 5d5161d38f001ab8aa06e40299bd93110a0c24e5 Mon Sep 17 00:00:00 2001 From: keviny Date: Mon, 8 Apr 2024 22:03:21 +0200 Subject: [PATCH 21/28] testing conversion for coges completed --- .../feems/components_model/component_base.py | 2 +- .../components_model/component_electric.py | 3 +- .../components_model/component_mechanical.py | 48 +- feems/feems/types_for_feems.py | 4 +- .../00_ConvertToFeems.ipynb | 79 +- .../01_ConvertToProtobuf.ipynb | 1901 +++++------------ machinery-system-structure/02_Utility.ipynb | 4 + .../MachSysS/_modidx.py | 8 + .../MachSysS/convert_to_feems.py | 4 +- .../MachSysS/convert_to_protobuf.py | 75 +- .../tests/electric_propulsion_system.mss | Bin 3529 -> 3529 bytes .../tests/system_proto.mss | Bin 3529 -> 3529 bytes .../tests/system_proto_with_coges.mss | Bin 0 -> 3264 bytes 13 files changed, 742 insertions(+), 1386 deletions(-) create mode 100644 machinery-system-structure/tests/system_proto_with_coges.mss diff --git a/feems/feems/components_model/component_base.py b/feems/feems/components_model/component_base.py index 001be32..4836fa2 100644 --- a/feems/feems/components_model/component_base.py +++ b/feems/feems/components_model/component_base.py @@ -30,7 +30,7 @@ T = TypeVar("T", float, np.ndarray) -@dataclass +@dataclass(kw_only=True) class ComponentRunPoint: load_ratio: np.ndarray efficiency: np.ndarray diff --git a/feems/feems/components_model/component_electric.py b/feems/feems/components_model/component_electric.py index 5c09199..59a8789 100644 --- a/feems/feems/components_model/component_electric.py +++ b/feems/feems/components_model/component_electric.py @@ -9,6 +9,7 @@ from .component_base import SerialSystem, Component, BasicComponent, ComponentRunPoint from .component_mechanical import ( COGAS, + COGASRunPoint, Engine, MainEngineForMechanicalPropulsion, MechanicalPropulsionComponent, @@ -572,7 +573,7 @@ class GensetRunPoint(NamedTuple): class COGESRunPoint(NamedTuple): coges_load_ratio: np.ndarray - cogas: ComponentRunPoint + cogas: COGASRunPoint class Genset(Component): diff --git a/feems/feems/components_model/component_mechanical.py b/feems/feems/components_model/component_mechanical.py index 7c2b9b1..8eacb8b 100644 --- a/feems/feems/components_model/component_mechanical.py +++ b/feems/feems/components_model/component_mechanical.py @@ -457,6 +457,12 @@ def get_engine_run_point_from_power_out_kw( ) +@dataclass(kw_only=True) +class COGASRunPoint(ComponentRunPoint): + gas_turbine_power_kw: np.ndarray = None + steam_turbine_power_kw: np.ndarray = None + + class COGAS(BasicComponent): """Combined gas and steam component class for basic information and efficiency interpolation""" @@ -471,7 +477,7 @@ def __init__( fuel_type: TypeFuel = TypeFuel.DIESEL, fuel_origin: FuelOrigin = FuelOrigin.FOSSIL, emissions_curves: List[EmissionCurve] = None, - NOx_calculation_method: NOxCalculationMethod = NOxCalculationMethod.TIER_3, + nox_calculation_method: NOxCalculationMethod = NOxCalculationMethod.TIER_3, ): """Constructor for COGES component""" # Validate the inputs for curves. The length of the curves should be the same and the x values should be the same. @@ -487,6 +493,10 @@ def __init__( raise ValueError( "The x values of the gas turbine power curve and steam turbine power curve should be the same." ) + if gas_turbine_power_curve.shape[1] != 2: + raise ValueError( + "The gas turbine power curve and steam turbine power curve should have two columns." + ) super().__init__( type_=TypeComponent.COGAS, @@ -498,17 +508,25 @@ def __init__( ) self.gas_turbine_power_curve = gas_turbine_power_curve self.steam_turbine_power_curve = steam_turbine_power_curve - self.total_power_curve = self.gas_turbine_power_curve.copy() - self.total_power_curve[:, 1] += self.steam_turbine_power_curve[:, 1] - self.power_ratio_gas_turbine_points = gas_turbine_power_curve.copy() - self.power_ratio_gas_turbine_points[:, 1] /= self.total_power_curve[:, 1] - self.power_ratio_gas_turbine_interpolator = get_efficiency_curve_from_points( - self.power_ratio_gas_turbine_points - ) + if ( + self.gas_turbine_power_curve is not None + and self.steam_turbine_power_curve is not None + ): + self.total_power_curve = self.gas_turbine_power_curve.copy() + self.total_power_curve[:, 1] += self.steam_turbine_power_curve[:, 1] + self.power_ratio_gas_turbine_points = gas_turbine_power_curve.copy() + self.power_ratio_gas_turbine_points[:, 1] /= self.total_power_curve[:, 1] + self.power_ratio_gas_turbine_interpolator, _ = ( + get_efficiency_curve_from_points(self.power_ratio_gas_turbine_points) + ) + else: + self.total_power_curve = None + self.power_ratio_gas_turbine_points = None + self.power_ratio_gas_turbine_interpolator = None self.fuel_type = fuel_type self.fuel_origin = fuel_origin self._setup_emissions(emissions_curves) - self._setup_nox(NOx_calculation_method, rated_speed) + self._setup_nox(nox_calculation_method, rated_speed) def _setup_emissions(self, emissions_curves: List[EmissionCurve] = None) -> None: self.emission_curves = emissions_curves @@ -559,6 +577,10 @@ def _setup_nox( @property def power_output_gas_turbine(self): """Power output of the gas turbine in kW""" + if self.power_ratio_gas_turbine_interpolator is None: + raise ValueError( + "The power ratio gas turbine interpolator is not defined. Please provide the power curves for the gas and steam turbines." + ) return self.power_ratio_gas_turbine_interpolator( self.power_output / self.rated_power ) @@ -577,7 +599,7 @@ def get_gas_turbine_run_point_from_power_output_kw( ghg_emission_factor_tank_to_wake: List[ Optional[GhgEmissionFactorTankToWake] ] = None, - ) -> ComponentRunPoint: + ) -> COGASRunPoint: # GHG factors for FuelEU Maritime is not available for COGAS yet. It should raise an error if the user tries to use it. if fuel_specified_by == FuelSpecifiedBy.FUEL_EU_MARITIME: raise ValueError( @@ -605,12 +627,16 @@ def get_gas_turbine_run_point_from_power_output_kw( self.emissions_g_per_kwh(emission_type=e, load_ratio=load_ratio) * power_kwh_per_s ) - return ComponentRunPoint( + result = COGASRunPoint( load_ratio=load_ratio, fuel_flow_rate_kg_per_s=FuelConsumption(fuels=[fuel]), efficiency=eff, emissions_g_per_s=emissionn_per_s, ) + if self.gas_turbine_power_curve is not None: + result.gas_turbine_power_kw = self.power_output_gas_turbine + result.steam_turbine_power_kw = self.power_output_steam_turbine + return result MechanicalComponent = Union[ diff --git a/feems/feems/types_for_feems.py b/feems/feems/types_for_feems.py index 583ed06..47f913f 100644 --- a/feems/feems/types_for_feems.py +++ b/feems/feems/types_for_feems.py @@ -182,8 +182,8 @@ class TypeComponent(Enum): SUPERCAPACITOR = 25 SUPERCAPACITOR_SYSTEM = 26 SHORE_POWER = 27 - COGES = 28 - COGAS = 29 + COGAS = 28 + COGES = 29 @unique diff --git a/machinery-system-structure/00_ConvertToFeems.ipynb b/machinery-system-structure/00_ConvertToFeems.ipynb index f3d21c0..91cd415 100644 --- a/machinery-system-structure/00_ConvertToFeems.ipynb +++ b/machinery-system-structure/00_ConvertToFeems.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -27,7 +27,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -37,7 +37,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -102,6 +102,8 @@ " efficiency_bsfc_power: Union[proto.Efficiency, proto.BSFC, proto.PowerCurve]\n", ") -> np.ndarray:\n", " \"\"\"Converts protobuf efficiency or bsfc to numpy array\"\"\"\n", + " if isinstance(efficiency_bsfc_power, proto.PowerCurve):\n", + " return convert_proto_curve1d_to_np_array(efficiency_bsfc_power.curve)\n", " if efficiency_bsfc_power.HasField(\"value\"):\n", " if efficiency_bsfc_power.value > 0:\n", " return np.array([efficiency_bsfc_power.value])\n", @@ -316,7 +318,7 @@ " subsystem: proto.Subsystem, switchboard_id: int\n", ") -> COGES:\n", " \"\"\"Converts protobuf subsystem message to feems component\"\"\"\n", - " cogas = convert_proto_cogas_to_feems(proto_cogas == subsystem.cogas)\n", + " cogas = convert_proto_cogas_to_feems(proto_cogas=subsystem.cogas)\n", " generator = convert_proto_electric_machine_to_feems(\n", " proto_component=subsystem.electric_machine,\n", " component_type=TypeComponent.SYNCHRONOUS_MACHINE,\n", @@ -695,7 +697,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -717,18 +719,9 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2024-04-02 08:59:14,254 - tests.utility - WARNING - Efficiency of generator is not supplied, using random monotonic curve\n", - "2024-04-02 08:59:14,255 - tests.utility - WARNING - Efficiency of engine is not supplied, using random monotonic curve\n" - ] - } - ], + "outputs": [], "source": [ "# Test conversion\n", "from tests.utility import create_switchboard_with_components\n", @@ -759,7 +752,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -875,7 +868,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -894,6 +887,7 @@ "from google.protobuf import json_format\n", "from deepdiff.diff import DeepDiff\n", "from pprint import pprint\n", + "from feems.types_for_feems import TypeComponent\n", "\n", "pathToMSSFile = os.path.join(\"tests\", \"electric_propulsion_system.mss\")\n", "system_proto = retrieve_machinery_system_from_file(pathToMSSFile)\n", @@ -925,12 +919,45 @@ " for component_key, diff_component in diff_subsystem.components_modified.items():\n", " assert (\n", " len(diff_component) == 0\n", + " ), f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"\n", + "\n", + "# Test system with COGES\n", + "pathToMSSFile = os.path.join(\"tests\", \"system_proto_with_coges.mss\")\n", + "system_proto = retrieve_machinery_system_from_file(pathToMSSFile)\n", + "system_feems = convert_proto_propulsion_system_to_feems(system_proto)\n", + "fuel_cells = list(\n", + " filter(\n", + " lambda component: component.type == TypeComponent.FUEL_CELL_SYSTEM,\n", + " system_feems.power_sources,\n", + " )\n", + ")\n", + "for fuel_cell in fuel_cells:\n", + " fuel_cell.number_modules = 3\n", + "system_proto_reconverted = convert_electric_system_to_protobuf_machinery_system(\n", + " system_feems\n", + ")\n", + "diff = compare_proto_machinery_system(system_proto, system_proto_reconverted)\n", + "assert len(diff.diff_electric_system.switchboards_added) == 0\n", + "assert len(diff.diff_electric_system.switchboards_removed) == 0\n", + "for (\n", + " switchboard_id,\n", + " diff_switchboard,\n", + ") in diff.diff_electric_system.switchboards_modified.items():\n", + " assert len(diff_switchboard.subsystems_added) == 0\n", + " assert len(diff_switchboard.subsystems_removed) == 0\n", + " for key, diff_subsystem in diff_switchboard.subsystems_modified.items():\n", + " assert len(diff_subsystem.diff_attributes) == 0\n", + " assert len(diff_subsystem.components_removed) == 0\n", + " assert len(diff_subsystem.components_added) == 0\n", + " for component_key, diff_component in diff_subsystem.components_modified.items():\n", + " assert (\n", + " len(diff_component) == 0\n", " ), f\"subcomponent {component_key} for component {key} has been modified: {diff_component.__str__()}\"" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -986,7 +1013,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -1047,6 +1074,18 @@ "display_name": "python3", "language": "python", "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" } }, "nbformat": 4, diff --git a/machinery-system-structure/01_ConvertToProtobuf.ipynb b/machinery-system-structure/01_ConvertToProtobuf.ipynb index 8593028..9d02ddf 100644 --- a/machinery-system-structure/01_ConvertToProtobuf.ipynb +++ b/machinery-system-structure/01_ConvertToProtobuf.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -27,7 +27,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -37,7 +37,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -52,9 +52,11 @@ ")\n", "from typing import cast, Union, List\n", "\n", + "from feems.components_model.component_base import BasicComponent\n", "from feems.types_for_feems import TypeComponent, NOxCalculationMethod, EmissionCurve\n", - "from feems.components_model.component_mechanical import EngineDualFuel\n", + "from feems.components_model.component_mechanical import COGAS, EngineDualFuel\n", "from feems.components_model.component_electric import (\n", + " COGES,\n", " ElectricComponent,\n", " FuelCellSystem,\n", " ElectricMachine,\n", @@ -71,6 +73,7 @@ " MechanicalPropulsionSystemWithElectricPowerSystem,\n", " HybridPropulsionSystem,\n", ")\n", + "import numpy as np\n", "\n", "import MachSysS.system_structure_pb2 as proto\n", "\n", @@ -94,6 +97,28 @@ " return efficiency\n", "\n", "\n", + "def convert_np_array_to_protobuf_power_curve(power_curve: np.array) -> proto.PowerCurve:\n", + " \"\"\"Convert power curve in the component to protobuf message\"\"\"\n", + " # Check if the array is in n x 2 dimension or a single value\n", + " if power_curve.shape[1] == 2:\n", + " curve = proto.Curve1D()\n", + " curve.points.extend(\n", + " [\n", + " proto.Point(x=each_point[0], y=each_point[1])\n", + " for each_point in power_curve\n", + " ]\n", + " )\n", + " return proto.PowerCurve(\n", + " x_label=\"load_ratio\",\n", + " y_label=\"power_kw\",\n", + " curve=curve,\n", + " )\n", + " else:\n", + " raise ValueError(\n", + " f\"The power curve array should have 2 columns. The array has {power_curve.shape[1]} columns.\"\n", + " )\n", + "\n", + "\n", "def convert_bsfc_curve_to_protobuf(\n", " component: Union[Engine, EngineDualFuel], for_pilot_fuel: bool = False\n", ") -> proto.BSFC:\n", @@ -287,6 +312,38 @@ " return engine\n", "\n", "\n", + "def convert_cogas_component_to_protobuf(\n", + " component: COGAS,\n", + " order_from_shaftline_or_switchboard: int = 1,\n", + ") -> proto.Engine:\n", + " \"\"\"Convert engine component of FEEMS to protobuf message\"\"\"\n", + " cogas = proto.COGAS(\n", + " name=component.name,\n", + " rated_power_kw=component.rated_power,\n", + " rated_speed_rpm=component.rated_speed,\n", + " efficiency=convert_efficiency_curve_to_protobuf(component),\n", + " fuel=proto.Fuel(\n", + " fuel_type=component.fuel_type.value,\n", + " fuel_origin=component.fuel_origin.value,\n", + " ),\n", + " nox_calculation_method=convert_nox_calculation_method_to_protobuf(\n", + " component.nox_calculation_method\n", + " ),\n", + " emission_curves=convert_emission_curves_to_protobuf(component.emission_curves),\n", + " order_from_switchboard_or_shaftline=order_from_shaftline_or_switchboard,\n", + " )\n", + " if component.gas_turbine_power_curve is not None:\n", + " cogas.gas_turbine_power_curve.CopyFrom(\n", + " convert_np_array_to_protobuf_power_curve(component.gas_turbine_power_curve)\n", + " )\n", + " cogas.steam_turbine_power_curve.CopyFrom(\n", + " convert_np_array_to_protobuf_power_curve(\n", + " component.steam_turbine_power_curve\n", + " )\n", + " )\n", + " return cogas\n", + "\n", + "\n", "def convert_switchboard_to_protobuf(\n", " switchboard_feems: Switchboard,\n", ") -> proto.Switchboard:\n", @@ -327,6 +384,18 @@ " order_from_switchboard_or_shaftline=2,\n", " )\n", " )\n", + " elif component.type == TypeComponent.COGES:\n", + " component = cast(COGES, component)\n", + " subsystem.cogas.CopyFrom(\n", + " convert_cogas_component_to_protobuf(\n", + " component=component.cogas, order_from_shaftline_or_switchboard=2\n", + " )\n", + " )\n", + " subsystem.electric_machine.CopyFrom(\n", + " convert_electric_machine_to_protobuf(\n", + " component=component.generator, order_from_switchboard=1\n", + " )\n", + " )\n", " elif component.type == TypeComponent.GENSET:\n", " component = cast(Genset, component)\n", " subsystem.electric_machine.CopyFrom(\n", @@ -478,6 +547,13 @@ "cell_type": "code", "execution_count": null, "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -487,8 +563,8 @@ "subsystems {\n", " engine {\n", " name: \"Main engine 1\"\n", - " rated_power_kw: 8928.5891111281962\n", - " rated_speed_rpm: 757.25205223143359\n", + " rated_power_kw: 4103.8900043553094\n", + " rated_speed_rpm: 913.600745345584\n", " bsfc {\n", " curve {\n", " x_label: \"power load\"\n", @@ -496,43 +572,43 @@ " curve {\n", " points {\n", " x: 0.1\n", - " y: 6.2063818073176069\n", + " y: 109.04962442674019\n", " }\n", " points {\n", " x: 0.2\n", - " y: 147.44930059614524\n", + " y: 159.80385975921502\n", " }\n", " points {\n", " x: 0.30000000000000004\n", - " y: 80.3767374313949\n", + " y: 125.93236290389875\n", " }\n", " points {\n", " x: 0.4\n", - " y: 168.68185788463742\n", + " y: 29.468621443657071\n", " }\n", " points {\n", " x: 0.5\n", - " y: 91.67216439330204\n", + " y: 0.60328367896804735\n", " }\n", " points {\n", " x: 0.6\n", - " y: 27.734180858941947\n", + " y: 87.710826101086454\n", " }\n", " points {\n", " x: 0.70000000000000007\n", - " y: 178.96619554803775\n", + " y: 112.7883843830551\n", " }\n", " points {\n", " x: 0.8\n", - " y: 40.071011135441182\n", + " y: 138.34192743249949\n", " }\n", " points {\n", " x: 0.9\n", - " y: 150.89138436839542\n", + " y: 72.978887710277746\n", " }\n", " points {\n", " x: 1\n", - " y: 183.40404671675364\n", + " y: 110.13418391715939\n", " }\n", " }\n", " }\n", @@ -546,14 +622,14 @@ " power_type: POWER_SOURCE\n", " component_type: MAIN_ENGINE\n", " name: \"Main engine 1\"\n", - " rated_power_kw: 8928.5891111281962\n", - " rated_speed_rpm: 757.25205223143359\n", + " rated_power_kw: 4103.8900043553094\n", + " rated_speed_rpm: 913.600745345584\n", "}\n", "subsystems {\n", " engine {\n", " name: \"Main engine 2\"\n", - " rated_power_kw: 1071.410888871804\n", - " rated_speed_rpm: 277.5402084780776\n", + " rated_power_kw: 5896.1099956446888\n", + " rated_speed_rpm: 702.22878904026311\n", " bsfc {\n", " curve {\n", " x_label: \"power load\"\n", @@ -561,43 +637,43 @@ " curve {\n", " points {\n", " x: 0.1\n", - " y: 7.1034772854899009\n", + " y: 80.651939374504252\n", " }\n", " points {\n", " x: 0.2\n", - " y: 54.196599242811729\n", + " y: 175.47242981360841\n", " }\n", " points {\n", " x: 0.30000000000000004\n", - " y: 191.49531882477234\n", + " y: 14.455828742832665\n", " }\n", " points {\n", " x: 0.4\n", - " y: 106.06567400661282\n", + " y: 158.17879811084887\n", " }\n", " points {\n", " x: 0.5\n", - " y: 139.09154958668273\n", + " y: 185.19882821559253\n", " }\n", " points {\n", " x: 0.6\n", - " y: 2.7341335186296334\n", + " y: 8.6788889403791138\n", " }\n", " points {\n", " x: 0.70000000000000007\n", - " y: 53.274249103030428\n", + " y: 158.60564379358169\n", " }\n", " points {\n", " x: 0.8\n", - " y: 7.6576675627555879\n", + " y: 85.171822506138838\n", " }\n", " points {\n", " x: 0.9\n", - " y: 76.363701229970673\n", + " y: 73.790069499397632\n", " }\n", " points {\n", " x: 1\n", - " y: 113.37653306310338\n", + " y: 23.687826760212303\n", " }\n", " }\n", " }\n", @@ -611,8 +687,8 @@ " power_type: POWER_SOURCE\n", " component_type: MAIN_ENGINE\n", " name: \"Main engine 2\"\n", - " rated_power_kw: 1071.410888871804\n", - " rated_speed_rpm: 277.5402084780776\n", + " rated_power_kw: 5896.1099956446888\n", + " rated_speed_rpm: 702.22878904026311\n", "}\n", "subsystems {\n", " gear {\n", @@ -676,14 +752,14 @@ " power_type: POWER_CONSUMER\n", " component_type: PROPELLER_LOAD\n", " name: \"Propeller 1\"\n", - " rated_power_kw: 8000\n", + " rated_power_kw: 7999.9999999999991\n", " rated_speed_rpm: 1000\n", "}\n", "subsystems {\n", " electric_machine {\n", " name: \"synchronous machine\"\n", " rated_power_kw: 10000\n", - " rated_speed_rpm: 268.85769655199942\n", + " rated_speed_rpm: 123.28635647849329\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", @@ -783,7 +859,7 @@ " component_type: PTI_PTO_SYSTEM\n", " name: \"PTI/PTO 1\"\n", " rated_power_kw: 10000\n", - " rated_speed_rpm: 268.85769655199942\n", + " rated_speed_rpm: 123.28635647849329\n", "}\n", "\n" ] @@ -829,7 +905,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -916,87 +992,82 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2024-04-08 18:37:59,699 - tests.utility - WARNING - Efficiency of generator is not supplied, using random monotonic curve\n", + "2024-04-08 18:37:59,700 - tests.utility - WARNING - Efficiency of engine is not supplied, using random monotonic curve\n", + "2024-04-08 18:37:59,712 - tests.utility - WARNING - Efficiency of generator is not supplied, using random monotonic curve\n", + "2024-04-08 18:37:59,712 - tests.utility - WARNING - Efficiency of engine is not supplied, using random monotonic curve\n" + ] + }, { "name": "stdout", "output_type": "stream", "text": [ - "name: \"ME Propulsion System\"\n", + "name: \"Electric propulsion system with coges\"\n", + "propulsion_type: ELECTRIC\n", "maximum_allowed_genset_load_percentage: 80\n", - "mechanical_system {\n", - " shaft_lines {\n", - " shaft_line_id: 1\n", + "electric_system {\n", + " switchboards {\n", + " switchboard_id: 1\n", " subsystems {\n", - " engine {\n", - " name: \"Main engine 1\"\n", - " rated_power_kw: 10000\n", - " rated_speed_rpm: 616.299232833948\n", - " bsfc {\n", + " converter1 {\n", + " name: \"Converter 1\"\n", + " rated_power_kw: 1000\n", + " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", - " y_label: \"bsfc\"\n", + " y_label: \"efficiency\"\n", " curve {\n", " points {\n", " x: 0.1\n", - " y: 158.66714790551916\n", - " }\n", - " points {\n", - " x: 0.2\n", - " y: 154.41330499203636\n", - " }\n", - " points {\n", - " x: 0.30000000000000004\n", - " y: 196.625139992027\n", + " y: 0.9\n", " }\n", " points {\n", - " x: 0.4\n", - " y: 96.345260976504576\n", + " x: 0.25\n", + " y: 0.95\n", " }\n", " points {\n", " x: 0.5\n", - " y: 114.8119354266663\n", - " }\n", - " points {\n", - " x: 0.6\n", - " y: 123.10509932525309\n", - " }\n", - " points {\n", - " x: 0.70000000000000007\n", - " y: 199.78791423581728\n", - " }\n", - " points {\n", - " x: 0.8\n", - " y: 191.52941614115804\n", + " y: 0.96\n", " }\n", " points {\n", - " x: 0.9\n", - " y: 154.02757904149783\n", + " x: 0.75\n", + " y: 0.97\n", " }\n", " points {\n", " x: 1\n", - " y: 31.905281061288161\n", + " y: 0.96\n", " }\n", " }\n", " }\n", " }\n", - " main_fuel {\n", - " fuel_type: HFO\n", - " fuel_origin: FOSSIL\n", - " }\n", " order_from_switchboard_or_shaftline: 1\n", " }\n", - " power_type: POWER_SOURCE\n", - " component_type: MAIN_ENGINE\n", - " name: \"Main engine 1\"\n", - " rated_power_kw: 10000\n", - " rated_speed_rpm: 616.299232833948\n", + " battery {\n", + " name: \"Battery 1\"\n", + " energy_capacity_kwh: 1000\n", + " rated_charging_rate_c: 1\n", + " rated_discharging_rate_c: 1\n", + " efficiency_charging: 0.975\n", + " efficiency_discharging: 0.975\n", + " initial_state_of_charge: 0.8\n", + " order_from_switchboard_or_shaftline: 2\n", + " }\n", + " power_type: ENERGY_STORAGE\n", + " component_type: BATTERY_SYSTEM\n", + " name: \"Battery system 1\"\n", + " rated_power_kw: 1000\n", " }\n", " subsystems {\n", - " gear {\n", - " name: \"Gear 1\"\n", - " rated_power_kw: 10000\n", + " electric_machine {\n", + " name: \"Propulsion motor 1\"\n", + " rated_power_kw: 2000\n", " rated_speed_rpm: 1000\n", " efficiency {\n", " curve {\n", @@ -1004,1541 +1075,604 @@ " y_label: \"efficiency\"\n", " curve {\n", " points {\n", + " x: 0.1\n", + " y: 0.7\n", + " }\n", + " points {\n", " x: 0.25\n", - " y: 0.9298900684\n", + " y: 0.85\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.9533974336\n", + " y: 0.96\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.9595580564\n", + " y: 0.97\n", " }\n", " points {\n", " x: 1\n", - " y: 0.9585018015\n", + " y: 0.96\n", " }\n", " }\n", " }\n", " }\n", - " order_from_switchboard_or_shaftline: 1\n", + " order_from_switchboard_or_shaftline: 2\n", " }\n", - " propeller {\n", + " converter1 {\n", + " name: \"Converter 1\"\n", + " rated_power_kw: 2000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", + " x: 0.1\n", + " y: 0.9\n", + " }\n", + " points {\n", " x: 0.25\n", - " y: 0.9298900684\n", + " y: 0.95\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.9533974336\n", + " y: 0.96\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.9595580564\n", + " y: 0.97\n", " }\n", " points {\n", " x: 1\n", - " y: 0.9585018015\n", + " y: 0.96\n", " }\n", " }\n", " }\n", " }\n", - " propulsor_id: 1\n", - " order_from_switchboard_or_shaftline: 2\n", + " order_from_switchboard_or_shaftline: 1\n", " }\n", " power_type: POWER_CONSUMER\n", - " component_type: PROPELLER_LOAD\n", - " name: \"Propeller 1\"\n", - " rated_power_kw: 8000\n", + " component_type: PROPULSION_DRIVE\n", + " name: \"Propulsion Drive 1\"\n", + " rated_power_kw: 2000\n", " rated_speed_rpm: 1000\n", " }\n", " subsystems {\n", - " electric_machine {\n", - " name: \"synchronous machine\"\n", - " rated_power_kw: 10000\n", - " rated_speed_rpm: 306.53749338761281\n", + " other_load {\n", + " name: \"Other load 1\"\n", + " rated_power_kw: 1000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", + " y: 1\n", " }\n", " points {\n", " x: 1\n", - " y: 0.9585018015\n", + " y: 1\n", " }\n", " }\n", " }\n", " }\n", - " order_from_switchboard_or_shaftline: 4\n", + " order_from_switchboard_or_shaftline: 1\n", " }\n", - " transformer {\n", - " name: \"transformer\"\n", + " power_type: POWER_CONSUMER\n", + " component_type: OTHER_LOAD\n", + " name: \"Other load 1\"\n", + " rated_power_kw: 1000\n", + " }\n", + " subsystems {\n", + " electric_machine {\n", + " name: \"Generator 1\"\n", " rated_power_kw: 10000\n", + " rated_speed_rpm: 1000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " y: 99\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 99\n", + " x: 0.1\n", + " y: 0.7\n", " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " converter1 {\n", - " name: \"inverter\"\n", - " rated_power_kw: 10000\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", " points {\n", " x: 0.25\n", - " y: 0.96\n", + " y: 0.85\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.97\n", + " y: 0.96\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.972\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.98\n", + " y: 0.97\n", " }\n", " }\n", " }\n", " }\n", - " order_from_switchboard_or_shaftline: 2\n", + " order_from_switchboard_or_shaftline: 1\n", " }\n", - " converter2 {\n", - " name: \"rectifier\"\n", - " rated_power_kw: 3000\n", + " cogas {\n", + " name: \"COGAS 1\"\n", + " rated_power_kw: 10000\n", + " rated_speed_rpm: 1000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " y: 99.5\n", + " y: 0.9\n", " }\n", " points {\n", " x: 1\n", - " y: 99.5\n", + " y: 0.9\n", " }\n", " }\n", " }\n", " }\n", - " order_from_switchboard_or_shaftline: 3\n", + " gas_turbine_power_curve {\n", + " x_label: \"load_ratio\"\n", + " y_label: \"power_kw\"\n", + " curve {\n", + " points {\n", + " x: 0.1\n", + " y: 200\n", + " }\n", + " points {\n", + " x: 0.25\n", + " y: 1000\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 3000\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 5250\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 7500\n", + " }\n", + " }\n", + " }\n", + " steam_turbine_power_curve {\n", + " x_label: \"load_ratio\"\n", + " y_label: \"power_kw\"\n", + " curve {\n", + " points {\n", + " x: 0.1\n", + " y: 800\n", + " }\n", + " points {\n", + " x: 0.25\n", + " y: 1500\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 2000\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 2250\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 2500\n", + " }\n", + " }\n", + " }\n", + " fuel {\n", + " fuel_type: NATURAL_GAS\n", + " fuel_origin: FOSSIL\n", + " }\n", + " order_from_switchboard_or_shaftline: 2\n", + " nox_calculation_method: TIER_3\n", " }\n", - " power_type: PTI_PTO\n", - " component_type: PTI_PTO_SYSTEM\n", - " name: \"PTI/PTO 1\"\n", + " power_type: POWER_SOURCE\n", + " component_type: COGES\n", + " name: \"COGES 1\"\n", " rated_power_kw: 10000\n", - " rated_speed_rpm: 306.53749338761281\n", + " rated_speed_rpm: 1000\n", " }\n", - " }\n", - "}\n", - "electric_system {\n", - " switchboards {\n", - " switchboard_id: 1\n", " subsystems {\n", " converter1 {\n", - " name: \"converter\"\n", - " rated_power_kw: 2478.360583366918\n", + " name: \"Converter 1\"\n", + " rated_power_kw: 3150\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " x: 0.25\n", - " y: 0.39658962019277733\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.539599941033186\n", + " x: 0.1\n", + " y: 0.9\n", " }\n", " points {\n", - " x: 0.75\n", - " y: 0.70817786684293083\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.82374339944754993\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " fuel_cell {\n", - " name: \"fuel cell\"\n", - " rated_power_kw: 3008.6560754587535\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.42407002602039845\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.63525308468590069\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.730976185427855\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.8851266070777779\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " fuel {\n", - " fuel_type: HYDROGEN\n", - " fuel_origin: RENEWABLE_NON_BIO\n", - " }\n", - " number_modules: 1\n", - " }\n", - " power_type: POWER_SOURCE\n", - " component_type: FUEL_CELL_SYSTEM\n", - " name: \"FUEL_CELL_SYSTEM 1\"\n", - " rated_power_kw: 2478.360583366918\n", - " }\n", - " subsystems {\n", - " electric_machine {\n", - " name: \"FUEL_CELL_SYSTEM 2\"\n", - " rated_power_kw: 2837.2745920810949\n", - " rated_speed_rpm: 587.751846606595\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " power_type: POWER_SOURCE\n", - " component_type: GENERATOR\n", - " name: \"FUEL_CELL_SYSTEM 2\"\n", - " rated_power_kw: 2837.2745920810949\n", - " rated_speed_rpm: 587.751846606595\n", - " }\n", - " subsystems {\n", - " electric_machine {\n", - " name: \"electric motor for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1304.5108462673925\n", - " rated_speed_rpm: 247.59339459832464\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 3\n", - " }\n", - " transformer {\n", - " name: \"transformer for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1304.5108462673925\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 98.5\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 98.5\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " converter1 {\n", - " name: \"frequency converter for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1304.5108462673925\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.96\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.97\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.972\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.98\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", - " power_type: POWER_CONSUMER\n", - " component_type: PROPULSION_DRIVE\n", - " name: \"PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1304.5108462673925\n", - " rated_speed_rpm: 247.59339459832464\n", - " }\n", - " subsystems {\n", - " other_load {\n", - " name: \"PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 1965.5775291856264\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 1\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 1\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " power_type: POWER_CONSUMER\n", - " component_type: OTHER_LOAD\n", - " name: \"PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 1965.5775291856264\n", - " }\n", - " subsystems {\n", - " other_load {\n", - " name: \"PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 981.91162454698087\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 1\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 1\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " power_type: POWER_CONSUMER\n", - " component_type: OTHER_LOAD\n", - " name: \"PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 981.91162454698087\n", - " }\n", - " subsystems {\n", - " electric_machine {\n", - " name: \"synchronous machine\"\n", - " rated_power_kw: 3299.5955115740144\n", - " rated_speed_rpm: 601.56852217300229\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 4\n", - " }\n", - " transformer {\n", - " name: \"transformer\"\n", - " rated_power_kw: 3299.5955115740144\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 99\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 99\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " converter1 {\n", - " name: \"inverter\"\n", - " rated_power_kw: 3299.5955115740144\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.96\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.97\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.972\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.98\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", - " converter2 {\n", - " name: \"rectifier\"\n", - " rated_power_kw: 3000\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 99.5\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 99.5\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 3\n", - " }\n", - " power_type: PTI_PTO\n", - " component_type: PTI_PTO_SYSTEM\n", - " name: \"PTI/PTO 1\"\n", - " rated_power_kw: 3299.5955115740144\n", - " rated_speed_rpm: 601.56852217300229\n", - " }\n", - " subsystems {\n", - " converter1 {\n", - " name: \"converter\"\n", - " rated_power_kw: 4613.0155516838131\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.5518640554898997\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.67070500646476172\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.67421411362430506\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.69163273193574792\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " battery {\n", - " name: \"battery\"\n", - " energy_capacity_kwh: 1537.671850561271\n", - " rated_charging_rate_c: 3\n", - " rated_discharging_rate_c: 3\n", - " efficiency_charging: 0.975\n", - " efficiency_discharging: 0.975\n", - " initial_state_of_charge: 0.8\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", - " power_type: ENERGY_STORAGE\n", - " component_type: BATTERY_SYSTEM\n", - " name: \"ENERGY_STORAGE_SYSTEM 1\"\n", - " rated_power_kw: 4613.0155516838131\n", - " }\n", - " }\n", - " switchboards {\n", - " switchboard_id: 2\n", - " subsystems {\n", - " converter1 {\n", - " name: \"converter\"\n", - " rated_power_kw: 350.92845355013145\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.39234020323749053\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.4445901241124709\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.58466686732150608\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.68170315983594909\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " fuel_cell {\n", - " name: \"fuel cell\"\n", - " rated_power_kw: 514.78190835228327\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.18588681520327377\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.30448788802681792\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.44492898642703704\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.54462828184152035\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " fuel {\n", - " fuel_type: HYDROGEN\n", - " fuel_origin: RENEWABLE_NON_BIO\n", - " }\n", - " number_modules: 1\n", - " }\n", - " power_type: POWER_SOURCE\n", - " component_type: FUEL_CELL_SYSTEM\n", - " name: \"FUEL_CELL_SYSTEM 1\"\n", - " rated_power_kw: 350.92845355013145\n", - " }\n", - " subsystems {\n", - " converter1 {\n", - " name: \"converter\"\n", - " rated_power_kw: 97.31378768437628\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.63360764741943176\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.7745552768635372\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.87698385048591632\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.99686680463166943\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " fuel_cell {\n", - " name: \"fuel cell\"\n", - " rated_power_kw: 97.619649116847242\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.58116482316103946\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.70209436632147126\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.85810821076510113\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.93084143159087518\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " fuel {\n", - " fuel_type: HYDROGEN\n", - " fuel_origin: RENEWABLE_NON_BIO\n", - " }\n", - " number_modules: 1\n", - " }\n", - " power_type: POWER_SOURCE\n", - " component_type: FUEL_CELL_SYSTEM\n", - " name: \"FUEL_CELL_SYSTEM 2\"\n", - " rated_power_kw: 97.31378768437628\n", - " }\n", - " subsystems {\n", - " electric_machine {\n", - " name: \"electric motor for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 139.5828857931466\n", - " rated_speed_rpm: 410.18228386091351\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 3\n", - " }\n", - " transformer {\n", - " name: \"transformer for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 139.5828857931466\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 98.5\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 98.5\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " converter1 {\n", - " name: \"frequency converter for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 139.5828857931466\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.96\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.97\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.972\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.98\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", - " power_type: POWER_CONSUMER\n", - " component_type: PROPULSION_DRIVE\n", - " name: \"PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 139.5828857931466\n", - " rated_speed_rpm: 410.18228386091351\n", - " }\n", - " subsystems {\n", - " electric_machine {\n", - " name: \"electric motor for PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 160.0693093051575\n", - " rated_speed_rpm: 276.35372580530827\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 3\n", - " }\n", - " transformer {\n", - " name: \"transformer for PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 160.0693093051575\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 98.5\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 98.5\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " converter1 {\n", - " name: \"frequency converter for PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 160.0693093051575\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.96\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.97\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.972\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.98\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", - " power_type: POWER_CONSUMER\n", - " component_type: PROPULSION_DRIVE\n", - " name: \"PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 160.0693093051575\n", - " rated_speed_rpm: 276.35372580530827\n", - " }\n", - " subsystems {\n", - " electric_machine {\n", - " name: \"electric motor for PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 58.347804901695874\n", - " rated_speed_rpm: 814.990008599895\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 3\n", - " }\n", - " transformer {\n", - " name: \"transformer for PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 58.347804901695874\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 98.5\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 98.5\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " converter1 {\n", - " name: \"frequency converter for PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 58.347804901695874\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.96\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.97\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.972\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.98\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", - " power_type: POWER_CONSUMER\n", - " component_type: PROPULSION_DRIVE\n", - " name: \"PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 58.347804901695874\n", - " rated_speed_rpm: 814.990008599895\n", - " }\n", - " subsystems {\n", - " electric_machine {\n", - " name: \"synchronous machine\"\n", - " rated_power_kw: 72.625012684428867\n", - " rated_speed_rpm: 986.50786379117676\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 4\n", - " }\n", - " transformer {\n", - " name: \"transformer\"\n", - " rated_power_kw: 72.625012684428867\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 99\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 99\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " converter1 {\n", - " name: \"inverter\"\n", - " rated_power_kw: 72.625012684428867\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.96\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.97\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.972\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.98\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", - " converter2 {\n", - " name: \"rectifier\"\n", - " rated_power_kw: 3000\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " y: 99.5\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 99.5\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 3\n", - " }\n", - " power_type: PTI_PTO\n", - " component_type: PTI_PTO_SYSTEM\n", - " name: \"PTI/PTO 1\"\n", - " rated_power_kw: 72.625012684428867\n", - " rated_speed_rpm: 986.50786379117676\n", - " }\n", - " subsystems {\n", - " converter1 {\n", - " name: \"converter\"\n", - " rated_power_kw: 45.693712045406443\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.49644053235563845\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.649135448857771\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.8029874550411582\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.82088292986119216\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " battery {\n", - " name: \"battery\"\n", - " energy_capacity_kwh: 15.231237348468815\n", - " rated_charging_rate_c: 3\n", - " rated_discharging_rate_c: 3\n", - " efficiency_charging: 0.975\n", - " efficiency_discharging: 0.975\n", - " initial_state_of_charge: 0.8\n", - " order_from_switchboard_or_shaftline: 2\n", - " }\n", - " power_type: ENERGY_STORAGE\n", - " component_type: BATTERY_SYSTEM\n", - " name: \"ENERGY_STORAGE_SYSTEM 1\"\n", - " rated_power_kw: 45.693712045406443\n", - " }\n", - " }\n", - " switchboards {\n", - " switchboard_id: 3\n", - " subsystems {\n", - " electric_machine {\n", - " name: \"GENERATOR 1\"\n", - " rated_power_kw: 3550.0781297114218\n", - " rated_speed_rpm: 557.855996224465\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " power_type: POWER_SOURCE\n", - " component_type: GENERATOR\n", - " name: \"GENERATOR 1\"\n", - " rated_power_kw: 3550.0781297114218\n", - " rated_speed_rpm: 557.855996224465\n", - " }\n", - " subsystems {\n", - " electric_machine {\n", - " name: \"GENERATOR 2\"\n", - " rated_power_kw: 4286.7328846113805\n", - " rated_speed_rpm: 618.65695022029115\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", - " }\n", - " points {\n", - " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " power_type: POWER_SOURCE\n", - " component_type: GENERATOR\n", - " name: \"GENERATOR 2\"\n", - " rated_power_kw: 4286.7328846113805\n", - " rated_speed_rpm: 618.65695022029115\n", - " }\n", - " subsystems {\n", - " electric_machine {\n", - " name: \"electric motor for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1536.6482828656267\n", - " rated_speed_rpm: 273.38089702409417\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", - " points {\n", - " x: 0.25\n", - " y: 0.9298900684\n", + " x: 0.25\n", + " y: 0.95\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.9533974336\n", - " }\n", - " points {\n", - " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", - " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 3\n", - " }\n", - " transformer {\n", - " name: \"transformer for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1536.6482828656267\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", + " y: 0.96\n", + " }\n", " points {\n", - " y: 98.5\n", + " x: 0.75\n", + " y: 0.97\n", " }\n", " points {\n", " x: 1\n", - " y: 98.5\n", + " y: 0.96\n", " }\n", " }\n", " }\n", " }\n", " order_from_switchboard_or_shaftline: 1\n", " }\n", - " converter1 {\n", - " name: \"frequency converter for PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1536.6482828656267\n", + " fuel_cell {\n", + " name: \"Fuel cell 1\"\n", + " rated_power_kw: 1000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", + " x: 0.1\n", + " y: 0.7\n", + " }\n", + " points {\n", " x: 0.25\n", - " y: 0.96\n", + " y: 0.85\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.97\n", + " y: 0.96\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.972\n", + " y: 0.97\n", " }\n", " points {\n", " x: 1\n", - " y: 0.98\n", + " y: 0.96\n", " }\n", " }\n", " }\n", " }\n", " order_from_switchboard_or_shaftline: 2\n", + " fuel {\n", + " fuel_type: HYDROGEN\n", + " fuel_origin: RENEWABLE_NON_BIO\n", + " }\n", + " number_modules: 3\n", " }\n", - " power_type: POWER_CONSUMER\n", - " component_type: PROPULSION_DRIVE\n", - " name: \"PROPULSION_DRIVE 1\"\n", - " rated_power_kw: 1536.6482828656267\n", - " rated_speed_rpm: 273.38089702409417\n", + " power_type: POWER_SOURCE\n", + " component_type: FUEL_CELL_SYSTEM\n", + " name: \"Fuel cell system 1\"\n", + " rated_power_kw: 3150\n", " }\n", + " }\n", + " switchboards {\n", + " switchboard_id: 2\n", " subsystems {\n", - " other_load {\n", - " name: \"PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 539.11065501196254\n", + " converter1 {\n", + " name: \"Converter 1\"\n", + " rated_power_kw: 1000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " y: 1\n", + " x: 0.1\n", + " y: 0.9\n", + " }\n", + " points {\n", + " x: 0.25\n", + " y: 0.95\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 0.96\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 0.97\n", " }\n", " points {\n", " x: 1\n", - " y: 1\n", + " y: 0.96\n", " }\n", " }\n", " }\n", " }\n", " order_from_switchboard_or_shaftline: 1\n", " }\n", - " power_type: POWER_CONSUMER\n", - " component_type: OTHER_LOAD\n", - " name: \"PROPULSION_DRIVE 2\"\n", - " rated_power_kw: 539.11065501196254\n", + " battery {\n", + " name: \"Battery 1\"\n", + " energy_capacity_kwh: 1000\n", + " rated_charging_rate_c: 1\n", + " rated_discharging_rate_c: 1\n", + " efficiency_charging: 0.975\n", + " efficiency_discharging: 0.975\n", + " initial_state_of_charge: 0.8\n", + " order_from_switchboard_or_shaftline: 2\n", + " }\n", + " power_type: ENERGY_STORAGE\n", + " component_type: BATTERY_SYSTEM\n", + " name: \"Battery system 1\"\n", + " rated_power_kw: 1000\n", " }\n", " subsystems {\n", " electric_machine {\n", - " name: \"electric motor for PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 4193.2410621224117\n", - " rated_speed_rpm: 329.28206483221788\n", + " name: \"Propulsion motor 1\"\n", + " rated_power_kw: 2000\n", + " rated_speed_rpm: 1000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", + " x: 0.1\n", + " y: 0.7\n", + " }\n", + " points {\n", " x: 0.25\n", - " y: 0.9298900684\n", + " y: 0.85\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.9533974336\n", + " y: 0.96\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.9595580564\n", + " y: 0.97\n", " }\n", " points {\n", " x: 1\n", - " y: 0.9585018015\n", + " y: 0.96\n", " }\n", " }\n", " }\n", " }\n", - " order_from_switchboard_or_shaftline: 3\n", + " order_from_switchboard_or_shaftline: 2\n", " }\n", - " transformer {\n", - " name: \"transformer for PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 4193.2410621224117\n", + " converter1 {\n", + " name: \"Converter 1\"\n", + " rated_power_kw: 2000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " y: 98.5\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 98.5\n", + " x: 0.1\n", + " y: 0.9\n", " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " converter1 {\n", - " name: \"frequency converter for PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 4193.2410621224117\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", " points {\n", " x: 0.25\n", - " y: 0.96\n", + " y: 0.95\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.97\n", + " y: 0.96\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.972\n", + " y: 0.97\n", " }\n", " points {\n", " x: 1\n", - " y: 0.98\n", + " y: 0.96\n", " }\n", " }\n", " }\n", " }\n", - " order_from_switchboard_or_shaftline: 2\n", + " order_from_switchboard_or_shaftline: 1\n", " }\n", " power_type: POWER_CONSUMER\n", " component_type: PROPULSION_DRIVE\n", - " name: \"PROPULSION_DRIVE 3\"\n", - " rated_power_kw: 4193.2410621224117\n", - " rated_speed_rpm: 329.28206483221788\n", + " name: \"Propulsion Drive 1\"\n", + " rated_power_kw: 2000\n", + " rated_speed_rpm: 1000\n", " }\n", " subsystems {\n", " electric_machine {\n", - " name: \"synchronous machine\"\n", - " rated_power_kw: 2818.129072565167\n", - " rated_speed_rpm: 230.92596118234056\n", + " name: \"Generator 2\"\n", + " rated_power_kw: 10000\n", + " rated_speed_rpm: 1000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", + " x: 0.1\n", + " y: 0.7\n", + " }\n", + " points {\n", " x: 0.25\n", - " y: 0.9298900684\n", + " y: 0.85\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.9533974336\n", + " y: 0.96\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.9595580564\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 0.9585018015\n", + " y: 0.97\n", " }\n", " }\n", " }\n", " }\n", - " order_from_switchboard_or_shaftline: 4\n", + " order_from_switchboard_or_shaftline: 1\n", " }\n", - " transformer {\n", - " name: \"transformer\"\n", - " rated_power_kw: 2818.129072565167\n", + " cogas {\n", + " name: \"COGAS 2\"\n", + " rated_power_kw: 10000\n", + " rated_speed_rpm: 1000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " y: 99\n", + " y: 0.9\n", " }\n", " points {\n", " x: 1\n", - " y: 99\n", + " y: 0.9\n", " }\n", " }\n", " }\n", " }\n", - " order_from_switchboard_or_shaftline: 1\n", + " gas_turbine_power_curve {\n", + " x_label: \"load_ratio\"\n", + " y_label: \"power_kw\"\n", + " curve {\n", + " points {\n", + " x: 0.1\n", + " y: 200\n", + " }\n", + " points {\n", + " x: 0.25\n", + " y: 1000\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 3000\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 5250\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 7500\n", + " }\n", + " }\n", + " }\n", + " steam_turbine_power_curve {\n", + " x_label: \"load_ratio\"\n", + " y_label: \"power_kw\"\n", + " curve {\n", + " points {\n", + " x: 0.1\n", + " y: 800\n", + " }\n", + " points {\n", + " x: 0.25\n", + " y: 1500\n", + " }\n", + " points {\n", + " x: 0.5\n", + " y: 2000\n", + " }\n", + " points {\n", + " x: 0.75\n", + " y: 2250\n", + " }\n", + " points {\n", + " x: 1\n", + " y: 2500\n", + " }\n", + " }\n", + " }\n", + " fuel {\n", + " fuel_type: NATURAL_GAS\n", + " fuel_origin: FOSSIL\n", + " }\n", + " order_from_switchboard_or_shaftline: 2\n", + " nox_calculation_method: TIER_3\n", " }\n", + " power_type: POWER_SOURCE\n", + " component_type: COGES\n", + " name: \"COGES 2\"\n", + " rated_power_kw: 10000\n", + " rated_speed_rpm: 1000\n", + " }\n", + " subsystems {\n", " converter1 {\n", - " name: \"inverter\"\n", - " rated_power_kw: 2818.129072565167\n", + " name: \"Converter 1\"\n", + " rated_power_kw: 3150\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", + " x: 0.1\n", + " y: 0.9\n", + " }\n", + " points {\n", " x: 0.25\n", - " y: 0.96\n", + " y: 0.95\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.97\n", + " y: 0.96\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.972\n", + " y: 0.97\n", " }\n", " points {\n", " x: 1\n", - " y: 0.98\n", + " y: 0.96\n", " }\n", " }\n", " }\n", " }\n", - " order_from_switchboard_or_shaftline: 2\n", + " order_from_switchboard_or_shaftline: 1\n", " }\n", - " converter2 {\n", - " name: \"rectifier\"\n", - " rated_power_kw: 3000\n", + " fuel_cell {\n", + " name: \"Fuel cell 2\"\n", + " rated_power_kw: 1000\n", " efficiency {\n", " curve {\n", " x_label: \"power load\"\n", " y_label: \"efficiency\"\n", " curve {\n", " points {\n", - " y: 99.5\n", - " }\n", - " points {\n", - " x: 1\n", - " y: 99.5\n", + " x: 0.1\n", + " y: 0.7\n", " }\n", - " }\n", - " }\n", - " }\n", - " order_from_switchboard_or_shaftline: 3\n", - " }\n", - " power_type: PTI_PTO\n", - " component_type: PTI_PTO_SYSTEM\n", - " name: \"PTI/PTO 1\"\n", - " rated_power_kw: 2818.129072565167\n", - " rated_speed_rpm: 230.92596118234056\n", - " }\n", - " subsystems {\n", - " converter1 {\n", - " name: \"converter\"\n", - " rated_power_kw: 5756.9832524014491\n", - " efficiency {\n", - " curve {\n", - " x_label: \"power load\"\n", - " y_label: \"efficiency\"\n", - " curve {\n", " points {\n", " x: 0.25\n", - " y: 0.38614390652279795\n", + " y: 0.85\n", " }\n", " points {\n", " x: 0.5\n", - " y: 0.57482256146291422\n", + " y: 0.96\n", " }\n", " points {\n", " x: 0.75\n", - " y: 0.62573078860901121\n", + " y: 0.97\n", " }\n", " points {\n", " x: 1\n", - " y: 0.74101150969848006\n", + " y: 0.96\n", " }\n", " }\n", " }\n", " }\n", - " order_from_switchboard_or_shaftline: 1\n", - " }\n", - " battery {\n", - " name: \"battery\"\n", - " energy_capacity_kwh: 1918.9944174671498\n", - " rated_charging_rate_c: 3\n", - " rated_discharging_rate_c: 3\n", - " efficiency_charging: 0.975\n", - " efficiency_discharging: 0.975\n", - " initial_state_of_charge: 0.8\n", " order_from_switchboard_or_shaftline: 2\n", + " fuel {\n", + " fuel_type: HYDROGEN\n", + " fuel_origin: RENEWABLE_NON_BIO\n", + " }\n", + " number_modules: 3\n", " }\n", - " power_type: ENERGY_STORAGE\n", - " component_type: BATTERY_SYSTEM\n", - " name: \"ENERGY_STORAGE_SYSTEM 1\"\n", - " rated_power_kw: 5756.9832524014491\n", + " power_type: POWER_SOURCE\n", + " component_type: FUEL_CELL_SYSTEM\n", + " name: \"Fuel cell system 2\"\n", + " rated_power_kw: 3150\n", " }\n", " }\n", "}\n", @@ -2562,7 +1696,7 @@ " MechanicalPropulsionSystem,\n", " MechanicalPropulsionSystemWithElectricPowerSystem,\n", ")\n", - "from feems.components_model.component_mechanical import Engine\n", + "from feems.components_model.component_mechanical import Engine, COGAS\n", "from feems.components_model.component_electric import (\n", " Genset,\n", " Battery,\n", @@ -2572,6 +1706,7 @@ " FuelCellSystem,\n", " FuelCell,\n", " BatterySystem,\n", + " COGES,\n", ")\n", "from feems.fuel import TypeFuel, FuelOrigin\n", "from feems.types_for_feems import TypePower, TypeComponent, NOxCalculationMethod\n", @@ -2615,7 +1750,6 @@ "system_proto = convert_mechanical_propulsion_system_with_electric_system_to_protobuf(\n", " system_feems\n", ")\n", - "print(system_proto)\n", "\n", "# Create an electric propulsion system\n", "number_gensets = 4\n", @@ -2656,6 +1790,7 @@ "energy_storages = []\n", "power_consumers = []\n", "fuel_cell_systems = []\n", + "coges = []\n", "number_batteries = 2\n", "for index in range(number_batteries):\n", " energy_storages.append(\n", @@ -2745,9 +1880,9 @@ "for index in range(number_fuel_cells):\n", " fuel_cell_systems.append(\n", " FuelCellSystem(\n", - " name=\"Fuel cell system 1\",\n", + " name=f\"Fuel cell system {index + 1}\",\n", " fuel_cell_module=FuelCell(\n", - " name=\"Fuel cell 1\",\n", + " name=f\"Fuel cell {index + 1}\",\n", " rated_power=1000,\n", " eff_curve=np.array(\n", " [[0.1, 0.70], [0.25, 0.85], [0.5, 0.96], [0.75, 0.97], [1.0, 0.96]]\n", @@ -2768,6 +1903,7 @@ " number_modules=3,\n", " )\n", " )\n", + "\n", "# Create the electric system\n", "electric_system = ElectricPowerSystem(\n", " name=\"Electric propulsion system\",\n", @@ -2789,7 +1925,64 @@ " assert each_fuel_cell.number_modules == 3\n", "\n", "with open(os.path.join(\"tests\", \"system_proto.mss\"), \"wb\") as file:\n", - " file.write(system_proto.SerializeToString())" + " file.write(system_proto.SerializeToString())\n", + "\n", + "# Create the electric system with COGES\n", + "number_coges = 2\n", + "rated_power = 10000\n", + "gas_turbine_power_curve = np.array(\n", + " [[0.1, 0.2], [0.25, 0.4], [0.5, 0.6], [0.75, 0.7], [1.0, 0.75]]\n", + ")\n", + "gas_turbine_power_curve[:, 1] *= rated_power * gas_turbine_power_curve[:, 0]\n", + "steam_turbine_power_curve = gas_turbine_power_curve.copy()\n", + "steam_turbine_power_curve[:, 1] = (\n", + " rated_power * steam_turbine_power_curve[:, 0] - gas_turbine_power_curve[:, 1]\n", + ")\n", + "for i in range(number_coges):\n", + " coges.append(\n", + " COGES(\n", + " name=f\"COGES {i + 1}\",\n", + " cogas=COGAS(\n", + " name=f\"COGAS {i + 1}\",\n", + " rated_power=10000,\n", + " rated_speed=1000,\n", + " eff_curve=np.array([0.9]),\n", + " gas_turbine_power_curve=gas_turbine_power_curve,\n", + " steam_turbine_power_curve=steam_turbine_power_curve,\n", + " fuel_type=TypeFuel.NATURAL_GAS,\n", + " fuel_origin=FuelOrigin.FOSSIL,\n", + " nox_calculation_method=NOxCalculationMethod.TIER_3,\n", + " ),\n", + " generator=ElectricMachine(\n", + " name=f\"Generator {i + 1}\",\n", + " rated_power=10000,\n", + " rated_speed=1000,\n", + " power_type=TypePower.POWER_SOURCE,\n", + " type_=TypeComponent.GENERATOR,\n", + " eff_curve=np.array(\n", + " [[0.1, 0.70], [0.25, 0.85], [0.5, 0.96], [0.75, 0.97]]\n", + " ),\n", + " switchboard_id=i + 1,\n", + " ),\n", + " )\n", + " )\n", + "\n", + "electric_system_with_coges = ElectricPowerSystem(\n", + " name=\"Electric propulsion system with coges\",\n", + " power_plant_components=energy_storages\n", + " + power_consumers\n", + " + coges\n", + " + fuel_cell_systems,\n", + " bus_tie_connections=[(1, 2)],\n", + ")\n", + "\n", + "system_proto_with_coges = convert_electric_system_to_protobuf_machinery_system(\n", + " electric_system_with_coges\n", + ")\n", + "with open(os.path.join(\"tests\", \"system_proto_with_coges.mss\"), \"wb\") as file:\n", + " file.write(system_proto_with_coges.SerializeToString())\n", + "\n", + "print(system_proto_with_coges)" ] }, { @@ -2801,7 +1994,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -2972,7 +2165,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -3155,7 +2348,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -3819,7 +3012,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -4744,7 +3937,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -4776,6 +3969,18 @@ "display_name": "python3", "language": "python", "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" } }, "nbformat": 4, diff --git a/machinery-system-structure/02_Utility.ipynb b/machinery-system-structure/02_Utility.ipynb index 11325d3..5d71383 100644 --- a/machinery-system-structure/02_Utility.ipynb +++ b/machinery-system-structure/02_Utility.ipynb @@ -76,6 +76,10 @@ "display_name": "python3", "language": "python", "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.12.1" } }, "nbformat": 4, diff --git a/machinery-system-structure/MachSysS/_modidx.py b/machinery-system-structure/MachSysS/_modidx.py index 66b81eb..3d8d86d 100644 --- a/machinery-system-structure/MachSysS/_modidx.py +++ b/machinery-system-structure/MachSysS/_modidx.py @@ -218,6 +218,10 @@ "converttoprotobuf.html#convert_bsfc_curve_to_protobuf", "MachSysS/convert_to_protobuf.py", ), + "MachSysS.convert_to_protobuf.convert_cogas_component_to_protobuf": ( + "converttoprotobuf.html#convert_cogas_component_to_protobuf", + "MachSysS/convert_to_protobuf.py", + ), "MachSysS.convert_to_protobuf.convert_efficiency_curve_to_protobuf": ( "converttoprotobuf.html#convert_efficiency_curve_to_protobuf", "MachSysS/convert_to_protobuf.py", @@ -262,6 +266,10 @@ "converttoprotobuf.html#convert_nox_calculation_method_to_protobuf", "MachSysS/convert_to_protobuf.py", ), + "MachSysS.convert_to_protobuf.convert_np_array_to_protobuf_power_curve": ( + "converttoprotobuf.html#convert_np_array_to_protobuf_power_curve", + "MachSysS/convert_to_protobuf.py", + ), "MachSysS.convert_to_protobuf.convert_serial_electric_system_to_protobuf": ( "converttoprotobuf.html#convert_serial_electric_system_to_protobuf", "MachSysS/convert_to_protobuf.py", diff --git a/machinery-system-structure/MachSysS/convert_to_feems.py b/machinery-system-structure/MachSysS/convert_to_feems.py index 466f120..3194ed0 100644 --- a/machinery-system-structure/MachSysS/convert_to_feems.py +++ b/machinery-system-structure/MachSysS/convert_to_feems.py @@ -94,6 +94,8 @@ def convert_proto_efficiency_bsfc_power_to_np_array( efficiency_bsfc_power: Union[proto.Efficiency, proto.BSFC, proto.PowerCurve] ) -> np.ndarray: """Converts protobuf efficiency or bsfc to numpy array""" + if isinstance(efficiency_bsfc_power, proto.PowerCurve): + return convert_proto_curve1d_to_np_array(efficiency_bsfc_power.curve) if efficiency_bsfc_power.HasField("value"): if efficiency_bsfc_power.value > 0: return np.array([efficiency_bsfc_power.value]) @@ -308,7 +310,7 @@ def convert_proto_coges_to_feems( subsystem: proto.Subsystem, switchboard_id: int ) -> COGES: """Converts protobuf subsystem message to feems component""" - cogas = convert_proto_cogas_to_feems(proto_cogas == subsystem.cogas) + cogas = convert_proto_cogas_to_feems(proto_cogas=subsystem.cogas) generator = convert_proto_electric_machine_to_feems( proto_component=subsystem.electric_machine, component_type=TypeComponent.SYNCHRONOUS_MACHINE, diff --git a/machinery-system-structure/MachSysS/convert_to_protobuf.py b/machinery-system-structure/MachSysS/convert_to_protobuf.py index 1205e74..bbe6282 100644 --- a/machinery-system-structure/MachSysS/convert_to_protobuf.py +++ b/machinery-system-structure/MachSysS/convert_to_protobuf.py @@ -3,6 +3,7 @@ # %% auto 0 __all__ = [ "convert_efficiency_curve_to_protobuf", + "convert_np_array_to_protobuf_power_curve", "convert_bsfc_curve_to_protobuf", "convert_electric_machine_to_protobuf", "convert_electric_component_to_protobuf", @@ -12,6 +13,7 @@ "convert_nox_calculation_method_to_protobuf", "convert_emission_curves_to_protobuf", "convert_engine_component_to_protobuf", + "convert_cogas_component_to_protobuf", "convert_switchboard_to_protobuf", "convert_shaftline_to_protobuf", "convert_electric_system_to_protobuf", @@ -32,9 +34,11 @@ ) from typing import cast, Union, List +from feems.components_model.component_base import BasicComponent from feems.types_for_feems import TypeComponent, NOxCalculationMethod, EmissionCurve -from feems.components_model.component_mechanical import EngineDualFuel +from feems.components_model.component_mechanical import COGAS, EngineDualFuel from feems.components_model.component_electric import ( + COGES, ElectricComponent, FuelCellSystem, ElectricMachine, @@ -51,6 +55,7 @@ MechanicalPropulsionSystemWithElectricPowerSystem, HybridPropulsionSystem, ) +import numpy as np import MachSysS.system_structure_pb2 as proto @@ -74,6 +79,28 @@ def convert_efficiency_curve_to_protobuf( return efficiency +def convert_np_array_to_protobuf_power_curve(power_curve: np.array) -> proto.PowerCurve: + """Convert power curve in the component to protobuf message""" + # Check if the array is in n x 2 dimension or a single value + if power_curve.shape[1] == 2: + curve = proto.Curve1D() + curve.points.extend( + [ + proto.Point(x=each_point[0], y=each_point[1]) + for each_point in power_curve + ] + ) + return proto.PowerCurve( + x_label="load_ratio", + y_label="power_kw", + curve=curve, + ) + else: + raise ValueError( + f"The power curve array should have 2 columns. The array has {power_curve.shape[1]} columns." + ) + + def convert_bsfc_curve_to_protobuf( component: Union[Engine, EngineDualFuel], for_pilot_fuel: bool = False ) -> proto.BSFC: @@ -267,6 +294,38 @@ def convert_engine_component_to_protobuf( return engine +def convert_cogas_component_to_protobuf( + component: COGAS, + order_from_shaftline_or_switchboard: int = 1, +) -> proto.Engine: + """Convert engine component of FEEMS to protobuf message""" + cogas = proto.COGAS( + name=component.name, + rated_power_kw=component.rated_power, + rated_speed_rpm=component.rated_speed, + efficiency=convert_efficiency_curve_to_protobuf(component), + fuel=proto.Fuel( + fuel_type=component.fuel_type.value, + fuel_origin=component.fuel_origin.value, + ), + nox_calculation_method=convert_nox_calculation_method_to_protobuf( + component.nox_calculation_method + ), + emission_curves=convert_emission_curves_to_protobuf(component.emission_curves), + order_from_switchboard_or_shaftline=order_from_shaftline_or_switchboard, + ) + if component.gas_turbine_power_curve is not None: + cogas.gas_turbine_power_curve.CopyFrom( + convert_np_array_to_protobuf_power_curve(component.gas_turbine_power_curve) + ) + cogas.steam_turbine_power_curve.CopyFrom( + convert_np_array_to_protobuf_power_curve( + component.steam_turbine_power_curve + ) + ) + return cogas + + def convert_switchboard_to_protobuf( switchboard_feems: Switchboard, ) -> proto.Switchboard: @@ -307,6 +366,18 @@ def convert_switchboard_to_protobuf( order_from_switchboard_or_shaftline=2, ) ) + elif component.type == TypeComponent.COGES: + component = cast(COGES, component) + subsystem.cogas.CopyFrom( + convert_cogas_component_to_protobuf( + component=component.cogas, order_from_shaftline_or_switchboard=2 + ) + ) + subsystem.electric_machine.CopyFrom( + convert_electric_machine_to_protobuf( + component=component.generator, order_from_switchboard=1 + ) + ) elif component.type == TypeComponent.GENSET: component = cast(Genset, component) subsystem.electric_machine.CopyFrom( @@ -454,7 +525,7 @@ def convert_shaftline_to_protobuf(shaftline_feems: ShaftLine) -> proto.ShaftLine return shaftline_proto -# %% ../01_ConvertToProtobuf.ipynb 5 +# %% ../01_ConvertToProtobuf.ipynb 6 def convert_electric_system_to_protobuf( electric_system: ElectricPowerSystem, ) -> proto.ElectricSystem: diff --git a/machinery-system-structure/tests/electric_propulsion_system.mss b/machinery-system-structure/tests/electric_propulsion_system.mss index 5aa5733f66a0a2f82cfe63a8bb2a84593388567a..bd1e6b507ac78506c9a92e34c88eafca488f4fd7 100644 GIT binary patch delta 25 ecmX>peNuV@KQE)vWC7lF+(w;@3?MLPg#!Rxw+3+l delta 11 ScmX>peNuV@Kkwvfwp{=llLTV` diff --git a/machinery-system-structure/tests/system_proto.mss b/machinery-system-structure/tests/system_proto.mss index 5aa5733f66a0a2f82cfe63a8bb2a84593388567a..bd1e6b507ac78506c9a92e34c88eafca488f4fd7 100644 GIT binary patch delta 25 ecmX>peNuV@KQE)vWC7lF+(w;@3?MLPg#!Rxw+3+l delta 11 ScmX>peNuV@Kkwvfwp{=llLTV` diff --git a/machinery-system-structure/tests/system_proto_with_coges.mss b/machinery-system-structure/tests/system_proto_with_coges.mss new file mode 100644 index 0000000000000000000000000000000000000000..6a4c12d2dbac1fe98f7c16a425c5b7d4e4f5fbd4 GIT binary patch literal 3264 zcmeHJO=uHA7|m=V-HbUTduu>l1tIp9cxpvY*Myc~$V{O+5KS#pdco{IZkDOj?7c1gw%dg~zbpH}8Azd%=gNY-;+R zW$LcyxFx%2IR(8~E&6mxFI)bCZaSA}F^&#~f^(i^ZjIs}F%@aom9d8i@69@eW$O9V z)6J!APv{zp-(4UBW&a3H+|%9><&FUQ^uD(L@$UCv!e@R+U;CWmTF+`$0|P$kE_z z8fpGxoOSobAc`BQjMPw^f2U1MdKK}fYTuRQGlaES!QPVNJA#cmVI_f z8qmVp+Ys0eXi4=NT77p6%~dLq8j{&O=~>HE?=W5`w*~j5ix+Tg#$RZwOd50Y7#{B_ zzymnSq#9}pGC@0B8ajeD_S8_ZNZM@jCfmzuBgBW!R zExuRqNOorW#5vAFS2w?-W19_u4vvjo!MJ7OIe4t)Xlh{Vxy$8lBQx?WA{&{Tq=SKC z1I&FQ?tzg5toB@Bd>Ch5l1v}fSH%~=FRao%f${33E-+sG&SQb`>MIR05mA*mBFbsS zMU{Ou)S`F_C~m6(IF{u2sfW29J>4DVnrwh-PnD>xo7A?sPWs!|gHUTn4nQ>D>nSA@ zQN!^t2?Nn8tN_vHmZb}9;+rv583s@&1hX3kP|N3Fccx6~AHojeG1&Zl1kko5$gr)` hwR`_w68x&0VG@8`2A2ex{~-z5I{8@Du74YheHY literal 0 HcmV?d00001 From 930391d39e1ab218c37901fe8f34060876450a53 Mon Sep 17 00:00:00 2001 From: kevinksyTRD <54361535+kevinksyTRD@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:13:51 +0200 Subject: [PATCH 22/28] Update publish_feems.yml --- .github/workflows/publish_feems.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish_feems.yml b/.github/workflows/publish_feems.yml index 17b4eeb..7136940 100644 --- a/.github/workflows/publish_feems.yml +++ b/.github/workflows/publish_feems.yml @@ -3,6 +3,7 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: push: branches: ["main"] + tags: ["v*"] jobs: build: From c1eabe7e4542bc820f791cfad4beb22ada64e638 Mon Sep 17 00:00:00 2001 From: kevinksyTRD <54361535+kevinksyTRD@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:19:46 +0200 Subject: [PATCH 23/28] Update publish_feems.yml --- .github/workflows/publish_feems.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/publish_feems.yml b/.github/workflows/publish_feems.yml index 7136940..e0858bd 100644 --- a/.github/workflows/publish_feems.yml +++ b/.github/workflows/publish_feems.yml @@ -2,7 +2,6 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: push: - branches: ["main"] tags: ["v*"] jobs: From e8456fd8a111ce2360eb4948bbc5708483d455a2 Mon Sep 17 00:00:00 2001 From: kevinksyTRD <54361535+kevinksyTRD@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:39:41 +0200 Subject: [PATCH 24/28] Update publish_feems.yml --- .github/workflows/publish_feems.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/publish_feems.yml b/.github/workflows/publish_feems.yml index e0858bd..c284f79 100644 --- a/.github/workflows/publish_feems.yml +++ b/.github/workflows/publish_feems.yml @@ -32,7 +32,6 @@ jobs: publish-to-pypi: name: >- Publish Python 🐍 distribution 📦 to PyPI - if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes needs: - build runs-on: ubuntu-latest From c8833a52a8551e3b3f8e7a0291d4f09fba030a0b Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 9 Apr 2024 14:40:53 +0200 Subject: [PATCH 25/28] publish at release --- .github/workflows/publish_MachSysS.yml | 5 +- .github/workflows/publish_RunFeemsSim.yml | 5 +- .github/workflows/publish_feems.yml | 4 +- .github/workflows/release-please.yml | 69 ----------------------- 4 files changed, 6 insertions(+), 77 deletions(-) delete mode 100644 .github/workflows/release-please.yml diff --git a/.github/workflows/publish_MachSysS.yml b/.github/workflows/publish_MachSysS.yml index 8fb92dd..cde32ad 100644 --- a/.github/workflows/publish_MachSysS.yml +++ b/.github/workflows/publish_MachSysS.yml @@ -1,8 +1,8 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: - push: - branches: ["main"] + release: + types: [created] jobs: build: @@ -32,7 +32,6 @@ jobs: publish-to-pypi: name: >- Publish Python 🐍 distribution 📦 to PyPI - if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes needs: - build runs-on: ubuntu-latest diff --git a/.github/workflows/publish_RunFeemsSim.yml b/.github/workflows/publish_RunFeemsSim.yml index fc2a530..e6d2e39 100644 --- a/.github/workflows/publish_RunFeemsSim.yml +++ b/.github/workflows/publish_RunFeemsSim.yml @@ -1,8 +1,8 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: - push: - branches: ["main"] + release: + types: [created] jobs: build: @@ -32,7 +32,6 @@ jobs: publish-to-pypi: name: >- Publish Python 🐍 distribution 📦 to PyPI - if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes needs: - build runs-on: ubuntu-latest diff --git a/.github/workflows/publish_feems.yml b/.github/workflows/publish_feems.yml index c284f79..f6f3e9c 100644 --- a/.github/workflows/publish_feems.yml +++ b/.github/workflows/publish_feems.yml @@ -1,8 +1,8 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: - push: - tags: ["v*"] + release: + types: [created] jobs: build: diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml deleted file mode 100644 index 0d456a5..0000000 --- a/.github/workflows/release-please.yml +++ /dev/null @@ -1,69 +0,0 @@ -on: - push: - branches: ["release"] - -permissions: - contents: write - pull-requests: write - id-token: write - -name: release-please - -jobs: - release-please: - runs-on: ubuntu-latest - steps: - - uses: google-github-actions/release-please-action@v4 - id: release - with: - # this assumes that you have created a personal access token - # (PAT) and configured it as a GitHub action secret named - token: ${{ secrets.PYCOSIM_UPLOAD }} - config-file: release-please-config.json - manifest-file: .release-please-manifest.json - include-component-in-tag: true - - name: Print the output - run: echo "The output was $ALLOUTPUT" - env: - ALLOUTPUT: ${{ toJSON(steps.release.outputs) }} - - uses: actions/checkout@v4 - if: ${{ steps.release.outputs.releases_created }} - - name: Set up Python - uses: actions/setup-python@v4 - if: ${{ steps.release.outputs.releases_created }} - with: - python-version: "3.12" - - name: Install pypa/build - if: ${{ steps.release.outputs.releases_created }} - run: >- - python3 -m - pip install - build - --user - - name: Build feems - if: ${{ steps.release.outputs.feems--release_created }} - run: python3 -m build - working-directory: feems - - name: Publish feems to PyPI - if: ${{ steps.release.outputs.feems--release_created }} - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: feems/dist - - name: Build MachSysS - if: ${{ steps.release.outputs.machinery-system-structure--release_created }} - run: python3 -m build - working-directory: machinery-system-structure - - name: Publish ship_model_lib to PyPI - if: ${{ steps.release.outputs.machinery-system-structure--release_created }} - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: machinery-system-structure/dist - - name: Build RunFEEMSSim - if: ${{ steps.release.outputs.RunFEEMSSim--release_created }} - run: python3 -m build - working-directory: RunFEEMSSim - - name: Publish RunFEEMSSim to PyPI - if: ${{ steps.release.outputs.RunFEEMSSim--release_created }} - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: RunFEEMSSim/dist From 7652cb5bf8ceb3b53ae759ebbfd854fd68b70d8e Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 9 Apr 2024 14:49:21 +0200 Subject: [PATCH 26/28] release workflow --- .github/workflows/publish_MachSysS.yml | 4 ++-- .github/workflows/publish_RunFeemsSim.yml | 4 ++-- .github/workflows/publish_feems.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish_MachSysS.yml b/.github/workflows/publish_MachSysS.yml index cde32ad..2c63a8e 100644 --- a/.github/workflows/publish_MachSysS.yml +++ b/.github/workflows/publish_MachSysS.yml @@ -1,8 +1,8 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: - release: - types: [created] + push: + branches: ["release"] jobs: build: diff --git a/.github/workflows/publish_RunFeemsSim.yml b/.github/workflows/publish_RunFeemsSim.yml index e6d2e39..908b249 100644 --- a/.github/workflows/publish_RunFeemsSim.yml +++ b/.github/workflows/publish_RunFeemsSim.yml @@ -1,8 +1,8 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: - release: - types: [created] + push: + branches: ["release"] jobs: build: diff --git a/.github/workflows/publish_feems.yml b/.github/workflows/publish_feems.yml index f6f3e9c..dd82111 100644 --- a/.github/workflows/publish_feems.yml +++ b/.github/workflows/publish_feems.yml @@ -1,8 +1,8 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: - release: - types: [created] + push: + branches: ["release"] jobs: build: From 466b88af6d5e5ff7428204a771fce0e48c2109a3 Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 9 Apr 2024 14:53:26 +0200 Subject: [PATCH 27/28] fixed pipeline --- .github/workflows/publish_MachSysS.yml | 2 +- .github/workflows/publish_RunFeemsSim.yml | 2 +- .github/workflows/publish_feems.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish_MachSysS.yml b/.github/workflows/publish_MachSysS.yml index 2c63a8e..97880a6 100644 --- a/.github/workflows/publish_MachSysS.yml +++ b/.github/workflows/publish_MachSysS.yml @@ -1,7 +1,7 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: - push: + pull_request: branches: ["release"] jobs: diff --git a/.github/workflows/publish_RunFeemsSim.yml b/.github/workflows/publish_RunFeemsSim.yml index 908b249..4c79c25 100644 --- a/.github/workflows/publish_RunFeemsSim.yml +++ b/.github/workflows/publish_RunFeemsSim.yml @@ -1,7 +1,7 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: - push: + pull_request: branches: ["release"] jobs: diff --git a/.github/workflows/publish_feems.yml b/.github/workflows/publish_feems.yml index dd82111..3064496 100644 --- a/.github/workflows/publish_feems.yml +++ b/.github/workflows/publish_feems.yml @@ -1,7 +1,7 @@ name: Publish Python 🐍 distribution 📦 to PyPI for FEEMS on: - push: + pull_request: branches: ["release"] jobs: From 1fb062e09ee95be22eb6642e7210c22eefb1be9d Mon Sep 17 00:00:00 2001 From: keviny Date: Tue, 9 Apr 2024 14:59:13 +0200 Subject: [PATCH 28/28] fixed version --- feems/pyproject.toml | 2 +- feems/tests/test_system.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/feems/pyproject.toml b/feems/pyproject.toml index b20069e..af37cdd 100644 --- a/feems/pyproject.toml +++ b/feems/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "feems" -version = "0.10.5" +version = "0.10.6" description = "" authors = ["Kevin Koosup Yum "] readme = "readme.md" diff --git a/feems/tests/test_system.py b/feems/tests/test_system.py index f5ec93c..fd2a880 100644 --- a/feems/tests/test_system.py +++ b/feems/tests/test_system.py @@ -1,7 +1,7 @@ import copy import pprint import random -from typing import List, Dict +from typing import List, Dict, Tuple from unittest import TestCase from feems.components_model.component_electric import ( @@ -366,7 +366,7 @@ def get_propulsion_drives( @staticmethod def get_components_numbers_electric_system( system: ElectricPowerSystem, - ) -> (int, int, int, int, int): + ) -> Tuple[int, int, int, int, int]: no_power_sources = system.no_power_sources no_propulsion_drive = system.no_propulsion_units no_other_load = system.no_other_load