From d080dde45c6ef8e487672bf63a5f67ac39fd257f Mon Sep 17 00:00:00 2001 From: Becca Rolph Date: Fri, 13 Jan 2023 11:37:37 -0700 Subject: [PATCH 01/71] Updated mooring system installation and hookup times. --- ORBIT/core/defaults/process_times.yaml | 2 +- ORBIT/phases/install/mooring_install/mooring.py | 4 +++- ORBIT/phases/install/quayside_assembly_tow/moored.py | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ORBIT/core/defaults/process_times.yaml b/ORBIT/core/defaults/process_times.yaml index 1c141c78..c1b94b26 100644 --- a/ORBIT/core/defaults/process_times.yaml +++ b/ORBIT/core/defaults/process_times.yaml @@ -66,7 +66,7 @@ "mooring_system_load_time": 5 # hr "mooring_site_survey_time": 4 # hr "suction_pile_install_time": 11 # hr -"drag_embed_install_time": 5 # hr +"drag_embed_install_time": 12 # hr # Increased from 5h so it now includes proof loading. This time increases with depth (in mooring.py) # Misc. "site_position_time": 2 # hr diff --git a/ORBIT/phases/install/mooring_install/mooring.py b/ORBIT/phases/install/mooring_install/mooring.py index 3b3573b9..296d82fc 100644 --- a/ORBIT/phases/install/mooring_install/mooring.py +++ b/ORBIT/phases/install/mooring_install/mooring.py @@ -268,7 +268,7 @@ def install_mooring_line(vessel, depth, **kwargs): ------ vessel.task representing time to install mooring line. """ - + install_time = 0.005 * depth yield vessel.task_wrapper( @@ -320,6 +320,7 @@ def release(**kwargs): return "", 0 +''' # commented anchor_install_time because this overwrites what is called from process_times.yaml . def anchor_install_time(self, depth): """ Returns time to install anchor. Varies by depth. @@ -342,3 +343,4 @@ def anchor_install_time(self, depth): ) return fixed + 0.005 * depth +''' \ No newline at end of file diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index c38908b2..c79fbe66 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -383,14 +383,14 @@ def install_moored_substructures( constraints={"windspeed": le(15), "waveheight": le(2.5)}, ) yield vessel.task_wrapper( - "Connect Mooring Lines", - 22, + "Connect Mooring Lines, Pre-tension and pre-stretch", + 20, suspendable=True, constraints={"windspeed": le(15), "waveheight": le(2.5)}, ) yield vessel.task_wrapper( "Check Mooring Lines", - 12, + 6, suspendable=True, constraints={"windspeed": le(15), "waveheight": le(2.5)}, ) From 1d1432eef8683b7c2199803ed06c54bd8f79fdd8 Mon Sep 17 00:00:00 2001 From: Becca Rolph Date: Thu, 19 Jan 2023 13:21:14 -0700 Subject: [PATCH 02/71] working on mooring update --- ORBIT/phases/design/mooring_system_design.py | 50 +++++--------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index 383a4924..f6af0053 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -29,7 +29,7 @@ class MooringSystemDesign(DesignPhase): output_config = { "mooring_system": { "num_lines": "int", - "line_diam": "m, float", + #"line_diam": "m, float", "line_mass": "t", "line_cost": "USD", "line_length": "m", @@ -64,7 +64,7 @@ def run(self): """ self.determine_mooring_line() - self.calculate_breaking_load() + #self.calculate_breaking_load() self.calculate_line_length_mass() self.calculate_anchor_mass_cost() @@ -75,48 +75,24 @@ def determine_mooring_line(self): Returns the diameter of the mooring lines based on the turbine rating. """ - tr = self.config["turbine"]["turbine_rating"] - fit = -0.0004 * (tr ** 2) + 0.0132 * tr + 0.0536 + self.line_cost = 999 # this is the result of a function of depth - if fit <= 0.09: - self.line_diam = 0.09 - self.line_mass_per_m = 0.161 - self.line_cost_rate = 399.0 + #def calculate_breaking_load(self): + # """ + # Returns the mooring line breaking load. + # """ - elif fit <= 0.12: - self.line_diam = 0.12 - self.line_mass_per_m = 0.288 - self.line_cost_rate = 721.0 - - else: - self.line_diam = 0.15 - self.line_mass_per_m = 0.450 - self.line_cost_rate = 1088.0 - - def calculate_breaking_load(self): - """ - Returns the mooring line breaking load. - """ - - self.breaking_load = ( - 419449 * (self.line_diam ** 2) + 93415 * self.line_diam - 3577.9 - ) + # self.breaking_load = ( + # 419449 * (self.line_diam ** 2) + 93415 * self.line_diam - 3577.9 + # ) def calculate_line_length_mass(self): """ Returns the mooring line length and mass. """ - if self.anchor_type == "Drag Embedment": - fixed = self._design.get("drag_embedment_fixed_length", 500) - - else: - fixed = 0 - depth = self.config["site"]["depth"] - self.line_length = ( - 0.0002 * (depth ** 2) + 1.264 * depth + 47.776 + fixed - ) + self.line_length = 999 # fill this in with fitted eqn result of total semitaut line length self.line_mass = self.line_length * self.line_mass_per_m @@ -134,7 +110,7 @@ def calculate_anchor_mass_cost(self): else: self.anchor_mass = 50 - self.anchor_cost = sqrt(self.breaking_load / 9.81 / 1250) * 150000 + self.anchor_cost = 999 # make this output the cost as a function of depth (Matt H.) # sqrt(self.breaking_load / 9.81 / 1250) * 150000 @property def line_cost(self): @@ -158,7 +134,7 @@ def detailed_output(self): return { "num_lines": self.num_lines, - "line_diam": self.line_diam, + #"line_diam": self.line_diam, "line_mass": self.line_mass, "line_length": self.line_length, "line_cost": self.line_cost, From 15c5c3efef911476e2c9f9a226468592e63093aa Mon Sep 17 00:00:00 2001 From: Becca Rolph Date: Fri, 20 Jan 2023 16:09:01 -0700 Subject: [PATCH 03/71] Added the Semi-taut mooring system design module --- .../design/SemiTaut_mooring_system_design.py | 171 ++++++++++++++++++ ORBIT/phases/design/mooring_system_design.py | 151 ---------------- examples/4. Example Fixed Project.ipynb | 6 +- ...ample_floating_project_mooring_update.yaml | 55 ++++++ 4 files changed, 229 insertions(+), 154 deletions(-) create mode 100644 ORBIT/phases/design/SemiTaut_mooring_system_design.py delete mode 100644 ORBIT/phases/design/mooring_system_design.py create mode 100644 examples/configs/example_floating_project_mooring_update.yaml diff --git a/ORBIT/phases/design/SemiTaut_mooring_system_design.py b/ORBIT/phases/design/SemiTaut_mooring_system_design.py new file mode 100644 index 00000000..fcd68a37 --- /dev/null +++ b/ORBIT/phases/design/SemiTaut_mooring_system_design.py @@ -0,0 +1,171 @@ +"""`MooringSystemDesign` and related functionality.""" + +__author__ = "Jake Nunemaker" +__copyright__ = "Copyright 2020, National Renewable Energy Laboratory" +__maintainer__ = "Jake Nunemaker" +__email__ = "jake.nunemaker@nrel.gov" + + +from math import sqrt +from scipy import optimize +from scipy.interpolate import interp1d +import numpy as np + +from ORBIT.phases.design import DesignPhase + + +class SemiTautMooringSystemDesign(DesignPhase): + """Mooring System and Anchor Design.""" + + expected_config = { + "site": {"depth": "float"}, + "turbine": {"turbine_rating": "int | float"}, + "plant": {"num_turbines": "int"}, + "mooring_system_design": { + "num_lines": "int | float (optional, default: 4)", + "anchor_type": "str (optional, default: 'Drag Embedment')", + "mooring_line_cost_rate": "int | float (optional)", + "drag_embedment_fixed_length": "int | float (optional, default: .5km)", + }, + } + + output_config = { + "mooring_system": { + "num_lines": "int", + #"line_diam": "m, float", # this is not needed for mooring.py + "line_mass": "t", # you need this for mooring.py (mooring installation module) + "line_cost": "USD", # you can calculate this based on each rope&chain length & diameter. + "line_length": "m", # this can be calculated from rope length and chain length (which you get from an empirical eqn as function of depth) + "anchor_mass": "t", # you need this for mooring.py (mooring installation module) + "anchor_type": "str", # keep, changed default to drag embedment. + "anchor_cost": "USD", # this can be calculated also as a function of (depth?) from the empirical data you have. + } + } + + def __init__(self, config, **kwargs): + """ + Creates an instance of MooringSystemDesign. + + Parameters + ---------- + config : dict + """ + + config = self.initialize_library(config, **kwargs) + self.config = self.validate_config(config) + self.num_turbines = self.config["plant"]["num_turbines"] + + self._design = self.config.get("mooring_system_design", {}) + self.num_lines = self._design.get("num_lines", 4) + self.anchor_type = self._design.get("anchor_type", "Drag Embedment") + + self._outputs = {} + + def run(self): + """ + Main run function. + """ + + self.calculate_line_length_mass() + self.determine_mooring_line_cost() + self.calculate_anchor_mass_cost() + + self._outputs["mooring_system"] = {**self.design_result} + + def calculate_line_length_mass(self): + """ + Returns the mooring line length and mass. + """ + + depth = self.config["site"]["depth"] + chain_diam = self.config["mooring_system"]["chain_diameter"] + rope_diam = self.config["mooring_system"]["rope_diameter"] + + # Input hybrid mooring system design from Cooperman et al. (2022), https://www.nrel.gov/docs/fy22osti/82341.pdf 'Assessment of Offshore Wind Energy Leasing Areas for Humboldt and Moorow Bay Wind Energy Areas, California + depths = np.array([500, 750, 1000, 1250, 1500]) + rope_lengths = np.array([478.41, 830.34, 1229.98, 1183.93, 1079.62]) + rope_diameters = np.array([0.2, 0.2, 0.2, 0.2, 0.2]) # you need the diameter for the cost data + chain_lengths = np.array([917.11, 800.36, 609.07, 896.42, 1280.57]) + chain_diameters = np.array([0.13, 0.17, 0.22, 0.22, 0.22]) + + # Interpolate + finterp_rope = interp1d(depths, rope_lengths) + finterp_chain = interp1d(depths, chain_lengths) + finterp_rope_diam = interp1d(depths, rope_diameters) + finterp_chain_diam = interp1d(depths, chain_diameters) + + # Rope and chain length at project depth + self.chain_length = finterp_chain(depth) + self.rope_length = finterp_rope(depth) + # Rope and chain diameter at project depth + self.rope_diameter = finterp_rope_diam(depth) + self.chain_diameter = finterp_chain_diam(depth) + + self.line_length = self.rope_length + self.chain_length + + chain_kg_per_m = 19900 * (self.chain_diameter**2) # 19,900 kg/m^2 (diameter)/m (length) + rope_kg_per_m = 797.8 * (self.rope_diameter**2) # 797.8 kg/ m^2 (diameter) / m (length) + self.line_mass = (self.chain_length * chain_kg_per_m) + (self.rope_length * rope_kg_per_m) # kg + print('total hybrid line mass is ' + str(self.line_mass)) + + def calculate_anchor_mass_cost(self): + """ + Returns the mass and cost of anchors. + + TODO: Anchor masses are rough estimates based on initial literature + review. Should be revised when this module is overhauled in the future. + """ + + if self.anchor_type == "Drag Embedment": + self.anchor_mass = 20 # t. This should be updated, but I don't have updated data right now for this. + # Input hybrid mooring system design from Cooperman et al. (2022), https://www.nrel.gov/docs/fy22osti/82341.pdf 'Assessment of Offshore Wind Energy Leasing Areas for Humboldt and Moorow Bay Wind Energy Areas, California + depths = np.array([500, 750, 1000, 1250, 1500]) + anchor_costs = np.array([112766, 125511, 148703, 204988, 246655]) # [USD] + + # interpolate anchor cost to project depth + depth = self.config["site"]["depth"] + finterp_anchor_cost = interp1d(depths, anchor_costs) + self.anchor_cost = finterp_anchor_cost(depth) # replace this with interp. function based on depth of hybrid mooring line + + @property + def line_cost(self): + """Returns cost of one line mooring line.""" + # Input hybrid mooring system design from Cooperman et al. (2022), https://www.nrel.gov/docs/fy22osti/82341.pdf 'Assessment of Offshore Wind Energy Leasing Areas for Humboldt and Moorow Bay Wind Energy Areas, California + depths = np.array([500, 750, 1000, 1250, 1500]) # [m] + total_line_costs = np.array([826598, 1221471, 1682208, 2380035, 3229700]) # [USD] + finterp_total_line_cost = interp1d(depths, total_line_costs) + depth = self.config["site"]["depth"] + self.line_cost = finterp_total_line_cost(depth) + return self.line_cost + + @property + def total_cost(self): + """Returns the total cost of the mooring system.""" + + return ( + self.num_lines + * self.num_turbines + * (self.anchor_cost + self.line_cost) + ) + + @property + def detailed_output(self): + """Returns detailed phase information.""" + + return { + "num_lines": self.num_lines, + #"line_diam": self.line_diam, + "line_mass": self.line_mass, + "line_length": self.line_length, + "line_cost": self.line_cost, + "anchor_type": self.anchor_type, + "anchor_mass": self.anchor_mass, + "anchor_cost": self.anchor_cost, + "system_cost": self.total_cost, + } + + @property + def design_result(self): + """Returns the results of the design phase.""" + + return {"mooring_system": self.detailed_output} diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py deleted file mode 100644 index f6af0053..00000000 --- a/ORBIT/phases/design/mooring_system_design.py +++ /dev/null @@ -1,151 +0,0 @@ -"""`MooringSystemDesign` and related functionality.""" - -__author__ = "Jake Nunemaker" -__copyright__ = "Copyright 2020, National Renewable Energy Laboratory" -__maintainer__ = "Jake Nunemaker" -__email__ = "jake.nunemaker@nrel.gov" - - -from math import sqrt - -from ORBIT.phases.design import DesignPhase - - -class MooringSystemDesign(DesignPhase): - """Mooring System and Anchor Design.""" - - expected_config = { - "site": {"depth": "float"}, - "turbine": {"turbine_rating": "int | float"}, - "plant": {"num_turbines": "int"}, - "mooring_system_design": { - "num_lines": "int | float (optional, default: 4)", - "anchor_type": "str (optional, default: 'Suction Pile')", - "mooring_line_cost_rate": "int | float (optional)", - "drag_embedment_fixed_length": "int | float (optional, default: .5km)", - }, - } - - output_config = { - "mooring_system": { - "num_lines": "int", - #"line_diam": "m, float", - "line_mass": "t", - "line_cost": "USD", - "line_length": "m", - "anchor_mass": "t", - "anchor_type": "str", - "anchor_cost": "USD", - } - } - - def __init__(self, config, **kwargs): - """ - Creates an instance of MooringSystemDesign. - - Parameters - ---------- - config : dict - """ - - config = self.initialize_library(config, **kwargs) - self.config = self.validate_config(config) - self.num_turbines = self.config["plant"]["num_turbines"] - - self._design = self.config.get("mooring_system_design", {}) - self.num_lines = self._design.get("num_lines", 4) - self.anchor_type = self._design.get("anchor_type", "Suction Pile") - - self._outputs = {} - - def run(self): - """ - Main run function. - """ - - self.determine_mooring_line() - #self.calculate_breaking_load() - self.calculate_line_length_mass() - self.calculate_anchor_mass_cost() - - self._outputs["mooring_system"] = {**self.design_result} - - def determine_mooring_line(self): - """ - Returns the diameter of the mooring lines based on the turbine rating. - """ - - self.line_cost = 999 # this is the result of a function of depth - - #def calculate_breaking_load(self): - # """ - # Returns the mooring line breaking load. - # """ - - # self.breaking_load = ( - # 419449 * (self.line_diam ** 2) + 93415 * self.line_diam - 3577.9 - # ) - - def calculate_line_length_mass(self): - """ - Returns the mooring line length and mass. - """ - - depth = self.config["site"]["depth"] - self.line_length = 999 # fill this in with fitted eqn result of total semitaut line length - - self.line_mass = self.line_length * self.line_mass_per_m - - def calculate_anchor_mass_cost(self): - """ - Returns the mass and cost of anchors. - - TODO: Anchor masses are rough estimates based on initial literature - review. Should be revised when this module is overhauled in the future. - """ - - if self.anchor_type == "Drag Embedment": - self.anchor_mass = 20 - self.anchor_cost = self.breaking_load / 9.81 / 20.0 * 2000.0 - - else: - self.anchor_mass = 50 - self.anchor_cost = 999 # make this output the cost as a function of depth (Matt H.) # sqrt(self.breaking_load / 9.81 / 1250) * 150000 - - @property - def line_cost(self): - """Returns cost of one line mooring line.""" - - return self.line_length * self.line_cost_rate - - @property - def total_cost(self): - """Returns the total cost of the mooring system.""" - - return ( - self.num_lines - * self.num_turbines - * (self.anchor_cost + self.line_length * self.line_cost_rate) - ) - - @property - def detailed_output(self): - """Returns detailed phase information.""" - - return { - "num_lines": self.num_lines, - #"line_diam": self.line_diam, - "line_mass": self.line_mass, - "line_length": self.line_length, - "line_cost": self.line_cost, - "anchor_type": self.anchor_type, - "anchor_mass": self.anchor_mass, - "anchor_cost": self.anchor_cost, - "system_cost": self.total_cost, - } - - @property - def design_result(self): - """Returns the results of the design phase.""" - - return {"mooring_system": self.detailed_output} diff --git a/examples/4. Example Fixed Project.ipynb b/examples/4. Example Fixed Project.ipynb index f8a4c389..e80ef45c 100644 --- a/examples/4. Example Fixed Project.ipynb +++ b/examples/4. Example Fixed Project.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -899,7 +899,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -913,7 +913,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.9.15" } }, "nbformat": 4, diff --git a/examples/configs/example_floating_project_mooring_update.yaml b/examples/configs/example_floating_project_mooring_update.yaml new file mode 100644 index 00000000..baad61c0 --- /dev/null +++ b/examples/configs/example_floating_project_mooring_update.yaml @@ -0,0 +1,55 @@ +# Site + Plant Parameters +site: + depth: 900 + distance: 100 + distance_to_landfall: 100 +plant: + layout: ring + num_turbines: 50 + row_spacing: 7 + substation_distance: 1 + turbine_spacing: 7 +port: + monthly_rate: 2000000.0 + sub_assembly_lines: 1 + turbine_assembly_cranes: 1 +# Vessels +array_cable_install_vessel: example_cable_lay_vessel +export_cable_install_vessel: example_cable_lay_vessel +mooring_install_vessel: example_support_vessel +oss_install_vessel: floating_heavy_lift_vessel +support_vessel: example_support_vessel +towing_vessel: example_towing_vessel +towing_vessel_groups: + station_keeping_vessels: 2 + towing_vessels: 3 +wtiv: floating_heavy_lift_vessel +# Module Specific +substructure: + takt_time: 168 +OffshoreSubstationInstallation: + feeder: floating_barge +array_system: + free_cable_length: 0.5 +array_system_design: + cables: + - XLPE_630mm_66kV +export_system_design: + cables: XLPE_500mm_132kV + percent_added_length: 0.0 +# Configured Phases +design_phases: +- ArraySystemDesign +- ExportSystemDesign +- MooringSystemDesign +- OffshoreSubstationDesign +- SemiSubmersibleDesign +install_phases: + ArrayCableInstallation: 0 + ExportCableInstallation: 0 + MooredSubInstallation: 0 + MooringSystemInstallation: 0 + OffshoreSubstationInstallation: 0 + TurbineInstallation: 0 +# Project Inputs +turbine: 12MW_generic From 5b4023f553fc51801e9d0476b719aa5dfa38a90e Mon Sep 17 00:00:00 2001 From: Becca Rolph Date: Fri, 20 Jan 2023 16:56:38 -0700 Subject: [PATCH 04/71] Added SemiTaut design phase to design init --- examples/4. Example Fixed Project.ipynb | 2 +- ...5. Example Floating Project-SemiTaut.ipynb | 210 ++++++++++++++++++ ...=> example_floating_project_SemiTaut.yaml} | 2 +- 3 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 examples/5. Example Floating Project-SemiTaut.ipynb rename examples/configs/{example_floating_project_mooring_update.yaml => example_floating_project_SemiTaut.yaml} (97%) diff --git a/examples/4. Example Fixed Project.ipynb b/examples/4. Example Fixed Project.ipynb index e80ef45c..d01275cb 100644 --- a/examples/4. Example Fixed Project.ipynb +++ b/examples/4. Example Fixed Project.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ diff --git a/examples/5. Example Floating Project-SemiTaut.ipynb b/examples/5. Example Floating Project-SemiTaut.ipynb new file mode 100644 index 00000000..0ef7f6b3 --- /dev/null +++ b/examples/5. Example Floating Project-SemiTaut.ipynb @@ -0,0 +1,210 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Jake Nunemaker\n", + "\n", + "National Renewable Energy Lab\n", + "\n", + "Last updated: 12/23/2020" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import pandas as pd\n", + "from ORBIT import ProjectManager, load_config \n", + "\n", + "weather = pd.read_csv(\"data/example_weather.csv\", parse_dates=[\"datetime\"])\\\n", + " .set_index(\"datetime\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load the project configuration" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Num turbines: 50\n", + "Turbine: 12MW_generic\n", + "\n", + "Site: {'depth': 900, 'distance': 100, 'distance_to_landfall': 100}\n" + ] + } + ], + "source": [ + "fixed_config = load_config(\"configs/example_floating_project_SemiTaut.yaml\") \n", + "\n", + "print(f\"Num turbines: {fixed_config['plant']['num_turbines']}\")\n", + "print(f\"Turbine: {fixed_config['turbine']}\")\n", + "print(f\"\\nSite: {fixed_config['site']}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Phases" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Design phases: ['ArraySystemDesign', 'ExportSystemDesign', 'SemiTautMooringSystemDesign', 'OffshoreSubstationDesign', 'SemiSubmersibleDesign']\n", + "\n", + "Install phases: ['ArrayCableInstallation', 'ExportCableInstallation', 'MooredSubInstallation', 'MooringSystemInstallation', 'OffshoreSubstationInstallation', 'TurbineInstallation']\n" + ] + } + ], + "source": [ + "print(f\"Design phases: {fixed_config['design_phases']}\")\n", + "print(f\"\\nInstall phases: {list(fixed_config['install_phases'].keys())}\")\n", + "# This now says \"SemiTautMooringSystemDesign\" in the design phases" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ORBIT library intialized at 'C:\\Users\\rrolph\\OneDrive - NREL\\ORBIT\\library'\n" + ] + }, + { + "ename": "PhaseNotFound", + "evalue": "Unrecognized phase 'SemiTautMooringSystemDesign'.", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mPhaseNotFound\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[4], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m project \u001b[38;5;241m=\u001b[39m ProjectManager(fixed_config, weather\u001b[38;5;241m=\u001b[39mweather)\n\u001b[1;32m----> 2\u001b[0m \u001b[43mproject\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32m~\\OneDrive - NREL\\ORBIT\\ORBIT\\manager.py:157\u001b[0m, in \u001b[0;36mProjectManager.run\u001b[1;34m(self, **kwargs)\u001b[0m\n\u001b[0;32m 154\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(install_phases, \u001b[38;5;28mstr\u001b[39m):\n\u001b[0;32m 155\u001b[0m install_phases \u001b[38;5;241m=\u001b[39m [install_phases]\n\u001b[1;32m--> 157\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_all_design_phases(design_phases, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m 159\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(install_phases, (\u001b[38;5;28mlist\u001b[39m, \u001b[38;5;28mset\u001b[39m)):\n\u001b[0;32m 160\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_multiple_phases_in_serial(install_phases, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[1;32m~\\OneDrive - NREL\\ORBIT\\ORBIT\\manager.py:610\u001b[0m, in \u001b[0;36mProjectManager.run_all_design_phases\u001b[1;34m(self, phase_list, **kwargs)\u001b[0m\n\u001b[0;32m 605\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 606\u001b[0m \u001b[38;5;124;03mRuns multiple design phases and adds '.design_result' to self.config.\u001b[39;00m\n\u001b[0;32m 607\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 609\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m name \u001b[38;5;129;01min\u001b[39;00m phase_list:\n\u001b[1;32m--> 610\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_design_phase(name, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[1;32m~\\OneDrive - NREL\\ORBIT\\ORBIT\\manager.py:624\u001b[0m, in \u001b[0;36mProjectManager.run_design_phase\u001b[1;34m(self, name, **kwargs)\u001b[0m\n\u001b[0;32m 613\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 614\u001b[0m \u001b[38;5;124;03mRuns a design phase defined by 'name' and merges the '.design_result'\u001b[39;00m\n\u001b[0;32m 615\u001b[0m \u001b[38;5;124;03minto self.config.\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 620\u001b[0m \u001b[38;5;124;03m Name of design phase that partially matches a key in `phase_dict`.\u001b[39;00m\n\u001b[0;32m 621\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 623\u001b[0m _catch \u001b[38;5;241m=\u001b[39m kwargs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcatch_exceptions\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mFalse\u001b[39;00m)\n\u001b[1;32m--> 624\u001b[0m _class \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_phase_class\u001b[49m\u001b[43m(\u001b[49m\u001b[43mname\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 625\u001b[0m _config \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcreate_config_for_phase(name)\n\u001b[0;32m 627\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m _catch:\n", + "File \u001b[1;32m~\\OneDrive - NREL\\ORBIT\\ORBIT\\manager.py:600\u001b[0m, in \u001b[0;36mProjectManager.get_phase_class\u001b[1;34m(self, phase)\u001b[0m\n\u001b[0;32m 598\u001b[0m phase_class \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfind_key_match(phase)\n\u001b[0;32m 599\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m phase_class \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m--> 600\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m PhaseNotFound(phase)\n\u001b[0;32m 602\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m phase_class\n", + "\u001b[1;31mPhaseNotFound\u001b[0m: Unrecognized phase 'SemiTautMooringSystemDesign'." + ] + } + ], + "source": [ + "project = ProjectManager(fixed_config, weather=weather)\n", + "project.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Top Level Outputs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(f\"Installation CapEx: {project.installation_capex/1e6:.0f} M\")\n", + "print(f\"System CapEx: {project.system_capex/1e6:.0f} M\")\n", + "print(f\"Turbine CapEx: {project.turbine_capex/1e6:.0f} M\")\n", + "print(f\"Soft CapEx: {project.soft_capex/1e6:.0f} M\")\n", + "print(f\"Total CapEx: {project.total_capex/1e6:.0f} M\")\n", + "\n", + "print(f\"\\nInstallation Time: {project.installation_time:.0f} h\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### CapEx Breakdown" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "project.capex_breakdown" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Installation Actions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pd.DataFrame(project.actions)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.9.15" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/configs/example_floating_project_mooring_update.yaml b/examples/configs/example_floating_project_SemiTaut.yaml similarity index 97% rename from examples/configs/example_floating_project_mooring_update.yaml rename to examples/configs/example_floating_project_SemiTaut.yaml index baad61c0..05ef5a8d 100644 --- a/examples/configs/example_floating_project_mooring_update.yaml +++ b/examples/configs/example_floating_project_SemiTaut.yaml @@ -41,7 +41,7 @@ export_system_design: design_phases: - ArraySystemDesign - ExportSystemDesign -- MooringSystemDesign +- SemiTautMooringSystemDesign - OffshoreSubstationDesign - SemiSubmersibleDesign install_phases: From c5b72f99f11c6ffd80c0588c1697cc8a6fbaf171 Mon Sep 17 00:00:00 2001 From: Becca Rolph Date: Fri, 20 Jan 2023 17:40:50 -0700 Subject: [PATCH 05/71] fixed import so new semitaut design module is running. might be giving too low of a cost for the hybrid mooring system compared to other projects --- ORBIT/manager.py | 2 + .../design/SemiTaut_mooring_system_design.py | 18 +- ORBIT/phases/design/__init__.py | 1 + ORBIT/phases/design/mooring_system_design.py | 175 ++++++++ ...5. Example Floating Project-SemiTaut.ipynb | 396 +++++++++++++++++- 5 files changed, 559 insertions(+), 33 deletions(-) create mode 100644 ORBIT/phases/design/mooring_system_design.py diff --git a/ORBIT/manager.py b/ORBIT/manager.py index 6aeb5ba1..d87e5d00 100644 --- a/ORBIT/manager.py +++ b/ORBIT/manager.py @@ -30,6 +30,7 @@ ArraySystemDesign, ExportSystemDesign, MooringSystemDesign, + SemiTautMooringSystemDesign, ScourProtectionDesign, SemiSubmersibleDesign, CustomArraySystemDesign, @@ -69,6 +70,7 @@ class ProjectManager: ScourProtectionDesign, OffshoreSubstationDesign, MooringSystemDesign, + SemiTautMooringSystemDesign, SemiSubmersibleDesign, SparDesign, ) diff --git a/ORBIT/phases/design/SemiTaut_mooring_system_design.py b/ORBIT/phases/design/SemiTaut_mooring_system_design.py index fcd68a37..bcd62465 100644 --- a/ORBIT/phases/design/SemiTaut_mooring_system_design.py +++ b/ORBIT/phases/design/SemiTaut_mooring_system_design.py @@ -1,13 +1,10 @@ """`MooringSystemDesign` and related functionality.""" -__author__ = "Jake Nunemaker" +__author__ = "Jake Nunemaker, modified by Becca F." __copyright__ = "Copyright 2020, National Renewable Energy Laboratory" __maintainer__ = "Jake Nunemaker" -__email__ = "jake.nunemaker@nrel.gov" +__email__ = "jake.nunemaker@nrel.gov & rebecca.fuchs@nrel.gov" - -from math import sqrt -from scipy import optimize from scipy.interpolate import interp1d import numpy as np @@ -78,9 +75,7 @@ def calculate_line_length_mass(self): """ depth = self.config["site"]["depth"] - chain_diam = self.config["mooring_system"]["chain_diameter"] - rope_diam = self.config["mooring_system"]["rope_diameter"] - + # Input hybrid mooring system design from Cooperman et al. (2022), https://www.nrel.gov/docs/fy22osti/82341.pdf 'Assessment of Offshore Wind Energy Leasing Areas for Humboldt and Moorow Bay Wind Energy Areas, California depths = np.array([500, 750, 1000, 1250, 1500]) rope_lengths = np.array([478.41, 830.34, 1229.98, 1183.93, 1079.62]) @@ -106,7 +101,9 @@ def calculate_line_length_mass(self): chain_kg_per_m = 19900 * (self.chain_diameter**2) # 19,900 kg/m^2 (diameter)/m (length) rope_kg_per_m = 797.8 * (self.rope_diameter**2) # 797.8 kg/ m^2 (diameter) / m (length) self.line_mass = (self.chain_length * chain_kg_per_m) + (self.rope_length * rope_kg_per_m) # kg - print('total hybrid line mass is ' + str(self.line_mass)) + print('total hybrid line mass is ' + str(self.line_mass) + 'kg') + # convert kg to metric tonnes + self.line_mass = self.line_mass/1e3 def calculate_anchor_mass_cost(self): """ @@ -127,8 +124,7 @@ def calculate_anchor_mass_cost(self): finterp_anchor_cost = interp1d(depths, anchor_costs) self.anchor_cost = finterp_anchor_cost(depth) # replace this with interp. function based on depth of hybrid mooring line - @property - def line_cost(self): + def determine_mooring_line_cost(self): """Returns cost of one line mooring line.""" # Input hybrid mooring system design from Cooperman et al. (2022), https://www.nrel.gov/docs/fy22osti/82341.pdf 'Assessment of Offshore Wind Energy Leasing Areas for Humboldt and Moorow Bay Wind Energy Areas, California depths = np.array([500, 750, 1000, 1250, 1500]) # [m] diff --git a/ORBIT/phases/design/__init__.py b/ORBIT/phases/design/__init__.py index d234df4c..7d74fa37 100644 --- a/ORBIT/phases/design/__init__.py +++ b/ORBIT/phases/design/__init__.py @@ -13,5 +13,6 @@ from .array_system_design import ArraySystemDesign, CustomArraySystemDesign from .export_system_design import ExportSystemDesign from .mooring_system_design import MooringSystemDesign +from .SemiTaut_mooring_system_design import SemiTautMooringSystemDesign from .scour_protection_design import ScourProtectionDesign from .semi_submersible_design import SemiSubmersibleDesign diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py new file mode 100644 index 00000000..383a4924 --- /dev/null +++ b/ORBIT/phases/design/mooring_system_design.py @@ -0,0 +1,175 @@ +"""`MooringSystemDesign` and related functionality.""" + +__author__ = "Jake Nunemaker" +__copyright__ = "Copyright 2020, National Renewable Energy Laboratory" +__maintainer__ = "Jake Nunemaker" +__email__ = "jake.nunemaker@nrel.gov" + + +from math import sqrt + +from ORBIT.phases.design import DesignPhase + + +class MooringSystemDesign(DesignPhase): + """Mooring System and Anchor Design.""" + + expected_config = { + "site": {"depth": "float"}, + "turbine": {"turbine_rating": "int | float"}, + "plant": {"num_turbines": "int"}, + "mooring_system_design": { + "num_lines": "int | float (optional, default: 4)", + "anchor_type": "str (optional, default: 'Suction Pile')", + "mooring_line_cost_rate": "int | float (optional)", + "drag_embedment_fixed_length": "int | float (optional, default: .5km)", + }, + } + + output_config = { + "mooring_system": { + "num_lines": "int", + "line_diam": "m, float", + "line_mass": "t", + "line_cost": "USD", + "line_length": "m", + "anchor_mass": "t", + "anchor_type": "str", + "anchor_cost": "USD", + } + } + + def __init__(self, config, **kwargs): + """ + Creates an instance of MooringSystemDesign. + + Parameters + ---------- + config : dict + """ + + config = self.initialize_library(config, **kwargs) + self.config = self.validate_config(config) + self.num_turbines = self.config["plant"]["num_turbines"] + + self._design = self.config.get("mooring_system_design", {}) + self.num_lines = self._design.get("num_lines", 4) + self.anchor_type = self._design.get("anchor_type", "Suction Pile") + + self._outputs = {} + + def run(self): + """ + Main run function. + """ + + self.determine_mooring_line() + self.calculate_breaking_load() + self.calculate_line_length_mass() + self.calculate_anchor_mass_cost() + + self._outputs["mooring_system"] = {**self.design_result} + + def determine_mooring_line(self): + """ + Returns the diameter of the mooring lines based on the turbine rating. + """ + + tr = self.config["turbine"]["turbine_rating"] + fit = -0.0004 * (tr ** 2) + 0.0132 * tr + 0.0536 + + if fit <= 0.09: + self.line_diam = 0.09 + self.line_mass_per_m = 0.161 + self.line_cost_rate = 399.0 + + elif fit <= 0.12: + self.line_diam = 0.12 + self.line_mass_per_m = 0.288 + self.line_cost_rate = 721.0 + + else: + self.line_diam = 0.15 + self.line_mass_per_m = 0.450 + self.line_cost_rate = 1088.0 + + def calculate_breaking_load(self): + """ + Returns the mooring line breaking load. + """ + + self.breaking_load = ( + 419449 * (self.line_diam ** 2) + 93415 * self.line_diam - 3577.9 + ) + + def calculate_line_length_mass(self): + """ + Returns the mooring line length and mass. + """ + + if self.anchor_type == "Drag Embedment": + fixed = self._design.get("drag_embedment_fixed_length", 500) + + else: + fixed = 0 + + depth = self.config["site"]["depth"] + self.line_length = ( + 0.0002 * (depth ** 2) + 1.264 * depth + 47.776 + fixed + ) + + self.line_mass = self.line_length * self.line_mass_per_m + + def calculate_anchor_mass_cost(self): + """ + Returns the mass and cost of anchors. + + TODO: Anchor masses are rough estimates based on initial literature + review. Should be revised when this module is overhauled in the future. + """ + + if self.anchor_type == "Drag Embedment": + self.anchor_mass = 20 + self.anchor_cost = self.breaking_load / 9.81 / 20.0 * 2000.0 + + else: + self.anchor_mass = 50 + self.anchor_cost = sqrt(self.breaking_load / 9.81 / 1250) * 150000 + + @property + def line_cost(self): + """Returns cost of one line mooring line.""" + + return self.line_length * self.line_cost_rate + + @property + def total_cost(self): + """Returns the total cost of the mooring system.""" + + return ( + self.num_lines + * self.num_turbines + * (self.anchor_cost + self.line_length * self.line_cost_rate) + ) + + @property + def detailed_output(self): + """Returns detailed phase information.""" + + return { + "num_lines": self.num_lines, + "line_diam": self.line_diam, + "line_mass": self.line_mass, + "line_length": self.line_length, + "line_cost": self.line_cost, + "anchor_type": self.anchor_type, + "anchor_mass": self.anchor_mass, + "anchor_cost": self.anchor_cost, + "system_cost": self.total_cost, + } + + @property + def design_result(self): + """Returns the results of the design phase.""" + + return {"mooring_system": self.detailed_output} diff --git a/examples/5. Example Floating Project-SemiTaut.ipynb b/examples/5. Example Floating Project-SemiTaut.ipynb index 0ef7f6b3..03f2ac83 100644 --- a/examples/5. Example Floating Project-SemiTaut.ipynb +++ b/examples/5. Example Floating Project-SemiTaut.ipynb @@ -100,22 +100,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "ORBIT library intialized at 'C:\\Users\\rrolph\\OneDrive - NREL\\ORBIT\\library'\n" - ] - }, - { - "ename": "PhaseNotFound", - "evalue": "Unrecognized phase 'SemiTautMooringSystemDesign'.", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mPhaseNotFound\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[4], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m project \u001b[38;5;241m=\u001b[39m ProjectManager(fixed_config, weather\u001b[38;5;241m=\u001b[39mweather)\n\u001b[1;32m----> 2\u001b[0m \u001b[43mproject\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[1;32m~\\OneDrive - NREL\\ORBIT\\ORBIT\\manager.py:157\u001b[0m, in \u001b[0;36mProjectManager.run\u001b[1;34m(self, **kwargs)\u001b[0m\n\u001b[0;32m 154\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(install_phases, \u001b[38;5;28mstr\u001b[39m):\n\u001b[0;32m 155\u001b[0m install_phases \u001b[38;5;241m=\u001b[39m [install_phases]\n\u001b[1;32m--> 157\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_all_design_phases(design_phases, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m 159\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(install_phases, (\u001b[38;5;28mlist\u001b[39m, \u001b[38;5;28mset\u001b[39m)):\n\u001b[0;32m 160\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_multiple_phases_in_serial(install_phases, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", - "File \u001b[1;32m~\\OneDrive - NREL\\ORBIT\\ORBIT\\manager.py:610\u001b[0m, in \u001b[0;36mProjectManager.run_all_design_phases\u001b[1;34m(self, phase_list, **kwargs)\u001b[0m\n\u001b[0;32m 605\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 606\u001b[0m \u001b[38;5;124;03mRuns multiple design phases and adds '.design_result' to self.config.\u001b[39;00m\n\u001b[0;32m 607\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 609\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m name \u001b[38;5;129;01min\u001b[39;00m phase_list:\n\u001b[1;32m--> 610\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_design_phase(name, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", - "File \u001b[1;32m~\\OneDrive - NREL\\ORBIT\\ORBIT\\manager.py:624\u001b[0m, in \u001b[0;36mProjectManager.run_design_phase\u001b[1;34m(self, name, **kwargs)\u001b[0m\n\u001b[0;32m 613\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 614\u001b[0m \u001b[38;5;124;03mRuns a design phase defined by 'name' and merges the '.design_result'\u001b[39;00m\n\u001b[0;32m 615\u001b[0m \u001b[38;5;124;03minto self.config.\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 620\u001b[0m \u001b[38;5;124;03m Name of design phase that partially matches a key in `phase_dict`.\u001b[39;00m\n\u001b[0;32m 621\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 623\u001b[0m _catch \u001b[38;5;241m=\u001b[39m kwargs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcatch_exceptions\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mFalse\u001b[39;00m)\n\u001b[1;32m--> 624\u001b[0m _class \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_phase_class\u001b[49m\u001b[43m(\u001b[49m\u001b[43mname\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 625\u001b[0m _config \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcreate_config_for_phase(name)\n\u001b[0;32m 627\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m _catch:\n", - "File \u001b[1;32m~\\OneDrive - NREL\\ORBIT\\ORBIT\\manager.py:600\u001b[0m, in \u001b[0;36mProjectManager.get_phase_class\u001b[1;34m(self, phase)\u001b[0m\n\u001b[0;32m 598\u001b[0m phase_class \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfind_key_match(phase)\n\u001b[0;32m 599\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m phase_class \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m--> 600\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m PhaseNotFound(phase)\n\u001b[0;32m 602\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m phase_class\n", - "\u001b[1;31mPhaseNotFound\u001b[0m: Unrecognized phase 'SemiTautMooringSystemDesign'." + "ORBIT library intialized at 'C:\\Users\\rrolph\\OneDrive - NREL\\ORBIT\\library'\n", + "total hybrid line mass is 579876.2530880001kg\n" ] } ], @@ -133,9 +119,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installation CapEx: 418 M\n", + "System CapEx: 1218 M\n", + "Turbine CapEx: 780 M\n", + "Soft CapEx: 387 M\n", + "Total CapEx: 2955 M\n", + "\n", + "Installation Time: 27501 h\n" + ] + } + ], "source": [ "print(f\"Installation CapEx: {project.installation_capex/1e6:.0f} M\")\n", "print(f\"System CapEx: {project.system_capex/1e6:.0f} M\")\n", @@ -155,9 +155,33 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "{'Array System': 56983076.60642063,\n", + " 'Export System': 103712476.9152,\n", + " 'Substructure': 630709636.6,\n", + " 'Mooring System': 327467880.0,\n", + " 'Offshore Substation': 99479100.0,\n", + " 'Array System Installation': 22844527.89607126,\n", + " 'Export System Installation': 135112258.0470523,\n", + " 'Substructure Installation': 78569120.05327243,\n", + " 'Mooring System Installation': 48485331.05022831,\n", + " 'Offshore Substation Installation': 5499328.911719939,\n", + " 'Turbine Installation': 127738070.77625567,\n", + " 'Turbine': 780000000,\n", + " 'Soft': 387000000,\n", + " 'Project': 151250000.0}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "project.capex_breakdown" ] @@ -171,9 +195,337 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cost_multiplieragentactiondurationcostleveltimephaselocationsite_depthhub_heightphase_namemax_waveheightmax_windspeedtransit_speednum_vessels
00.5Array Cable Installation VesselMobilize72.0000001.800000e+05ACTION0.000000ArrayCableInstallationNaNNaNNaNNaNNaNNaNNaNNaN
10.5Export Cable Installation VesselMobilize72.0000001.800000e+05ACTION0.000000ExportCableInstallationNaNNaNNaNNaNNaNNaNNaNNaN
2NaNOnshore ConstructionOnshore Construction0.0000001.075454e+08ACTION0.000000ExportCableInstallationLandfallNaNNaNNaNNaNNaNNaNNaN
31.0Mooring System Installation VesselMobilize168.0000007.000000e+05ACTION0.000000MooringSystemInstallationNaNNaNNaNNaNNaNNaNNaNNaN
40.5Heavy Lift VesselMobilize72.0000007.500000e+05ACTION0.000000OffshoreSubstationInstallationNaNNaNNaNNaNNaNNaNNaNNaN
...................................................
4334NaNMulti-Purpose Support VesselConnect Mooring Lines, Pre-tension and pre-str...20.0000008.333333e+04ACTION8544.500000MooredSubInstallationNaNNaNNaNNaNNaNNaNNaNNaN
4335NaNMulti-Purpose Support VesselCheck Mooring Lines6.0000002.500000e+04ACTION8550.500000MooredSubInstallationNaNNaNNaNNaNNaNNaNNaNNaN
4336NaNTowing Group 1Positioning Support34.0000008.500000e+04ACTION8550.500000MooredSubInstallationsiteNaNNaNNaNNaNNaNNaN2.0
4337NaNMulti-Purpose Support VesselTransit10.0000004.166667e+04ACTION8560.500000MooredSubInstallationNaNNaNNaNNaNNaNNaNNaNNaN
4338NaNTowing Group 1Transit16.6666676.250000e+04ACTION8567.166667MooredSubInstallationNaNNaNNaNNaNNaNNaNNaN3.0
\n", + "

4339 rows Ă— 16 columns

\n", + "
" + ], + "text/plain": [ + " cost_multiplier agent \\\n", + "0 0.5 Array Cable Installation Vessel \n", + "1 0.5 Export Cable Installation Vessel \n", + "2 NaN Onshore Construction \n", + "3 1.0 Mooring System Installation Vessel \n", + "4 0.5 Heavy Lift Vessel \n", + "... ... ... \n", + "4334 NaN Multi-Purpose Support Vessel \n", + "4335 NaN Multi-Purpose Support Vessel \n", + "4336 NaN Towing Group 1 \n", + "4337 NaN Multi-Purpose Support Vessel \n", + "4338 NaN Towing Group 1 \n", + "\n", + " action duration \\\n", + "0 Mobilize 72.000000 \n", + "1 Mobilize 72.000000 \n", + "2 Onshore Construction 0.000000 \n", + "3 Mobilize 168.000000 \n", + "4 Mobilize 72.000000 \n", + "... ... ... \n", + "4334 Connect Mooring Lines, Pre-tension and pre-str... 20.000000 \n", + "4335 Check Mooring Lines 6.000000 \n", + "4336 Positioning Support 34.000000 \n", + "4337 Transit 10.000000 \n", + "4338 Transit 16.666667 \n", + "\n", + " cost level time phase \\\n", + "0 1.800000e+05 ACTION 0.000000 ArrayCableInstallation \n", + "1 1.800000e+05 ACTION 0.000000 ExportCableInstallation \n", + "2 1.075454e+08 ACTION 0.000000 ExportCableInstallation \n", + "3 7.000000e+05 ACTION 0.000000 MooringSystemInstallation \n", + "4 7.500000e+05 ACTION 0.000000 OffshoreSubstationInstallation \n", + "... ... ... ... ... \n", + "4334 8.333333e+04 ACTION 8544.500000 MooredSubInstallation \n", + "4335 2.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", + "4336 8.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", + "4337 4.166667e+04 ACTION 8560.500000 MooredSubInstallation \n", + "4338 6.250000e+04 ACTION 8567.166667 MooredSubInstallation \n", + "\n", + " location site_depth hub_height phase_name max_waveheight \\\n", + "0 NaN NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN NaN \n", + "2 Landfall NaN NaN NaN NaN \n", + "3 NaN NaN NaN NaN NaN \n", + "4 NaN NaN NaN NaN NaN \n", + "... ... ... ... ... ... \n", + "4334 NaN NaN NaN NaN NaN \n", + "4335 NaN NaN NaN NaN NaN \n", + "4336 site NaN NaN NaN NaN \n", + "4337 NaN NaN NaN NaN NaN \n", + "4338 NaN NaN NaN NaN NaN \n", + "\n", + " max_windspeed transit_speed num_vessels \n", + "0 NaN NaN NaN \n", + "1 NaN NaN NaN \n", + "2 NaN NaN NaN \n", + "3 NaN NaN NaN \n", + "4 NaN NaN NaN \n", + "... ... ... ... \n", + "4334 NaN NaN NaN \n", + "4335 NaN NaN NaN \n", + "4336 NaN NaN 2.0 \n", + "4337 NaN NaN NaN \n", + "4338 NaN NaN 3.0 \n", + "\n", + "[4339 rows x 16 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "pd.DataFrame(project.actions)" ] From 047213088d644ee1ebd275a0b801308ef00a6ef1 Mon Sep 17 00:00:00 2001 From: Becca Rolph Date: Tue, 24 Jan 2023 13:39:38 -0700 Subject: [PATCH 06/71] Changed water depth to match comparison project --- ...5. Example Floating Project-SemiTaut.ipynb | 110 +++++++++--------- .../example_floating_project_SemiTaut.yaml | 2 +- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/examples/5. Example Floating Project-SemiTaut.ipynb b/examples/5. Example Floating Project-SemiTaut.ipynb index 03f2ac83..23899e96 100644 --- a/examples/5. Example Floating Project-SemiTaut.ipynb +++ b/examples/5. Example Floating Project-SemiTaut.ipynb @@ -44,7 +44,7 @@ "Num turbines: 50\n", "Turbine: 12MW_generic\n", "\n", - "Site: {'depth': 900, 'distance': 100, 'distance_to_landfall': 100}\n" + "Site: {'depth': 500, 'distance': 100, 'distance_to_landfall': 100}\n" ] } ], @@ -101,7 +101,7 @@ "output_type": "stream", "text": [ "ORBIT library intialized at 'C:\\Users\\rrolph\\OneDrive - NREL\\ORBIT\\library'\n", - "total hybrid line mass is 579876.2530880001kg\n" + "total hybrid line mass is 323700.2840200001kg\n" ] } ], @@ -126,13 +126,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "Installation CapEx: 418 M\n", - "System CapEx: 1218 M\n", + "Installation CapEx: 410 M\n", + "System CapEx: 1066 M\n", "Turbine CapEx: 780 M\n", "Soft CapEx: 387 M\n", - "Total CapEx: 2955 M\n", + "Total CapEx: 2794 M\n", "\n", - "Installation Time: 27501 h\n" + "Installation Time: 26286 h\n" ] } ], @@ -155,35 +155,35 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'Array System': 56983076.60642063,\n", - " 'Export System': 103712476.9152,\n", - " 'Substructure': 630709636.6,\n", - " 'Mooring System': 327467880.0,\n", - " 'Offshore Substation': 99479100.0,\n", - " 'Array System Installation': 22844527.89607126,\n", - " 'Export System Installation': 135112258.0470523,\n", - " 'Substructure Installation': 78569120.05327243,\n", - " 'Mooring System Installation': 48485331.05022831,\n", - " 'Offshore Substation Installation': 5499328.911719939,\n", - " 'Turbine Installation': 127738070.77625567,\n", - " 'Turbine': 780000000,\n", - " 'Soft': 387000000,\n", - " 'Project': 151250000.0}" + "{'Array System': 73.86136722816696,\n", + " 'Export System': 172.32636751400003,\n", + " 'Substructure': 1051.1827276666668,\n", + " 'Mooring System': 313.1213333333333,\n", + " 'Offshore Substation': 165.7985,\n", + " 'Array System Installation': 35.42268447056795,\n", + " 'Export System Installation': 225.18351574438626,\n", + " 'Substructure Installation': 130.9485334221207,\n", + " 'Mooring System Installation': 69.2752092846271,\n", + " 'Offshore Substation Installation': 8.780764320142058,\n", + " 'Turbine Installation': 212.89678462709279,\n", + " 'Turbine': 1300.0,\n", + " 'Soft': 645.0,\n", + " 'Project': 252.08333333333334}" ] }, - "execution_count": 6, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "project.capex_breakdown" + "project.capex_breakdown_per_kw" ] }, { @@ -353,7 +353,7 @@ " ...\n", " \n", " \n", - " 4334\n", + " 4317\n", " NaN\n", " Multi-Purpose Support Vessel\n", " Connect Mooring Lines, Pre-tension and pre-str...\n", @@ -372,7 +372,7 @@ " NaN\n", " \n", " \n", - " 4335\n", + " 4318\n", " NaN\n", " Multi-Purpose Support Vessel\n", " Check Mooring Lines\n", @@ -391,7 +391,7 @@ " NaN\n", " \n", " \n", - " 4336\n", + " 4319\n", " NaN\n", " Towing Group 1\n", " Positioning Support\n", @@ -410,7 +410,7 @@ " 2.0\n", " \n", " \n", - " 4337\n", + " 4320\n", " NaN\n", " Multi-Purpose Support Vessel\n", " Transit\n", @@ -429,7 +429,7 @@ " NaN\n", " \n", " \n", - " 4338\n", + " 4321\n", " NaN\n", " Towing Group 1\n", " Transit\n", @@ -449,7 +449,7 @@ " \n", " \n", "\n", - "

4339 rows Ă— 16 columns

\n", + "

4322 rows Ă— 16 columns

\n", "" ], "text/plain": [ @@ -460,11 +460,11 @@ "3 1.0 Mooring System Installation Vessel \n", "4 0.5 Heavy Lift Vessel \n", "... ... ... \n", - "4334 NaN Multi-Purpose Support Vessel \n", - "4335 NaN Multi-Purpose Support Vessel \n", - "4336 NaN Towing Group 1 \n", - "4337 NaN Multi-Purpose Support Vessel \n", - "4338 NaN Towing Group 1 \n", + "4317 NaN Multi-Purpose Support Vessel \n", + "4318 NaN Multi-Purpose Support Vessel \n", + "4319 NaN Towing Group 1 \n", + "4320 NaN Multi-Purpose Support Vessel \n", + "4321 NaN Towing Group 1 \n", "\n", " action duration \\\n", "0 Mobilize 72.000000 \n", @@ -473,11 +473,11 @@ "3 Mobilize 168.000000 \n", "4 Mobilize 72.000000 \n", "... ... ... \n", - "4334 Connect Mooring Lines, Pre-tension and pre-str... 20.000000 \n", - "4335 Check Mooring Lines 6.000000 \n", - "4336 Positioning Support 34.000000 \n", - "4337 Transit 10.000000 \n", - "4338 Transit 16.666667 \n", + "4317 Connect Mooring Lines, Pre-tension and pre-str... 20.000000 \n", + "4318 Check Mooring Lines 6.000000 \n", + "4319 Positioning Support 34.000000 \n", + "4320 Transit 10.000000 \n", + "4321 Transit 16.666667 \n", "\n", " cost level time phase \\\n", "0 1.800000e+05 ACTION 0.000000 ArrayCableInstallation \n", @@ -486,11 +486,11 @@ "3 7.000000e+05 ACTION 0.000000 MooringSystemInstallation \n", "4 7.500000e+05 ACTION 0.000000 OffshoreSubstationInstallation \n", "... ... ... ... ... \n", - "4334 8.333333e+04 ACTION 8544.500000 MooredSubInstallation \n", - "4335 2.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", - "4336 8.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", - "4337 4.166667e+04 ACTION 8560.500000 MooredSubInstallation \n", - "4338 6.250000e+04 ACTION 8567.166667 MooredSubInstallation \n", + "4317 8.333333e+04 ACTION 8544.500000 MooredSubInstallation \n", + "4318 2.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", + "4319 8.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", + "4320 4.166667e+04 ACTION 8560.500000 MooredSubInstallation \n", + "4321 6.250000e+04 ACTION 8567.166667 MooredSubInstallation \n", "\n", " location site_depth hub_height phase_name max_waveheight \\\n", "0 NaN NaN NaN NaN NaN \n", @@ -499,11 +499,11 @@ "3 NaN NaN NaN NaN NaN \n", "4 NaN NaN NaN NaN NaN \n", "... ... ... ... ... ... \n", - "4334 NaN NaN NaN NaN NaN \n", - "4335 NaN NaN NaN NaN NaN \n", - "4336 site NaN NaN NaN NaN \n", - "4337 NaN NaN NaN NaN NaN \n", - "4338 NaN NaN NaN NaN NaN \n", + "4317 NaN NaN NaN NaN NaN \n", + "4318 NaN NaN NaN NaN NaN \n", + "4319 site NaN NaN NaN NaN \n", + "4320 NaN NaN NaN NaN NaN \n", + "4321 NaN NaN NaN NaN NaN \n", "\n", " max_windspeed transit_speed num_vessels \n", "0 NaN NaN NaN \n", @@ -512,13 +512,13 @@ "3 NaN NaN NaN \n", "4 NaN NaN NaN \n", "... ... ... ... \n", - "4334 NaN NaN NaN \n", - "4335 NaN NaN NaN \n", - "4336 NaN NaN 2.0 \n", - "4337 NaN NaN NaN \n", - "4338 NaN NaN 3.0 \n", + "4317 NaN NaN NaN \n", + "4318 NaN NaN NaN \n", + "4319 NaN NaN 2.0 \n", + "4320 NaN NaN NaN \n", + "4321 NaN NaN 3.0 \n", "\n", - "[4339 rows x 16 columns]" + "[4322 rows x 16 columns]" ] }, "execution_count": 7, diff --git a/examples/configs/example_floating_project_SemiTaut.yaml b/examples/configs/example_floating_project_SemiTaut.yaml index 05ef5a8d..5183f7f6 100644 --- a/examples/configs/example_floating_project_SemiTaut.yaml +++ b/examples/configs/example_floating_project_SemiTaut.yaml @@ -1,6 +1,6 @@ # Site + Plant Parameters site: - depth: 900 + depth: 500 distance: 100 distance_to_landfall: 100 plant: From 7eb2d76288001d51391d57876576a5fb71a6919e Mon Sep 17 00:00:00 2001 From: Rolph Date: Sat, 4 Feb 2023 11:02:58 -0700 Subject: [PATCH 07/71] Created a Floating Offshore Substation design module that uses (for now) the same mooring system as the turbines --- examples/configs/example_floating_project_SemiTaut.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/configs/example_floating_project_SemiTaut.yaml b/examples/configs/example_floating_project_SemiTaut.yaml index 5183f7f6..b2ffc08e 100644 --- a/examples/configs/example_floating_project_SemiTaut.yaml +++ b/examples/configs/example_floating_project_SemiTaut.yaml @@ -27,8 +27,6 @@ wtiv: floating_heavy_lift_vessel # Module Specific substructure: takt_time: 168 -OffshoreSubstationInstallation: - feeder: floating_barge array_system: free_cable_length: 0.5 array_system_design: @@ -42,14 +40,15 @@ design_phases: - ArraySystemDesign - ExportSystemDesign - SemiTautMooringSystemDesign -- OffshoreSubstationDesign +# OffshoreFloatingSubstationDesign takes the mooring system unit cost of SemiTautMooringSystemDesign, so that needs to be run first +- OffshoreFloatingSubstationDesign - SemiSubmersibleDesign install_phases: ArrayCableInstallation: 0 ExportCableInstallation: 0 MooredSubInstallation: 0 MooringSystemInstallation: 0 - OffshoreSubstationInstallation: 0 - TurbineInstallation: 0 + FloatingSubstationInstallation: 0 + #TurbineInstallation: 0 # We assume the turbine is installed at quayside onto the substructure so the necessary steps are in 'MooredSubInstallation' # Project Inputs turbine: 12MW_generic From 2aa20b87ec05cbca7344664b65dc711a6e9a834e Mon Sep 17 00:00:00 2001 From: Rolph Date: Sat, 4 Feb 2023 11:56:58 -0700 Subject: [PATCH 08/71] last commit didnt have all changes for adding floating oss design module --- ORBIT/manager.py | 2 + .../design/SemiTaut_mooring_system_design.py | 2 +- ORBIT/phases/design/__init__.py | 1 + ORBIT/phases/design/mooring_system_design.py | 1 + ORBIT/phases/design/oss_design_floating.py | 320 ++++++++++++++++++ ORBIT/phases/install/oss_install/floating.py | 13 +- 6 files changed, 332 insertions(+), 7 deletions(-) create mode 100644 ORBIT/phases/design/oss_design_floating.py diff --git a/ORBIT/manager.py b/ORBIT/manager.py index d87e5d00..348d9cc8 100644 --- a/ORBIT/manager.py +++ b/ORBIT/manager.py @@ -35,6 +35,7 @@ SemiSubmersibleDesign, CustomArraySystemDesign, OffshoreSubstationDesign, + OffshoreFloatingSubstationDesign, ) from ORBIT.phases.install import ( JacketInstallation, @@ -69,6 +70,7 @@ class ProjectManager: ExportSystemDesign, ScourProtectionDesign, OffshoreSubstationDesign, + OffshoreFloatingSubstationDesign, MooringSystemDesign, SemiTautMooringSystemDesign, SemiSubmersibleDesign, diff --git a/ORBIT/phases/design/SemiTaut_mooring_system_design.py b/ORBIT/phases/design/SemiTaut_mooring_system_design.py index bcd62465..b04b0887 100644 --- a/ORBIT/phases/design/SemiTaut_mooring_system_design.py +++ b/ORBIT/phases/design/SemiTaut_mooring_system_design.py @@ -101,7 +101,7 @@ def calculate_line_length_mass(self): chain_kg_per_m = 19900 * (self.chain_diameter**2) # 19,900 kg/m^2 (diameter)/m (length) rope_kg_per_m = 797.8 * (self.rope_diameter**2) # 797.8 kg/ m^2 (diameter) / m (length) self.line_mass = (self.chain_length * chain_kg_per_m) + (self.rope_length * rope_kg_per_m) # kg - print('total hybrid line mass is ' + str(self.line_mass) + 'kg') + #print('total hybrid line mass is ' + str(self.line_mass) + 'kg') # convert kg to metric tonnes self.line_mass = self.line_mass/1e3 diff --git a/ORBIT/phases/design/__init__.py b/ORBIT/phases/design/__init__.py index 7d74fa37..9bc61875 100644 --- a/ORBIT/phases/design/__init__.py +++ b/ORBIT/phases/design/__init__.py @@ -7,6 +7,7 @@ from .design_phase import DesignPhase # isort:skip +from .oss_design_floating import OffshoreFloatingSubstationDesign from .oss_design import OffshoreSubstationDesign from .spar_design import SparDesign from .monopile_design import MonopileDesign diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index 383a4924..5b0eec8b 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -36,6 +36,7 @@ class MooringSystemDesign(DesignPhase): "anchor_mass": "t", "anchor_type": "str", "anchor_cost": "USD", + "system_cost": "USD", } } diff --git a/ORBIT/phases/design/oss_design_floating.py b/ORBIT/phases/design/oss_design_floating.py new file mode 100644 index 00000000..3484c87f --- /dev/null +++ b/ORBIT/phases/design/oss_design_floating.py @@ -0,0 +1,320 @@ +"""Provides the 'OffshoreSubstationDesign` class.""" + +__author__ = "Jake Nunemaker" +__copyright__ = "Copyright 2020, National Renewable Energy Laboratory" +__maintainer__ = "Jake Nunemaker" +__email__ = "Jake.Nunemaker@nrel.gov" + + +import numpy as np + +from ORBIT.phases.design import DesignPhase + + +class OffshoreFloatingSubstationDesign(DesignPhase): + """Offshore Substation Design Class.""" + + expected_config = { + "site": {"depth": "m"}, + "plant": {"num_turbines": "int"}, + "turbine": {"turbine_rating": "MW"}, + "substation_design": { + "mpt_cost_rate": "USD/MW (optional)", + "topside_fab_cost_rate": "USD/t (optional)", + "topside_design_cost": "USD (optional)", + "shunt_cost_rate": "USD/MW (optional)", + "switchgear_cost": "USD (optional)", + "backup_gen_cost": "USD (optional)", + "workspace_cost": "USD (optional)", + "other_ancillary_cost": "USD (optional)", + "topside_assembly_factor": "float (optional)", + "oss_substructure_cost_rate": "USD/t (optional)", + "oss_pile_cost_rate": "USD/t (optional)", + "num_substations": "int (optional)", + }, + } + + output_config = { + "num_substations": "int", + "offshore_substation_topside": "dict", + #"offshore_substation_substructure", "dict", + } + + def __init__(self, config, **kwargs): + """ + Creates an instance of OffshoreSubstationDesign. + + Parameters + ---------- + config : dict + """ + + config = self.initialize_library(config, **kwargs) + self.config = self.validate_config(config) + self._outputs = {} + + def run(self): + """Main run function.""" + + self.calc_substructure_length() + self.calc_substructure_deck_space() + self.calc_topside_deck_space() + + self.calc_num_mpt_and_rating() + self.calc_mpt_cost() + self.calc_topside_mass_and_cost() + self.calc_shunt_reactor_cost() + self.calc_switchgear_cost() + self.calc_ancillary_system_cost() + self.calc_assembly_cost() + self.calc_substructure_mass_and_cost() + + self._outputs["offshore_substation_substructure"] = { + "type": "Floating", + "deck_space": self.substructure_deck_space, + "mass": self.substructure_mass, + "length": self.substructure_length, + "unit_cost": self.substructure_cost, + } + + self._outputs["offshore_substation_topside"] = { + "deck_space": self.topside_deck_space, + "mass": self.topside_mass, + "unit_cost": self.substation_cost, + } + + self._outputs["num_substations"] = self.num_substations + + @property + def substation_cost(self): + """Returns total procuremet cost of the topside.""" + + return ( + self.mpt_cost + + self.topside_cost + + self.shunt_reactor_cost + + self.switchgear_costs + + self.ancillary_system_costs + + self.land_assembly_cost + ) + + @property + def total_cost(self): + """Returns total procurement cost of the substation(s).""" + + if not self._outputs: + raise Exception("Has OffshoreSubstationDesign been ran yet?") + + return ( + self.substructure_cost + self.substation_cost + ) * self.num_substations + + def calc_substructure_length(self): + """ + Calculates substructure length as the site depth + 10m + """ + + self.substructure_length = self.config["site"]["depth"] + 10 + + def calc_substructure_deck_space(self): + """ + Calculates required deck space for the substation substructure. + + Coming soon! + """ + + self.substructure_deck_space = 1 + + def calc_topside_deck_space(self): + """ + Calculates required deck space for the substation topside. + + Coming soon! + """ + + self.topside_deck_space = 1 + + def calc_num_mpt_and_rating(self): + """ + Calculates the number of main power transformers (MPTs) and their rating. + + Parameters + ---------- + num_turbines : int + turbine_rating : float + """ + + _design = self.config.get("substation_design", {}) + + num_turbines = self.config["plant"]["num_turbines"] + turbine_rating = self.config["turbine"]["turbine_rating"] + capacity = num_turbines * turbine_rating + + self.num_substations = _design.get( + "num_substations", int(np.ceil(capacity / 500)) + ) + self.num_mpt = np.ceil( + num_turbines * turbine_rating / (250 * self.num_substations) + ) + self.mpt_rating = ( + round( + ( + (num_turbines * turbine_rating * 1.15) + / (self.num_mpt * self.num_substations) + ) + / 10.0 + ) + * 10.0 + ) + + def calc_mpt_cost(self): + """ + Calculates the total cost for all MPTs. + + Parameters + ---------- + mpt_cost_rate : float + """ + + _design = self.config.get("substation_design", {}) + mpt_cost_rate = _design.get("mpt_cost_rate", 12500) + + self.mpt_cost = self.mpt_rating * self.num_mpt * mpt_cost_rate + + def calc_topside_mass_and_cost(self): + """ + Calculates the mass and cost of the substation topsides. + + Parameters + ---------- + topside_fab_cost_rate : int | float + topside_design_cost: int | float + """ + + _design = self.config.get("substation_design", {}) + topside_fab_cost_rate = _design.get("topside_fab_cost_rate", 14500) + topside_design_cost = _design.get("topside_design_cost", 4.5e6) + + self.topside_mass = 3.85 * self.mpt_rating * self.num_mpt + 285 + self.topside_cost = ( + self.topside_mass * topside_fab_cost_rate + topside_design_cost + ) + + def calc_shunt_reactor_cost(self): + """ + Calculates the cost of the shunt reactor. + + Parameters + ---------- + shunt_cost_rate : int | float + """ + + _design = self.config.get("substation_design", {}) + shunt_cost_rate = _design.get("shunt_cost_rate", 35000) + + self.shunt_reactor_cost = ( + self.mpt_rating * self.num_mpt * shunt_cost_rate * 0.5 + ) + + def calc_switchgear_cost(self): + """ + Calculates the cost of the switchgear. + + Parameters + ---------- + switchgear_cost : int | float + """ + + _design = self.config.get("substation_design", {}) + switchgear_cost = _design.get("switchgear_cost", 14.5e5) + + self.switchgear_costs = self.num_mpt * switchgear_cost + + def calc_ancillary_system_cost(self): + """ + Calculates cost of ancillary systems. + + Parameters + ---------- + backup_gen_cost : int | float + workspace_cost : int | float + other_ancillary_cost : int | float + """ + + _design = self.config.get("substation_design", {}) + backup_gen_cost = _design.get("backup_gen_cost", 1e6) + workspace_cost = _design.get("workspace_cost", 2e6) + other_ancillary_cost = _design.get("other_ancillary_cost", 3e6) + + self.ancillary_system_costs = ( + backup_gen_cost + workspace_cost + other_ancillary_cost + ) + + def calc_assembly_cost(self): + """ + Calculates the cost of assembly on land. + + Parameters + ---------- + topside_assembly_factor : int | float + """ + + _design = self.config.get("substation_design", {}) + topside_assembly_factor = _design.get("topside_assembly_factor", 0.075) + self.land_assembly_cost = ( + self.switchgear_costs + + self.shunt_reactor_cost + + self.ancillary_system_costs + ) * topside_assembly_factor + + def calc_substructure_mass_and_cost(self): + """ + Calculates the mass and associated cost of the substation substructure. + + Parameters + ---------- + oss_substructure_cost_rate : int | float + oss_pile_cost_rate : int | float + """ + + _design = self.config.get("substation_design", {}) + oss_substructure_cost_rate = _design.get( + "oss_substructure_cost_rate", 3000 + ) + oss_pile_cost_rate = _design.get("oss_pile_cost_rate", 0) + + substructure_mass = 0.4 * self.topside_mass + #substructure_pile_mass = 8 * substructure_mass ** 0.5574 + substructure_pile_mass = 0 # the monopiles are no longer needed because there is s mooring system + self.substructure_cost = ( + substructure_mass * oss_substructure_cost_rate + + substructure_pile_mass * oss_pile_cost_rate + ) + print('substructure cost:' + str(self.substructure_cost)) + self.substructure_mass = substructure_mass + substructure_pile_mass + + @property + def design_result(self): + """ + Returns the results of self.run(). + """ + + if not self._outputs: + raise Exception("Has OffshoreSubstationDesign been ran yet?") + + return self._outputs + + @property + def detailed_output(self): + """Returns detailed phase information.""" + + _outputs = { + "num_substations": self.num_substations, + "substation_mpt_rating": self.mpt_rating, + "substation_topside_mass": self.topside_mass, + "substation_topside_cost": self.topside_cost, + "substation_substructure_mass": self.substructure_mass, + "substation_substructure_cost": self.substructure_cost, + } + + return _outputs diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index 6580e19a..d752cdd4 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -25,7 +25,7 @@ class FloatingSubstationInstallation(InstallPhase): and tow-out processes. """ - phase = "Offshore Substation Installation" + phase = "Offshore Floating Substation Installation" capex_category = "Offshore Substation" #: @@ -41,9 +41,10 @@ class FloatingSubstationInstallation(InstallPhase): "type": "Floating", "takt_time": "int | float (optional, default: 0)", "unit_cost": "USD", - "mooring_cost": "USD", - "towing_speed": "int | float (optional, default: 6 km/h)", - }, + #"mooring_cost": "USD", + "towing_speed": "int | float (optional, default: 6 km/h)" + }, + "mooring_system": {"system_cost": "USD"}, } def __init__(self, config, weather=None, **kwargs): @@ -89,8 +90,8 @@ def system_capex(self): substructure = self.config["offshore_substation_substructure"][ "unit_cost" ] - mooring = self.config["offshore_substation_substructure"][ - "mooring_cost" + mooring = self.config["mooring_system"][ + "system_cost" ] return self.num_substations * (topside + substructure + mooring) From e2fc7a5145ef7e2a2cb9059f00131d7b4f901458 Mon Sep 17 00:00:00 2001 From: Rolph Date: Sat, 4 Feb 2023 13:07:27 -0700 Subject: [PATCH 09/71] testing why floatingPY is called twice --- ORBIT/phases/design/oss_design_floating.py | 2 +- ORBIT/phases/install/oss_install/floating.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ORBIT/phases/design/oss_design_floating.py b/ORBIT/phases/design/oss_design_floating.py index 3484c87f..a1f384d3 100644 --- a/ORBIT/phases/design/oss_design_floating.py +++ b/ORBIT/phases/design/oss_design_floating.py @@ -290,7 +290,7 @@ def calc_substructure_mass_and_cost(self): substructure_mass * oss_substructure_cost_rate + substructure_pile_mass * oss_pile_cost_rate ) - print('substructure cost:' + str(self.substructure_cost)) + #print('substructure cost:' + str(self.substructure_cost)) self.substructure_mass = substructure_mass + substructure_pile_mass @property diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index d752cdd4..cdbf7558 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -93,7 +93,9 @@ def system_capex(self): mooring = self.config["mooring_system"][ "system_cost" ] - + print('topside: ' + str(topside)) + print('oss substructure' + str(substructure)) + print('mooring system' + str(mooring)) return self.num_substations * (topside + substructure + mooring) def initialize_substructure_production(self): From 3744934caa6c06f40cdd2c2b0eab9963c4f4641e Mon Sep 17 00:00:00 2001 From: Rolph Date: Sat, 4 Feb 2023 13:16:11 -0700 Subject: [PATCH 10/71] adding example run scripts that show 2x print statement --- ...5. Example Floating Project-SemiTaut.ipynb | 219 ++++++++++-------- examples/5. Example Floating Project.ipynb | 191 ++++++++------- .../example_floating_project_SemiTaut.yaml | 4 +- 3 files changed, 222 insertions(+), 192 deletions(-) diff --git a/examples/5. Example Floating Project-SemiTaut.ipynb b/examples/5. Example Floating Project-SemiTaut.ipynb index 23899e96..5d1756d8 100644 --- a/examples/5. Example Floating Project-SemiTaut.ipynb +++ b/examples/5. Example Floating Project-SemiTaut.ipynb @@ -44,7 +44,7 @@ "Num turbines: 50\n", "Turbine: 12MW_generic\n", "\n", - "Site: {'depth': 500, 'distance': 100, 'distance_to_landfall': 100}\n" + "Site: {'depth': 900, 'distance': 100, 'distance_to_landfall': 100}\n" ] } ], @@ -72,9 +72,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "Design phases: ['ArraySystemDesign', 'ExportSystemDesign', 'SemiTautMooringSystemDesign', 'OffshoreSubstationDesign', 'SemiSubmersibleDesign']\n", + "Design phases: ['ArraySystemDesign', 'ExportSystemDesign', 'SemiTautMooringSystemDesign', 'OffshoreFloatingSubstationDesign', 'SemiSubmersibleDesign']\n", "\n", - "Install phases: ['ArrayCableInstallation', 'ExportCableInstallation', 'MooredSubInstallation', 'MooringSystemInstallation', 'OffshoreSubstationInstallation', 'TurbineInstallation']\n" + "Install phases: ['ArrayCableInstallation', 'ExportCableInstallation', 'MooredSubInstallation', 'MooringSystemInstallation', 'FloatingSubstationInstallation']\n" ] } ], @@ -91,6 +91,13 @@ "### Run" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": 4, @@ -101,7 +108,12 @@ "output_type": "stream", "text": [ "ORBIT library intialized at 'C:\\Users\\rrolph\\OneDrive - NREL\\ORBIT\\library'\n", - "total hybrid line mass is 323700.2840200001kg\n" + "topside: 47826750.0\n", + "oss substructure1912800.0\n", + "mooring system327467880.0\n", + "topside: 47826750.0\n", + "oss substructure1912800.0\n", + "mooring system327467880.0\n" ] } ], @@ -126,13 +138,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "Installation CapEx: 410 M\n", - "System CapEx: 1066 M\n", + "Installation CapEx: 300 M\n", + "System CapEx: 1873 M\n", "Turbine CapEx: 780 M\n", "Soft CapEx: 387 M\n", - "Total CapEx: 2794 M\n", + "Total CapEx: 3491 M\n", "\n", - "Installation Time: 26286 h\n" + "Installation Time: 22581 h\n" ] } ], @@ -155,29 +167,60 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'Array System': 73.86136722816696,\n", - " 'Export System': 172.32636751400003,\n", + "{'Array System': 56983076.60642063,\n", + " 'Export System': 103712476.9152,\n", + " 'Substructure': 630709636.6,\n", + " 'Mooring System': 327467880.0,\n", + " 'Offshore Substation': 754414860.0,\n", + " 'Array System Installation': 22844527.89607126,\n", + " 'Export System Installation': 135112258.0470523,\n", + " 'Substructure Installation': 78569120.05327243,\n", + " 'Mooring System Installation': 48485331.05022831,\n", + " 'Offshore Substation Installation': 14801636.225266362,\n", + " 'Turbine': 780000000,\n", + " 'Soft': 387000000,\n", + " 'Project': 151250000.0}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "project.capex_breakdown" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Array System': 94.97179434403438,\n", + " 'Export System': 172.854128192,\n", " 'Substructure': 1051.1827276666668,\n", - " 'Mooring System': 313.1213333333333,\n", - " 'Offshore Substation': 165.7985,\n", - " 'Array System Installation': 35.42268447056795,\n", - " 'Export System Installation': 225.18351574438626,\n", + " 'Mooring System': 545.7798,\n", + " 'Offshore Substation': 1257.3581,\n", + " 'Array System Installation': 38.07421316011877,\n", + " 'Export System Installation': 225.18709674508716,\n", " 'Substructure Installation': 130.9485334221207,\n", - " 'Mooring System Installation': 69.2752092846271,\n", - " 'Offshore Substation Installation': 8.780764320142058,\n", - " 'Turbine Installation': 212.89678462709279,\n", + " 'Mooring System Installation': 80.80888508371386,\n", + " 'Offshore Substation Installation': 24.66939370877727,\n", " 'Turbine': 1300.0,\n", " 'Soft': 645.0,\n", " 'Project': 252.08333333333334}" ] }, - "execution_count": 13, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -195,7 +238,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -228,8 +271,6 @@ " time\n", " phase\n", " location\n", - " site_depth\n", - " hub_height\n", " phase_name\n", " max_waveheight\n", " max_windspeed\n", @@ -254,8 +295,6 @@ " NaN\n", " NaN\n", " NaN\n", - " NaN\n", - " NaN\n", " \n", " \n", " 1\n", @@ -273,8 +312,6 @@ " NaN\n", " NaN\n", " NaN\n", - " NaN\n", - " NaN\n", " \n", " \n", " 2\n", @@ -292,8 +329,6 @@ " NaN\n", " NaN\n", " NaN\n", - " NaN\n", - " NaN\n", " \n", " \n", " 3\n", @@ -311,21 +346,17 @@ " NaN\n", " NaN\n", " NaN\n", - " NaN\n", - " NaN\n", " \n", " \n", " 4\n", - " 0.5\n", - " Heavy Lift Vessel\n", - " Mobilize\n", - " 72.000000\n", - " 7.500000e+05\n", + " NaN\n", + " Substation Assembly Line 1\n", + " Substation Substructure Assembly\n", + " 0.000000\n", + " 0.000000e+00\n", " ACTION\n", " 0.000000\n", - " OffshoreSubstationInstallation\n", - " NaN\n", - " NaN\n", + " FloatingSubstationInstallation\n", " NaN\n", " NaN\n", " NaN\n", @@ -349,11 +380,9 @@ " ...\n", " ...\n", " ...\n", - " ...\n", - " ...\n", " \n", " \n", - " 4317\n", + " 2876\n", " NaN\n", " Multi-Purpose Support Vessel\n", " Connect Mooring Lines, Pre-tension and pre-str...\n", @@ -368,11 +397,9 @@ " NaN\n", " NaN\n", " NaN\n", - " NaN\n", - " NaN\n", " \n", " \n", - " 4318\n", + " 2877\n", " NaN\n", " Multi-Purpose Support Vessel\n", " Check Mooring Lines\n", @@ -387,11 +414,9 @@ " NaN\n", " NaN\n", " NaN\n", - " NaN\n", - " NaN\n", " \n", " \n", - " 4319\n", + " 2878\n", " NaN\n", " Towing Group 1\n", " Positioning Support\n", @@ -405,12 +430,10 @@ " NaN\n", " NaN\n", " NaN\n", - " NaN\n", - " NaN\n", " 2.0\n", " \n", " \n", - " 4320\n", + " 2879\n", " NaN\n", " Multi-Purpose Support Vessel\n", " Transit\n", @@ -425,11 +448,9 @@ " NaN\n", " NaN\n", " NaN\n", - " NaN\n", - " NaN\n", " \n", " \n", - " 4321\n", + " 2880\n", " NaN\n", " Towing Group 1\n", " Transit\n", @@ -443,13 +464,11 @@ " NaN\n", " NaN\n", " NaN\n", - " NaN\n", - " NaN\n", " 3.0\n", " \n", " \n", "\n", - "

4322 rows Ă— 16 columns

\n", + "

2881 rows Ă— 14 columns

\n", "" ], "text/plain": [ @@ -458,70 +477,70 @@ "1 0.5 Export Cable Installation Vessel \n", "2 NaN Onshore Construction \n", "3 1.0 Mooring System Installation Vessel \n", - "4 0.5 Heavy Lift Vessel \n", + "4 NaN Substation Assembly Line 1 \n", "... ... ... \n", - "4317 NaN Multi-Purpose Support Vessel \n", - "4318 NaN Multi-Purpose Support Vessel \n", - "4319 NaN Towing Group 1 \n", - "4320 NaN Multi-Purpose Support Vessel \n", - "4321 NaN Towing Group 1 \n", + "2876 NaN Multi-Purpose Support Vessel \n", + "2877 NaN Multi-Purpose Support Vessel \n", + "2878 NaN Towing Group 1 \n", + "2879 NaN Multi-Purpose Support Vessel \n", + "2880 NaN Towing Group 1 \n", "\n", " action duration \\\n", "0 Mobilize 72.000000 \n", "1 Mobilize 72.000000 \n", "2 Onshore Construction 0.000000 \n", "3 Mobilize 168.000000 \n", - "4 Mobilize 72.000000 \n", + "4 Substation Substructure Assembly 0.000000 \n", "... ... ... \n", - "4317 Connect Mooring Lines, Pre-tension and pre-str... 20.000000 \n", - "4318 Check Mooring Lines 6.000000 \n", - "4319 Positioning Support 34.000000 \n", - "4320 Transit 10.000000 \n", - "4321 Transit 16.666667 \n", + "2876 Connect Mooring Lines, Pre-tension and pre-str... 20.000000 \n", + "2877 Check Mooring Lines 6.000000 \n", + "2878 Positioning Support 34.000000 \n", + "2879 Transit 10.000000 \n", + "2880 Transit 16.666667 \n", "\n", " cost level time phase \\\n", "0 1.800000e+05 ACTION 0.000000 ArrayCableInstallation \n", "1 1.800000e+05 ACTION 0.000000 ExportCableInstallation \n", "2 1.075454e+08 ACTION 0.000000 ExportCableInstallation \n", "3 7.000000e+05 ACTION 0.000000 MooringSystemInstallation \n", - "4 7.500000e+05 ACTION 0.000000 OffshoreSubstationInstallation \n", + "4 0.000000e+00 ACTION 0.000000 FloatingSubstationInstallation \n", "... ... ... ... ... \n", - "4317 8.333333e+04 ACTION 8544.500000 MooredSubInstallation \n", - "4318 2.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", - "4319 8.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", - "4320 4.166667e+04 ACTION 8560.500000 MooredSubInstallation \n", - "4321 6.250000e+04 ACTION 8567.166667 MooredSubInstallation \n", + "2876 8.333333e+04 ACTION 8544.500000 MooredSubInstallation \n", + "2877 2.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", + "2878 8.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", + "2879 4.166667e+04 ACTION 8560.500000 MooredSubInstallation \n", + "2880 6.250000e+04 ACTION 8567.166667 MooredSubInstallation \n", "\n", - " location site_depth hub_height phase_name max_waveheight \\\n", - "0 NaN NaN NaN NaN NaN \n", - "1 NaN NaN NaN NaN NaN \n", - "2 Landfall NaN NaN NaN NaN \n", - "3 NaN NaN NaN NaN NaN \n", - "4 NaN NaN NaN NaN NaN \n", - "... ... ... ... ... ... \n", - "4317 NaN NaN NaN NaN NaN \n", - "4318 NaN NaN NaN NaN NaN \n", - "4319 site NaN NaN NaN NaN \n", - "4320 NaN NaN NaN NaN NaN \n", - "4321 NaN NaN NaN NaN NaN \n", + " location phase_name max_waveheight max_windspeed transit_speed \\\n", + "0 NaN NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN NaN \n", + "2 Landfall NaN NaN NaN NaN \n", + "3 NaN NaN NaN NaN NaN \n", + "4 NaN NaN NaN NaN NaN \n", + "... ... ... ... ... ... \n", + "2876 NaN NaN NaN NaN NaN \n", + "2877 NaN NaN NaN NaN NaN \n", + "2878 site NaN NaN NaN NaN \n", + "2879 NaN NaN NaN NaN NaN \n", + "2880 NaN NaN NaN NaN NaN \n", "\n", - " max_windspeed transit_speed num_vessels \n", - "0 NaN NaN NaN \n", - "1 NaN NaN NaN \n", - "2 NaN NaN NaN \n", - "3 NaN NaN NaN \n", - "4 NaN NaN NaN \n", - "... ... ... ... \n", - "4317 NaN NaN NaN \n", - "4318 NaN NaN NaN \n", - "4319 NaN NaN 2.0 \n", - "4320 NaN NaN NaN \n", - "4321 NaN NaN 3.0 \n", + " num_vessels \n", + "0 NaN \n", + "1 NaN \n", + "2 NaN \n", + "3 NaN \n", + "4 NaN \n", + "... ... \n", + "2876 NaN \n", + "2877 NaN \n", + "2878 2.0 \n", + "2879 NaN \n", + "2880 3.0 \n", "\n", - "[4322 rows x 16 columns]" + "[2881 rows x 14 columns]" ] }, - "execution_count": 7, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } diff --git a/examples/5. Example Floating Project.ipynb b/examples/5. Example Floating Project.ipynb index 8b01b575..0c216779 100644 --- a/examples/5. Example Floating Project.ipynb +++ b/examples/5. Example Floating Project.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -34,7 +34,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -65,7 +65,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -92,14 +92,14 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "ORBIT library intialized at '/Users/jnunemak/Fun/repos/ORBIT/library'\n" + "ORBIT library intialized at 'C:\\Users\\rrolph\\OneDrive - NREL\\ORBIT\\library'\n" ] } ], @@ -117,7 +117,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -128,9 +128,9 @@ "System CapEx: 1222 M\n", "Turbine CapEx: 780 M\n", "Soft CapEx: 387 M\n", - "Total CapEx: 2961 M\n", + "Total CapEx: 2960 M\n", "\n", - "Installation Time: 27750 h\n" + "Installation Time: 27734 h\n" ] } ], @@ -153,35 +153,35 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'Array System': 56983076.60642063,\n", - " 'Export System': 103712476.9152,\n", - " 'Substructure': 630709636.6,\n", - " 'Mooring System': 331379224.80820334,\n", - " 'Offshore Substation': 99479100.0,\n", - " 'Array System Installation': 22844527.896071255,\n", - " 'Export System Installation': 135112258.0470523,\n", - " 'Substructure Installation': 79182122.33637744,\n", - " 'Mooring System Installation': 50094520.5479452,\n", - " 'Offshore Substation Installation': 5499328.911719939,\n", - " 'Turbine Installation': 127738070.77625567,\n", - " 'Turbine': 780000000,\n", - " 'Soft': 387000000,\n", - " 'Project': 151250000.0}" + "{'Array System': 94.97179434403438,\n", + " 'Export System': 172.854128192,\n", + " 'Substructure': 1051.1827276666668,\n", + " 'Mooring System': 552.2987080136722,\n", + " 'Offshore Substation': 165.7985,\n", + " 'Array System Installation': 38.07421316011877,\n", + " 'Export System Installation': 225.18709674508716,\n", + " 'Substructure Installation': 130.9485334221207,\n", + " 'Mooring System Installation': 83.49086757990867,\n", + " 'Offshore Substation Installation': 9.165548186199898,\n", + " 'Turbine Installation': 212.89678462709279,\n", + " 'Turbine': 1300.0,\n", + " 'Soft': 645.0,\n", + " 'Project': 252.08333333333334}" ] }, - "execution_count": 7, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "project.capex_breakdown" + "project.capex_breakdown_per_kw" ] }, { @@ -193,7 +193,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -351,14 +351,14 @@ " ...\n", " \n", " \n", - " 4405\n", + " 4397\n", " NaN\n", " Multi-Purpose Support Vessel\n", - " Connect Mooring Lines\n", - " 22.000000\n", - " 9.166667e+04\n", + " Connect Mooring Lines, Pre-tension and pre-str...\n", + " 20.000000\n", + " 8.333333e+04\n", " ACTION\n", - " 8554.500000\n", + " 8544.500000\n", " MooredSubInstallation\n", " NaN\n", " NaN\n", @@ -370,14 +370,14 @@ " NaN\n", " \n", " \n", - " 4406\n", + " 4398\n", " NaN\n", " Multi-Purpose Support Vessel\n", " Check Mooring Lines\n", - " 12.000000\n", - " 5.000000e+04\n", + " 6.000000\n", + " 2.500000e+04\n", " ACTION\n", - " 8566.500000\n", + " 8550.500000\n", " MooredSubInstallation\n", " NaN\n", " NaN\n", @@ -389,14 +389,14 @@ " NaN\n", " \n", " \n", - " 4407\n", + " 4399\n", " NaN\n", " Towing Group 1\n", " Positioning Support\n", - " 42.000000\n", - " 1.050000e+05\n", + " 34.000000\n", + " 8.500000e+04\n", " ACTION\n", - " 8566.500000\n", + " 8550.500000\n", " MooredSubInstallation\n", " site\n", " NaN\n", @@ -408,14 +408,14 @@ " 2.0\n", " \n", " \n", - " 4408\n", + " 4400\n", " NaN\n", " Multi-Purpose Support Vessel\n", " Transit\n", " 10.000000\n", " 4.166667e+04\n", " ACTION\n", - " 8576.500000\n", + " 8560.500000\n", " MooredSubInstallation\n", " NaN\n", " NaN\n", @@ -427,14 +427,14 @@ " NaN\n", " \n", " \n", - " 4409\n", + " 4401\n", " NaN\n", " Towing Group 1\n", " Transit\n", " 16.666667\n", " 6.250000e+04\n", " ACTION\n", - " 8583.166667\n", + " 8567.166667\n", " MooredSubInstallation\n", " NaN\n", " NaN\n", @@ -447,7 +447,7 @@ " \n", " \n", "\n", - "

4410 rows Ă— 16 columns

\n", + "

4402 rows Ă— 16 columns

\n", "" ], "text/plain": [ @@ -458,55 +458,68 @@ "3 1.0 Mooring System Installation Vessel \n", "4 0.5 Heavy Lift Vessel \n", "... ... ... \n", - "4405 NaN Multi-Purpose Support Vessel \n", - "4406 NaN Multi-Purpose Support Vessel \n", - "4407 NaN Towing Group 1 \n", - "4408 NaN Multi-Purpose Support Vessel \n", - "4409 NaN Towing Group 1 \n", + "4397 NaN Multi-Purpose Support Vessel \n", + "4398 NaN Multi-Purpose Support Vessel \n", + "4399 NaN Towing Group 1 \n", + "4400 NaN Multi-Purpose Support Vessel \n", + "4401 NaN Towing Group 1 \n", + "\n", + " action duration \\\n", + "0 Mobilize 72.000000 \n", + "1 Mobilize 72.000000 \n", + "2 Onshore Construction 0.000000 \n", + "3 Mobilize 168.000000 \n", + "4 Mobilize 72.000000 \n", + "... ... ... \n", + "4397 Connect Mooring Lines, Pre-tension and pre-str... 20.000000 \n", + "4398 Check Mooring Lines 6.000000 \n", + "4399 Positioning Support 34.000000 \n", + "4400 Transit 10.000000 \n", + "4401 Transit 16.666667 \n", "\n", - " action duration cost level time \\\n", - "0 Mobilize 72.000000 1.800000e+05 ACTION 0.000000 \n", - "1 Mobilize 72.000000 1.800000e+05 ACTION 0.000000 \n", - "2 Onshore Construction 0.000000 1.075454e+08 ACTION 0.000000 \n", - "3 Mobilize 168.000000 7.000000e+05 ACTION 0.000000 \n", - "4 Mobilize 72.000000 7.500000e+05 ACTION 0.000000 \n", - "... ... ... ... ... ... \n", - "4405 Connect Mooring Lines 22.000000 9.166667e+04 ACTION 8554.500000 \n", - "4406 Check Mooring Lines 12.000000 5.000000e+04 ACTION 8566.500000 \n", - "4407 Positioning Support 42.000000 1.050000e+05 ACTION 8566.500000 \n", - "4408 Transit 10.000000 4.166667e+04 ACTION 8576.500000 \n", - "4409 Transit 16.666667 6.250000e+04 ACTION 8583.166667 \n", + " cost level time phase \\\n", + "0 1.800000e+05 ACTION 0.000000 ArrayCableInstallation \n", + "1 1.800000e+05 ACTION 0.000000 ExportCableInstallation \n", + "2 1.075454e+08 ACTION 0.000000 ExportCableInstallation \n", + "3 7.000000e+05 ACTION 0.000000 MooringSystemInstallation \n", + "4 7.500000e+05 ACTION 0.000000 OffshoreSubstationInstallation \n", + "... ... ... ... ... \n", + "4397 8.333333e+04 ACTION 8544.500000 MooredSubInstallation \n", + "4398 2.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", + "4399 8.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", + "4400 4.166667e+04 ACTION 8560.500000 MooredSubInstallation \n", + "4401 6.250000e+04 ACTION 8567.166667 MooredSubInstallation \n", "\n", - " phase location site_depth hub_height \\\n", - "0 ArrayCableInstallation NaN NaN NaN \n", - "1 ExportCableInstallation NaN NaN NaN \n", - "2 ExportCableInstallation Landfall NaN NaN \n", - "3 MooringSystemInstallation NaN NaN NaN \n", - "4 OffshoreSubstationInstallation NaN NaN NaN \n", - "... ... ... ... ... \n", - "4405 MooredSubInstallation NaN NaN NaN \n", - "4406 MooredSubInstallation NaN NaN NaN \n", - "4407 MooredSubInstallation site NaN NaN \n", - "4408 MooredSubInstallation NaN NaN NaN \n", - "4409 MooredSubInstallation NaN NaN NaN \n", + " location site_depth hub_height phase_name max_waveheight \\\n", + "0 NaN NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN NaN \n", + "2 Landfall NaN NaN NaN NaN \n", + "3 NaN NaN NaN NaN NaN \n", + "4 NaN NaN NaN NaN NaN \n", + "... ... ... ... ... ... \n", + "4397 NaN NaN NaN NaN NaN \n", + "4398 NaN NaN NaN NaN NaN \n", + "4399 site NaN NaN NaN NaN \n", + "4400 NaN NaN NaN NaN NaN \n", + "4401 NaN NaN NaN NaN NaN \n", "\n", - " phase_name max_waveheight max_windspeed transit_speed num_vessels \n", - "0 NaN NaN NaN NaN NaN \n", - "1 NaN NaN NaN NaN NaN \n", - "2 NaN NaN NaN NaN NaN \n", - "3 NaN NaN NaN NaN NaN \n", - "4 NaN NaN NaN NaN NaN \n", - "... ... ... ... ... ... \n", - "4405 NaN NaN NaN NaN NaN \n", - "4406 NaN NaN NaN NaN NaN \n", - "4407 NaN NaN NaN NaN 2.0 \n", - "4408 NaN NaN NaN NaN NaN \n", - "4409 NaN NaN NaN NaN 3.0 \n", + " max_windspeed transit_speed num_vessels \n", + "0 NaN NaN NaN \n", + "1 NaN NaN NaN \n", + "2 NaN NaN NaN \n", + "3 NaN NaN NaN \n", + "4 NaN NaN NaN \n", + "... ... ... ... \n", + "4397 NaN NaN NaN \n", + "4398 NaN NaN NaN \n", + "4399 NaN NaN 2.0 \n", + "4400 NaN NaN NaN \n", + "4401 NaN NaN 3.0 \n", "\n", - "[4410 rows x 16 columns]" + "[4402 rows x 16 columns]" ] }, - "execution_count": 8, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -525,7 +538,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -539,7 +552,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.9.15" } }, "nbformat": 4, diff --git a/examples/configs/example_floating_project_SemiTaut.yaml b/examples/configs/example_floating_project_SemiTaut.yaml index b2ffc08e..c43de907 100644 --- a/examples/configs/example_floating_project_SemiTaut.yaml +++ b/examples/configs/example_floating_project_SemiTaut.yaml @@ -1,6 +1,6 @@ # Site + Plant Parameters site: - depth: 500 + depth: 900 distance: 100 distance_to_landfall: 100 plant: @@ -40,7 +40,6 @@ design_phases: - ArraySystemDesign - ExportSystemDesign - SemiTautMooringSystemDesign -# OffshoreFloatingSubstationDesign takes the mooring system unit cost of SemiTautMooringSystemDesign, so that needs to be run first - OffshoreFloatingSubstationDesign - SemiSubmersibleDesign install_phases: @@ -49,6 +48,5 @@ install_phases: MooredSubInstallation: 0 MooringSystemInstallation: 0 FloatingSubstationInstallation: 0 - #TurbineInstallation: 0 # We assume the turbine is installed at quayside onto the substructure so the necessary steps are in 'MooredSubInstallation' # Project Inputs turbine: 12MW_generic From ba3ab5db0e07c4913220197cfafc16fa99981b31 Mon Sep 17 00:00:00 2001 From: Becca Rolph Date: Mon, 6 Feb 2023 11:24:41 -0700 Subject: [PATCH 11/71] corrected that all moorings from farm were being added to each substation. now just one mooring system per oss. --- ORBIT/phases/install/oss_install/floating.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index cdbf7558..e554764d 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -44,7 +44,11 @@ class FloatingSubstationInstallation(InstallPhase): #"mooring_cost": "USD", "towing_speed": "int | float (optional, default: 6 km/h)" }, - "mooring_system": {"system_cost": "USD"}, + "mooring_system": { + #"system_cost": "USD", "}, # system cost is for all moorings in the whole farm, so you dont want this to be added to each substation + "num_lines", "int", + "line_cost", "USD", + "anchor_cost", "USD" } def __init__(self, config, weather=None, **kwargs): @@ -90,13 +94,15 @@ def system_capex(self): substructure = self.config["offshore_substation_substructure"][ "unit_cost" ] - mooring = self.config["mooring_system"][ - "system_cost" - ] + # mooring system + num_mooring_lines = self.config["mooring_system"]["num_lines"] + line_cost = self.config["mooring_system"]["line_cost"] + anchor_cost = self.config["mooring_system"]["anchor_cost"] + mooring_system_for_each_oss = num_mooring_lines*(line_cost + anchor_cost) print('topside: ' + str(topside)) print('oss substructure' + str(substructure)) print('mooring system' + str(mooring)) - return self.num_substations * (topside + substructure + mooring) + return self.num_substations * (topside + substructure + mooring_system_for_each_oss) def initialize_substructure_production(self): """ From 9ecee38c5d0afd94b3477f3039e4eb2ab8e8be1b Mon Sep 17 00:00:00 2001 From: Becca Rolph Date: Mon, 6 Feb 2023 11:31:39 -0700 Subject: [PATCH 12/71] fixed syntax errors --- ORBIT/phases/install/oss_install/floating.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index e554764d..cc6fa94d 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -48,8 +48,8 @@ class FloatingSubstationInstallation(InstallPhase): #"system_cost": "USD", "}, # system cost is for all moorings in the whole farm, so you dont want this to be added to each substation "num_lines", "int", "line_cost", "USD", - "anchor_cost", "USD" - } + "anchor_cost", "USD"} + } def __init__(self, config, weather=None, **kwargs): """ @@ -101,7 +101,7 @@ def system_capex(self): mooring_system_for_each_oss = num_mooring_lines*(line_cost + anchor_cost) print('topside: ' + str(topside)) print('oss substructure' + str(substructure)) - print('mooring system' + str(mooring)) + print('mooring system' + str(mooring_system_for_each_oss)) return self.num_substations * (topside + substructure + mooring_system_for_each_oss) def initialize_substructure_production(self): From 82095700cb56636126b9638df082dc55d4e1e06d Mon Sep 17 00:00:00 2001 From: Becca Rolph Date: Mon, 6 Feb 2023 11:38:23 -0700 Subject: [PATCH 13/71] updated example notebooks --- ...5. Example Floating Project-SemiTaut.ipynb | 19 +++++++++++++------ examples/5. Example Floating Project.ipynb | 4 ++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/examples/5. Example Floating Project-SemiTaut.ipynb b/examples/5. Example Floating Project-SemiTaut.ipynb index 5d1756d8..aa999ce7 100644 --- a/examples/5. Example Floating Project-SemiTaut.ipynb +++ b/examples/5. Example Floating Project-SemiTaut.ipynb @@ -1,5 +1,12 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "metadata": {}, @@ -110,10 +117,10 @@ "ORBIT library intialized at 'C:\\Users\\rrolph\\OneDrive - NREL\\ORBIT\\library'\n", "topside: 47826750.0\n", "oss substructure1912800.0\n", - "mooring system327467880.0\n", + "mooring system6549357.6\n", "topside: 47826750.0\n", "oss substructure1912800.0\n", - "mooring system327467880.0\n" + "mooring system6549357.6\n" ] } ], @@ -139,10 +146,10 @@ "output_type": "stream", "text": [ "Installation CapEx: 300 M\n", - "System CapEx: 1873 M\n", + "System CapEx: 1231 M\n", "Turbine CapEx: 780 M\n", "Soft CapEx: 387 M\n", - "Total CapEx: 3491 M\n", + "Total CapEx: 2850 M\n", "\n", "Installation Time: 22581 h\n" ] @@ -177,7 +184,7 @@ " 'Export System': 103712476.9152,\n", " 'Substructure': 630709636.6,\n", " 'Mooring System': 327467880.0,\n", - " 'Offshore Substation': 754414860.0,\n", + " 'Offshore Substation': 112577815.2,\n", " 'Array System Installation': 22844527.89607126,\n", " 'Export System Installation': 135112258.0470523,\n", " 'Substructure Installation': 78569120.05327243,\n", @@ -209,7 +216,7 @@ " 'Export System': 172.854128192,\n", " 'Substructure': 1051.1827276666668,\n", " 'Mooring System': 545.7798,\n", - " 'Offshore Substation': 1257.3581,\n", + " 'Offshore Substation': 187.629692,\n", " 'Array System Installation': 38.07421316011877,\n", " 'Export System Installation': 225.18709674508716,\n", " 'Substructure Installation': 130.9485334221207,\n", diff --git a/examples/5. Example Floating Project.ipynb b/examples/5. Example Floating Project.ipynb index 0c216779..8c8c12d6 100644 --- a/examples/5. Example Floating Project.ipynb +++ b/examples/5. Example Floating Project.ipynb @@ -153,7 +153,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -175,7 +175,7 @@ " 'Project': 252.08333333333334}" ] }, - "execution_count": 9, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } From ff6ebd97d4277a78d69c1524d11ce9751c44b5f1 Mon Sep 17 00:00:00 2001 From: Shields Date: Tue, 21 Feb 2023 15:50:27 -0700 Subject: [PATCH 14/71] Added flag for floating OSS in ElectricalDesign (zero out monopile cost) --- ORBIT/phases/design/electrical_export.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ORBIT/phases/design/electrical_export.py b/ORBIT/phases/design/electrical_export.py index 42f5011d..23062c5c 100644 --- a/ORBIT/phases/design/electrical_export.py +++ b/ORBIT/phases/design/electrical_export.py @@ -28,6 +28,7 @@ class ElectricalDesign(CableSystem): }, }, "substation_design": { + "floating_oss": "T/F (optional, default: False)", "mpt_cost_rate": "USD/MW (optional)", "topside_fab_cost_rate": "USD/t (optional)", "topside_design_cost": "USD (optional)", @@ -85,6 +86,7 @@ def __init__(self, config, **kwargs): self._distance_to_interconnection = 3 # SUBSTATION + self._floating_oss = config["substation_design"]["floating_oss"] self._outputs = {} def run(self): @@ -432,7 +434,11 @@ def calc_substructure_mass_and_cost(self): oss_pile_cost_rate = _design.get("oss_pile_cost_rate", 0) substructure_mass = 0.4 * self.topside_mass - substructure_pile_mass = 8 * substructure_mass**0.5574 + if self._floating_oss == False: + substructure_pile_mass = 8 * substructure_mass**0.5574 + else: + substructure_pile_mass = 0 # No piles for floating OSS + print('OSS sub mass', substructure_pile_mass) self.substructure_cost = ( substructure_mass * oss_substructure_cost_rate + substructure_pile_mass * oss_pile_cost_rate From f930b22ff0199895285260913a1edfa3ddaf601b Mon Sep 17 00:00:00 2001 From: Shields Date: Tue, 21 Feb 2023 15:54:01 -0700 Subject: [PATCH 15/71] Remove print statement --- ORBIT/phases/design/electrical_export.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ORBIT/phases/design/electrical_export.py b/ORBIT/phases/design/electrical_export.py index 23062c5c..1d127773 100644 --- a/ORBIT/phases/design/electrical_export.py +++ b/ORBIT/phases/design/electrical_export.py @@ -438,7 +438,7 @@ def calc_substructure_mass_and_cost(self): substructure_pile_mass = 8 * substructure_mass**0.5574 else: substructure_pile_mass = 0 # No piles for floating OSS - print('OSS sub mass', substructure_pile_mass) + self.substructure_cost = ( substructure_mass * oss_substructure_cost_rate + substructure_pile_mass * oss_pile_cost_rate From 8ca374cea55317ff21b836be6d64755c2cf50364 Mon Sep 17 00:00:00 2001 From: asharma Date: Tue, 21 Feb 2023 23:14:43 -0700 Subject: [PATCH 16/71] allow floating_oss to be optional --- ORBIT/phases/design/electrical_export.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ORBIT/phases/design/electrical_export.py b/ORBIT/phases/design/electrical_export.py index 1d127773..fd556cb6 100644 --- a/ORBIT/phases/design/electrical_export.py +++ b/ORBIT/phases/design/electrical_export.py @@ -86,7 +86,11 @@ def __init__(self, config, **kwargs): self._distance_to_interconnection = 3 # SUBSTATION - self._floating_oss = config["substation_design"]["floating_oss"] + try: + self._floating_oss = config["substation_design"]["floating_oss"] + except KeyError: + self._floating_oss = False + self._outputs = {} def run(self): From 30795dacda5939cd23cf5820adecc232e793c381 Mon Sep 17 00:00:00 2001 From: Shields Date: Thu, 23 Feb 2023 15:10:32 -0700 Subject: [PATCH 17/71] Suppress print statement in oss_install/floating.py --- ORBIT/phases/install/oss_install/floating.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index cc6fa94d..88f40dae 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -99,9 +99,9 @@ def system_capex(self): line_cost = self.config["mooring_system"]["line_cost"] anchor_cost = self.config["mooring_system"]["anchor_cost"] mooring_system_for_each_oss = num_mooring_lines*(line_cost + anchor_cost) - print('topside: ' + str(topside)) - print('oss substructure' + str(substructure)) - print('mooring system' + str(mooring_system_for_each_oss)) + # print('topside: ' + str(topside)) + # print('oss substructure' + str(substructure)) + # print('mooring system' + str(mooring_system_for_each_oss)) return self.num_substations * (topside + substructure + mooring_system_for_each_oss) def initialize_substructure_production(self): @@ -153,7 +153,7 @@ def initialize_installation_vessel(self): @property def detailed_output(self): - + return {} From 48f84b00297bf6b25ee12effc3d08077de2c0b4b Mon Sep 17 00:00:00 2001 From: asharma Date: Fri, 3 Mar 2023 16:15:05 -0700 Subject: [PATCH 18/71] Make delay messages more informative --- ORBIT/phases/install/jacket_install/standard.py | 2 +- ORBIT/phases/install/monopile_install/standard.py | 2 +- ORBIT/phases/install/oss_install/standard.py | 2 +- ORBIT/phases/install/quayside_assembly_tow/gravity_base.py | 2 +- ORBIT/phases/install/quayside_assembly_tow/moored.py | 2 +- ORBIT/phases/install/turbine_install/standard.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ORBIT/phases/install/jacket_install/standard.py b/ORBIT/phases/install/jacket_install/standard.py index 2f8f0c55..95fb7402 100644 --- a/ORBIT/phases/install/jacket_install/standard.py +++ b/ORBIT/phases/install/jacket_install/standard.py @@ -480,7 +480,7 @@ def install_jackets_from_queue( start = wtiv.env.now yield queue.activate delay_time = wtiv.env.now - start - wtiv.submit_action_log("Delay", delay_time, location="Site") + wtiv.submit_action_log("Delay: Not enough vessels for jackets", delay_time, location="Site") # Transit to port wtiv.at_site = False diff --git a/ORBIT/phases/install/monopile_install/standard.py b/ORBIT/phases/install/monopile_install/standard.py index 5a204709..da16ad13 100644 --- a/ORBIT/phases/install/monopile_install/standard.py +++ b/ORBIT/phases/install/monopile_install/standard.py @@ -441,7 +441,7 @@ def install_monopiles_from_queue(wtiv, queue, monopiles, distance, **kwargs): start = wtiv.env.now yield queue.activate delay_time = wtiv.env.now - start - wtiv.submit_action_log("Delay", delay_time, location="Site") + wtiv.submit_action_log("Delay: Not enough vessels for monopiles", delay_time, location="Site") # Transit to port wtiv.at_site = False diff --git a/ORBIT/phases/install/oss_install/standard.py b/ORBIT/phases/install/oss_install/standard.py index 04038af9..c69f160d 100644 --- a/ORBIT/phases/install/oss_install/standard.py +++ b/ORBIT/phases/install/oss_install/standard.py @@ -257,7 +257,7 @@ def install_oss_from_queue(vessel, queue, substations, distance, **kwargs): start = vessel.env.now yield queue.activate delay_time = vessel.env.now - start - vessel.submit_action_log("Delay", delay_time, location="Site") + vessel.submit_action_log("Delay: Not enough vessels for oss", delay_time, location="Site") # Transit to port vessel.at_site = False diff --git a/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py b/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py index 4cbd97f6..6772a5cb 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py +++ b/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py @@ -407,6 +407,6 @@ def install_gravity_base_foundations( delay_time = vessel.env.now - start if n != 0: - vessel.submit_action_log("Delay", delay_time, location="Site") + vessel.submit_action_log("Delay: Not enough vessels for gravity foundations", delay_time, location="Site") yield vessel.transit(distance) diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index c79fbe66..a7cf9447 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -412,6 +412,6 @@ def install_moored_substructures( delay_time = vessel.env.now - start if n != 0: - vessel.submit_action_log("Delay", delay_time, location="Site") + vessel.submit_action_log("Delay: Not enough vessels for Moored substructures", delay_time, location="Site") yield vessel.transit(distance) diff --git a/ORBIT/phases/install/turbine_install/standard.py b/ORBIT/phases/install/turbine_install/standard.py index d23515a1..c05e3088 100644 --- a/ORBIT/phases/install/turbine_install/standard.py +++ b/ORBIT/phases/install/turbine_install/standard.py @@ -458,7 +458,7 @@ def install_turbine_components_from_queue( start = wtiv.env.now yield queue.activate delay_time = wtiv.env.now - start - wtiv.submit_action_log("Delay", delay_time, location="Site") + wtiv.submit_action_log("Delay: Not enough vessels for turbines", delay_time, location="Site") # Transit to port wtiv.at_site = False From 866c8d222b9ec94c2a7e505db82a271d32650485 Mon Sep 17 00:00:00 2001 From: Shields Date: Wed, 15 Mar 2023 11:58:47 -0600 Subject: [PATCH 19/71] Add electrical commissioning process (and update nacelle lift time) in TurbineAssemblyLine --- .../install/quayside_assembly_tow/common.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/common.py b/ORBIT/phases/install/quayside_assembly_tow/common.py index 252965b7..354a7367 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/common.py +++ b/ORBIT/phases/install/quayside_assembly_tow/common.py @@ -213,6 +213,8 @@ def assemble_turbine(self): yield self.mechanical_completion() + yield self.electrical_completion() + start = self.env.now yield self.target.put(1) delay = self.env.now - start @@ -267,7 +269,7 @@ def lift_and_attach_nacelle(self): """ yield self.task( - "Lift and Attach Nacelle", 7, constraints={"windspeed": le(15)} + "Lift and Attach Nacelle", 12, constraints={"windspeed": le(15)} ) @process @@ -292,6 +294,17 @@ def mechanical_completion(self): "Mechanical Completion", 24, constraints={"windspeed": le(18)} ) + @process + def electrical_completion(self): + """ + Task representing time associated with performing electrical completion + work at quayside, including precommissioning. Assumes the tower is delivered to port in multiple sections, requiring cable pull-in after tower assembly. + """ + + yield self.task( + "Electrical Completion", 72, constraints={"windspeed": le(18)} + ) + class TowingGroup(Agent): """Class to represent an arbitrary group of towing vessels.""" From 53559c32e1d56e74608dc7fe3a1e0780de0bb6a3 Mon Sep 17 00:00:00 2001 From: Shields Date: Wed, 15 Mar 2023 13:19:57 -0600 Subject: [PATCH 20/71] Update tower section process time in TurbineAssemblyLine --- ORBIT/phases/install/quayside_assembly_tow/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/common.py b/ORBIT/phases/install/quayside_assembly_tow/common.py index 354a7367..6fcd9e4f 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/common.py +++ b/ORBIT/phases/install/quayside_assembly_tow/common.py @@ -257,7 +257,7 @@ def lift_and_attach_tower_section(self): yield self.task( "Lift and Attach Tower Section", - 12, + 4, constraints={"windspeed": le(15)}, ) From 5b400aba9d2b5a5f7a4d6affe025a763f54c4b41 Mon Sep 17 00:00:00 2001 From: Shields Date: Wed, 15 Mar 2023 13:55:11 -0600 Subject: [PATCH 21/71] Added constraint for O&M activities at port to TurbineAssemblyLine.move_substructure --- ORBIT/phases/install/quayside_assembly_tow/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/common.py b/ORBIT/phases/install/quayside_assembly_tow/common.py index 6fcd9e4f..a37fea5a 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/common.py +++ b/ORBIT/phases/install/quayside_assembly_tow/common.py @@ -237,7 +237,7 @@ def move_substructure(self): TODO: Move to dynamic process involving tow groups. """ - yield self.task("Move Substructure", 8) + yield self.task("Move Substructure", 8, {'port_in_use': false()}) @process def prepare_for_assembly(self): From 5cc306d64bdf452ed4c147f3bd3991d14e6d4035 Mon Sep 17 00:00:00 2001 From: Jake Nunemaker <42254629+JakeNunemaker@users.noreply.github.com> Date: Tue, 14 Mar 2023 11:47:10 -0600 Subject: [PATCH 22/71] Feature/phase dates rework (#135) * Added check for mixed phase start types. * Added ProjectManager.start date and conditional logic to calculate phase dates if weather is not defined or phase starts are defined as ints. * Revised logic for calculating defined start time. * Added fixed timedelta functionality to dependent phases. * Added tests for fixed amount dependent phases. * Added test for phase_dates. * Removed ceil from several methods in ProjectManager. --- ORBIT/manager.py | 99 ++++++++++++++++++++++------- tests/test_project_manager.py | 113 ++++++++++++++++++++++++++++++++-- 2 files changed, 186 insertions(+), 26 deletions(-) diff --git a/ORBIT/manager.py b/ORBIT/manager.py index 3252b650..303ecbaf 100644 --- a/ORBIT/manager.py +++ b/ORBIT/manager.py @@ -132,6 +132,17 @@ def __init__(self, config, library_path=None, weather=None): self.phase_times = {} self._output_logs = [] + @property + def start_date(self): + """Return start date for the analysis. If weather is configured, the + first date in the weather profile is used. If weather is not configured, + an arbitary start date is assumed and used to index phase times.""" + + if self.weather is not None: + return self.weather.index[0].to_pydatetime() + + return dt.datetime(2010, 1, 1, 0, 0) + def run(self, **kwargs): """ Main project run method. @@ -681,7 +692,7 @@ def run_multiple_phases_in_serial(self, phase_list, **kwargs): pass self._output_logs.extend(logs) - start = ceil(start + time) + start = start + time def run_multiple_phases_overlapping(self, phases, **kwargs): """ @@ -784,7 +795,37 @@ def get_dependency_start_time(self, target, perc): start = self.phase_starts[target] elapsed = self.phase_times[target] - return start + elapsed * perc + if isinstance(perc, (int, float)): + + if (perc < 0.) or (perc > 1.): + raise ValueError(f"Dependent phase perc must be between 0. and 1.") + + return start + elapsed * perc + + if isinstance(perc, str): + + try: + delta = dt.timedelta( + **{ + v.split("=")[0].strip(): float(v.split("=")[1]) + for v in perc.split(";") + } + ) + + return start + delta.days * 24 + delta.seconds / 3600 + + except (TypeError, IndexError): + raise ValueError( + f"Dependent phase amount must be defined with this format: " + "'weeks=1;hours=12'. Accepted entries: 'weeks', 'days', 'hours'." + ) + + else: + raise ValueError( + f"Unrecognized dependent phase amount: '{perc}'. " + f"Must be float between 0. and 1.0 or str with format " + "'weeks=1;days=0;hours=12'" + ) @staticmethod def transform_weather_input(weather): @@ -833,24 +874,8 @@ def _parse_install_phase_values(self, phases): for k, v in phases.items(): - if isinstance(v, (int, float)): - defined[k] = ceil(v) - - elif isinstance(v, str): - _dt = dt.datetime.strptime(v, self.date_format_short) - - try: - i = self.weather.index.get_loc(_dt) - defined[k] = i - - except AttributeError: - raise ValueError( - f"No weather profile configured " - f"for '{k}': '{v}' input type." - ) - - except KeyError: - raise WeatherProfileError(_dt, self.weather) + if isinstance(v, (int, float, str)): + defined[k] = v elif isinstance(v, tuple) and len(v) == 2: depends[k] = v @@ -860,7 +885,32 @@ def _parse_install_phase_values(self, phases): if not defined: raise ValueError("No phases have a defined start index/date.") + + if len(set(type(i) for i in defined.values())) > 1: + raise ValueError( + "Defined start date types can't be mixed. " + "All must be an int (index location) or str (format: '%m/%d/%Y'). " + "This does not apply to the dependent phases defined as tuples." + ) + + for k, v in defined.items(): + + if isinstance(v, int): + continue + _dt = dt.datetime.strptime(v, self.date_format_short) + + if self.weather is not None: + try: + defined[k] = self.weather.index.get_loc(_dt) + + except KeyError: + raise WeatherProfileError(_dt, self.weather) + + else: + delta = (_dt - self.start_date) + defined[k] = delta.days * 24 + delta.seconds / 3600 + return defined, depends def get_weather_profile(self, start): @@ -1147,8 +1197,13 @@ def phase_dates(self): for phase, _start in self.config["install_phases"].items(): - start = dt.datetime.strptime(_start, self.date_format_short) - end = start + dt.timedelta(hours=ceil(self.phase_times[phase])) + try: + start = dt.datetime.strptime(_start, self.date_format_short) + + except TypeError: + start = self.start_date + dt.timedelta(hours=self.phase_starts[phase]) + + end = start + dt.timedelta(hours=self.phase_times[phase]) dates[phase] = { "start": start.strftime(self.date_format_long), diff --git a/tests/test_project_manager.py b/tests/test_project_manager.py index 7e62a225..113c2ac8 100644 --- a/tests/test_project_manager.py +++ b/tests/test_project_manager.py @@ -7,6 +7,7 @@ from copy import deepcopy import pandas as pd +import datetime as dt import pytest from ORBIT import ProjectManager @@ -148,11 +149,11 @@ class SpecificTurbineInstallation(InstallPhase): ### Overlapping Install Phases -def test_install_phase_start_parsing(): +def test_install_phase_start_parsing__dates(): config_mixed_starts = deepcopy(config) config_mixed_starts["install_phases"] = { - "MonopileInstallation": 0, + "MonopileInstallation": "10/22/2010", "TurbineInstallation": "10/22/2009", "ArrayCableInstallation": ("MonopileInstallation", 0.5), } @@ -164,10 +165,95 @@ def test_install_phase_start_parsing(): assert len(defined) == 2 assert len(depends) == 1 - assert defined["MonopileInstallation"] == 0 + assert defined["MonopileInstallation"] == 8761 assert defined["TurbineInstallation"] == 1 +def test_install_phase_start_parsing__ints(): + + config_mixed_starts = deepcopy(config) + config_mixed_starts["install_phases"] = { + "MonopileInstallation": 0, + "TurbineInstallation": 100, + "ArrayCableInstallation": ("MonopileInstallation", 0.5), + } + + project = ProjectManager(config_mixed_starts, weather=weather_df) + defined, depends = project._parse_install_phase_values( + config_mixed_starts["install_phases"] + ) + assert len(defined) == 2 + assert len(depends) == 1 + + assert defined["MonopileInstallation"] == 0 + assert defined["TurbineInstallation"] == 100 + +@pytest.mark.parametrize("weather", (None, weather_df)) +@pytest.mark.parametrize("defined", (0, "10/22/2009")) +@pytest.mark.parametrize( + "amount_str, diff", + [ + ("hours=10", 10), + ("days=1", 24), + ("days=1;hours=10", 34), + ("weeks=1", 168), + ("weeks=1;days=1;hours=10", 202), + ] +) +def test_dependent_install_phases_fixed_amounts(weather, defined, amount_str, diff): + + new = deepcopy(config) + new["install_phases"] = { + "MonopileInstallation": defined, + "TurbineInstallation": ("MonopileInstallation", amount_str), + } + + project = ProjectManager(new, weather=weather) + project.run() + + diff_calc = project.phase_starts["TurbineInstallation"] - project.phase_starts["MonopileInstallation"] + + assert diff_calc == diff + + +@pytest.mark.parametrize("input_val", (-1, 1.2, "years=10", "days:10")) +def test_dependent_install_phases_bad_inputs(input_val): + + new = deepcopy(config) + new["install_phases"] = { + "MonopileInstallation": 0, + "TurbineInstallation": ("MonopileInstallation", input_val), + } + + project = ProjectManager(new) + + with pytest.raises(ValueError): + project.run() + + +@pytest.mark.parametrize("weather", (None, weather_df)) +@pytest.mark.parametrize("defined", (0, "10/22/2009")) +@pytest.mark.parametrize("input_val", (0.5, "hours=10", "days=1;hours=10")) +def test_dependent_install_phases_phase_dates(weather, defined, input_val): + + new = deepcopy(config) + new["install_phases"] = { + "MonopileInstallation": defined, + "TurbineInstallation": ("MonopileInstallation", input_val), + } + + project = ProjectManager(new, weather=weather) + project.run() + + phase_dates = project.phase_dates + for p in ["MonopileInstallation", "TurbineInstallation"]: + assert p in phase_dates + + for key in ["start", "end"]: + _ = dt.datetime.strptime(phase_dates[p][key], project.date_format_long) + assert True + + def test_chained_dependencies(): config_chained = deepcopy(config) @@ -227,7 +313,6 @@ def test_index_starts(m_start, t_start): [ (0, 0, 0), (0, 1000, 1000), - (0, "05/01/2010", 4585), ("03/01/2010", "03/01/2010", 0), ("03/01/2010", "05/01/2010", 1464), ], @@ -251,6 +336,26 @@ def test_start_dates_with_weather(m_start, t_start, expected): assert _diff == expected +@pytest.mark.parametrize( + "m_start, t_start", + [ + (0, "03/01/2010"), + ("03/01/2010", 0), + ], +) +def test_mixed_start_date_types(m_start, t_start): + + config_with_defined_starts = deepcopy(config) + config_with_defined_starts["install_phases"] = { + "MonopileInstallation": m_start, + "TurbineInstallation": t_start, + "ArrayCableInstallation": ("MonopileInstallation", 0.5), + } + + with pytest.raises(ValueError): + project = ProjectManager(config_with_defined_starts, weather_df) + project.run() + def test_duplicate_phase_definitions(): config_with_duplicates = deepcopy(config) config_with_duplicates["MonopileInstallation_1"] = { From e58c88612819850be23bfba000fb6e15ce369583 Mon Sep 17 00:00:00 2001 From: asharma Date: Wed, 15 Mar 2023 14:23:12 -0600 Subject: [PATCH 23/71] change default value to boolean --- ORBIT/phases/install/quayside_assembly_tow/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/common.py b/ORBIT/phases/install/quayside_assembly_tow/common.py index a37fea5a..a2e83c49 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/common.py +++ b/ORBIT/phases/install/quayside_assembly_tow/common.py @@ -237,7 +237,7 @@ def move_substructure(self): TODO: Move to dynamic process involving tow groups. """ - yield self.task("Move Substructure", 8, {'port_in_use': false()}) + yield self.task("Move Substructure", 8, {'port_in_use': False}) @process def prepare_for_assembly(self): From 04009f25a02d0e11ea5920a7f6baec7da510ca03 Mon Sep 17 00:00:00 2001 From: asharma Date: Wed, 15 Mar 2023 21:30:09 -0600 Subject: [PATCH 24/71] implementation for transfering and installing --- ORBIT/core/library.py | 3 +- .../install/quayside_assembly_tow/common.py | 43 ++- .../quayside_assembly_tow/gravity_base.py | 26 +- .../install/quayside_assembly_tow/moored.py | 284 ++++++++---------- .../doc_MooredSubInstallation.rst | 1 + library/vessels/example_ahts_vessel.yaml | 6 + .../project/config/moored_install.yaml | 4 +- .../config/moored_install_multi_assembly.yaml | 21 ++ ...ored_install_multi_assembly_multi_tow.yaml | 21 ++ .../config/moored_install_multi_tow.yaml | 21 ++ .../config/moored_install_no_supply.yaml | 4 +- .../library/vessels/test_ahts_vessel.yaml | 6 + .../quayside_assembly_tow/test_moored.py | 27 +- 13 files changed, 283 insertions(+), 184 deletions(-) create mode 100644 library/vessels/example_ahts_vessel.yaml create mode 100644 tests/data/library/project/config/moored_install_multi_assembly.yaml create mode 100644 tests/data/library/project/config/moored_install_multi_assembly_multi_tow.yaml create mode 100644 tests/data/library/project/config/moored_install_multi_tow.yaml create mode 100644 tests/data/library/vessels/test_ahts_vessel.yaml diff --git a/ORBIT/core/library.py b/ORBIT/core/library.py index 6f771cc0..e33b4523 100644 --- a/ORBIT/core/library.py +++ b/ORBIT/core/library.py @@ -38,12 +38,12 @@ import yaml import pandas as pd from yaml import Dumper - from ORBIT.core.exceptions import LibraryItemNotFoundError ROOT = os.path.abspath(os.path.join(os.path.abspath(__file__), "../../..")) default_library = os.path.join(ROOT, "library") + # Need a custom loader to read in scientific notation correctly class CustomSafeLoader(yaml.SafeLoader): def construct_python_tuple(self, node): @@ -277,6 +277,7 @@ def export_library_specs(key, filename, data, file_ext="yaml"): "wtiv": "vessels", "towing_vessel": "vessels", "support_vessel": "vessels", + "ahts_vessel": "vessels", # cables "cables": "cables", "array_system": "cables", diff --git a/ORBIT/phases/install/quayside_assembly_tow/common.py b/ORBIT/phases/install/quayside_assembly_tow/common.py index a2e83c49..5ca39c6a 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/common.py +++ b/ORBIT/phases/install/quayside_assembly_tow/common.py @@ -237,7 +237,7 @@ def move_substructure(self): TODO: Move to dynamic process involving tow groups. """ - yield self.task("Move Substructure", 8, {'port_in_use': False}) + yield self.task("Move Substructure", 8, {"port_in_use": False}) @process def prepare_for_assembly(self): @@ -309,7 +309,7 @@ def electrical_completion(self): class TowingGroup(Agent): """Class to represent an arbitrary group of towing vessels.""" - def __init__(self, vessel_specs, num=1): + def __init__(self, vessel_specs, ahts_vessel_specs=None, num=1): """ Creates an instance of TowingGroup. @@ -318,13 +318,27 @@ def __init__(self, vessel_specs, num=1): vessel_specs : dict Specs for the individual vessels used in the towing group. Currently restricted to one vessel specification per group. + num : int + Towing group number + ahts_vessel_specs : dict + Specs for the anchor hndling tug vessel. """ super().__init__(f"Towing Group {num}") self._specs = vessel_specs - self.day_rate = self._specs["vessel_specs"]["day_rate"] + self.day_rate_towing = self._specs["vessel_specs"]["day_rate"] + self.day_rate_anchor = 0.0 self.transit_speed = self._specs["transport_specs"]["transit_speed"] + if ahts_vessel_specs is not None: + self.day_rate_anchor = ahts_vessel_specs["vessel_specs"][ + "day_rate" + ] + self.transit_speed = min( + vessel_specs["transport_specs"]["transit_speed"], + ahts_vessel_specs["transport_specs"]["transit_speed"], + ) + def initialize(self): """Initializes the towing group.""" @@ -332,7 +346,13 @@ def initialize(self): @process def group_task( - self, name, duration, num_vessels, constraints={}, **kwargs + self, + name, + duration, + num_vessels, + num_ahts_vessels=0, + constraints={}, + **kwargs, ): """ Submits a group task with any number of towing vessels. @@ -346,9 +366,12 @@ def group_task( Rounded up to the nearest int. num_vessels : int Number of individual towing vessels needed for the operation. + num_ahts_vessels : int + Number of anchor handling tug vessels used for the operation. """ kwargs = {**kwargs, "num_vessels": num_vessels} + kwargs = {**kwargs, "num_ahts_vessels": num_ahts_vessels} yield self.task(name, duration, constraints=constraints, **kwargs) def operation_cost(self, hours, **kwargs): @@ -365,8 +388,16 @@ def operation_cost(self, hours, **kwargs): """ mult = kwargs.get("cost_multiplier", 1.0) - vessels = kwargs.get("num_vessels", 1) - return (self.day_rate / 24) * vessels * hours * mult + num_towing_vessels = kwargs.get("num_vessels", 1) + num_ahts_vessels = kwargs.get("num_ahts_vessels", 0) + return ( + ( + (self.day_rate_towing / 24) * num_towing_vessels + + (self.day_rate_anchor / 24) * num_ahts_vessels + ) + * hours + * mult + ) def submit_action_log(self, action, duration, **kwargs): """ diff --git a/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py b/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py index 6772a5cb..665f6d7c 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py +++ b/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py @@ -8,7 +8,6 @@ import simpy from marmot import le, process - from ORBIT.core import Vessel, WetStorage from ORBIT.phases.install import InstallPhase @@ -184,7 +183,7 @@ def initialize_towing_groups(self, **kwargs): towing_speed = self.config["substructure"].get("towing_speed", 6) for i in range(num_groups): - g = TowingGroup(vessel, num=i + 1) + g = TowingGroup(vessel, None, num=i + 1) self.env.register(g) g.initialize() self.installation_groups.append(g) @@ -293,18 +292,21 @@ def transfer_gbf_substructures_from_storage( transit_time = distance / group.transit_speed while True: - start = group.env.now assembly = yield feed.get() delay = group.env.now - start if delay > 0: group.submit_action_log( - "Delay: No Completed Assemblies Available", delay + "Delay: No Completed Assemblies Available", + delay, + num_vessels=towing_vessels, ) yield group.group_task( - "Tow Substructure", towing_time, num_vessels=towing_vessels + "Tow Substructure", + towing_time, + num_vessels=towing_vessels, ) # At Site @@ -314,7 +316,12 @@ def transfer_gbf_substructures_from_storage( queue_time = group.env.now - queue_start if queue_time > 0: - group.submit_action_log("Queue", queue_time, location="Site") + group.submit_action_log( + "Queue", + queue_time, + location="Site", + num_vessels=towing_vessels, + ) queue.vessel = group active_start = group.env.now @@ -357,7 +364,6 @@ def install_gravity_base_foundations( n = 0 while n < substructures: if queue.vessel: - start = vessel.env.now if n == 0: vessel.mobilize() @@ -407,6 +413,10 @@ def install_gravity_base_foundations( delay_time = vessel.env.now - start if n != 0: - vessel.submit_action_log("Delay: Not enough vessels for gravity foundations", delay_time, location="Site") + vessel.submit_action_log( + "Delay: Not enough vessels for gravity foundations", + delay_time, + location="Site", + ) yield vessel.transit(distance) diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index a7cf9447..561df3a9 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -26,11 +26,11 @@ class MooredSubInstallation(InstallPhase): #: expected_config = { - "support_vessel": "str", + "ahts_vessel": "str", "towing_vessel": "str", "towing_vessel_groups": { "towing_vessels": "int", - "station_keeping_vessels": "int", + "ahts_vessels": "int (optional, default: 1)", "num_groups": "int (optional)", }, "substructure": { @@ -86,7 +86,6 @@ def setup_simulation(self, **kwargs): self.initialize_turbine_assembly() self.initialize_queue() self.initialize_towing_groups() - self.initialize_support_vessel() @property def system_capex(self): @@ -177,24 +176,30 @@ def initialize_towing_groups(self, **kwargs): self.installation_groups = [] - vessel = self.config["towing_vessel"] + towing_vessel = self.config["towing_vessel"] num_groups = self.config["towing_vessel_groups"].get("num_groups", 1) - towing = self.config["towing_vessel_groups"]["towing_vessels"] + num_towing = self.config["towing_vessel_groups"]["towing_vessels"] towing_speed = self.config["substructure"].get("towing_speed", 6) + ahts_vessel = self.config["ahts_vessel"] + num_ahts = self.config["towing_vessel_groups"]["ahts_vessels"] + + remaining_substructures = [1] * self.num_turbines + for i in range(num_groups): - g = TowingGroup(vessel, num=i + 1) + g = TowingGroup(towing_vessel, ahts_vessel, i + 1) self.env.register(g) g.initialize() self.installation_groups.append(g) - transfer_moored_substructures_from_storage( + transfer_install_moored_substructures_from_storage( g, self.assembly_storage, self.distance, - self.active_group, - towing, + num_towing, + num_ahts, towing_speed, + remaining_substructures, **kwargs, ) @@ -208,32 +213,6 @@ def initialize_queue(self): self.active_group.vessel = None self.active_group.activate = self.env.event() - def initialize_support_vessel(self, **kwargs): - """ - Initializes Multi-Purpose Support Vessel to perform installation - processes at site. - """ - - specs = self.config["support_vessel"] - vessel = self.initialize_vessel("Multi-Purpose Support Vessel", specs) - - self.env.register(vessel) - vessel.initialize(mobilize=False) - self.support_vessel = vessel - - station_keeping_vessels = self.config["towing_vessel_groups"][ - "station_keeping_vessels" - ] - - install_moored_substructures( - self.support_vessel, - self.active_group, - self.distance, - self.num_turbines, - station_keeping_vessels, - **kwargs, - ) - @property def detailed_output(self): """""" @@ -252,9 +231,6 @@ def detailed_output(self): k: self.operational_delay(str(k)) for k in self.installation_groups }, - self.support_vessel: self.operational_delay( - str(self.support_vessel) - ), } } @@ -268,11 +244,50 @@ def operational_delay(self, name): @process -def transfer_moored_substructures_from_storage( - group, feed, distance, queue, towing_vessels, towing_speed, **kwargs +def transfer_install_moored_substructures_from_storage( + group, + feed, + distance, + towing_vessels, + ahts_vessels, + towing_speed, + remaining_substructures, + **kwargs, ): """ - Process logic for the towing vessel group. + Trigger the substructure installtions. Shuts down after + self.remaining_substructures is empty. + """ + + while True: + try: + _ = remaining_substructures.pop(0) + yield towing_group_actions( + group, + feed, + distance, + towing_vessels, + ahts_vessels, + towing_speed, + **kwargs, + ) + + except IndexError: + break + + +@process +def towing_group_actions( + group, + feed, + distance, + towing_vessels, + ahts_vessels, + towing_speed, + **kwargs, +): + """ + Process logic for the towing vessel group. Assumes there is an anchor tug boat with each group Parameters ---------- @@ -286,132 +301,79 @@ def transfer_moored_substructures_from_storage( Number of vessels to use for towing to site. towing_speed : int | float Configured towing speed (km/h) + num_substructures : int + Number of substructures to be installed corresponding to number of turbines """ towing_time = distance / towing_speed transit_time = distance / group.transit_speed - while True: - - start = group.env.now - assembly = yield feed.get() - delay = group.env.now - start - - if delay > 0: - group.submit_action_log( - "Delay: No Completed Assemblies Available", delay - ) - - yield group.group_task( - "Ballast to Towing Draft", - 6, - num_vessels=towing_vessels, - constraints={"windspeed": le(15), "waveheight": le(2.5)}, - ) + start = group.env.now + assembly = yield feed.get() + delay = group.env.now - start - yield group.group_task( - "Tow Substructure", - towing_time, + if delay > 0: + group.submit_action_log( + "Delay: No Completed Assemblies Available", + delay, num_vessels=towing_vessels, - constraints={"windspeed": le(15), "waveheight": le(2.5)}, - ) - - # At Site - with queue.request() as req: - queue_start = group.env.now - yield req - - queue_time = group.env.now - queue_start - if queue_time > 0: - group.submit_action_log("Queue", queue_time, location="Site") - - queue.vessel = group - active_start = group.env.now - queue.activate.succeed() - - # Released by WTIV when objects are depleted - group.release = group.env.event() - yield group.release - active_time = group.env.now - active_start - - queue.vessel = None - queue.activate = group.env.event() - - yield group.group_task( - "Transit", transit_time, num_vessels=towing_vessels + num_ahts_vessels=ahts_vessels, ) - -@process -def install_moored_substructures( - vessel, queue, distance, substructures, station_keeping_vessels, **kwargs -): - """ - Logic that a Multi-Purpose Support Vessel uses at site to complete the - installation of moored substructures. - - Parameters - ---------- - vessel : Vessel - queue : - distance : int | float - Distance between port and site (km). - substructures : int - Number of substructures to install before transiting back to port. - station_keeping_vessels : int - Number of vessels to use for substructure station keeping during final - installation at site. - """ - - n = 0 - while n < substructures: - if queue.vessel: - - start = vessel.env.now - if n == 0: - vessel.mobilize() - yield vessel.transit(distance) - - yield vessel.task_wrapper( - "Position Substructure", - 2, - constraints={"windspeed": le(15), "waveheight": le(2.5)}, - ) - yield vessel.task_wrapper( - "Ballast to Operational Draft", - 6, - constraints={"windspeed": le(15), "waveheight": le(2.5)}, - ) - yield vessel.task_wrapper( - "Connect Mooring Lines, Pre-tension and pre-stretch", - 20, - suspendable=True, - constraints={"windspeed": le(15), "waveheight": le(2.5)}, - ) - yield vessel.task_wrapper( - "Check Mooring Lines", - 6, - suspendable=True, - constraints={"windspeed": le(15), "waveheight": le(2.5)}, - ) - - group_time = vessel.env.now - start - queue.vessel.submit_action_log( - "Positioning Support", - group_time, - location="site", - num_vessels=station_keeping_vessels, - ) - yield queue.vessel.release.succeed() - vessel.submit_debug_log(progress="Substructure") - n += 1 - - else: - start = vessel.env.now - yield queue.activate - delay_time = vessel.env.now - start - - if n != 0: - vessel.submit_action_log("Delay: Not enough vessels for Moored substructures", delay_time, location="Site") - - yield vessel.transit(distance) + yield group.group_task( + "Ballast to Towing Draft", + 6, + num_vessels=towing_vessels, + num_ahts_vessels=ahts_vessels, + constraints={"windspeed": le(15), "waveheight": le(2.5)}, + ) + + yield group.group_task( + "Tow Substructure", + towing_time, + num_vessels=towing_vessels, + num_ahts_vessels=ahts_vessels, + constraints={"windspeed": le(15), "waveheight": le(2.5)}, + ) + + # At Site + yield group.group_task( + "Position Substructure", + 2, + num_vessels=towing_vessels, + num_ahts_vessels=ahts_vessels, + constraints={"windspeed": le(15), "waveheight": le(2.5)}, + ) + + yield group.group_task( + "Ballast to Operational Draft", + 6, + num_vessels=towing_vessels, + num_ahts_vessels=ahts_vessels, + constraints={"windspeed": le(15), "waveheight": le(2.5)}, + ) + + yield group.group_task( + "Connect Mooring Lines, Pre-tension and pre-stretch", + 20, + num_vessels=towing_vessels, + num_ahts_vessels=ahts_vessels, + suspendable=True, + constraints={"windspeed": le(15), "waveheight": le(2.5)}, + ) + + yield group.group_task( + "Check Mooring Lines", + 6, + num_vessels=towing_vessels, + num_ahts_vessels=ahts_vessels, + suspendable=True, + constraints={"windspeed": le(15), "waveheight": le(2.5)}, + ) + + yield group.group_task( + "Transit", + transit_time, + num_vessels=towing_vessels, + num_ahts_vessels=ahts_vessels, + ) diff --git a/docs/source/phases/install/quayside_towout/doc_MooredSubInstallation.rst b/docs/source/phases/install/quayside_towout/doc_MooredSubInstallation.rst index ad137a51..3838bca7 100644 --- a/docs/source/phases/install/quayside_towout/doc_MooredSubInstallation.rst +++ b/docs/source/phases/install/quayside_towout/doc_MooredSubInstallation.rst @@ -28,6 +28,7 @@ the key parameters available. ... "support_vessel": "example_support_vessel", # Will perform onsite installation procedures. + "ahts_vessel": "example_ahts_vessel", # Anchor handling tug supply vessel associated with each tow group. "towing_vessel": "example_towing_vessel", # Towing groups will contain multiple of this vessel. "towing_groups": { "towing_vessel": 1, # Vessels used to tow the substructure to site. diff --git a/library/vessels/example_ahts_vessel.yaml b/library/vessels/example_ahts_vessel.yaml new file mode 100644 index 00000000..28023f85 --- /dev/null +++ b/library/vessels/example_ahts_vessel.yaml @@ -0,0 +1,6 @@ +transport_specs: + max_waveheight: 2.5 # m + max_windspeed: 20 # m/s + transit_speed: 6 # km/h +vessel_specs: + day_rate: 100000 # USD/day diff --git a/tests/data/library/project/config/moored_install.yaml b/tests/data/library/project/config/moored_install.yaml index 47cd8bb0..631f0e44 100644 --- a/tests/data/library/project/config/moored_install.yaml +++ b/tests/data/library/project/config/moored_install.yaml @@ -12,10 +12,10 @@ substructure: takt_time: 168 towing_speed: 6 unit_cost: 12e6 -support_vessel: test_support_vessel +ahts_vessel: test_ahts_vessel towing_vessel: test_towing_vessel towing_vessel_groups: num_groups: 1 - station_keeping_vessels: 3 + ahts_vessels: 1 towing_vessels: 1 turbine: 12MW_generic diff --git a/tests/data/library/project/config/moored_install_multi_assembly.yaml b/tests/data/library/project/config/moored_install_multi_assembly.yaml new file mode 100644 index 00000000..2f196638 --- /dev/null +++ b/tests/data/library/project/config/moored_install_multi_assembly.yaml @@ -0,0 +1,21 @@ +plant: + num_turbines: 50 +port: + assembly_storage: 1 + sub_assembly_lines: 3 + sub_storage: 1 + turbine_assembly_cranes: 1 +site: + depth: 500 + distance: 50 +substructure: + takt_time: 168 + towing_speed: 6 + unit_cost: 12e6 +ahts_vessel: test_ahts_vessel +towing_vessel: test_towing_vessel +towing_vessel_groups: + num_groups: 1 + ahts_vessels: 1 + towing_vessels: 1 +turbine: 12MW_generic diff --git a/tests/data/library/project/config/moored_install_multi_assembly_multi_tow.yaml b/tests/data/library/project/config/moored_install_multi_assembly_multi_tow.yaml new file mode 100644 index 00000000..2f196638 --- /dev/null +++ b/tests/data/library/project/config/moored_install_multi_assembly_multi_tow.yaml @@ -0,0 +1,21 @@ +plant: + num_turbines: 50 +port: + assembly_storage: 1 + sub_assembly_lines: 3 + sub_storage: 1 + turbine_assembly_cranes: 1 +site: + depth: 500 + distance: 50 +substructure: + takt_time: 168 + towing_speed: 6 + unit_cost: 12e6 +ahts_vessel: test_ahts_vessel +towing_vessel: test_towing_vessel +towing_vessel_groups: + num_groups: 1 + ahts_vessels: 1 + towing_vessels: 1 +turbine: 12MW_generic diff --git a/tests/data/library/project/config/moored_install_multi_tow.yaml b/tests/data/library/project/config/moored_install_multi_tow.yaml new file mode 100644 index 00000000..ae4585e5 --- /dev/null +++ b/tests/data/library/project/config/moored_install_multi_tow.yaml @@ -0,0 +1,21 @@ +plant: + num_turbines: 50 +port: + assembly_storage: 1 + sub_assembly_lines: 1 + sub_storage: 1 + turbine_assembly_cranes: 1 +site: + depth: 500 + distance: 50 +substructure: + takt_time: 168 + towing_speed: 6 + unit_cost: 12e6 +ahts_vessel: test_ahts_vessel +towing_vessel: test_towing_vessel +towing_vessel_groups: + num_groups: 3 + ahts_vessels: 1 + towing_vessels: 1 +turbine: 12MW_generic diff --git a/tests/data/library/project/config/moored_install_no_supply.yaml b/tests/data/library/project/config/moored_install_no_supply.yaml index 249abd85..57d48179 100644 --- a/tests/data/library/project/config/moored_install_no_supply.yaml +++ b/tests/data/library/project/config/moored_install_no_supply.yaml @@ -10,10 +10,10 @@ substructure: takt_time: 0 towing_speed: 6 unit_cost: 12e6 -support_vessel: test_support_vessel +ahts_vessel: test_ahts_vessel towing_vessel: test_towing_vessel towing_vessel_groups: num_groups: 1 - station_keeping_vessels: 3 + ahts_vessels: 1 towing_vessels: 1 turbine: 12MW_generic diff --git a/tests/data/library/vessels/test_ahts_vessel.yaml b/tests/data/library/vessels/test_ahts_vessel.yaml new file mode 100644 index 00000000..28023f85 --- /dev/null +++ b/tests/data/library/vessels/test_ahts_vessel.yaml @@ -0,0 +1,6 @@ +transport_specs: + max_waveheight: 2.5 # m + max_windspeed: 20 # m/s + transit_speed: 6 # km/h +vessel_specs: + day_rate: 100000 # USD/day diff --git a/tests/phases/install/quayside_assembly_tow/test_moored.py b/tests/phases/install/quayside_assembly_tow/test_moored.py index e1fc0af7..c2ebba3f 100644 --- a/tests/phases/install/quayside_assembly_tow/test_moored.py +++ b/tests/phases/install/quayside_assembly_tow/test_moored.py @@ -14,16 +14,21 @@ from ORBIT.phases.install import MooredSubInstallation config = extract_library_specs("config", "moored_install") +multi_assembly = extract_library_specs( + "config", "moored_install_multi_assembly" +) +multi_tow = extract_library_specs("config", "moored_install_multi_tow") +multi_assembly_multi_tow = extract_library_specs( + "config", "moored_install_multi_assembly_multi_tow" +) no_supply = extract_library_specs("config", "moored_install_no_supply") def test_simulation_setup(): - sim = MooredSubInstallation(config) assert sim.config == config assert sim.env - assert sim.support_vessel assert len(sim.sub_assembly_lines) == config["port"]["sub_assembly_lines"] assert ( len(sim.turbine_assembly_lines) @@ -39,9 +44,18 @@ def test_simulation_setup(): @pytest.mark.parametrize( "weather", (None, test_weather), ids=["no_weather", "test_weather"] ) -@pytest.mark.parametrize("config", (config, no_supply)) +@pytest.mark.parametrize( + "config", + (config, multi_assembly, multi_tow, multi_assembly_multi_tow, no_supply), + ids=[ + "1 assembly, 1 tow", + "3 assembly, 1 tow", + "1 assembly, 3 tow", + "3 assembly, 3 tow", + "no supply", + ], +) def test_for_complete_logging(weather, config): - sim = MooredSubInstallation(config, weather=weather) sim.run() @@ -56,3 +70,8 @@ def test_for_complete_logging(weather, config): assert ~df["cost"].isnull().any() _ = sim.agent_efficiencies _ = sim.detailed_output + + installed_mooring_lines = len( + [a for a in sim.env.actions if a["action"] == "Position Substructure"] + ) + assert installed_mooring_lines == sim.num_turbines From 841b4d0c4730891a23245e13d1ee1072967605c6 Mon Sep 17 00:00:00 2001 From: Jake Nunemaker Date: Tue, 28 Mar 2023 09:24:40 -0600 Subject: [PATCH 25/71] Revised port_in_use constraint. --- ORBIT/phases/install/quayside_assembly_tow/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/common.py b/ORBIT/phases/install/quayside_assembly_tow/common.py index 5ca39c6a..49533caa 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/common.py +++ b/ORBIT/phases/install/quayside_assembly_tow/common.py @@ -7,7 +7,7 @@ __email__ = "jake.nunemaker@nrel.gov" -from marmot import Agent, le, process +from marmot import Agent, le, process, false from marmot._exceptions import AgentNotRegistered @@ -237,7 +237,7 @@ def move_substructure(self): TODO: Move to dynamic process involving tow groups. """ - yield self.task("Move Substructure", 8, {"port_in_use": False}) + yield self.task("Move Substructure", 8, {"port_in_use": false()}) @process def prepare_for_assembly(self): From f66affc21aa4db4a0b0e66c702ce23da021807c8 Mon Sep 17 00:00:00 2001 From: asharma Date: Sat, 8 Apr 2023 18:53:33 -0600 Subject: [PATCH 26/71] improve delay message and formatting --- ORBIT/phases/install/oss_install/floating.py | 41 +++++++++++--------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index 88f40dae..3d4e551b 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -6,11 +6,10 @@ __email__ = "jake.nunemaker@nrel.gov" -from marmot import Agent, process, le -from marmot._exceptions import AgentNotRegistered - +from marmot import Agent, le, process from ORBIT.core import WetStorage from ORBIT.core.logic import position_onsite +from marmot._exceptions import AgentNotRegistered from ORBIT.phases.install import InstallPhase from ORBIT.phases.install.mooring_install.mooring import ( install_mooring_line, @@ -41,15 +40,19 @@ class FloatingSubstationInstallation(InstallPhase): "type": "Floating", "takt_time": "int | float (optional, default: 0)", "unit_cost": "USD", - #"mooring_cost": "USD", - "towing_speed": "int | float (optional, default: 6 km/h)" - }, - "mooring_system": { - #"system_cost": "USD", "}, # system cost is for all moorings in the whole farm, so you dont want this to be added to each substation - "num_lines", "int", - "line_cost", "USD", - "anchor_cost", "USD"} - } + # "mooring_cost": "USD", + "towing_speed": "int | float (optional, default: 6 km/h)", + }, + "mooring_system": { + # "system_cost": "USD", "}, # system cost is for all moorings in the whole farm, so you dont want this to be added to each substation + "num_lines", + "int", + "line_cost", + "USD", + "anchor_cost", + "USD", + }, + } def __init__(self, config, weather=None, **kwargs): """ @@ -98,11 +101,15 @@ def system_capex(self): num_mooring_lines = self.config["mooring_system"]["num_lines"] line_cost = self.config["mooring_system"]["line_cost"] anchor_cost = self.config["mooring_system"]["anchor_cost"] - mooring_system_for_each_oss = num_mooring_lines*(line_cost + anchor_cost) + mooring_system_for_each_oss = num_mooring_lines * ( + line_cost + anchor_cost + ) # print('topside: ' + str(topside)) # print('oss substructure' + str(substructure)) # print('mooring system' + str(mooring_system_for_each_oss)) - return self.num_substations * (topside + substructure + mooring_system_for_each_oss) + return self.num_substations * ( + topside + substructure + mooring_system_for_each_oss + ) def initialize_substructure_production(self): """ @@ -153,7 +160,6 @@ def initialize_installation_vessel(self): @property def detailed_output(self): - return {} @@ -184,13 +190,12 @@ def install_floating_substations( travel_time = distance / towing_speed for _ in range(number): - start = vessel.env.now yield feed.get() delay = vessel.env.now - start if delay > 0: vessel.submit_action_log( - "Delay: Waiting on Completed Assembly", delay + "Delay: Waiting on Substation Assembly", delay ) yield vessel.task( @@ -205,7 +210,7 @@ def install_floating_substations( constraints={"windspeed": le(15), "waveheight": le(2.5)}, ) - for _ in range (3): + for _ in range(3): yield perform_mooring_site_survey(vessel) yield install_mooring_anchor(vessel, depth, "Suction Pile") yield install_mooring_line(vessel, depth) From 9684fec263afb41bd7a7ac1dc0fa777ef5a57fe3 Mon Sep 17 00:00:00 2001 From: asharma Date: Sat, 8 Apr 2023 18:58:09 -0600 Subject: [PATCH 27/71] use user-defined wave height and wind speed limits --- .../install/quayside_assembly_tow/common.py | 12 +++++++++- .../install/quayside_assembly_tow/moored.py | 24 +++++++++++++------ library/vessels/example_ahts_vessel.yaml | 6 ++--- library/vessels/example_towing_vessel.yaml | 4 ++-- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/common.py b/ORBIT/phases/install/quayside_assembly_tow/common.py index 49533caa..ada96e21 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/common.py +++ b/ORBIT/phases/install/quayside_assembly_tow/common.py @@ -7,7 +7,7 @@ __email__ = "jake.nunemaker@nrel.gov" -from marmot import Agent, le, process, false +from marmot import Agent, le, false, process from marmot._exceptions import AgentNotRegistered @@ -328,12 +328,22 @@ def __init__(self, vessel_specs, ahts_vessel_specs=None, num=1): self._specs = vessel_specs self.day_rate_towing = self._specs["vessel_specs"]["day_rate"] self.day_rate_anchor = 0.0 + self.max_waveheight = self._specs["transport_specs"]["max_waveheight"] + self.max_windspeed = self._specs["transport_specs"]["max_windspeed"] self.transit_speed = self._specs["transport_specs"]["transit_speed"] if ahts_vessel_specs is not None: self.day_rate_anchor = ahts_vessel_specs["vessel_specs"][ "day_rate" ] + self.max_waveheight = min( + vessel_specs["transport_specs"]["max_waveheight"], + ahts_vessel_specs["transport_specs"]["max_waveheight"], + ) + self.max_windspeed = min( + vessel_specs["transport_specs"]["max_windspeed"], + ahts_vessel_specs["transport_specs"]["max_windspeed"], + ) self.transit_speed = min( vessel_specs["transport_specs"]["transit_speed"], ahts_vessel_specs["transport_specs"]["transit_speed"], diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index 561df3a9..54fbfe39 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -8,7 +8,6 @@ import simpy from marmot import le, process - from ORBIT.core import Vessel, WetStorage from ORBIT.phases.install import InstallPhase @@ -299,10 +298,10 @@ def towing_group_actions( Distance from port to site. towing_vessels : int Number of vessels to use for towing to site. + ahts_vessels : int + Number of anchor handling tug vessels. towing_speed : int | float - Configured towing speed (km/h) - num_substructures : int - Number of substructures to be installed corresponding to number of turbines + Configured towing speed (km/h). """ towing_time = distance / towing_speed @@ -314,7 +313,7 @@ def towing_group_actions( if delay > 0: group.submit_action_log( - "Delay: No Completed Assemblies Available", + "Delay: No Completed Turbine Assemblies", delay, num_vessels=towing_vessels, num_ahts_vessels=ahts_vessels, @@ -325,7 +324,10 @@ def towing_group_actions( 6, num_vessels=towing_vessels, num_ahts_vessels=ahts_vessels, - constraints={"windspeed": le(15), "waveheight": le(2.5)}, + constraints={ + "windspeed": le(group.max_windspeed), + "waveheight": le(group.max_waveheight), + }, ) yield group.group_task( @@ -333,7 +335,10 @@ def towing_group_actions( towing_time, num_vessels=towing_vessels, num_ahts_vessels=ahts_vessels, - constraints={"windspeed": le(15), "waveheight": le(2.5)}, + constraints={ + "windspeed": le(group.max_windspeed), + "waveheight": le(group.max_waveheight), + }, ) # At Site @@ -376,4 +381,9 @@ def towing_group_actions( transit_time, num_vessels=towing_vessels, num_ahts_vessels=ahts_vessels, + suspendable=True, + constraints={ + "windspeed": le(group.max_windspeed), + "waveheight": le(group.max_waveheight), + }, ) diff --git a/library/vessels/example_ahts_vessel.yaml b/library/vessels/example_ahts_vessel.yaml index 28023f85..338152ac 100644 --- a/library/vessels/example_ahts_vessel.yaml +++ b/library/vessels/example_ahts_vessel.yaml @@ -1,6 +1,6 @@ transport_specs: - max_waveheight: 2.5 # m - max_windspeed: 20 # m/s + max_waveheight: 3.0 # m + max_windspeed: 15 # m/s transit_speed: 6 # km/h vessel_specs: - day_rate: 100000 # USD/day + day_rate: 100000 # USD/day diff --git a/library/vessels/example_towing_vessel.yaml b/library/vessels/example_towing_vessel.yaml index 5aa4bf58..c4de57e5 100644 --- a/library/vessels/example_towing_vessel.yaml +++ b/library/vessels/example_towing_vessel.yaml @@ -1,6 +1,6 @@ transport_specs: - max_waveheight: 2.5 # m - max_windspeed: 20 # m/s + max_waveheight: 3.0 # m + max_windspeed: 15 # m/s transit_speed: 6 # km/h vessel_specs: day_rate: 30000 # USD/day From 25fafaf2a9a2eaf8d1b7fe2aa8f194eecc792141 Mon Sep 17 00:00:00 2001 From: Shields Date: Fri, 14 Apr 2023 14:05:17 -0600 Subject: [PATCH 28/71] Added dynamic cables (20% cost adder), cable lay/bury times, and cable lay vessel day rate --- ORBIT/core/defaults/process_times.yaml | 6 +++--- library/cables/HVDC_2000mm_320kV_dynamic.yaml | 11 +++++++++++ library/cables/XLPE_1000m_220kV_dynamic.yaml | 10 ++++++++++ library/cables/XLPE_185mm_66kV_dynamic.yaml | 9 +++++++++ library/cables/XLPE_500mm_132kV.yaml | 2 +- library/cables/XLPE_500mm_132kV_dynamic.yaml | 10 ++++++++++ library/cables/XLPE_630mm_66kV_dynamic.yaml | 11 +++++++++++ library/vessels/example_cable_lay_vessel.yaml | 2 +- 8 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 library/cables/HVDC_2000mm_320kV_dynamic.yaml create mode 100644 library/cables/XLPE_1000m_220kV_dynamic.yaml create mode 100644 library/cables/XLPE_185mm_66kV_dynamic.yaml create mode 100644 library/cables/XLPE_500mm_132kV_dynamic.yaml create mode 100644 library/cables/XLPE_630mm_66kV_dynamic.yaml diff --git a/ORBIT/core/defaults/process_times.yaml b/ORBIT/core/defaults/process_times.yaml index c1b94b26..f8a3a1d3 100644 --- a/ORBIT/core/defaults/process_times.yaml +++ b/ORBIT/core/defaults/process_times.yaml @@ -13,9 +13,9 @@ "cable_lower_time": 1 # hr "cable_pull_in_time": 5.5 # hr "cable_termination_time": 5.5 # hr -"cable_lay_speed": 1 # km/hr -"cable_lay_bury_speed": 0.3 # km/hr -"cable_bury_speed": 0.5 # km/hr +"cable_lay_speed": 0.4 # km/hr (10 km/day) +"cable_lay_bury_speed": 0.0625 # km/hr (1-2 km/day) +"cable_bury_speed": 0.4 # km/hr "cable_splice_time": 48 # hr "cable_raise_time": 0.5 # hr diff --git a/library/cables/HVDC_2000mm_320kV_dynamic.yaml b/library/cables/HVDC_2000mm_320kV_dynamic.yaml new file mode 100644 index 00000000..3a03d881 --- /dev/null +++ b/library/cables/HVDC_2000mm_320kV_dynamic.yaml @@ -0,0 +1,11 @@ +# Copper from Prysmian +ac_resistance: 0 # ohm/km +capacitance: 295000 # nF/km +conductor_size: 2000 # mm^2 +cost_per_km: 600000 # $ (20% adder over HVDC_2000mm_320kV) +current_capacity: 1900 # A # ESTIMATE +inductance: 0.127 # mH/km +linear_density: 53 # t/km +cable_type: HVDC-monopole # HVDC vs HVAC +name: HVDC_2000mm_320kV +rated_voltage: 320 diff --git a/library/cables/XLPE_1000m_220kV_dynamic.yaml b/library/cables/XLPE_1000m_220kV_dynamic.yaml new file mode 100644 index 00000000..d179ae21 --- /dev/null +++ b/library/cables/XLPE_1000m_220kV_dynamic.yaml @@ -0,0 +1,10 @@ +ac_resistance: 0.16 # ohm/km +capacitance: 190 # nF/km +conductor_size: 1000 # mm^2 +cost_per_km: 1020000 # $ (20% adder over XLPE_1000m_220kV) +current_capacity: 825 # A +inductance: 0.38 # mH/km +linear_density: 115 # t/km +cable_type: HVAC # HVDC vs HVAC +name: XLPE_1000m_220kV +rated_voltage: 220 diff --git a/library/cables/XLPE_185mm_66kV_dynamic.yaml b/library/cables/XLPE_185mm_66kV_dynamic.yaml new file mode 100644 index 00000000..5a9e706e --- /dev/null +++ b/library/cables/XLPE_185mm_66kV_dynamic.yaml @@ -0,0 +1,9 @@ +ac_resistance: 0.128 # +capacitance: 163 # +conductor_size: 185 # +cost_per_km: 240000 # $ (20% adder over XLPE_185mm_66kV) +current_capacity: 445 # At 2m burial depth +inductance: 0.443 # +linear_density: 26.1 # +name: XLPE_185mm_66kV +rated_voltage: 66 diff --git a/library/cables/XLPE_500mm_132kV.yaml b/library/cables/XLPE_500mm_132kV.yaml index e58a7a02..af7061c7 100644 --- a/library/cables/XLPE_500mm_132kV.yaml +++ b/library/cables/XLPE_500mm_132kV.yaml @@ -1,7 +1,7 @@ ac_resistance: 0.06 capacitance: 200 conductor_size: 500 -cost_per_km: 200000 +cost_per_km: 500000 current_capacity: 625 inductance: 0.4 linear_density: 50 diff --git a/library/cables/XLPE_500mm_132kV_dynamic.yaml b/library/cables/XLPE_500mm_132kV_dynamic.yaml new file mode 100644 index 00000000..b0b1ec59 --- /dev/null +++ b/library/cables/XLPE_500mm_132kV_dynamic.yaml @@ -0,0 +1,10 @@ +ac_resistance: 0.06 +capacitance: 200 +conductor_size: 500 +cost_per_km: 600000 # $ (20% adder over XLPE_500mm_132kV) +current_capacity: 625 +inductance: 0.4 +linear_density: 50 +cable_type: HVAC +name: XLPE_500mm_132kV +rated_voltage: 132 diff --git a/library/cables/XLPE_630mm_66kV_dynamic.yaml b/library/cables/XLPE_630mm_66kV_dynamic.yaml new file mode 100644 index 00000000..69d857c3 --- /dev/null +++ b/library/cables/XLPE_630mm_66kV_dynamic.yaml @@ -0,0 +1,11 @@ +ac_resistance: 0.04 +capacitance: 300 +conductor_size: 630 +cost_per_km: 480000 # $ (20% adder over XLPE_630mm_66kV) +current_capacity: 775 +inductance: 0.35 +linear_density: 42.5 +name: XLPE_630mm_66kV +rated_voltage: 66 +switchgear_cost: 1e6 +cable_type: HVAC # HVDC vs HVAC diff --git a/library/vessels/example_cable_lay_vessel.yaml b/library/vessels/example_cable_lay_vessel.yaml index 728ac348..7813dc7b 100644 --- a/library/vessels/example_cable_lay_vessel.yaml +++ b/library/vessels/example_cable_lay_vessel.yaml @@ -3,7 +3,7 @@ transport_specs: max_windspeed: 25 # m/s transit_speed: 11.5 # km/hr vessel_specs: - day_rate: 120000 # USD/day, cost of operating vessel with crew + day_rate: 225000 # USD/day, cost of operating vessel with crew min_draft: 4.8 # m overall_length: 99.0 # m cable_storage: From 2cd2098d4a703e421fb879fc3fc80f2d959deb33 Mon Sep 17 00:00:00 2001 From: Shields Date: Fri, 14 Apr 2023 17:07:05 -0600 Subject: [PATCH 29/71] Update CLV carousel specs to match Leonardo da --- library/vessels/example_cable_lay_vessel.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/vessels/example_cable_lay_vessel.yaml b/library/vessels/example_cable_lay_vessel.yaml index 7813dc7b..8840ba6c 100644 --- a/library/vessels/example_cable_lay_vessel.yaml +++ b/library/vessels/example_cable_lay_vessel.yaml @@ -4,7 +4,7 @@ transport_specs: transit_speed: 11.5 # km/hr vessel_specs: day_rate: 225000 # USD/day, cost of operating vessel with crew - min_draft: 4.8 # m - overall_length: 99.0 # m + min_draft: 8.5 # m + overall_length: 171.0 # m cable_storage: - max_mass: 4000 # t + max_mass: 13000 # t From 347fcf2cec5f5046418244f0e53e5de43079c1c0 Mon Sep 17 00:00:00 2001 From: asharma Date: Sun, 16 Apr 2023 20:30:09 -0600 Subject: [PATCH 30/71] change delay message --- ORBIT/phases/install/oss_install/floating.py | 4 +++- ORBIT/phases/install/quayside_assembly_tow/common.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index 3d4e551b..6e7f9a4b 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -308,7 +308,9 @@ def assemble_substructure(self): delay = self.env.now - start if delay > 0: - self.submit_action_log("Delay: No Wet Storage Available", delay) + self.submit_action_log( + "Delay: No Substructure Storage Available", delay + ) @process def start(self): diff --git a/ORBIT/phases/install/quayside_assembly_tow/common.py b/ORBIT/phases/install/quayside_assembly_tow/common.py index ada96e21..4083cc36 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/common.py +++ b/ORBIT/phases/install/quayside_assembly_tow/common.py @@ -94,7 +94,9 @@ def assemble_substructure(self): delay = self.env.now - start if delay > 0: - self.submit_action_log("Delay: No Wet Storage Available", delay) + self.submit_action_log( + "Delay: No Substructure Storage Available", delay + ) @process def start(self): From b3150a575cc69a873ea14c88289e9e70f7322c43 Mon Sep 17 00:00:00 2001 From: asharma Date: Tue, 18 Apr 2023 16:43:16 -0600 Subject: [PATCH 31/71] change vessel speeds --- library/vessels/example_ahts_vessel.yaml | 2 +- library/vessels/example_towing_vessel.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/vessels/example_ahts_vessel.yaml b/library/vessels/example_ahts_vessel.yaml index 338152ac..66c2eeda 100644 --- a/library/vessels/example_ahts_vessel.yaml +++ b/library/vessels/example_ahts_vessel.yaml @@ -1,6 +1,6 @@ transport_specs: max_waveheight: 3.0 # m max_windspeed: 15 # m/s - transit_speed: 6 # km/h + transit_speed: 14 # km/h vessel_specs: day_rate: 100000 # USD/day diff --git a/library/vessels/example_towing_vessel.yaml b/library/vessels/example_towing_vessel.yaml index c4de57e5..695a8f94 100644 --- a/library/vessels/example_towing_vessel.yaml +++ b/library/vessels/example_towing_vessel.yaml @@ -1,6 +1,6 @@ transport_specs: max_waveheight: 3.0 # m max_windspeed: 15 # m/s - transit_speed: 6 # km/h + transit_speed: 14 # km/h vessel_specs: day_rate: 30000 # USD/day From 65bfb0d34f787dcd9e4eb4420f3fde911ae22270 Mon Sep 17 00:00:00 2001 From: asharma Date: Thu, 20 Apr 2023 11:49:58 -0600 Subject: [PATCH 32/71] remove duplicate transit back to port --- ORBIT/phases/install/cable_install/array.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ORBIT/phases/install/cable_install/array.py b/ORBIT/phases/install/cable_install/array.py index d4d8a181..5fbb5923 100644 --- a/ORBIT/phases/install/cable_install/array.py +++ b/ORBIT/phases/install/cable_install/array.py @@ -10,7 +10,6 @@ import numpy as np from marmot import process - from ORBIT.core import Vessel from ORBIT.core.logic import position_onsite from ORBIT.phases.install import InstallPhase @@ -237,7 +236,6 @@ def install_array_cables( trench_vessel.at_site = True elif trench_vessel.at_site: - try: # Dig trench along each cable section distance trench_distance = trench_sections.pop(0) @@ -269,7 +267,6 @@ def install_array_cables( vessel.at_site = True elif vessel.at_site: - try: length, num_sections, *extra = sections.pop(0) if extra: @@ -291,12 +288,10 @@ def install_array_cables( break for _ in range(num_sections): - try: section = vessel.cable_storage.get_cable(length) except InsufficientCable: - yield vessel.transit(distance, **kwargs) yield load_cable_on_vessel(vessel, cable, **kwargs) yield vessel.transit(distance, **kwargs) @@ -330,11 +325,6 @@ def install_array_cables( vessel, installed, total_cable_length, breakpoints ) - # Transit back to port - vessel.at_site = False - yield vessel.transit(distance, **kwargs) - vessel.at_port = True - ## Burial Process if burial_vessel is None: vessel.submit_debug_log( From d118855a1a28662ed098a91e376a4cd03a1a990b Mon Sep 17 00:00:00 2001 From: Jake Nunemaker Date: Fri, 21 Apr 2023 09:44:38 -0600 Subject: [PATCH 33/71] Added project progress debug logs to MooredSubInstallation and FloatingOSSInstallation so monthly_opex works. --- ORBIT/phases/install/oss_install/floating.py | 6 ++++++ ORBIT/phases/install/quayside_assembly_tow/moored.py | 3 +++ 2 files changed, 9 insertions(+) diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index 6e7f9a4b..471118db 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -229,6 +229,12 @@ def install_floating_substations( yield vessel.transit(distance) + # TODO: Revise this to work with multiple substations + vessel.submit_debug_log( + message="Substation installation complete!", + progress="Offshore Substation", + ) + class SubstationAssemblyLine(Agent): """Substation Assembly Line Class.""" diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index 54fbfe39..c087e066 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -376,6 +376,9 @@ def towing_group_actions( constraints={"windspeed": le(15), "waveheight": le(2.5)}, ) + group.submit_debug_log(progress="Substructure") + group.submit_debug_log(progress="Turbine") + yield group.group_task( "Transit", transit_time, From c540a766172f8e79db29c70b66a99af2956a2778 Mon Sep 17 00:00:00 2001 From: asharma Date: Sat, 22 Apr 2023 00:08:49 -0600 Subject: [PATCH 34/71] allow separate cable lay burial rates --- ORBIT/core/defaults/process_times.yaml | 1 - ORBIT/phases/install/cable_install/common.py | 4 +--- library/vessels/example_cable_lay_vessel.yaml | 1 + .../vessels/test_cable_lay_vessel.yaml | 1 + .../cable_install/test_array_install.py | 19 ++++--------------- .../cable_install/test_export_install.py | 19 ++++--------------- 6 files changed, 11 insertions(+), 34 deletions(-) diff --git a/ORBIT/core/defaults/process_times.yaml b/ORBIT/core/defaults/process_times.yaml index f8a3a1d3..1ec8d812 100644 --- a/ORBIT/core/defaults/process_times.yaml +++ b/ORBIT/core/defaults/process_times.yaml @@ -14,7 +14,6 @@ "cable_pull_in_time": 5.5 # hr "cable_termination_time": 5.5 # hr "cable_lay_speed": 0.4 # km/hr (10 km/day) -"cable_lay_bury_speed": 0.0625 # km/hr (1-2 km/day) "cable_bury_speed": 0.4 # km/hr "cable_splice_time": 48 # hr "cable_raise_time": 0.5 # hr diff --git a/ORBIT/phases/install/cable_install/common.py b/ORBIT/phases/install/cable_install/common.py index f2481138..483e9718 100644 --- a/ORBIT/phases/install/cable_install/common.py +++ b/ORBIT/phases/install/cable_install/common.py @@ -7,7 +7,6 @@ from marmot import process - from ORBIT.core.logic import position_onsite from ORBIT.core.defaults import process_times as pt @@ -176,8 +175,7 @@ def lay_bury_cable(vessel, distance, **kwargs): kwargs = {**kwargs, **getattr(vessel, "_transport_specs", {})} - key = "cable_lay_bury_speed" - lay_bury_speed = kwargs.get(key, pt[key]) + lay_bury_speed = vessel._vessel_specs.get("cable_lay_bury_speed", 0.0625) lay_bury_time = distance / lay_bury_speed yield vessel.task_wrapper( diff --git a/library/vessels/example_cable_lay_vessel.yaml b/library/vessels/example_cable_lay_vessel.yaml index 8840ba6c..3fd571c8 100644 --- a/library/vessels/example_cable_lay_vessel.yaml +++ b/library/vessels/example_cable_lay_vessel.yaml @@ -6,5 +6,6 @@ vessel_specs: day_rate: 225000 # USD/day, cost of operating vessel with crew min_draft: 8.5 # m overall_length: 171.0 # m + cable_lay_bury_speed: 0.0625 # km/hr cable_storage: max_mass: 13000 # t diff --git a/tests/data/library/vessels/test_cable_lay_vessel.yaml b/tests/data/library/vessels/test_cable_lay_vessel.yaml index 73bfb1a8..ee0f1b34 100644 --- a/tests/data/library/vessels/test_cable_lay_vessel.yaml +++ b/tests/data/library/vessels/test_cable_lay_vessel.yaml @@ -6,5 +6,6 @@ vessel_specs: day_rate: 50000 # USD/day, cost of operating vessel with crew min_draft: 4.8 # m overall_length: 99.0 # m + cable_lay_bury_speed: 0.0625 # km/hr cable_storage: max_mass: 6000 diff --git a/tests/phases/install/cable_install/test_array_install.py b/tests/phases/install/cable_install/test_array_install.py index 5a01c14b..dc94153e 100644 --- a/tests/phases/install/cable_install/test_array_install.py +++ b/tests/phases/install/cable_install/test_array_install.py @@ -12,7 +12,6 @@ import pandas as pd import pytest - from ORBIT import ProjectManager from tests.data import test_weather from ORBIT.core.library import extract_library_specs @@ -28,7 +27,6 @@ "config", (base_config, simul_config), ids=["separate", "simultaneous"] ) def test_simulation_setup(config): - sim = ArrayCableInstallation(config) assert sim.env @@ -37,7 +35,6 @@ def test_simulation_setup(config): "config", (base_config, simul_config), ids=["separate", "simultaneous"] ) def test_vessel_initialization(config): - sim = ArrayCableInstallation(config) assert sim.install_vessel assert sim.install_vessel.cable_storage @@ -53,7 +50,6 @@ def test_vessel_initialization(config): "weather", (None, test_weather), ids=["no_weather", "test_weather"] ) def test_for_complete_logging(config, weather): - sim = ArrayCableInstallation(config, weather=weather) sim.run() @@ -72,24 +68,21 @@ def test_for_complete_logging(config, weather): def test_simultaneous_speed_kwargs(): - sim = ArrayCableInstallation(simul_config) sim.run() baseline = sim.total_phase_time - key = "cable_lay_bury_speed" - val = pt[key] * 0.1 - - kwargs = {key: val} + sim.install_vessel._vessel_specs["cable_lay_bury_speed"] = ( + sim.install_vessel._vessel_specs["cable_lay_bury_speed"] * 0.1 + ) - sim = ArrayCableInstallation(simul_config, **kwargs) + sim = ArrayCableInstallation(simul_config) sim.run() assert sim.total_phase_time > baseline def test_separate_speed_kwargs(): - sim = ArrayCableInstallation(base_config) sim.run() df = pd.DataFrame(sim.env.actions) @@ -114,7 +107,6 @@ def test_separate_speed_kwargs(): def test_kwargs_for_array_install(): - sim = ArrayCableInstallation(base_config) sim.run() baseline = sim.total_phase_time @@ -131,7 +123,6 @@ def test_kwargs_for_array_install(): failed = [] for kw in keywords: - default = pt[kw] if "speed" in kw: @@ -163,7 +154,6 @@ def test_kwargs_for_array_install(): def test_kwargs_for_array_install_in_ProjectManager(): - base = deepcopy(base_config) base["install_phases"] = ["ArrayCableInstallation"] @@ -183,7 +173,6 @@ def test_kwargs_for_array_install_in_ProjectManager(): failed = [] for kw in keywords: - default = pt[kw] if "speed" in kw: diff --git a/tests/phases/install/cable_install/test_export_install.py b/tests/phases/install/cable_install/test_export_install.py index 12f0c1dc..3a03a9df 100644 --- a/tests/phases/install/cable_install/test_export_install.py +++ b/tests/phases/install/cable_install/test_export_install.py @@ -12,7 +12,6 @@ import pandas as pd import pytest - from ORBIT import ProjectManager from tests.data import test_weather from ORBIT.core.library import extract_library_specs @@ -28,7 +27,6 @@ "config", (base_config, simul_config), ids=["separate", "simultaneous"] ) def test_simulation_setup(config): - sim = ExportCableInstallation(config) assert sim.env assert sim.cable @@ -42,7 +40,6 @@ def test_simulation_setup(config): "config", (base_config, simul_config), ids=["separate", "simultaneous"] ) def test_vessel_initialization(config): - sim = ExportCableInstallation(config) assert sim.install_vessel assert sim.install_vessel.cable_storage @@ -58,7 +55,6 @@ def test_vessel_initialization(config): "weather", (None, test_weather), ids=["no_weather", "test_weather"] ) def test_for_complete_logging(config, weather): - sim = ExportCableInstallation(config, weather=weather) sim.run() @@ -77,24 +73,21 @@ def test_for_complete_logging(config, weather): def test_simultaneous_speed_kwargs(): - sim = ExportCableInstallation(simul_config) sim.run() baseline = sim.total_phase_time - key = "cable_lay_bury_speed" - val = pt[key] * 0.1 - - kwargs = {key: val} + sim.install_vessel._vessel_specs["cable_lay_bury_speed"] = ( + sim.install_vessel._vessel_specs["cable_lay_bury_speed"] * 0.1 + ) - sim = ExportCableInstallation(simul_config, **kwargs) + sim = ExportCableInstallation(simul_config) sim.run() assert sim.total_phase_time > baseline def test_separate_speed_kwargs(): - sim = ExportCableInstallation(base_config) sim.run() df = pd.DataFrame(sim.env.actions) @@ -119,7 +112,6 @@ def test_separate_speed_kwargs(): def test_kwargs_for_export_install(): - new_export_system = { "cable": {"linear_density": 50.0, "sections": [1000], "number": 1}, "system_cost": 200e6, @@ -150,7 +142,6 @@ def test_kwargs_for_export_install(): failed = [] for kw in keywords: - default = pt[kw] if "speed" in kw: @@ -182,7 +173,6 @@ def test_kwargs_for_export_install(): def test_kwargs_for_export_install_in_ProjectManager(): - new_export_system = { "cable": {"linear_density": 50.0, "sections": [1000], "number": 1}, "system_cost": 200e6, @@ -213,7 +203,6 @@ def test_kwargs_for_export_install_in_ProjectManager(): failed = [] for kw in keywords: - default = pt[kw] if "speed" in kw: From 50144ca43eaf75e44256b22e7af64e9273607787 Mon Sep 17 00:00:00 2001 From: asharma Date: Sun, 30 Apr 2023 19:07:23 -0600 Subject: [PATCH 35/71] account for multiple assembly lines in installation costs --- ORBIT/phases/install/install_phase.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ORBIT/phases/install/install_phase.py b/ORBIT/phases/install/install_phase.py index 97b93c3b..0fbad57a 100644 --- a/ORBIT/phases/install/install_phase.py +++ b/ORBIT/phases/install/install_phase.py @@ -12,7 +12,6 @@ import numpy as np import simpy import pandas as pd - from ORBIT.core import Port, Vessel, Environment from ORBIT.phases import BasePhase from ORBIT.core.defaults import common_costs @@ -121,9 +120,14 @@ def port_costs(self): return 0 else: - key = "port_cost_per_month" port_config = self.config.get("port", {}) + assert port_config.get("sub_assembly_lines", 1) == port_config.get( + "turbine_assembly_cranes", 1 + ), "Number of substructure assembly lines is not equal to number of turbine assembly cranes" + + key = "port_cost_per_month" rate = port_config.get("monthly_rate", common_costs[key]) + rate += rate * (port_config.get("sub_assembly_lines", 1) - 1) * 0.5 months = self.total_phase_time / (8760 / 12) return months * rate From 5a38ca4fb21c46329a2695efd28356a6b55a5293 Mon Sep 17 00:00:00 2001 From: asharma Date: Fri, 26 May 2023 13:40:05 -0600 Subject: [PATCH 36/71] update vessel specs --- library/vessels/example_towing_vessel.yaml | 2 +- tests/data/library/vessels/test_ahts_vessel.yaml | 8 ++++---- tests/data/library/vessels/test_towing_vessel.yaml | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/library/vessels/example_towing_vessel.yaml b/library/vessels/example_towing_vessel.yaml index 695a8f94..0dcdc3ef 100644 --- a/library/vessels/example_towing_vessel.yaml +++ b/library/vessels/example_towing_vessel.yaml @@ -3,4 +3,4 @@ transport_specs: max_windspeed: 15 # m/s transit_speed: 14 # km/h vessel_specs: - day_rate: 30000 # USD/day + day_rate: 35000 # USD/day diff --git a/tests/data/library/vessels/test_ahts_vessel.yaml b/tests/data/library/vessels/test_ahts_vessel.yaml index 28023f85..66c2eeda 100644 --- a/tests/data/library/vessels/test_ahts_vessel.yaml +++ b/tests/data/library/vessels/test_ahts_vessel.yaml @@ -1,6 +1,6 @@ transport_specs: - max_waveheight: 2.5 # m - max_windspeed: 20 # m/s - transit_speed: 6 # km/h + max_waveheight: 3.0 # m + max_windspeed: 15 # m/s + transit_speed: 14 # km/h vessel_specs: - day_rate: 100000 # USD/day + day_rate: 100000 # USD/day diff --git a/tests/data/library/vessels/test_towing_vessel.yaml b/tests/data/library/vessels/test_towing_vessel.yaml index 5aa4bf58..0dcdc3ef 100644 --- a/tests/data/library/vessels/test_towing_vessel.yaml +++ b/tests/data/library/vessels/test_towing_vessel.yaml @@ -1,6 +1,6 @@ transport_specs: - max_waveheight: 2.5 # m - max_windspeed: 20 # m/s - transit_speed: 6 # km/h + max_waveheight: 3.0 # m + max_windspeed: 15 # m/s + transit_speed: 14 # km/h vessel_specs: - day_rate: 30000 # USD/day + day_rate: 35000 # USD/day From 3baed36052d7503de6ea6f2db0b40945d637ea35 Mon Sep 17 00:00:00 2001 From: Jake Nunemaker Date: Fri, 20 Oct 2023 09:48:54 -0600 Subject: [PATCH 37/71] Revert solo monopile install to original get items from port method --- ORBIT/phases/install/monopile_install/standard.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ORBIT/phases/install/monopile_install/standard.py b/ORBIT/phases/install/monopile_install/standard.py index da16ad13..47ae2923 100644 --- a/ORBIT/phases/install/monopile_install/standard.py +++ b/ORBIT/phases/install/monopile_install/standard.py @@ -14,7 +14,7 @@ from ORBIT.core.logic import ( prep_for_site_operations, shuttle_items_to_queue_wait, - get_list_of_items_from_port_wait, + get_list_of_items_from_port, ) from ORBIT.phases.install import InstallPhase from ORBIT.core.exceptions import ItemNotFound @@ -326,7 +326,7 @@ def solo_install_monopiles(vessel, port, distance, monopiles, **kwargs): if vessel.at_port: try: # Get substructure + transition piece from port - yield get_list_of_items_from_port_wait( + yield get_list_of_items_from_port( vessel, port, component_list, **kwargs ) From 9cd12445daff80948cac9fae6dcab2f2438c8e77 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Tue, 30 Apr 2024 15:45:47 -0600 Subject: [PATCH 38/71] Added semitaut arrays features to mooringsystem. Created rope/chain densities as optional user inputs. --- ORBIT/phases/design/__init__.py | 5 +- ORBIT/phases/design/mooring_system_design.py | 92 +++++++++++++++++--- 2 files changed, 80 insertions(+), 17 deletions(-) diff --git a/ORBIT/phases/design/__init__.py b/ORBIT/phases/design/__init__.py index 3998529e..7871e0ca 100644 --- a/ORBIT/phases/design/__init__.py +++ b/ORBIT/phases/design/__init__.py @@ -7,15 +7,14 @@ from .design_phase import DesignPhase # isort:skip -from .oss_design_floating import OffshoreFloatingSubstationDesign from .oss_design import OffshoreSubstationDesign from .spar_design import SparDesign from .monopile_design import MonopileDesign from .electrical_export import ElectricalDesign from .array_system_design import ArraySystemDesign, CustomArraySystemDesign +from .oss_design_floating import OffshoreFloatingSubstationDesign from .export_system_design import ExportSystemDesign from .mooring_system_design import MooringSystemDesign -from .SemiTaut_mooring_system_design import SemiTautMooringSystemDesign from .scour_protection_design import ScourProtectionDesign from .semi_submersible_design import SemiSubmersibleDesign -from .electrical_export import ElectricalDesign +from .SemiTaut_mooring_system_design import SemiTautMooringSystemDesign diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index 5b0eec8b..707943bf 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -1,13 +1,15 @@ """`MooringSystemDesign` and related functionality.""" -__author__ = "Jake Nunemaker" +__author__ = "Jake Nunemaker, modified by Becca Fuchs" __copyright__ = "Copyright 2020, National Renewable Energy Laboratory" __maintainer__ = "Jake Nunemaker" -__email__ = "jake.nunemaker@nrel.gov" - +__email__ = "jake.nunemaker@nrel.gov, rebecca.fuchs@nrel.gov" from math import sqrt +import numpy as np +from scipy.interpolate import interp1d + from ORBIT.phases.design import DesignPhase @@ -21,8 +23,11 @@ class MooringSystemDesign(DesignPhase): "mooring_system_design": { "num_lines": "int | float (optional, default: 4)", "anchor_type": "str (optional, default: 'Suction Pile')", + "mooring_type": "str (optional, default: 'Catenary')", "mooring_line_cost_rate": "int | float (optional)", "drag_embedment_fixed_length": "int | float (optional, default: .5km)", + "chain_density": "int | float (optional, default: 19900 kg/m**3)", + "rope_density": "int | float (optional, default: 797.8 kg/m**3)", }, } @@ -56,6 +61,34 @@ def __init__(self, config, **kwargs): self._design = self.config.get("mooring_system_design", {}) self.num_lines = self._design.get("num_lines", 4) self.anchor_type = self._design.get("anchor_type", "Suction Pile") + self.mooring_type = self._design.get("mooring_type", "Catenary") + + # Input hybrid mooring system design from Cooperman et al. (2022), + # https://www.nrel.gov/docs/fy22osti/82341.pdf + _semitaut = { + "depths": np.array([500, 750, 1000, 1250, 1500], dtype=float), + "rope_lengths": np.array( + [478.41, 830.34, 1229.98, 1183.93, 1079.62], dtype=float + ), + "rope_diameters": np.array([0.2, 0.2, 0.2, 0.2, 0.2], dtype=float), + "chain_lengths": np.array( + [917.11, 800.36, 609.07, 896.42, 1280.57], dtype=float + ), + "chain_diamters": np.array([0.13, 0.17, 0.22, 0.22, 0.22]), + } + + self.finterp_rope_l = interp1d( + _semitaut["depths"], _semitaut["rope_lengths"] + ) + self.finterp_rope_d = interp1d( + _semitaut["depths"], _semitaut["rope_diameters"] + ) + self.finterp_chain_l = interp1d( + _semitaut["depths"], _semitaut["chain_lengths"] + ) + self.finterp_chain_d = interp1d( + _semitaut["depths"], _semitaut["chain_diameters"] + ) self._outputs = {} @@ -77,7 +110,7 @@ def determine_mooring_line(self): """ tr = self.config["turbine"]["turbine_rating"] - fit = -0.0004 * (tr ** 2) + 0.0132 * tr + 0.0536 + fit = -0.0004 * (tr**2) + 0.0132 * tr + 0.0536 if fit <= 0.09: self.line_diam = 0.09 @@ -100,26 +133,57 @@ def calculate_breaking_load(self): """ self.breaking_load = ( - 419449 * (self.line_diam ** 2) + 93415 * self.line_diam - 3577.9 + 419449 * (self.line_diam**2) + 93415 * self.line_diam - 3577.9 ) def calculate_line_length_mass(self): """ Returns the mooring line length and mass. """ + depth = self.config["site"]["depth"] - if self.anchor_type == "Drag Embedment": - fixed = self._design.get("drag_embedment_fixed_length", 500) + if self.mooring_type == "Catenary": + if self.anchor_type == "Drag Embedment": + fixed = self._design.get("drag_embedment_fixed_length", 500) - else: - fixed = 0 + else: + fixed = 0 - depth = self.config["site"]["depth"] - self.line_length = ( - 0.0002 * (depth ** 2) + 1.264 * depth + 47.776 + fixed - ) + self.line_length = ( + 0.0002 * (depth**2) + 1.264 * depth + 47.776 + fixed + ) + + self.line_mass = self.line_length * self.line_mass_per_m - self.line_mass = self.line_length * self.line_mass_per_m + else: + if self.anchor_type == "Drag Embedment": + fixed = self.get("drag_embedment_fixed_length", 0) + + else: + fixed = 0 + + # Rope and chain length at project depth + self.chain_length = self.finterp_chain_l(depth) + self.rope_length = self.finterp_rope_l(depth) + # Rope and chain diameter at project depth + self.rope_diameter = self.finterp_rope_d(depth) + self.chain_diameter = self.finterp_chain_d(depth) + + self.line_length = self.rope_length + self.chain_length + + chain_kg_per_m = ( + self._design.get("mooring_chain_density", 19900) + * self.chain_diameter**2 + ) + rope_kg_per_m = ( + self._design.get("mooring_rope_density", 797.8) + * self.rope_diameter**2 + ) + + self.line_mass = ( + self.chain_length * chain_kg_per_m + + self.rope_length * rope_kg_per_m + ) / 1e3 def calculate_anchor_mass_cost(self): """ From 671bd2a6295d79dcb04fd726a91bafdd0d719b0f Mon Sep 17 00:00:00 2001 From: nriccobo Date: Wed, 1 May 2024 09:26:10 -0600 Subject: [PATCH 39/71] Added anchor cost and total line cost of semitaut option. --- ORBIT/phases/design/mooring_system_design.py | 66 +++++++++++++++----- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index 707943bf..3ffe8e0c 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -57,6 +57,7 @@ def __init__(self, config, **kwargs): config = self.initialize_library(config, **kwargs) self.config = self.validate_config(config) self.num_turbines = self.config["plant"]["num_turbines"] + self.depth = self.config["site"]["depth"] self._design = self.config.get("mooring_system_design", {}) self.num_lines = self._design.get("num_lines", 4) @@ -66,15 +67,21 @@ def __init__(self, config, **kwargs): # Input hybrid mooring system design from Cooperman et al. (2022), # https://www.nrel.gov/docs/fy22osti/82341.pdf _semitaut = { - "depths": np.array([500, 750, 1000, 1250, 1500], dtype=float), + "depths": np.array([500.0, 750.0, 1000.0, 1250.0, 1500.0]), "rope_lengths": np.array( - [478.41, 830.34, 1229.98, 1183.93, 1079.62], dtype=float + [478.41, 830.34, 1229.98, 1183.93, 1079.62] ), - "rope_diameters": np.array([0.2, 0.2, 0.2, 0.2, 0.2], dtype=float), + "rope_diameters": np.array([0.2, 0.2, 0.2, 0.2, 0.2]), "chain_lengths": np.array( - [917.11, 800.36, 609.07, 896.42, 1280.57], dtype=float + [917.11, 800.36, 609.07, 896.42, 1280.57] ), "chain_diamters": np.array([0.13, 0.17, 0.22, 0.22, 0.22]), + "anchor_costs": np.array( + [112766.0, 125511.0, 148703.0, 204988.0, 246655.0] + ), + "total_line_costs": np.array( + [826598.0, 1221471.0, 1682208.0, 2380035.0, 3229700.0] + ), } self.finterp_rope_l = interp1d( @@ -89,6 +96,12 @@ def __init__(self, config, **kwargs): self.finterp_chain_d = interp1d( _semitaut["depths"], _semitaut["chain_diameters"] ) + self.finterp_anchor_cost = interp1d( + _semitaut["depths", _semitaut["anchor_costs"]] + ) + self.finterp_total_line_cost = interp1d( + _semitaut["depths"], _semitaut["total_line_costs"] + ) self._outputs = {} @@ -140,7 +153,6 @@ def calculate_line_length_mass(self): """ Returns the mooring line length and mass. """ - depth = self.config["site"]["depth"] if self.mooring_type == "Catenary": if self.anchor_type == "Drag Embedment": @@ -150,7 +162,10 @@ def calculate_line_length_mass(self): fixed = 0 self.line_length = ( - 0.0002 * (depth**2) + 1.264 * depth + 47.776 + fixed + 0.0002 * (self.depth**2) + + 1.264 * self.depth + + 47.776 + + fixed ) self.line_mass = self.line_length * self.line_mass_per_m @@ -163,11 +178,11 @@ def calculate_line_length_mass(self): fixed = 0 # Rope and chain length at project depth - self.chain_length = self.finterp_chain_l(depth) - self.rope_length = self.finterp_rope_l(depth) + self.chain_length = self.finterp_chain_l(self.depth) + self.rope_length = self.finterp_rope_l(self.depth) # Rope and chain diameter at project depth - self.rope_diameter = self.finterp_rope_d(depth) - self.chain_diameter = self.finterp_chain_d(depth) + self.rope_diameter = self.finterp_rope_d(self.depth) + self.chain_diameter = self.finterp_chain_d(self.depth) self.line_length = self.rope_length + self.chain_length @@ -193,19 +208,36 @@ def calculate_anchor_mass_cost(self): review. Should be revised when this module is overhauled in the future. """ - if self.anchor_type == "Drag Embedment": - self.anchor_mass = 20 - self.anchor_cost = self.breaking_load / 9.81 / 20.0 * 2000.0 + if self.mooring_type == "Catenary": + if self.anchor_type == "Drag Embedment": + self.anchor_mass = 20 + self.anchor_cost = self.breaking_load / 9.81 / 20.0 * 2000.0 + else: + self.anchor_mass = 50 + self.anchor_cost = ( + sqrt(self.breaking_load / 9.81 / 1250) * 150000 + ) else: - self.anchor_mass = 50 - self.anchor_cost = sqrt(self.breaking_load / 9.81 / 1250) * 150000 + if self.anchor_type == "Drag Embedment": + self.anchor_mass = 20 + + else: + self.anchor_mass = 50 + + self.anchor_cost = self.finterp_anchor_cost(self.depth) @property def line_cost(self): """Returns cost of one line mooring line.""" - return self.line_length * self.line_cost_rate + if self.mooring_type == "Catenary": + line_cost = self.line_length * self.line_cost_rate + + else: + line_cost = self.finterp_total_line_cost(self.depth) + + return line_cost @property def total_cost(self): @@ -214,7 +246,7 @@ def total_cost(self): return ( self.num_lines * self.num_turbines - * (self.anchor_cost + self.line_length * self.line_cost_rate) + * (self.anchor_cost + self.line_cost) ) @property From da759ea4b2652d20f6520d2cdae41882a2bfd621 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Wed, 1 May 2024 10:20:38 -0600 Subject: [PATCH 40/71] Cleaned up interp objects and repetitive lines. --- ORBIT/phases/design/mooring_system_design.py | 107 ++++++++----------- 1 file changed, 47 insertions(+), 60 deletions(-) diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index 3ffe8e0c..88673735 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -7,7 +7,6 @@ from math import sqrt -import numpy as np from scipy.interpolate import interp1d from ORBIT.phases.design import DesignPhase @@ -64,45 +63,24 @@ def __init__(self, config, **kwargs): self.anchor_type = self._design.get("anchor_type", "Suction Pile") self.mooring_type = self._design.get("mooring_type", "Catenary") - # Input hybrid mooring system design from Cooperman et al. (2022), - # https://www.nrel.gov/docs/fy22osti/82341.pdf - _semitaut = { - "depths": np.array([500.0, 750.0, 1000.0, 1250.0, 1500.0]), - "rope_lengths": np.array( - [478.41, 830.34, 1229.98, 1183.93, 1079.62] - ), - "rope_diameters": np.array([0.2, 0.2, 0.2, 0.2, 0.2]), - "chain_lengths": np.array( - [917.11, 800.36, 609.07, 896.42, 1280.57] - ), - "chain_diamters": np.array([0.13, 0.17, 0.22, 0.22, 0.22]), - "anchor_costs": np.array( - [112766.0, 125511.0, 148703.0, 204988.0, 246655.0] - ), - "total_line_costs": np.array( - [826598.0, 1221471.0, 1682208.0, 2380035.0, 3229700.0] - ), + # Semi-Taut mooring system design parameters based on depth + # Cooperman et al. (2022), https://www.nrel.gov/docs/fy22osti/82341.pdf + self._semitaut = { + "depths": [500.0, 750.0, 1000.0, 1250.0, 1500.0], + "rope_lengths": [478.41, 830.34, 1229.98, 1183.93, 1079.62], + "rope_diameter": 0.2, + "chain_lengths": [917.11, 800.36, 609.07, 896.42, 1280.57], + "chain_diameters": [0.13, 0.17, 0.22, 0.22, 0.22], + "anchor_costs": [112766.0, 125511.0, 148703.0, 204988.0, 246655.0], + "total_line_costs": [ + 826598.0, + 1221471.0, + 1682208.0, + 2380035.0, + 3229700.0, + ], } - self.finterp_rope_l = interp1d( - _semitaut["depths"], _semitaut["rope_lengths"] - ) - self.finterp_rope_d = interp1d( - _semitaut["depths"], _semitaut["rope_diameters"] - ) - self.finterp_chain_l = interp1d( - _semitaut["depths"], _semitaut["chain_lengths"] - ) - self.finterp_chain_d = interp1d( - _semitaut["depths"], _semitaut["chain_diameters"] - ) - self.finterp_anchor_cost = interp1d( - _semitaut["depths", _semitaut["anchor_costs"]] - ) - self.finterp_total_line_cost = interp1d( - _semitaut["depths"], _semitaut["total_line_costs"] - ) - self._outputs = {} def run(self): @@ -162,43 +140,47 @@ def calculate_line_length_mass(self): fixed = 0 self.line_length = ( - 0.0002 * (self.depth**2) - + 1.264 * self.depth - + 47.776 - + fixed + 0.0002 * (self.depth**2) + 1.264 * self.depth + 47.776 + fixed ) self.line_mass = self.line_length * self.line_mass_per_m else: if self.anchor_type == "Drag Embedment": - fixed = self.get("drag_embedment_fixed_length", 0) + fixed = self._design.get("drag_embedment_fixed_length", 0) else: fixed = 0 - # Rope and chain length at project depth - self.chain_length = self.finterp_chain_l(self.depth) - self.rope_length = self.finterp_rope_l(self.depth) - # Rope and chain diameter at project depth - self.rope_diameter = self.finterp_rope_d(self.depth) - self.chain_diameter = self.finterp_chain_d(self.depth) + # Interpolation of rope and chain length at project depth + self.chain_length = interp1d( + self._semitaut["depths"], self._semitaut["chain_lengths"] + )(self.depth) + self.rope_length = interp1d( + self._semitaut["depths"], self._semitaut["rope_lengths"] + )(self.depth) + + # Rope and interpolated chain diameter at project depth + rope_diameter = self._semitaut["rope_diameter"] + chain_diameter = interp1d( + self._semitaut["depths"], self._semitaut["chain_diameters"] + )(self.depth) self.line_length = self.rope_length + self.chain_length - chain_kg_per_m = ( + chain_mass_per_m = ( self._design.get("mooring_chain_density", 19900) - * self.chain_diameter**2 - ) - rope_kg_per_m = ( + * chain_diameter**2 + ) # kg + rope_mass_per_m = ( self._design.get("mooring_rope_density", 797.8) - * self.rope_diameter**2 - ) + * rope_diameter**2 + ) # kg self.line_mass = ( - self.chain_length * chain_kg_per_m - + self.rope_length * rope_kg_per_m - ) / 1e3 + self.chain_length * chain_mass_per_m + + self.rope_length * rope_mass_per_m + ) / 1e3 # tonnes def calculate_anchor_mass_cost(self): """ @@ -225,7 +207,9 @@ def calculate_anchor_mass_cost(self): else: self.anchor_mass = 50 - self.anchor_cost = self.finterp_anchor_cost(self.depth) + self.anchor_cost = interp1d( + self._semitaut["depths"], self._semitaut["anchor_costs"] + )(self.depth) @property def line_cost(self): @@ -235,7 +219,10 @@ def line_cost(self): line_cost = self.line_length * self.line_cost_rate else: - line_cost = self.finterp_total_line_cost(self.depth) + + line_cost = interp1d( + self._semitaut["depths"], self._semitaut["total_line_costs"] + )(self.depth) return line_cost From 7413a00a1b7ef4f6b44e1c34407c7f2d9b85cacd Mon Sep 17 00:00:00 2001 From: nriccobo Date: Wed, 1 May 2024 14:58:45 -0600 Subject: [PATCH 41/71] renamed semitaut dict to semitaut_params for clarity --- ORBIT/phases/design/mooring_system_design.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index 88673735..43fa6d91 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -65,7 +65,7 @@ def __init__(self, config, **kwargs): # Semi-Taut mooring system design parameters based on depth # Cooperman et al. (2022), https://www.nrel.gov/docs/fy22osti/82341.pdf - self._semitaut = { + self._semitaut_params = { "depths": [500.0, 750.0, 1000.0, 1250.0, 1500.0], "rope_lengths": [478.41, 830.34, 1229.98, 1183.93, 1079.62], "rope_diameter": 0.2, @@ -154,16 +154,19 @@ def calculate_line_length_mass(self): # Interpolation of rope and chain length at project depth self.chain_length = interp1d( - self._semitaut["depths"], self._semitaut["chain_lengths"] + self._semitaut_params["depths"], + self._semitaut_params["chain_lengths"], )(self.depth) self.rope_length = interp1d( - self._semitaut["depths"], self._semitaut["rope_lengths"] + self._semitaut_params["depths"], + self._semitaut_params["rope_lengths"], )(self.depth) # Rope and interpolated chain diameter at project depth - rope_diameter = self._semitaut["rope_diameter"] + rope_diameter = self._semitaut_params["rope_diameter"] chain_diameter = interp1d( - self._semitaut["depths"], self._semitaut["chain_diameters"] + self._semitaut_params["depths"], + self._semitaut_params["chain_diameters"], )(self.depth) self.line_length = self.rope_length + self.chain_length @@ -208,7 +211,8 @@ def calculate_anchor_mass_cost(self): self.anchor_mass = 50 self.anchor_cost = interp1d( - self._semitaut["depths"], self._semitaut["anchor_costs"] + self._semitaut_params["depths"], + self._semitaut_params["anchor_costs"], )(self.depth) @property @@ -221,7 +225,8 @@ def line_cost(self): else: line_cost = interp1d( - self._semitaut["depths"], self._semitaut["total_line_costs"] + self._semitaut_params["depths"], + self._semitaut_params["total_line_costs"], )(self.depth) return line_cost From 0f56d8e28b8d49dc1bb42cd951b387856227d991 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Wed, 1 May 2024 18:11:55 -0600 Subject: [PATCH 42/71] Cleaned up pre-commit warnings/errors like unused kwargs and line lengths. --- .../install/quayside_assembly_tow/moored.py | 150 ++++++++++++++++-- 1 file changed, 141 insertions(+), 9 deletions(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index c087e066..cc3834bc 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -6,9 +6,12 @@ __email__ = "jake.nunemaker@nrel.gov" +from warnings import warn + import simpy from marmot import le, process -from ORBIT.core import Vessel, WetStorage + +from ORBIT.core import WetStorage from ORBIT.phases.install import InstallPhase from .common import TowingGroup, TurbineAssemblyLine, SubstructureAssemblyLine @@ -25,10 +28,12 @@ class MooredSubInstallation(InstallPhase): #: expected_config = { + "support_vessel": "str", "ahts_vessel": "str", "towing_vessel": "str", "towing_vessel_groups": { "towing_vessels": "int", + "station_keeping_vessels": "int", "ahts_vessels": "int (optional, default: 1)", "num_groups": "int (optional)", }, @@ -67,9 +72,9 @@ def __init__(self, config, weather=None, **kwargs): config = self.initialize_library(config, **kwargs) self.config = self.validate_config(config) - self.setup_simulation(**kwargs) + self.setup_simulation() - def setup_simulation(self, **kwargs): + def setup_simulation(self): """ Sets up simulation infrastructure. - Initializes substructure production @@ -85,6 +90,7 @@ def setup_simulation(self, **kwargs): self.initialize_turbine_assembly() self.initialize_queue() self.initialize_towing_groups() + self.initialize_support_vessel() @property def system_capex(self): @@ -181,7 +187,8 @@ def initialize_towing_groups(self, **kwargs): towing_speed = self.config["substructure"].get("towing_speed", 6) ahts_vessel = self.config["ahts_vessel"] - num_ahts = self.config["towing_vessel_groups"]["ahts_vessels"] + + num_ahts = self.config["towing_vessel_groups"].get("ahts_vessels", 1) remaining_substructures = [1] * self.num_turbines @@ -212,9 +219,57 @@ def initialize_queue(self): self.active_group.vessel = None self.active_group.activate = self.env.event() + def initialize_support_vessel(self): + """ + ** DEPRECATED ** The support vessel is deprecated and an AHTS + vessel will perform the installation with the towing group. + + Initializes Multi-Purpose Support Vessel to perform installation + processes at site. + """ + + specs = self.config["support_vessel"] + + if specs is not None: + warn( + "support_vessel will be deprecated and replaced with" + " towing_vessels and to ahts_vessel in the towing groups.", + DeprecationWarning, + stacklevel=2, + ) + + # vessel = self.initialize_vessel("Multi-Purpose Support Vessel", + # specs) + + # self.env.register(vessel) + # vessel.initialize(mobilize=False) + # self.support_vessel = vessel + + station_keeping_vessels = self.config["towing_vessel_groups"][ + "station_keeping_vessels" + ] + + if station_keeping_vessels is not None: + print(station_keeping_vessels) + warn( + "station_keeping_vessels will be deprecated and replaced with" + " towing_vessels and ahts_vessels in the towing groups.", + DeprecationWarning, + stacklevel=2, + ) + + # install_moored_substructures( + # self.support_vessel, + # self.active_group, + # self.distance, + # self.num_turbines, + # station_keeping_vessels, + # **kwargs, + # ) + @property def detailed_output(self): - """""" + """return detailed outputs.""" return { "operational_delays": { @@ -234,7 +289,7 @@ def detailed_output(self): } def operational_delay(self, name): - """""" + """return operational delays""" actions = [a for a in self.env.actions if a["agent"] == name] delay = sum(a["duration"] for a in actions if "Delay" in a["action"]) @@ -283,10 +338,10 @@ def towing_group_actions( towing_vessels, ahts_vessels, towing_speed, - **kwargs, ): """ - Process logic for the towing vessel group. Assumes there is an anchor tug boat with each group + Process logic for the towing vessel group. Assumes there is an + anchor tug boat with each group Parameters ---------- @@ -308,7 +363,7 @@ def towing_group_actions( transit_time = distance / group.transit_speed start = group.env.now - assembly = yield feed.get() + _ = yield feed.get() delay = group.env.now - start if delay > 0: @@ -390,3 +445,80 @@ def towing_group_actions( "waveheight": le(group.max_waveheight), }, ) + + +@process +def install_moored_substructures( + vessel, queue, distance, substructures, station_keeping_vessels +): + """ + ** DEPRECATED ** This method is deprecated and is now performed + in towing_group_action() by the towing group with AHTS vessel. + Logic that a Multi-Purpose Support Vessel uses at site to complete the + installation of moored substructures. + + Parameters + ---------- + vessel : Vessel + queue : + distance : int | float + Distance between port and site (km). + substructures : int + Number of substructures to install before transiting back to port. + station_keeping_vessels : int + Number of vessels to use for substructure station keeping during final + installation at site. + """ + + n = 0 + while n < substructures: + if queue.vessel: + + start = vessel.env.now + if n == 0: + vessel.mobilize() + yield vessel.transit(distance) + + yield vessel.task_wrapper( + "Position Substructure", + 2, + constraints={"windspeed": le(15), "waveheight": le(2.5)}, + ) + yield vessel.task_wrapper( + "Ballast to Operational Draft", + 6, + constraints={"windspeed": le(15), "waveheight": le(2.5)}, + ) + yield vessel.task_wrapper( + "Connect Mooring Lines", + 22, + suspendable=True, + constraints={"windspeed": le(15), "waveheight": le(2.5)}, + ) + yield vessel.task_wrapper( + "Check Mooring Lines", + 12, + suspendable=True, + constraints={"windspeed": le(15), "waveheight": le(2.5)}, + ) + + group_time = vessel.env.now - start + queue.vessel.submit_action_log( + "Positioning Support", + group_time, + location="site", + num_vessels=station_keeping_vessels, + ) + yield queue.vessel.release.succeed() + vessel.submit_debug_log(progress="Substructure") + n += 1 + + else: + start = vessel.env.now + yield queue.activate + delay_time = vessel.env.now - start + + if n != 0: + vessel.submit_action_log("Delay", delay_time, location="Site") + + yield vessel.transit(distance) From 4e0f5dfc58f9b116bf385ee904ebaa4f91c18d22 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Thu, 2 May 2024 09:16:17 -0600 Subject: [PATCH 43/71] Check if ahts_vessel is None rather than a KeyError. --- ORBIT/phases/install/quayside_assembly_tow/moored.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index cc3834bc..a0585011 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -186,10 +186,13 @@ def initialize_towing_groups(self, **kwargs): num_towing = self.config["towing_vessel_groups"]["towing_vessels"] towing_speed = self.config["substructure"].get("towing_speed", 6) - ahts_vessel = self.config["ahts_vessel"] - + ahts_vessel = self.config.get("ahts_vessel", None) num_ahts = self.config["towing_vessel_groups"].get("ahts_vessels", 1) + if ahts_vessel is None: + warn("No ['ahts_vessel'] specified. num_ahts set to 0.") + num_ahts = 0 + remaining_substructures = [1] * self.num_turbines for i in range(num_groups): From 6b8c2c753e423d65d1b1b21f213f22bbf6e68237 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Thu, 2 May 2024 09:30:04 -0600 Subject: [PATCH 44/71] Made ahts_vessel optional temporarily to raise warnings rather than a KeyError. --- ORBIT/phases/install/quayside_assembly_tow/moored.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index a0585011..084781f4 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -29,7 +29,7 @@ class MooredSubInstallation(InstallPhase): #: expected_config = { "support_vessel": "str", - "ahts_vessel": "str", + "ahts_vessel": "str, (optional)", "towing_vessel": "str", "towing_vessel_groups": { "towing_vessels": "int", @@ -190,7 +190,10 @@ def initialize_towing_groups(self, **kwargs): num_ahts = self.config["towing_vessel_groups"].get("ahts_vessels", 1) if ahts_vessel is None: - warn("No ['ahts_vessel'] specified. num_ahts set to 0.") + warn( + "No ['ahts_vessel'] specified. num_ahts set to 0." + " ahts_vessel will be required in future releases.\n" + ) num_ahts = 0 remaining_substructures = [1] * self.num_turbines @@ -236,7 +239,7 @@ def initialize_support_vessel(self): if specs is not None: warn( "support_vessel will be deprecated and replaced with" - " towing_vessels and to ahts_vessel in the towing groups.", + " towing_vessels and ahts_vessel in the towing groups.\n", DeprecationWarning, stacklevel=2, ) @@ -256,7 +259,7 @@ def initialize_support_vessel(self): print(station_keeping_vessels) warn( "station_keeping_vessels will be deprecated and replaced with" - " towing_vessels and ahts_vessels in the towing groups.", + " towing_vessels and ahts_vessels in the towing groups.\n", DeprecationWarning, stacklevel=2, ) From 6573b45ab691dd75567a97e6702c08f326fd1ed5 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Thu, 2 May 2024 11:19:37 -0600 Subject: [PATCH 45/71] Adjusted floating true/false logic in electrical export. Eliminate redundant class for FloatingOffshoreSubstation. --- ORBIT/phases/design/electrical_export.py | 52 +++++++++++-------- ORBIT/phases/install/oss_install/floating.py | 23 ++++++-- .../install/quayside_assembly_tow/moored.py | 8 +++ 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/ORBIT/phases/design/electrical_export.py b/ORBIT/phases/design/electrical_export.py index 67952c4b..19635a04 100644 --- a/ORBIT/phases/design/electrical_export.py +++ b/ORBIT/phases/design/electrical_export.py @@ -69,6 +69,7 @@ class ElectricalDesign(CableSystem): "converter_cost": "USD (optional)", "onshore_converter_cost": "USD (optional)", "topside_assembly_factor": "float (optional)", + "oss_substructure_type": "str (optional, default: Monopile)", "oss_substructure_cost_rate": "USD/t (optional)", "oss_pile_cost_rate": "USD/t (optional)", }, @@ -126,25 +127,24 @@ def __init__(self, config, **kwargs): "interconnection_distance", 3 ) - # SUBSTATION - try: - self._floating_oss = config["substation_design"]["floating_oss"] - except KeyError: - self._floating_oss = False - - self._outputs = {} - - def run(self): - """Main run function.""" - self.export_system_design = self.config["export_system_design"] self.offshore_substation_design = self.config.get( "substation_design", {} ) + + self.substructure_type = self.offshore_substation_design.get( + "oss_substructure_type", "Monopile" + ) + self.onshore_substation_design = self.config.get( "onshore_substation_design", {} ) + self._outputs = {} + + def run(self): + """Main run function.""" + # CABLES self._initialize_cables() self.cable = self.cables[[*self.cables][0]] @@ -188,7 +188,8 @@ def run(self): self.calc_onshore_cost() self._outputs["offshore_substation_substructure"] = { - "type": "Monopile", # Substation install only supports monopiles + "type": self.substructure_type, # Substation install + # only supports monopiles "deck_space": self.substructure_deck_space, "mass": self.substructure_mass, "length": self.substructure_length, @@ -351,19 +352,18 @@ def calc_num_substations(self): ---------- substation_capacity : int | float """ - self._design = self.config.get("substation_design", {}) # HVAC substation capacity - _substation_capacity = self._design.get( + _substation_capacity = self.offshore_substation_design.get( "substation_capacity", 1200 ) # MW if "HVDC" in self.cable.cable_type: - self.num_substations = self._design.get( + self.num_substations = self.offshore_substation_design.get( "num_substations", int(self.num_cables / 2) ) else: - self.num_substations = self._design.get( + self.num_substations = self.offshore_substation_design.get( "num_substations", int(np.ceil(self._plant_capacity / _substation_capacity)), ) @@ -499,8 +499,10 @@ def calc_assembly_cost(self): topside_assembly_factor : int | float """ - _design = self.config.get("substation_design", {}) - topside_assembly_factor = _design.get("topside_assembly_factor", 0.075) + topside_assembly_factor = self.offshore_substation_design.get( + "topside_assembly_factor", 0.075 + ) + self.land_assembly_cost = ( self.switchgear_cost + self.shunt_reactor_cost @@ -517,18 +519,22 @@ def calc_substructure_mass_and_cost(self): oss_pile_cost_rate : int | float """ - _design = self.config.get("substation_design", {}) substructure_mass = 0.4 * self.topside_mass - oss_pile_cost_rate = _design.get("oss_pile_cost_rate", 0) - oss_substructure_cost_rate = _design.get( + oss_pile_cost_rate = self.offshore_substation_design.get( + "oss_pile_cost_rate", 0 + ) + oss_substructure_cost_rate = self.offshore_substation_design.get( "oss_substructure_cost_rate", 3000 ) + # TODO: Determine a better method to calculate substructure mass + # for different substructure types substructure_mass = 0.4 * self.topside_mass - if self._floating_oss == False: + + if self.substructure_type == "Monopile": substructure_pile_mass = 8 * substructure_mass**0.5574 else: - substructure_pile_mass = 0 # No piles for floating OSS + substructure_pile_mass = 0 # Assume floating and no piles are used self.substructure_cost = ( substructure_mass * oss_substructure_cost_rate diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index 471118db..4dd7e8e4 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -6,10 +6,13 @@ __email__ = "jake.nunemaker@nrel.gov" +from warnings import warn + from marmot import Agent, le, process +from marmot._exceptions import AgentNotRegistered + from ORBIT.core import WetStorage from ORBIT.core.logic import position_onsite -from marmot._exceptions import AgentNotRegistered from ORBIT.phases.install import InstallPhase from ORBIT.phases.install.mooring_install.mooring import ( install_mooring_line, @@ -37,14 +40,16 @@ class FloatingSubstationInstallation(InstallPhase): "attach_time": "int | float (optional, default: 24)", }, "offshore_substation_substructure": { - "type": "Floating", + "type": "str", "takt_time": "int | float (optional, default: 0)", "unit_cost": "USD", # "mooring_cost": "USD", "towing_speed": "int | float (optional, default: 6 km/h)", }, "mooring_system": { - # "system_cost": "USD", "}, # system cost is for all moorings in the whole farm, so you dont want this to be added to each substation + # "system_cost": "USD", "}, + # system cost is for all moorings in the whole farm, + # so you dont want this to be added to each substation "num_lines", "int", "line_cost", @@ -74,7 +79,7 @@ def __init__(self, config, weather=None, **kwargs): self.initialize_port() self.setup_simulation(**kwargs) - def setup_simulation(self, **kwargs): + def setup_simulation(self): """ Initializes required objects for simulation. - Creates port @@ -117,6 +122,16 @@ def initialize_substructure_production(self): quayside. """ + substructure_type = self.config["offshore_substation_substructure"][ + "type" + ] + + if substructure_type != "Floating": + warn( + f"Offshore substation substructure is {substructure_type}" + " and should be 'Floating'.\n" + ) + self.wet_storage = WetStorage(self.env, float("inf")) takt_time = self.config["offshore_substation_substructure"].get( "takt_time", 0 diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index 084781f4..31618768 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -291,6 +291,9 @@ def detailed_output(self): k: self.operational_delay(str(k)) for k in self.installation_groups }, + # self.support_vessel: self.operational_delay( + # str(self.support_vessel) + # ), } } @@ -476,6 +479,11 @@ def install_moored_substructures( installation at site. """ + warn( + "** DEPRECATED ** This method is deprecated and is now performed" + " in towing_group_action() by the towing group with AHTS vessel.\n" + ) + n = 0 while n < substructures: if queue.vessel: From 3e2b6c83c79e8c7b81373b32d7809e8e4de2f0c8 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Tue, 21 May 2024 14:03:03 -0600 Subject: [PATCH 46/71] Updated semitaut examples. --- ...5. Example Floating Project-SemiTaut.ipynb | 327 ++++++++++-------- .../example_floating_project_SemiTaut.yaml | 8 +- 2 files changed, 189 insertions(+), 146 deletions(-) diff --git a/examples/5. Example Floating Project-SemiTaut.ipynb b/examples/5. Example Floating Project-SemiTaut.ipynb index aa999ce7..edf2b103 100644 --- a/examples/5. Example Floating Project-SemiTaut.ipynb +++ b/examples/5. Example Floating Project-SemiTaut.ipynb @@ -20,14 +20,25 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "UserWarning: /var/folders/90/1lkt657x3n1cw5x65j3lfgd5406fb8/T/ipykernel_93742/1311156483.py:7\n", + "Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format." + ] + } + ], "source": [ "import os\n", "import pandas as pd\n", - "from ORBIT import ProjectManager, load_config \n", + "from ORBIT import ProjectManager, load_config\n", "\n", + "import warnings\n", + "warnings.filterwarnings(\"default\")\n", "weather = pd.read_csv(\"data/example_weather.csv\", parse_dates=[\"datetime\"])\\\n", " .set_index(\"datetime\")" ] @@ -41,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -56,7 +67,7 @@ } ], "source": [ - "fixed_config = load_config(\"configs/example_floating_project_SemiTaut.yaml\") \n", + "fixed_config = load_config(\"configs/example_floating_project_SemiTaut.yaml\")\n", "\n", "print(f\"Num turbines: {fixed_config['plant']['num_turbines']}\")\n", "print(f\"Turbine: {fixed_config['turbine']}\")\n", @@ -72,14 +83,14 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Design phases: ['ArraySystemDesign', 'ExportSystemDesign', 'SemiTautMooringSystemDesign', 'OffshoreFloatingSubstationDesign', 'SemiSubmersibleDesign']\n", + "Design phases: ['ArraySystemDesign', 'ElectricalDesign', 'SemiTautMooringSystemDesign', 'SemiSubmersibleDesign']\n", "\n", "Install phases: ['ArrayCableInstallation', 'ExportCableInstallation', 'MooredSubInstallation', 'MooringSystemInstallation', 'FloatingSubstationInstallation']\n" ] @@ -100,27 +111,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 4, + "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "ORBIT library intialized at 'C:\\Users\\rrolph\\OneDrive - NREL\\ORBIT\\library'\n", - "topside: 47826750.0\n", - "oss substructure1912800.0\n", - "mooring system6549357.6\n", - "topside: 47826750.0\n", - "oss substructure1912800.0\n", - "mooring system6549357.6\n" + "2\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "UserWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:193\n", + "No ['ahts_vessel'] specified. num_ahts set to 0. ahts_vessel will be required in future releases.\n", + "DeprecationWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:93\n", + "support_vessel will be deprecated and replaced with towing_vessels and ahts_vessel in the towing groups.\n", + "DeprecationWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:93\n", + "station_keeping_vessels will be deprecated and replaced with towing_vessels and ahts_vessels in the towing groups.\n" ] } ], @@ -138,20 +148,20 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Installation CapEx: 300 M\n", - "System CapEx: 1231 M\n", + "Installation CapEx: 345 M\n", + "System CapEx: 1333 M\n", "Turbine CapEx: 780 M\n", "Soft CapEx: 387 M\n", - "Total CapEx: 2850 M\n", + "Total CapEx: 2997 M\n", "\n", - "Installation Time: 22581 h\n" + "Installation Time: 35527 h\n" ] } ], @@ -174,28 +184,28 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Array System': 56983076.60642063,\n", - " 'Export System': 103712476.9152,\n", + " 'Export System': 259281192.288,\n", " 'Substructure': 630709636.6,\n", " 'Mooring System': 327467880.0,\n", - " 'Offshore Substation': 112577815.2,\n", - " 'Array System Installation': 22844527.89607126,\n", - " 'Export System Installation': 135112258.0470523,\n", - " 'Substructure Installation': 78569120.05327243,\n", + " 'Offshore Substation': 58536861.93724438,\n", + " 'Array System Installation': 63027746.845681354,\n", + " 'Export System Installation': 148076127.6910655,\n", + " 'Substructure Installation': 78801350.29354209,\n", " 'Mooring System Installation': 48485331.05022831,\n", - " 'Offshore Substation Installation': 14801636.225266362,\n", + " 'Offshore Substation Installation': 7070795.281582953,\n", " 'Turbine': 780000000,\n", " 'Soft': 387000000,\n", " 'Project': 151250000.0}" ] }, - "execution_count": 6, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -206,28 +216,28 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Array System': 94.97179434403438,\n", - " 'Export System': 172.854128192,\n", + " 'Export System': 432.13532047999996,\n", " 'Substructure': 1051.1827276666668,\n", " 'Mooring System': 545.7798,\n", - " 'Offshore Substation': 187.629692,\n", - " 'Array System Installation': 38.07421316011877,\n", - " 'Export System Installation': 225.18709674508716,\n", - " 'Substructure Installation': 130.9485334221207,\n", + " 'Offshore Substation': 97.56143656207396,\n", + " 'Array System Installation': 105.04624474280226,\n", + " 'Export System Installation': 246.79354615177581,\n", + " 'Substructure Installation': 131.33558382257016,\n", " 'Mooring System Installation': 80.80888508371386,\n", - " 'Offshore Substation Installation': 24.66939370877727,\n", + " 'Offshore Substation Installation': 11.784658802638255,\n", " 'Turbine': 1300.0,\n", " 'Soft': 645.0,\n", " 'Project': 252.08333333333334}" ] }, - "execution_count": 7, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -245,7 +255,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -283,6 +293,7 @@ " max_windspeed\n", " transit_speed\n", " num_vessels\n", + " num_ahts_vessels\n", " \n", " \n", " \n", @@ -292,7 +303,7 @@ " Array Cable Installation Vessel\n", " Mobilize\n", " 72.000000\n", - " 1.800000e+05\n", + " 3.375000e+05\n", " ACTION\n", " 0.000000\n", " ArrayCableInstallation\n", @@ -302,6 +313,7 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", " \n", " \n", " 1\n", @@ -309,7 +321,7 @@ " Export Cable Installation Vessel\n", " Mobilize\n", " 72.000000\n", - " 1.800000e+05\n", + " 3.375000e+05\n", " ACTION\n", " 0.000000\n", " ExportCableInstallation\n", @@ -319,6 +331,7 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", " \n", " \n", " 2\n", @@ -326,7 +339,7 @@ " Onshore Construction\n", " Onshore Construction\n", " 0.000000\n", - " 1.075454e+08\n", + " 1.665604e+06\n", " ACTION\n", " 0.000000\n", " ExportCableInstallation\n", @@ -336,6 +349,7 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", " \n", " \n", " 3\n", @@ -353,6 +367,7 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", " \n", " \n", " 4\n", @@ -370,6 +385,7 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", " \n", " \n", " ...\n", @@ -387,18 +403,20 @@ " ...\n", " ...\n", " ...\n", + " ...\n", " \n", " \n", - " 2876\n", + " 2988\n", " NaN\n", - " Multi-Purpose Support Vessel\n", - " Connect Mooring Lines, Pre-tension and pre-str...\n", - " 20.000000\n", - " 8.333333e+04\n", + " Export Cable Installation Vessel\n", + " Pull In Cable\n", + " 5.500000\n", + " 5.156250e+04\n", " ACTION\n", - " 8544.500000\n", - " MooredSubInstallation\n", + " 12017.280762\n", + " ExportCableInstallation\n", " NaN\n", + " ExportCableInstallation\n", " NaN\n", " NaN\n", " NaN\n", @@ -406,16 +424,17 @@ " NaN\n", " \n", " \n", - " 2877\n", + " 2989\n", " NaN\n", - " Multi-Purpose Support Vessel\n", - " Check Mooring Lines\n", - " 6.000000\n", - " 2.500000e+04\n", + " Export Cable Installation Vessel\n", + " Terminate Cable\n", + " 5.500000\n", + " 5.156250e+04\n", " ACTION\n", - " 8550.500000\n", - " MooredSubInstallation\n", + " 12022.780762\n", + " ExportCableInstallation\n", " NaN\n", + " ExportCableInstallation\n", " NaN\n", " NaN\n", " NaN\n", @@ -423,32 +442,34 @@ " NaN\n", " \n", " \n", - " 2878\n", + " 2990\n", " NaN\n", - " Towing Group 1\n", - " Positioning Support\n", - " 34.000000\n", - " 8.500000e+04\n", + " Export Cable Installation Vessel\n", + " Transit\n", + " 8.000000\n", + " 7.500000e+04\n", " ACTION\n", - " 8550.500000\n", - " MooredSubInstallation\n", - " site\n", + " 12030.780762\n", + " ExportCableInstallation\n", + " NaN\n", + " NaN\n", + " NaN\n", " NaN\n", " NaN\n", " NaN\n", " NaN\n", - " 2.0\n", " \n", " \n", - " 2879\n", + " 2991\n", " NaN\n", - " Multi-Purpose Support Vessel\n", - " Transit\n", - " 10.000000\n", - " 4.166667e+04\n", + " Export Cable Installation Vessel\n", + " Delay\n", + " 26.000000\n", + " 2.437500e+05\n", " ACTION\n", - " 8560.500000\n", - " MooredSubInstallation\n", + " 12056.780762\n", + " ExportCableInstallation\n", + " NaN\n", " NaN\n", " NaN\n", " NaN\n", @@ -457,25 +478,26 @@ " NaN\n", " \n", " \n", - " 2880\n", + " 2992\n", " NaN\n", - " Towing Group 1\n", + " Export Cable Installation Vessel\n", " Transit\n", - " 16.666667\n", - " 6.250000e+04\n", + " 0.695652\n", + " 6.521739e+03\n", " ACTION\n", - " 8567.166667\n", - " MooredSubInstallation\n", + " 12057.476414\n", + " ExportCableInstallation\n", + " NaN\n", + " NaN\n", " NaN\n", " NaN\n", " NaN\n", " NaN\n", " NaN\n", - " 3.0\n", " \n", " \n", "\n", - "

2881 rows Ă— 14 columns

\n", + "

2993 rows Ă— 15 columns

\n", "" ], "text/plain": [ @@ -486,68 +508,68 @@ "3 1.0 Mooring System Installation Vessel \n", "4 NaN Substation Assembly Line 1 \n", "... ... ... \n", - "2876 NaN Multi-Purpose Support Vessel \n", - "2877 NaN Multi-Purpose Support Vessel \n", - "2878 NaN Towing Group 1 \n", - "2879 NaN Multi-Purpose Support Vessel \n", - "2880 NaN Towing Group 1 \n", + "2988 NaN Export Cable Installation Vessel \n", + "2989 NaN Export Cable Installation Vessel \n", + "2990 NaN Export Cable Installation Vessel \n", + "2991 NaN Export Cable Installation Vessel \n", + "2992 NaN Export Cable Installation Vessel \n", "\n", - " action duration \\\n", - "0 Mobilize 72.000000 \n", - "1 Mobilize 72.000000 \n", - "2 Onshore Construction 0.000000 \n", - "3 Mobilize 168.000000 \n", - "4 Substation Substructure Assembly 0.000000 \n", - "... ... ... \n", - "2876 Connect Mooring Lines, Pre-tension and pre-str... 20.000000 \n", - "2877 Check Mooring Lines 6.000000 \n", - "2878 Positioning Support 34.000000 \n", - "2879 Transit 10.000000 \n", - "2880 Transit 16.666667 \n", + " action duration cost level \\\n", + "0 Mobilize 72.000000 3.375000e+05 ACTION \n", + "1 Mobilize 72.000000 3.375000e+05 ACTION \n", + "2 Onshore Construction 0.000000 1.665604e+06 ACTION \n", + "3 Mobilize 168.000000 7.000000e+05 ACTION \n", + "4 Substation Substructure Assembly 0.000000 0.000000e+00 ACTION \n", + "... ... ... ... ... \n", + "2988 Pull In Cable 5.500000 5.156250e+04 ACTION \n", + "2989 Terminate Cable 5.500000 5.156250e+04 ACTION \n", + "2990 Transit 8.000000 7.500000e+04 ACTION \n", + "2991 Delay 26.000000 2.437500e+05 ACTION \n", + "2992 Transit 0.695652 6.521739e+03 ACTION \n", "\n", - " cost level time phase \\\n", - "0 1.800000e+05 ACTION 0.000000 ArrayCableInstallation \n", - "1 1.800000e+05 ACTION 0.000000 ExportCableInstallation \n", - "2 1.075454e+08 ACTION 0.000000 ExportCableInstallation \n", - "3 7.000000e+05 ACTION 0.000000 MooringSystemInstallation \n", - "4 0.000000e+00 ACTION 0.000000 FloatingSubstationInstallation \n", - "... ... ... ... ... \n", - "2876 8.333333e+04 ACTION 8544.500000 MooredSubInstallation \n", - "2877 2.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", - "2878 8.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", - "2879 4.166667e+04 ACTION 8560.500000 MooredSubInstallation \n", - "2880 6.250000e+04 ACTION 8567.166667 MooredSubInstallation \n", + " time phase location \\\n", + "0 0.000000 ArrayCableInstallation NaN \n", + "1 0.000000 ExportCableInstallation NaN \n", + "2 0.000000 ExportCableInstallation Landfall \n", + "3 0.000000 MooringSystemInstallation NaN \n", + "4 0.000000 FloatingSubstationInstallation NaN \n", + "... ... ... ... \n", + "2988 12017.280762 ExportCableInstallation NaN \n", + "2989 12022.780762 ExportCableInstallation NaN \n", + "2990 12030.780762 ExportCableInstallation NaN \n", + "2991 12056.780762 ExportCableInstallation NaN \n", + "2992 12057.476414 ExportCableInstallation NaN \n", "\n", - " location phase_name max_waveheight max_windspeed transit_speed \\\n", - "0 NaN NaN NaN NaN NaN \n", - "1 NaN NaN NaN NaN NaN \n", - "2 Landfall NaN NaN NaN NaN \n", - "3 NaN NaN NaN NaN NaN \n", - "4 NaN NaN NaN NaN NaN \n", - "... ... ... ... ... ... \n", - "2876 NaN NaN NaN NaN NaN \n", - "2877 NaN NaN NaN NaN NaN \n", - "2878 site NaN NaN NaN NaN \n", - "2879 NaN NaN NaN NaN NaN \n", - "2880 NaN NaN NaN NaN NaN \n", + " phase_name max_waveheight max_windspeed transit_speed \\\n", + "0 NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN \n", + "2 NaN NaN NaN NaN \n", + "3 NaN NaN NaN NaN \n", + "4 NaN NaN NaN NaN \n", + "... ... ... ... ... \n", + "2988 ExportCableInstallation NaN NaN NaN \n", + "2989 ExportCableInstallation NaN NaN NaN \n", + "2990 NaN NaN NaN NaN \n", + "2991 NaN NaN NaN NaN \n", + "2992 NaN NaN NaN NaN \n", "\n", - " num_vessels \n", - "0 NaN \n", - "1 NaN \n", - "2 NaN \n", - "3 NaN \n", - "4 NaN \n", - "... ... \n", - "2876 NaN \n", - "2877 NaN \n", - "2878 2.0 \n", - "2879 NaN \n", - "2880 3.0 \n", + " num_vessels num_ahts_vessels \n", + "0 NaN NaN \n", + "1 NaN NaN \n", + "2 NaN NaN \n", + "3 NaN NaN \n", + "4 NaN NaN \n", + "... ... ... \n", + "2988 NaN NaN \n", + "2989 NaN NaN \n", + "2990 NaN NaN \n", + "2991 NaN NaN \n", + "2992 NaN NaN \n", "\n", - "[2881 rows x 14 columns]" + "[2993 rows x 15 columns]" ] }, - "execution_count": 8, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -558,10 +580,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "data": { + "text/plain": [ + "{'type': 'Monopile',\n", + " 'deck_space': 1,\n", + " 'mass': 1606.7690784724548,\n", + " 'length': 910,\n", + " 'unit_cost': 3576000.0}" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "project.design_results[\"offshore_substation_substructure\"]" + ] } ], "metadata": { @@ -580,7 +619,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.15" + "version": "3.8.18" } }, "nbformat": 4, diff --git a/examples/configs/example_floating_project_SemiTaut.yaml b/examples/configs/example_floating_project_SemiTaut.yaml index c43de907..c0890c62 100644 --- a/examples/configs/example_floating_project_SemiTaut.yaml +++ b/examples/configs/example_floating_project_SemiTaut.yaml @@ -19,9 +19,11 @@ export_cable_install_vessel: example_cable_lay_vessel mooring_install_vessel: example_support_vessel oss_install_vessel: floating_heavy_lift_vessel support_vessel: example_support_vessel +#ahts_vessel: example_ahts_vessel towing_vessel: example_towing_vessel towing_vessel_groups: station_keeping_vessels: 2 + ahts_vessels: 1 towing_vessels: 3 wtiv: floating_heavy_lift_vessel # Module Specific @@ -35,12 +37,14 @@ array_system_design: export_system_design: cables: XLPE_500mm_132kV percent_added_length: 0.0 +offshore_substation_substructure: + type: Floating # Configured Phases design_phases: - ArraySystemDesign -- ExportSystemDesign +- ElectricalDesign - SemiTautMooringSystemDesign -- OffshoreFloatingSubstationDesign +#- OffshoreFloatingSubstationDesign - SemiSubmersibleDesign install_phases: ArrayCableInstallation: 0 From fab774bd1cff7731ecaaa891d43f2491c355bab8 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Fri, 31 May 2024 11:34:50 -0600 Subject: [PATCH 47/71] Updated electrical_design testing to check floating/fixed offshore substation --- tests/phases/design/test_electrical_design.py | 80 ++++++++++++++++++- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/tests/phases/design/test_electrical_design.py b/tests/phases/design/test_electrical_design.py index 2ca93e26..5539e928 100644 --- a/tests/phases/design/test_electrical_design.py +++ b/tests/phases/design/test_electrical_design.py @@ -20,7 +20,9 @@ "plant": {"capacity": 500}, "export_system_design": {"cables": "XLPE_630mm_220kV"}, "landfall": {}, - "substation_design": {}, + "substation_design": { + "oss_pile_cost_rate": 1200, # need to set this for kwarg tests + }, } @@ -59,6 +61,78 @@ def test_parameter_sweep(distance_to_landfall, depth, plant_cap, cable): assert 1e6 <= o.total_substation_cost <= 1e9 +def test_calc_substructure_mass_and_cost(): + + o = ElectricalDesign(base) + o.run() + + floating = deepcopy(base) + floating["substation_design"]["oss_substructure_type"] = "Floating" + o_floating = ElectricalDesign(floating) + o_floating.run() + + assert ( + o.detailed_output["substation_substructure_cost"] + != o_floating.detailed_output["substation_substructure_cost"] + ) + assert ( + o.detailed_output["substation_substructure_mass"] + != o_floating.detailed_output["substation_substructure_mass"] + ) + + +def test_calc_topside_mass_and_cost(): + """Test topside mass and cost for HVDC compared to HVDC-Monopole and HVDC-Bipole""" + + o = ElectricalDesign(base) + o.run() + + base_dc = deepcopy(base) + cables = ["HVDC_2000mm_320kV", "HVDC_2500mm_525kV"] + + for cable in cables: + base_dc["export_system_design"]["cables"] = cable + + o_dc = ElectricalDesign(base_dc) + o_dc.run() + + assert ( + o.detailed_output["substation_topside_mass"] + == o_dc.detailed_output["substation_topside_mass"] + ) + assert ( + o.detailed_output["substation_topside_cost"] + != o_dc.detailed_output["substation_topside_cost"] + ) + + +def test_oss_substructure_kwargs(): + test_kwargs = { + "oss_substructure_type": "Floating", + "oss_substructure_cost_rate": 7250, + "oss_pile_cost_rate": 2500, + "num_substations": 4, + } + + o = ElectricalDesign(base) + o.run() + base_cost_total = o.detailed_output["total_substation_cost"] + base_cost_subst = o.detailed_output["substation_substructure_cost"] + + for k, v in test_kwargs.items(): + config = deepcopy(base) + config["substation_design"] = {} + config["substation_design"][k] = v + + o = ElectricalDesign(config) + o.run() + cost_total = o.detailed_output["total_substation_cost"] + cost_subst = o.detailed_output["substation_substructure_cost"] + + assert cost_total != base_cost_total + assert cost_subst != base_cost_subst + + def test_ac_oss_kwargs(): test_kwargs = { "mpt_unit_cost": 13500, @@ -70,8 +144,6 @@ def test_ac_oss_kwargs(): "workspace_cost": 3e6, "other_ancillary_cost": 4e6, "topside_assembly_factor": 0.09, - "oss_substructure_cost_rate": 7250, - "oss_pile_cost_rate": 2500, "num_substations": 4, } @@ -109,7 +181,7 @@ def test_dc_oss_kwargs(): o = ElectricalDesign(config) o.run() cost = o.detailed_output["total_substation_cost"] - print("passed") + assert cost != base_cost From c10f253f8f95749a1b0eab3678edc193d473074e Mon Sep 17 00:00:00 2001 From: nriccobo Date: Fri, 31 May 2024 11:39:42 -0600 Subject: [PATCH 48/71] Updated oss_design test for floating/fixed options --- tests/phases/design/test_oss_design.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/phases/design/test_oss_design.py b/tests/phases/design/test_oss_design.py index b2dd6316..b6257e2d 100644 --- a/tests/phases/design/test_oss_design.py +++ b/tests/phases/design/test_oss_design.py @@ -62,6 +62,7 @@ def test_oss_kwargs(): "workspace_cost": 3e6, "other_ancillary_cost": 4e6, "topside_assembly_factor": 0.08, + "oss_substructure_type": "Floating", "oss_substructure_cost_rate": 7250, "oss_pile_cost_rate": 2500, "num_substations": 2, @@ -75,6 +76,7 @@ def test_oss_kwargs(): config = deepcopy(base) config["substation_design"] = {} + config["substation_design"]["oss_pile_cost_rate"] = 1500 config["substation_design"][k] = v o = OffshoreSubstationDesign(config) From 3aa5aa5becc006dabdeef65a1d43ebe8aff2b332 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Fri, 31 May 2024 12:00:22 -0600 Subject: [PATCH 49/71] Adjusted floating/standard oss install to count for floating and fix pylint warnings --- ORBIT/phases/install/oss_install/floating.py | 2 +- ORBIT/phases/install/oss_install/standard.py | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index 4dd7e8e4..69c53f76 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -77,7 +77,7 @@ def __init__(self, config, weather=None, **kwargs): self.config = self.validate_config(config) self.initialize_port() - self.setup_simulation(**kwargs) + self.setup_simulation() def setup_simulation(self): """ diff --git a/ORBIT/phases/install/oss_install/standard.py b/ORBIT/phases/install/oss_install/standard.py index f3da2a3f..f931bc24 100644 --- a/ORBIT/phases/install/oss_install/standard.py +++ b/ORBIT/phases/install/oss_install/standard.py @@ -9,7 +9,6 @@ import simpy from marmot import process -from ORBIT.core import Vessel from ORBIT.core.logic import shuttle_items_to_queue, prep_for_site_operations from ORBIT.phases.install import InstallPhase from ORBIT.phases.install.monopile_install.common import ( @@ -48,7 +47,7 @@ class OffshoreSubstationInstallation(InstallPhase): "unit_cost": "USD", }, "offshore_substation_substructure": { - "type": "Monopile", + "type": "str", "deck_space": "m2", "mass": "t", "length": "m", @@ -257,7 +256,11 @@ def install_oss_from_queue(vessel, queue, substations, distance, **kwargs): start = vessel.env.now yield queue.activate delay_time = vessel.env.now - start - vessel.submit_action_log("Delay: Not enough vessels for oss", delay_time, location="Site") + vessel.submit_action_log( + "Delay: Not enough vessels for oss", + delay_time, + location="Site", + ) # Transit to port vessel.at_site = False From 6d8e4111d9b4142b46b920c5717d393e42689bf3 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Fri, 31 May 2024 12:40:48 -0600 Subject: [PATCH 50/71] Cleaned up line length and mass calc and included TLP option --- ORBIT/phases/design/mooring_system_design.py | 59 ++++++++++++-------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index 43fa6d91..384139d7 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -24,7 +24,8 @@ class MooringSystemDesign(DesignPhase): "anchor_type": "str (optional, default: 'Suction Pile')", "mooring_type": "str (optional, default: 'Catenary')", "mooring_line_cost_rate": "int | float (optional)", - "drag_embedment_fixed_length": "int | float (optional, default: .5km)", + "drag_embedment_fixed_length": "int (optional, default: 500m)", + "draft_depth": "int (optional, default: 20m)", "chain_density": "int | float (optional, default: 19900 kg/m**3)", "rope_density": "int | float (optional, default: 797.8 kg/m**3)", }, @@ -37,6 +38,7 @@ class MooringSystemDesign(DesignPhase): "line_mass": "t", "line_cost": "USD", "line_length": "m", + "mooring_type": "str", "anchor_mass": "t", "anchor_type": "str", "anchor_cost": "USD", @@ -130,46 +132,42 @@ def calculate_breaking_load(self): def calculate_line_length_mass(self): """ Returns the mooring line length and mass. - """ - - if self.mooring_type == "Catenary": - if self.anchor_type == "Drag Embedment": - fixed = self._design.get("drag_embedment_fixed_length", 500) - else: - fixed = 0 - - self.line_length = ( - 0.0002 * (self.depth**2) + 1.264 * self.depth + 47.776 + fixed - ) + Parameters + ---------- + drag_embedment_fixed_length + draft_depth + """ - self.line_mass = self.line_length * self.line_mass_per_m + # Add extra fixed line length for drag embedments + if self.anchor_type == "Drag Embedment": + fixed = self._design.get("drag_embedment_fixed_length", 500) else: - if self.anchor_type == "Drag Embedment": - fixed = self._design.get("drag_embedment_fixed_length", 0) + fixed = 0 - else: - fixed = 0 + draft = self._design.get("draft_depth", 20) + + if self.mooring_type == "SemiTaut": # Interpolation of rope and chain length at project depth self.chain_length = interp1d( self._semitaut_params["depths"], self._semitaut_params["chain_lengths"], - )(self.depth) + )(self.depth).item() self.rope_length = interp1d( self._semitaut_params["depths"], self._semitaut_params["rope_lengths"], - )(self.depth) + )(self.depth).item() # Rope and interpolated chain diameter at project depth rope_diameter = self._semitaut_params["rope_diameter"] chain_diameter = interp1d( self._semitaut_params["depths"], self._semitaut_params["chain_diameters"], - )(self.depth) + )(self.depth).item() - self.line_length = self.rope_length + self.chain_length + self.line_length = self.rope_length + self.chain_length + fixed chain_mass_per_m = ( self._design.get("mooring_chain_density", 19900) @@ -185,6 +183,20 @@ def calculate_line_length_mass(self): + self.rope_length * rope_mass_per_m ) / 1e3 # tonnes + elif self.mooring_type == "TLP": + + self.line_length = self.depth - draft + + self.line_mass = self.line_length * self.line_mass_per_m + + else: + + self.line_length = ( + 0.0002 * (self.depth**2) + 1.264 * self.depth + 47.776 + fixed + ) + + self.line_mass = self.line_length * self.line_mass_per_m + def calculate_anchor_mass_cost(self): """ Returns the mass and cost of anchors. @@ -213,7 +225,7 @@ def calculate_anchor_mass_cost(self): self.anchor_cost = interp1d( self._semitaut_params["depths"], self._semitaut_params["anchor_costs"], - )(self.depth) + )(self.depth).item() @property def line_cost(self): @@ -227,7 +239,7 @@ def line_cost(self): line_cost = interp1d( self._semitaut_params["depths"], self._semitaut_params["total_line_costs"], - )(self.depth) + )(self.depth).item() return line_cost @@ -251,6 +263,7 @@ def detailed_output(self): "line_mass": self.line_mass, "line_length": self.line_length, "line_cost": self.line_cost, + "mooring_type": self.mooring_type, "anchor_type": self.anchor_type, "anchor_mass": self.anchor_mass, "anchor_cost": self.anchor_cost, From b36453f3effacfa189c108752b71e9a6b8aa1430 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Fri, 31 May 2024 14:52:43 -0600 Subject: [PATCH 51/71] Rearranged floating or fixed logic. Set substructure length=0 for floating --- ORBIT/phases/design/electrical_export.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ORBIT/phases/design/electrical_export.py b/ORBIT/phases/design/electrical_export.py index 19635a04..9c10bce8 100644 --- a/ORBIT/phases/design/electrical_export.py +++ b/ORBIT/phases/design/electrical_export.py @@ -188,8 +188,7 @@ def run(self): self.calc_onshore_cost() self._outputs["offshore_substation_substructure"] = { - "type": self.substructure_type, # Substation install - # only supports monopiles + "type": self.substructure_type, "deck_space": self.substructure_deck_space, "mass": self.substructure_mass, "length": self.substructure_length, @@ -531,10 +530,11 @@ def calc_substructure_mass_and_cost(self): # for different substructure types substructure_mass = 0.4 * self.topside_mass - if self.substructure_type == "Monopile": - substructure_pile_mass = 8 * substructure_mass**0.5574 + if self.substructure_type == "Floating": + substructure_pile_mass = 0 # No piles used for floating platform + else: - substructure_pile_mass = 0 # Assume floating and no piles are used + substructure_pile_mass = 8 * substructure_mass**0.5574 self.substructure_cost = ( substructure_mass * oss_substructure_cost_rate @@ -548,7 +548,11 @@ def calc_substructure_length(self): Calculates substructure length as the site depth + 10m """ - self.substructure_length = self.config["site"]["depth"] + 10 + if self.substructure_type == "Floating": + self.substructure_length = 0 + + else: + self.substructure_length = self.config["site"]["depth"] + 10 def calc_substructure_deck_space(self): """ From 1bf24728c170d50d96b6ab95a04d45b2531550a7 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Fri, 31 May 2024 14:54:30 -0600 Subject: [PATCH 52/71] Rearranged mooring type logic to default to catenary --- ORBIT/phases/design/mooring_system_design.py | 38 +++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index 384139d7..f02240f9 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -100,6 +100,8 @@ def run(self): def determine_mooring_line(self): """ Returns the diameter of the mooring lines based on the turbine rating. + + TODO: Add TLP option and consider merging SemiTaut interp here """ tr = self.config["turbine"]["turbine_rating"] @@ -133,6 +135,8 @@ def calculate_line_length_mass(self): """ Returns the mooring line length and mass. + TODO: Improve TLP line length and mass + Parameters ---------- drag_embedment_fixed_length @@ -203,44 +207,54 @@ def calculate_anchor_mass_cost(self): TODO: Anchor masses are rough estimates based on initial literature review. Should be revised when this module is overhauled in the future. + TODO: Mooring types for Catenary, TLP, SemiTaut will likely have + different anchors. """ - if self.mooring_type == "Catenary": + if self.mooring_type == "SemiTaut": + if self.anchor_type == "Drag Embedment": self.anchor_mass = 20 - self.anchor_cost = self.breaking_load / 9.81 / 20.0 * 2000.0 + + # Interpolation of anchor cost at project depth + self.anchor_cost = interp1d( + self._semitaut_params["depths"], + self._semitaut_params["anchor_costs"], + )(self.depth).item() else: self.anchor_mass = 50 self.anchor_cost = ( sqrt(self.breaking_load / 9.81 / 1250) * 150000 ) + else: + if self.anchor_type == "Drag Embedment": self.anchor_mass = 20 + self.anchor_cost = self.breaking_load / 9.81 / 20.0 * 2000.0 else: self.anchor_mass = 50 - - self.anchor_cost = interp1d( - self._semitaut_params["depths"], - self._semitaut_params["anchor_costs"], - )(self.depth).item() + self.anchor_cost = ( + sqrt(self.breaking_load / 9.81 / 1250) * 150000 + ) @property def line_cost(self): """Returns cost of one line mooring line.""" - if self.mooring_type == "Catenary": - line_cost = self.line_length * self.line_cost_rate - - else: - + if self.mooring_type == "SemiTaut": + # Interpolation of line cost at project depth line_cost = interp1d( self._semitaut_params["depths"], self._semitaut_params["total_line_costs"], )(self.depth).item() + else: + + line_cost = self.line_length * self.line_cost_rate + return line_cost @property From c358c3d03ea66e54eeb4a7ad282b316847652338 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Fri, 31 May 2024 16:38:19 -0600 Subject: [PATCH 53/71] Made interp1d extrapolate outside range and connected mooring_list_cost_rate kwarg. Updated tests --- ORBIT/phases/design/mooring_system_design.py | 13 ++- .../design/test_mooring_system_design.py | 88 ++++++++++++++++++- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index f02240f9..1fb11678 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -104,23 +104,25 @@ def determine_mooring_line(self): TODO: Add TLP option and consider merging SemiTaut interp here """ + _design = self.config.get("mooring_system_design", {}) + tr = self.config["turbine"]["turbine_rating"] fit = -0.0004 * (tr**2) + 0.0132 * tr + 0.0536 if fit <= 0.09: self.line_diam = 0.09 self.line_mass_per_m = 0.161 - self.line_cost_rate = 399.0 + self.line_cost_rate = _design.get("mooring_line_cost_rate", 399.0) elif fit <= 0.12: self.line_diam = 0.12 self.line_mass_per_m = 0.288 - self.line_cost_rate = 721.0 + self.line_cost_rate = _design.get("mooring_line_cost_rate", 721.0) else: self.line_diam = 0.15 self.line_mass_per_m = 0.450 - self.line_cost_rate = 1088.0 + self.line_cost_rate = _design.get("mooring_line_cost_rate", 1088.0) def calculate_breaking_load(self): """ @@ -158,10 +160,12 @@ def calculate_line_length_mass(self): self.chain_length = interp1d( self._semitaut_params["depths"], self._semitaut_params["chain_lengths"], + fill_value="extrapolate", )(self.depth).item() self.rope_length = interp1d( self._semitaut_params["depths"], self._semitaut_params["rope_lengths"], + fill_value="extrapolate", )(self.depth).item() # Rope and interpolated chain diameter at project depth @@ -169,6 +173,7 @@ def calculate_line_length_mass(self): chain_diameter = interp1d( self._semitaut_params["depths"], self._semitaut_params["chain_diameters"], + fill_value="extrapolate", )(self.depth).item() self.line_length = self.rope_length + self.chain_length + fixed @@ -220,6 +225,7 @@ def calculate_anchor_mass_cost(self): self.anchor_cost = interp1d( self._semitaut_params["depths"], self._semitaut_params["anchor_costs"], + fill_value="extrapolate", )(self.depth).item() else: @@ -249,6 +255,7 @@ def line_cost(self): line_cost = interp1d( self._semitaut_params["depths"], self._semitaut_params["total_line_costs"], + fill_value="extrapolate", )(self.depth).item() else: diff --git a/tests/phases/design/test_mooring_system_design.py b/tests/phases/design/test_mooring_system_design.py index 88a7a747..cd4261e2 100644 --- a/tests/phases/design/test_mooring_system_design.py +++ b/tests/phases/design/test_mooring_system_design.py @@ -10,12 +10,16 @@ import pytest -from ORBIT.phases.design import MooringSystemDesign +from ORBIT.phases.design import ( + MooringSystemDesign, + SemiTaut_mooring_system_design, +) base = { "site": {"depth": 200}, "turbine": {"turbine_rating": 6}, "plant": {"num_turbines": 50}, + "mooring_system_design": {}, } @@ -33,7 +37,7 @@ def test_depth_sweep(depth): @pytest.mark.parametrize("rating", range(3, 15, 1)) -def test_rating_sweeip(rating): +def test_rating_sweep(rating): config = deepcopy(base) config["turbine"]["turbine_rating"] = rating @@ -45,6 +49,86 @@ def test_rating_sweeip(rating): assert m.total_cost +def test_catenary_mooring_system_kwargs(): + + test_kwargs = { + "num_lines": 6, + "anchor_type": "Drag Embedment", + "mooring_line_cost_rate": 2500, + } + + m = MooringSystemDesign(base) + m.run() + + base_cost = m.detailed_output["system_cost"] + + for k, v in test_kwargs.items(): + config = deepcopy(base) + config["mooring_system_design"] = {} + config["mooring_system_design"][k] = v + + m = MooringSystemDesign(config) + m.run() + + assert m.detailed_output["system_cost"] != base_cost + + +def test_semitaut_mooring_system_kwargs(): + + semi_base = deepcopy(base) + semi_base["mooring_system_design"]["mooring_type"] = "SemiTaut" + + test_kwargs = { + "num_lines": 6, + "anchor_type": "Drag Embedment", + "chain_density": 10000, + "rope_density": 1000, + } + + m = MooringSystemDesign(semi_base) + m.run() + + base_cost = m.detailed_output["system_cost"] + + for k, v in test_kwargs.items(): + config = deepcopy(semi_base) + config["mooring_system_design"] = {} + config["mooring_system_design"][k] = v + + m = MooringSystemDesign(config) + m.run() + + assert m.detailed_output["system_cost"] != base_cost + + +def test_tlp_mooring_system_kwargs(): + + tlp_base = deepcopy(base) + tlp_base["mooring_system_design"]["mooring_type"] = "TLP" + + test_kwargs = { + "num_lines": 6, + "anchor_type": "Drag Embedment", + "mooring_line_cost_rate": 2500, + "draft_depth": 10, + } + + m = MooringSystemDesign(tlp_base) + m.run() + + base_cost = m.detailed_output["system_cost"] + + for k, v in test_kwargs.items(): + config = deepcopy(tlp_base) + config["mooring_system_design"] = {} + config["mooring_system_design"][k] = v + + m = MooringSystemDesign(config) + m.run() + + assert m.detailed_output["system_cost"] != base_cost + + def test_drag_embedment_fixed_length(): m = MooringSystemDesign(base) From eaee68a23563ab2fd495a6cd95c964f2e34dd2a1 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Fri, 31 May 2024 17:28:45 -0600 Subject: [PATCH 54/71] Updated floating example and config yaml --- examples/5. Example Floating Project.ipynb | 1138 +++++++++-------- .../configs/example_floating_project.yaml | 20 +- 2 files changed, 604 insertions(+), 554 deletions(-) diff --git a/examples/5. Example Floating Project.ipynb b/examples/5. Example Floating Project.ipynb index 8c8c12d6..7513d223 100644 --- a/examples/5. Example Floating Project.ipynb +++ b/examples/5. Example Floating Project.ipynb @@ -1,560 +1,604 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Jake Nunemaker\n", - "\n", - "National Renewable Energy Lab\n", - "\n", - "Last updated: 12/23/2020" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import pandas as pd\n", - "from ORBIT import ProjectManager, load_config\n", - "\n", - "weather = pd.read_csv(\"data/example_weather.csv\", parse_dates=[\"datetime\"])\\\n", - " .set_index(\"datetime\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Load the project configuration" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ + "cells": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Num turbines: 50\n", - "Turbine: 12MW_generic\n", - "\n", - "Site: {'depth': 900, 'distance': 100, 'distance_to_landfall': 100}\n" - ] - } - ], - "source": [ - "fixed_config = load_config(\"configs/example_floating_project.yaml\") \n", - "\n", - "print(f\"Num turbines: {fixed_config['plant']['num_turbines']}\")\n", - "print(f\"Turbine: {fixed_config['turbine']}\")\n", - "print(f\"\\nSite: {fixed_config['site']}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Phases" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Example Floating Project\n", + "\n", + "This tutorial uses prepared ORBIT configs that are stored as .yaml files in the `~/configs/` folder. These example projects each exhibit different functionalities within ORBIT. Using these examples and combinations of them, most project configurations can be modeled. \n", + "\n", + "Last updated: May 2024" + ] + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "Design phases: ['ArraySystemDesign', 'ExportSystemDesign', 'MooringSystemDesign', 'OffshoreSubstationDesign', 'SemiSubmersibleDesign']\n", - "\n", - "Install phases: ['ArrayCableInstallation', 'ExportCableInstallation', 'MooredSubInstallation', 'MooringSystemInstallation', 'OffshoreSubstationInstallation', 'TurbineInstallation']\n" - ] - } - ], - "source": [ - "print(f\"Design phases: {fixed_config['design_phases']}\")\n", - "print(f\"\\nInstall phases: {list(fixed_config['install_phases'].keys())}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Run" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "UserWarning: /var/folders/90/1lkt657x3n1cw5x65j3lfgd5406fb8/T/ipykernel_74288/2795185578.py:8\n", + "Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format." + ] + } + ], + "source": [ + "import pandas as pd\n", + "from pprint import pprint\n", + "from ORBIT import ProjectManager, load_config\n", + "\n", + "import warnings\n", + "warnings.filterwarnings(\"default\")\n", + "\n", + "weather = pd.read_csv(\"data/example_weather.csv\", parse_dates=[\"datetime\"])\\\n", + " .set_index(\"datetime\")" + ] + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "ORBIT library intialized at 'C:\\Users\\rrolph\\OneDrive - NREL\\ORBIT\\library'\n" - ] - } - ], - "source": [ - "project = ProjectManager(fixed_config, weather=weather)\n", - "project.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Top Level Outputs" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load the project configuration\n", + "`~/configs/example_floating_project.yaml`" + ] + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "Installation CapEx: 420 M\n", - "System CapEx: 1222 M\n", - "Turbine CapEx: 780 M\n", - "Soft CapEx: 387 M\n", - "Total CapEx: 2960 M\n", - "\n", - "Installation Time: 27734 h\n" - ] - } - ], - "source": [ - "print(f\"Installation CapEx: {project.installation_capex/1e6:.0f} M\")\n", - "print(f\"System CapEx: {project.system_capex/1e6:.0f} M\")\n", - "print(f\"Turbine CapEx: {project.turbine_capex/1e6:.0f} M\")\n", - "print(f\"Soft CapEx: {project.soft_capex/1e6:.0f} M\")\n", - "print(f\"Total CapEx: {project.total_capex/1e6:.0f} M\")\n", - "\n", - "print(f\"\\nInstallation Time: {project.installation_time:.0f} h\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### CapEx Breakdown" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Num turbines: 50\n", + "Turbine: 12MW_generic\n", + "\n", + "Site: {'depth': 900, 'distance': 100, 'distance_to_landfall': 100}\n" + ] + } + ], + "source": [ + "floating_config = load_config(\"configs/example_floating_project.yaml\")\n", + "\n", + "print(f\"Num turbines: {floating_config['plant']['num_turbines']}\")\n", + "print(f\"Turbine: {floating_config['turbine']}\")\n", + "print(f\"\\nSite: {floating_config['site']}\")" + ] + }, { - "data": { - "text/plain": [ - "{'Array System': 94.97179434403438,\n", - " 'Export System': 172.854128192,\n", - " 'Substructure': 1051.1827276666668,\n", - " 'Mooring System': 552.2987080136722,\n", - " 'Offshore Substation': 165.7985,\n", - " 'Array System Installation': 38.07421316011877,\n", - " 'Export System Installation': 225.18709674508716,\n", - " 'Substructure Installation': 130.9485334221207,\n", - " 'Mooring System Installation': 83.49086757990867,\n", - " 'Offshore Substation Installation': 9.165548186199898,\n", - " 'Turbine Installation': 212.89678462709279,\n", - " 'Turbine': 1300.0,\n", - " 'Soft': 645.0,\n", - " 'Project': 252.08333333333334}" + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Phases" ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "project.capex_breakdown_per_kw" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Installation Actions" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cost_multiplieragentactiondurationcostleveltimephaselocationsite_depthhub_heightphase_namemax_waveheightmax_windspeedtransit_speednum_vessels
00.5Array Cable Installation VesselMobilize72.0000001.800000e+05ACTION0.000000ArrayCableInstallationNaNNaNNaNNaNNaNNaNNaNNaN
10.5Export Cable Installation VesselMobilize72.0000001.800000e+05ACTION0.000000ExportCableInstallationNaNNaNNaNNaNNaNNaNNaNNaN
2NaNOnshore ConstructionOnshore Construction0.0000001.075454e+08ACTION0.000000ExportCableInstallationLandfallNaNNaNNaNNaNNaNNaNNaN
31.0Mooring System Installation VesselMobilize168.0000007.000000e+05ACTION0.000000MooringSystemInstallationNaNNaNNaNNaNNaNNaNNaNNaN
40.5Heavy Lift VesselMobilize72.0000007.500000e+05ACTION0.000000OffshoreSubstationInstallationNaNNaNNaNNaNNaNNaNNaNNaN
...................................................
4397NaNMulti-Purpose Support VesselConnect Mooring Lines, Pre-tension and pre-str...20.0000008.333333e+04ACTION8544.500000MooredSubInstallationNaNNaNNaNNaNNaNNaNNaNNaN
4398NaNMulti-Purpose Support VesselCheck Mooring Lines6.0000002.500000e+04ACTION8550.500000MooredSubInstallationNaNNaNNaNNaNNaNNaNNaNNaN
4399NaNTowing Group 1Positioning Support34.0000008.500000e+04ACTION8550.500000MooredSubInstallationsiteNaNNaNNaNNaNNaNNaN2.0
4400NaNMulti-Purpose Support VesselTransit10.0000004.166667e+04ACTION8560.500000MooredSubInstallationNaNNaNNaNNaNNaNNaNNaNNaN
4401NaNTowing Group 1Transit16.6666676.250000e+04ACTION8567.166667MooredSubInstallationNaNNaNNaNNaNNaNNaNNaN3.0
\n", - "

4402 rows Ă— 16 columns

\n", - "
" + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Design phases: ['ArraySystemDesign', 'ElectricalDesign', 'MooringSystemDesign', 'OffshoreFloatingSubstationDesign', 'SemiSubmersibleDesign']\n", + "\n", + "Install phases: ['ArrayCableInstallation', 'ExportCableInstallation', 'MooredSubInstallation', 'MooringSystemInstallation', 'FloatingSubstationInstallation']\n" + ] + } ], - "text/plain": [ - " cost_multiplier agent \\\n", - "0 0.5 Array Cable Installation Vessel \n", - "1 0.5 Export Cable Installation Vessel \n", - "2 NaN Onshore Construction \n", - "3 1.0 Mooring System Installation Vessel \n", - "4 0.5 Heavy Lift Vessel \n", - "... ... ... \n", - "4397 NaN Multi-Purpose Support Vessel \n", - "4398 NaN Multi-Purpose Support Vessel \n", - "4399 NaN Towing Group 1 \n", - "4400 NaN Multi-Purpose Support Vessel \n", - "4401 NaN Towing Group 1 \n", - "\n", - " action duration \\\n", - "0 Mobilize 72.000000 \n", - "1 Mobilize 72.000000 \n", - "2 Onshore Construction 0.000000 \n", - "3 Mobilize 168.000000 \n", - "4 Mobilize 72.000000 \n", - "... ... ... \n", - "4397 Connect Mooring Lines, Pre-tension and pre-str... 20.000000 \n", - "4398 Check Mooring Lines 6.000000 \n", - "4399 Positioning Support 34.000000 \n", - "4400 Transit 10.000000 \n", - "4401 Transit 16.666667 \n", - "\n", - " cost level time phase \\\n", - "0 1.800000e+05 ACTION 0.000000 ArrayCableInstallation \n", - "1 1.800000e+05 ACTION 0.000000 ExportCableInstallation \n", - "2 1.075454e+08 ACTION 0.000000 ExportCableInstallation \n", - "3 7.000000e+05 ACTION 0.000000 MooringSystemInstallation \n", - "4 7.500000e+05 ACTION 0.000000 OffshoreSubstationInstallation \n", - "... ... ... ... ... \n", - "4397 8.333333e+04 ACTION 8544.500000 MooredSubInstallation \n", - "4398 2.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", - "4399 8.500000e+04 ACTION 8550.500000 MooredSubInstallation \n", - "4400 4.166667e+04 ACTION 8560.500000 MooredSubInstallation \n", - "4401 6.250000e+04 ACTION 8567.166667 MooredSubInstallation \n", - "\n", - " location site_depth hub_height phase_name max_waveheight \\\n", - "0 NaN NaN NaN NaN NaN \n", - "1 NaN NaN NaN NaN NaN \n", - "2 Landfall NaN NaN NaN NaN \n", - "3 NaN NaN NaN NaN NaN \n", - "4 NaN NaN NaN NaN NaN \n", - "... ... ... ... ... ... \n", - "4397 NaN NaN NaN NaN NaN \n", - "4398 NaN NaN NaN NaN NaN \n", - "4399 site NaN NaN NaN NaN \n", - "4400 NaN NaN NaN NaN NaN \n", - "4401 NaN NaN NaN NaN NaN \n", - "\n", - " max_windspeed transit_speed num_vessels \n", - "0 NaN NaN NaN \n", - "1 NaN NaN NaN \n", - "2 NaN NaN NaN \n", - "3 NaN NaN NaN \n", - "4 NaN NaN NaN \n", - "... ... ... ... \n", - "4397 NaN NaN NaN \n", - "4398 NaN NaN NaN \n", - "4399 NaN NaN 2.0 \n", - "4400 NaN NaN NaN \n", - "4401 NaN NaN 3.0 \n", - "\n", - "[4402 rows x 16 columns]" + "source": [ + "print(f\"Design phases: {floating_config['design_phases']}\")\n", + "print(f\"\\nInstall phases: {list(floating_config['install_phases'].keys())}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ORBIT library intialized at '/Users/nriccobo/GitHub/ORBIT/library'\n", + "2\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "DeprecationWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:93\n", + "support_vessel will be deprecated and replaced with towing_vessels and ahts_vessel in the towing groups.\n", + "DeprecationWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:93\n", + "station_keeping_vessels will be deprecated and replaced with towing_vessels and ahts_vessels in the towing groups.\n" + ] + } + ], + "source": [ + "project = ProjectManager(floating_config, weather=weather)\n", + "project.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Top Level Outputs" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installation CapEx: 392 M\n", + "System CapEx: 1333 M\n", + "Turbine CapEx: 780 M\n", + "Soft CapEx: 387 M\n", + "Total CapEx: 3043 M\n", + "\n", + "Installation Time: 35527 h\n" + ] + } + ], + "source": [ + "print(f\"Installation CapEx: {project.installation_capex/1e6:.0f} M\")\n", + "print(f\"System CapEx: {project.system_capex/1e6:.0f} M\")\n", + "print(f\"Turbine CapEx: {project.turbine_capex/1e6:.0f} M\")\n", + "print(f\"Soft CapEx: {project.soft_capex/1e6:.0f} M\")\n", + "print(f\"Total CapEx: {project.total_capex/1e6:.0f} M\")\n", + "\n", + "print(f\"\\nInstallation Time: {project.installation_time:.0f} h\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### CapEx Breakdown" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Array System': 94.97179434403438,\n", + " 'Export System': 432.13532047999996,\n", + " 'Substructure': 1051.1827276666668,\n", + " 'Mooring System': 545.7798,\n", + " 'Offshore Substation': 97.56143656207396,\n", + " 'Array System Installation': 105.04624474280226,\n", + " 'Export System Installation': 246.79354615177581,\n", + " 'Substructure Installation': 208.2509277379141,\n", + " 'Mooring System Installation': 80.80888508371386,\n", + " 'Offshore Substation Installation': 11.784658802638255,\n", + " 'Turbine': 1300.0,\n", + " 'Soft': 645.0,\n", + " 'Project': 252.08333333333334}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "project.capex_breakdown_per_kw" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Installation Actions" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cost_multiplieragentactiondurationcostleveltimephaselocationphase_namemax_waveheightmax_windspeedtransit_speednum_vesselsnum_ahts_vessels
00.5Array Cable Installation VesselMobilize72.0000003.375000e+05ACTION0.000000ArrayCableInstallationNaNNaNNaNNaNNaNNaNNaN
10.5Export Cable Installation VesselMobilize72.0000003.375000e+05ACTION0.000000ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
2NaNOnshore ConstructionOnshore Construction0.0000001.665604e+06ACTION0.000000ExportCableInstallationLandfallNaNNaNNaNNaNNaNNaN
31.0Mooring System Installation VesselMobilize168.0000007.000000e+05ACTION0.000000MooringSystemInstallationNaNNaNNaNNaNNaNNaNNaN
4NaNSubstation Assembly Line 1Substation Substructure Assembly0.0000000.000000e+00ACTION0.000000FloatingSubstationInstallationNaNNaNNaNNaNNaNNaNNaN
................................................
2988NaNExport Cable Installation VesselPull In Cable5.5000005.156250e+04ACTION12017.280762ExportCableInstallationNaNExportCableInstallationNaNNaNNaNNaNNaN
2989NaNExport Cable Installation VesselTerminate Cable5.5000005.156250e+04ACTION12022.780762ExportCableInstallationNaNExportCableInstallationNaNNaNNaNNaNNaN
2990NaNExport Cable Installation VesselTransit8.0000007.500000e+04ACTION12030.780762ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
2991NaNExport Cable Installation VesselDelay26.0000002.437500e+05ACTION12056.780762ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
2992NaNExport Cable Installation VesselTransit0.6956526.521739e+03ACTION12057.476414ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
\n", + "

2993 rows \u00d7 15 columns

\n", + "
" + ], + "text/plain": [ + " cost_multiplier agent \\\n", + "0 0.5 Array Cable Installation Vessel \n", + "1 0.5 Export Cable Installation Vessel \n", + "2 NaN Onshore Construction \n", + "3 1.0 Mooring System Installation Vessel \n", + "4 NaN Substation Assembly Line 1 \n", + "... ... ... \n", + "2988 NaN Export Cable Installation Vessel \n", + "2989 NaN Export Cable Installation Vessel \n", + "2990 NaN Export Cable Installation Vessel \n", + "2991 NaN Export Cable Installation Vessel \n", + "2992 NaN Export Cable Installation Vessel \n", + "\n", + " action duration cost level \\\n", + "0 Mobilize 72.000000 3.375000e+05 ACTION \n", + "1 Mobilize 72.000000 3.375000e+05 ACTION \n", + "2 Onshore Construction 0.000000 1.665604e+06 ACTION \n", + "3 Mobilize 168.000000 7.000000e+05 ACTION \n", + "4 Substation Substructure Assembly 0.000000 0.000000e+00 ACTION \n", + "... ... ... ... ... \n", + "2988 Pull In Cable 5.500000 5.156250e+04 ACTION \n", + "2989 Terminate Cable 5.500000 5.156250e+04 ACTION \n", + "2990 Transit 8.000000 7.500000e+04 ACTION \n", + "2991 Delay 26.000000 2.437500e+05 ACTION \n", + "2992 Transit 0.695652 6.521739e+03 ACTION \n", + "\n", + " time phase location \\\n", + "0 0.000000 ArrayCableInstallation NaN \n", + "1 0.000000 ExportCableInstallation NaN \n", + "2 0.000000 ExportCableInstallation Landfall \n", + "3 0.000000 MooringSystemInstallation NaN \n", + "4 0.000000 FloatingSubstationInstallation NaN \n", + "... ... ... ... \n", + "2988 12017.280762 ExportCableInstallation NaN \n", + "2989 12022.780762 ExportCableInstallation NaN \n", + "2990 12030.780762 ExportCableInstallation NaN \n", + "2991 12056.780762 ExportCableInstallation NaN \n", + "2992 12057.476414 ExportCableInstallation NaN \n", + "\n", + " phase_name max_waveheight max_windspeed transit_speed \\\n", + "0 NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN \n", + "2 NaN NaN NaN NaN \n", + "3 NaN NaN NaN NaN \n", + "4 NaN NaN NaN NaN \n", + "... ... ... ... ... \n", + "2988 ExportCableInstallation NaN NaN NaN \n", + "2989 ExportCableInstallation NaN NaN NaN \n", + "2990 NaN NaN NaN NaN \n", + "2991 NaN NaN NaN NaN \n", + "2992 NaN NaN NaN NaN \n", + "\n", + " num_vessels num_ahts_vessels \n", + "0 NaN NaN \n", + "1 NaN NaN \n", + "2 NaN NaN \n", + "3 NaN NaN \n", + "4 NaN NaN \n", + "... ... ... \n", + "2988 NaN NaN \n", + "2989 NaN NaN \n", + "2990 NaN NaN \n", + "2991 NaN NaN \n", + "2992 NaN NaN \n", + "\n", + "[2993 rows x 15 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.DataFrame(project.actions)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'deck_space': 1,\n", + " 'length': 0,\n", + " 'mass': 1192.0,\n", + " 'type': 'Floating',\n", + " 'unit_cost': 3576000.0}\n", + "{'anchor_cost': 139426.2,\n", + " 'anchor_mass': 20,\n", + " 'anchor_type': 'Drag Embedment',\n", + " 'line_cost': 1497913.2,\n", + " 'line_diam': 0.15,\n", + " 'line_length': 2255.71,\n", + " 'line_mass': 579.8762530880001,\n", + " 'mooring_type': 'SemiTaut',\n", + " 'num_lines': 4,\n", + " 'system_cost': 327467880.0}\n", + "'Mooring System: $/kW'\n", + "545.7798\n", + "80.80888508371386\n" + ] + } + ], + "source": [ + "pprint(project.design_results[\"offshore_substation_substructure\"])\n", + "pprint(project.design_results[\"mooring_system\"])\n", + "\n", + "pprint(\"Mooring System: $/kW\")\n", + "pprint(project.capex_breakdown_per_kw['Mooring System'])\n", + "\n", + "pprint(project.capex_breakdown_per_kw['Mooring System Installation'])" ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" } - ], - "source": [ - "pd.DataFrame(project.actions)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.8.18" + } }, - "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.9.15" - } - }, - "nbformat": 4, - "nbformat_minor": 4 + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/examples/configs/example_floating_project.yaml b/examples/configs/example_floating_project.yaml index baad61c0..36769569 100644 --- a/examples/configs/example_floating_project.yaml +++ b/examples/configs/example_floating_project.yaml @@ -19,6 +19,7 @@ export_cable_install_vessel: example_cable_lay_vessel mooring_install_vessel: example_support_vessel oss_install_vessel: floating_heavy_lift_vessel support_vessel: example_support_vessel +ahts_vessel: example_ahts_vessel towing_vessel: example_towing_vessel towing_vessel_groups: station_keeping_vessels: 2 @@ -27,8 +28,11 @@ wtiv: floating_heavy_lift_vessel # Module Specific substructure: takt_time: 168 -OffshoreSubstationInstallation: - feeder: floating_barge +substation_design: + oss_substructure_type: Floating +mooring_system_design: + anchor_type: Drag Embedment + mooring_type: SemiTaut array_system: free_cable_length: 0.5 array_system_design: @@ -40,16 +44,18 @@ export_system_design: # Configured Phases design_phases: - ArraySystemDesign -- ExportSystemDesign +#- ExportSystemDesign +- ElectricalDesign - MooringSystemDesign -- OffshoreSubstationDesign +#- SemiTautMooringSystemDesign +- OffshoreFloatingSubstationDesign - SemiSubmersibleDesign install_phases: ArrayCableInstallation: 0 ExportCableInstallation: 0 MooredSubInstallation: 0 MooringSystemInstallation: 0 - OffshoreSubstationInstallation: 0 - TurbineInstallation: 0 + FloatingSubstationInstallation: 0 +# TurbineInstallation: 0 # Project Inputs -turbine: 12MW_generic +turbine: 15MW_generic From adc16712b15b6e687bde16706b5949806a638dd3 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Mon, 3 Jun 2024 11:39:25 -0600 Subject: [PATCH 55/71] cleaned up fixed added length for semitaut. Updated test --- ORBIT/phases/design/mooring_system_design.py | 15 ++++++---- .../design/test_mooring_system_design.py | 29 ++++++++++++++++++- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index 1fb11678..bda8cb8b 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -104,25 +104,29 @@ def determine_mooring_line(self): TODO: Add TLP option and consider merging SemiTaut interp here """ - _design = self.config.get("mooring_system_design", {}) - tr = self.config["turbine"]["turbine_rating"] fit = -0.0004 * (tr**2) + 0.0132 * tr + 0.0536 if fit <= 0.09: self.line_diam = 0.09 self.line_mass_per_m = 0.161 - self.line_cost_rate = _design.get("mooring_line_cost_rate", 399.0) + self.line_cost_rate = self._design.get( + "mooring_line_cost_rate", 399.0 + ) elif fit <= 0.12: self.line_diam = 0.12 self.line_mass_per_m = 0.288 - self.line_cost_rate = _design.get("mooring_line_cost_rate", 721.0) + self.line_cost_rate = self._design.get( + "mooring_line_cost_rate", 721.0 + ) else: self.line_diam = 0.15 self.line_mass_per_m = 0.450 - self.line_cost_rate = _design.get("mooring_line_cost_rate", 1088.0) + self.line_cost_rate = self._design.get( + "mooring_line_cost_rate", 1088.0 + ) def calculate_breaking_load(self): """ @@ -176,6 +180,7 @@ def calculate_line_length_mass(self): fill_value="extrapolate", )(self.depth).item() + fixed = self._design.get("drag_embedment_fixed_length", 0) self.line_length = self.rope_length + self.chain_length + fixed chain_mass_per_m = ( diff --git a/tests/phases/design/test_mooring_system_design.py b/tests/phases/design/test_mooring_system_design.py index cd4261e2..93fb714b 100644 --- a/tests/phases/design/test_mooring_system_design.py +++ b/tests/phases/design/test_mooring_system_design.py @@ -12,7 +12,7 @@ from ORBIT.phases.design import ( MooringSystemDesign, - SemiTaut_mooring_system_design, + SemiTautMooringSystemDesign, ) base = { @@ -167,3 +167,30 @@ def test_custom_num_lines(): m.run() assert m.design_result["mooring_system"]["num_lines"] == 5 + + +def test_new_old_semitaut_mooring_system(): + """Temporary test until we delete the SemiTaut_mooring_system""" + + config = deepcopy(base) + config["site"]["depth"] = 900.0 + config["mooring_system_design"]["mooring_type"] = "SemiTaut" + config["mooring_system_design"]["anchor_type"] = "Drag Embedment" + + old = SemiTautMooringSystemDesign(config) + old.run() + old_anchor_cost = old.anchor_cost.item() + old_line_cost = old.line_cost.item() + + new = MooringSystemDesign(config) + new.run() + + # same values + assert old.total_cost == new.total_cost + assert old_anchor_cost == new.anchor_cost + assert old.anchor_mass == new.anchor_mass + assert old_line_cost == new.line_cost + assert old.line_length == new.line_length + + # different values + assert len(old.detailed_output) != len(new.detailed_output) From 959e46b9efaf3db8f335249089caafa62fc4aadc Mon Sep 17 00:00:00 2001 From: nriccobo Date: Mon, 3 Jun 2024 13:27:17 -0600 Subject: [PATCH 56/71] Updated yaml configs and example notebooks --- ...5. Example Floating Project-SemiTaut.ipynb | 1229 +++++++++-------- examples/5. Example Floating Project.ipynb | 27 +- .../configs/example_floating_project.yaml | 2 +- .../example_floating_project_SemiTaut.yaml | 2 + 4 files changed, 639 insertions(+), 621 deletions(-) diff --git a/examples/5. Example Floating Project-SemiTaut.ipynb b/examples/5. Example Floating Project-SemiTaut.ipynb index edf2b103..d3090455 100644 --- a/examples/5. Example Floating Project-SemiTaut.ipynb +++ b/examples/5. Example Floating Project-SemiTaut.ipynb @@ -1,627 +1,642 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Jake Nunemaker\n", - "\n", - "National Renewable Energy Lab\n", - "\n", - "Last updated: 12/23/2020" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ + "cells": [ { - "name": "stderr", - "output_type": "stream", - "text": [ - "UserWarning: /var/folders/90/1lkt657x3n1cw5x65j3lfgd5406fb8/T/ipykernel_93742/1311156483.py:7\n", - "Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format." - ] - } - ], - "source": [ - "import os\n", - "import pandas as pd\n", - "from ORBIT import ProjectManager, load_config\n", - "\n", - "import warnings\n", - "warnings.filterwarnings(\"default\")\n", - "weather = pd.read_csv(\"data/example_weather.csv\", parse_dates=[\"datetime\"])\\\n", - " .set_index(\"datetime\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Load the project configuration" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "Num turbines: 50\n", - "Turbine: 12MW_generic\n", - "\n", - "Site: {'depth': 900, 'distance': 100, 'distance_to_landfall': 100}\n" - ] - } - ], - "source": [ - "fixed_config = load_config(\"configs/example_floating_project_SemiTaut.yaml\")\n", - "\n", - "print(f\"Num turbines: {fixed_config['plant']['num_turbines']}\")\n", - "print(f\"Turbine: {fixed_config['turbine']}\")\n", - "print(f\"\\nSite: {fixed_config['site']}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Phases" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Jake Nunemaker\n", + "\n", + "National Renewable Energy Lab\n", + "\n", + "Last updated: 12/23/2020" + ] + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "Design phases: ['ArraySystemDesign', 'ElectricalDesign', 'SemiTautMooringSystemDesign', 'SemiSubmersibleDesign']\n", - "\n", - "Install phases: ['ArrayCableInstallation', 'ExportCableInstallation', 'MooredSubInstallation', 'MooringSystemInstallation', 'FloatingSubstationInstallation']\n" - ] - } - ], - "source": [ - "print(f\"Design phases: {fixed_config['design_phases']}\")\n", - "print(f\"\\nInstall phases: {list(fixed_config['install_phases'].keys())}\")\n", - "# This now says \"SemiTautMooringSystemDesign\" in the design phases" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Run" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "UserWarning: /var/folders/90/1lkt657x3n1cw5x65j3lfgd5406fb8/T/ipykernel_31846/3472246521.py:7\n", + "Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format." + ] + } + ], + "source": [ + "import pandas as pd\n", + "from pprint import pprint\n", + "from ORBIT import ProjectManager, load_config\n", + "\n", + "import warnings\n", + "warnings.filterwarnings(\"default\")\n", + "weather = pd.read_csv(\"data/example_weather.csv\", parse_dates=[\"datetime\"])\\\n", + " .set_index(\"datetime\")" + ] + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "2\n" - ] + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load the project configuration" + ] }, { - "name": "stderr", - "output_type": "stream", - "text": [ - "UserWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:193\n", - "No ['ahts_vessel'] specified. num_ahts set to 0. ahts_vessel will be required in future releases.\n", - "DeprecationWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:93\n", - "support_vessel will be deprecated and replaced with towing_vessels and ahts_vessel in the towing groups.\n", - "DeprecationWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:93\n", - "station_keeping_vessels will be deprecated and replaced with towing_vessels and ahts_vessels in the towing groups.\n" - ] - } - ], - "source": [ - "project = ProjectManager(fixed_config, weather=weather)\n", - "project.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Top Level Outputs" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Num turbines: 50\n", + "Turbine: 12MW_generic\n", + "\n", + "Site: {'depth': 900, 'distance': 100, 'distance_to_landfall': 100}\n" + ] + } + ], + "source": [ + "fixed_config = load_config(\"configs/example_floating_project_SemiTaut.yaml\")\n", + "\n", + "print(f\"Num turbines: {fixed_config['plant']['num_turbines']}\")\n", + "print(f\"Turbine: {fixed_config['turbine']}\")\n", + "print(f\"\\nSite: {fixed_config['site']}\")" + ] + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "Installation CapEx: 345 M\n", - "System CapEx: 1333 M\n", - "Turbine CapEx: 780 M\n", - "Soft CapEx: 387 M\n", - "Total CapEx: 2997 M\n", - "\n", - "Installation Time: 35527 h\n" - ] - } - ], - "source": [ - "print(f\"Installation CapEx: {project.installation_capex/1e6:.0f} M\")\n", - "print(f\"System CapEx: {project.system_capex/1e6:.0f} M\")\n", - "print(f\"Turbine CapEx: {project.turbine_capex/1e6:.0f} M\")\n", - "print(f\"Soft CapEx: {project.soft_capex/1e6:.0f} M\")\n", - "print(f\"Total CapEx: {project.total_capex/1e6:.0f} M\")\n", - "\n", - "print(f\"\\nInstallation Time: {project.installation_time:.0f} h\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### CapEx Breakdown" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Phases" + ] + }, { - "data": { - "text/plain": [ - "{'Array System': 56983076.60642063,\n", - " 'Export System': 259281192.288,\n", - " 'Substructure': 630709636.6,\n", - " 'Mooring System': 327467880.0,\n", - " 'Offshore Substation': 58536861.93724438,\n", - " 'Array System Installation': 63027746.845681354,\n", - " 'Export System Installation': 148076127.6910655,\n", - " 'Substructure Installation': 78801350.29354209,\n", - " 'Mooring System Installation': 48485331.05022831,\n", - " 'Offshore Substation Installation': 7070795.281582953,\n", - " 'Turbine': 780000000,\n", - " 'Soft': 387000000,\n", - " 'Project': 151250000.0}" + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Design phases: ['ArraySystemDesign', 'ElectricalDesign', 'SemiTautMooringSystemDesign', 'SemiSubmersibleDesign']\n", + "\n", + "Install phases: ['ArrayCableInstallation', 'ExportCableInstallation', 'MooredSubInstallation', 'MooringSystemInstallation', 'FloatingSubstationInstallation']\n" + ] + } + ], + "source": [ + "print(f\"Design phases: {fixed_config['design_phases']}\")\n", + "print(f\"\\nInstall phases: {list(fixed_config['install_phases'].keys())}\")\n", + "# This now says \"SemiTautMooringSystemDesign\" in the design phases" ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "project.capex_breakdown" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ + }, { - "data": { - "text/plain": [ - "{'Array System': 94.97179434403438,\n", - " 'Export System': 432.13532047999996,\n", - " 'Substructure': 1051.1827276666668,\n", - " 'Mooring System': 545.7798,\n", - " 'Offshore Substation': 97.56143656207396,\n", - " 'Array System Installation': 105.04624474280226,\n", - " 'Export System Installation': 246.79354615177581,\n", - " 'Substructure Installation': 131.33558382257016,\n", - " 'Mooring System Installation': 80.80888508371386,\n", - " 'Offshore Substation Installation': 11.784658802638255,\n", - " 'Turbine': 1300.0,\n", - " 'Soft': 645.0,\n", - " 'Project': 252.08333333333334}" + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run" ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "project.capex_breakdown_per_kw" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Installation Actions" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ + }, { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
cost_multiplieragentactiondurationcostleveltimephaselocationphase_namemax_waveheightmax_windspeedtransit_speednum_vesselsnum_ahts_vessels
00.5Array Cable Installation VesselMobilize72.0000003.375000e+05ACTION0.000000ArrayCableInstallationNaNNaNNaNNaNNaNNaNNaN
10.5Export Cable Installation VesselMobilize72.0000003.375000e+05ACTION0.000000ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
2NaNOnshore ConstructionOnshore Construction0.0000001.665604e+06ACTION0.000000ExportCableInstallationLandfallNaNNaNNaNNaNNaNNaN
31.0Mooring System Installation VesselMobilize168.0000007.000000e+05ACTION0.000000MooringSystemInstallationNaNNaNNaNNaNNaNNaNNaN
4NaNSubstation Assembly Line 1Substation Substructure Assembly0.0000000.000000e+00ACTION0.000000FloatingSubstationInstallationNaNNaNNaNNaNNaNNaNNaN
................................................
2988NaNExport Cable Installation VesselPull In Cable5.5000005.156250e+04ACTION12017.280762ExportCableInstallationNaNExportCableInstallationNaNNaNNaNNaNNaN
2989NaNExport Cable Installation VesselTerminate Cable5.5000005.156250e+04ACTION12022.780762ExportCableInstallationNaNExportCableInstallationNaNNaNNaNNaNNaN
2990NaNExport Cable Installation VesselTransit8.0000007.500000e+04ACTION12030.780762ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
2991NaNExport Cable Installation VesselDelay26.0000002.437500e+05ACTION12056.780762ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
2992NaNExport Cable Installation VesselTransit0.6956526.521739e+03ACTION12057.476414ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
\n", - "

2993 rows Ă— 15 columns

\n", - "
" + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "UserWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:193\n", + "No ['ahts_vessel'] specified. num_ahts set to 0. ahts_vessel will be required in future releases.\n", + "DeprecationWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:93\n", + "support_vessel will be deprecated and replaced with towing_vessels and ahts_vessel in the towing groups.\n", + "DeprecationWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:93\n", + "station_keeping_vessels will be deprecated and replaced with towing_vessels and ahts_vessels in the towing groups.\n" + ] + } ], - "text/plain": [ - " cost_multiplier agent \\\n", - "0 0.5 Array Cable Installation Vessel \n", - "1 0.5 Export Cable Installation Vessel \n", - "2 NaN Onshore Construction \n", - "3 1.0 Mooring System Installation Vessel \n", - "4 NaN Substation Assembly Line 1 \n", - "... ... ... \n", - "2988 NaN Export Cable Installation Vessel \n", - "2989 NaN Export Cable Installation Vessel \n", - "2990 NaN Export Cable Installation Vessel \n", - "2991 NaN Export Cable Installation Vessel \n", - "2992 NaN Export Cable Installation Vessel \n", - "\n", - " action duration cost level \\\n", - "0 Mobilize 72.000000 3.375000e+05 ACTION \n", - "1 Mobilize 72.000000 3.375000e+05 ACTION \n", - "2 Onshore Construction 0.000000 1.665604e+06 ACTION \n", - "3 Mobilize 168.000000 7.000000e+05 ACTION \n", - "4 Substation Substructure Assembly 0.000000 0.000000e+00 ACTION \n", - "... ... ... ... ... \n", - "2988 Pull In Cable 5.500000 5.156250e+04 ACTION \n", - "2989 Terminate Cable 5.500000 5.156250e+04 ACTION \n", - "2990 Transit 8.000000 7.500000e+04 ACTION \n", - "2991 Delay 26.000000 2.437500e+05 ACTION \n", - "2992 Transit 0.695652 6.521739e+03 ACTION \n", - "\n", - " time phase location \\\n", - "0 0.000000 ArrayCableInstallation NaN \n", - "1 0.000000 ExportCableInstallation NaN \n", - "2 0.000000 ExportCableInstallation Landfall \n", - "3 0.000000 MooringSystemInstallation NaN \n", - "4 0.000000 FloatingSubstationInstallation NaN \n", - "... ... ... ... \n", - "2988 12017.280762 ExportCableInstallation NaN \n", - "2989 12022.780762 ExportCableInstallation NaN \n", - "2990 12030.780762 ExportCableInstallation NaN \n", - "2991 12056.780762 ExportCableInstallation NaN \n", - "2992 12057.476414 ExportCableInstallation NaN \n", - "\n", - " phase_name max_waveheight max_windspeed transit_speed \\\n", - "0 NaN NaN NaN NaN \n", - "1 NaN NaN NaN NaN \n", - "2 NaN NaN NaN NaN \n", - "3 NaN NaN NaN NaN \n", - "4 NaN NaN NaN NaN \n", - "... ... ... ... ... \n", - "2988 ExportCableInstallation NaN NaN NaN \n", - "2989 ExportCableInstallation NaN NaN NaN \n", - "2990 NaN NaN NaN NaN \n", - "2991 NaN NaN NaN NaN \n", - "2992 NaN NaN NaN NaN \n", - "\n", - " num_vessels num_ahts_vessels \n", - "0 NaN NaN \n", - "1 NaN NaN \n", - "2 NaN NaN \n", - "3 NaN NaN \n", - "4 NaN NaN \n", - "... ... ... \n", - "2988 NaN NaN \n", - "2989 NaN NaN \n", - "2990 NaN NaN \n", - "2991 NaN NaN \n", - "2992 NaN NaN \n", - "\n", - "[2993 rows x 15 columns]" + "source": [ + "project = ProjectManager(fixed_config, weather=weather)\n", + "project.run()" ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "pd.DataFrame(project.actions)" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Top Level Outputs" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installation CapEx: 345 M\n", + "System CapEx: 1333 M\n", + "Turbine CapEx: 780 M\n", + "Soft CapEx: 387 M\n", + "Total CapEx: 2997 M\n", + "\n", + "Installation Time: 35527 h\n" + ] + } + ], + "source": [ + "print(f\"Installation CapEx: {project.installation_capex/1e6:.0f} M\")\n", + "print(f\"System CapEx: {project.system_capex/1e6:.0f} M\")\n", + "print(f\"Turbine CapEx: {project.turbine_capex/1e6:.0f} M\")\n", + "print(f\"Soft CapEx: {project.soft_capex/1e6:.0f} M\")\n", + "print(f\"Total CapEx: {project.total_capex/1e6:.0f} M\")\n", + "\n", + "print(f\"\\nInstallation Time: {project.installation_time:.0f} h\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### CapEx Breakdown" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Array System': 56983076.60642063,\n", + " 'Export System': 259281192.288,\n", + " 'Substructure': 630709636.6,\n", + " 'Mooring System': 327467880.0,\n", + " 'Offshore Substation': 58536861.93724438,\n", + " 'Array System Installation': 63027746.845681354,\n", + " 'Export System Installation': 148076127.6910655,\n", + " 'Substructure Installation': 78801350.29354209,\n", + " 'Mooring System Installation': 48485331.05022831,\n", + " 'Offshore Substation Installation': 7070795.281582953,\n", + " 'Turbine': 780000000,\n", + " 'Soft': 387000000,\n", + " 'Project': 151250000.0}" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "project.capex_breakdown" + ] + }, { - "data": { - "text/plain": [ - "{'type': 'Monopile',\n", - " 'deck_space': 1,\n", - " 'mass': 1606.7690784724548,\n", - " 'length': 910,\n", - " 'unit_cost': 3576000.0}" + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Array System': 94.97179434403438,\n", + " 'Export System': 432.13532047999996,\n", + " 'Substructure': 1051.1827276666668,\n", + " 'Mooring System': 545.7798,\n", + " 'Offshore Substation': 97.56143656207396,\n", + " 'Array System Installation': 105.04624474280226,\n", + " 'Export System Installation': 246.79354615177581,\n", + " 'Substructure Installation': 131.33558382257016,\n", + " 'Mooring System Installation': 80.80888508371386,\n", + " 'Offshore Substation Installation': 11.784658802638255,\n", + " 'Turbine': 1300.0,\n", + " 'Soft': 645.0,\n", + " 'Project': 252.08333333333334}" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "project.capex_breakdown_per_kw" ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Installation Actions" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cost_multiplieragentactiondurationcostleveltimephaselocationphase_namemax_waveheightmax_windspeedtransit_speednum_vesselsnum_ahts_vessels
00.5Array Cable Installation VesselMobilize72.0000003.375000e+05ACTION0.000000ArrayCableInstallationNaNNaNNaNNaNNaNNaNNaN
10.5Export Cable Installation VesselMobilize72.0000003.375000e+05ACTION0.000000ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
2NaNOnshore ConstructionOnshore Construction0.0000001.665604e+06ACTION0.000000ExportCableInstallationLandfallNaNNaNNaNNaNNaNNaN
31.0Mooring System Installation VesselMobilize168.0000007.000000e+05ACTION0.000000MooringSystemInstallationNaNNaNNaNNaNNaNNaNNaN
4NaNSubstation Assembly Line 1Substation Substructure Assembly0.0000000.000000e+00ACTION0.000000FloatingSubstationInstallationNaNNaNNaNNaNNaNNaNNaN
................................................
2988NaNExport Cable Installation VesselPull In Cable5.5000005.156250e+04ACTION12017.280762ExportCableInstallationNaNExportCableInstallationNaNNaNNaNNaNNaN
2989NaNExport Cable Installation VesselTerminate Cable5.5000005.156250e+04ACTION12022.780762ExportCableInstallationNaNExportCableInstallationNaNNaNNaNNaNNaN
2990NaNExport Cable Installation VesselTransit8.0000007.500000e+04ACTION12030.780762ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
2991NaNExport Cable Installation VesselDelay26.0000002.437500e+05ACTION12056.780762ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
2992NaNExport Cable Installation VesselTransit0.6956526.521739e+03ACTION12057.476414ExportCableInstallationNaNNaNNaNNaNNaNNaNNaN
\n", + "

2993 rows \u00d7 15 columns

\n", + "
" + ], + "text/plain": [ + " cost_multiplier agent \\\n", + "0 0.5 Array Cable Installation Vessel \n", + "1 0.5 Export Cable Installation Vessel \n", + "2 NaN Onshore Construction \n", + "3 1.0 Mooring System Installation Vessel \n", + "4 NaN Substation Assembly Line 1 \n", + "... ... ... \n", + "2988 NaN Export Cable Installation Vessel \n", + "2989 NaN Export Cable Installation Vessel \n", + "2990 NaN Export Cable Installation Vessel \n", + "2991 NaN Export Cable Installation Vessel \n", + "2992 NaN Export Cable Installation Vessel \n", + "\n", + " action duration cost level \\\n", + "0 Mobilize 72.000000 3.375000e+05 ACTION \n", + "1 Mobilize 72.000000 3.375000e+05 ACTION \n", + "2 Onshore Construction 0.000000 1.665604e+06 ACTION \n", + "3 Mobilize 168.000000 7.000000e+05 ACTION \n", + "4 Substation Substructure Assembly 0.000000 0.000000e+00 ACTION \n", + "... ... ... ... ... \n", + "2988 Pull In Cable 5.500000 5.156250e+04 ACTION \n", + "2989 Terminate Cable 5.500000 5.156250e+04 ACTION \n", + "2990 Transit 8.000000 7.500000e+04 ACTION \n", + "2991 Delay 26.000000 2.437500e+05 ACTION \n", + "2992 Transit 0.695652 6.521739e+03 ACTION \n", + "\n", + " time phase location \\\n", + "0 0.000000 ArrayCableInstallation NaN \n", + "1 0.000000 ExportCableInstallation NaN \n", + "2 0.000000 ExportCableInstallation Landfall \n", + "3 0.000000 MooringSystemInstallation NaN \n", + "4 0.000000 FloatingSubstationInstallation NaN \n", + "... ... ... ... \n", + "2988 12017.280762 ExportCableInstallation NaN \n", + "2989 12022.780762 ExportCableInstallation NaN \n", + "2990 12030.780762 ExportCableInstallation NaN \n", + "2991 12056.780762 ExportCableInstallation NaN \n", + "2992 12057.476414 ExportCableInstallation NaN \n", + "\n", + " phase_name max_waveheight max_windspeed transit_speed \\\n", + "0 NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN \n", + "2 NaN NaN NaN NaN \n", + "3 NaN NaN NaN NaN \n", + "4 NaN NaN NaN NaN \n", + "... ... ... ... ... \n", + "2988 ExportCableInstallation NaN NaN NaN \n", + "2989 ExportCableInstallation NaN NaN NaN \n", + "2990 NaN NaN NaN NaN \n", + "2991 NaN NaN NaN NaN \n", + "2992 NaN NaN NaN NaN \n", + "\n", + " num_vessels num_ahts_vessels \n", + "0 NaN NaN \n", + "1 NaN NaN \n", + "2 NaN NaN \n", + "3 NaN NaN \n", + "4 NaN NaN \n", + "... ... ... \n", + "2988 NaN NaN \n", + "2989 NaN NaN \n", + "2990 NaN NaN \n", + "2991 NaN NaN \n", + "2992 NaN NaN \n", + "\n", + "[2993 rows x 15 columns]" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.DataFrame(project.actions)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'deck_space': 1,\n", + " 'length': 0,\n", + " 'mass': 1192.0,\n", + " 'type': 'Floating',\n", + " 'unit_cost': 3576000.0}\n", + "{'deck_space': 1, 'mass': 2980.0, 'unit_cost': 48411504.33724438}\n", + "{'anchor_cost': array(139426.2),\n", + " 'anchor_mass': 20,\n", + " 'anchor_type': 'Drag Embedment',\n", + " 'line_cost': array(1497913.2),\n", + " 'line_length': 1755.71,\n", + " 'line_mass': 579.8762530880001,\n", + " 'num_lines': 4,\n", + " 'system_cost': 327467880.0}\n", + "'Mooring System: $/kW'\n", + "545.7798\n", + "80.80888508371386\n" + ] + } + ], + "source": [ + "pprint(project.design_results[\"offshore_substation_substructure\"])\n", + "pprint(project.design_results[\"offshore_substation_topside\"])\n", + "pprint(project.design_results[\"mooring_system\"])\n", + "\n", + "pprint(\"Mooring System: $/kW\")\n", + "pprint(project.capex_breakdown_per_kw['Mooring System'])\n", + "pprint(project.capex_breakdown_per_kw['Mooring System Installation'])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.8.18" } - ], - "source": [ - "project.design_results[\"offshore_substation_substructure\"]" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.8.18" - } - }, - "nbformat": 4, - "nbformat_minor": 4 + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/examples/5. Example Floating Project.ipynb b/examples/5. Example Floating Project.ipynb index 7513d223..09b98d0b 100644 --- a/examples/5. Example Floating Project.ipynb +++ b/examples/5. Example Floating Project.ipynb @@ -13,14 +13,14 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "UserWarning: /var/folders/90/1lkt657x3n1cw5x65j3lfgd5406fb8/T/ipykernel_74288/2795185578.py:8\n", + "UserWarning: /var/folders/90/1lkt657x3n1cw5x65j3lfgd5406fb8/T/ipykernel_32264/2795185578.py:8\n", "Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format." ] } @@ -47,7 +47,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 27, "metadata": {}, "outputs": [ { @@ -78,7 +78,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 28, "metadata": {}, "outputs": [ { @@ -105,14 +105,13 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "ORBIT library intialized at '/Users/nriccobo/GitHub/ORBIT/library'\n", "2\n" ] }, @@ -141,7 +140,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 30, "metadata": {}, "outputs": [ { @@ -177,7 +176,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 31, "metadata": {}, "outputs": [ { @@ -198,7 +197,7 @@ " 'Project': 252.08333333333334}" ] }, - "execution_count": 6, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -216,7 +215,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 32, "metadata": {}, "outputs": [ { @@ -530,7 +529,7 @@ "[2993 rows x 15 columns]" ] }, - "execution_count": 7, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -541,7 +540,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 33, "metadata": {}, "outputs": [ { @@ -553,12 +552,13 @@ " 'mass': 1192.0,\n", " 'type': 'Floating',\n", " 'unit_cost': 3576000.0}\n", + "{'deck_space': 1, 'mass': 2980.0, 'unit_cost': 48411504.33724438}\n", "{'anchor_cost': 139426.2,\n", " 'anchor_mass': 20,\n", " 'anchor_type': 'Drag Embedment',\n", " 'line_cost': 1497913.2,\n", " 'line_diam': 0.15,\n", - " 'line_length': 2255.71,\n", + " 'line_length': 1755.71,\n", " 'line_mass': 579.8762530880001,\n", " 'mooring_type': 'SemiTaut',\n", " 'num_lines': 4,\n", @@ -571,6 +571,7 @@ ], "source": [ "pprint(project.design_results[\"offshore_substation_substructure\"])\n", + "pprint(project.design_results[\"offshore_substation_topside\"])\n", "pprint(project.design_results[\"mooring_system\"])\n", "\n", "pprint(\"Mooring System: $/kW\")\n", diff --git a/examples/configs/example_floating_project.yaml b/examples/configs/example_floating_project.yaml index 36769569..e7d23af8 100644 --- a/examples/configs/example_floating_project.yaml +++ b/examples/configs/example_floating_project.yaml @@ -58,4 +58,4 @@ install_phases: FloatingSubstationInstallation: 0 # TurbineInstallation: 0 # Project Inputs -turbine: 15MW_generic +turbine: 12MW_generic diff --git a/examples/configs/example_floating_project_SemiTaut.yaml b/examples/configs/example_floating_project_SemiTaut.yaml index c0890c62..cba486b6 100644 --- a/examples/configs/example_floating_project_SemiTaut.yaml +++ b/examples/configs/example_floating_project_SemiTaut.yaml @@ -29,6 +29,8 @@ wtiv: floating_heavy_lift_vessel # Module Specific substructure: takt_time: 168 +substation_design: + oss_substructure_type: Floating array_system: free_cable_length: 0.5 array_system_design: From f628d04e02173370346bd89c3a70049280fb2bbb Mon Sep 17 00:00:00 2001 From: nriccobo Date: Mon, 3 Jun 2024 15:11:11 -0600 Subject: [PATCH 57/71] Updated moored deprecated warnings and a test --- .../install/quayside_assembly_tow/moored.py | 19 ++++++++-------- .../quayside_assembly_tow/test_moored.py | 22 ++++++++++++++++++- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index 31618768..e4d8d752 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -28,12 +28,12 @@ class MooredSubInstallation(InstallPhase): #: expected_config = { - "support_vessel": "str", - "ahts_vessel": "str, (optional)", + "support_vessel": "str, (optional)", + "ahts_vessel": "str", "towing_vessel": "str", "towing_vessel_groups": { "towing_vessels": "int", - "station_keeping_vessels": "int", + "station_keeping_vessels": "int (optional)", "ahts_vessels": "int (optional, default: 1)", "num_groups": "int (optional)", }, @@ -234,7 +234,7 @@ def initialize_support_vessel(self): processes at site. """ - specs = self.config["support_vessel"] + specs = self.config.get("support_vessel", None) if specs is not None: warn( @@ -251,15 +251,16 @@ def initialize_support_vessel(self): # vessel.initialize(mobilize=False) # self.support_vessel = vessel - station_keeping_vessels = self.config["towing_vessel_groups"][ - "station_keeping_vessels" - ] + station_keeping_vessels = self.config["towing_vessel_groups"].get( + "station_keeping_vessels", None + ) if station_keeping_vessels is not None: print(station_keeping_vessels) warn( - "station_keeping_vessels will be deprecated and replaced with" - " towing_vessels and ahts_vessels in the towing groups.\n", + "['towing_vessl_groups]['station_keeping_vessels']" + " will be deprecated and replaced with" + " ['towing_vessl_groups]['ahts_vessels'].\n", DeprecationWarning, stacklevel=2, ) diff --git a/tests/phases/install/quayside_assembly_tow/test_moored.py b/tests/phases/install/quayside_assembly_tow/test_moored.py index c2ebba3f..3892495b 100644 --- a/tests/phases/install/quayside_assembly_tow/test_moored.py +++ b/tests/phases/install/quayside_assembly_tow/test_moored.py @@ -5,6 +5,8 @@ __maintainer__ = "Jake Nunemaker" __email__ = "jake.nunemaker@nrel.gov" +import warnings +from copy import deepcopy import pandas as pd import pytest @@ -14,6 +16,8 @@ from ORBIT.phases.install import MooredSubInstallation config = extract_library_specs("config", "moored_install") +no_supply = extract_library_specs("config", "moored_install_no_supply") + multi_assembly = extract_library_specs( "config", "moored_install_multi_assembly" ) @@ -21,7 +25,6 @@ multi_assembly_multi_tow = extract_library_specs( "config", "moored_install_multi_assembly_multi_tow" ) -no_supply = extract_library_specs("config", "moored_install_no_supply") def test_simulation_setup(): @@ -75,3 +78,20 @@ def test_for_complete_logging(weather, config): [a for a in sim.env.actions if a["action"] == "Position Substructure"] ) assert installed_mooring_lines == sim.num_turbines + + +def test_deprecated_landfall(): + + deprecated = deepcopy(config) + deprecated["support_vessel"] = "test_support_vessel" + + with pytest.deprecated_call(): + sim = MooredSubInstallation(deprecated) + sim.run() + + deprecated2 = deepcopy(config) + deprecated2["towing_vessel_groups"]["station_keeping_vessels"] = 2 + + with pytest.deprecated_call(): + sim = MooredSubInstallation(deprecated2) + sim.run() From 909ee373fd8b2b10f3745524e7c3de97190f6bd6 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Tue, 4 Jun 2024 10:26:06 -0600 Subject: [PATCH 58/71] WISDEM api test failed because of new ahts vessel logic. --- ORBIT/api/wisdem.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ORBIT/api/wisdem.py b/ORBIT/api/wisdem.py index f0a80256..6147c937 100644 --- a/ORBIT/api/wisdem.py +++ b/ORBIT/api/wisdem.py @@ -95,6 +95,11 @@ def setup(self): 3, desc="Number of station keeping vessels that attach to floating platforms under tow-out.", ) + self.add_discrete_input( + "ahts_vessels", + 1, + desc="Number of ahts vessels that attach to floating platforms under tow-out.", + ) self.add_discrete_input( "oss_install_vessel", "example_heavy_lift_vessel", @@ -378,11 +383,13 @@ def compile_orbit_config_file(self, inputs, outputs, discrete_inputs, discrete_o if floating_flag: vessels = { "support_vessel": "example_support_vessel", + "ahts_vessel" : "example_ahts_vessel", "towing_vessel": "example_towing_vessel", "mooring_install_vessel": "example_support_vessel", "towing_vessel_groups": { "towing_vessels": int(discrete_inputs["num_towing"]), "station_keeping_vessels": int(discrete_inputs["num_station_keeping"]), + "ahts_vessels" : int(discrete_inputs["ahts_vessels"]) }, } else: From d990832417e701ab67c03f25e95d8d71503469e3 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Tue, 4 Jun 2024 10:40:00 -0600 Subject: [PATCH 59/71] Updated test yaml configs to deal with ahts and support vessel calls --- .../library/project/config/complete_floating_project.yaml | 1 + tests/data/library/project/config/floating_oss_install.yaml | 4 ++++ tests/data/library/project/config/moored_install.yaml | 2 ++ .../data/library/project/config/moored_install_no_supply.yaml | 2 ++ 4 files changed, 9 insertions(+) diff --git a/tests/data/library/project/config/complete_floating_project.yaml b/tests/data/library/project/config/complete_floating_project.yaml index 45fbc3ec..dff5b427 100644 --- a/tests/data/library/project/config/complete_floating_project.yaml +++ b/tests/data/library/project/config/complete_floating_project.yaml @@ -42,6 +42,7 @@ site: substructure: takt_time: 168 support_vessel: test_support_vessel +ahts_vessel: test_ahts_vessel towing_vessel: test_towing_vessel towing_vessel_groups: station_keeping_vessels: 2 diff --git a/tests/data/library/project/config/floating_oss_install.yaml b/tests/data/library/project/config/floating_oss_install.yaml index 3b10e637..816b2679 100644 --- a/tests/data/library/project/config/floating_oss_install.yaml +++ b/tests/data/library/project/config/floating_oss_install.yaml @@ -6,6 +6,10 @@ offshore_substation_substructure: mooring_cost: 5e6 offshore_substation_topside: unit_cost: 100e6 +mooring_system: + num_lines: 3 + line_cost: 1e4 + anchor_cost: 1e5 site: depth: 500 distance: 40 diff --git a/tests/data/library/project/config/moored_install.yaml b/tests/data/library/project/config/moored_install.yaml index 631f0e44..242bb802 100644 --- a/tests/data/library/project/config/moored_install.yaml +++ b/tests/data/library/project/config/moored_install.yaml @@ -13,9 +13,11 @@ substructure: towing_speed: 6 unit_cost: 12e6 ahts_vessel: test_ahts_vessel +support_vessel: test_support_vessel towing_vessel: test_towing_vessel towing_vessel_groups: num_groups: 1 ahts_vessels: 1 + station_keeping_vessels: 3 towing_vessels: 1 turbine: 12MW_generic diff --git a/tests/data/library/project/config/moored_install_no_supply.yaml b/tests/data/library/project/config/moored_install_no_supply.yaml index 57d48179..a91dd2ba 100644 --- a/tests/data/library/project/config/moored_install_no_supply.yaml +++ b/tests/data/library/project/config/moored_install_no_supply.yaml @@ -11,9 +11,11 @@ substructure: towing_speed: 6 unit_cost: 12e6 ahts_vessel: test_ahts_vessel +support_vessel: test_support_vessel towing_vessel: test_towing_vessel towing_vessel_groups: num_groups: 1 + station_keeping_vessels: 3 ahts_vessels: 1 towing_vessels: 1 turbine: 12MW_generic From b352386821d58ebf540ca52e5d2d7330c0f999a8 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Wed, 5 Jun 2024 13:31:43 -0600 Subject: [PATCH 60/71] adjusted the name and comments for this temporary class. --- .../design/SemiTaut_mooring_system_design.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ORBIT/phases/design/SemiTaut_mooring_system_design.py b/ORBIT/phases/design/SemiTaut_mooring_system_design.py index b04b0887..e6db2abd 100644 --- a/ORBIT/phases/design/SemiTaut_mooring_system_design.py +++ b/ORBIT/phases/design/SemiTaut_mooring_system_design.py @@ -12,7 +12,7 @@ class SemiTautMooringSystemDesign(DesignPhase): - """Mooring System and Anchor Design.""" + """SemiTaut Mooring System and Anchor Design.""" expected_config = { "site": {"depth": "float"}, @@ -33,7 +33,7 @@ class SemiTautMooringSystemDesign(DesignPhase): "line_mass": "t", # you need this for mooring.py (mooring installation module) "line_cost": "USD", # you can calculate this based on each rope&chain length & diameter. "line_length": "m", # this can be calculated from rope length and chain length (which you get from an empirical eqn as function of depth) - "anchor_mass": "t", # you need this for mooring.py (mooring installation module) + "anchor_mass": "t", # you need this for mooring.py (mooring installation module) "anchor_type": "str", # keep, changed default to drag embedment. "anchor_cost": "USD", # this can be calculated also as a function of (depth?) from the empirical data you have. } @@ -41,7 +41,7 @@ class SemiTautMooringSystemDesign(DesignPhase): def __init__(self, config, **kwargs): """ - Creates an instance of MooringSystemDesign. + Creates an instance of SemiTautMooringSystemDesign. Parameters ---------- @@ -82,29 +82,29 @@ def calculate_line_length_mass(self): rope_diameters = np.array([0.2, 0.2, 0.2, 0.2, 0.2]) # you need the diameter for the cost data chain_lengths = np.array([917.11, 800.36, 609.07, 896.42, 1280.57]) chain_diameters = np.array([0.13, 0.17, 0.22, 0.22, 0.22]) - + # Interpolate finterp_rope = interp1d(depths, rope_lengths) finterp_chain = interp1d(depths, chain_lengths) finterp_rope_diam = interp1d(depths, rope_diameters) finterp_chain_diam = interp1d(depths, chain_diameters) - + # Rope and chain length at project depth self.chain_length = finterp_chain(depth) self.rope_length = finterp_rope(depth) # Rope and chain diameter at project depth self.rope_diameter = finterp_rope_diam(depth) self.chain_diameter = finterp_chain_diam(depth) - + self.line_length = self.rope_length + self.chain_length - + chain_kg_per_m = 19900 * (self.chain_diameter**2) # 19,900 kg/m^2 (diameter)/m (length) - rope_kg_per_m = 797.8 * (self.rope_diameter**2) # 797.8 kg/ m^2 (diameter) / m (length) + rope_kg_per_m = 797.8 * (self.rope_diameter**2) # 797.8 kg/ m^2 (diameter) / m (length) self.line_mass = (self.chain_length * chain_kg_per_m) + (self.rope_length * rope_kg_per_m) # kg #print('total hybrid line mass is ' + str(self.line_mass) + 'kg') # convert kg to metric tonnes self.line_mass = self.line_mass/1e3 - + def calculate_anchor_mass_cost(self): """ Returns the mass and cost of anchors. @@ -118,7 +118,7 @@ def calculate_anchor_mass_cost(self): # Input hybrid mooring system design from Cooperman et al. (2022), https://www.nrel.gov/docs/fy22osti/82341.pdf 'Assessment of Offshore Wind Energy Leasing Areas for Humboldt and Moorow Bay Wind Energy Areas, California depths = np.array([500, 750, 1000, 1250, 1500]) anchor_costs = np.array([112766, 125511, 148703, 204988, 246655]) # [USD] - + # interpolate anchor cost to project depth depth = self.config["site"]["depth"] finterp_anchor_cost = interp1d(depths, anchor_costs) From 411e45bf2619abd53077a6e9818945ca44dcb4ac Mon Sep 17 00:00:00 2001 From: nriccobo Date: Wed, 5 Jun 2024 13:37:34 -0600 Subject: [PATCH 61/71] Added comment for oss substructure mass calcs. --- ORBIT/phases/design/electrical_export.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ORBIT/phases/design/electrical_export.py b/ORBIT/phases/design/electrical_export.py index 9c10bce8..78404528 100644 --- a/ORBIT/phases/design/electrical_export.py +++ b/ORBIT/phases/design/electrical_export.py @@ -526,6 +526,10 @@ def calc_substructure_mass_and_cost(self): "oss_substructure_cost_rate", 3000 ) + # Substructure mass components calculated by curve fits in + # equations 81-84 from Maness et al. 2017 + # https://www.nrel.gov/docs/fy17osti/66874.pdf + # # TODO: Determine a better method to calculate substructure mass # for different substructure types substructure_mass = 0.4 * self.topside_mass From 50ae6a1ab60050742faf13947b1929b5eab5c8e3 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Thu, 6 Jun 2024 11:16:29 -0600 Subject: [PATCH 62/71] Updated electrical design tests and fixed duplicate line in ElectricalDesign --- ORBIT/phases/design/electrical_export.py | 1 - tests/phases/design/test_electrical_design.py | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ORBIT/phases/design/electrical_export.py b/ORBIT/phases/design/electrical_export.py index 78404528..0e44f83c 100644 --- a/ORBIT/phases/design/electrical_export.py +++ b/ORBIT/phases/design/electrical_export.py @@ -518,7 +518,6 @@ def calc_substructure_mass_and_cost(self): oss_pile_cost_rate : int | float """ - substructure_mass = 0.4 * self.topside_mass oss_pile_cost_rate = self.offshore_substation_design.get( "oss_pile_cost_rate", 0 ) diff --git a/tests/phases/design/test_electrical_design.py b/tests/phases/design/test_electrical_design.py index 5539e928..b248d28f 100644 --- a/tests/phases/design/test_electrical_design.py +++ b/tests/phases/design/test_electrical_design.py @@ -61,6 +61,20 @@ def test_parameter_sweep(distance_to_landfall, depth, plant_cap, cable): assert 1e6 <= o.total_substation_cost <= 1e9 +def test_detailed_design_length(): + """Ensure that the same # of output variables are used for a floating and fixed offshore substation.""" + + o = ElectricalDesign(base) + o.run() + + floating = deepcopy(base) + floating["substation_design"]["oss_substructure_type"] = "Floating" + o_floating = ElectricalDesign(floating) + o_floating.run() + + assert len(o.detailed_output) == len(o_floating.detailed_output) + + def test_calc_substructure_mass_and_cost(): o = ElectricalDesign(base) @@ -335,6 +349,13 @@ def test_total_cable(): assert export.total_length == pytest.approx(length * 9, abs=1e-10) +def test_total_cable_cost(): + export = ElectricalDesign(config) + export.run() + + assert export.total_cable_cost == 135068310.0 + + def test_cables_property(): export = ElectricalDesign(config) export.run() From 5e27035e7ae7cf219673bd8af018837364d40ca9 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Fri, 7 Jun 2024 15:15:00 -0600 Subject: [PATCH 63/71] Updating floating example and cleaned comments in oss_floating. --- ORBIT/phases/install/oss_install/floating.py | 4 - examples/5. Example Floating Project.ipynb | 164 ++++++++++-------- .../configs/example_floating_project.yaml | 4 +- 3 files changed, 96 insertions(+), 76 deletions(-) diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index 69c53f76..53353021 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -43,13 +43,9 @@ class FloatingSubstationInstallation(InstallPhase): "type": "str", "takt_time": "int | float (optional, default: 0)", "unit_cost": "USD", - # "mooring_cost": "USD", "towing_speed": "int | float (optional, default: 6 km/h)", }, "mooring_system": { - # "system_cost": "USD", "}, - # system cost is for all moorings in the whole farm, - # so you dont want this to be added to each substation "num_lines", "int", "line_cost", diff --git a/examples/5. Example Floating Project.ipynb b/examples/5. Example Floating Project.ipynb index 09b98d0b..911922e2 100644 --- a/examples/5. Example Floating Project.ipynb +++ b/examples/5. Example Floating Project.ipynb @@ -13,14 +13,14 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "UserWarning: /var/folders/90/1lkt657x3n1cw5x65j3lfgd5406fb8/T/ipykernel_32264/2795185578.py:8\n", + "UserWarning: /var/folders/90/1lkt657x3n1cw5x65j3lfgd5406fb8/T/ipykernel_71795/2795185578.py:8\n", "Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format." ] } @@ -47,7 +47,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -78,7 +78,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -87,7 +87,7 @@ "text": [ "Design phases: ['ArraySystemDesign', 'ElectricalDesign', 'MooringSystemDesign', 'OffshoreFloatingSubstationDesign', 'SemiSubmersibleDesign']\n", "\n", - "Install phases: ['ArrayCableInstallation', 'ExportCableInstallation', 'MooredSubInstallation', 'MooringSystemInstallation', 'FloatingSubstationInstallation']\n" + "Install phases: ['ArrayCableInstallation', 'ExportCableInstallation', 'MooredSubInstallation', 'MooringSystemInstallation', 'FloatingSubstationInstallation', 'TurbineInstallation']\n" ] } ], @@ -105,13 +105,14 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ + "ORBIT library intialized at '/Users/nriccobo/GitHub/ORBIT/library'\n", "2\n" ] }, @@ -122,7 +123,7 @@ "DeprecationWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:93\n", "support_vessel will be deprecated and replaced with towing_vessels and ahts_vessel in the towing groups.\n", "DeprecationWarning: /Users/nriccobo/GitHub/ORBIT/ORBIT/phases/install/quayside_assembly_tow/moored.py:93\n", - "station_keeping_vessels will be deprecated and replaced with towing_vessels and ahts_vessels in the towing groups.\n" + "['towing_vessl_groups]['station_keeping_vessels'] will be deprecated and replaced with ['towing_vessl_groups]['ahts_vessels'].\n" ] } ], @@ -140,20 +141,20 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Installation CapEx: 392 M\n", + "Installation CapEx: 519 M\n", "System CapEx: 1333 M\n", "Turbine CapEx: 780 M\n", "Soft CapEx: 387 M\n", - "Total CapEx: 3043 M\n", + "Total CapEx: 3171 M\n", "\n", - "Installation Time: 35527 h\n" + "Installation Time: 40914 h\n" ] } ], @@ -176,7 +177,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -192,12 +193,13 @@ " 'Substructure Installation': 208.2509277379141,\n", " 'Mooring System Installation': 80.80888508371386,\n", " 'Offshore Substation Installation': 11.784658802638255,\n", + " 'Turbine Installation': 212.89678462709279,\n", " 'Turbine': 1300.0,\n", " 'Soft': 645.0,\n", " 'Project': 252.08333333333334}" ] }, - "execution_count": 31, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -215,7 +217,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -248,6 +250,8 @@ " time\n", " phase\n", " location\n", + " site_depth\n", + " hub_height\n", " phase_name\n", " max_waveheight\n", " max_windspeed\n", @@ -274,6 +278,8 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", + " NaN\n", " \n", " \n", " 1\n", @@ -292,6 +298,8 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", + " NaN\n", " \n", " \n", " 2\n", @@ -310,6 +318,8 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", + " NaN\n", " \n", " \n", " 3\n", @@ -328,6 +338,8 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", + " NaN\n", " \n", " \n", " 4\n", @@ -346,6 +358,8 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", + " NaN\n", " \n", " \n", " ...\n", @@ -364,9 +378,11 @@ " ...\n", " ...\n", " ...\n", + " ...\n", + " ...\n", " \n", " \n", - " 2988\n", + " 4458\n", " NaN\n", " Export Cable Installation Vessel\n", " Pull In Cable\n", @@ -376,6 +392,8 @@ " 12017.280762\n", " ExportCableInstallation\n", " NaN\n", + " NaN\n", + " NaN\n", " ExportCableInstallation\n", " NaN\n", " NaN\n", @@ -384,7 +402,7 @@ " NaN\n", " \n", " \n", - " 2989\n", + " 4459\n", " NaN\n", " Export Cable Installation Vessel\n", " Terminate Cable\n", @@ -394,6 +412,8 @@ " 12022.780762\n", " ExportCableInstallation\n", " NaN\n", + " NaN\n", + " NaN\n", " ExportCableInstallation\n", " NaN\n", " NaN\n", @@ -402,7 +422,7 @@ " NaN\n", " \n", " \n", - " 2990\n", + " 4460\n", " NaN\n", " Export Cable Installation Vessel\n", " Transit\n", @@ -418,9 +438,11 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", + " NaN\n", " \n", " \n", - " 2991\n", + " 4461\n", " NaN\n", " Export Cable Installation Vessel\n", " Delay\n", @@ -436,9 +458,11 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", + " NaN\n", " \n", " \n", - " 2992\n", + " 4462\n", " NaN\n", " Export Cable Installation Vessel\n", " Transit\n", @@ -454,10 +478,12 @@ " NaN\n", " NaN\n", " NaN\n", + " NaN\n", + " NaN\n", " \n", " \n", "\n", - "

2993 rows \u00d7 15 columns

\n", + "

4463 rows \u00d7 17 columns

\n", "" ], "text/plain": [ @@ -468,11 +494,11 @@ "3 1.0 Mooring System Installation Vessel \n", "4 NaN Substation Assembly Line 1 \n", "... ... ... \n", - "2988 NaN Export Cable Installation Vessel \n", - "2989 NaN Export Cable Installation Vessel \n", - "2990 NaN Export Cable Installation Vessel \n", - "2991 NaN Export Cable Installation Vessel \n", - "2992 NaN Export Cable Installation Vessel \n", + "4458 NaN Export Cable Installation Vessel \n", + "4459 NaN Export Cable Installation Vessel \n", + "4460 NaN Export Cable Installation Vessel \n", + "4461 NaN Export Cable Installation Vessel \n", + "4462 NaN Export Cable Installation Vessel \n", "\n", " action duration cost level \\\n", "0 Mobilize 72.000000 3.375000e+05 ACTION \n", @@ -481,55 +507,55 @@ "3 Mobilize 168.000000 7.000000e+05 ACTION \n", "4 Substation Substructure Assembly 0.000000 0.000000e+00 ACTION \n", "... ... ... ... ... \n", - "2988 Pull In Cable 5.500000 5.156250e+04 ACTION \n", - "2989 Terminate Cable 5.500000 5.156250e+04 ACTION \n", - "2990 Transit 8.000000 7.500000e+04 ACTION \n", - "2991 Delay 26.000000 2.437500e+05 ACTION \n", - "2992 Transit 0.695652 6.521739e+03 ACTION \n", + "4458 Pull In Cable 5.500000 5.156250e+04 ACTION \n", + "4459 Terminate Cable 5.500000 5.156250e+04 ACTION \n", + "4460 Transit 8.000000 7.500000e+04 ACTION \n", + "4461 Delay 26.000000 2.437500e+05 ACTION \n", + "4462 Transit 0.695652 6.521739e+03 ACTION \n", "\n", - " time phase location \\\n", - "0 0.000000 ArrayCableInstallation NaN \n", - "1 0.000000 ExportCableInstallation NaN \n", - "2 0.000000 ExportCableInstallation Landfall \n", - "3 0.000000 MooringSystemInstallation NaN \n", - "4 0.000000 FloatingSubstationInstallation NaN \n", - "... ... ... ... \n", - "2988 12017.280762 ExportCableInstallation NaN \n", - "2989 12022.780762 ExportCableInstallation NaN \n", - "2990 12030.780762 ExportCableInstallation NaN \n", - "2991 12056.780762 ExportCableInstallation NaN \n", - "2992 12057.476414 ExportCableInstallation NaN \n", + " time phase location site_depth \\\n", + "0 0.000000 ArrayCableInstallation NaN NaN \n", + "1 0.000000 ExportCableInstallation NaN NaN \n", + "2 0.000000 ExportCableInstallation Landfall NaN \n", + "3 0.000000 MooringSystemInstallation NaN NaN \n", + "4 0.000000 FloatingSubstationInstallation NaN NaN \n", + "... ... ... ... ... \n", + "4458 12017.280762 ExportCableInstallation NaN NaN \n", + "4459 12022.780762 ExportCableInstallation NaN NaN \n", + "4460 12030.780762 ExportCableInstallation NaN NaN \n", + "4461 12056.780762 ExportCableInstallation NaN NaN \n", + "4462 12057.476414 ExportCableInstallation NaN NaN \n", "\n", - " phase_name max_waveheight max_windspeed transit_speed \\\n", - "0 NaN NaN NaN NaN \n", - "1 NaN NaN NaN NaN \n", - "2 NaN NaN NaN NaN \n", - "3 NaN NaN NaN NaN \n", - "4 NaN NaN NaN NaN \n", - "... ... ... ... ... \n", - "2988 ExportCableInstallation NaN NaN NaN \n", - "2989 ExportCableInstallation NaN NaN NaN \n", - "2990 NaN NaN NaN NaN \n", - "2991 NaN NaN NaN NaN \n", - "2992 NaN NaN NaN NaN \n", + " hub_height phase_name max_waveheight max_windspeed \\\n", + "0 NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN \n", + "2 NaN NaN NaN NaN \n", + "3 NaN NaN NaN NaN \n", + "4 NaN NaN NaN NaN \n", + "... ... ... ... ... \n", + "4458 NaN ExportCableInstallation NaN NaN \n", + "4459 NaN ExportCableInstallation NaN NaN \n", + "4460 NaN NaN NaN NaN \n", + "4461 NaN NaN NaN NaN \n", + "4462 NaN NaN NaN NaN \n", "\n", - " num_vessels num_ahts_vessels \n", - "0 NaN NaN \n", - "1 NaN NaN \n", - "2 NaN NaN \n", - "3 NaN NaN \n", - "4 NaN NaN \n", - "... ... ... \n", - "2988 NaN NaN \n", - "2989 NaN NaN \n", - "2990 NaN NaN \n", - "2991 NaN NaN \n", - "2992 NaN NaN \n", + " transit_speed num_vessels num_ahts_vessels \n", + "0 NaN NaN NaN \n", + "1 NaN NaN NaN \n", + "2 NaN NaN NaN \n", + "3 NaN NaN NaN \n", + "4 NaN NaN NaN \n", + "... ... ... ... \n", + "4458 NaN NaN NaN \n", + "4459 NaN NaN NaN \n", + "4460 NaN NaN NaN \n", + "4461 NaN NaN NaN \n", + "4462 NaN NaN NaN \n", "\n", - "[2993 rows x 15 columns]" + "[4463 rows x 17 columns]" ] }, - "execution_count": 32, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -540,7 +566,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 8, "metadata": {}, "outputs": [ { diff --git a/examples/configs/example_floating_project.yaml b/examples/configs/example_floating_project.yaml index e7d23af8..28e7fd24 100644 --- a/examples/configs/example_floating_project.yaml +++ b/examples/configs/example_floating_project.yaml @@ -44,10 +44,8 @@ export_system_design: # Configured Phases design_phases: - ArraySystemDesign -#- ExportSystemDesign - ElectricalDesign - MooringSystemDesign -#- SemiTautMooringSystemDesign - OffshoreFloatingSubstationDesign - SemiSubmersibleDesign install_phases: @@ -56,6 +54,6 @@ install_phases: MooredSubInstallation: 0 MooringSystemInstallation: 0 FloatingSubstationInstallation: 0 -# TurbineInstallation: 0 + TurbineInstallation: 0 # Project Inputs turbine: 12MW_generic From 65728e8bfb89abc96267d7c86ed1360fff356cb3 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Mon, 10 Jun 2024 09:28:09 -0600 Subject: [PATCH 64/71] Added reference for semitaut line constants --- ORBIT/phases/design/mooring_system_design.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/ORBIT/phases/design/mooring_system_design.py b/ORBIT/phases/design/mooring_system_design.py index bda8cb8b..e14bb09c 100644 --- a/ORBIT/phases/design/mooring_system_design.py +++ b/ORBIT/phases/design/mooring_system_design.py @@ -1,9 +1,12 @@ """`MooringSystemDesign` and related functionality.""" -__author__ = "Jake Nunemaker, modified by Becca Fuchs" +__author__ = "Jake Nunemaker, Becca Fuchs" __copyright__ = "Copyright 2020, National Renewable Energy Laboratory" -__maintainer__ = "Jake Nunemaker" -__email__ = "jake.nunemaker@nrel.gov, rebecca.fuchs@nrel.gov" +__maintainer__ = "Nicholas Riccobono" +__email__ = ( + "jake.nunemaker@nrel.gov, rebecca.fuchs@nrel.gov," + "nicholas.riccobono@nrel.gov" +) from math import sqrt @@ -141,12 +144,10 @@ def calculate_line_length_mass(self): """ Returns the mooring line length and mass. + SemiTaut model based on: + https://github.com/NREL/MoorPy/blob/dev/moorpy/MoorProps_default.yaml TODO: Improve TLP line length and mass - Parameters - ---------- - drag_embedment_fixed_length - draft_depth """ # Add extra fixed line length for drag embedments @@ -183,14 +184,15 @@ def calculate_line_length_mass(self): fixed = self._design.get("drag_embedment_fixed_length", 0) self.line_length = self.rope_length + self.chain_length + fixed + # line characteristics based on MoorPy defaults, chain_mass_per_m = ( self._design.get("mooring_chain_density", 19900) * chain_diameter**2 - ) # kg + ) # kg/m rope_mass_per_m = ( self._design.get("mooring_rope_density", 797.8) * rope_diameter**2 - ) # kg + ) # kg/m self.line_mass = ( self.chain_length * chain_mass_per_m From 8749076ea76dde32d346bd2fd77902e5711bfe67 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Mon, 10 Jun 2024 11:13:32 -0600 Subject: [PATCH 65/71] Removed commented anchor install cost method. Added to process_time --- .../phases/install/mooring_install/mooring.py | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/ORBIT/phases/install/mooring_install/mooring.py b/ORBIT/phases/install/mooring_install/mooring.py index 296d82fc..a8997f39 100644 --- a/ORBIT/phases/install/mooring_install/mooring.py +++ b/ORBIT/phases/install/mooring_install/mooring.py @@ -268,7 +268,7 @@ def install_mooring_line(vessel, depth, **kwargs): ------ vessel.task representing time to install mooring line. """ - + install_time = 0.005 * depth yield vessel.task_wrapper( @@ -319,28 +319,3 @@ def release(**kwargs): """Dummy method to work with `get_list_of_items_from_port`.""" return "", 0 - -''' # commented anchor_install_time because this overwrites what is called from process_times.yaml . - def anchor_install_time(self, depth): - """ - Returns time to install anchor. Varies by depth. - - Parameters - ---------- - depth : int | float - Depth at site (m). - """ - - if self.anchor_type == "Suction Pile": - fixed = 11 - - elif self.anchor_type == "Drag Embedment": - fixed = 5 - - else: - raise ValueError( - f"Mooring System Anchor Type: {self.anchor_type} not recognized." - ) - - return fixed + 0.005 * depth -''' \ No newline at end of file From 90bb8c55f04e2b786f15d9a43fbd48c5f76e1b6d Mon Sep 17 00:00:00 2001 From: nriccobo Date: Mon, 10 Jun 2024 11:38:26 -0600 Subject: [PATCH 66/71] Updated tests to verify defaults. Cleaned up single character object names. --- tests/phases/design/test_electrical_design.py | 146 +++++++++--------- .../design/test_mooring_system_design.py | 96 +++++++----- 2 files changed, 133 insertions(+), 109 deletions(-) diff --git a/tests/phases/design/test_electrical_design.py b/tests/phases/design/test_electrical_design.py index b248d28f..45e03155 100644 --- a/tests/phases/design/test_electrical_design.py +++ b/tests/phases/design/test_electrical_design.py @@ -43,63 +43,69 @@ def test_parameter_sweep(distance_to_landfall, depth, plant_cap, cable): "substation_design": {}, } - o = ElectricalDesign(config) - o.run() + elect = ElectricalDesign(config) + elect.run() # Check valid substructure length - assert 10 <= o._outputs["offshore_substation_substructure"]["length"] <= 80 + assert ( + 10 + <= elect._outputs["offshore_substation_substructure"]["length"] + <= 80 + ) # Check valid substructure mass assert ( - 200 <= o._outputs["offshore_substation_substructure"]["mass"] <= 2700 + 200 + <= elect._outputs["offshore_substation_substructure"]["mass"] + <= 2700 ) # Check valid topside mass - assert 200 <= o._outputs["offshore_substation_topside"]["mass"] <= 5500 + assert 200 <= elect._outputs["offshore_substation_topside"]["mass"] <= 5500 # Check valid substation cost - assert 1e6 <= o.total_substation_cost <= 1e9 + assert 1e6 <= elect.total_substation_cost <= 1e9 def test_detailed_design_length(): """Ensure that the same # of output variables are used for a floating and fixed offshore substation.""" - o = ElectricalDesign(base) - o.run() + elect = ElectricalDesign(base) + elect.run() floating = deepcopy(base) floating["substation_design"]["oss_substructure_type"] = "Floating" - o_floating = ElectricalDesign(floating) - o_floating.run() + elect_floating = ElectricalDesign(floating) + elect_floating.run() - assert len(o.detailed_output) == len(o_floating.detailed_output) + assert len(elect.detailed_output) == len(elect_floating.detailed_output) def test_calc_substructure_mass_and_cost(): - o = ElectricalDesign(base) - o.run() + elect = ElectricalDesign(base) + elect.run() floating = deepcopy(base) floating["substation_design"]["oss_substructure_type"] = "Floating" - o_floating = ElectricalDesign(floating) - o_floating.run() + elect_floating = ElectricalDesign(floating) + elect_floating.run() assert ( - o.detailed_output["substation_substructure_cost"] - != o_floating.detailed_output["substation_substructure_cost"] + elect.detailed_output["substation_substructure_cost"] + != elect_floating.detailed_output["substation_substructure_cost"] ) assert ( - o.detailed_output["substation_substructure_mass"] - != o_floating.detailed_output["substation_substructure_mass"] + elect.detailed_output["substation_substructure_mass"] + != elect_floating.detailed_output["substation_substructure_mass"] ) def test_calc_topside_mass_and_cost(): """Test topside mass and cost for HVDC compared to HVDC-Monopole and HVDC-Bipole""" - o = ElectricalDesign(base) - o.run() + elect = ElectricalDesign(base) + elect.run() base_dc = deepcopy(base) cables = ["HVDC_2000mm_320kV", "HVDC_2500mm_525kV"] @@ -107,16 +113,16 @@ def test_calc_topside_mass_and_cost(): for cable in cables: base_dc["export_system_design"]["cables"] = cable - o_dc = ElectricalDesign(base_dc) - o_dc.run() + elect_dc = ElectricalDesign(base_dc) + elect_dc.run() assert ( - o.detailed_output["substation_topside_mass"] - == o_dc.detailed_output["substation_topside_mass"] + elect.detailed_output["substation_topside_mass"] + == elect_dc.detailed_output["substation_topside_mass"] ) assert ( - o.detailed_output["substation_topside_cost"] - != o_dc.detailed_output["substation_topside_cost"] + elect.detailed_output["substation_topside_cost"] + != elect_dc.detailed_output["substation_topside_cost"] ) @@ -128,20 +134,20 @@ def test_oss_substructure_kwargs(): "num_substations": 4, } - o = ElectricalDesign(base) - o.run() - base_cost_total = o.detailed_output["total_substation_cost"] - base_cost_subst = o.detailed_output["substation_substructure_cost"] + elect = ElectricalDesign(base) + elect.run() + base_cost_total = elect.detailed_output["total_substation_cost"] + base_cost_subst = elect.detailed_output["substation_substructure_cost"] for k, v in test_kwargs.items(): config = deepcopy(base) config["substation_design"] = {} config["substation_design"][k] = v - o = ElectricalDesign(config) - o.run() - cost_total = o.detailed_output["total_substation_cost"] - cost_subst = o.detailed_output["substation_substructure_cost"] + elect = ElectricalDesign(config) + elect.run() + cost_total = elect.detailed_output["total_substation_cost"] + cost_subst = elect.detailed_output["substation_substructure_cost"] assert cost_total != base_cost_total assert cost_subst != base_cost_subst @@ -161,18 +167,18 @@ def test_ac_oss_kwargs(): "num_substations": 4, } - o = ElectricalDesign(base) - o.run() - base_cost = o.detailed_output["total_substation_cost"] + elect = ElectricalDesign(base) + elect.run() + base_cost = elect.detailed_output["total_substation_cost"] for k, v in test_kwargs.items(): config = deepcopy(base) config["substation_design"] = {} config["substation_design"][k] = v - o = ElectricalDesign(config) - o.run() - cost = o.detailed_output["total_substation_cost"] + elect = ElectricalDesign(config) + elect.run() + cost = elect.detailed_output["total_substation_cost"] print("passed") assert cost != base_cost @@ -182,9 +188,9 @@ def test_dc_oss_kwargs(): dc_base = deepcopy(base) dc_base["export_system_design"]["cables"] = "HVDC_2000mm_320kV" - o = ElectricalDesign(dc_base) - o.run() - base_cost = o.detailed_output["total_substation_cost"] + elect = ElectricalDesign(dc_base) + elect.run() + base_cost = elect.detailed_output["total_substation_cost"] for k, v in test_kwargs.items(): config = deepcopy(base) @@ -192,9 +198,9 @@ def test_dc_oss_kwargs(): config["substation_design"] = {} config["substation_design"][k] = v - o = ElectricalDesign(config) - o.run() - cost = o.detailed_output["total_substation_cost"] + elect = ElectricalDesign(config) + elect.run() + cost = elect.detailed_output["total_substation_cost"] assert cost != base_cost @@ -232,35 +238,35 @@ def test_new_old_hvac_substation(): def test_hvdc_substation(): config = deepcopy(base) config["export_system_design"] = {"cables": "HVDC_2000mm_320kV"} - o = ElectricalDesign(config) - o.run() - assert o.converter_cost != 0 - assert o.shunt_reactor_cost == 0 - assert o.dc_breaker_cost != 0 - assert o.switchgear_cost == 0 - assert o.mpt_cost == 0 - # assert o.num_cables / o.num_converters == 2 # breaks + elect = ElectricalDesign(config) + elect.run() + assert elect.converter_cost != 0 + assert elect.shunt_reactor_cost == 0 + assert elect.dc_breaker_cost != 0 + assert elect.switchgear_cost == 0 + assert elect.mpt_cost == 0 + # assert elect.num_cables / elect.num_converters == 2 # breaks config = deepcopy(base) config["export_system_design"] = {"cables": "HVDC_2500mm_525kV"} - o = ElectricalDesign(config) - o.run() + elect = ElectricalDesign(config) + elect.run() - # assert o.num_converters == o.num_cables # breaks + # assert elect.num_converters == elect.num_cables # breaks def test_onshore_substation(): config = deepcopy(base) - o = ElectricalDesign(config) - o.run() - assert o.onshore_cost == pytest.approx(95.487e6, abs=1e2) # 109.32e6 + elect = ElectricalDesign(config) + elect.run() + assert elect.onshore_cost == pytest.approx(95.487e6, abs=1e2) # 109.32e6 config_mono = deepcopy(config) config_mono["export_system_design"] = {"cables": "HVDC_2000mm_320kV"} - o_mono = ElectricalDesign(config_mono) - o_mono.run() - assert o_mono.onshore_cost == 244.3e6 + o_monelect = ElectricalDesign(config_mono) + o_monelect.run() + assert o_monelect.onshore_cost == 244.3e6 config_bi = deepcopy(config) config_bi["export_system_design"] = {"cables": "HVDC_2500mm_525kV"} @@ -280,18 +286,18 @@ def test_export_kwargs(): # "interconnection_distance": 6, } - o = ElectricalDesign(base) - o.run() - base_cost = o.total_cost + elect = ElectricalDesign(base) + elect.run() + base_cost = elect.total_cost for k, v in test_kwargs.items(): config = deepcopy(base) config["export_system_design"] = {"cables": "XLPE_630mm_220kV"} config["export_system_design"][k] = v - o = ElectricalDesign(config) - o.run() - cost = o.total_cost + elect = ElectricalDesign(config) + elect.run() + cost = elect.total_cost assert cost != base_cost diff --git a/tests/phases/design/test_mooring_system_design.py b/tests/phases/design/test_mooring_system_design.py index 93fb714b..bf0e7021 100644 --- a/tests/phases/design/test_mooring_system_design.py +++ b/tests/phases/design/test_mooring_system_design.py @@ -29,11 +29,11 @@ def test_depth_sweep(depth): config = deepcopy(base) config["site"]["depth"] = depth - m = MooringSystemDesign(config) - m.run() + moor = MooringSystemDesign(config) + moor.run() - assert m.design_result - assert m.total_cost + assert moor.design_result + assert moor.total_cost @pytest.mark.parametrize("rating", range(3, 15, 1)) @@ -42,11 +42,29 @@ def test_rating_sweep(rating): config = deepcopy(base) config["turbine"]["turbine_rating"] = rating - m = MooringSystemDesign(config) - m.run() + moor = MooringSystemDesign(config) + moor.run() - assert m.design_result - assert m.total_cost + assert moor.design_result + assert moor.total_cost + + +def test_mooring_system_defaults(): + + moor_base = MooringSystemDesign(base) + moor_base.run() + + base_cost = moor_base.detailed_output["system_cost"] + + config_defs = deepcopy(base) + config_defs["mooring_system_design"] = {} + config_defs["mooring_system_design"]["mooring_type"] = "Catenary" + config_defs["mooring_system_design"]["anchor_type"] = "Suction Pile" + + moor_defs = MooringSystemDesign(config_defs) + moor_defs.run() + + assert moor_defs.detailed_output["system_cost"] == base_cost def test_catenary_mooring_system_kwargs(): @@ -57,20 +75,20 @@ def test_catenary_mooring_system_kwargs(): "mooring_line_cost_rate": 2500, } - m = MooringSystemDesign(base) - m.run() + moor = MooringSystemDesign(base) + moor.run() - base_cost = m.detailed_output["system_cost"] + base_cost = moor.detailed_output["system_cost"] for k, v in test_kwargs.items(): config = deepcopy(base) config["mooring_system_design"] = {} config["mooring_system_design"][k] = v - m = MooringSystemDesign(config) - m.run() + moor = MooringSystemDesign(config) + moor.run() - assert m.detailed_output["system_cost"] != base_cost + assert moor.detailed_output["system_cost"] != base_cost def test_semitaut_mooring_system_kwargs(): @@ -85,20 +103,20 @@ def test_semitaut_mooring_system_kwargs(): "rope_density": 1000, } - m = MooringSystemDesign(semi_base) - m.run() + moor = MooringSystemDesign(semi_base) + moor.run() - base_cost = m.detailed_output["system_cost"] + base_cost = moor.detailed_output["system_cost"] for k, v in test_kwargs.items(): config = deepcopy(semi_base) config["mooring_system_design"] = {} config["mooring_system_design"][k] = v - m = MooringSystemDesign(config) - m.run() + moor = MooringSystemDesign(config) + moor.run() - assert m.detailed_output["system_cost"] != base_cost + assert moor.detailed_output["system_cost"] != base_cost def test_tlp_mooring_system_kwargs(): @@ -113,36 +131,36 @@ def test_tlp_mooring_system_kwargs(): "draft_depth": 10, } - m = MooringSystemDesign(tlp_base) - m.run() + moor = MooringSystemDesign(tlp_base) + moor.run() - base_cost = m.detailed_output["system_cost"] + base_cost = moor.detailed_output["system_cost"] for k, v in test_kwargs.items(): config = deepcopy(tlp_base) config["mooring_system_design"] = {} config["mooring_system_design"][k] = v - m = MooringSystemDesign(config) - m.run() + moor = MooringSystemDesign(config) + moor.run() - assert m.detailed_output["system_cost"] != base_cost + assert moor.detailed_output["system_cost"] != base_cost def test_drag_embedment_fixed_length(): - m = MooringSystemDesign(base) - m.run() + moor = MooringSystemDesign(base) + moor.run() - baseline = m.line_length + baseline = moor.line_length default = deepcopy(base) default["mooring_system_design"] = {"anchor_type": "Drag Embedment"} - m = MooringSystemDesign(default) - m.run() + moor = MooringSystemDesign(default) + moor.run() - with_default = m.line_length + with_default = moor.line_length assert with_default > baseline custom = deepcopy(base) @@ -151,11 +169,11 @@ def test_drag_embedment_fixed_length(): "drag_embedment_fixed_length": 1000, } - m = MooringSystemDesign(custom) - m.run() + moor = MooringSystemDesign(custom) + moor.run() - assert m.line_length > with_default - assert m.line_length > baseline + assert moor.line_length > with_default + assert moor.line_length > baseline def test_custom_num_lines(): @@ -163,10 +181,10 @@ def test_custom_num_lines(): config = deepcopy(base) config["mooring_system_design"] = {"num_lines": 5} - m = MooringSystemDesign(config) - m.run() + moor = MooringSystemDesign(config) + moor.run() - assert m.design_result["mooring_system"]["num_lines"] == 5 + assert moor.design_result["mooring_system"]["num_lines"] == 5 def test_new_old_semitaut_mooring_system(): From bdcff41dd594b2f6ae3abb38e5ec2e2610c7cf41 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Mon, 10 Jun 2024 11:41:56 -0600 Subject: [PATCH 67/71] Updated changelog and docs. --- docs/source/changelog.rst | 11 ++++++++++- .../phases/design/doc_OffshoreSubstationDesign.rst | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 0b8e1003..17be76bd 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -5,7 +5,16 @@ ORBIT Changelog Unreleased (TBD) ---------------- - +- merged SemiTaut_Mooring_Update +- The ``MooringSystemDesign`` module now can use a Catenary or SemiTaut mooring system. User can specify "mooring_type". +- The ``FloatingOffshoreSubstation`` and ``ElectricalDesign`` modules now actually have a floating option to remove any substructure mass (and cost) from older versions. User can specify "oss_substructure_type" +- The ``MoredSubInstallation`` now utilizes an AHTS vessel which must be added to any config file as (ahts_vessel) +- "drag_embedment_install_time" increased from 5 to 12 hours +- quayside turbine tower section lift time from 12 to 4 hours per section. User specifies number of sections (default =1) +- quayside nacelle lift time changed from 7 to 12 hours +Unreleased (TBD) +---------------- +- merged electrical-refactor - Updated ``ElectricalDesign`` module. This class combines the elements of ``ExportSystemDesign`` and the ``OffshoreSubstationDesign`` modules. Its purpose is to represent the export system more accurately by linking the type of cable (AC versus DC) and substation’s components (i.e. transformers versus converters).Figure 1 shows how to add ElectricalDesign() to a yaml diff --git a/docs/source/phases/design/doc_OffshoreSubstationDesign.rst b/docs/source/phases/design/doc_OffshoreSubstationDesign.rst index ec393be6..ef309b47 100644 --- a/docs/source/phases/design/doc_OffshoreSubstationDesign.rst +++ b/docs/source/phases/design/doc_OffshoreSubstationDesign.rst @@ -16,4 +16,4 @@ References ---------- .. [#maness2017] Michael Maness, Benjamin Maples, Aaron Smith, - NREL Offshore Balance-of-System Model, 2017 + NREL Offshore Balance-of-System Model, 2017. https://www.nrel.gov/docs/fy17osti/66874.pdf From 08cae489ca9d2b73d694cbb6532ad796d619c4f0 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Mon, 10 Jun 2024 11:44:23 -0600 Subject: [PATCH 68/71] changelog and floating.py clean up and update after file save. --- ORBIT/phases/install/oss_install/floating.py | 4 +--- docs/source/changelog.rst | 5 +++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ORBIT/phases/install/oss_install/floating.py b/ORBIT/phases/install/oss_install/floating.py index 53353021..1170ad7e 100644 --- a/ORBIT/phases/install/oss_install/floating.py +++ b/ORBIT/phases/install/oss_install/floating.py @@ -105,9 +105,7 @@ def system_capex(self): mooring_system_for_each_oss = num_mooring_lines * ( line_cost + anchor_cost ) - # print('topside: ' + str(topside)) - # print('oss substructure' + str(substructure)) - # print('mooring system' + str(mooring_system_for_each_oss)) + return self.num_substations * ( topside + substructure + mooring_system_for_each_oss ) diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 17be76bd..914f37a6 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -12,6 +12,11 @@ Unreleased (TBD) - "drag_embedment_install_time" increased from 5 to 12 hours - quayside turbine tower section lift time from 12 to 4 hours per section. User specifies number of sections (default =1) - quayside nacelle lift time changed from 7 to 12 hours +- XLPE_500mm_132kV cost_per_km changed from 200k to 500k +- example_cable_lay_vessel min_draft changed from 4.8m to 8.5m, overall_length 99m to 171m, max_mass 4000t to 13000t +- example_towing_vessel max_waveheight changed from 2.5m to 3.0m, max_windspeed 20m to 15m, transit_speed 6km/h to 14 km/h, day_rate 30k to 35k + + Unreleased (TBD) ---------------- - merged electrical-refactor From 41e57c2dd69d905cd0aec4b4108b949dafbf6839 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Fri, 14 Jun 2024 11:20:51 -0600 Subject: [PATCH 69/71] Addressed the deprecated support_vessel call in gravity-base install. Aligned install with moored install --- .../quayside_assembly_tow/gravity_base.py | 47 ++++++++++++++++--- .../test_gravity_based.py | 18 +++++++ .../quayside_assembly_tow/test_moored.py | 2 +- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py b/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py index 665f6d7c..a25e4404 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py +++ b/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py @@ -5,9 +5,11 @@ __maintainer__ = "Jake Nunemaker" __email__ = "jake.nunemaker@nrel.gov" +from warnings import warn import simpy from marmot import le, process + from ORBIT.core import Vessel, WetStorage from ORBIT.phases.install import InstallPhase @@ -25,11 +27,13 @@ class GravityBasedInstallation(InstallPhase): #: expected_config = { - "support_vessel": "str", + "support_vessel": "str, (optional)", + "ahts_vessel": "str", "towing_vessel": "str", "towing_vessel_groups": { "towing_vessels": "int", - "station_keeping_vessels": "int", + "station_keeping_vessels": "int (optional)", + "ahts_vessels": "int (optional, default: 1)", "num_groups": "int (optional)", }, "substructure": { @@ -210,20 +214,49 @@ def initialize_queue(self): def initialize_support_vessel(self, **kwargs): """ + ** The support vessel is deprecated and an AHTS + vessel will perform the installation with the towing group. + # TODO: determine if the installation process for GBF is still + sound. + Initializes Multi-Purpose Support Vessel to perform installation processes at site. """ - specs = self.config["support_vessel"] - vessel = self.initialize_vessel("Multi-Purpose Support Vessel", specs) + specs = self.config.get("support_vessel", None) + + if specs is not None: + warn( + "support_vessel will be deprecated and replaced with" + " towing_vessels and ahts_vessel in the towing groups.\n", + DeprecationWarning, + stacklevel=2, + ) + + specs = self.config["ahts_vessel"] + vessel = self.initialize_vessel("Multi-Purpose AHTS Vessel", specs) self.env.register(vessel) vessel.initialize(mobilize=False) self.support_vessel = vessel - station_keeping_vessels = self.config["towing_vessel_groups"][ - "station_keeping_vessels" - ] + station_keeping_vessels = self.config["towing_vessel_groups"].get( + "station_keeping_vessels", None + ) + + if station_keeping_vessels is not None: + print(station_keeping_vessels) + warn( + "['towing_vessl_groups]['station_keeping_vessels']" + " will be deprecated and replaced with" + " ['towing_vessl_groups]['ahts_vessels'].\n", + DeprecationWarning, + stacklevel=2, + ) + + station_keeping_vessels = self.config["towing_vessel_groups"].get( + "ahts_vessels", 1 + ) install_gravity_base_foundations( self.support_vessel, diff --git a/tests/phases/install/quayside_assembly_tow/test_gravity_based.py b/tests/phases/install/quayside_assembly_tow/test_gravity_based.py index dafad84b..84c57b9d 100644 --- a/tests/phases/install/quayside_assembly_tow/test_gravity_based.py +++ b/tests/phases/install/quayside_assembly_tow/test_gravity_based.py @@ -5,6 +5,7 @@ __maintainer__ = "Jake Nunemaker" __email__ = "jake.nunemaker@nrel.gov" +from copy import deepcopy import pandas as pd import pytest @@ -56,3 +57,20 @@ def test_for_complete_logging(weather, config): assert ~df["cost"].isnull().any() _ = sim.agent_efficiencies _ = sim.detailed_output + + +def test_deprecated_vessel(): + + deprecated = deepcopy(config) + deprecated["support_vessel"] = "test_support_vessel" + + with pytest.deprecated_call(): + sim = GravityBasedInstallation(deprecated) + sim.run() + + deprecated2 = deepcopy(config) + deprecated2["towing_vessel_groups"]["station_keeping_vessels"] = 2 + + with pytest.deprecated_call(): + sim = GravityBasedInstallation(deprecated2) + sim.run() diff --git a/tests/phases/install/quayside_assembly_tow/test_moored.py b/tests/phases/install/quayside_assembly_tow/test_moored.py index 3892495b..17dd0cb0 100644 --- a/tests/phases/install/quayside_assembly_tow/test_moored.py +++ b/tests/phases/install/quayside_assembly_tow/test_moored.py @@ -80,7 +80,7 @@ def test_for_complete_logging(weather, config): assert installed_mooring_lines == sim.num_turbines -def test_deprecated_landfall(): +def test_deprecated_vessel(): deprecated = deepcopy(config) deprecated["support_vessel"] = "test_support_vessel" From 90dd2cfea3a08a4325cdc25c48a2398792617222 Mon Sep 17 00:00:00 2001 From: nriccobo Date: Mon, 17 Jun 2024 13:57:18 -0600 Subject: [PATCH 70/71] Had to remove a print statement that I left. --- ORBIT/phases/install/quayside_assembly_tow/gravity_base.py | 1 - ORBIT/phases/install/quayside_assembly_tow/moored.py | 1 - 2 files changed, 2 deletions(-) diff --git a/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py b/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py index a25e4404..1e80b1fc 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py +++ b/ORBIT/phases/install/quayside_assembly_tow/gravity_base.py @@ -245,7 +245,6 @@ def initialize_support_vessel(self, **kwargs): ) if station_keeping_vessels is not None: - print(station_keeping_vessels) warn( "['towing_vessl_groups]['station_keeping_vessels']" " will be deprecated and replaced with" diff --git a/ORBIT/phases/install/quayside_assembly_tow/moored.py b/ORBIT/phases/install/quayside_assembly_tow/moored.py index e4d8d752..916a09fc 100644 --- a/ORBIT/phases/install/quayside_assembly_tow/moored.py +++ b/ORBIT/phases/install/quayside_assembly_tow/moored.py @@ -256,7 +256,6 @@ def initialize_support_vessel(self): ) if station_keeping_vessels is not None: - print(station_keeping_vessels) warn( "['towing_vessl_groups]['station_keeping_vessels']" " will be deprecated and replaced with" From a133c01942f3ef8d091ab755ab57c5573e78e6ff Mon Sep 17 00:00:00 2001 From: nriccobo Date: Tue, 18 Jun 2024 15:23:24 -0600 Subject: [PATCH 71/71] Updated sim setup test to sweep different configs. --- .../install/quayside_assembly_tow/test_moored.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/phases/install/quayside_assembly_tow/test_moored.py b/tests/phases/install/quayside_assembly_tow/test_moored.py index 17dd0cb0..8f36ef4c 100644 --- a/tests/phases/install/quayside_assembly_tow/test_moored.py +++ b/tests/phases/install/quayside_assembly_tow/test_moored.py @@ -27,7 +27,17 @@ ) -def test_simulation_setup(): +@pytest.mark.parametrize( + "config", + (config, multi_assembly, multi_tow, multi_assembly_multi_tow), + ids=[ + "1 assembly, 1 tow", + "3 assembly, 1 tow", + "1 assembly, 3 tow", + "3 assembly, 3 tow", + ], +) +def test_simulation_setup(config): sim = MooredSubInstallation(config) assert sim.config == config assert sim.env