Skip to content

Commit

Permalink
testing conversion for coges completed
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinksyTRD committed Apr 8, 2024
1 parent f50f829 commit 5d5161d
Show file tree
Hide file tree
Showing 13 changed files with 742 additions and 1,386 deletions.
2 changes: 1 addition & 1 deletion feems/feems/components_model/component_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
T = TypeVar("T", float, np.ndarray)


@dataclass
@dataclass(kw_only=True)
class ComponentRunPoint:
load_ratio: np.ndarray
efficiency: np.ndarray
Expand Down
3 changes: 2 additions & 1 deletion feems/feems/components_model/component_electric.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .component_base import SerialSystem, Component, BasicComponent, ComponentRunPoint
from .component_mechanical import (
COGAS,
COGASRunPoint,
Engine,
MainEngineForMechanicalPropulsion,
MechanicalPropulsionComponent,
Expand Down Expand Up @@ -572,7 +573,7 @@ class GensetRunPoint(NamedTuple):

class COGESRunPoint(NamedTuple):
coges_load_ratio: np.ndarray
cogas: ComponentRunPoint
cogas: COGASRunPoint


class Genset(Component):
Expand Down
48 changes: 37 additions & 11 deletions feems/feems/components_model/component_mechanical.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"""

Expand All @@ -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.
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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
)
Expand All @@ -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(
Expand Down Expand Up @@ -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[
Expand Down
4 changes: 2 additions & 2 deletions feems/feems/types_for_feems.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ class TypeComponent(Enum):
SUPERCAPACITOR = 25
SUPERCAPACITOR_SYSTEM = 26
SHORE_POWER = 27
COGES = 28
COGAS = 29
COGAS = 28
COGES = 29


@unique
Expand Down
79 changes: 59 additions & 20 deletions machinery-system-structure/00_ConvertToFeems.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -27,7 +27,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -37,7 +37,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -695,7 +697,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -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",
Expand Down Expand Up @@ -759,7 +752,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -875,7 +868,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -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",
Expand Down Expand Up @@ -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": [
Expand Down Expand Up @@ -986,7 +1013,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -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,
Expand Down
Loading

0 comments on commit 5d5161d

Please sign in to comment.