diff --git a/examples/03_Frequency_Domain_Analysis_RAFT/01_platform.yaml b/examples/03_Frequency_Domain_Analysis_RAFT/01_platform.yaml index a860d818..4e733a4a 100644 --- a/examples/03_Frequency_Domain_Analysis_RAFT/01_platform.yaml +++ b/examples/03_Frequency_Domain_Analysis_RAFT/01_platform.yaml @@ -27,7 +27,7 @@ platform: rB : [ 0, 0, 15] # [m] and B coordinates shape : circ # [-] circular or rectangular gamma : 0.0 # [deg] twist angle about the member's z-axis - potMod : True # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory # --- outer shell including hydro--- stations : [0, 1] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB d : 10.0 # [m] diameters if circular or side lengths if rectangular (can be pairs) @@ -50,7 +50,7 @@ platform: heading : [ 60, 180, 300] # [deg] heading rotation of column about z axis (for repeated members) shape : circ # [-] circular or rectangular gamma : 0.0 # [deg] twist angle about the member's z-axis - potMod : True # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory # --- outer shell including hydro--- stations : [0, 35] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB d : 12.5 # [m] diameters if circular or side lengths if rectangular (can be pairs) diff --git a/examples/03_Frequency_Domain_Analysis_RAFT/02_FOWT.yaml b/examples/03_Frequency_Domain_Analysis_RAFT/02_FOWT.yaml index 533b143e..7d5dd939 100644 --- a/examples/03_Frequency_Domain_Analysis_RAFT/02_FOWT.yaml +++ b/examples/03_Frequency_Domain_Analysis_RAFT/02_FOWT.yaml @@ -1123,7 +1123,7 @@ platform: rB : [ 0, 0, 15] # [m] and B coordinates shape : circ # [-] circular or rectangular gamma : 0.0 # [deg] twist angle about the member's z-axis - potMod : True # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory # --- outer shell including hydro--- stations : [0, 1] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB d : 10.0 # [m] diameters if circular or side lengths if rectangular (can be pairs) @@ -1146,7 +1146,7 @@ platform: heading : [ 60, 180, 300] # [deg] heading rotation of column about z axis (for repeated members) shape : circ # [-] circular or rectangular gamma : 0.0 # [deg] twist angle about the member's z-axis - potMod : True # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory # --- outer shell including hydro--- stations : [0, 35] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB d : 12.5 # [m] diameters if circular or side lengths if rectangular (can be pairs) diff --git a/examples/05_Anchors/anchor_drilled.py b/examples/05_Anchors/anchor_drilled.py new file mode 100644 index 00000000..e252be61 --- /dev/null +++ b/examples/05_Anchors/anchor_drilled.py @@ -0,0 +1,64 @@ + +from famodel.anchors.anchor import Anchor + +# --- Define soil profile --- +profile_map = [ + { + 'name': 'CPT_D1', + 'x': 0.0, 'y': 0.0, + 'layers': [ + {'top': 1.5, 'bottom': 5.0, 'soil_type': 'rock', 'UCS_top': 6.0, 'UCS_bot': 8.0, 'Em_top': 175, 'Em_bot': 290}, + {'top': 5.0, 'bottom': 9.0, 'soil_type': 'rock', 'UCS_top': 8.0, 'UCS_bot': 10.7, 'Em_top': 277, 'Em_bot': 297}, + {'top': 9.0, 'bottom': 30.0, 'soil_type': 'rock', 'UCS_top': 8.0, 'UCS_bot': 10.5, 'Em_top': 280, 'Em_bot': 305} + ] + } +] + +# --- Create driven pile anchor --- +anchor = Anchor( + dd = { + 'type': 'drilled', + 'design': { + 'L': 10.0, # Embedded length + 'D': 2.85, # Diameter + 'zlug': 1.0 # Padeye depth + } + }, + r = [0.0, 0.0, 0.0]) + +# Assign mooring loads +anchor.loads = { + 'Hm': 5.0e6, + 'Vm': 2.5e5} + +anchor.line_type = 'chain' +anchor.d = 0.16 +anchor.w = 5000.0 + +# Assign local soil +anchor.setSoilProfile(profile_map) + +# --- Step 1: Capacity --- +anchor.getCapacityAnchor( + Hm = anchor.loads['Hm'], + Vm = anchor.loads['Vm'], + zlug = anchor.dd['design']['zlug'], + line_type = anchor.line_type, + d = anchor.d, + w = anchor.w, + plot = True) + +print('\nCapacity Results:') +for key, val in anchor.anchorCapacity.items(): + print(f'{key}: {val:.2f}') + +# --- Step 2: Optimize Anchor Geometry --- +anchor.getSizeAnchor( + geom = [anchor.dd['design']['L'], anchor.dd['design']['D']], + geomKeys = ['L', 'D'], + geomBounds = [(2.0, 30.0), (2.25, 5.0)], + loads = None, + lambdap_con = [4, 50], + zlug_fix = True, + safety_factor = {'SF_horizontal': 1, 'SF_vertical': 1}, + plot = True) \ No newline at end of file diff --git a/examples/05_Anchors/anchor_driven_rock.py b/examples/05_Anchors/anchor_driven_rock.py new file mode 100644 index 00000000..8564bea6 --- /dev/null +++ b/examples/05_Anchors/anchor_driven_rock.py @@ -0,0 +1,65 @@ + +from famodel.anchors.anchor import Anchor + +# --- Define soil profile --- +profile_map = [ + { + 'name': 'CPT_D1', + 'x': 0.0, 'y': 0.0, + 'layers': [ + {'top': 1.5, 'bottom': 6.0, 'soil_type': 'rock', 'UCS_top': 5.0, 'UCS_bot': 5.0, 'Em_top': 7, 'Em_bot': 7}, + {'top': 6.0, 'bottom': 15.0, 'soil_type': 'rock', 'UCS_top': 6.0, 'UCS_bot': 6.7, 'Em_top': 7, 'Em_bot': 7}, + {'top': 15.0, 'bottom': 35.0, 'soil_type': 'rock', 'UCS_top': 10.0, 'UCS_bot': 10.5, 'Em_top': 7, 'Em_bot': 7} + ] + } +] + +# --- Create driven pile anchor --- +anchor = Anchor( + dd = { + 'type': 'driven', + 'design': { + 'L': 15.0, # Embedded length + 'D': 1.85, # Diameter + 'zlug': 1.5 # Padeye depth + } + }, + r = [0.0, 0.0, 0.0] +) + +# Assign mooring loads +anchor.loads = { + 'Hm': 2.5e6, + 'Vm': 2.5e5} + +anchor.line_type = 'chain' +anchor.d = 0.16 +anchor.w = 5000.0 + +# Assign local soil +anchor.setSoilProfile(profile_map) + +# --- Step 1: Capacity --- +anchor.getCapacityAnchor( + Hm = anchor.loads['Hm'], + Vm = anchor.loads['Vm'], + zlug = anchor.dd['design']['zlug'], + line_type = anchor.line_type, + d = anchor.d, + w = anchor.w, + plot = True) + +print('\nCapacity Results:') +for key, val in anchor.anchorCapacity.items(): + print(f'{key}: {val:.2f}') + +# --- Step 2: Optimize Anchor Geometry --- +anchor.getSizeAnchor( + geom = [anchor.dd['design']['L'], anchor.dd['design']['D']], + geomKeys = ['L', 'D'], + geomBounds = [(2.0, 70.0), (0.25, 3.0)], + loads = None, + lambdap_con = [4, 50], + zlug_fix = True, + safety_factor = {'SF_horizontal': 1, 'SF_vertical': 1}, + plot = True) \ No newline at end of file diff --git a/famodel/anchors/getCapacityPile_map.py b/examples/05_Anchors/anchor_driven_soil.py similarity index 55% rename from famodel/anchors/getCapacityPile_map.py rename to examples/05_Anchors/anchor_driven_soil.py index 38998786..4ea2efd1 100644 --- a/famodel/anchors/getCapacityPile_map.py +++ b/examples/05_Anchors/anchor_driven_soil.py @@ -1,5 +1,5 @@ -from anchor_map import Anchor +from famodel.anchors.anchor import Anchor # --- Define soil profile --- profile_map = [ @@ -7,9 +7,9 @@ 'name': 'CPT_D1', 'x': 0.0, 'y': 0.0, 'layers': [ - {'top': 1.0, 'bottom': 6.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 10.0, 'Su_top': 45, 'Su_bot': 60}, - {'top': 6.0, 'bottom': 15.0, 'soil_type': 'clay', 'gamma_top': 10.0, 'gamma_bot': 10.0, 'Su_top': 60, 'Su_bot': 80}, - {'top': 15.0, 'bottom': 35.0, 'soil_type': 'clay', 'gamma_top': 10.0, 'gamma_bot': 10.5, 'Su_top': 80, 'Su_bot': 100} + {'top': 1.5, 'bottom': 6.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 10.0, 'Su_top': 25, 'Su_bot': 200}, + {'top': 6.0, 'bottom': 15.0, 'soil_type': 'sand', 'gamma_top': 10.0, 'gamma_bot': 10.0, 'phi_top': 28, 'phi_bot': 32, 'Dr_top': 80, 'Dr_bot': 85}, + {'top': 15.0, 'bottom': 35.0, 'soil_type': 'clay', 'gamma_top': 10.0, 'gamma_bot': 10.5, 'Su_top': 100, 'Su_bot': 100} ] } ] @@ -20,8 +20,8 @@ 'type': 'driven', 'design': { 'L': 25.0, # Embedded length - 'D': 2.0, # Diameter - 'zlug': 10.0 # Padeye depth + 'D': 2.00, # Diameter + 'zlug': 3.0 # Padeye depth } }, r = [0.0, 0.0, 0.0] @@ -29,9 +29,9 @@ # Assign mooring loads anchor.loads = { - 'Hm': 4.0e6, - 'Vm': 2.5e6 -} + 'Hm': 7.0e5, + 'Vm': 2.5e5} + anchor.line_type = 'chain' anchor.d = 0.16 anchor.w = 5000.0 @@ -47,8 +47,7 @@ line_type = anchor.line_type, d = anchor.d, w = anchor.w, - plot = True -) + plot = True) print('\nLug Forces Computed:') print(f'Ha = {Ha:.2f} N') @@ -62,9 +61,19 @@ line_type = anchor.line_type, d = anchor.d, w = anchor.w, - plot = True -) + plot = True) print('\nCapacity Results:') -for key, val in anchor.capacity_results.items(): +for key, val in anchor.anchorCapacity.items(): print(f'{key}: {val:.2f}') + +# --- Step 3: Optimize Anchor Geometry --- +anchor.getSizeAnchor( + geom = [anchor.dd['design']['L'], anchor.dd['design']['D']], + geomKeys = ['L', 'D'], + geomBounds = [(2.0, 50.0), (0.25, 3.5)], + loads = None, + lambdap_con = [3, 50], + zlug_fix = True, + safety_factor = {'SF_horizontal': 1, 'SF_vertical': 1}, + plot = True) \ No newline at end of file diff --git a/famodel/anchors/getCapacityHelical_clay.py b/examples/05_Anchors/anchor_helical.py similarity index 62% rename from famodel/anchors/getCapacityHelical_clay.py rename to examples/05_Anchors/anchor_helical.py index f1367126..3c6c81e5 100644 --- a/famodel/anchors/getCapacityHelical_clay.py +++ b/examples/05_Anchors/anchor_helical.py @@ -1,5 +1,5 @@ -from anchor_map import Anchor +from famodel.anchors.anchor import Anchor # --- Soil profile for helical pile in clay --- profile_map = [ @@ -7,9 +7,9 @@ 'name': 'CPT_H1', 'x': 0.0, 'y': 0.0, 'layers': [ - {'top': 1.0, 'bottom': 3.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 9.0, 'Su_top': 60, 'Su_bot': 50}, - {'top': 3.0, 'bottom': 7.0, 'soil_type': 'clay', 'gamma_top': 15.0, 'gamma_bot': 25.0, 'Su_top': 100, 'Su_bot': 150}, - {'top': 7.0, 'bottom': 15.0, 'soil_type': 'clay', 'gamma_top': 25.0, 'gamma_bot': 50.0, 'Su_top': 200, 'Su_bot': 400} + {'top': 1.0, 'bottom': 3.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 9.0, 'Su_top': 60, 'Su_bot': 50}, + {'top': 3.0, 'bottom': 7.0, 'soil_type': 'clay', 'gamma_top': 15.0, 'gamma_bot': 25.0, 'Su_top': 100, 'Su_bot': 150}, + {'top': 7.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 25.0, 'gamma_bot': 50.0, 'Su_top': 200, 'Su_bot': 400} ] } ] @@ -30,9 +30,9 @@ # --- Assign mooring loads and properties --- anchor.loads = { - 'Hm': 80e4, - 'Vm': 50e3 -} + 'Hm': 8e5, + 'Vm': 1e5} + anchor.line_type = 'chain' anchor.d = 0.16 anchor.w = 5000.0 @@ -48,8 +48,7 @@ line_type = anchor.line_type, d = anchor.d, w = anchor.w, - plot = True -) + plot = True) print('\nLug Forces Computed:') print(f'Ha = {Ha:.2f} N') @@ -63,9 +62,19 @@ line_type = anchor.line_type, d = anchor.d, w = anchor.w, - plot = True -) + plot = False) print('\nCapacity Results:') -for key, val in anchor.capacity_results.items(): +for key, val in anchor.anchorCapacity.items(): print(f'{key}: {val:.2f}') + +# --- Step 3: Optimize Anchor Geometry --- +anchor.getSizeAnchor( + geom = [anchor.dd['design']['L'], anchor.dd['design']['D']], + geomKeys = ['L', 'D'], + geomBounds = [(6.0, 25.0), (0.5, 2.0)], + loads = None, + lambdap_con = [6, 15], + zlug_fix = True, + safety_factor = {'SF_horizontal': 1, 'SF_vertical': 1}, + plot = False) diff --git a/famodel/anchors/getCapacityPlate_map.py b/examples/05_Anchors/anchor_plate.py similarity index 67% rename from famodel/anchors/getCapacityPlate_map.py rename to examples/05_Anchors/anchor_plate.py index 088cd40b..f04c3675 100644 --- a/famodel/anchors/getCapacityPlate_map.py +++ b/examples/05_Anchors/anchor_plate.py @@ -1,7 +1,6 @@ -from anchor_map import Anchor -import numpy as np -from famodel.anchors.anchors_famodel_map.capacity_plots_map import plot_load +from famodel.anchors.anchor import Anchor +from famodel.anchors.anchors_famodel.support_plots import plot_load # --- Define soil profile --- profile_map = [ @@ -10,7 +9,7 @@ 'x': 0.0, 'y': 0.0, 'layers': [ {'top': 2.0, 'bottom': 4.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 8.5, 'Su_top': 10, 'Su_bot': 25}, - {'top': 4.0, 'bottom': 6.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 25, 'Su_bot': 50}, + {'top': 4.0, 'bottom': 6.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 15, 'Su_bot': 40}, {'top': 6.0, 'bottom': 16.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 9.5, 'Su_top': 50, 'Su_bot': 100}, {'top': 16.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 9.5, 'gamma_bot': 9.5, 'Su_top': 100, 'Su_bot': 100} ] @@ -19,15 +18,14 @@ # --- Create plate anchor --- anchor = Anchor( - dd = {'type': 'plate', 'design': {'B': 3.0, 'L': 6.0, 'zlug': 5.0, 'beta': 30.0}}, - r = [100.0, 100.0, 0.0] -) + dd = {'type': 'plate', 'design': {'B': 3.0, 'L': 6.0, 'zlug': 14.0, 'beta': 30.0}}, + r = [0.0, 0.0, 0.0]) # --- Assign load and mooring properties --- anchor.loads = { - 'Hm': 2.5e6, - 'Vm': 1.5e6 -} + 'Hm': 3.5e6, + 'Vm': 2.5e6} + anchor.line_type = 'chain' anchor.d = 0.16 anchor.w = 5000.0 @@ -43,8 +41,7 @@ line_type = anchor.line_type, d = anchor.d, w = anchor.w, - plot = True -) + plot = True) print('\nLug Forces Computed:') print(f'Ha = {Ha:.2f} N') @@ -58,9 +55,20 @@ line_type = anchor.line_type, d = anchor.d, w = anchor.w, - plot = True -) + plot = True) print('\nCapacity Results:') -for key, value in anchor.capacity_results.items(): +for key, value in anchor.anchorCapacity.items(): print(f'{key}: {value:.2f}') + +# --- Step 3: Optimize Anchor Geometry --- +anchor.getSizeAnchor( + geom = [anchor.dd['design']['B'], anchor.dd['design']['L']], + geomKeys = ['B', 'L'], + geomBounds = [(0.5, 6.0), (2.0, 12.0)], + loads = None, + lambdap_con = [2, 4], # less critical for plates + zlug_fix = True, + safety_factor = {'SF_horizontal': 2, 'SF_vertical': 3}, + #safety_factor = {'SF_combined': 3}, + plot = True) diff --git a/examples/05_Anchors/anchor_soil_layered.py b/examples/05_Anchors/anchor_soil_layered.py new file mode 100644 index 00000000..714eaefd --- /dev/null +++ b/examples/05_Anchors/anchor_soil_layered.py @@ -0,0 +1,65 @@ + + +from famodel import Project +from famodel.anchors.anchor import Anchor + +# Step 1: Initialize and load soil +proj = Project() +proj.loadSoil( + filename='inputs/GulfOfMaine_soil_layered_100x100.txt', + soil_mode='layered', + profile_source='inputs/GulfOfMaine_soil_profiles.yaml') + +for label, props in proj.soilProps.items(): + print(f"{label}: {props}") + +# Step 2: Create and register an anchor at a known position in the grid +anchor = Anchor( + dd = {'type': 'suction', 'design': {'D': 3.5, 'L': 12.0, 'zlug': 9.67}}, + r = [54.0, -4450.0, 0.0]) + +# Step 3: Assign local soil profile from project (nearest neighbor lookup) +soil_id, soil_profile = proj.getSoilAtLocation(anchor.r[0], anchor.r[1]) +anchor.soilProps = {soil_id: soil_profile} +anchor.setSoilProfile([{'name': soil_id, 'layers': soil_profile}]) # ensures `anchor.soil_profile` is set + +# Step 4: Assign loads and line +anchor.loads = {'Hm': 2e6, 'Vm': 1.5e6} +anchor.line_type = 'chain' +anchor.d = 0.16 +anchor.w = 5000.0 + +# Step 5: Run capacity check and optimization +anchor.getLugForces( + Hm=anchor.loads['Hm'], Vm=anchor.loads['Vm'], + zlug = anchor.dd['design']['zlug'], + d=anchor.d, w=anchor.w, + plot=True) + +anchor.getCapacityAnchor( + Hm=anchor.loads['Hm'], Vm=anchor.loads['Vm'], + zlug = anchor.dd['design']['zlug'], + line_type=anchor.line_type, d=anchor.d, w=anchor.w, + mass_update=True, + plot=True) +anchor.getCost() +print(f'Material cost: {anchor.cost["Material cost"]:.2f} USD [2024]') + +results = anchor.getSizeAnchor( + geom = [anchor.dd['design']['L'], anchor.dd['design']['D']], + geomKeys = ['L', 'D'], + geomBounds = [(8.0, 15.0), (2.0, 4.0)], + loads = None, + lambdap_con = [3, 6], + zlug_fix = False, + safety_factor = {'SF_combined': 1}, + plot = True) + +# Step 6: Report +print('\nFinal Optimized Anchor:') +print('Design:', anchor.dd['design']) +print('Capacity Results:', anchor.anchorCapacity) +anchor.getCost() +print(f'Material cost: {anchor.cost["Material cost"]:.2f} USD [2024]') + + diff --git a/examples/05_Anchors/anchor_soil_uniform.py b/examples/05_Anchors/anchor_soil_uniform.py new file mode 100644 index 00000000..01886c7f --- /dev/null +++ b/examples/05_Anchors/anchor_soil_uniform.py @@ -0,0 +1,69 @@ + +from famodel import Project +from famodel.anchors.anchor import Anchor + +# Step 1: Initialize and load soil +proj = Project() +proj.loadSoil( + filename='inputs/GulfOfMaine_soil_layered_100x100.txt', + soil_mode='uniform') # 'uniform' soil does not need from the profile_source yaml file + +for label, props in proj.soilProps.items(): + print(f"{label}: {props}") + +# Convert to profile_map format so anchor capacity models can use it +proj.convertUniformToLayered(default_layer=50.0) + +for label, props in proj.profile_map.items(): + print(f"{label}: {props}") + +# Step 2: Create and register an anchor at a known position in the grid +anchor = Anchor( + dd = {'type': 'suction', 'design': {'D': 3.5, 'L': 12.0, 'zlug': 9.67}}, + r = [54.0, -4450.0, 0.0]) + +# Step 3: Assign local soil profile from project (nearest neighbor lookup) +soil_id, _ = proj.getSoilAtLocation(anchor.r[0], anchor.r[1]) +soil_profile = proj.profile_map[soil_id] # get compatible layered format +anchor.soilProps = {soil_id: soil_profile} +anchor.setSoilProfile([{'name': soil_id, 'layers': soil_profile}]) # ensures `anchor.soil_profile` is set + +# Step 4: Assign loads and line +anchor.loads = {'Hm': 1e6, 'Vm': 5e4} +anchor.line_type = 'chain' +anchor.d = 0.16 +anchor.w = 5000.0 + +# Step 5: Run capacity check and optimization +anchor.getLugForces( + Hm=anchor.loads['Hm'], Vm=anchor.loads['Vm'], + zlug = anchor.dd['design']['zlug'], + d=anchor.d, w=anchor.w, + plot=True) + +anchor.getCapacityAnchor( + Hm=anchor.loads['Hm'], Vm=anchor.loads['Vm'], + zlug = anchor.dd['design']['zlug'], + line_type=anchor.line_type, d=anchor.d, w=anchor.w, + mass_update=True, + plot=True) +anchor.getCost() +print(f'Material cost: {anchor.cost["Material cost"]:.2f} USD [2024]') + +results = anchor.getSizeAnchor( + geom = [anchor.dd['design']['L'], anchor.dd['design']['D']], + geomKeys = ['L', 'D'], + geomBounds = [(8.0, 15.0), (2.0, 4.0)], + lambdap_con = [3, 6], + zlug_fix = False, + safety_factor = {'SF_combined': 1}, + plot = True) + +# Step 6: Report +print('\nFinal Optimized Anchor:') +print('Design:', anchor.dd['design']) +print('Capacity Results:', anchor.anchorCapacity) +anchor.getCost() +print(f'Material cost: {anchor.cost["Material cost"]:.2f} USD [2024]') + + diff --git a/famodel/anchors/getCapacitySuction_map.py b/examples/05_Anchors/anchor_suction.py similarity index 58% rename from famodel/anchors/getCapacitySuction_map.py rename to examples/05_Anchors/anchor_suction.py index 1c41ac6e..ccc4ea57 100644 --- a/famodel/anchors/getCapacitySuction_map.py +++ b/examples/05_Anchors/anchor_suction.py @@ -1,7 +1,6 @@ -from anchor_map import Anchor -import numpy as np -from famodel.anchors.anchors_famodel_map.capacity_plots_map import plot_load +from famodel.anchors.anchor import Anchor +from famodel.anchors.anchors_famodel.support_plots import plot_suction # --- Define soil profile --- profile_map = [ @@ -9,10 +8,10 @@ 'name': 'CPT_A1', 'x': 0.0, 'y': 0.0, 'layers': [ - {'top': 2.0, 'bottom': 4.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 8.5, 'Su_top': 10, 'Su_bot': 25}, - {'top': 4.0, 'bottom': 6.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 25, 'Su_bot': 50}, - {'top': 6.0, 'bottom': 16.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 9.5, 'Su_top': 50, 'Su_bot': 100}, - {'top': 16.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 9.5, 'gamma_bot': 9.5, 'Su_top': 100, 'Su_bot': 100} + {'top': 2.0, 'bottom': 4.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 8.5, 'Su_top': 10, 'Su_bot': 25}, + {'top': 4.0, 'bottom': 6.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 25, 'Su_bot': 50}, + {'top': 6.0, 'bottom': 16.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 9.5, 'Su_top': 50, 'Su_bot': 100}, + {'top': 16.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 9.5, 'gamma_bot': 9.5, 'Su_top': 100, 'Su_bot': 100} ] }, { @@ -29,10 +28,10 @@ 'name': 'CPT_A2', 'x': 0.0, 'y': 500.0, 'layers': [ - {'top': 2.0, 'bottom': 4.0, 'soil_type': 'clay', 'gamma_top': 7.5, 'gamma_bot': 8.0, 'Su_top': 5, 'Su_bot': 20}, - {'top': 4.0, 'bottom': 8.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 8.5, 'Su_top': 20, 'Su_bot': 45}, - {'top': 8.0, 'bottom': 16.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 45, 'Su_bot': 95}, - {'top': 16.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 9.0, 'Su_top': 95, 'Su_bot': 95} + {'top': 2.0, 'bottom': 4.0, 'soil_type': 'clay', 'gamma_top': 7.5, 'gamma_bot': 8.0, 'Su_top': 5, 'Su_bot': 20}, + {'top': 4.0, 'bottom': 8.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 8.5, 'Su_top': 20, 'Su_bot': 45}, + {'top': 8.0, 'bottom': 16.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 45, 'Su_bot': 95}, + {'top': 16.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 9.0, 'Su_top': 95, 'Su_bot': 95} ] }, { @@ -49,14 +48,27 @@ anchor = Anchor( - dd = {'type': 'suction', 'design': {'D': 2.5, 'L': 12.0, 'zlug': 9.0}}, - r = [250.0, 000.0, 000.0] -) + dd = {'type': 'suction', 'design': {'D': 2.5, 'L': 12.0, 'zlug': 8.67}}, + r = [250.0, 250.0, 000.0]) + +# --- Step 0: Create anchor based grid CPTs --- +anchor.interpolateSoilProfile(profile_map) + +# --- Step 1: Plot suction pile and soil profile --- +# Access anchor geometrical properties +L = anchor.dd['design']['L'] +D = anchor.dd['design']['D'] +zlug = anchor.dd['design']['zlug'] +# Access matched profile +layers = anchor.soil_profile[0]['layers'] +z0 = layers[0]['top'] + +plot_suction(layers, L=L, D=D, z0=z0, zlug=zlug) # Assign loads manually anchor.loads = { - 'Hm': 3e6, # Horizontal mudline load (N) - 'Vm': 2e6 # Vertical mudline load (N) + 'Hm': 3.0e6, # Horizontal mudline load (N) + 'Vm': 1.0e6 # Vertical mudline load (N) } # Assign line properties manually @@ -64,11 +76,8 @@ anchor.d = 0.16 # Chain diameter (m) anchor.w = 5000.0 # Nominal submerged weight (N/m) -# --- Step 0: Create anchor based grid CPTs --- -anchor.setSoilProfile(profile_map) - -# --- Step 1: Compute Lug Forces --- +# --- Step 2: Compute Lug Forces --- layers, Ha, Va = anchor.getLugForces( Hm = anchor.loads['Hm'], Vm = anchor.loads['Vm'], @@ -76,43 +85,55 @@ line_type = anchor.line_type, d = anchor.d, w = anchor.w, - plot = True -) + plot = True) print('\nLug Forces Computed:') print(f'Ha = {Ha:.2f} N') print(f'Va = {Va:.2f} N') -# --- Step 2: Compute Capacity --- +# --- Step 3: Compute Capacity --- anchor.getCapacityAnchor( Hm = anchor.loads['Hm'], Vm = anchor.loads['Vm'], zlug = anchor.dd['design']['zlug'], line_type = anchor.line_type, - d = anchor.d, - w = anchor.w, - plot = True -) + d = anchor.d, w = anchor.w, + mass_update=False, + plot = True) print('\nCapacity Results:') -for key, value in anchor.capacity_results.items(): +for key, value in anchor.anchorCapacity.items(): print(f'{key}: {value:.2f}') + +# --- Step 4: Compute Costs --- +anchor.getCost() + +print(f"Mass: {anchor.anchorCapacity['Weight pile']/9.81:.2f} kg") +print(f"Material unit cost: {anchor.cost['unit_cost']:.2f} USD/kg") +print(f'Material cost: {anchor.cost["Material cost"]:.2f} USD [2024]') -# --- Step 3: Optimize Anchor Geometry --- +#%% +# --- Step 5: Optimize Anchor Geometry --- anchor.getSizeAnchor( geom = [anchor.dd['design']['L'], anchor.dd['design']['D']], geomKeys = ['L', 'D'], - geomBounds = [(5.0, 15.0), (2.0, 6.0)], + geomBounds = [(5.0, 15.0), (1.0, 4.0)], loads = None, - minfs = {'Ha': 1.0, 'Va': 1.0}, lambdap_con = [3, 6], zlug_fix = False, - plot = True -) + safety_factor = {'SF_horizontal': 2, 'SF_vertical': 3}, + plot = True) print('\nFinal Optimized Anchor:') print('Design:', anchor.dd['design']) -print('Capacity Results:', anchor.capacity_results) +print('Capacity Results:', anchor.anchorCapacity) + +# # --- Step 6: Compute Costs --- +anchor.getCost() + +print(f"Mass: {anchor.anchorCapacity['Weight pile']/9.81:.2f} kg") +print(f"Material unit cost: {anchor.cost['unit_cost']:.2f} USD/kg") +print(f'Material cost: {anchor.cost["Material cost"]:.2f} USD [2024]') -# --- Step 4: Visualize Anchor Geometry --- -anchor.getCombinedPlot() +# --- Step 7: Visualize Anchor Geometry --- +# anchor.getCombinedPlot() diff --git a/famodel/anchors/getCapacityTorpedo_map.py b/examples/05_Anchors/anchor_torpedo.py similarity index 85% rename from famodel/anchors/getCapacityTorpedo_map.py rename to examples/05_Anchors/anchor_torpedo.py index 6ecb01cb..9201f289 100644 --- a/famodel/anchors/getCapacityTorpedo_map.py +++ b/examples/05_Anchors/anchor_torpedo.py @@ -1,6 +1,6 @@ -from anchor_map import Anchor -from famodel.anchors.anchors_famodel_map.capacity_plots_map import plot_load +from famodel.anchors.anchor import Anchor +from famodel.anchors.anchors_famodel.support_plots import plot_load # --- Define soil profile --- profile_map = [ @@ -10,7 +10,7 @@ 'layers': [ {'top': 0.0, 'bottom': 20.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 8.5, 'Su_top': 50, 'Su_bot': 70}, {'top': 20.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 8.5, 'Su_top': 80, 'Su_bot': 100}, - {'top': 25.0, 'bottom': 50.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 125, 'Su_bot': 150} + {'top': 25.0, 'bottom': 50.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 100, 'Su_bot': 150} ] } ] @@ -24,7 +24,7 @@ 'D2': 1.5, # Shaft diameter 'L1': 11.0, # Winged section length 'L2': 5.0, # Shaft section length - 'zlug': 20.0, # Padeye depth + 'zlug': 15.0, # Padeye depth 'ballast': 10000 } }, @@ -71,7 +71,7 @@ ) print('\nCapacity Results:') -for key, value in anchor.capacity_results.items(): +for key, value in anchor.anchorCapacity.items(): print(f'{key}: {value:.2f}') @@ -84,15 +84,14 @@ geomKeys = ['L1', 'D1'], geomBounds = [(7.0, 25.0), (2.5, 4.5)], loads = None, - minfs = {'Ha': 1.0, 'Va': 1.0}, lambdap_con = [2, 8], zlug_fix = True, - plot = True -) + safety_factor = {'SF_combined': 1}, + plot = True) print('\nFinal Optimized Anchor:') print('Design:', anchor.dd['design']) -print('Capacity Results:', anchor.capacity_results) +print('Capacity Results:', anchor.anchorCapacity) # --- Step 4: Visualize Anchor Geometry --- # anchor.getCombinedPlot() diff --git a/examples/05_Anchors/example_suction.ipynb b/examples/05_Anchors/example_suction.ipynb new file mode 100644 index 00000000..34149187 --- /dev/null +++ b/examples/05_Anchors/example_suction.ipynb @@ -0,0 +1,544 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ef2db749", + "metadata": {}, + "source": [ + "# Suction Anchor Capacity – Jupyter Notebook" + ] + }, + { + "cell_type": "markdown", + "id": "cf0c1c98", + "metadata": {}, + "source": [ + "### Step 1: Import required libraries\n", + "\n", + "We begin by importing the essential modules:\n", + "\n", + "- `Anchor` from `famodel.anchors.anchor`: the main class that encapsulates the suction anchor's capacity methods - soil properties, anchor geometry and extreme loads.\n", + "- `plot_suction` from `famodel.anchors.anchors_famodel.capacity_plots`: a custom plotting utility that visualizes anchor geometry and soil properties.\n", + "\n", + "These imports set up the environment to define, simulate, and visualize the anchor system." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9f2d8d4b", + "metadata": {}, + "outputs": [], + "source": [ + "from famodel.anchors.anchor import Anchor\n", + "from famodel.anchors.anchors_famodel.support_plots import plot_suction" + ] + }, + { + "cell_type": "markdown", + "id": "b84ceffb", + "metadata": {}, + "source": [ + "### Step 2: Define the layered soil profile map\n", + "We create a list of CPT locations in the vertices of a 500x500 m square within the Lease Area, each with a set of layered clay soil parameters." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "935551c4", + "metadata": {}, + "outputs": [], + "source": [ + "profile_map = [\n", + " {\n", + " 'name': 'CPT_A1',\n", + " 'x': 0.0, 'y': 0.0,\n", + " 'layers': [\n", + " {'top': 2.0, 'bottom': 4.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 8.5, 'Su_top': 10, 'Su_bot': 25},\n", + " {'top': 4.0, 'bottom': 6.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 25, 'Su_bot': 50},\n", + " {'top': 6.0, 'bottom': 16.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 9.5, 'Su_top': 50, 'Su_bot': 100},\n", + " {'top': 16.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 9.5, 'gamma_bot': 9.5, 'Su_top': 100, 'Su_bot': 100}\n", + " ]\n", + " },\n", + " {\n", + " 'name': 'CPT_B1',\n", + " 'x': 500.0, 'y': 0.0,\n", + " 'layers': [\n", + " {'top': 2.0, 'bottom': 4.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 15, 'Su_bot': 30},\n", + " {'top': 4.0, 'bottom': 6.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 9.5, 'Su_top': 30, 'Su_bot': 55},\n", + " {'top': 6.0, 'bottom': 16.0, 'soil_type': 'clay', 'gamma_top': 9.5, 'gamma_bot': 10.0, 'Su_top': 55, 'Su_bot': 105},\n", + " {'top': 16.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 10.0, 'gamma_bot': 10.0, 'Su_top': 105, 'Su_bot': 105}\n", + " ]\n", + " },\n", + " {\n", + " 'name': 'CPT_A2',\n", + " 'x': 0.0, 'y': 500.0,\n", + " 'layers': [\n", + " {'top': 2.0, 'bottom': 4.0, 'soil_type': 'clay', 'gamma_top': 7.5, 'gamma_bot': 8.0, 'Su_top': 5, 'Su_bot': 20},\n", + " {'top': 4.0, 'bottom': 8.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 8.5, 'Su_top': 20, 'Su_bot': 45},\n", + " {'top': 8.0, 'bottom': 16.0, 'soil_type': 'clay', 'gamma_top': 8.5, 'gamma_bot': 9.0, 'Su_top': 45, 'Su_bot': 95},\n", + " {'top': 16.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 9.0, 'Su_top': 95, 'Su_bot': 95}\n", + " ]\n", + " },\n", + " {\n", + " 'name': 'CPT_B2',\n", + " 'x': 500.0, 'y': 500.0,\n", + " 'layers': [\n", + " {'top': 1.0, 'bottom': 2.0, 'soil_type': 'clay', 'gamma_top': 9.0, 'gamma_bot': 9.5, 'Su_top': 20, 'Su_bot': 35},\n", + " {'top': 2.0, 'bottom': 8.0, 'soil_type': 'clay', 'gamma_top': 9.5, 'gamma_bot': 10.0, 'Su_top': 35, 'Su_bot': 60},\n", + " {'top': 8.0, 'bottom': 16.0, 'soil_type': 'clay', 'gamma_top': 10.0, 'gamma_bot': 10.5, 'Su_top': 60, 'Su_bot': 110},\n", + " {'top': 16.0, 'bottom': 25.0, 'soil_type': 'clay', 'gamma_top': 10.5, 'gamma_bot': 10.5, 'Su_top': 110, 'Su_bot': 110}\n", + " ]\n", + " }\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "6d32c699", + "metadata": {}, + "source": [ + "### Step 3: Initialize the anchor object\n", + "We define a suction anchor with its type, initial geometry and anchor location within the defined area." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "3aab0b15", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "zlug: 8.67\n", + "L: 12.0\n" + ] + } + ], + "source": [ + "anchor = Anchor(\n", + " dd = {'type': 'suction', 'design': {'D': 2.5, 'L': 12.0, 'zlug': 8.67}},\n", + " r = [250.0, 250.0, 0.0]\n", + ")\n", + "print('zlug:', anchor.dd['design']['zlug'])\n", + "print('L:', anchor.dd['design']['L'])\n" + ] + }, + { + "cell_type": "markdown", + "id": "c26832ae", + "metadata": {}, + "source": [ + "### Step 4: Assign soil profile to anchor location\n", + "This connects the anchor object to the appropriate CPT soil data based on proximity." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "368fac90", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "zlug: 8.67\n", + "L: 12.0\n" + ] + } + ], + "source": [ + "anchor.interpolateSoilProfile(profile_map)\n", + "print('zlug:', anchor.dd['design']['zlug'])\n", + "print('L:', anchor.dd['design']['L'])\n" + ] + }, + { + "cell_type": "markdown", + "id": "b7ca698d", + "metadata": {}, + "source": [ + "### Step 5: Plot suction anchor and soil profile\n", + "We represent a suction anchor embedded in the soil." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "71419ebe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "zlug: 8.67\n", + "L: 12.0\n", + "{'soil_type': 'clay', 'top': 1.75, 'bottom': 3.5, 'gamma_top': 8.25, 'gamma_bot': 8.75, 'Su_top': 12.5, 'Su_bot': 27.5}\n" + ] + }, + { + "data": { + "image/png": "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J0yePBlv376Fra0thg4diilTpkBPTy+vNp+ICiEWFkT0xdHT08P06dOxePFi3LlzRzFdIpFkuvgWQKYDxdKlS+fphajpB80RERGZCpYXL17A0tIyz9YFpB38pRdZOZWe07Jly1TeQcra2lrl8tu3b4eTkxN2796tdICe1f7XRMmSJSESiRAZGZlpXlbTNGVhYYExY8YgODgYd+7cQfv27WFhYYErV65AEASl3KOiopCamprnvy9V9u/fj4SEBOzduxcODg6K6Vnd4hgARo0aBW9vb9y4cQPLly9H5cqV4eHhoZifnvf//vc/pfZUUfVskJo1a2LXrl0QBAF///03Nm/ejICAABgaGuKHH37QYguJqKjhUCgiKtYiIiKynJ4+3MbOzk4xzdHREX///bdS3OnTp/Hu3Tulae3atcOZM2fwzz//qFyvRCIBAI3OIrRs2RIAMl18ffXqVdy/f19xt53CpGnTpihRogTu3bunOBv06UvdWRCRSAR9fX2lg9PIyMgcPy/C2NgYDRs2xN69e5XucBQfH48DBw5ku7xUKlV5puHTvtKqVSu8e/cO+/fvV4pLv+j8c/2+0vddel8D0h7yt27duizj0x8S+f333+PkyZMYPny40v739PSErq4uHj9+rPJ3qm1+tWvXxuLFi1GiRAncuHEjB1tJREUJz1gQUbHm6ekJe3t7dOzYEVWqVIFcLkdISAh++eUXmJiYYPTo0YrY/v37Y+rUqZg2bRpcXV1x7949LF++HObm5kptBgQE4MiRI2jRogUmT56MmjVrIiYmBkePHsW4ceNQpUoVVKhQAYaGhtixYweqVq0KExMT2NnZKRUy6ZydnfHNN99g2bJlEIvFaNeuHcLCwjB16lSULVsWY8eOzff9pC0TExMsW7YMAwYMQHR0NHr06AErKyu8evUKt27dwqtXrxQP3MtKhw4dsHfvXgwfPhw9evTAs2fPMGvWLNja2uLhw4c5ymnWrFlo27YtPDw88P3330Mmk2HevHkwNjZGdHS02mVjY2Ph6OgIb29vtG7dGmXLlsW7d+8QHByMpUuXomrVqoo7Pvn4+GDFihUYMGAAwsLCULNmTVy4cAE///wz2rdvj9atW+co/6zcvn0b//vf/zJNb9CgATw8PKCvr48+ffpg4sSJSEpKwqpVq/D27dss29LR0cGIESMwadIkGBsbZ7qm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Z2rQoEEKCQnRqlWralwnUpfKykoNHTpUzz77bI37IiMj7f++fft2SdKxY8d07Nixet8TV7db2+uurKx0uX+pKqgZhlHrxda1bd+V5zx27JjatGnjVh8AcD4QLACgCYiJidHWrVsd1m3fvl1XXXWV/WiFK06fPq3ExER16dJFL7zwQo3nKC8v186dO+3XRfzwww/av3+/rrnmGpefw9/fXxUVFQ7rtm3bpujoaD3++OP2dd98843L25SkHj16aPXq1erYsaPTT7k6dOiQJk+erCVLluitt97SmDFjtHHjRvuRgNp6c2W7rvDz86ux7Z/z9/dXTEyMvvjiC8vfY1Ht888/V3x8fKNsCwCs4OJtAGgC/vCHP2jjxo166qmntH//fi1fvlyLFi2yXzTtqgcffFC5ublasGCBjh49qoKCAhUUFOjMmTPq3LmzEhMTNW7cOG3dulX79u3Tvffeq7Zt29Y4DasuHTt21KeffqqvvvpKhYWFKisr05VXXqmcnBytWrVKhw4d0oIFC9z+JKMJEybo2LFjuueee/Sf//xHX3/9tT744AP99re/VUVFhSoqKpScnKyBAwfqvvvu09KlS/X55587HBXp2LGjdu7cqezsbBUWFqqysrLe7brzujdu3KiCgoI6P/510KBBNUJiQ5WUlGj37t2NFlIAwAqCBQA0AT169NBbb72lVatWKTY2Vk8++aRmzZqllJQUt7azefNm5efnKyYmRpGRkfZb9elDS5cuVc+ePTVkyBD17dtXpmlq/fr1NU7Jqcu4ceN09dVXq1evXmrTpo22bdumxMRETZ48WQ899JDi4uK0fft2t78gLioqStu2bVNFRYUGDRqk2NhYTZw4USEhIbLZbHrmmWeUnZ2tV155RZIUERGhv/zlL3riiSfsH7c7depU+fj4KCYmRm3atFFOTk6923XV3LlztWHDBrVv317du3ev8/1Zv369ioqK3Hr9tVm3bp06dOjQKN+JAQBWGWZ9J8YCAIBGlZSUpO7du2v69OmWttO7d29NmjRJo0ePbqTOAKDhOGIBAMAFNmfOnFo/hcodR44c0ciRI3XPPfc0UlcAYA1HLAAAAABYxhELAAAAAJYRLAAAAABYRrAAAAAAYBnBAgAAAIBlBAsAAAAAlhEsAAAAAFhGsAAAAABgGcECAAAAgGUECwAAAACW/X+g8QVIJUUlcQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Access anchor geometrical properties\n", + "L = anchor.dd['design']['L']\n", + "D = anchor.dd['design']['D']\n", + "zlug = anchor.dd['design']['zlug']\n", + "print('zlug:', anchor.dd['design']['zlug'])\n", + "print('L:', anchor.dd['design']['L'])\n", + "# Access matched profile\n", + "layers = anchor.soil_profile[0]['layers']\n", + "print(layers[0])\n", + "z0 = layers[0]['top'] \n", + "\n", + "plot_suction(layers, L=L, D=D, z0=z0, zlug=zlug)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "3d5ee57b", + "metadata": {}, + "source": [ + "### Step 6: Assign external loads and line properties\n", + "We assign horizontal and vertical loads and specify the mooring line type and its physical properties (nominal diameter and weight (N/m))." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "38df38f6", + "metadata": {}, + "outputs": [], + "source": [ + "anchor.loads = {\n", + " 'Hm': 3e6,\n", + " 'Vm': 2e6\n", + "}\n", + "anchor.line_type = 'chain'\n", + "anchor.d = 0.16\n", + "anchor.w = 5000.0\n" + ] + }, + { + "cell_type": "markdown", + "id": "b70c8102", + "metadata": {}, + "source": [ + "### Step 7: Compute lug forces\n", + "We compute the forces acting at the lug using load, geometry, and soil interaction. " + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "4ae865bd", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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WKaSBwC4cuUKbGxs0qwXi8UQi8UpynV1dbP8B5sd+6T8hX2A2AeIfYDYByi7+4Am+y5QCcSQIUOwZcsW7N+/H8bGxoiMjAQAmJqawsDAAAAwfvx4PH/+HBs2bAAALFy4EA4ODqhUqRKSkpKwadMm7N69G7t3786110FERERElFcVqARi2bJlAIAmTZqolK9duxa9evUCALx8+RJPnjxR1iUlJWH06NF4/vw5DAwMUKlSJfj7+8PHxyenwiYiIiIiyjcKVAKhzu0c69atU3k+duxYjB07NpsiIiIiIiIqWAr0OhBERERERJS1mEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHamEAQEREREZHaCmQC8ffff8PR0RH6+vqoUaMGTp48mW7748ePo0aNGtDX10fJkiWxfPnyHIqUiIiIiCh/KXAJxPbt2zF8+HBMmDABV65cQaNGjeDt7Y0nT56k2j4iIgI+Pj5o1KgRrly5gl9//RXDhg3D7t27czhyIiIiIqK8r8AlEH/++Sd++ukn9O3bFxUqVMDChQtha2uLZcuWpdp++fLlsLOzw8KFC1Gh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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Lug Forces Computed:\n", + "Ha = 1904935.43 N\n", + "Va = 2787196.16 N\n" + ] + } + ], + "source": [ + "layers, Ha, Va = anchor.getLugForces(\n", + " Hm = anchor.loads['Hm'],\n", + " Vm = anchor.loads['Vm'],\n", + " zlug = anchor.dd['design']['zlug'],\n", + " line_type = anchor.line_type,\n", + " d = anchor.d,\n", + " w = anchor.w,\n", + " plot = True\n", + ")\n", + "\n", + "print('\\nLug Forces Computed:')\n", + "print(f'Ha = {Ha:.2f} N')\n", + "print(f'Va = {Va:.2f} N')" + ] + }, + { + "cell_type": "markdown", + "id": "97f25452", + "metadata": {}, + "source": [ + "### Step 8: Compute the anchor capacity\n", + "This checks whether the current anchor design meets load requirements. Results and plots are printed for reference." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "aea072d6", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Capacity Results:\n", + "Hmax: 8496895.31\n", + "Vmax: 6037871.08\n", + "Ha: 1904935.43\n", + "Va: 2787196.16\n", + "zlug: 8.67\n", + "z0: 1.75\n", + "UC: 0.01\n", + "Weight pile: 457496.77\n", + "Initial mass from dd: Not defined\n" + ] + } + ], + "source": [ + "anchor.getCapacityAnchor(\n", + " Hm = anchor.loads['Hm'],\n", + " Vm = anchor.loads['Vm'],\n", + " zlug = anchor.dd['design']['zlug'],\n", + " line_type = anchor.line_type,\n", + " d = anchor.d,\n", + " w = anchor.w,\n", + " plot = True\n", + ")\n", + "\n", + "print('\\nCapacity Results:')\n", + "for key, value in anchor.anchorCapacity.items():\n", + " print(f'{key}: {value:.2f}')\n", + "print('Initial mass from dd:', anchor.dd['design'].get('mass', 'Not defined'))" + ] + }, + { + "cell_type": "markdown", + "id": "052f68ee", + "metadata": {}, + "source": [ + "### Step 9: Anchor material costs\n", + "We assess the cost of the suction pile defined by the manufacturing cost (USD/kg)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "2858630b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mass: 46635.76 kg\n", + "Material unit cost: 10.25 USD/kg\n", + "Material cost: 478016.50 USD [2024]\n" + ] + } + ], + "source": [ + "anchor.getCost()\n", + "\n", + "print(f\"Mass: {anchor.anchorCapacity['Weight pile']/9.81:.2f} kg\")\n", + "print(f\"Material unit cost: {anchor.cost['unit_cost']:.2f} USD/kg\")\n", + "print(f'Material cost: {anchor.cost[\"Material cost\"]:.2f} USD [2024]')\n" + ] + }, + { + "cell_type": "markdown", + "id": "ec72f15a", + "metadata": {}, + "source": [ + "### Step 10: Optimize anchor geometry\n", + "We optimize anchor length and diameter to ensure capacity requirements are met efficiently within given bounds. Note that a safety factor (SF_combined) = 2 is used in this optimization process. This means that the unity check (UC = 1/SF) equals 0.5. This way the design can accept some extra capacity based on input preference." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "304da340", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[Debug] Anchor type parsed: 'suction'\n" + ] + }, + { + "data": { + "image/png": "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C23w8IDevc3TBjc3N958801ee+016urqmDZtGv/973+vGHK7kI5KGbu5ufH000+Lrx944AGWLFlCRUWFGFVpTU5ODo8++igKhYKYmBgxz/hSTs68efNYsWKF6OQsX76cefPm8fLLL7fZ76GHHuK1117j0Ucfbfd7bQVnDQ7bpnWEtaeQSoViomlp8MwzQlTnt98Eh2ftWigshA8+EDa5HIYPFxaGTpkCAwcKn3difSiVSsLDwy+6n+l0OqqqqqisrLxoq66uRqvVUlxc3EZq14RUKsXLywtvb2+8vb3bPPf29sbDw8NuZJfN0fcchdYRR1PKpel5e+mWEokEPz8/QkNDRacmMDCwUw62037Wzbp1cNttQpFPd3dYsUIQzzHhqPbrMSdn4cKFLFy4sKcO32nOnIE+fS7999OnzePo/PLLL7z88susX7+eyMhIbr/9dh555BE++OCDi/YtKSnhL3/5C2vXrsXPz4/Zs2czceJEioqK+O677/jss886/f27du0iKCjoko7G/fffz5dffsmIESPIzc1l9+7dbZykC4mPj0cmk5Genk6fPn349ddf+e233y5ycvr27cv06dN59dVXeeGFFzrdbmtBq9U6lZdsmLNnz4pFJ81FSAjcdZewNTfDli2Cw7N6tXBdMokX/OUv4O8PkyYJDs/kycJnnVg3crmcgIAAAgICLvqbXq+nurqaioqKdh0gg8FAVVXVJWv+mMQ/WjtAHh4eeHp64uHhgYeHB25ubjYRDbJE37N1tFot1dXVVFZWio60yaExiehciFQqxc/Pr02B3ODg4KteCuC0n3XS0iLcO/75T+F1UhJ8/TUkJrbdz1Ht5zCjNVME5/PPBalXEydOwIIF7Ud4usqkSZPazL5pNBpxXcs333zDokWLSPi9ES+++CJpaWntOjm7d+9m2rRpvPrqq2RnZ7NixQqeeuopYmNjL+t4XIqamhruvffeyzoZI0aM4K233sLNzQ29Xs+zzz57yfU7JubNm8fy5csZOnQoI0aMuGRU6umnn2b48OE8+uijnW67tdDS0mLpJji5CkpLSy36/a6ugvMyebLw+uxZoer0mjWwcSOUl8MXXwgbQL9+56M8I0cKn3diO8hkMvz8/NqdVDIYDNTV1VFdXU1NTQ3V1dXiZnptUuM0KZO1h0kx0eT0tHaATIpxbm5uqFQqizpDlu57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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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GERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkOYMXGN9++y3q1asHuVyOVq1aIS4uTmvfmJgYyGQytc/Vq1dfY8RERERUHIMWGHv27MGUKVMwZ84cJCQkwNfXFz179kRqamqRyyUnJyMtLU35adSo0WuKmIiIiHRhYsiNr1ixAmPGjMHYsWMBAKtWrcKxY8ewbt06LFmyROty9vb2qFq1qk7byMnJQU5OjnI6IyMDAJCXp4BCoSh58BVQYT6YF3XMjXbMjWbMi3bMjXZlPTf6xCUTQohSjEWr3NxcWFpaYt++fejXr5+yffLkyUhMTMSpU6fUlomJiYGfnx9cXV2RnZ0NDw8PfPbZZ/Dz89O6nQULFiAkJEStffPmPahe3VyanSEiIqoEsrKyMGzYMDx58gQ2NjZF9jXYGYz79+8jPz8fDg4OKu0ODg5IT0/XuIyjoyP++9//olWrVsjJycG2bdvQtWtXxMTEoGPHjhqXmTVrFoKDg5XTGRkZcHZ2RqdOHeHsbCfdDlUACoUC0dHR8Pf3h6mpqaHDKVOYG+2YG82YF+2YG+3Kem4KrwLowqCXSABAJpOpTAsh1NoKubu7w93dXTnt4+OD27dvY/ny5VoLDHNzc5ibq5+pMDExLZNfXllgasrcaMPcaMfcaMa8aMfcaFdWc6NPTAYb5FmjRg0YGxurna24e/eu2lmNorRt2xZ//PGH1OERERHRKzBYgWFmZoZWrVohOjpapT06Ohrt2rXTeT0JCQlwdHSUOjwiIiJ6BQa9RBIcHIwRI0bA29sbPj4++O9//4vU1FSMGzcOwIvxE3fu3MHWrVsBvLjLxNXVFU2bNkVubi62b9+OiIgIREREGHI3iIiI6CUGLTDeeecdPHjwAAsXLkRaWhqaNWuGqKgouLi4AADS0tJUnomRm5uLadOm4c6dO7CwsEDTpk1x5MgRBAQEGGoXiIiISAODD/IcP348xo8fr3FeeHi4yvT06dMxffr01xAVERERvQqDPyqciIiIKh4WGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5FhhEREQkORYYREREJDkWGERERCQ5gxcY3377LerVqwe5XI5WrVohLi6uyP6nTp1Cq1atIJfLUb9+faxfv/41RUpERES6MmiBsWfPHkyZMgVz5sxBQkICfH190bNnT6Smpmrsn5KSgoCAAPj6+iIhIQGzZ8/GpEmTEBER8ZojJyIioqIYtMBYsWIFxowZg7Fjx6JJkyZYtWoVnJ2dsW7dOo39169fj7p162LVqlVo0qQJxo4di9GjR2P58uWvOXIiIiIqiomhNpybm4v4+HjMnDlTpb179+44e/asxmXOnTuH7t27q7T16NEDoaGhUCgUMDU1VVsmJycHOTk5yuknT54AAB49eogqVV51LyoWhUKBrKwsPHjwQGMuKzPmRjvmRjPmRTvmRruynpunT58CAIQQxfY1WIFx//595Ofnw8HBQaXdwcEB6enpGpdJT0/X2D8vLw/379+Ho6Oj2jJLlixBSEiIWnuLFm6vED0REVHl9fTpU9ja2hbZx2AFRiGZTKYyLYRQayuuv6b2QrNmzUJwcLBy+vHjx3BxcUFqamqxyalsMjIy4OzsjNu3b8PGxsbQ4ZQpzI12zI1mzIt2zI12ZT03Qgg8ffoUTk5OxfY1WIFRo0YNGBsbq52tuHv3rtpZikK1atXS2N/ExAR2dnYalzE3N4e5ublau62tbZn88soCGxsb5kYL5kY75kYz5kU75ka7spwbXf84N9ggTzMzM7Rq1QrR0dEq7dHR0WjXrp3GZXx8fNT6Hz9+HN7e3mXyWhUREVFlZdC7SIKDg7Fp0yZs3rwZSUlJmDp1KlJTUzFu3DgALy5vjBw5Utl/3LhxuHXrFoKDg5GUlITNmzcjNDQU06ZNM9QuEBERkQYGHYPxzjvv4MGDB1i4cCHS0tLQrFkzREVFwcXFBQCQlpam8kyMevXqISoqClOnTsXatWvh5OSEr7/+GgMGDNB5m+bm5pg/f77GyyaVHXOjHXOjHXOjGfOiHXOjXUXKjUzocq8JERERkR4M/qhwIiIiqnhYYBAREZHkWGAQERGR5FhgEBERkeQqZIHBV8Brp09uYmJiIJPJ1D5Xr159jRGXvtjYWPTu3RtOTk6QyWQ4ePBgsctUlmNG39xUlmNmyZIlaN26NaytrWFvb4/AwEAkJycXu1xlOG5KkpvKctysW7cOzZs3Vz5Ey8fHBz/88EORy5TnY6bCFRh8Bbx2+uamUHJyMtLS0pSfRo0avaaIX4/MzEx4enpizZo1OvWvTMeMvrkpVNGPmVOnTuHjjz/G+fPnER0djby8PHTv3h2ZmZlal6ksx01JclOooh83derUwRdffIGLFy/i4sWL6NKlC/r27Yvff/9dY/9yf8yICubNN98U48aNU2lr3LixmDlzpsb+06dPF40bN1Zp+/DDD0Xbtm1LLUZD0Tc3J0+eFADEo0ePXkN0ZQMAERkZWWSfynTM/JsuuamMx4wQQty9e1cAEKdOndLap7IeN7rkprIeN0IIUa1aNbFp0yaN88r7MVOhzmAUvgL+5Ve6l+QV8BcvXoRCoSi1WF+3kuSmkJeXFxwdHdG1a1ecPHmyNMMsFyrLMfMqKtsx8+TJEwBA9erVtfaprMeNLrkpVJmOm/z8fOzevRuZmZnw8fHR2Ke8HzMVqsAojVfAVxQlyY2joyP++9//IiIiAgcOHIC7uzu6du2K2NjY1xFymVVZjpmSqIzHjBACwcHB6NChA5o1a6a1X2U8bnTNTWU6bi5fvgwrKyuYm5tj3LhxiIyMhIeHh8a+5f2YMfjr2ktDab8CvjzTJzfu7u5wd3dXTvv4+OD27dtYvnw5OnbsWKpxlnWV6ZjRR2U8ZiZMmIBff/0Vp0+fLrZvZTtudM1NZTpu3N3dkZiYiMePHyMiIgJBQUE4deqU1iKjPB8zFeoMxut6BXx5VJLcaNK2bVv88ccfUodXrlSWY0YqFfmYmThxIg4dOoSTJ0+iTp06RfatbMeNPrnRpKIeN2ZmZmjYsCG8vb2xZMkSeHp6YvXq1Rr7lvdjpkIVGHwFvHYlyY0mCQkJcHR0lDq8cqWyHDNSqYjHjBACEyZMwIEDB/DTTz+hXr16xS5TWY6bkuRGk4p43GgihEBOTo7GeeX+mDHQ4NJSs3v3bmFqaipCQ0PFlStXxJQpU0SVKlXEzZs3hRBCzJw5U4wYMULZ/8aNG8LS0lJMnTpVXLlyRYSGhgpTU1Oxf/9+Q+1CqdE3NytXrhSRkZHi2rVr4rfffhMzZ84UAERERIShdqFUPH36VCQkJIiEhAQBQKxYsUIkJCSIW7duCSEq9zGjb24qyzHz0UcfCVtbWxETEyPS0tKUn6ysLGWfynrclCQ3leW4mTVrloiNjRUpKSni119/FbNnzxZGRkbi+PHjQoiKd8xUuAJDCCHWrl0rXFxchJmZmWjZsqXK7VFBQUGiU6dOKv1jYmKEl5eXMDMzE66urmLdunWvOeLXR5/cLF26VDRo0EDI5XJRrVo10aFDB3HkyBEDRF26Cm+Re/kTFBQkhKjcx4y+uaksx4ymnAAQYWFhyj6V9bgpSW4qy3EzevRo5b+/NWvWFF27dlUWF0JUvGOGr2snIiIiyVWoMRhERERUNrDAICIiIsmxwCAiIiLJscAgIiIiybHAICIiIsmxwCAiIiLJscAgIiIiybHAICIiqkBiY2PRu3dvODk5QSaT4eDBg3qvQwiB5cuXw83NDebm5nB2dsbixYv1WgcLDKJy6ubNm5DJZEhMTDR0KMVasGABWrRoYegwXpmrqytWrVpVKutOTk5GrVq18PTpU72Wy8nJQd26dREfH18qcVH5k5mZCU9PT6xZs6bE65g8eTI2bdqE5cuX4+rVqzh8+DDefPNN/VZi4CeJElVYQUFBom/fvmrthY/ffvTo0SutPy8vT6SlpQmFQvFK69GHtn0qzvz584Wnp6fk8bxud+/eFZmZmcppACIyMlKSdQ8YMEAsXLhQOV14nDRt2lTk5eWp9LW1tVV59Pbq1atF165dJYmDKhZNx2hOTo749NNPhZOTk7C0tBRvvvmmOHnypHL+lStXhImJibh69eorbZtnMIjKodzcXBgbG6NWrVowMTExdDiVRs2aNWFpaSn5ev/66y8cOnQI7733ntq869evY+vWrUUuP3z4cMTFxSEpKUny2Kjiee+993DmzBns3r0bv/76KwYNGoS33noLf/zxBwDg8OHDqF+/Pr7//nvUq1cPrq6uGDt2LB4+fKjXdlhgEJUBERERaNq0KczNzeHq6oqvvvpKZb6rqyv+85//YNSoUbC1tcX777+vdolk1KhRkMlkap+YmBgAwKNHjzBy5EhUq1YNlpaW6Nmzp/IfFAAIDw9H1apVcezYMTRp0gRWVlZ46623kJaWBuDFZY4tW7bgu+++U1v3jBkz4ObmBktLS9SvXx9z586FQqHQKwe///473n77bdjY2MDa2hq+vr64fv06AODChQvw9/dHjRo1YGtri06dOuHSpUsqy8tkMqxbtw49e/aEhYUF6tWrh3379qn00SXOQ4cOwdvbG3K5HDVq1ED//v1VvofCSySurq4AgH79+kEmk8HV1RU3b96EkZERLl68qLLOb775Bi4uLhBaXv20d+9eeHp6ok6dOmrzJk6ciPnz5yM7O1tr7uzs7NCuXTvs2rVLax8i4EXBumvXLuzbtw++vr5o0KABpk2bhg4dOiAsLAwAcOPGDdy6dQv79u3D1q1bER4ejvj4eAwcOFCvbbHAIDKw+Ph4DB48GEOGDMHly5exYMECzJ07F+Hh4Sr9vvzySzRr1gzx8fGYO3eu2npWr16NtLQ05Wfy5Mmwt7dH48aNAbwoQC5evIhDhw7h3LlzEEIgICBA5RdsVlYWli9fjm3btiE2NhapqamYNm0aAGDatGkYPHiwsuhIS0tDu3btAADW1tYIDw/HlStXsHr1amzcuBErV67UOQd37txBx44dIZfL8dNPPyE+Ph6jR49GXl4eAODp06cICgpCXFwczp8/j0aNGiEgIEBtvMLcuXMxYMAA/PLLL3j33XcxdOhQlb/qi4vzyJEj6N+/P95++20kJCTgxIkT8Pb21hjzhQsXAABhYWFIS0vDhQsX4Orqim7duin/oS4UFhamLAA1iY2N1bqdKVOmIC8vr9jr6W+++Sbi4uKK7EN06dIlCCHg5uYGKysr5efUqVPKgr6goAA5OTnYunUrfH190blzZ4SGhuLkyZNITk7WfWOvdIGFiLQKCgoSxsbGokqVKiofuVyuMgZj2LBhwt/fX2XZTz/9VHh4eCinXVxcRGBgoEqflJQUAUAkJCSobTsiIkKYm5uLuLg4IYQQ165dEwDEmTNnlH3u378vLCwsxN69e4UQQoSFhQkA4s8//1T2Wbt2rXBwcFDZJ13GYCxbtky0atVKOV3cGIxZs2aJevXqidzc3GLXLcSL8SfW1tbi8OHDyjYAYty4cSr92rRpIz766COd4/Tx8RHDhw/X2t/FxUWsXLlSZZsvX9/es2ePqFatmsjOzhZCCJGYmChkMplISUnRul5PT0+V8RdCqI7VWb9+vahevbp4/PixEEJ9DIYQL8ZhuLq6at0GVU4vH6O7d+8WxsbG4urVq+KPP/5Q+aSlpQkhhJg3b54wMTFRWU9WVpYAoPJ6+eLwDAZRKfLz80NiYqLKZ9OmTSp9kpKS0L59e5W29u3b448//kB+fr6yTdtfuC9LSEjAyJEjsXbtWnTo0EG5DRMTE7Rp00bZz87ODu7u7ip/4VtaWqJBgwbKaUdHR9y9e7fYbe7fvx8dOnRArVq1YGVlhblz5yI1NVWneAEgMTERvr6+MDU11Tj/7t27GDduHNzc3GBrawtbW1s8e/ZMbRs+Pj5q0//ev+LiTExMRNeuXXWOW5PAwECYmJggMjISALB582b4+fkpL6lo8vz5c8jlcq3zx4wZgxo1amDp0qVa+1hYWCArK6vEcVPl4OXlhfz8fNy9excNGzZU+dSqVQvAi39/8vLylGc0AODatWsAABcXF523xQKDqBRVqVJF7X/i2rVrq/QRQqidOhcartVXqVKl2O2lp6ejT58+GDNmDMaMGVPk+jRt++Vf8DKZTOuyhc6fP48hQ4agZ8+e+P7775GQkIA5c+YgNze32HgLWVhYFDl/1KhRiI+Px6pVq3D27FkkJibCzs5Op20U7p8ucRYXhy7MzMwwYsQIhIWFITc3Fzt37sTo0aOLXKZGjRp49OiR1vkmJib4z3/+g9WrV+Pvv//W2Ofhw4eoWbPmK8VOFcOzZ8+Uf9AAQEpKChITE5Gamgo3NzcMHz4cI0eOxIEDB5CSkoILFy5g6dKliIqKAgB069YNLVu2xOjRo5GQkID4+Hh8+OGH8Pf3h5ubm85xsMAgMjAPDw+cPn1ape3s2bNwc3ODsbGxzuvJzs5G37590bhxY6xYsUJtG3l5efjf//6nbHvw4AGuXbuGJk2a6LwNMzMzlbMqAHDmzBm4uLhgzpw58Pb2RqNGjXDr1i2d1wkAzZs3R1xcnNaBoXFxcZg0aRICAgKUg2Hv37+v1u/8+fNq04VjUHSJs3nz5jhx4oTOcZuamqrlAwDGjh2LH3/8Ed9++y0UCoXKQFFNvLy8cOXKlSL7DBo0CE2bNkVISIjG+b/99hu8vLx0jp0qrosXL8LLy0t5PAQHB8PLywvz5s0D8GJM0MiRI/HJJ5/A3d0dffr0wf/+9z84OzsDAIyMjHD48GHUqFEDHTt2xNtvv40mTZpg9+7desXB+9uIDOyTTz5B69atsWjRIrzzzjs4d+4c1qxZg2+//Vav9Xz44Ye4ffs2Tpw4gXv37inbq1evjkaNGqFv3754//33sWHDBlhbW2PmzJmoXbs2+vbtq/M2XF1dcezYMSQnJ8POzg62trZo2LAhUlNTsXv3brRu3RpHjhxRXh7Q1YQJE/DNN99gyJAhmDVrFmxtbXH+/Hm8+eabcHd3R8OGDbFt2zZ4e3sjIyMDn376qcazDfv27YO3tzc6dOiAHTt24Oeff0ZoaCgA6BTn/Pnz0bVrVzRo0ABDhgxBXl4efvjhB0yfPl1rPk6cOIH27dvD3Nwc1apVAwA0adIEbdu2xYwZMzB69Ohiz4z06NEDY8eORX5+fpFF5RdffIEePXponBcXF4dFixYVuR2qHDp37lzkmUdTU1OEhIRoLVYBwMnJCREREa8WyCuOHyEiLfR50Nb+/fuFh4eHMDU1FXXr1hVffvmlyjIvDy4UQn2Qp4uLiwCg9il8gM7Dhw/FiBEjhK2trbCwsBA9evQQ165dU64vLCxM2NraqmwjMjJS/Pufibt37wp/f39hZWWlsu5PP/1U2NnZCSsrK/HOO++IlStXqqxLlwdt/fLLL6J79+7C0tJSWFtbC19fX3H9+nUhhBCXLl0S3t7ewtzcXDRq1Ejs27dP44DLtWvXCn9/f2Fubi5cXFzErl27VLZRXJxCvBgg26JFC2FmZiZq1Kgh+vfvr/V7OHTokGjYsKEwMTERLi4uKusJDQ0VAMTPP/9c5H4L8WLQau3atcXRo0eVbdoeyNa9e3cBQGWQ59mzZ0XVqlVFVlZWsdsiel1kQhRzgZWIqByQyWSIjIxEYGCgoUMBAHz++efYvXs3Ll++rFP/b7/9Ft999x2OHTum97YGDRoELy8vzJ49W+9liUoLL5EQEUno2bNnSEpKwjfffKPXJYsPPvgAjx49wtOnT2Ftba3zcjk5OfD09MTUqVNLEi5RqeEZDCKqEMrKGYxRo0Zh165dCAwMxM6dO/UaqEtUkbDAICIiIsnxNlUiIiKSHAsMIiIikhwLDCIiIpIcCwwiIiKSHAsMIiIikhwLDCIiIpIcCwwiIiKSHAsMIiIiktz/A8QNgV/KMLowAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Final Optimized Anchor (UC-based):\n", + "Design: {'D': 1.427702436403329, 'L': 8.565624503775082, 'zlug': 5.710416335850054}\n", + "Capacity Results: {'Hmax': 0.1, 'Vmax': 1719845.4215692256, 'Ha': 2528247.4234612333, 'Va': 2414423.5137604806, 'zlug': 5.710416335850054, 'z0': 1.75, 'UC': 1.0997495198266297e+39, 'Weight pile': 114372.69697445678}\n", + "\n", + "Final Optimized Anchor:\n", + "Design: {'D': 1.427702436403329, 'L': 8.565624503775082, 'zlug': 5.710416335850054}\n", + "Capacity Results: {'Hmax': 0.1, 'Vmax': 1719845.4215692256, 'Ha': 2528247.4234612333, 'Va': 2414423.5137604806, 'zlug': 5.710416335850054, 'z0': 1.75, 'UC': 1.0997495198266297e+39, 'Weight pile': 114372.69697445678}\n" + ] + } + ], + "source": [ + "anchor.getSizeAnchor(\n", + " geom = [anchor.dd['design']['L'], anchor.dd['design']['D']],\n", + " geomKeys = ['L', 'D'],\n", + " geomBounds = [(5.0, 15.0), (1.0, 4.0)],\n", + " loads = None,\n", + " lambdap_con = [3, 6],\n", + " zlug_fix = False,\n", + " safety_factor = {'SF_combined': 2},\n", + " plot = True\n", + ")\n", + "\n", + "print('\\nFinal Optimized Anchor:')\n", + "print('Design:', anchor.dd['design'])\n", + "print('Capacity Results:', anchor.anchorCapacity)" + ] + }, + { + "cell_type": "markdown", + "id": "b7c5fff6", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "id": "490a71e1", + "metadata": {}, + "source": [ + "### Step 11: Optimized anchor material costs\n", + "We assess the cost of the optimized suction pile defined by the manufacturing cost (USD/kg)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "a439735f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mass: 11658.79 kg\n", + "Material unit cost: 10.25 USD/kg\n", + "Material cost: 119502.56 USD [2024]\n" + ] + } + ], + "source": [ + "anchor.getCost()\n", + "\n", + "print(f\"Mass: {anchor.anchorCapacity['Weight pile']/9.81:.2f} kg\")\n", + "print(f\"Material unit cost: {anchor.cost['unit_cost']:.2f} USD/kg\")\n", + "print(f'Material cost: {anchor.cost[\"Material cost\"]:.2f} USD [2024]')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "fam", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/05_Anchors/inputs/GulfOfMaine_bathymetry_100x100.txt b/examples/05_Anchors/inputs/GulfOfMaine_bathymetry_100x100.txt new file mode 100644 index 00000000..22b0bc97 --- /dev/null +++ b/examples/05_Anchors/inputs/GulfOfMaine_bathymetry_100x100.txt @@ -0,0 +1,104 @@ +--- MoorPy Bathymetry Input File --- +nGridX 100 +nGridY 100 + -4420.52 -4345.53 -4270.54 -4195.55 -4120.57 -4045.58 -3970.59 -3895.60 -3820.61 -3745.62 -3670.63 -3595.64 -3520.66 -3445.67 -3370.68 -3295.69 -3220.70 -3145.71 -3070.72 -2995.74 -2920.75 -2845.76 -2770.77 -2695.78 -2620.79 -2545.80 -2470.81 -2395.83 -2320.84 -2245.85 -2170.86 -2095.87 -2020.88 -1945.89 -1870.90 -1795.92 -1720.93 -1645.94 -1570.95 -1495.96 -1420.97 -1345.98 -1270.99 -1196.01 -1121.02 -1046.03 -971.04 -896.05 -821.06 -746.07 -671.08 -596.10 -521.11 -446.12 -371.13 -296.14 -221.15 -146.16 -71.17 3.81 78.80 153.79 228.78 303.77 378.76 453.75 528.74 603.72 678.71 753.70 828.69 903.68 978.67 1053.66 1128.64 1203.63 1278.62 1353.61 1428.60 1503.59 1578.58 1653.57 1728.55 1803.54 1878.53 1953.52 2028.51 2103.50 2178.49 2253.48 2328.46 2403.45 2478.44 2553.43 2628.42 2703.41 2778.40 2853.39 2928.37 3003.36 +-3873.36 176.051 176.899 177.747 178.595 179.442 179.494 178.011 176.528 175.045 173.562 172.871 172.659 172.447 172.235 172.023 172.577 173.212 173.848 174.483 175.080 175.503 175.927 176.350 176.773 176.902 176.690 176.479 176.267 176.056 175.370 174.523 173.676 172.829 172.010 172.221 172.432 172.643 172.854 173.000 173.002 173.004 173.006 173.007 173.256 173.677 174.098 174.519 174.939 174.812 174.602 174.391 174.181 174.003 174.004 174.006 174.007 174.008 174.100 174.310 174.521 174.732 174.942 174.551 173.917 173.282 172.648 172.013 172.426 172.847 173.268 173.689 174.225 175.069 175.914 176.758 177.602 177.745 177.323 176.901 176.479 176.057 175.281 174.435 173.589 172.743 171.946 171.523 171.101 170.678 170.255 169.916 169.705 169.494 169.283 169.072 169.291 169.714 170.137 170.561 170.984 +-3803.23 176.470 177.228 177.985 178.743 179.501 179.525 178.132 176.739 175.346 173.953 173.276 173.035 172.793 172.551 172.309 172.832 173.438 174.043 174.649 175.215 175.609 176.002 176.396 176.789 176.916 176.734 176.553 176.371 176.190 175.534 174.717 173.900 173.083 172.291 172.443 172.594 172.745 172.895 173.028 173.120 173.211 173.303 173.395 173.592 173.863 174.134 174.405 174.676 174.607 174.487 174.367 174.246 174.153 174.215 174.276 174.337 174.398 174.498 174.649 174.799 174.950 175.101 174.735 174.161 173.586 173.012 172.437 172.702 172.973 173.244 173.515 173.893 174.558 175.222 175.887 176.551 176.663 176.331 175.999 175.667 175.335 174.649 173.893 173.137 172.381 171.670 171.307 170.945 170.582 170.219 169.940 169.789 169.638 169.486 169.335 169.553 169.947 170.340 170.734 171.127 +-3733.10 176.888 177.556 178.224 178.892 179.560 179.556 178.253 176.950 175.647 174.344 173.682 173.410 173.138 172.867 172.595 173.087 173.663 174.239 174.814 175.351 175.715 176.078 176.442 176.805 176.930 176.778 176.627 176.475 176.324 175.698 174.911 174.124 173.337 172.573 172.664 172.755 172.846 172.937 173.056 173.237 173.419 173.600 173.782 173.928 174.049 174.170 174.292 174.413 174.402 174.372 174.342 174.311 174.304 174.425 174.546 174.667 174.788 174.896 174.987 175.078 175.169 175.260 174.919 174.405 173.890 173.375 172.861 172.977 173.098 173.220 173.341 173.562 174.046 174.531 175.015 175.500 175.582 175.340 175.097 174.855 174.613 174.017 173.350 172.684 172.018 171.394 171.091 170.788 170.486 170.183 169.964 169.873 169.781 169.690 169.599 169.816 170.179 170.543 170.906 171.270 +-3662.97 177.307 177.885 178.463 179.041 179.619 179.588 178.374 177.161 175.948 174.735 174.088 173.786 173.484 173.182 172.881 173.343 173.889 174.434 174.980 175.487 175.820 176.154 176.488 176.821 176.944 176.822 176.700 176.579 176.457 175.862 175.105 174.348 173.591 172.854 172.885 172.916 172.947 172.978 173.083 173.355 173.626 173.897 174.169 174.264 174.235 174.207 174.178 174.150 174.198 174.257 174.317 174.376 174.454 174.635 174.816 174.997 175.178 175.295 175.326 175.356 175.387 175.418 175.103 174.649 174.194 173.739 173.284 173.253 173.224 173.195 173.167 173.230 173.534 173.839 174.144 174.449 174.500 174.348 174.196 174.044 173.891 173.385 172.808 172.232 171.656 171.118 170.875 170.632 170.389 170.146 169.988 169.956 169.925 169.894 169.862 170.079 170.412 170.745 171.079 171.412 +-3592.83 177.725 178.213 178.702 179.190 179.678 179.619 178.495 177.372 176.249 175.126 174.494 174.162 173.830 173.498 173.166 173.599 174.114 174.630 175.146 175.623 175.926 176.230 176.534 176.837 176.958 176.866 176.774 176.683 176.591 176.026 175.299 174.572 173.845 173.135 173.106 173.078 173.049 173.020 173.111 173.472 173.833 174.195 174.556 174.600 174.422 174.243 174.065 173.887 173.993 174.142 174.292 174.441 174.605 174.846 175.086 175.327 175.568 175.693 175.664 175.635 175.606 175.577 175.287 174.893 174.498 174.103 173.708 173.528 173.350 173.171 172.993 172.897 173.022 173.148 173.273 173.398 173.419 173.357 173.294 173.232 173.170 172.753 172.266 171.780 171.294 170.843 170.660 170.476 170.293 170.110 170.011 170.040 170.069 170.097 170.126 170.341 170.645 170.948 171.252 171.555 +-3522.70 178.144 178.542 178.941 179.339 179.737 179.650 178.616 177.583 176.550 175.516 174.899 174.538 174.176 173.814 173.452 173.854 174.340 174.826 175.311 175.758 176.032 176.306 176.579 176.853 176.971 176.910 176.848 176.786 176.725 176.190 175.493 174.796 174.098 173.416 173.328 173.239 173.150 173.062 173.138 173.589 174.041 174.492 174.943 174.936 174.608 174.280 173.952 173.624 173.788 174.028 174.267 174.506 174.755 175.056 175.357 175.658 175.958 176.091 176.002 175.913 175.825 175.736 175.471 175.137 174.802 174.467 174.132 173.804 173.475 173.147 172.819 172.565 172.511 172.456 172.401 172.347 172.338 172.365 172.393 172.420 172.448 172.121 171.724 171.328 170.931 170.567 170.444 170.321 170.197 170.074 170.035 170.124 170.212 170.301 170.389 170.604 170.877 171.151 171.424 171.698 +-3452.57 178.563 178.871 179.180 179.488 179.796 179.681 178.737 177.794 176.850 175.907 175.305 174.914 174.522 174.130 173.738 174.110 174.565 175.021 175.477 175.894 176.138 176.382 176.625 176.869 176.985 176.954 176.922 176.890 176.859 176.354 175.687 175.019 174.352 173.698 173.549 173.401 173.252 173.103 173.166 173.707 174.248 174.789 175.330 175.273 174.795 174.317 173.839 173.360 173.584 173.913 174.242 174.571 174.905 175.266 175.627 175.988 176.349 176.490 176.341 176.192 176.043 175.894 175.656 175.381 175.106 174.831 174.556 174.079 173.601 173.123 172.645 172.233 171.999 171.764 171.530 171.295 171.257 171.374 171.491 171.609 171.726 171.489 171.182 170.876 170.569 170.291 170.228 170.165 170.101 170.038 170.059 170.208 170.356 170.505 170.653 170.866 171.110 171.353 171.597 171.841 +-3382.44 178.982 179.200 179.419 179.637 179.855 179.712 178.858 178.004 177.151 176.297 175.711 175.289 174.868 174.446 174.024 174.365 174.791 175.217 175.643 176.030 176.244 176.458 176.671 176.885 176.999 176.997 176.996 176.994 176.992 176.518 175.881 175.243 174.606 173.979 173.771 173.562 173.353 173.145 173.193 173.824 174.455 175.086 175.717 175.609 174.981 174.353 173.725 173.097 173.379 173.798 174.217 174.636 175.056 175.476 175.897 176.318 176.739 176.888 176.679 176.471 176.262 176.053 175.840 175.625 175.410 175.195 174.979 174.354 173.726 173.098 172.470 171.901 171.487 171.072 170.658 170.244 170.175 170.383 170.590 170.797 171.005 170.857 170.640 170.424 170.207 170.015 170.012 170.009 170.005 170.002 170.083 170.292 170.500 170.708 170.917 171.129 171.342 171.556 171.770 171.983 +-3312.31 178.885 179.181 179.476 179.772 180.067 179.987 179.168 178.348 177.528 176.709 176.134 175.711 175.287 174.863 174.440 174.753 175.149 175.545 175.941 176.304 176.516 176.728 176.940 177.152 177.253 177.225 177.197 177.169 177.141 176.661 176.025 175.389 174.754 174.128 173.887 173.647 173.407 173.167 173.212 173.904 174.597 175.289 175.982 175.878 175.214 174.550 173.886 173.221 173.502 173.926 174.350 174.774 175.185 175.523 175.862 176.201 176.539 176.653 176.469 176.286 176.102 175.919 175.776 175.649 175.522 175.396 175.269 174.665 174.057 173.450 172.843 172.286 171.862 171.438 171.014 170.590 170.456 170.555 170.653 170.752 170.850 170.689 170.477 170.265 170.053 169.873 169.930 169.986 170.043 170.099 170.173 170.272 170.371 170.470 170.569 170.745 170.957 171.169 171.382 171.594 +-3242.18 178.749 179.134 179.519 179.905 180.290 180.280 179.491 178.701 177.912 177.122 176.559 176.135 175.711 175.288 174.864 175.151 175.517 175.882 176.248 176.587 176.799 177.011 177.223 177.435 177.522 177.464 177.406 177.348 177.290 176.802 176.167 175.531 174.895 174.268 173.998 173.728 173.458 173.188 173.230 173.982 174.735 175.487 176.240 176.143 175.449 174.755 174.061 173.367 173.643 174.067 174.491 174.915 175.313 175.561 175.810 176.059 176.307 176.383 176.229 176.076 175.922 175.769 175.698 175.662 175.625 175.588 175.551 174.977 174.400 173.822 173.245 172.710 172.286 171.862 171.438 171.014 170.814 170.792 170.771 170.750 170.728 170.547 170.336 170.124 169.912 169.739 169.855 169.972 170.088 170.205 170.266 170.245 170.225 170.204 170.183 170.321 170.533 170.745 170.957 171.170 +-3172.05 178.612 179.087 179.562 180.038 180.513 180.574 179.814 179.054 178.295 177.535 176.983 176.559 176.136 175.712 175.289 175.548 175.884 176.220 176.556 176.869 177.081 177.293 177.505 177.717 177.791 177.703 177.615 177.527 177.439 176.944 176.308 175.673 175.037 174.409 174.109 173.809 173.509 173.209 173.248 174.060 174.873 175.685 176.498 176.409 175.685 174.960 174.236 173.512 173.785 174.209 174.632 175.056 175.441 175.599 175.758 175.917 176.076 176.113 175.989 175.866 175.742 175.619 175.621 175.674 175.727 175.780 175.833 175.290 174.742 174.195 173.647 173.134 172.710 172.286 171.862 171.438 171.171 171.030 170.889 170.748 170.606 170.406 170.194 169.982 169.770 169.605 169.781 169.958 170.134 170.310 170.360 170.219 170.078 169.938 169.797 169.897 170.109 170.321 170.533 170.745 +-3101.92 178.475 179.040 179.605 180.170 180.736 180.867 180.137 179.408 178.678 177.948 177.408 176.984 176.560 176.137 175.713 175.945 176.251 176.557 176.863 177.152 177.364 177.576 177.788 178.000 178.060 177.942 177.824 177.706 177.588 177.086 176.450 175.814 175.178 174.550 174.220 173.890 173.560 173.229 173.266 174.138 175.011 175.883 176.755 176.674 175.920 175.166 174.412 173.658 173.926 174.350 174.774 175.198 175.569 175.637 175.706 175.775 175.844 175.843 175.749 175.656 175.562 175.469 175.544 175.687 175.830 175.973 176.116 175.602 175.085 174.567 174.050 173.558 173.134 172.710 172.286 171.862 171.529 171.268 171.007 170.745 170.484 170.265 170.053 169.841 169.629 169.470 169.707 169.943 170.180 170.416 170.453 170.192 169.932 169.671 169.411 169.473 169.685 169.897 170.109 170.321 +-3031.78 178.338 178.993 179.648 180.303 180.958 181.160 180.461 179.761 179.061 178.361 177.832 177.408 176.985 176.561 176.137 176.342 176.618 176.894 177.170 177.435 177.647 177.859 178.071 178.283 178.329 178.181 178.033 177.885 177.737 177.227 176.591 175.956 175.320 174.691 174.331 173.971 173.610 173.250 173.284 174.216 175.149 176.081 177.013 176.939 176.155 175.371 174.587 173.803 174.067 174.491 174.915 175.339 175.697 175.676 175.655 175.634 175.613 175.573 175.510 175.446 175.382 175.319 175.466 175.699 175.932 176.165 176.398 175.915 175.427 174.940 174.452 173.982 173.558 173.134 172.710 172.286 171.886 171.505 171.124 170.743 170.362 170.123 169.911 169.699 169.487 169.336 169.633 169.929 170.225 170.521 170.546 170.166 169.785 169.405 169.025 169.049 169.261 169.473 169.685 169.897 +-2961.65 178.201 178.946 179.691 180.436 181.181 181.453 180.784 180.114 179.444 178.775 178.256 177.833 177.409 176.985 176.562 176.739 176.985 177.231 177.477 177.717 177.929 178.142 178.354 178.566 178.598 178.420 178.242 178.064 177.886 177.369 176.733 176.097 175.462 174.832 174.441 174.051 173.661 173.271 173.302 174.294 175.287 176.279 177.271 177.205 176.391 175.577 174.763 173.949 174.209 174.633 175.057 175.480 175.825 175.714 175.603 175.492 175.381 175.303 175.270 175.236 175.202 175.169 175.389 175.712 176.034 176.357 176.680 176.227 175.770 175.312 174.855 174.406 173.982 173.558 173.134 172.711 172.244 171.743 171.242 170.741 170.240 169.982 169.770 169.558 169.346 169.202 169.558 169.915 170.271 170.627 170.640 170.139 169.639 169.139 168.638 168.625 168.837 169.049 169.261 169.473 +-2891.52 178.064 178.899 179.733 180.568 181.403 181.747 181.107 180.467 179.827 179.188 178.681 178.257 177.833 177.410 176.986 177.136 177.352 177.569 177.785 178.000 178.212 178.424 178.636 178.848 178.867 178.659 178.451 178.244 178.036 177.510 176.875 176.239 175.603 174.972 174.552 174.132 173.712 173.292 173.320 174.372 175.425 176.477 177.529 177.470 176.626 175.782 174.938 174.094 174.350 174.774 175.198 175.622 175.953 175.752 175.551 175.350 175.149 175.033 175.030 175.026 175.022 175.019 175.311 175.724 176.137 176.550 176.962 176.540 176.112 175.685 175.257 174.830 174.407 173.983 173.559 173.135 172.601 171.980 171.360 170.739 170.118 169.840 169.628 169.416 169.205 169.068 169.484 169.900 170.317 170.733 170.733 170.112 169.492 168.872 168.252 168.201 168.413 168.625 168.837 169.049 +-2821.39 178.038 178.783 179.528 180.273 181.018 181.311 180.701 180.090 179.480 178.870 178.406 178.033 177.661 177.289 176.916 177.091 177.329 177.567 177.804 178.042 178.280 178.518 178.756 178.994 179.014 178.776 178.538 178.300 178.062 177.568 176.984 176.400 175.817 175.237 174.813 174.390 173.966 173.542 173.546 174.527 175.508 176.489 177.470 177.410 176.615 175.820 175.024 174.229 174.469 174.866 175.264 175.662 175.961 175.696 175.432 175.167 174.903 174.730 174.677 174.625 174.572 174.520 174.788 175.185 175.583 175.981 176.378 176.064 175.745 175.426 175.107 174.788 174.469 174.150 173.831 173.512 173.017 172.381 171.745 171.109 170.473 170.237 170.077 169.917 169.757 169.661 170.033 170.404 170.776 171.147 171.103 170.441 169.779 169.117 168.455 168.355 168.515 168.675 168.834 168.994 +-2751.26 178.032 178.657 179.282 179.907 180.532 180.756 180.175 179.595 179.015 178.434 178.018 177.706 177.394 177.081 176.769 176.976 177.244 177.512 177.780 178.048 178.315 178.583 178.851 179.119 179.141 178.873 178.605 178.337 178.069 177.612 177.088 176.565 176.041 175.520 175.096 174.672 174.249 173.825 173.801 174.692 175.583 176.475 177.366 177.304 176.569 175.833 175.098 174.363 174.584 174.952 175.319 175.687 175.952 175.627 175.303 174.979 174.654 174.421 174.309 174.196 174.084 173.971 174.201 174.568 174.936 175.304 175.671 175.476 175.277 175.078 174.879 174.680 174.481 174.282 174.083 173.883 173.441 172.805 172.169 171.533 170.897 170.711 170.611 170.511 170.412 170.361 170.673 170.984 171.296 171.607 171.515 170.823 170.131 169.439 168.747 168.597 168.697 168.797 168.897 168.997 +-2681.13 178.025 178.531 179.036 179.541 180.046 180.200 179.650 179.099 178.549 177.999 177.631 177.379 177.126 176.874 176.621 176.862 177.159 177.457 177.755 178.053 178.351 178.648 178.946 179.244 179.269 178.971 178.673 178.375 178.077 177.657 177.193 176.729 176.266 175.803 175.379 174.955 174.532 174.108 174.056 174.857 175.659 176.460 177.261 177.198 176.523 175.847 175.172 174.496 174.699 175.037 175.375 175.713 175.943 175.558 175.174 174.790 174.405 174.112 173.940 173.768 173.595 173.423 173.614 173.951 174.289 174.627 174.965 174.888 174.809 174.730 174.651 174.572 174.492 174.413 174.334 174.255 173.865 173.229 172.593 171.957 171.321 171.186 171.146 171.106 171.066 171.061 171.313 171.564 171.816 172.067 171.927 171.205 170.483 169.761 169.039 168.839 168.879 168.919 168.959 168.999 +-2611.00 178.019 178.405 178.790 179.175 179.560 179.645 179.125 178.604 178.084 177.563 177.244 177.051 176.859 176.666 176.474 176.747 177.075 177.402 177.730 178.058 178.386 178.714 179.041 179.369 179.397 179.069 178.741 178.413 178.085 177.701 177.297 176.894 176.490 176.086 175.662 175.238 174.814 174.391 174.311 175.023 175.734 176.446 177.157 177.092 176.476 175.861 175.245 174.630 174.815 175.123 175.430 175.738 175.934 175.490 175.045 174.601 174.157 173.804 173.571 173.339 173.107 172.874 173.027 173.335 173.642 173.950 174.258 174.300 174.341 174.382 174.423 174.463 174.504 174.545 174.585 174.626 174.289 173.653 173.017 172.381 171.745 171.660 171.680 171.700 171.720 171.761 171.952 172.144 172.336 172.527 172.339 171.587 170.835 170.083 169.331 169.080 169.060 169.040 169.021 169.001 +-2540.87 178.013 178.279 178.544 178.809 179.075 179.090 178.599 178.109 177.618 177.128 176.856 176.724 176.591 176.459 176.326 176.632 176.990 177.347 177.705 178.063 178.421 178.779 179.137 179.494 179.525 179.167 178.809 178.451 178.093 177.746 177.402 177.058 176.714 176.369 175.945 175.521 175.097 174.673 174.567 175.188 175.810 176.431 177.053 176.986 176.430 175.874 175.319 174.763 174.930 175.208 175.486 175.764 175.925 175.421 174.917 174.412 173.908 173.495 173.203 172.911 172.618 172.326 172.440 172.718 172.995 173.273 173.551 173.712 173.873 174.034 174.194 174.355 174.515 174.676 174.836 174.997 174.713 174.077 173.441 172.805 172.169 172.135 172.215 172.295 172.374 172.461 172.592 172.724 172.856 172.987 172.751 171.969 171.187 170.405 169.623 169.322 169.242 169.162 169.082 169.003 +-2470.74 178.007 178.153 178.298 178.444 178.589 178.534 178.074 177.613 177.153 176.692 176.469 176.396 176.324 176.251 176.178 176.517 176.905 177.293 177.680 178.068 178.456 178.844 179.232 179.619 179.652 179.265 178.877 178.489 178.101 177.790 177.506 177.222 176.938 176.652 176.228 175.804 175.380 174.956 174.822 175.354 175.886 176.417 176.949 176.879 176.384 175.888 175.392 174.897 175.046 175.293 175.541 175.789 175.916 175.352 174.788 174.224 173.659 173.187 172.834 172.482 172.130 171.778 171.853 172.101 172.349 172.596 172.844 173.125 173.405 173.686 173.966 174.247 174.527 174.807 175.088 175.368 175.137 174.501 173.865 173.229 172.593 172.609 172.749 172.889 173.029 173.160 173.232 173.304 173.376 173.447 173.163 172.351 171.539 170.727 169.915 169.564 169.424 169.284 169.144 169.005 +-2400.60 178.001 178.027 178.053 178.078 178.104 177.979 177.548 177.118 176.687 176.257 176.081 176.069 176.056 176.043 176.031 176.402 176.820 177.238 177.656 178.073 178.491 178.909 179.327 179.744 179.780 179.362 178.945 178.527 178.109 177.834 177.610 177.387 177.163 176.935 176.511 176.087 175.663 175.239 175.078 175.519 175.961 176.403 176.845 176.773 176.337 175.902 175.466 175.030 175.161 175.379 175.597 175.815 175.907 175.283 174.659 174.035 173.411 172.878 172.466 172.054 171.642 171.229 171.266 171.484 171.702 171.920 172.137 172.537 172.937 173.338 173.738 174.138 174.539 174.939 175.339 175.739 175.561 174.925 174.289 173.653 173.018 173.084 173.284 173.483 173.683 173.860 173.872 173.884 173.896 173.907 173.575 172.733 171.891 171.049 170.207 169.805 169.606 169.406 169.206 169.006 +-2330.47 178.438 178.320 178.203 178.086 177.968 177.773 177.419 177.066 176.713 176.360 176.180 176.109 176.038 175.967 175.896 176.245 176.645 177.045 177.445 177.845 178.245 178.645 179.045 179.445 179.512 179.183 178.855 178.527 178.199 178.027 177.911 177.795 177.679 177.557 177.158 176.758 176.358 175.959 175.736 175.919 176.103 176.287 176.470 176.270 175.798 175.326 174.854 174.382 174.544 174.804 175.064 175.324 175.480 175.036 174.593 174.150 173.707 173.262 172.814 172.366 171.918 171.470 171.458 171.621 171.785 171.949 172.113 172.391 172.671 172.950 173.230 173.523 173.850 174.178 174.506 174.834 174.664 174.101 173.537 172.974 172.410 172.579 172.887 173.195 173.503 173.788 173.908 174.028 174.148 174.267 174.025 173.249 172.473 171.696 170.920 170.465 170.157 169.849 169.542 169.235 +-2260.34 178.996 178.729 178.462 178.195 177.927 177.661 177.398 177.134 176.871 176.608 176.408 176.247 176.086 175.925 175.764 176.077 176.447 176.817 177.187 177.557 177.927 178.297 178.667 179.037 179.143 178.934 178.726 178.517 178.309 178.257 178.261 178.265 178.269 178.265 177.895 177.526 177.156 176.786 176.493 176.377 176.261 176.145 176.029 175.670 175.138 174.605 174.073 173.541 173.747 174.067 174.387 174.707 174.950 174.746 174.543 174.339 174.136 173.815 173.337 172.859 172.381 171.903 171.839 171.943 172.047 172.151 172.254 172.354 172.454 172.553 172.653 172.783 172.990 173.198 173.406 173.614 173.442 172.968 172.495 172.021 171.547 171.831 172.260 172.688 173.115 173.524 173.794 174.063 174.333 174.602 174.485 173.799 173.113 172.426 171.740 171.231 170.803 170.376 169.948 169.521 +-2190.21 179.555 179.138 178.721 178.304 177.887 177.549 177.376 177.202 177.029 176.856 176.636 176.385 176.134 175.883 175.632 175.909 176.249 176.589 176.929 177.269 177.609 177.949 178.289 178.629 178.773 178.684 178.596 178.507 178.419 178.487 178.611 178.734 178.858 178.973 178.633 178.293 177.953 177.614 177.251 176.836 176.420 176.004 175.588 175.069 174.477 173.885 173.293 172.701 172.951 173.331 173.711 174.091 174.420 174.456 174.492 174.529 174.565 174.367 173.859 173.351 172.843 172.336 172.221 172.265 172.308 172.352 172.396 172.317 172.236 172.156 172.076 172.042 172.130 172.218 172.307 172.395 172.219 171.836 171.452 171.068 170.684 171.084 171.632 172.180 172.728 173.260 173.679 174.099 174.518 174.938 174.946 174.349 173.753 173.156 172.560 171.997 171.449 170.902 170.355 169.807 +-2120.08 180.114 179.548 178.981 178.414 177.846 177.437 177.354 177.270 177.187 177.104 176.864 176.523 176.183 175.842 175.501 175.740 176.050 176.361 176.671 176.981 177.291 177.601 177.911 178.221 178.404 178.435 178.466 178.497 178.529 178.717 178.960 179.204 179.448 179.680 179.371 179.061 178.751 178.441 178.009 177.294 176.578 175.863 175.147 174.469 173.817 173.165 172.513 171.861 172.154 172.594 173.034 173.474 173.890 174.166 174.442 174.718 174.994 174.920 174.382 173.844 173.306 172.768 172.602 172.586 172.570 172.554 172.538 172.279 172.019 171.759 171.499 171.302 171.270 171.239 171.207 171.175 170.997 170.703 170.409 170.116 169.822 170.337 171.004 171.672 172.340 172.995 173.565 174.134 174.704 175.273 175.406 174.900 174.393 173.886 173.380 172.762 172.095 171.428 170.761 170.094 +-2049.95 180.673 179.957 179.240 178.523 177.806 177.325 177.332 177.338 177.345 177.352 177.092 176.662 176.231 175.800 175.369 175.572 175.852 176.132 176.413 176.693 176.973 177.253 177.533 177.813 178.034 178.185 178.336 178.487 178.639 178.947 179.310 179.673 180.037 180.388 180.108 179.828 179.549 179.269 178.767 177.752 176.737 175.722 174.706 173.868 173.156 172.444 171.732 171.020 171.358 171.858 172.357 172.857 173.359 173.875 174.391 174.907 175.423 175.473 174.905 174.337 173.769 173.201 172.984 172.908 172.832 172.756 172.680 172.242 171.802 171.362 170.922 170.562 170.410 170.259 170.107 169.955 169.775 169.571 169.367 169.163 168.959 169.589 170.377 171.164 171.952 172.731 173.451 174.170 174.889 175.608 175.867 175.450 175.033 174.617 174.200 173.528 172.741 171.954 171.167 170.380 +-1979.82 181.233 180.366 179.500 178.633 177.766 177.213 177.310 177.406 177.503 177.599 177.321 176.800 176.279 175.759 175.238 175.404 175.654 175.904 176.154 176.405 176.655 176.905 177.155 177.405 177.664 177.935 178.206 178.477 178.749 179.176 179.660 180.143 180.626 181.096 180.846 180.596 180.346 180.096 179.525 178.211 176.896 175.581 174.266 173.268 172.496 171.724 170.952 170.180 170.561 171.121 171.681 172.241 172.829 173.585 174.341 175.096 175.852 176.025 175.428 174.830 174.232 173.634 173.365 173.229 173.093 172.957 172.821 172.204 171.584 170.965 170.345 169.822 169.550 169.279 169.007 168.736 168.552 168.438 168.324 168.210 168.096 168.842 169.749 170.657 171.564 172.467 173.336 174.205 175.074 175.943 176.327 176.000 175.674 175.347 175.020 174.294 173.387 172.480 171.573 170.666 +-1909.69 181.793 180.776 179.760 178.743 177.726 177.101 177.287 177.474 177.660 177.847 177.549 176.939 176.328 175.717 175.107 175.236 175.456 175.676 175.896 176.116 176.337 176.557 176.777 176.997 177.295 177.685 178.076 178.467 178.858 179.406 180.009 180.612 181.216 181.803 181.583 181.364 181.144 180.924 180.284 178.669 177.055 175.440 173.825 172.667 171.835 171.003 170.172 169.340 169.765 170.384 171.004 171.624 172.299 173.295 174.290 175.286 176.281 176.578 175.950 175.322 174.695 174.067 173.747 173.551 173.355 173.159 172.963 172.167 171.367 170.568 169.768 169.082 168.690 168.299 167.907 167.516 167.330 167.306 167.282 167.258 167.234 168.094 169.122 170.149 171.177 172.203 173.222 174.241 175.260 176.279 176.788 176.551 176.314 176.077 175.840 175.059 174.032 173.005 171.979 170.952 +-1839.55 182.160 181.207 180.255 179.302 178.350 177.741 177.847 177.952 178.057 178.162 177.830 177.216 176.601 175.987 175.373 175.456 175.625 175.794 175.962 176.131 176.300 176.468 176.637 176.806 177.090 177.514 177.938 178.362 178.786 179.366 180.002 180.637 181.273 181.893 181.703 181.513 181.323 181.133 180.502 178.850 177.199 175.547 173.895 172.725 171.899 171.073 170.247 169.421 169.785 170.333 170.881 171.430 172.047 173.063 174.079 175.095 176.111 176.425 175.811 175.197 174.583 173.970 173.705 173.580 173.456 173.332 173.208 172.385 171.559 170.733 169.907 169.187 168.741 168.295 167.849 167.403 167.182 167.138 167.094 167.051 167.007 167.800 168.751 169.702 170.652 171.614 172.652 173.691 174.729 175.767 176.316 176.147 175.979 175.811 175.643 174.846 173.764 172.683 171.602 170.521 +-1769.42 182.450 181.647 180.844 180.041 179.239 178.682 178.638 178.593 178.548 178.503 178.131 177.547 176.963 176.378 175.794 175.827 175.936 176.045 176.153 176.262 176.371 176.480 176.588 176.697 176.949 177.372 177.796 178.220 178.644 179.224 179.860 180.496 181.132 181.753 181.592 181.432 181.272 181.112 180.521 178.929 177.337 175.745 174.153 173.025 172.229 171.433 170.637 169.841 170.105 170.534 170.962 171.390 171.897 172.853 173.809 174.765 175.721 176.014 175.430 174.846 174.262 173.678 173.507 173.503 173.498 173.494 173.490 172.698 171.902 171.106 170.310 169.602 169.126 168.651 168.175 167.699 167.431 167.327 167.224 167.120 167.016 167.674 168.475 169.276 170.077 170.904 171.912 172.920 173.929 174.937 175.491 175.383 175.275 175.167 175.058 174.259 173.148 172.037 170.925 169.814 +-1699.29 182.740 182.086 181.433 180.780 180.128 179.624 179.429 179.235 179.040 178.845 178.432 177.878 177.324 176.770 176.215 176.197 176.246 176.295 176.344 176.393 176.442 176.491 176.540 176.588 176.807 177.231 177.655 178.079 178.503 179.082 179.718 180.354 180.990 181.612 181.482 181.351 181.221 181.091 180.539 179.007 177.475 175.943 174.411 173.325 172.559 171.793 171.028 170.262 170.426 170.734 171.042 171.351 171.746 172.642 173.538 174.435 175.331 175.603 175.049 174.495 173.941 173.387 173.310 173.425 173.541 173.656 173.772 173.010 172.244 171.478 170.712 170.018 169.512 169.006 168.501 167.995 167.680 167.517 167.353 167.189 167.026 167.548 168.199 168.850 169.501 170.193 171.172 172.150 173.128 174.107 174.667 174.619 174.571 174.522 174.474 173.672 172.531 171.390 170.249 169.108 +-1629.16 183.029 182.525 182.022 181.519 181.017 180.565 180.221 179.877 179.532 179.187 178.734 178.209 177.685 177.161 176.637 176.568 176.557 176.547 176.536 176.524 176.513 176.502 176.491 176.480 176.665 177.089 177.513 177.937 178.361 178.941 179.577 180.213 180.848 181.471 181.371 181.271 181.170 181.070 180.558 179.085 177.613 176.141 174.669 173.626 172.890 172.154 171.418 170.682 170.746 170.935 171.123 171.312 171.596 172.432 173.268 174.104 174.941 175.192 174.667 174.143 173.619 173.095 173.112 173.348 173.583 173.819 174.054 173.323 172.587 171.851 171.115 170.434 169.898 169.362 168.826 168.291 167.930 167.706 167.482 167.259 167.035 167.422 167.923 168.424 168.926 169.483 170.431 171.380 172.328 173.276 173.843 173.855 173.867 173.878 173.890 173.086 171.914 170.743 169.572 168.401 +-1559.03 183.318 182.965 182.611 182.258 181.905 181.507 181.013 180.518 180.024 179.529 179.035 178.540 178.046 177.552 177.058 176.939 176.869 176.798 176.727 176.656 176.585 176.513 176.442 176.371 176.524 176.948 177.372 177.796 178.220 178.799 179.435 180.071 180.707 181.330 181.260 181.190 181.119 181.049 180.576 179.164 177.751 176.339 174.927 173.926 173.220 172.514 171.808 171.102 171.066 171.135 171.204 171.272 171.446 172.222 172.998 173.774 174.550 174.780 174.286 173.792 173.298 172.804 172.915 173.270 173.626 173.981 174.336 173.635 172.929 172.223 171.517 170.850 170.284 169.718 169.152 168.587 168.179 167.895 167.612 167.328 167.045 167.296 167.647 167.998 168.350 168.772 169.691 170.609 171.528 172.446 173.019 173.091 173.163 173.234 173.306 172.499 171.298 170.097 168.895 167.694 +-1488.90 183.607 183.403 183.200 182.997 182.794 182.449 181.805 181.160 180.516 179.872 179.336 178.872 178.407 177.943 177.479 177.310 177.180 177.049 176.918 176.787 176.656 176.525 176.394 176.262 176.382 176.806 177.230 177.654 178.078 178.658 179.294 179.929 180.565 181.189 181.149 181.109 181.068 181.028 180.594 179.242 177.890 176.537 175.185 174.227 173.551 172.874 172.198 171.522 171.387 171.336 171.284 171.233 171.295 172.012 172.728 173.444 174.160 174.369 173.905 173.441 172.977 172.512 172.718 173.193 173.668 174.143 174.619 173.948 173.272 172.596 171.919 171.266 170.670 170.074 169.478 168.882 168.428 168.084 167.741 167.397 167.054 167.170 167.371 167.573 167.774 168.062 168.950 169.839 170.727 171.616 172.196 172.327 172.459 172.590 172.722 171.912 170.681 169.450 168.219 166.988 +-1418.77 183.896 183.842 183.788 183.735 183.682 183.390 182.597 181.803 181.008 180.214 179.637 179.203 178.768 178.334 177.900 177.681 177.491 177.300 177.109 176.918 176.727 176.536 176.345 176.154 176.241 176.665 177.089 177.513 177.936 178.516 179.152 179.788 180.424 181.049 181.038 181.028 181.018 181.007 180.612 179.320 178.028 176.735 175.443 174.527 173.881 173.235 172.589 171.943 171.707 171.536 171.365 171.194 171.145 171.801 172.458 173.114 173.770 173.958 173.523 173.089 172.655 172.221 172.520 173.116 173.711 174.306 174.901 174.261 173.614 172.968 172.322 171.681 171.056 170.430 169.804 169.178 168.677 168.274 167.870 167.467 167.063 167.043 167.095 167.146 167.198 167.351 168.210 169.068 169.927 170.785 171.372 171.563 171.755 171.946 172.138 171.325 170.064 168.803 167.542 166.281 +-1348.64 183.459 183.497 183.535 183.573 183.611 183.383 182.592 181.802 181.012 180.222 179.688 179.322 178.956 178.590 178.225 178.030 177.857 177.684 177.511 177.332 177.120 176.908 176.697 176.485 176.508 176.814 177.121 177.427 177.734 178.224 178.782 179.339 179.896 180.445 180.503 180.562 180.621 180.680 180.364 179.171 177.978 176.784 175.591 174.688 173.993 173.298 172.603 171.908 171.647 171.455 171.263 171.071 170.995 171.591 172.188 172.784 173.380 173.555 173.170 172.786 172.402 172.017 172.332 172.928 173.525 174.121 174.718 174.166 173.609 173.052 172.495 171.922 171.306 170.689 170.073 169.457 168.959 168.555 168.151 167.746 167.342 167.279 167.278 167.278 167.278 167.370 168.100 168.830 169.560 170.291 170.801 170.994 171.186 171.379 171.572 170.806 169.613 168.419 167.225 166.031 +-1278.51 182.613 182.711 182.809 182.907 183.005 182.847 182.146 181.446 180.745 180.045 179.601 179.325 179.049 178.773 178.497 178.366 178.253 178.140 178.027 177.898 177.686 177.474 177.262 177.051 176.992 177.119 177.245 177.372 177.499 177.853 178.291 178.728 179.165 179.598 179.746 179.895 180.044 180.193 179.976 178.902 177.829 176.756 175.683 174.778 173.992 173.207 172.422 171.637 171.391 171.228 171.066 170.904 170.844 171.381 171.917 172.454 172.990 173.156 172.832 172.507 172.183 171.859 172.148 172.684 173.221 173.757 174.294 173.861 173.424 172.987 172.550 172.071 171.485 170.899 170.313 169.726 169.259 168.885 168.510 168.136 167.761 167.703 167.703 167.703 167.702 167.772 168.322 168.872 169.422 169.973 170.365 170.527 170.690 170.853 171.015 170.323 169.249 168.176 167.102 166.028 +-1208.37 181.767 181.925 182.082 182.240 182.398 182.310 181.700 181.089 180.479 179.868 179.514 179.328 179.142 178.956 178.770 178.702 178.649 178.596 178.543 178.463 178.252 178.040 177.828 177.616 177.476 177.423 177.370 177.317 177.264 177.482 177.800 178.117 178.435 178.751 178.989 179.228 179.467 179.706 179.588 178.634 177.681 176.728 175.774 174.867 173.992 173.117 172.242 171.367 171.134 171.001 170.869 170.737 170.694 171.171 171.647 172.124 172.600 172.758 172.493 172.229 171.964 171.700 171.964 172.440 172.917 173.393 173.870 173.556 173.239 172.922 172.605 172.221 171.665 171.109 170.552 169.996 169.559 169.214 168.870 168.525 168.181 168.127 168.127 168.127 168.127 168.173 168.544 168.914 169.284 169.655 169.928 170.061 170.194 170.326 170.459 169.840 168.886 167.932 166.978 166.024 +-1138.24 180.921 181.138 181.356 181.574 181.792 181.774 181.253 180.732 180.212 179.692 179.427 179.330 179.234 179.138 179.043 179.038 179.045 179.052 179.059 179.029 178.817 178.605 178.394 178.182 177.961 177.728 177.495 177.262 177.029 177.112 177.309 177.507 177.704 177.904 178.232 178.561 178.890 179.218 179.200 178.366 177.533 176.699 175.866 174.956 173.991 173.026 172.061 171.096 170.877 170.774 170.672 170.570 170.544 170.960 171.377 171.794 172.210 172.360 172.155 171.950 171.746 171.541 171.779 172.196 172.613 173.029 173.446 173.251 173.054 172.857 172.660 172.371 171.845 171.318 170.792 170.265 169.858 169.544 169.229 168.915 168.600 168.551 168.551 168.551 168.551 168.575 168.765 168.956 169.146 169.337 169.492 169.595 169.697 169.800 169.903 169.357 168.523 167.689 166.855 166.021 +-1068.11 180.074 180.352 180.630 180.907 181.185 181.237 180.806 180.376 179.945 179.515 179.339 179.333 179.327 179.321 179.315 179.373 179.440 179.507 179.574 179.595 179.383 179.171 178.959 178.748 178.446 178.033 177.620 177.207 176.794 176.741 176.819 176.896 176.974 177.057 177.475 177.894 178.312 178.731 178.811 178.098 177.384 176.671 175.957 175.045 173.990 172.935 171.881 170.826 170.620 170.548 170.475 170.403 170.394 170.750 171.107 171.464 171.820 171.961 171.817 171.672 171.527 171.383 171.595 171.952 172.309 172.665 173.022 172.947 172.869 172.792 172.715 172.521 172.024 171.528 171.031 170.535 170.158 169.873 169.589 169.304 169.020 168.975 168.975 168.975 168.975 168.976 168.987 168.998 169.008 169.019 169.056 169.128 169.201 169.274 169.346 168.874 168.160 167.446 166.732 166.018 +-997.98 179.228 179.565 179.903 180.241 180.579 180.700 180.359 180.019 179.678 179.338 179.252 179.336 179.420 179.503 179.587 179.709 179.836 179.963 180.090 180.160 179.949 179.737 179.525 179.313 178.930 178.338 177.745 177.152 176.560 176.370 176.328 176.286 176.244 176.210 176.718 177.227 177.735 178.244 178.423 177.829 177.236 176.642 176.049 175.134 173.990 172.845 171.700 170.555 170.363 170.321 170.278 170.236 170.243 170.540 170.837 171.133 171.430 171.563 171.478 171.393 171.309 171.224 171.411 171.708 172.005 172.301 172.598 172.642 172.684 172.727 172.769 172.670 172.204 171.737 171.271 170.805 170.457 170.203 169.948 169.694 169.439 169.400 169.399 169.399 169.399 169.378 169.208 169.039 168.870 168.701 168.619 168.662 168.704 168.747 168.790 168.391 167.797 167.203 166.609 166.014 +-927.85 178.381 178.779 179.176 179.574 179.972 180.163 179.913 179.662 179.411 179.160 179.165 179.338 179.512 179.686 179.860 180.045 180.232 180.419 180.605 180.726 180.514 180.303 180.091 179.879 179.415 178.643 177.870 177.098 176.325 176.000 175.838 175.675 175.513 175.363 175.961 176.559 177.158 177.756 178.035 177.561 177.087 176.613 176.140 175.224 173.989 172.754 171.520 170.285 170.106 170.094 170.081 170.069 170.093 170.330 170.567 170.803 171.040 171.164 171.140 171.115 171.090 171.065 171.227 171.464 171.701 171.937 172.174 172.337 172.499 172.662 172.824 172.820 172.383 171.947 171.511 171.074 170.757 170.532 170.308 170.083 169.859 169.824 169.824 169.824 169.823 169.779 169.430 169.081 168.732 168.383 168.183 168.195 168.208 168.221 168.234 167.909 167.435 166.960 166.486 166.011 +-857.72 177.695 178.135 178.576 179.017 179.457 179.696 179.501 179.306 179.111 178.916 178.945 179.122 179.299 179.477 179.654 179.907 180.171 180.434 180.698 180.897 180.772 180.647 180.522 180.397 179.955 179.125 178.294 177.464 176.634 176.205 175.924 175.642 175.360 175.092 175.693 176.294 176.895 177.496 177.817 177.481 177.144 176.808 176.472 175.613 174.376 173.139 171.903 170.666 170.437 170.367 170.296 170.226 170.195 170.389 170.583 170.778 170.972 171.083 171.083 171.083 171.083 171.083 171.234 171.446 171.658 171.870 172.082 172.259 172.436 172.613 172.790 172.789 172.330 171.871 171.412 170.953 170.652 170.475 170.299 170.122 169.945 169.932 169.950 169.967 169.985 169.948 169.542 169.135 168.728 168.322 168.054 167.984 167.914 167.845 167.775 167.472 167.066 166.659 166.253 165.846 +-787.59 177.130 177.600 178.071 178.542 179.012 179.282 179.117 178.951 178.786 178.621 178.626 178.743 178.861 178.978 179.095 179.421 179.774 180.128 180.482 180.781 180.805 180.830 180.855 180.880 180.534 179.734 178.934 178.133 177.333 176.825 176.423 176.021 175.620 175.232 175.773 176.314 176.855 177.396 177.720 177.534 177.348 177.161 176.975 176.213 175.037 173.860 172.683 171.506 171.182 170.992 170.801 170.611 170.473 170.637 170.802 170.966 171.131 171.224 171.224 171.224 171.224 171.224 171.376 171.588 171.800 172.012 172.224 172.341 172.458 172.574 172.691 172.631 172.112 171.593 171.074 170.555 170.262 170.145 170.028 169.911 169.794 169.816 169.864 169.911 169.959 169.952 169.575 169.199 168.822 168.445 168.146 167.956 167.766 167.577 167.388 167.068 166.692 166.315 165.939 165.562 +-717.46 176.565 177.065 177.566 178.067 178.567 178.867 178.732 178.597 178.462 178.327 178.307 178.364 178.422 178.479 178.537 178.934 179.378 179.821 180.265 180.664 180.839 181.013 181.188 181.363 181.114 180.343 179.573 178.803 178.032 177.444 176.923 176.401 175.879 175.372 175.853 176.335 176.816 177.297 177.624 177.587 177.551 177.514 177.478 176.814 175.697 174.580 173.463 172.347 171.927 171.617 171.306 170.996 170.751 170.886 171.020 171.155 171.289 171.366 171.366 171.366 171.366 171.366 171.517 171.729 171.941 172.153 172.365 172.422 172.479 172.536 172.593 172.473 171.894 171.315 170.736 170.157 169.871 169.814 169.757 169.700 169.643 169.700 169.778 169.855 169.932 169.956 169.609 169.262 168.916 168.569 168.238 167.928 167.619 167.309 167.000 166.665 166.318 165.972 165.625 165.279 +-647.32 176.000 176.530 177.061 177.592 178.122 178.452 178.347 178.242 178.137 178.032 177.988 177.986 177.983 177.981 177.978 178.448 178.981 179.515 180.048 180.548 180.872 181.196 181.521 181.846 181.693 180.953 180.212 179.472 178.731 178.063 177.422 176.781 176.139 175.513 175.934 176.355 176.776 177.197 177.527 177.640 177.754 177.867 177.980 177.415 176.358 175.301 174.244 173.187 172.672 172.242 171.811 171.381 171.030 171.134 171.239 171.343 171.448 171.507 171.507 171.507 171.507 171.507 171.658 171.870 172.082 172.294 172.506 172.504 172.501 172.498 172.495 172.314 171.675 171.036 170.397 169.759 169.481 169.484 169.487 169.490 169.493 169.584 169.691 169.799 169.906 169.959 169.643 169.326 169.009 168.693 168.330 167.900 167.471 167.042 166.612 166.261 165.945 165.628 165.312 164.995 +-577.19 175.435 175.995 176.556 177.117 177.677 178.038 177.962 177.887 177.812 177.737 177.670 177.607 177.545 177.482 177.420 177.961 178.585 179.208 179.832 180.431 180.905 181.379 181.854 182.328 182.272 181.562 180.851 180.141 179.431 178.683 177.922 177.160 176.399 175.653 176.014 176.376 176.737 177.098 177.430 177.693 177.956 178.220 178.483 178.015 177.018 176.021 175.024 174.027 173.416 172.866 172.317 171.767 171.308 171.383 171.457 171.532 171.606 171.649 171.649 171.649 171.649 171.649 171.800 172.012 172.224 172.436 172.648 172.586 172.523 172.460 172.397 172.156 171.457 170.758 170.059 169.360 169.090 169.153 169.216 169.279 169.342 169.468 169.605 169.743 169.880 169.963 169.676 169.390 169.103 168.816 168.421 167.872 167.323 166.774 166.225 165.858 165.571 165.285 164.998 164.712 +-507.06 174.870 175.460 176.051 176.642 177.232 177.623 177.578 177.533 177.487 177.442 177.351 177.229 177.106 176.984 176.861 177.475 178.188 178.901 179.615 180.314 180.938 181.562 182.186 182.811 182.852 182.171 181.491 180.810 180.130 179.303 178.421 177.540 176.659 175.794 176.095 176.396 176.697 176.999 177.333 177.746 178.159 178.572 178.986 178.616 177.679 176.742 175.805 174.868 174.161 173.491 172.822 172.152 171.587 171.631 171.676 171.720 171.765 171.790 171.790 171.790 171.790 171.790 171.941 172.153 172.365 172.577 172.789 172.667 172.545 172.422 172.299 171.998 171.239 170.480 169.721 168.962 168.700 168.823 168.946 169.069 169.191 169.352 169.519 169.687 169.854 169.967 169.710 169.454 169.197 168.940 168.513 167.844 167.175 166.506 165.837 165.455 165.198 164.941 164.685 164.428 +-436.93 174.305 174.925 175.546 176.167 176.787 177.208 177.193 177.178 177.162 177.147 177.032 176.850 176.668 176.485 176.303 176.988 177.791 178.595 179.398 180.197 180.971 181.745 182.519 183.293 183.431 182.780 182.130 181.479 180.829 179.922 178.921 177.920 176.919 175.934 176.175 176.417 176.658 176.899 177.236 177.799 178.362 178.925 179.488 179.216 178.339 177.462 176.585 175.708 174.906 174.117 173.327 172.537 171.865 171.880 171.894 171.909 171.923 171.931 171.931 171.931 171.931 171.931 172.083 172.295 172.507 172.719 172.931 172.749 172.566 172.383 172.200 171.840 171.021 170.202 169.383 168.564 168.309 168.492 168.675 168.858 169.041 169.236 169.433 169.631 169.828 169.971 169.744 169.517 169.291 169.064 168.605 167.816 167.027 166.238 165.449 165.051 164.824 164.598 164.371 164.145 +-366.80 173.947 174.524 175.100 175.677 176.253 176.662 176.706 176.751 176.796 176.840 176.723 176.496 176.268 176.041 175.814 176.519 177.352 178.185 179.017 179.852 180.700 181.548 182.396 183.244 183.463 182.903 182.343 181.783 181.223 180.332 179.318 178.304 177.290 176.291 176.458 176.624 176.790 176.956 177.261 177.897 178.533 179.169 179.805 179.599 178.782 177.964 177.147 176.330 175.486 174.638 173.790 172.942 172.212 172.165 172.119 172.073 172.026 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.767 170.934 170.102 169.269 168.436 168.157 168.308 168.458 168.609 168.759 168.962 169.174 169.386 169.599 169.758 169.561 169.365 169.168 168.971 168.512 167.679 166.847 166.014 165.181 164.781 164.569 164.357 164.145 163.933 +-296.67 173.802 174.259 174.715 175.172 175.628 175.983 176.117 176.252 176.386 176.521 176.422 176.165 175.908 175.651 175.393 176.068 176.871 177.674 178.476 179.286 180.134 180.982 181.830 182.678 182.964 182.554 182.144 181.734 181.324 180.539 179.615 178.691 177.767 176.856 176.932 177.008 177.084 177.160 177.402 178.038 178.674 179.311 179.947 179.775 179.018 178.261 177.503 176.746 175.911 175.063 174.215 173.367 172.623 172.486 172.350 172.214 172.078 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.775 170.973 170.170 169.367 168.565 168.231 168.262 168.292 168.323 168.354 168.538 168.750 168.962 169.174 169.337 169.171 169.004 168.837 168.671 168.241 167.439 166.636 165.833 165.030 164.639 164.427 164.215 164.003 163.791 +-226.54 173.657 173.994 174.330 174.667 175.003 175.304 175.528 175.753 175.977 176.202 176.122 175.835 175.547 175.260 174.973 175.617 176.390 177.163 177.936 178.721 179.568 180.416 181.264 182.112 182.466 182.205 181.945 181.685 181.425 180.746 179.912 179.078 178.244 177.420 177.406 177.393 177.379 177.365 177.544 178.180 178.816 179.452 180.088 179.951 179.254 178.557 177.859 177.162 176.335 175.487 174.639 173.791 173.034 172.808 172.581 172.355 172.129 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.784 171.011 170.238 169.466 168.693 168.305 168.216 168.126 168.037 167.948 168.114 168.326 168.538 168.750 168.917 168.780 168.644 168.507 168.370 167.971 167.198 166.425 165.652 164.880 164.498 164.286 164.074 163.862 163.650 +-156.41 173.512 173.729 173.945 174.162 174.378 174.625 174.939 175.254 175.568 175.883 175.821 175.504 175.187 174.870 174.552 175.167 175.909 176.652 177.395 178.155 179.002 179.850 180.698 181.546 181.967 181.856 181.746 181.636 181.526 180.954 180.209 179.465 178.721 177.985 177.881 177.777 177.674 177.570 177.685 178.321 178.957 179.593 180.229 180.128 179.490 178.853 178.216 177.578 176.759 175.911 175.063 174.215 173.445 173.129 172.813 172.496 172.180 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.792 171.049 170.307 169.564 168.821 168.379 168.170 167.960 167.751 167.542 167.690 167.902 168.114 168.326 168.497 168.390 168.283 168.177 168.070 167.700 166.957 166.214 165.472 164.729 164.356 164.144 163.932 163.720 163.508 +-86.28 173.367 173.464 173.561 173.657 173.754 173.946 174.350 174.754 175.159 175.563 175.521 175.174 174.827 174.479 174.132 174.716 175.428 176.141 176.854 177.589 178.436 179.284 180.132 180.980 181.468 181.508 181.547 181.587 181.627 181.161 180.506 179.852 179.198 178.549 178.356 178.162 177.968 177.775 177.826 178.462 179.098 179.734 180.371 180.304 179.726 179.149 178.572 177.994 177.183 176.335 175.487 174.639 173.856 173.450 173.044 172.638 172.232 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.800 171.088 170.375 169.662 168.949 168.453 168.123 167.794 167.465 167.136 167.266 167.478 167.690 167.902 168.076 168.000 167.923 167.846 167.770 167.429 166.717 166.004 165.291 164.578 164.215 164.003 163.791 163.579 163.367 +-16.14 173.222 173.199 173.176 173.153 173.129 173.267 173.761 174.255 174.749 175.244 175.220 174.843 174.466 174.089 173.712 174.265 174.948 175.631 176.313 177.023 177.871 178.718 179.566 180.414 180.969 181.158 181.348 181.538 181.727 181.368 180.803 180.239 179.675 179.114 178.830 178.547 178.263 177.979 177.967 178.603 179.240 179.876 180.512 180.480 179.963 179.445 178.928 178.410 177.608 176.760 175.912 175.064 174.267 173.771 173.275 172.779 172.283 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.809 171.126 170.443 169.760 169.077 168.526 168.077 167.628 167.179 166.730 166.841 167.054 167.266 167.478 167.656 167.609 167.563 167.516 167.469 167.159 166.476 165.793 165.110 164.427 164.073 163.861 163.649 163.437 163.225 +53.99 173.078 172.935 172.792 172.649 172.505 172.587 173.171 173.755 174.340 174.924 174.920 174.513 174.106 173.699 173.291 173.814 174.467 175.120 175.773 176.457 177.305 178.152 179.000 179.848 180.470 180.809 181.149 181.488 181.828 181.575 181.100 180.626 180.152 179.678 179.305 178.931 178.558 178.184 178.109 178.745 179.381 180.017 180.653 180.656 180.199 179.741 179.284 178.826 178.032 177.184 176.336 175.488 174.678 174.092 173.506 172.920 172.334 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.817 171.164 170.511 169.858 169.206 168.600 168.031 167.462 166.893 166.324 166.417 166.629 166.842 167.054 167.236 167.219 167.202 167.186 167.169 166.888 166.235 165.582 164.930 164.277 163.932 163.720 163.508 163.296 163.084 +124.12 172.995 172.783 172.570 172.358 172.146 172.189 172.799 173.410 174.020 174.630 174.635 174.224 173.812 173.401 172.990 173.485 174.108 174.731 175.354 176.009 176.831 177.653 178.475 179.297 179.948 180.385 180.821 181.258 181.695 181.554 181.195 180.837 180.478 180.119 179.695 179.271 178.847 178.423 178.300 178.897 179.493 180.090 180.686 180.685 180.247 179.810 179.373 178.935 178.155 177.320 176.485 175.650 174.845 174.208 173.572 172.936 172.300 171.926 171.899 171.873 171.846 171.820 171.954 172.153 172.351 172.550 172.749 172.565 172.379 172.194 172.008 171.711 171.128 170.545 169.962 169.379 168.751 168.088 167.426 166.763 166.101 166.180 166.392 166.604 166.816 166.997 166.970 166.944 166.918 166.892 166.618 165.995 165.372 164.749 164.126 163.809 163.623 163.437 163.251 163.065 +194.25 172.995 172.783 172.571 172.359 172.147 172.170 172.721 173.271 173.821 174.372 174.370 173.989 173.607 173.226 172.845 173.317 173.910 174.503 175.096 175.716 176.478 177.240 178.002 178.764 179.395 179.862 180.329 180.796 181.263 181.238 181.030 180.821 180.613 180.402 179.978 179.554 179.130 178.706 178.557 179.063 179.570 180.076 180.583 180.526 180.059 179.591 179.124 178.657 177.898 177.093 176.288 175.483 174.703 174.067 173.431 172.795 172.159 171.759 171.672 171.586 171.499 171.413 171.508 171.677 171.846 172.015 172.184 172.059 171.933 171.808 171.682 171.462 170.999 170.536 170.073 169.609 169.000 168.277 167.555 166.832 166.110 166.180 166.392 166.604 166.816 166.989 166.902 166.816 166.730 166.644 166.347 165.754 165.161 164.568 163.975 163.709 163.583 163.457 163.331 163.205 +264.38 172.995 172.783 172.571 172.359 172.147 172.151 172.642 173.132 173.623 174.113 174.105 173.754 173.402 173.051 172.700 173.149 173.713 174.276 174.839 175.424 176.126 176.828 177.530 178.232 178.843 179.340 179.836 180.333 180.830 180.923 180.865 180.806 180.748 180.685 180.261 179.837 179.413 178.989 178.813 179.229 179.646 180.063 180.479 180.367 179.870 179.373 178.875 178.378 177.641 176.866 176.091 175.317 174.562 173.926 173.290 172.654 172.017 171.592 171.445 171.299 171.152 171.006 171.063 171.202 171.340 171.479 171.618 171.553 171.488 171.422 171.357 171.213 170.870 170.527 170.183 169.840 169.249 168.466 167.684 166.901 166.119 166.180 166.392 166.604 166.816 166.981 166.834 166.688 166.542 166.396 166.077 165.514 164.951 164.388 163.825 163.609 163.543 163.477 163.411 163.345 +334.51 172.995 172.783 172.571 172.359 172.147 172.133 172.563 172.994 173.424 173.855 173.840 173.519 173.198 172.876 172.555 172.982 173.515 174.048 174.581 175.131 175.773 176.415 177.057 177.699 178.290 178.817 179.344 179.871 180.398 180.608 180.699 180.791 180.882 180.968 180.544 180.120 179.696 179.272 179.069 179.396 179.722 180.049 180.376 180.209 179.681 179.154 178.627 178.099 177.384 176.639 175.895 175.150 174.421 173.784 173.148 172.512 171.876 171.424 171.218 171.012 170.805 170.599 170.617 170.726 170.835 170.944 171.053 171.047 171.042 171.036 171.031 170.964 170.741 170.517 170.294 170.070 169.497 168.655 167.812 166.970 166.128 166.180 166.392 166.604 166.816 166.973 166.767 166.560 166.354 166.148 165.806 165.273 164.740 164.207 163.674 163.510 163.504 163.498 163.492 163.486 +404.64 172.995 172.783 172.571 172.359 172.147 172.114 172.485 172.855 173.226 173.596 173.575 173.284 172.993 172.701 172.410 172.814 173.317 173.820 174.323 174.839 175.421 176.003 176.585 177.167 177.738 178.295 178.851 179.408 179.965 180.293 180.534 180.775 181.016 181.251 180.827 180.403 179.979 179.555 179.325 179.562 179.799 180.035 180.272 180.050 179.493 178.935 178.378 177.821 177.128 176.413 175.698 174.983 174.279 173.643 173.007 172.371 171.735 171.257 170.991 170.725 170.458 170.192 170.172 170.250 170.329 170.408 170.487 170.542 170.596 170.650 170.705 170.715 170.611 170.508 170.405 170.301 169.746 168.844 167.941 167.039 166.136 166.180 166.392 166.604 166.816 166.965 166.699 166.432 166.166 165.900 165.536 165.033 164.530 164.027 163.524 163.411 163.465 163.518 163.572 163.626 +474.77 172.995 172.783 172.571 172.359 172.147 172.095 172.406 172.717 173.027 173.338 173.310 173.049 172.788 172.526 172.265 172.646 173.119 173.592 174.065 174.546 175.068 175.590 176.112 176.635 177.185 177.772 178.359 178.946 179.533 179.977 180.368 180.759 181.151 181.534 181.110 180.686 180.262 179.838 179.582 179.728 179.875 180.022 180.169 179.891 179.304 178.717 178.129 177.542 176.871 176.186 175.501 174.816 174.138 173.502 172.866 172.229 171.593 171.090 170.764 170.437 170.111 169.785 169.726 169.775 169.824 169.873 169.922 170.036 170.150 170.264 170.379 170.466 170.482 170.499 170.515 170.532 169.995 169.032 168.070 167.108 166.145 166.180 166.392 166.604 166.816 166.957 166.631 166.304 165.978 165.652 165.265 164.792 164.319 163.846 163.373 163.311 163.425 163.539 163.653 163.767 +544.91 172.995 172.783 172.571 172.359 172.147 172.077 172.328 172.578 172.829 173.079 173.045 172.814 172.583 172.351 172.120 172.478 172.921 173.364 173.807 174.254 174.716 175.178 175.640 176.102 176.633 177.249 177.866 178.483 179.100 179.662 180.203 180.744 181.285 181.817 181.393 180.969 180.545 180.121 179.838 179.895 179.952 180.008 180.065 179.733 179.115 178.498 177.881 177.264 176.614 175.959 175.304 174.649 173.996 173.360 172.724 172.088 171.452 170.923 170.537 170.150 169.764 169.378 169.280 169.299 169.318 169.337 169.356 169.530 169.704 169.879 170.053 170.217 170.353 170.490 170.626 170.762 170.244 169.221 168.199 167.176 166.154 166.180 166.392 166.604 166.816 166.949 166.562 166.176 165.790 165.404 164.995 164.552 164.109 163.666 163.222 163.212 163.386 163.560 163.733 163.907 +615.04 172.897 172.695 172.493 172.292 172.090 172.012 172.213 172.414 172.615 172.817 172.780 172.579 172.378 172.176 171.975 172.320 172.744 173.168 173.592 174.017 174.452 174.887 175.322 175.757 176.276 176.901 177.526 178.152 178.777 179.378 179.970 180.562 181.154 181.737 181.335 180.932 180.530 180.128 179.841 179.829 179.818 179.807 179.796 179.430 178.805 178.180 177.555 176.930 176.285 175.638 174.991 174.344 173.700 173.074 172.449 171.824 171.199 170.665 170.252 169.839 169.426 169.014 168.887 168.876 168.865 168.854 168.843 169.043 169.244 169.445 169.646 169.847 170.048 170.249 170.451 170.652 170.171 169.166 168.161 167.156 166.151 166.171 166.372 166.573 166.774 166.894 166.492 166.090 165.688 165.286 164.875 164.450 164.026 163.602 163.178 163.170 163.338 163.507 163.675 163.844 +685.17 172.615 172.443 172.271 172.100 171.928 171.861 172.032 172.204 172.375 172.546 172.515 172.344 172.172 172.001 171.830 172.178 172.602 173.026 173.450 173.881 174.345 174.810 175.275 175.740 176.263 176.858 177.453 178.048 178.643 179.149 179.622 180.094 180.566 181.031 180.688 180.346 180.004 179.662 179.408 179.366 179.325 179.284 179.243 178.882 178.287 177.692 177.097 176.501 175.836 175.158 174.481 173.804 173.138 172.543 171.948 171.353 170.758 170.254 169.871 169.488 169.105 168.722 168.583 168.542 168.501 168.460 168.419 168.589 168.760 168.931 169.102 169.273 169.444 169.615 169.787 169.958 169.549 168.694 167.839 166.984 166.129 166.145 166.316 166.487 166.659 166.761 166.419 166.077 165.735 165.392 165.016 164.592 164.168 163.743 163.319 163.227 163.275 163.324 163.373 163.422 +755.30 172.333 172.191 172.049 171.907 171.766 171.710 171.852 171.993 172.134 172.276 172.250 172.109 171.967 171.826 171.684 172.036 172.460 172.884 173.309 173.744 174.238 174.733 175.228 175.723 176.249 176.814 177.380 177.945 178.510 178.921 179.273 179.626 179.978 180.324 180.042 179.760 179.477 179.195 178.975 178.904 178.832 178.761 178.690 178.334 177.769 177.203 176.638 176.073 175.386 174.678 173.971 173.264 172.577 172.012 171.447 170.882 170.317 169.843 169.490 169.137 168.784 168.431 168.279 168.208 168.137 168.066 167.995 168.135 168.276 168.417 168.558 168.699 168.840 168.981 169.123 169.264 168.926 168.221 167.516 166.811 166.106 166.120 166.261 166.402 166.543 166.628 166.345 166.063 165.781 165.499 165.157 164.733 164.309 163.885 163.460 163.284 163.213 163.141 163.070 162.999 +825.43 172.050 171.939 171.827 171.715 171.604 171.560 171.671 171.782 171.894 172.005 171.985 171.874 171.762 171.651 171.539 171.895 172.319 172.743 173.167 173.607 174.132 174.656 175.181 175.706 176.236 176.771 177.306 177.841 178.377 178.693 178.925 179.157 179.390 179.618 179.395 179.173 178.951 178.728 178.542 178.441 178.339 178.238 178.137 177.786 177.250 176.715 176.180 175.645 174.936 174.198 173.461 172.724 172.016 171.481 170.946 170.411 169.876 169.431 169.108 168.785 168.462 168.139 167.975 167.874 167.773 167.672 167.571 167.681 167.792 167.903 168.014 168.125 168.236 168.348 168.459 168.570 168.304 167.749 167.194 166.639 166.083 166.094 166.206 166.317 166.428 166.494 166.272 166.050 165.827 165.605 165.298 164.874 164.450 164.026 163.602 163.341 163.150 162.959 162.768 162.577 +895.56 171.768 171.686 171.605 171.523 171.441 171.409 171.491 171.572 171.653 171.735 171.720 171.639 171.557 171.476 171.394 171.753 172.177 172.601 173.025 173.470 174.025 174.579 175.134 175.689 176.222 176.728 177.233 177.738 178.243 178.464 178.577 178.689 178.801 178.911 178.749 178.587 178.424 178.262 178.109 177.978 177.847 177.715 177.584 177.237 176.732 176.227 175.722 175.217 174.486 173.718 172.951 172.184 171.455 170.950 170.444 169.939 169.434 169.020 168.727 168.434 168.141 167.848 167.670 167.539 167.408 167.277 167.146 167.227 167.308 167.389 167.470 167.551 167.632 167.714 167.795 167.876 167.682 167.277 166.871 166.466 166.061 166.069 166.150 166.231 166.312 166.361 166.199 166.036 165.874 165.712 165.440 165.015 164.591 164.167 163.743 163.398 163.087 162.776 162.465 162.154 +965.69 171.486 171.434 171.382 171.331 171.279 171.259 171.310 171.361 171.413 171.464 171.455 171.403 171.352 171.300 171.249 171.612 172.036 172.460 172.884 173.333 173.918 174.502 175.087 175.672 176.209 176.684 177.160 177.635 178.110 178.236 178.229 178.221 178.213 178.205 178.102 178.000 177.898 177.795 177.676 177.515 177.354 177.193 177.031 176.689 176.214 175.739 175.263 174.788 174.036 173.239 172.441 171.644 170.894 170.418 169.943 169.468 168.993 168.609 168.346 168.083 167.820 167.557 167.366 167.205 167.044 166.883 166.722 166.773 166.824 166.875 166.926 166.977 167.028 167.080 167.131 167.182 167.060 166.804 166.549 166.294 166.038 166.043 166.095 166.146 166.197 166.227 166.125 166.023 165.920 165.818 165.581 165.157 164.733 164.308 163.884 163.455 163.024 162.593 162.162 161.731 +1035.82 171.204 171.182 171.160 171.138 171.117 171.108 171.130 171.151 171.172 171.194 171.190 171.168 171.147 171.125 171.104 171.470 171.894 172.318 172.742 173.196 173.811 174.425 175.040 175.655 176.196 176.641 177.086 177.532 177.977 178.008 177.880 177.753 177.625 177.498 177.456 177.413 177.371 177.329 177.243 177.052 176.861 176.670 176.479 176.141 175.696 175.250 174.805 174.360 173.586 172.759 171.931 171.104 170.332 169.887 169.442 168.997 168.552 168.198 167.964 167.731 167.498 167.265 167.062 166.871 166.680 166.489 166.298 166.319 166.340 166.361 166.382 166.403 166.424 166.445 166.467 166.488 166.437 166.332 166.227 166.121 166.016 166.018 166.039 166.060 166.081 166.094 166.052 166.009 165.967 165.925 165.722 165.298 164.874 164.450 164.025 163.512 162.961 162.410 161.859 161.308 +1105.95 170.882 170.899 170.915 170.932 170.949 170.965 170.982 170.999 171.016 171.033 171.045 171.054 171.062 171.071 171.080 171.450 171.875 172.299 172.723 173.177 173.796 174.415 175.034 175.653 176.175 176.572 176.970 177.368 177.766 177.722 177.510 177.298 177.086 176.875 176.875 176.875 176.875 176.875 176.813 176.600 176.388 176.176 175.964 175.635 175.219 174.804 174.389 173.974 173.201 172.371 171.540 170.710 169.939 169.514 169.090 168.666 168.242 167.913 167.710 167.507 167.303 167.100 166.897 166.694 166.491 166.288 166.085 166.075 166.066 166.057 166.049 166.040 166.031 166.022 166.013 166.004 166.005 166.014 166.023 166.032 166.041 166.042 166.042 166.042 166.042 166.040 166.032 166.023 166.014 166.005 165.822 165.398 164.974 164.550 164.126 163.546 162.901 162.256 161.611 160.967 +1176.09 170.459 170.536 170.612 170.689 170.765 170.842 170.919 170.996 171.073 171.150 171.204 171.243 171.281 171.320 171.359 171.733 172.157 172.581 173.006 173.451 174.010 174.569 175.127 175.686 176.135 176.443 176.751 177.059 177.366 177.298 177.086 176.874 176.662 176.451 176.451 176.451 176.451 176.450 176.388 176.176 175.964 175.752 175.540 175.228 174.843 174.457 174.072 173.687 172.970 172.200 171.429 170.659 169.939 169.514 169.090 168.666 168.242 167.926 167.753 167.579 167.406 167.233 167.060 166.887 166.714 166.541 166.367 166.328 166.289 166.250 166.211 166.172 166.134 166.095 166.056 166.017 166.022 166.061 166.100 166.139 166.177 166.183 166.183 166.183 166.183 166.178 166.139 166.100 166.061 166.022 165.822 165.398 164.974 164.550 164.125 163.525 162.850 162.175 161.500 160.825 +1246.22 170.036 170.172 170.309 170.445 170.582 170.719 170.855 170.992 171.129 171.266 171.363 171.432 171.500 171.569 171.638 172.015 172.440 172.864 173.288 173.724 174.223 174.722 175.221 175.720 176.096 176.313 176.531 176.749 176.967 176.874 176.662 176.450 176.237 176.027 176.027 176.026 176.026 176.026 175.964 175.752 175.540 175.328 175.116 174.821 174.466 174.110 173.755 173.400 172.739 172.028 171.318 170.608 169.939 169.514 169.090 168.666 168.242 167.939 167.795 167.652 167.509 167.366 167.223 167.080 166.937 166.793 166.650 166.581 166.512 166.443 166.374 166.305 166.237 166.168 166.099 166.030 166.039 166.108 166.177 166.246 166.314 166.325 166.325 166.325 166.324 166.315 166.246 166.177 166.109 166.040 165.822 165.398 164.973 164.549 164.125 163.503 162.798 162.094 161.389 160.684 +1316.35 169.613 169.809 170.005 170.202 170.398 170.595 170.792 170.989 171.185 171.382 171.522 171.621 171.719 171.818 171.916 172.298 172.722 173.147 173.571 173.997 174.436 174.875 175.314 175.753 176.056 176.184 176.312 176.440 176.568 176.450 176.238 176.025 175.813 175.602 175.602 175.602 175.602 175.602 175.540 175.328 175.116 174.904 174.691 174.414 174.089 173.764 173.438 173.113 172.508 171.857 171.207 170.556 169.939 169.514 169.090 168.666 168.242 167.951 167.838 167.725 167.612 167.499 167.386 167.272 167.159 167.046 166.933 166.834 166.735 166.636 166.537 166.438 166.339 166.241 166.142 166.043 166.056 166.155 166.254 166.353 166.451 166.466 166.466 166.466 166.466 166.452 166.354 166.255 166.156 166.057 165.822 165.397 164.973 164.549 164.125 163.482 162.747 162.012 161.277 160.543 +1386.48 169.189 169.445 169.702 169.958 170.215 170.471 170.728 170.985 171.242 171.499 171.681 171.809 171.938 172.067 172.195 172.581 173.005 173.429 173.853 174.271 174.650 175.029 175.408 175.787 176.017 176.055 176.093 176.131 176.168 176.026 175.814 175.601 175.389 175.178 175.178 175.178 175.178 175.178 175.116 174.904 174.692 174.479 174.267 174.007 173.712 173.417 173.121 172.826 172.277 171.686 171.096 170.505 169.939 169.515 169.090 168.666 168.242 167.964 167.881 167.798 167.715 167.632 167.548 167.465 167.382 167.299 167.216 167.087 166.958 166.829 166.700 166.571 166.442 166.313 166.185 166.056 166.073 166.202 166.331 166.460 166.588 166.607 166.607 166.607 166.607 166.590 166.461 166.332 166.203 166.075 165.821 165.397 164.973 164.549 164.125 163.460 162.696 161.931 161.166 160.401 +1456.61 168.766 169.082 169.398 169.715 170.031 170.348 170.665 170.981 171.298 171.615 171.840 171.998 172.157 172.315 172.474 172.863 173.288 173.712 174.136 174.544 174.863 175.183 175.502 175.820 175.977 175.925 175.873 175.821 175.769 175.602 175.389 175.177 174.965 174.754 174.754 174.754 174.754 174.754 174.692 174.480 174.267 174.055 173.843 173.600 173.335 173.070 172.804 172.539 172.046 171.515 170.984 170.454 169.939 169.515 169.090 168.666 168.242 167.977 167.924 167.871 167.818 167.764 167.711 167.658 167.605 167.552 167.498 167.340 167.181 167.022 166.863 166.704 166.545 166.386 166.228 166.069 166.090 166.249 166.408 166.567 166.725 166.749 166.749 166.749 166.749 166.727 166.568 166.409 166.251 166.092 165.821 165.397 164.973 164.549 164.125 163.439 162.644 161.849 161.055 160.260 +1526.74 168.342 168.718 169.095 169.471 169.848 170.224 170.601 170.978 171.354 171.731 171.998 172.187 172.376 172.564 172.753 173.146 173.570 173.994 174.419 174.818 175.077 175.336 175.595 175.854 175.938 175.796 175.654 175.512 175.370 175.177 174.965 174.753 174.541 174.330 174.330 174.330 174.330 174.329 174.268 174.056 173.843 173.631 173.419 173.193 172.958 172.723 172.487 172.252 171.814 171.344 170.873 170.403 169.939 169.515 169.090 168.666 168.242 167.990 167.967 167.944 167.920 167.897 167.874 167.851 167.828 167.804 167.781 167.593 167.404 167.215 167.026 166.837 166.648 166.459 166.270 166.082 166.107 166.296 166.485 166.674 166.862 166.890 166.890 166.890 166.890 166.864 166.675 166.487 166.298 166.109 165.821 165.397 164.973 164.549 164.125 163.417 162.593 161.768 160.943 160.118 +1596.87 167.976 168.394 168.812 169.230 169.648 170.071 170.507 170.944 171.381 171.818 172.123 172.336 172.548 172.760 172.972 173.362 173.780 174.197 174.615 175.001 175.214 175.426 175.638 175.850 175.879 175.674 175.468 175.263 175.057 174.838 174.612 174.387 174.161 173.937 173.930 173.924 173.917 173.910 173.844 173.631 173.419 173.207 172.995 172.779 172.560 172.341 172.122 171.903 171.514 171.096 170.679 170.261 169.845 169.434 169.024 168.613 168.202 167.971 167.978 167.984 167.991 167.998 168.005 168.012 168.018 168.025 168.032 167.820 167.608 167.396 167.184 166.972 166.760 166.548 166.336 166.123 166.145 166.343 166.542 166.740 166.939 166.974 166.981 166.988 166.994 166.971 166.759 166.547 166.335 166.123 165.824 165.406 164.989 164.571 164.153 163.436 162.594 161.752 160.911 160.069 +1667.00 167.834 168.222 168.610 168.998 169.386 169.806 170.302 170.799 171.295 171.792 172.123 172.335 172.548 172.760 172.972 173.336 173.724 174.111 174.499 174.860 175.072 175.284 175.496 175.708 175.751 175.576 175.400 175.225 175.049 174.794 174.509 174.224 173.938 173.654 173.617 173.581 173.544 173.507 173.419 173.207 172.995 172.783 172.571 172.337 172.089 171.840 171.591 171.342 170.974 170.586 170.199 169.811 169.429 169.079 168.728 168.377 168.027 167.842 167.879 167.916 167.953 167.989 168.026 168.063 168.100 168.137 168.173 167.962 167.749 167.537 167.325 167.113 166.901 166.689 166.477 166.265 166.252 166.391 166.529 166.668 166.807 166.858 166.895 166.932 166.968 166.971 166.759 166.547 166.335 166.123 165.836 165.449 165.061 164.674 164.286 163.598 162.787 161.975 161.163 160.351 +1737.14 167.692 168.050 168.408 168.766 169.124 169.540 170.097 170.653 171.210 171.767 172.123 172.335 172.547 172.759 172.972 173.310 173.668 174.025 174.383 174.719 174.931 175.143 175.355 175.567 175.623 175.477 175.332 175.186 175.041 174.751 174.406 174.061 173.715 173.371 173.304 173.238 173.171 173.104 172.995 172.783 172.571 172.359 172.147 171.896 171.617 171.338 171.059 170.780 170.434 170.077 169.719 169.362 169.014 168.723 168.432 168.142 167.851 167.714 167.781 167.847 167.914 167.981 168.048 168.114 168.181 168.248 168.315 168.103 167.891 167.679 167.467 167.255 167.042 166.830 166.618 166.406 166.359 166.438 166.517 166.595 166.674 166.742 166.809 166.876 166.943 166.971 166.759 166.547 166.335 166.122 165.849 165.491 165.134 164.776 164.418 163.761 162.979 162.197 161.415 160.633 +1807.27 167.550 167.878 168.206 168.534 168.862 169.275 169.891 170.508 171.125 171.741 172.123 172.335 172.547 172.759 172.971 173.284 173.611 173.939 174.267 174.577 174.789 175.001 175.213 175.425 175.495 175.379 175.263 175.148 175.032 174.708 174.303 173.898 173.492 173.088 172.992 172.895 172.798 172.701 172.571 172.359 172.147 171.935 171.722 171.455 171.146 170.837 170.528 170.219 169.894 169.567 169.239 168.912 168.598 168.368 168.137 167.906 167.676 167.585 167.682 167.779 167.876 167.972 168.069 168.166 168.263 168.359 168.456 168.244 168.032 167.820 167.608 167.396 167.184 166.972 166.760 166.548 166.467 166.485 166.504 166.523 166.541 166.627 166.723 166.820 166.917 166.971 166.759 166.547 166.334 166.122 165.861 165.534 165.206 164.879 164.551 163.923 163.171 162.419 161.667 160.915 +1877.40 167.408 167.706 168.004 168.302 168.600 169.010 169.686 170.363 171.039 171.716 172.123 172.335 172.547 172.759 172.971 173.258 173.555 173.853 174.151 174.436 174.648 174.860 175.072 175.284 175.366 175.281 175.195 175.110 175.024 174.665 174.200 173.735 173.269 172.805 172.679 172.552 172.425 172.298 172.147 171.935 171.723 171.510 171.298 171.013 170.674 170.336 169.997 169.658 169.354 169.057 168.759 168.462 168.183 168.012 167.841 167.671 167.500 167.457 167.584 167.710 167.837 167.964 168.090 168.217 168.344 168.471 168.597 168.386 168.174 167.962 167.749 167.537 167.325 167.113 166.901 166.689 166.574 166.533 166.491 166.450 166.409 166.511 166.638 166.764 166.891 166.971 166.759 166.547 166.334 166.122 165.874 165.576 165.279 164.981 164.683 164.085 163.363 162.642 161.920 161.198 +1947.53 167.267 167.535 167.802 168.070 168.338 168.744 169.480 170.217 170.954 171.690 172.123 172.335 172.547 172.759 172.971 173.232 173.499 173.767 174.035 174.294 174.506 174.718 174.930 175.142 175.238 175.182 175.127 175.071 175.016 174.622 174.097 173.572 173.046 172.522 172.366 172.209 172.052 171.896 171.723 171.511 171.298 171.086 170.874 170.572 170.203 169.834 169.465 169.097 168.815 168.547 168.280 168.012 167.767 167.656 167.546 167.435 167.324 167.328 167.485 167.642 167.798 167.955 168.112 168.269 168.425 168.582 168.739 168.527 168.315 168.103 167.891 167.679 167.467 167.254 167.042 166.830 166.681 166.580 166.479 166.377 166.276 166.395 166.552 166.708 166.865 166.971 166.759 166.546 166.334 166.122 165.887 165.619 165.351 165.084 164.816 164.248 163.556 162.864 162.172 161.480 +2017.66 167.125 167.363 167.601 167.838 168.076 168.478 169.275 170.071 170.868 171.665 172.123 172.335 172.547 172.759 172.971 173.205 173.443 173.681 173.919 174.153 174.365 174.577 174.789 175.001 175.110 175.084 175.058 175.033 175.007 174.579 173.994 173.409 172.823 172.240 172.053 171.866 171.679 171.493 171.299 171.086 170.874 170.662 170.450 170.131 169.732 169.333 168.934 168.535 168.275 168.037 167.800 167.562 167.352 167.301 167.250 167.199 167.149 167.200 167.386 167.573 167.760 167.947 168.133 168.320 168.507 168.693 168.880 168.668 168.456 168.244 168.032 167.820 167.608 167.396 167.184 166.972 166.788 166.627 166.466 166.305 166.144 166.279 166.466 166.653 166.839 166.971 166.758 166.546 166.334 166.122 165.899 165.662 165.424 165.186 164.949 164.410 163.748 163.086 162.424 161.762 +2087.79 167.002 167.222 167.442 167.663 167.883 168.285 169.126 169.966 170.806 171.646 172.120 172.328 172.536 172.744 172.952 173.148 173.343 173.538 173.732 173.929 174.136 174.343 174.551 174.758 174.879 174.888 174.896 174.905 174.914 174.468 173.845 173.222 172.599 171.978 171.766 171.554 171.342 171.129 170.917 170.705 170.493 170.281 170.069 169.738 169.318 168.898 168.479 168.059 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.089 167.296 167.504 167.711 167.919 168.126 168.334 168.541 168.749 168.956 168.749 168.542 168.334 168.127 167.918 167.706 167.494 167.282 167.070 166.860 166.653 166.445 166.238 166.030 166.181 166.393 166.605 166.817 166.971 166.764 166.556 166.348 166.141 165.929 165.713 165.496 165.279 165.063 164.552 163.920 163.288 162.656 162.024 +2157.92 167.002 167.282 167.563 167.843 168.123 168.550 169.330 170.111 170.891 171.671 172.103 172.281 172.459 172.636 172.814 172.903 172.978 173.053 173.127 173.217 173.395 173.572 173.749 173.927 174.057 174.125 174.194 174.262 174.331 173.967 173.434 172.901 172.368 171.837 171.625 171.412 171.200 170.988 170.776 170.564 170.352 170.140 169.927 169.614 169.224 168.834 168.445 168.055 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.076 167.254 167.431 167.609 167.786 167.964 168.141 168.319 168.496 168.674 168.496 168.319 168.141 167.964 167.777 167.565 167.353 167.140 166.928 166.736 166.558 166.381 166.203 166.026 166.181 166.393 166.605 166.817 166.975 166.798 166.620 166.442 166.265 166.058 165.811 165.565 165.318 165.072 164.573 163.971 163.369 162.767 162.165 +2228.05 167.003 167.343 167.683 168.023 168.363 168.815 169.535 170.256 170.976 171.696 172.085 172.233 172.381 172.529 172.677 172.658 172.613 172.568 172.523 172.506 172.653 172.801 172.948 173.095 173.234 173.363 173.491 173.620 173.749 173.467 173.024 172.580 172.137 171.695 171.483 171.271 171.059 170.847 170.635 170.423 170.210 169.998 169.786 169.489 169.130 168.770 168.410 168.051 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.063 167.211 167.358 167.506 167.653 167.801 167.948 168.096 168.243 168.391 168.244 168.096 167.949 167.801 167.635 167.423 167.211 166.999 166.787 166.612 166.464 166.317 166.169 166.021 166.181 166.393 166.605 166.818 166.979 166.832 166.684 166.536 166.389 166.186 165.910 165.633 165.357 165.080 164.594 164.022 163.450 162.878 162.306 +2298.18 167.003 167.403 167.803 168.203 168.604 169.080 169.740 170.400 171.061 171.721 172.068 172.186 172.304 172.422 172.539 172.413 172.248 172.083 171.918 171.794 171.912 172.029 172.146 172.264 172.412 172.600 172.789 172.977 173.166 172.966 172.613 172.260 171.907 171.554 171.342 171.130 170.918 170.705 170.493 170.281 170.069 169.857 169.645 169.365 169.036 168.706 168.376 168.047 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.050 167.168 167.285 167.403 167.520 167.638 167.755 167.873 167.991 168.108 167.991 167.873 167.756 167.638 167.494 167.282 167.070 166.858 166.646 166.487 166.370 166.252 166.135 166.017 166.181 166.393 166.605 166.818 166.984 166.866 166.748 166.631 166.513 166.315 166.008 165.702 165.395 165.089 164.615 164.073 163.531 162.989 162.447 +2368.32 167.003 167.463 167.923 168.383 168.844 169.345 169.945 170.545 171.146 171.746 172.051 172.139 172.227 172.314 172.402 172.169 171.884 171.599 171.313 171.083 171.170 171.258 171.345 171.432 171.589 171.838 172.086 172.335 172.583 172.465 172.202 171.939 171.675 171.413 171.200 170.988 170.776 170.564 170.352 170.140 169.928 169.716 169.503 169.241 168.941 168.642 168.342 168.042 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.038 167.125 167.213 167.300 167.388 167.475 167.563 167.650 167.738 167.825 167.738 167.650 167.563 167.475 167.352 167.140 166.928 166.716 166.504 166.363 166.275 166.188 166.100 166.013 166.181 166.393 166.606 166.818 166.988 166.900 166.812 166.725 166.637 166.443 166.107 165.770 165.434 165.097 164.636 164.124 163.612 163.100 162.588 +2438.45 167.003 167.523 168.043 168.563 169.084 169.610 170.150 170.691 171.231 171.771 172.033 172.091 172.149 172.207 172.265 171.924 171.519 171.114 170.709 170.371 170.429 170.486 170.544 170.601 170.767 171.075 171.384 171.692 172.001 171.964 171.791 171.617 171.444 171.271 171.059 170.847 170.635 170.423 170.211 169.998 169.786 169.574 169.362 169.117 168.847 168.578 168.308 168.038 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.025 167.082 167.140 167.197 167.255 167.312 167.370 167.427 167.485 167.543 167.485 167.428 167.370 167.313 167.211 166.999 166.787 166.575 166.363 166.239 166.181 166.124 166.066 166.008 166.181 166.393 166.606 166.818 166.992 166.934 166.877 166.819 166.761 166.572 166.205 165.839 165.472 165.106 164.657 164.175 163.693 163.211 162.729 +2508.58 167.003 167.583 168.163 168.743 169.323 169.875 170.355 170.836 171.316 171.796 172.016 172.044 172.072 172.100 172.128 171.680 171.155 170.630 170.104 169.660 169.687 169.715 169.742 169.770 169.944 170.313 170.681 171.050 171.418 171.463 171.380 171.296 171.213 171.130 170.918 170.706 170.494 170.281 170.069 169.857 169.645 169.433 169.221 168.993 168.753 168.513 168.274 168.034 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.012 167.039 167.067 167.094 167.122 167.150 167.177 167.205 167.232 167.260 167.232 167.205 167.177 167.150 167.070 166.857 166.645 166.433 166.221 166.114 166.087 166.059 166.032 166.004 166.181 166.394 166.606 166.818 166.996 166.968 166.941 166.913 166.885 166.700 166.304 165.907 165.511 165.114 164.678 164.226 163.774 163.322 162.870 +2578.71 166.985 167.620 168.254 168.888 169.522 170.096 170.519 170.943 171.367 171.791 171.969 171.965 171.960 171.956 171.951 171.401 170.762 170.123 169.484 168.939 168.941 168.943 168.944 168.946 169.130 169.554 169.978 170.402 170.826 170.949 170.954 170.958 170.962 170.967 170.757 170.547 170.337 170.127 169.917 169.708 169.498 169.288 169.078 168.869 168.659 168.449 168.239 168.030 167.818 167.606 167.394 167.182 167.000 166.997 166.995 166.992 166.990 166.988 166.988 166.988 166.988 166.988 166.988 166.988 166.988 166.988 166.988 166.991 166.993 166.996 166.998 166.940 166.731 166.521 166.311 166.101 166.013 166.015 166.017 166.020 166.022 166.202 166.411 166.621 166.831 167.010 167.006 167.001 166.996 166.992 166.809 166.387 165.966 165.544 165.122 164.698 164.274 163.850 163.425 163.001 +2648.84 166.702 167.306 167.911 168.515 169.119 169.671 170.095 170.519 170.943 171.367 171.510 171.446 171.382 171.317 171.253 170.668 170.000 169.331 168.662 168.095 168.127 168.159 168.190 168.222 168.423 168.847 169.271 169.695 170.119 170.285 170.350 170.414 170.478 170.543 170.363 170.183 170.003 169.823 169.643 169.463 169.284 169.104 168.924 168.744 168.565 168.385 168.205 168.026 167.818 167.606 167.394 167.182 166.995 166.963 166.930 166.898 166.866 166.847 166.847 166.847 166.847 166.847 166.847 166.847 166.847 166.847 166.847 166.880 166.912 166.944 166.977 166.949 166.769 166.589 166.410 166.230 166.171 166.204 166.236 166.268 166.301 166.459 166.639 166.818 166.998 167.143 167.079 167.014 166.949 166.885 166.681 166.289 165.897 165.505 165.113 164.698 164.274 163.849 163.425 163.001 +2718.97 166.419 166.993 167.567 168.142 168.716 169.247 169.671 170.095 170.519 170.942 171.052 170.927 170.803 170.679 170.554 169.936 169.237 168.538 167.840 167.251 167.313 167.374 167.436 167.498 167.716 168.140 168.564 168.988 169.412 169.621 169.745 169.870 169.994 170.118 169.969 169.819 169.669 169.519 169.369 169.219 169.069 168.920 168.770 168.620 168.470 168.321 168.171 168.021 167.818 167.606 167.394 167.182 166.991 166.929 166.866 166.804 166.741 166.706 166.706 166.706 166.706 166.706 166.706 166.706 166.706 166.706 166.706 166.768 166.831 166.893 166.955 166.957 166.808 166.658 166.508 166.358 166.330 166.392 166.454 166.517 166.579 166.716 166.866 167.016 167.165 167.276 167.151 167.027 166.902 166.778 166.552 166.190 165.828 165.466 165.104 164.698 164.274 163.849 163.425 163.001 +2789.10 166.136 166.680 167.224 167.768 168.313 168.822 169.246 169.670 170.094 170.518 170.593 170.409 170.225 170.040 169.856 169.204 168.475 167.746 167.017 166.407 166.499 166.590 166.682 166.774 167.009 167.433 167.857 168.281 168.705 168.957 169.141 169.326 169.510 169.694 169.574 169.454 169.335 169.215 169.095 168.975 168.855 168.735 168.616 168.496 168.376 168.256 168.137 168.017 167.818 167.606 167.394 167.182 166.987 166.894 166.802 166.709 166.617 166.564 166.564 166.564 166.564 166.564 166.564 166.564 166.564 166.564 166.564 166.657 166.749 166.842 166.934 166.966 166.846 166.726 166.607 166.487 166.488 166.581 166.673 166.765 166.857 166.973 167.093 167.213 167.332 167.409 167.224 167.040 166.855 166.671 166.423 166.091 165.759 165.427 165.095 164.698 164.273 163.849 163.425 163.001 +2859.23 165.852 166.367 166.881 167.395 167.910 168.398 168.822 169.246 169.670 170.094 170.135 169.890 169.646 169.402 169.157 168.471 167.712 166.954 166.195 165.563 165.684 165.806 165.928 166.050 166.302 166.726 167.150 167.573 167.997 168.293 168.537 168.782 169.026 169.270 169.180 169.090 169.000 168.911 168.821 168.731 168.641 168.551 168.462 168.372 168.282 168.192 168.103 168.013 167.818 167.606 167.394 167.182 166.982 166.860 166.738 166.615 166.493 166.423 166.423 166.423 166.423 166.423 166.423 166.423 166.423 166.423 166.423 166.545 166.668 166.790 166.913 166.974 166.885 166.795 166.705 166.615 166.647 166.769 166.891 167.014 167.136 167.230 167.320 167.410 167.500 167.542 167.297 167.053 166.808 166.564 166.295 165.993 165.691 165.389 165.087 164.697 164.273 163.849 163.425 163.001 +2929.37 165.569 166.054 166.538 167.022 167.506 167.973 168.397 168.821 169.245 169.669 169.676 169.372 169.068 168.763 168.459 167.739 166.950 166.161 165.372 164.719 164.870 165.022 165.174 165.326 165.594 166.018 166.442 166.866 167.290 167.629 167.933 168.237 168.542 168.846 168.786 168.726 168.666 168.606 168.547 168.487 168.427 168.367 168.307 168.248 168.188 168.128 168.068 168.009 167.818 167.606 167.394 167.182 166.978 166.826 166.673 166.521 166.369 166.281 166.281 166.281 166.281 166.281 166.281 166.281 166.281 166.281 166.281 166.434 166.586 166.739 166.891 166.983 166.923 166.863 166.804 166.744 166.805 166.958 167.110 167.262 167.415 167.488 167.547 167.607 167.667 167.675 167.370 167.065 166.761 166.456 166.166 165.894 165.622 165.350 165.078 164.697 164.273 163.849 163.425 163.000 +2999.50 165.286 165.741 166.195 166.649 167.103 167.549 167.973 168.397 168.821 169.245 169.218 168.854 168.489 168.125 167.761 167.006 166.188 165.369 164.550 163.874 164.056 164.238 164.420 164.602 164.887 165.311 165.735 166.159 166.583 166.964 167.329 167.693 168.058 168.422 168.392 168.362 168.332 168.302 168.272 168.242 168.213 168.183 168.153 168.123 168.093 168.064 168.034 168.004 167.818 167.606 167.394 167.182 166.974 166.792 166.609 166.427 166.244 166.140 166.140 166.140 166.140 166.140 166.140 166.140 166.140 166.140 166.140 166.322 166.505 166.687 166.870 166.992 166.962 166.932 166.902 166.872 166.964 167.146 167.329 167.511 167.693 167.745 167.774 167.804 167.834 167.807 167.443 167.078 166.714 166.349 166.037 165.795 165.553 165.311 165.069 164.697 164.273 163.849 163.424 163.000 +3069.63 165.003 165.428 165.852 166.276 166.700 167.125 167.548 167.972 168.396 168.820 168.760 168.335 167.911 167.487 167.062 166.274 165.425 164.576 163.728 163.030 163.242 163.455 163.667 163.879 164.182 164.606 165.030 165.455 165.879 166.303 166.727 167.152 167.576 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 167.818 167.606 167.394 167.182 166.970 166.758 166.545 166.333 166.121 166.000 166.000 166.000 166.000 166.000 166.000 166.000 166.000 166.000 166.000 166.212 166.424 166.636 166.848 167.000 167.000 167.000 167.000 167.000 167.121 167.333 167.545 167.758 167.970 168.000 168.000 168.000 168.000 167.939 167.515 167.091 166.667 166.242 165.909 165.697 165.485 165.273 165.061 164.697 164.273 163.848 163.424 163.000 diff --git a/examples/05_Anchors/inputs/GulfOfMaine_soil_layered_100x100.txt b/examples/05_Anchors/inputs/GulfOfMaine_soil_layered_100x100.txt new file mode 100644 index 00000000..50ba5b79 --- /dev/null +++ b/examples/05_Anchors/inputs/GulfOfMaine_soil_layered_100x100.txt @@ -0,0 +1,112 @@ +--- MoorPy Soil Input File --- +nGridX 100 +nGridY 100 + -4420.52 -4345.53 -4270.54 -4195.55 -4120.57 -4045.58 -3970.59 -3895.60 -3820.61 -3745.62 -3670.63 -3595.64 -3520.66 -3445.67 -3370.68 -3295.69 -3220.70 -3145.71 -3070.72 -2995.74 -2920.75 -2845.76 -2770.77 -2695.78 -2620.79 -2545.80 -2470.81 -2395.83 -2320.84 -2245.85 -2170.86 -2095.87 -2020.88 -1945.89 -1870.90 -1795.92 -1720.93 -1645.94 -1570.95 -1495.96 -1420.97 -1345.98 -1270.99 -1196.01 -1121.02 -1046.03 -971.04 -896.05 -821.06 -746.07 -671.08 -596.10 -521.11 -446.12 -371.13 -296.14 -221.15 -146.16 -71.17 3.81 78.80 153.79 228.78 303.77 378.76 453.75 528.74 603.72 678.71 753.70 828.69 903.68 978.67 1053.66 1128.64 1203.63 1278.62 1353.61 1428.60 1503.59 1578.58 1653.57 1728.55 1803.54 1878.53 1953.52 2028.51 2103.50 2178.49 2253.48 2328.46 2403.45 2478.44 2553.43 2628.42 2703.41 2778.40 2853.39 2928.37 3003.36 +-3873.36 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 +-3803.23 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 +-3733.10 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 +-3662.97 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3592.83 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3522.70 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3452.57 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3382.44 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3312.31 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3242.18 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3172.05 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3101.92 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 +-3031.78 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 +-2961.65 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2891.52 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2821.39 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2751.26 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2681.13 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2611.00 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2540.87 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 +-2470.74 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 +-2400.60 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 +-2330.47 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 +-2260.34 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 +-2190.21 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-2120.08 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-2049.95 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-1979.82 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 +-1909.69 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 +-1839.55 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 +-1769.42 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 +-1699.29 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_1 +-1629.16 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 +-1559.03 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 +-1488.90 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 +-1418.77 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 +-1348.64 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 +-1278.51 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 +-1208.37 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 +-1138.24 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 +-1068.11 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-997.98 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-927.85 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-857.72 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-787.59 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-717.46 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-647.32 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-577.19 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 +-507.06 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 +-436.93 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 +-366.80 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +-296.67 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +-226.54 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +-156.41 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +-86.28 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +-16.14 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +53.99 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +124.12 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +194.25 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +264.38 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +334.51 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +404.64 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +474.77 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +544.91 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +615.04 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +685.17 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +755.30 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +825.43 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +895.56 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +965.69 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1035.82 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1105.95 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1176.09 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1246.22 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1316.35 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1386.48 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1456.61 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1526.74 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1596.87 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1667.00 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1737.14 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1807.27 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1877.40 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1947.53 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +2017.66 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2087.79 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2157.92 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2228.05 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2298.18 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2368.32 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2438.45 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2508.58 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2578.71 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2648.84 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2718.97 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2789.10 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2859.23 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2929.37 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2999.50 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +3069.63 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +--- SOIL TYPES --- +Class gamma Su0 k alpha phi UCS Em +(name) (kN/m^3) (kPa) (kPa/m) (-) (deg) (MPa) (MPa) +pro_0 8.00 14.0 2.8 0.7 - - - +pro_1 8.00 12.0 2.4 0.7 - - - +pro_2 8.00 10.0 2.0 0.7 - - - +pro_3 8.00 8.0 1.6 0.7 - - - +pro_4 8.00 6.0 1.2 0.7 - - - \ No newline at end of file diff --git a/examples/05_Anchors/inputs/GulfOfMaine_soil_profiles.yaml b/examples/05_Anchors/inputs/GulfOfMaine_soil_profiles.yaml new file mode 100644 index 00000000..d0308033 --- /dev/null +++ b/examples/05_Anchors/inputs/GulfOfMaine_soil_profiles.yaml @@ -0,0 +1,116 @@ +pro_0: + layers: + - soil_type: clay + top: 0 + bottom: 12 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 10.0 + Su_bot: 20.0 + - soil_type: clay + top: 12 + bottom: 22 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 15.0 + Su_bot: 25.0 + - soil_type: clay + top: 22 + bottom: 30 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 55.0 + Su_bot: 70.0 +pro_1: + layers: + - soil_type: clay + top: 0 + bottom: 5 + gamma_top: 8.2 + gamma_bot: 8.2 + Su_top: 12.0 + Su_bot: 22.0 + - soil_type: clay + top: 5 + bottom: 15 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 22.0 + Su_bot: 22.0 + - soil_type: clay + top: 15 + bottom: 30 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 22.0 + Su_bot: 50.0 +pro_2: + layers: + - soil_type: clay + top: 0 + bottom: 8 + gamma_top: 8.4 + gamma_bot: 8.4 + Su_top: 14.0 + Su_bot: 14.0 + - soil_type: clay + top: 8 + bottom: 18 + gamma_top: 8.4 + gamma_bot: 8.4 + Su_top: 15.0 + Su_bot: 25.0 + - soil_type: clay + top: 18 + bottom: 30 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 25.0 + Su_bot: 25.0 + +pro_3: + layers: + - soil_type: clay + top: 0 + bottom: 15 + gamma_top: 8.6 + gamma_bot: 8.6 + Su_top: 20.0 + Su_bot: 26.0 + - soil_type: clay + top: 15 + bottom: 25 + gamma_top: 8.6 + gamma_bot: 8.6 + Su_top: 20.0 + Su_bot: 40.0 + - soil_type: clay + top: 25 + bottom: 30 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 40.0 + Su_bot: 40.0 +pro_4: + layers: + - soil_type: clay + top: 0 + bottom: 3 + gamma_top: 8.8 + gamma_bot: 8.8 + Su_top: 10.0 + Su_bot: 10.0 + - soil_type: clay + top: 3 + bottom: 10 + gamma_top: 8.8 + gamma_bot: 8.8 + Su_top: 16.0 + Su_bot: 40.0 + - soil_type: clay + top: 10 + bottom: 30 + gamma_top: 8.8 + gamma_bot: 8.8 + Su_top: 40.0 + Su_bot: 60.0 \ No newline at end of file diff --git a/examples/GulfOfMaine_bathymetry_100x100.txt b/examples/GulfOfMaine_bathymetry_100x100.txt new file mode 100644 index 00000000..22b0bc97 --- /dev/null +++ b/examples/GulfOfMaine_bathymetry_100x100.txt @@ -0,0 +1,104 @@ +--- MoorPy Bathymetry Input File --- +nGridX 100 +nGridY 100 + -4420.52 -4345.53 -4270.54 -4195.55 -4120.57 -4045.58 -3970.59 -3895.60 -3820.61 -3745.62 -3670.63 -3595.64 -3520.66 -3445.67 -3370.68 -3295.69 -3220.70 -3145.71 -3070.72 -2995.74 -2920.75 -2845.76 -2770.77 -2695.78 -2620.79 -2545.80 -2470.81 -2395.83 -2320.84 -2245.85 -2170.86 -2095.87 -2020.88 -1945.89 -1870.90 -1795.92 -1720.93 -1645.94 -1570.95 -1495.96 -1420.97 -1345.98 -1270.99 -1196.01 -1121.02 -1046.03 -971.04 -896.05 -821.06 -746.07 -671.08 -596.10 -521.11 -446.12 -371.13 -296.14 -221.15 -146.16 -71.17 3.81 78.80 153.79 228.78 303.77 378.76 453.75 528.74 603.72 678.71 753.70 828.69 903.68 978.67 1053.66 1128.64 1203.63 1278.62 1353.61 1428.60 1503.59 1578.58 1653.57 1728.55 1803.54 1878.53 1953.52 2028.51 2103.50 2178.49 2253.48 2328.46 2403.45 2478.44 2553.43 2628.42 2703.41 2778.40 2853.39 2928.37 3003.36 +-3873.36 176.051 176.899 177.747 178.595 179.442 179.494 178.011 176.528 175.045 173.562 172.871 172.659 172.447 172.235 172.023 172.577 173.212 173.848 174.483 175.080 175.503 175.927 176.350 176.773 176.902 176.690 176.479 176.267 176.056 175.370 174.523 173.676 172.829 172.010 172.221 172.432 172.643 172.854 173.000 173.002 173.004 173.006 173.007 173.256 173.677 174.098 174.519 174.939 174.812 174.602 174.391 174.181 174.003 174.004 174.006 174.007 174.008 174.100 174.310 174.521 174.732 174.942 174.551 173.917 173.282 172.648 172.013 172.426 172.847 173.268 173.689 174.225 175.069 175.914 176.758 177.602 177.745 177.323 176.901 176.479 176.057 175.281 174.435 173.589 172.743 171.946 171.523 171.101 170.678 170.255 169.916 169.705 169.494 169.283 169.072 169.291 169.714 170.137 170.561 170.984 +-3803.23 176.470 177.228 177.985 178.743 179.501 179.525 178.132 176.739 175.346 173.953 173.276 173.035 172.793 172.551 172.309 172.832 173.438 174.043 174.649 175.215 175.609 176.002 176.396 176.789 176.916 176.734 176.553 176.371 176.190 175.534 174.717 173.900 173.083 172.291 172.443 172.594 172.745 172.895 173.028 173.120 173.211 173.303 173.395 173.592 173.863 174.134 174.405 174.676 174.607 174.487 174.367 174.246 174.153 174.215 174.276 174.337 174.398 174.498 174.649 174.799 174.950 175.101 174.735 174.161 173.586 173.012 172.437 172.702 172.973 173.244 173.515 173.893 174.558 175.222 175.887 176.551 176.663 176.331 175.999 175.667 175.335 174.649 173.893 173.137 172.381 171.670 171.307 170.945 170.582 170.219 169.940 169.789 169.638 169.486 169.335 169.553 169.947 170.340 170.734 171.127 +-3733.10 176.888 177.556 178.224 178.892 179.560 179.556 178.253 176.950 175.647 174.344 173.682 173.410 173.138 172.867 172.595 173.087 173.663 174.239 174.814 175.351 175.715 176.078 176.442 176.805 176.930 176.778 176.627 176.475 176.324 175.698 174.911 174.124 173.337 172.573 172.664 172.755 172.846 172.937 173.056 173.237 173.419 173.600 173.782 173.928 174.049 174.170 174.292 174.413 174.402 174.372 174.342 174.311 174.304 174.425 174.546 174.667 174.788 174.896 174.987 175.078 175.169 175.260 174.919 174.405 173.890 173.375 172.861 172.977 173.098 173.220 173.341 173.562 174.046 174.531 175.015 175.500 175.582 175.340 175.097 174.855 174.613 174.017 173.350 172.684 172.018 171.394 171.091 170.788 170.486 170.183 169.964 169.873 169.781 169.690 169.599 169.816 170.179 170.543 170.906 171.270 +-3662.97 177.307 177.885 178.463 179.041 179.619 179.588 178.374 177.161 175.948 174.735 174.088 173.786 173.484 173.182 172.881 173.343 173.889 174.434 174.980 175.487 175.820 176.154 176.488 176.821 176.944 176.822 176.700 176.579 176.457 175.862 175.105 174.348 173.591 172.854 172.885 172.916 172.947 172.978 173.083 173.355 173.626 173.897 174.169 174.264 174.235 174.207 174.178 174.150 174.198 174.257 174.317 174.376 174.454 174.635 174.816 174.997 175.178 175.295 175.326 175.356 175.387 175.418 175.103 174.649 174.194 173.739 173.284 173.253 173.224 173.195 173.167 173.230 173.534 173.839 174.144 174.449 174.500 174.348 174.196 174.044 173.891 173.385 172.808 172.232 171.656 171.118 170.875 170.632 170.389 170.146 169.988 169.956 169.925 169.894 169.862 170.079 170.412 170.745 171.079 171.412 +-3592.83 177.725 178.213 178.702 179.190 179.678 179.619 178.495 177.372 176.249 175.126 174.494 174.162 173.830 173.498 173.166 173.599 174.114 174.630 175.146 175.623 175.926 176.230 176.534 176.837 176.958 176.866 176.774 176.683 176.591 176.026 175.299 174.572 173.845 173.135 173.106 173.078 173.049 173.020 173.111 173.472 173.833 174.195 174.556 174.600 174.422 174.243 174.065 173.887 173.993 174.142 174.292 174.441 174.605 174.846 175.086 175.327 175.568 175.693 175.664 175.635 175.606 175.577 175.287 174.893 174.498 174.103 173.708 173.528 173.350 173.171 172.993 172.897 173.022 173.148 173.273 173.398 173.419 173.357 173.294 173.232 173.170 172.753 172.266 171.780 171.294 170.843 170.660 170.476 170.293 170.110 170.011 170.040 170.069 170.097 170.126 170.341 170.645 170.948 171.252 171.555 +-3522.70 178.144 178.542 178.941 179.339 179.737 179.650 178.616 177.583 176.550 175.516 174.899 174.538 174.176 173.814 173.452 173.854 174.340 174.826 175.311 175.758 176.032 176.306 176.579 176.853 176.971 176.910 176.848 176.786 176.725 176.190 175.493 174.796 174.098 173.416 173.328 173.239 173.150 173.062 173.138 173.589 174.041 174.492 174.943 174.936 174.608 174.280 173.952 173.624 173.788 174.028 174.267 174.506 174.755 175.056 175.357 175.658 175.958 176.091 176.002 175.913 175.825 175.736 175.471 175.137 174.802 174.467 174.132 173.804 173.475 173.147 172.819 172.565 172.511 172.456 172.401 172.347 172.338 172.365 172.393 172.420 172.448 172.121 171.724 171.328 170.931 170.567 170.444 170.321 170.197 170.074 170.035 170.124 170.212 170.301 170.389 170.604 170.877 171.151 171.424 171.698 +-3452.57 178.563 178.871 179.180 179.488 179.796 179.681 178.737 177.794 176.850 175.907 175.305 174.914 174.522 174.130 173.738 174.110 174.565 175.021 175.477 175.894 176.138 176.382 176.625 176.869 176.985 176.954 176.922 176.890 176.859 176.354 175.687 175.019 174.352 173.698 173.549 173.401 173.252 173.103 173.166 173.707 174.248 174.789 175.330 175.273 174.795 174.317 173.839 173.360 173.584 173.913 174.242 174.571 174.905 175.266 175.627 175.988 176.349 176.490 176.341 176.192 176.043 175.894 175.656 175.381 175.106 174.831 174.556 174.079 173.601 173.123 172.645 172.233 171.999 171.764 171.530 171.295 171.257 171.374 171.491 171.609 171.726 171.489 171.182 170.876 170.569 170.291 170.228 170.165 170.101 170.038 170.059 170.208 170.356 170.505 170.653 170.866 171.110 171.353 171.597 171.841 +-3382.44 178.982 179.200 179.419 179.637 179.855 179.712 178.858 178.004 177.151 176.297 175.711 175.289 174.868 174.446 174.024 174.365 174.791 175.217 175.643 176.030 176.244 176.458 176.671 176.885 176.999 176.997 176.996 176.994 176.992 176.518 175.881 175.243 174.606 173.979 173.771 173.562 173.353 173.145 173.193 173.824 174.455 175.086 175.717 175.609 174.981 174.353 173.725 173.097 173.379 173.798 174.217 174.636 175.056 175.476 175.897 176.318 176.739 176.888 176.679 176.471 176.262 176.053 175.840 175.625 175.410 175.195 174.979 174.354 173.726 173.098 172.470 171.901 171.487 171.072 170.658 170.244 170.175 170.383 170.590 170.797 171.005 170.857 170.640 170.424 170.207 170.015 170.012 170.009 170.005 170.002 170.083 170.292 170.500 170.708 170.917 171.129 171.342 171.556 171.770 171.983 +-3312.31 178.885 179.181 179.476 179.772 180.067 179.987 179.168 178.348 177.528 176.709 176.134 175.711 175.287 174.863 174.440 174.753 175.149 175.545 175.941 176.304 176.516 176.728 176.940 177.152 177.253 177.225 177.197 177.169 177.141 176.661 176.025 175.389 174.754 174.128 173.887 173.647 173.407 173.167 173.212 173.904 174.597 175.289 175.982 175.878 175.214 174.550 173.886 173.221 173.502 173.926 174.350 174.774 175.185 175.523 175.862 176.201 176.539 176.653 176.469 176.286 176.102 175.919 175.776 175.649 175.522 175.396 175.269 174.665 174.057 173.450 172.843 172.286 171.862 171.438 171.014 170.590 170.456 170.555 170.653 170.752 170.850 170.689 170.477 170.265 170.053 169.873 169.930 169.986 170.043 170.099 170.173 170.272 170.371 170.470 170.569 170.745 170.957 171.169 171.382 171.594 +-3242.18 178.749 179.134 179.519 179.905 180.290 180.280 179.491 178.701 177.912 177.122 176.559 176.135 175.711 175.288 174.864 175.151 175.517 175.882 176.248 176.587 176.799 177.011 177.223 177.435 177.522 177.464 177.406 177.348 177.290 176.802 176.167 175.531 174.895 174.268 173.998 173.728 173.458 173.188 173.230 173.982 174.735 175.487 176.240 176.143 175.449 174.755 174.061 173.367 173.643 174.067 174.491 174.915 175.313 175.561 175.810 176.059 176.307 176.383 176.229 176.076 175.922 175.769 175.698 175.662 175.625 175.588 175.551 174.977 174.400 173.822 173.245 172.710 172.286 171.862 171.438 171.014 170.814 170.792 170.771 170.750 170.728 170.547 170.336 170.124 169.912 169.739 169.855 169.972 170.088 170.205 170.266 170.245 170.225 170.204 170.183 170.321 170.533 170.745 170.957 171.170 +-3172.05 178.612 179.087 179.562 180.038 180.513 180.574 179.814 179.054 178.295 177.535 176.983 176.559 176.136 175.712 175.289 175.548 175.884 176.220 176.556 176.869 177.081 177.293 177.505 177.717 177.791 177.703 177.615 177.527 177.439 176.944 176.308 175.673 175.037 174.409 174.109 173.809 173.509 173.209 173.248 174.060 174.873 175.685 176.498 176.409 175.685 174.960 174.236 173.512 173.785 174.209 174.632 175.056 175.441 175.599 175.758 175.917 176.076 176.113 175.989 175.866 175.742 175.619 175.621 175.674 175.727 175.780 175.833 175.290 174.742 174.195 173.647 173.134 172.710 172.286 171.862 171.438 171.171 171.030 170.889 170.748 170.606 170.406 170.194 169.982 169.770 169.605 169.781 169.958 170.134 170.310 170.360 170.219 170.078 169.938 169.797 169.897 170.109 170.321 170.533 170.745 +-3101.92 178.475 179.040 179.605 180.170 180.736 180.867 180.137 179.408 178.678 177.948 177.408 176.984 176.560 176.137 175.713 175.945 176.251 176.557 176.863 177.152 177.364 177.576 177.788 178.000 178.060 177.942 177.824 177.706 177.588 177.086 176.450 175.814 175.178 174.550 174.220 173.890 173.560 173.229 173.266 174.138 175.011 175.883 176.755 176.674 175.920 175.166 174.412 173.658 173.926 174.350 174.774 175.198 175.569 175.637 175.706 175.775 175.844 175.843 175.749 175.656 175.562 175.469 175.544 175.687 175.830 175.973 176.116 175.602 175.085 174.567 174.050 173.558 173.134 172.710 172.286 171.862 171.529 171.268 171.007 170.745 170.484 170.265 170.053 169.841 169.629 169.470 169.707 169.943 170.180 170.416 170.453 170.192 169.932 169.671 169.411 169.473 169.685 169.897 170.109 170.321 +-3031.78 178.338 178.993 179.648 180.303 180.958 181.160 180.461 179.761 179.061 178.361 177.832 177.408 176.985 176.561 176.137 176.342 176.618 176.894 177.170 177.435 177.647 177.859 178.071 178.283 178.329 178.181 178.033 177.885 177.737 177.227 176.591 175.956 175.320 174.691 174.331 173.971 173.610 173.250 173.284 174.216 175.149 176.081 177.013 176.939 176.155 175.371 174.587 173.803 174.067 174.491 174.915 175.339 175.697 175.676 175.655 175.634 175.613 175.573 175.510 175.446 175.382 175.319 175.466 175.699 175.932 176.165 176.398 175.915 175.427 174.940 174.452 173.982 173.558 173.134 172.710 172.286 171.886 171.505 171.124 170.743 170.362 170.123 169.911 169.699 169.487 169.336 169.633 169.929 170.225 170.521 170.546 170.166 169.785 169.405 169.025 169.049 169.261 169.473 169.685 169.897 +-2961.65 178.201 178.946 179.691 180.436 181.181 181.453 180.784 180.114 179.444 178.775 178.256 177.833 177.409 176.985 176.562 176.739 176.985 177.231 177.477 177.717 177.929 178.142 178.354 178.566 178.598 178.420 178.242 178.064 177.886 177.369 176.733 176.097 175.462 174.832 174.441 174.051 173.661 173.271 173.302 174.294 175.287 176.279 177.271 177.205 176.391 175.577 174.763 173.949 174.209 174.633 175.057 175.480 175.825 175.714 175.603 175.492 175.381 175.303 175.270 175.236 175.202 175.169 175.389 175.712 176.034 176.357 176.680 176.227 175.770 175.312 174.855 174.406 173.982 173.558 173.134 172.711 172.244 171.743 171.242 170.741 170.240 169.982 169.770 169.558 169.346 169.202 169.558 169.915 170.271 170.627 170.640 170.139 169.639 169.139 168.638 168.625 168.837 169.049 169.261 169.473 +-2891.52 178.064 178.899 179.733 180.568 181.403 181.747 181.107 180.467 179.827 179.188 178.681 178.257 177.833 177.410 176.986 177.136 177.352 177.569 177.785 178.000 178.212 178.424 178.636 178.848 178.867 178.659 178.451 178.244 178.036 177.510 176.875 176.239 175.603 174.972 174.552 174.132 173.712 173.292 173.320 174.372 175.425 176.477 177.529 177.470 176.626 175.782 174.938 174.094 174.350 174.774 175.198 175.622 175.953 175.752 175.551 175.350 175.149 175.033 175.030 175.026 175.022 175.019 175.311 175.724 176.137 176.550 176.962 176.540 176.112 175.685 175.257 174.830 174.407 173.983 173.559 173.135 172.601 171.980 171.360 170.739 170.118 169.840 169.628 169.416 169.205 169.068 169.484 169.900 170.317 170.733 170.733 170.112 169.492 168.872 168.252 168.201 168.413 168.625 168.837 169.049 +-2821.39 178.038 178.783 179.528 180.273 181.018 181.311 180.701 180.090 179.480 178.870 178.406 178.033 177.661 177.289 176.916 177.091 177.329 177.567 177.804 178.042 178.280 178.518 178.756 178.994 179.014 178.776 178.538 178.300 178.062 177.568 176.984 176.400 175.817 175.237 174.813 174.390 173.966 173.542 173.546 174.527 175.508 176.489 177.470 177.410 176.615 175.820 175.024 174.229 174.469 174.866 175.264 175.662 175.961 175.696 175.432 175.167 174.903 174.730 174.677 174.625 174.572 174.520 174.788 175.185 175.583 175.981 176.378 176.064 175.745 175.426 175.107 174.788 174.469 174.150 173.831 173.512 173.017 172.381 171.745 171.109 170.473 170.237 170.077 169.917 169.757 169.661 170.033 170.404 170.776 171.147 171.103 170.441 169.779 169.117 168.455 168.355 168.515 168.675 168.834 168.994 +-2751.26 178.032 178.657 179.282 179.907 180.532 180.756 180.175 179.595 179.015 178.434 178.018 177.706 177.394 177.081 176.769 176.976 177.244 177.512 177.780 178.048 178.315 178.583 178.851 179.119 179.141 178.873 178.605 178.337 178.069 177.612 177.088 176.565 176.041 175.520 175.096 174.672 174.249 173.825 173.801 174.692 175.583 176.475 177.366 177.304 176.569 175.833 175.098 174.363 174.584 174.952 175.319 175.687 175.952 175.627 175.303 174.979 174.654 174.421 174.309 174.196 174.084 173.971 174.201 174.568 174.936 175.304 175.671 175.476 175.277 175.078 174.879 174.680 174.481 174.282 174.083 173.883 173.441 172.805 172.169 171.533 170.897 170.711 170.611 170.511 170.412 170.361 170.673 170.984 171.296 171.607 171.515 170.823 170.131 169.439 168.747 168.597 168.697 168.797 168.897 168.997 +-2681.13 178.025 178.531 179.036 179.541 180.046 180.200 179.650 179.099 178.549 177.999 177.631 177.379 177.126 176.874 176.621 176.862 177.159 177.457 177.755 178.053 178.351 178.648 178.946 179.244 179.269 178.971 178.673 178.375 178.077 177.657 177.193 176.729 176.266 175.803 175.379 174.955 174.532 174.108 174.056 174.857 175.659 176.460 177.261 177.198 176.523 175.847 175.172 174.496 174.699 175.037 175.375 175.713 175.943 175.558 175.174 174.790 174.405 174.112 173.940 173.768 173.595 173.423 173.614 173.951 174.289 174.627 174.965 174.888 174.809 174.730 174.651 174.572 174.492 174.413 174.334 174.255 173.865 173.229 172.593 171.957 171.321 171.186 171.146 171.106 171.066 171.061 171.313 171.564 171.816 172.067 171.927 171.205 170.483 169.761 169.039 168.839 168.879 168.919 168.959 168.999 +-2611.00 178.019 178.405 178.790 179.175 179.560 179.645 179.125 178.604 178.084 177.563 177.244 177.051 176.859 176.666 176.474 176.747 177.075 177.402 177.730 178.058 178.386 178.714 179.041 179.369 179.397 179.069 178.741 178.413 178.085 177.701 177.297 176.894 176.490 176.086 175.662 175.238 174.814 174.391 174.311 175.023 175.734 176.446 177.157 177.092 176.476 175.861 175.245 174.630 174.815 175.123 175.430 175.738 175.934 175.490 175.045 174.601 174.157 173.804 173.571 173.339 173.107 172.874 173.027 173.335 173.642 173.950 174.258 174.300 174.341 174.382 174.423 174.463 174.504 174.545 174.585 174.626 174.289 173.653 173.017 172.381 171.745 171.660 171.680 171.700 171.720 171.761 171.952 172.144 172.336 172.527 172.339 171.587 170.835 170.083 169.331 169.080 169.060 169.040 169.021 169.001 +-2540.87 178.013 178.279 178.544 178.809 179.075 179.090 178.599 178.109 177.618 177.128 176.856 176.724 176.591 176.459 176.326 176.632 176.990 177.347 177.705 178.063 178.421 178.779 179.137 179.494 179.525 179.167 178.809 178.451 178.093 177.746 177.402 177.058 176.714 176.369 175.945 175.521 175.097 174.673 174.567 175.188 175.810 176.431 177.053 176.986 176.430 175.874 175.319 174.763 174.930 175.208 175.486 175.764 175.925 175.421 174.917 174.412 173.908 173.495 173.203 172.911 172.618 172.326 172.440 172.718 172.995 173.273 173.551 173.712 173.873 174.034 174.194 174.355 174.515 174.676 174.836 174.997 174.713 174.077 173.441 172.805 172.169 172.135 172.215 172.295 172.374 172.461 172.592 172.724 172.856 172.987 172.751 171.969 171.187 170.405 169.623 169.322 169.242 169.162 169.082 169.003 +-2470.74 178.007 178.153 178.298 178.444 178.589 178.534 178.074 177.613 177.153 176.692 176.469 176.396 176.324 176.251 176.178 176.517 176.905 177.293 177.680 178.068 178.456 178.844 179.232 179.619 179.652 179.265 178.877 178.489 178.101 177.790 177.506 177.222 176.938 176.652 176.228 175.804 175.380 174.956 174.822 175.354 175.886 176.417 176.949 176.879 176.384 175.888 175.392 174.897 175.046 175.293 175.541 175.789 175.916 175.352 174.788 174.224 173.659 173.187 172.834 172.482 172.130 171.778 171.853 172.101 172.349 172.596 172.844 173.125 173.405 173.686 173.966 174.247 174.527 174.807 175.088 175.368 175.137 174.501 173.865 173.229 172.593 172.609 172.749 172.889 173.029 173.160 173.232 173.304 173.376 173.447 173.163 172.351 171.539 170.727 169.915 169.564 169.424 169.284 169.144 169.005 +-2400.60 178.001 178.027 178.053 178.078 178.104 177.979 177.548 177.118 176.687 176.257 176.081 176.069 176.056 176.043 176.031 176.402 176.820 177.238 177.656 178.073 178.491 178.909 179.327 179.744 179.780 179.362 178.945 178.527 178.109 177.834 177.610 177.387 177.163 176.935 176.511 176.087 175.663 175.239 175.078 175.519 175.961 176.403 176.845 176.773 176.337 175.902 175.466 175.030 175.161 175.379 175.597 175.815 175.907 175.283 174.659 174.035 173.411 172.878 172.466 172.054 171.642 171.229 171.266 171.484 171.702 171.920 172.137 172.537 172.937 173.338 173.738 174.138 174.539 174.939 175.339 175.739 175.561 174.925 174.289 173.653 173.018 173.084 173.284 173.483 173.683 173.860 173.872 173.884 173.896 173.907 173.575 172.733 171.891 171.049 170.207 169.805 169.606 169.406 169.206 169.006 +-2330.47 178.438 178.320 178.203 178.086 177.968 177.773 177.419 177.066 176.713 176.360 176.180 176.109 176.038 175.967 175.896 176.245 176.645 177.045 177.445 177.845 178.245 178.645 179.045 179.445 179.512 179.183 178.855 178.527 178.199 178.027 177.911 177.795 177.679 177.557 177.158 176.758 176.358 175.959 175.736 175.919 176.103 176.287 176.470 176.270 175.798 175.326 174.854 174.382 174.544 174.804 175.064 175.324 175.480 175.036 174.593 174.150 173.707 173.262 172.814 172.366 171.918 171.470 171.458 171.621 171.785 171.949 172.113 172.391 172.671 172.950 173.230 173.523 173.850 174.178 174.506 174.834 174.664 174.101 173.537 172.974 172.410 172.579 172.887 173.195 173.503 173.788 173.908 174.028 174.148 174.267 174.025 173.249 172.473 171.696 170.920 170.465 170.157 169.849 169.542 169.235 +-2260.34 178.996 178.729 178.462 178.195 177.927 177.661 177.398 177.134 176.871 176.608 176.408 176.247 176.086 175.925 175.764 176.077 176.447 176.817 177.187 177.557 177.927 178.297 178.667 179.037 179.143 178.934 178.726 178.517 178.309 178.257 178.261 178.265 178.269 178.265 177.895 177.526 177.156 176.786 176.493 176.377 176.261 176.145 176.029 175.670 175.138 174.605 174.073 173.541 173.747 174.067 174.387 174.707 174.950 174.746 174.543 174.339 174.136 173.815 173.337 172.859 172.381 171.903 171.839 171.943 172.047 172.151 172.254 172.354 172.454 172.553 172.653 172.783 172.990 173.198 173.406 173.614 173.442 172.968 172.495 172.021 171.547 171.831 172.260 172.688 173.115 173.524 173.794 174.063 174.333 174.602 174.485 173.799 173.113 172.426 171.740 171.231 170.803 170.376 169.948 169.521 +-2190.21 179.555 179.138 178.721 178.304 177.887 177.549 177.376 177.202 177.029 176.856 176.636 176.385 176.134 175.883 175.632 175.909 176.249 176.589 176.929 177.269 177.609 177.949 178.289 178.629 178.773 178.684 178.596 178.507 178.419 178.487 178.611 178.734 178.858 178.973 178.633 178.293 177.953 177.614 177.251 176.836 176.420 176.004 175.588 175.069 174.477 173.885 173.293 172.701 172.951 173.331 173.711 174.091 174.420 174.456 174.492 174.529 174.565 174.367 173.859 173.351 172.843 172.336 172.221 172.265 172.308 172.352 172.396 172.317 172.236 172.156 172.076 172.042 172.130 172.218 172.307 172.395 172.219 171.836 171.452 171.068 170.684 171.084 171.632 172.180 172.728 173.260 173.679 174.099 174.518 174.938 174.946 174.349 173.753 173.156 172.560 171.997 171.449 170.902 170.355 169.807 +-2120.08 180.114 179.548 178.981 178.414 177.846 177.437 177.354 177.270 177.187 177.104 176.864 176.523 176.183 175.842 175.501 175.740 176.050 176.361 176.671 176.981 177.291 177.601 177.911 178.221 178.404 178.435 178.466 178.497 178.529 178.717 178.960 179.204 179.448 179.680 179.371 179.061 178.751 178.441 178.009 177.294 176.578 175.863 175.147 174.469 173.817 173.165 172.513 171.861 172.154 172.594 173.034 173.474 173.890 174.166 174.442 174.718 174.994 174.920 174.382 173.844 173.306 172.768 172.602 172.586 172.570 172.554 172.538 172.279 172.019 171.759 171.499 171.302 171.270 171.239 171.207 171.175 170.997 170.703 170.409 170.116 169.822 170.337 171.004 171.672 172.340 172.995 173.565 174.134 174.704 175.273 175.406 174.900 174.393 173.886 173.380 172.762 172.095 171.428 170.761 170.094 +-2049.95 180.673 179.957 179.240 178.523 177.806 177.325 177.332 177.338 177.345 177.352 177.092 176.662 176.231 175.800 175.369 175.572 175.852 176.132 176.413 176.693 176.973 177.253 177.533 177.813 178.034 178.185 178.336 178.487 178.639 178.947 179.310 179.673 180.037 180.388 180.108 179.828 179.549 179.269 178.767 177.752 176.737 175.722 174.706 173.868 173.156 172.444 171.732 171.020 171.358 171.858 172.357 172.857 173.359 173.875 174.391 174.907 175.423 175.473 174.905 174.337 173.769 173.201 172.984 172.908 172.832 172.756 172.680 172.242 171.802 171.362 170.922 170.562 170.410 170.259 170.107 169.955 169.775 169.571 169.367 169.163 168.959 169.589 170.377 171.164 171.952 172.731 173.451 174.170 174.889 175.608 175.867 175.450 175.033 174.617 174.200 173.528 172.741 171.954 171.167 170.380 +-1979.82 181.233 180.366 179.500 178.633 177.766 177.213 177.310 177.406 177.503 177.599 177.321 176.800 176.279 175.759 175.238 175.404 175.654 175.904 176.154 176.405 176.655 176.905 177.155 177.405 177.664 177.935 178.206 178.477 178.749 179.176 179.660 180.143 180.626 181.096 180.846 180.596 180.346 180.096 179.525 178.211 176.896 175.581 174.266 173.268 172.496 171.724 170.952 170.180 170.561 171.121 171.681 172.241 172.829 173.585 174.341 175.096 175.852 176.025 175.428 174.830 174.232 173.634 173.365 173.229 173.093 172.957 172.821 172.204 171.584 170.965 170.345 169.822 169.550 169.279 169.007 168.736 168.552 168.438 168.324 168.210 168.096 168.842 169.749 170.657 171.564 172.467 173.336 174.205 175.074 175.943 176.327 176.000 175.674 175.347 175.020 174.294 173.387 172.480 171.573 170.666 +-1909.69 181.793 180.776 179.760 178.743 177.726 177.101 177.287 177.474 177.660 177.847 177.549 176.939 176.328 175.717 175.107 175.236 175.456 175.676 175.896 176.116 176.337 176.557 176.777 176.997 177.295 177.685 178.076 178.467 178.858 179.406 180.009 180.612 181.216 181.803 181.583 181.364 181.144 180.924 180.284 178.669 177.055 175.440 173.825 172.667 171.835 171.003 170.172 169.340 169.765 170.384 171.004 171.624 172.299 173.295 174.290 175.286 176.281 176.578 175.950 175.322 174.695 174.067 173.747 173.551 173.355 173.159 172.963 172.167 171.367 170.568 169.768 169.082 168.690 168.299 167.907 167.516 167.330 167.306 167.282 167.258 167.234 168.094 169.122 170.149 171.177 172.203 173.222 174.241 175.260 176.279 176.788 176.551 176.314 176.077 175.840 175.059 174.032 173.005 171.979 170.952 +-1839.55 182.160 181.207 180.255 179.302 178.350 177.741 177.847 177.952 178.057 178.162 177.830 177.216 176.601 175.987 175.373 175.456 175.625 175.794 175.962 176.131 176.300 176.468 176.637 176.806 177.090 177.514 177.938 178.362 178.786 179.366 180.002 180.637 181.273 181.893 181.703 181.513 181.323 181.133 180.502 178.850 177.199 175.547 173.895 172.725 171.899 171.073 170.247 169.421 169.785 170.333 170.881 171.430 172.047 173.063 174.079 175.095 176.111 176.425 175.811 175.197 174.583 173.970 173.705 173.580 173.456 173.332 173.208 172.385 171.559 170.733 169.907 169.187 168.741 168.295 167.849 167.403 167.182 167.138 167.094 167.051 167.007 167.800 168.751 169.702 170.652 171.614 172.652 173.691 174.729 175.767 176.316 176.147 175.979 175.811 175.643 174.846 173.764 172.683 171.602 170.521 +-1769.42 182.450 181.647 180.844 180.041 179.239 178.682 178.638 178.593 178.548 178.503 178.131 177.547 176.963 176.378 175.794 175.827 175.936 176.045 176.153 176.262 176.371 176.480 176.588 176.697 176.949 177.372 177.796 178.220 178.644 179.224 179.860 180.496 181.132 181.753 181.592 181.432 181.272 181.112 180.521 178.929 177.337 175.745 174.153 173.025 172.229 171.433 170.637 169.841 170.105 170.534 170.962 171.390 171.897 172.853 173.809 174.765 175.721 176.014 175.430 174.846 174.262 173.678 173.507 173.503 173.498 173.494 173.490 172.698 171.902 171.106 170.310 169.602 169.126 168.651 168.175 167.699 167.431 167.327 167.224 167.120 167.016 167.674 168.475 169.276 170.077 170.904 171.912 172.920 173.929 174.937 175.491 175.383 175.275 175.167 175.058 174.259 173.148 172.037 170.925 169.814 +-1699.29 182.740 182.086 181.433 180.780 180.128 179.624 179.429 179.235 179.040 178.845 178.432 177.878 177.324 176.770 176.215 176.197 176.246 176.295 176.344 176.393 176.442 176.491 176.540 176.588 176.807 177.231 177.655 178.079 178.503 179.082 179.718 180.354 180.990 181.612 181.482 181.351 181.221 181.091 180.539 179.007 177.475 175.943 174.411 173.325 172.559 171.793 171.028 170.262 170.426 170.734 171.042 171.351 171.746 172.642 173.538 174.435 175.331 175.603 175.049 174.495 173.941 173.387 173.310 173.425 173.541 173.656 173.772 173.010 172.244 171.478 170.712 170.018 169.512 169.006 168.501 167.995 167.680 167.517 167.353 167.189 167.026 167.548 168.199 168.850 169.501 170.193 171.172 172.150 173.128 174.107 174.667 174.619 174.571 174.522 174.474 173.672 172.531 171.390 170.249 169.108 +-1629.16 183.029 182.525 182.022 181.519 181.017 180.565 180.221 179.877 179.532 179.187 178.734 178.209 177.685 177.161 176.637 176.568 176.557 176.547 176.536 176.524 176.513 176.502 176.491 176.480 176.665 177.089 177.513 177.937 178.361 178.941 179.577 180.213 180.848 181.471 181.371 181.271 181.170 181.070 180.558 179.085 177.613 176.141 174.669 173.626 172.890 172.154 171.418 170.682 170.746 170.935 171.123 171.312 171.596 172.432 173.268 174.104 174.941 175.192 174.667 174.143 173.619 173.095 173.112 173.348 173.583 173.819 174.054 173.323 172.587 171.851 171.115 170.434 169.898 169.362 168.826 168.291 167.930 167.706 167.482 167.259 167.035 167.422 167.923 168.424 168.926 169.483 170.431 171.380 172.328 173.276 173.843 173.855 173.867 173.878 173.890 173.086 171.914 170.743 169.572 168.401 +-1559.03 183.318 182.965 182.611 182.258 181.905 181.507 181.013 180.518 180.024 179.529 179.035 178.540 178.046 177.552 177.058 176.939 176.869 176.798 176.727 176.656 176.585 176.513 176.442 176.371 176.524 176.948 177.372 177.796 178.220 178.799 179.435 180.071 180.707 181.330 181.260 181.190 181.119 181.049 180.576 179.164 177.751 176.339 174.927 173.926 173.220 172.514 171.808 171.102 171.066 171.135 171.204 171.272 171.446 172.222 172.998 173.774 174.550 174.780 174.286 173.792 173.298 172.804 172.915 173.270 173.626 173.981 174.336 173.635 172.929 172.223 171.517 170.850 170.284 169.718 169.152 168.587 168.179 167.895 167.612 167.328 167.045 167.296 167.647 167.998 168.350 168.772 169.691 170.609 171.528 172.446 173.019 173.091 173.163 173.234 173.306 172.499 171.298 170.097 168.895 167.694 +-1488.90 183.607 183.403 183.200 182.997 182.794 182.449 181.805 181.160 180.516 179.872 179.336 178.872 178.407 177.943 177.479 177.310 177.180 177.049 176.918 176.787 176.656 176.525 176.394 176.262 176.382 176.806 177.230 177.654 178.078 178.658 179.294 179.929 180.565 181.189 181.149 181.109 181.068 181.028 180.594 179.242 177.890 176.537 175.185 174.227 173.551 172.874 172.198 171.522 171.387 171.336 171.284 171.233 171.295 172.012 172.728 173.444 174.160 174.369 173.905 173.441 172.977 172.512 172.718 173.193 173.668 174.143 174.619 173.948 173.272 172.596 171.919 171.266 170.670 170.074 169.478 168.882 168.428 168.084 167.741 167.397 167.054 167.170 167.371 167.573 167.774 168.062 168.950 169.839 170.727 171.616 172.196 172.327 172.459 172.590 172.722 171.912 170.681 169.450 168.219 166.988 +-1418.77 183.896 183.842 183.788 183.735 183.682 183.390 182.597 181.803 181.008 180.214 179.637 179.203 178.768 178.334 177.900 177.681 177.491 177.300 177.109 176.918 176.727 176.536 176.345 176.154 176.241 176.665 177.089 177.513 177.936 178.516 179.152 179.788 180.424 181.049 181.038 181.028 181.018 181.007 180.612 179.320 178.028 176.735 175.443 174.527 173.881 173.235 172.589 171.943 171.707 171.536 171.365 171.194 171.145 171.801 172.458 173.114 173.770 173.958 173.523 173.089 172.655 172.221 172.520 173.116 173.711 174.306 174.901 174.261 173.614 172.968 172.322 171.681 171.056 170.430 169.804 169.178 168.677 168.274 167.870 167.467 167.063 167.043 167.095 167.146 167.198 167.351 168.210 169.068 169.927 170.785 171.372 171.563 171.755 171.946 172.138 171.325 170.064 168.803 167.542 166.281 +-1348.64 183.459 183.497 183.535 183.573 183.611 183.383 182.592 181.802 181.012 180.222 179.688 179.322 178.956 178.590 178.225 178.030 177.857 177.684 177.511 177.332 177.120 176.908 176.697 176.485 176.508 176.814 177.121 177.427 177.734 178.224 178.782 179.339 179.896 180.445 180.503 180.562 180.621 180.680 180.364 179.171 177.978 176.784 175.591 174.688 173.993 173.298 172.603 171.908 171.647 171.455 171.263 171.071 170.995 171.591 172.188 172.784 173.380 173.555 173.170 172.786 172.402 172.017 172.332 172.928 173.525 174.121 174.718 174.166 173.609 173.052 172.495 171.922 171.306 170.689 170.073 169.457 168.959 168.555 168.151 167.746 167.342 167.279 167.278 167.278 167.278 167.370 168.100 168.830 169.560 170.291 170.801 170.994 171.186 171.379 171.572 170.806 169.613 168.419 167.225 166.031 +-1278.51 182.613 182.711 182.809 182.907 183.005 182.847 182.146 181.446 180.745 180.045 179.601 179.325 179.049 178.773 178.497 178.366 178.253 178.140 178.027 177.898 177.686 177.474 177.262 177.051 176.992 177.119 177.245 177.372 177.499 177.853 178.291 178.728 179.165 179.598 179.746 179.895 180.044 180.193 179.976 178.902 177.829 176.756 175.683 174.778 173.992 173.207 172.422 171.637 171.391 171.228 171.066 170.904 170.844 171.381 171.917 172.454 172.990 173.156 172.832 172.507 172.183 171.859 172.148 172.684 173.221 173.757 174.294 173.861 173.424 172.987 172.550 172.071 171.485 170.899 170.313 169.726 169.259 168.885 168.510 168.136 167.761 167.703 167.703 167.703 167.702 167.772 168.322 168.872 169.422 169.973 170.365 170.527 170.690 170.853 171.015 170.323 169.249 168.176 167.102 166.028 +-1208.37 181.767 181.925 182.082 182.240 182.398 182.310 181.700 181.089 180.479 179.868 179.514 179.328 179.142 178.956 178.770 178.702 178.649 178.596 178.543 178.463 178.252 178.040 177.828 177.616 177.476 177.423 177.370 177.317 177.264 177.482 177.800 178.117 178.435 178.751 178.989 179.228 179.467 179.706 179.588 178.634 177.681 176.728 175.774 174.867 173.992 173.117 172.242 171.367 171.134 171.001 170.869 170.737 170.694 171.171 171.647 172.124 172.600 172.758 172.493 172.229 171.964 171.700 171.964 172.440 172.917 173.393 173.870 173.556 173.239 172.922 172.605 172.221 171.665 171.109 170.552 169.996 169.559 169.214 168.870 168.525 168.181 168.127 168.127 168.127 168.127 168.173 168.544 168.914 169.284 169.655 169.928 170.061 170.194 170.326 170.459 169.840 168.886 167.932 166.978 166.024 +-1138.24 180.921 181.138 181.356 181.574 181.792 181.774 181.253 180.732 180.212 179.692 179.427 179.330 179.234 179.138 179.043 179.038 179.045 179.052 179.059 179.029 178.817 178.605 178.394 178.182 177.961 177.728 177.495 177.262 177.029 177.112 177.309 177.507 177.704 177.904 178.232 178.561 178.890 179.218 179.200 178.366 177.533 176.699 175.866 174.956 173.991 173.026 172.061 171.096 170.877 170.774 170.672 170.570 170.544 170.960 171.377 171.794 172.210 172.360 172.155 171.950 171.746 171.541 171.779 172.196 172.613 173.029 173.446 173.251 173.054 172.857 172.660 172.371 171.845 171.318 170.792 170.265 169.858 169.544 169.229 168.915 168.600 168.551 168.551 168.551 168.551 168.575 168.765 168.956 169.146 169.337 169.492 169.595 169.697 169.800 169.903 169.357 168.523 167.689 166.855 166.021 +-1068.11 180.074 180.352 180.630 180.907 181.185 181.237 180.806 180.376 179.945 179.515 179.339 179.333 179.327 179.321 179.315 179.373 179.440 179.507 179.574 179.595 179.383 179.171 178.959 178.748 178.446 178.033 177.620 177.207 176.794 176.741 176.819 176.896 176.974 177.057 177.475 177.894 178.312 178.731 178.811 178.098 177.384 176.671 175.957 175.045 173.990 172.935 171.881 170.826 170.620 170.548 170.475 170.403 170.394 170.750 171.107 171.464 171.820 171.961 171.817 171.672 171.527 171.383 171.595 171.952 172.309 172.665 173.022 172.947 172.869 172.792 172.715 172.521 172.024 171.528 171.031 170.535 170.158 169.873 169.589 169.304 169.020 168.975 168.975 168.975 168.975 168.976 168.987 168.998 169.008 169.019 169.056 169.128 169.201 169.274 169.346 168.874 168.160 167.446 166.732 166.018 +-997.98 179.228 179.565 179.903 180.241 180.579 180.700 180.359 180.019 179.678 179.338 179.252 179.336 179.420 179.503 179.587 179.709 179.836 179.963 180.090 180.160 179.949 179.737 179.525 179.313 178.930 178.338 177.745 177.152 176.560 176.370 176.328 176.286 176.244 176.210 176.718 177.227 177.735 178.244 178.423 177.829 177.236 176.642 176.049 175.134 173.990 172.845 171.700 170.555 170.363 170.321 170.278 170.236 170.243 170.540 170.837 171.133 171.430 171.563 171.478 171.393 171.309 171.224 171.411 171.708 172.005 172.301 172.598 172.642 172.684 172.727 172.769 172.670 172.204 171.737 171.271 170.805 170.457 170.203 169.948 169.694 169.439 169.400 169.399 169.399 169.399 169.378 169.208 169.039 168.870 168.701 168.619 168.662 168.704 168.747 168.790 168.391 167.797 167.203 166.609 166.014 +-927.85 178.381 178.779 179.176 179.574 179.972 180.163 179.913 179.662 179.411 179.160 179.165 179.338 179.512 179.686 179.860 180.045 180.232 180.419 180.605 180.726 180.514 180.303 180.091 179.879 179.415 178.643 177.870 177.098 176.325 176.000 175.838 175.675 175.513 175.363 175.961 176.559 177.158 177.756 178.035 177.561 177.087 176.613 176.140 175.224 173.989 172.754 171.520 170.285 170.106 170.094 170.081 170.069 170.093 170.330 170.567 170.803 171.040 171.164 171.140 171.115 171.090 171.065 171.227 171.464 171.701 171.937 172.174 172.337 172.499 172.662 172.824 172.820 172.383 171.947 171.511 171.074 170.757 170.532 170.308 170.083 169.859 169.824 169.824 169.824 169.823 169.779 169.430 169.081 168.732 168.383 168.183 168.195 168.208 168.221 168.234 167.909 167.435 166.960 166.486 166.011 +-857.72 177.695 178.135 178.576 179.017 179.457 179.696 179.501 179.306 179.111 178.916 178.945 179.122 179.299 179.477 179.654 179.907 180.171 180.434 180.698 180.897 180.772 180.647 180.522 180.397 179.955 179.125 178.294 177.464 176.634 176.205 175.924 175.642 175.360 175.092 175.693 176.294 176.895 177.496 177.817 177.481 177.144 176.808 176.472 175.613 174.376 173.139 171.903 170.666 170.437 170.367 170.296 170.226 170.195 170.389 170.583 170.778 170.972 171.083 171.083 171.083 171.083 171.083 171.234 171.446 171.658 171.870 172.082 172.259 172.436 172.613 172.790 172.789 172.330 171.871 171.412 170.953 170.652 170.475 170.299 170.122 169.945 169.932 169.950 169.967 169.985 169.948 169.542 169.135 168.728 168.322 168.054 167.984 167.914 167.845 167.775 167.472 167.066 166.659 166.253 165.846 +-787.59 177.130 177.600 178.071 178.542 179.012 179.282 179.117 178.951 178.786 178.621 178.626 178.743 178.861 178.978 179.095 179.421 179.774 180.128 180.482 180.781 180.805 180.830 180.855 180.880 180.534 179.734 178.934 178.133 177.333 176.825 176.423 176.021 175.620 175.232 175.773 176.314 176.855 177.396 177.720 177.534 177.348 177.161 176.975 176.213 175.037 173.860 172.683 171.506 171.182 170.992 170.801 170.611 170.473 170.637 170.802 170.966 171.131 171.224 171.224 171.224 171.224 171.224 171.376 171.588 171.800 172.012 172.224 172.341 172.458 172.574 172.691 172.631 172.112 171.593 171.074 170.555 170.262 170.145 170.028 169.911 169.794 169.816 169.864 169.911 169.959 169.952 169.575 169.199 168.822 168.445 168.146 167.956 167.766 167.577 167.388 167.068 166.692 166.315 165.939 165.562 +-717.46 176.565 177.065 177.566 178.067 178.567 178.867 178.732 178.597 178.462 178.327 178.307 178.364 178.422 178.479 178.537 178.934 179.378 179.821 180.265 180.664 180.839 181.013 181.188 181.363 181.114 180.343 179.573 178.803 178.032 177.444 176.923 176.401 175.879 175.372 175.853 176.335 176.816 177.297 177.624 177.587 177.551 177.514 177.478 176.814 175.697 174.580 173.463 172.347 171.927 171.617 171.306 170.996 170.751 170.886 171.020 171.155 171.289 171.366 171.366 171.366 171.366 171.366 171.517 171.729 171.941 172.153 172.365 172.422 172.479 172.536 172.593 172.473 171.894 171.315 170.736 170.157 169.871 169.814 169.757 169.700 169.643 169.700 169.778 169.855 169.932 169.956 169.609 169.262 168.916 168.569 168.238 167.928 167.619 167.309 167.000 166.665 166.318 165.972 165.625 165.279 +-647.32 176.000 176.530 177.061 177.592 178.122 178.452 178.347 178.242 178.137 178.032 177.988 177.986 177.983 177.981 177.978 178.448 178.981 179.515 180.048 180.548 180.872 181.196 181.521 181.846 181.693 180.953 180.212 179.472 178.731 178.063 177.422 176.781 176.139 175.513 175.934 176.355 176.776 177.197 177.527 177.640 177.754 177.867 177.980 177.415 176.358 175.301 174.244 173.187 172.672 172.242 171.811 171.381 171.030 171.134 171.239 171.343 171.448 171.507 171.507 171.507 171.507 171.507 171.658 171.870 172.082 172.294 172.506 172.504 172.501 172.498 172.495 172.314 171.675 171.036 170.397 169.759 169.481 169.484 169.487 169.490 169.493 169.584 169.691 169.799 169.906 169.959 169.643 169.326 169.009 168.693 168.330 167.900 167.471 167.042 166.612 166.261 165.945 165.628 165.312 164.995 +-577.19 175.435 175.995 176.556 177.117 177.677 178.038 177.962 177.887 177.812 177.737 177.670 177.607 177.545 177.482 177.420 177.961 178.585 179.208 179.832 180.431 180.905 181.379 181.854 182.328 182.272 181.562 180.851 180.141 179.431 178.683 177.922 177.160 176.399 175.653 176.014 176.376 176.737 177.098 177.430 177.693 177.956 178.220 178.483 178.015 177.018 176.021 175.024 174.027 173.416 172.866 172.317 171.767 171.308 171.383 171.457 171.532 171.606 171.649 171.649 171.649 171.649 171.649 171.800 172.012 172.224 172.436 172.648 172.586 172.523 172.460 172.397 172.156 171.457 170.758 170.059 169.360 169.090 169.153 169.216 169.279 169.342 169.468 169.605 169.743 169.880 169.963 169.676 169.390 169.103 168.816 168.421 167.872 167.323 166.774 166.225 165.858 165.571 165.285 164.998 164.712 +-507.06 174.870 175.460 176.051 176.642 177.232 177.623 177.578 177.533 177.487 177.442 177.351 177.229 177.106 176.984 176.861 177.475 178.188 178.901 179.615 180.314 180.938 181.562 182.186 182.811 182.852 182.171 181.491 180.810 180.130 179.303 178.421 177.540 176.659 175.794 176.095 176.396 176.697 176.999 177.333 177.746 178.159 178.572 178.986 178.616 177.679 176.742 175.805 174.868 174.161 173.491 172.822 172.152 171.587 171.631 171.676 171.720 171.765 171.790 171.790 171.790 171.790 171.790 171.941 172.153 172.365 172.577 172.789 172.667 172.545 172.422 172.299 171.998 171.239 170.480 169.721 168.962 168.700 168.823 168.946 169.069 169.191 169.352 169.519 169.687 169.854 169.967 169.710 169.454 169.197 168.940 168.513 167.844 167.175 166.506 165.837 165.455 165.198 164.941 164.685 164.428 +-436.93 174.305 174.925 175.546 176.167 176.787 177.208 177.193 177.178 177.162 177.147 177.032 176.850 176.668 176.485 176.303 176.988 177.791 178.595 179.398 180.197 180.971 181.745 182.519 183.293 183.431 182.780 182.130 181.479 180.829 179.922 178.921 177.920 176.919 175.934 176.175 176.417 176.658 176.899 177.236 177.799 178.362 178.925 179.488 179.216 178.339 177.462 176.585 175.708 174.906 174.117 173.327 172.537 171.865 171.880 171.894 171.909 171.923 171.931 171.931 171.931 171.931 171.931 172.083 172.295 172.507 172.719 172.931 172.749 172.566 172.383 172.200 171.840 171.021 170.202 169.383 168.564 168.309 168.492 168.675 168.858 169.041 169.236 169.433 169.631 169.828 169.971 169.744 169.517 169.291 169.064 168.605 167.816 167.027 166.238 165.449 165.051 164.824 164.598 164.371 164.145 +-366.80 173.947 174.524 175.100 175.677 176.253 176.662 176.706 176.751 176.796 176.840 176.723 176.496 176.268 176.041 175.814 176.519 177.352 178.185 179.017 179.852 180.700 181.548 182.396 183.244 183.463 182.903 182.343 181.783 181.223 180.332 179.318 178.304 177.290 176.291 176.458 176.624 176.790 176.956 177.261 177.897 178.533 179.169 179.805 179.599 178.782 177.964 177.147 176.330 175.486 174.638 173.790 172.942 172.212 172.165 172.119 172.073 172.026 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.767 170.934 170.102 169.269 168.436 168.157 168.308 168.458 168.609 168.759 168.962 169.174 169.386 169.599 169.758 169.561 169.365 169.168 168.971 168.512 167.679 166.847 166.014 165.181 164.781 164.569 164.357 164.145 163.933 +-296.67 173.802 174.259 174.715 175.172 175.628 175.983 176.117 176.252 176.386 176.521 176.422 176.165 175.908 175.651 175.393 176.068 176.871 177.674 178.476 179.286 180.134 180.982 181.830 182.678 182.964 182.554 182.144 181.734 181.324 180.539 179.615 178.691 177.767 176.856 176.932 177.008 177.084 177.160 177.402 178.038 178.674 179.311 179.947 179.775 179.018 178.261 177.503 176.746 175.911 175.063 174.215 173.367 172.623 172.486 172.350 172.214 172.078 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.775 170.973 170.170 169.367 168.565 168.231 168.262 168.292 168.323 168.354 168.538 168.750 168.962 169.174 169.337 169.171 169.004 168.837 168.671 168.241 167.439 166.636 165.833 165.030 164.639 164.427 164.215 164.003 163.791 +-226.54 173.657 173.994 174.330 174.667 175.003 175.304 175.528 175.753 175.977 176.202 176.122 175.835 175.547 175.260 174.973 175.617 176.390 177.163 177.936 178.721 179.568 180.416 181.264 182.112 182.466 182.205 181.945 181.685 181.425 180.746 179.912 179.078 178.244 177.420 177.406 177.393 177.379 177.365 177.544 178.180 178.816 179.452 180.088 179.951 179.254 178.557 177.859 177.162 176.335 175.487 174.639 173.791 173.034 172.808 172.581 172.355 172.129 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.784 171.011 170.238 169.466 168.693 168.305 168.216 168.126 168.037 167.948 168.114 168.326 168.538 168.750 168.917 168.780 168.644 168.507 168.370 167.971 167.198 166.425 165.652 164.880 164.498 164.286 164.074 163.862 163.650 +-156.41 173.512 173.729 173.945 174.162 174.378 174.625 174.939 175.254 175.568 175.883 175.821 175.504 175.187 174.870 174.552 175.167 175.909 176.652 177.395 178.155 179.002 179.850 180.698 181.546 181.967 181.856 181.746 181.636 181.526 180.954 180.209 179.465 178.721 177.985 177.881 177.777 177.674 177.570 177.685 178.321 178.957 179.593 180.229 180.128 179.490 178.853 178.216 177.578 176.759 175.911 175.063 174.215 173.445 173.129 172.813 172.496 172.180 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.792 171.049 170.307 169.564 168.821 168.379 168.170 167.960 167.751 167.542 167.690 167.902 168.114 168.326 168.497 168.390 168.283 168.177 168.070 167.700 166.957 166.214 165.472 164.729 164.356 164.144 163.932 163.720 163.508 +-86.28 173.367 173.464 173.561 173.657 173.754 173.946 174.350 174.754 175.159 175.563 175.521 175.174 174.827 174.479 174.132 174.716 175.428 176.141 176.854 177.589 178.436 179.284 180.132 180.980 181.468 181.508 181.547 181.587 181.627 181.161 180.506 179.852 179.198 178.549 178.356 178.162 177.968 177.775 177.826 178.462 179.098 179.734 180.371 180.304 179.726 179.149 178.572 177.994 177.183 176.335 175.487 174.639 173.856 173.450 173.044 172.638 172.232 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.800 171.088 170.375 169.662 168.949 168.453 168.123 167.794 167.465 167.136 167.266 167.478 167.690 167.902 168.076 168.000 167.923 167.846 167.770 167.429 166.717 166.004 165.291 164.578 164.215 164.003 163.791 163.579 163.367 +-16.14 173.222 173.199 173.176 173.153 173.129 173.267 173.761 174.255 174.749 175.244 175.220 174.843 174.466 174.089 173.712 174.265 174.948 175.631 176.313 177.023 177.871 178.718 179.566 180.414 180.969 181.158 181.348 181.538 181.727 181.368 180.803 180.239 179.675 179.114 178.830 178.547 178.263 177.979 177.967 178.603 179.240 179.876 180.512 180.480 179.963 179.445 178.928 178.410 177.608 176.760 175.912 175.064 174.267 173.771 173.275 172.779 172.283 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.809 171.126 170.443 169.760 169.077 168.526 168.077 167.628 167.179 166.730 166.841 167.054 167.266 167.478 167.656 167.609 167.563 167.516 167.469 167.159 166.476 165.793 165.110 164.427 164.073 163.861 163.649 163.437 163.225 +53.99 173.078 172.935 172.792 172.649 172.505 172.587 173.171 173.755 174.340 174.924 174.920 174.513 174.106 173.699 173.291 173.814 174.467 175.120 175.773 176.457 177.305 178.152 179.000 179.848 180.470 180.809 181.149 181.488 181.828 181.575 181.100 180.626 180.152 179.678 179.305 178.931 178.558 178.184 178.109 178.745 179.381 180.017 180.653 180.656 180.199 179.741 179.284 178.826 178.032 177.184 176.336 175.488 174.678 174.092 173.506 172.920 172.334 172.000 172.000 172.000 172.000 172.000 172.151 172.363 172.575 172.787 172.999 172.789 172.577 172.365 172.153 171.817 171.164 170.511 169.858 169.206 168.600 168.031 167.462 166.893 166.324 166.417 166.629 166.842 167.054 167.236 167.219 167.202 167.186 167.169 166.888 166.235 165.582 164.930 164.277 163.932 163.720 163.508 163.296 163.084 +124.12 172.995 172.783 172.570 172.358 172.146 172.189 172.799 173.410 174.020 174.630 174.635 174.224 173.812 173.401 172.990 173.485 174.108 174.731 175.354 176.009 176.831 177.653 178.475 179.297 179.948 180.385 180.821 181.258 181.695 181.554 181.195 180.837 180.478 180.119 179.695 179.271 178.847 178.423 178.300 178.897 179.493 180.090 180.686 180.685 180.247 179.810 179.373 178.935 178.155 177.320 176.485 175.650 174.845 174.208 173.572 172.936 172.300 171.926 171.899 171.873 171.846 171.820 171.954 172.153 172.351 172.550 172.749 172.565 172.379 172.194 172.008 171.711 171.128 170.545 169.962 169.379 168.751 168.088 167.426 166.763 166.101 166.180 166.392 166.604 166.816 166.997 166.970 166.944 166.918 166.892 166.618 165.995 165.372 164.749 164.126 163.809 163.623 163.437 163.251 163.065 +194.25 172.995 172.783 172.571 172.359 172.147 172.170 172.721 173.271 173.821 174.372 174.370 173.989 173.607 173.226 172.845 173.317 173.910 174.503 175.096 175.716 176.478 177.240 178.002 178.764 179.395 179.862 180.329 180.796 181.263 181.238 181.030 180.821 180.613 180.402 179.978 179.554 179.130 178.706 178.557 179.063 179.570 180.076 180.583 180.526 180.059 179.591 179.124 178.657 177.898 177.093 176.288 175.483 174.703 174.067 173.431 172.795 172.159 171.759 171.672 171.586 171.499 171.413 171.508 171.677 171.846 172.015 172.184 172.059 171.933 171.808 171.682 171.462 170.999 170.536 170.073 169.609 169.000 168.277 167.555 166.832 166.110 166.180 166.392 166.604 166.816 166.989 166.902 166.816 166.730 166.644 166.347 165.754 165.161 164.568 163.975 163.709 163.583 163.457 163.331 163.205 +264.38 172.995 172.783 172.571 172.359 172.147 172.151 172.642 173.132 173.623 174.113 174.105 173.754 173.402 173.051 172.700 173.149 173.713 174.276 174.839 175.424 176.126 176.828 177.530 178.232 178.843 179.340 179.836 180.333 180.830 180.923 180.865 180.806 180.748 180.685 180.261 179.837 179.413 178.989 178.813 179.229 179.646 180.063 180.479 180.367 179.870 179.373 178.875 178.378 177.641 176.866 176.091 175.317 174.562 173.926 173.290 172.654 172.017 171.592 171.445 171.299 171.152 171.006 171.063 171.202 171.340 171.479 171.618 171.553 171.488 171.422 171.357 171.213 170.870 170.527 170.183 169.840 169.249 168.466 167.684 166.901 166.119 166.180 166.392 166.604 166.816 166.981 166.834 166.688 166.542 166.396 166.077 165.514 164.951 164.388 163.825 163.609 163.543 163.477 163.411 163.345 +334.51 172.995 172.783 172.571 172.359 172.147 172.133 172.563 172.994 173.424 173.855 173.840 173.519 173.198 172.876 172.555 172.982 173.515 174.048 174.581 175.131 175.773 176.415 177.057 177.699 178.290 178.817 179.344 179.871 180.398 180.608 180.699 180.791 180.882 180.968 180.544 180.120 179.696 179.272 179.069 179.396 179.722 180.049 180.376 180.209 179.681 179.154 178.627 178.099 177.384 176.639 175.895 175.150 174.421 173.784 173.148 172.512 171.876 171.424 171.218 171.012 170.805 170.599 170.617 170.726 170.835 170.944 171.053 171.047 171.042 171.036 171.031 170.964 170.741 170.517 170.294 170.070 169.497 168.655 167.812 166.970 166.128 166.180 166.392 166.604 166.816 166.973 166.767 166.560 166.354 166.148 165.806 165.273 164.740 164.207 163.674 163.510 163.504 163.498 163.492 163.486 +404.64 172.995 172.783 172.571 172.359 172.147 172.114 172.485 172.855 173.226 173.596 173.575 173.284 172.993 172.701 172.410 172.814 173.317 173.820 174.323 174.839 175.421 176.003 176.585 177.167 177.738 178.295 178.851 179.408 179.965 180.293 180.534 180.775 181.016 181.251 180.827 180.403 179.979 179.555 179.325 179.562 179.799 180.035 180.272 180.050 179.493 178.935 178.378 177.821 177.128 176.413 175.698 174.983 174.279 173.643 173.007 172.371 171.735 171.257 170.991 170.725 170.458 170.192 170.172 170.250 170.329 170.408 170.487 170.542 170.596 170.650 170.705 170.715 170.611 170.508 170.405 170.301 169.746 168.844 167.941 167.039 166.136 166.180 166.392 166.604 166.816 166.965 166.699 166.432 166.166 165.900 165.536 165.033 164.530 164.027 163.524 163.411 163.465 163.518 163.572 163.626 +474.77 172.995 172.783 172.571 172.359 172.147 172.095 172.406 172.717 173.027 173.338 173.310 173.049 172.788 172.526 172.265 172.646 173.119 173.592 174.065 174.546 175.068 175.590 176.112 176.635 177.185 177.772 178.359 178.946 179.533 179.977 180.368 180.759 181.151 181.534 181.110 180.686 180.262 179.838 179.582 179.728 179.875 180.022 180.169 179.891 179.304 178.717 178.129 177.542 176.871 176.186 175.501 174.816 174.138 173.502 172.866 172.229 171.593 171.090 170.764 170.437 170.111 169.785 169.726 169.775 169.824 169.873 169.922 170.036 170.150 170.264 170.379 170.466 170.482 170.499 170.515 170.532 169.995 169.032 168.070 167.108 166.145 166.180 166.392 166.604 166.816 166.957 166.631 166.304 165.978 165.652 165.265 164.792 164.319 163.846 163.373 163.311 163.425 163.539 163.653 163.767 +544.91 172.995 172.783 172.571 172.359 172.147 172.077 172.328 172.578 172.829 173.079 173.045 172.814 172.583 172.351 172.120 172.478 172.921 173.364 173.807 174.254 174.716 175.178 175.640 176.102 176.633 177.249 177.866 178.483 179.100 179.662 180.203 180.744 181.285 181.817 181.393 180.969 180.545 180.121 179.838 179.895 179.952 180.008 180.065 179.733 179.115 178.498 177.881 177.264 176.614 175.959 175.304 174.649 173.996 173.360 172.724 172.088 171.452 170.923 170.537 170.150 169.764 169.378 169.280 169.299 169.318 169.337 169.356 169.530 169.704 169.879 170.053 170.217 170.353 170.490 170.626 170.762 170.244 169.221 168.199 167.176 166.154 166.180 166.392 166.604 166.816 166.949 166.562 166.176 165.790 165.404 164.995 164.552 164.109 163.666 163.222 163.212 163.386 163.560 163.733 163.907 +615.04 172.897 172.695 172.493 172.292 172.090 172.012 172.213 172.414 172.615 172.817 172.780 172.579 172.378 172.176 171.975 172.320 172.744 173.168 173.592 174.017 174.452 174.887 175.322 175.757 176.276 176.901 177.526 178.152 178.777 179.378 179.970 180.562 181.154 181.737 181.335 180.932 180.530 180.128 179.841 179.829 179.818 179.807 179.796 179.430 178.805 178.180 177.555 176.930 176.285 175.638 174.991 174.344 173.700 173.074 172.449 171.824 171.199 170.665 170.252 169.839 169.426 169.014 168.887 168.876 168.865 168.854 168.843 169.043 169.244 169.445 169.646 169.847 170.048 170.249 170.451 170.652 170.171 169.166 168.161 167.156 166.151 166.171 166.372 166.573 166.774 166.894 166.492 166.090 165.688 165.286 164.875 164.450 164.026 163.602 163.178 163.170 163.338 163.507 163.675 163.844 +685.17 172.615 172.443 172.271 172.100 171.928 171.861 172.032 172.204 172.375 172.546 172.515 172.344 172.172 172.001 171.830 172.178 172.602 173.026 173.450 173.881 174.345 174.810 175.275 175.740 176.263 176.858 177.453 178.048 178.643 179.149 179.622 180.094 180.566 181.031 180.688 180.346 180.004 179.662 179.408 179.366 179.325 179.284 179.243 178.882 178.287 177.692 177.097 176.501 175.836 175.158 174.481 173.804 173.138 172.543 171.948 171.353 170.758 170.254 169.871 169.488 169.105 168.722 168.583 168.542 168.501 168.460 168.419 168.589 168.760 168.931 169.102 169.273 169.444 169.615 169.787 169.958 169.549 168.694 167.839 166.984 166.129 166.145 166.316 166.487 166.659 166.761 166.419 166.077 165.735 165.392 165.016 164.592 164.168 163.743 163.319 163.227 163.275 163.324 163.373 163.422 +755.30 172.333 172.191 172.049 171.907 171.766 171.710 171.852 171.993 172.134 172.276 172.250 172.109 171.967 171.826 171.684 172.036 172.460 172.884 173.309 173.744 174.238 174.733 175.228 175.723 176.249 176.814 177.380 177.945 178.510 178.921 179.273 179.626 179.978 180.324 180.042 179.760 179.477 179.195 178.975 178.904 178.832 178.761 178.690 178.334 177.769 177.203 176.638 176.073 175.386 174.678 173.971 173.264 172.577 172.012 171.447 170.882 170.317 169.843 169.490 169.137 168.784 168.431 168.279 168.208 168.137 168.066 167.995 168.135 168.276 168.417 168.558 168.699 168.840 168.981 169.123 169.264 168.926 168.221 167.516 166.811 166.106 166.120 166.261 166.402 166.543 166.628 166.345 166.063 165.781 165.499 165.157 164.733 164.309 163.885 163.460 163.284 163.213 163.141 163.070 162.999 +825.43 172.050 171.939 171.827 171.715 171.604 171.560 171.671 171.782 171.894 172.005 171.985 171.874 171.762 171.651 171.539 171.895 172.319 172.743 173.167 173.607 174.132 174.656 175.181 175.706 176.236 176.771 177.306 177.841 178.377 178.693 178.925 179.157 179.390 179.618 179.395 179.173 178.951 178.728 178.542 178.441 178.339 178.238 178.137 177.786 177.250 176.715 176.180 175.645 174.936 174.198 173.461 172.724 172.016 171.481 170.946 170.411 169.876 169.431 169.108 168.785 168.462 168.139 167.975 167.874 167.773 167.672 167.571 167.681 167.792 167.903 168.014 168.125 168.236 168.348 168.459 168.570 168.304 167.749 167.194 166.639 166.083 166.094 166.206 166.317 166.428 166.494 166.272 166.050 165.827 165.605 165.298 164.874 164.450 164.026 163.602 163.341 163.150 162.959 162.768 162.577 +895.56 171.768 171.686 171.605 171.523 171.441 171.409 171.491 171.572 171.653 171.735 171.720 171.639 171.557 171.476 171.394 171.753 172.177 172.601 173.025 173.470 174.025 174.579 175.134 175.689 176.222 176.728 177.233 177.738 178.243 178.464 178.577 178.689 178.801 178.911 178.749 178.587 178.424 178.262 178.109 177.978 177.847 177.715 177.584 177.237 176.732 176.227 175.722 175.217 174.486 173.718 172.951 172.184 171.455 170.950 170.444 169.939 169.434 169.020 168.727 168.434 168.141 167.848 167.670 167.539 167.408 167.277 167.146 167.227 167.308 167.389 167.470 167.551 167.632 167.714 167.795 167.876 167.682 167.277 166.871 166.466 166.061 166.069 166.150 166.231 166.312 166.361 166.199 166.036 165.874 165.712 165.440 165.015 164.591 164.167 163.743 163.398 163.087 162.776 162.465 162.154 +965.69 171.486 171.434 171.382 171.331 171.279 171.259 171.310 171.361 171.413 171.464 171.455 171.403 171.352 171.300 171.249 171.612 172.036 172.460 172.884 173.333 173.918 174.502 175.087 175.672 176.209 176.684 177.160 177.635 178.110 178.236 178.229 178.221 178.213 178.205 178.102 178.000 177.898 177.795 177.676 177.515 177.354 177.193 177.031 176.689 176.214 175.739 175.263 174.788 174.036 173.239 172.441 171.644 170.894 170.418 169.943 169.468 168.993 168.609 168.346 168.083 167.820 167.557 167.366 167.205 167.044 166.883 166.722 166.773 166.824 166.875 166.926 166.977 167.028 167.080 167.131 167.182 167.060 166.804 166.549 166.294 166.038 166.043 166.095 166.146 166.197 166.227 166.125 166.023 165.920 165.818 165.581 165.157 164.733 164.308 163.884 163.455 163.024 162.593 162.162 161.731 +1035.82 171.204 171.182 171.160 171.138 171.117 171.108 171.130 171.151 171.172 171.194 171.190 171.168 171.147 171.125 171.104 171.470 171.894 172.318 172.742 173.196 173.811 174.425 175.040 175.655 176.196 176.641 177.086 177.532 177.977 178.008 177.880 177.753 177.625 177.498 177.456 177.413 177.371 177.329 177.243 177.052 176.861 176.670 176.479 176.141 175.696 175.250 174.805 174.360 173.586 172.759 171.931 171.104 170.332 169.887 169.442 168.997 168.552 168.198 167.964 167.731 167.498 167.265 167.062 166.871 166.680 166.489 166.298 166.319 166.340 166.361 166.382 166.403 166.424 166.445 166.467 166.488 166.437 166.332 166.227 166.121 166.016 166.018 166.039 166.060 166.081 166.094 166.052 166.009 165.967 165.925 165.722 165.298 164.874 164.450 164.025 163.512 162.961 162.410 161.859 161.308 +1105.95 170.882 170.899 170.915 170.932 170.949 170.965 170.982 170.999 171.016 171.033 171.045 171.054 171.062 171.071 171.080 171.450 171.875 172.299 172.723 173.177 173.796 174.415 175.034 175.653 176.175 176.572 176.970 177.368 177.766 177.722 177.510 177.298 177.086 176.875 176.875 176.875 176.875 176.875 176.813 176.600 176.388 176.176 175.964 175.635 175.219 174.804 174.389 173.974 173.201 172.371 171.540 170.710 169.939 169.514 169.090 168.666 168.242 167.913 167.710 167.507 167.303 167.100 166.897 166.694 166.491 166.288 166.085 166.075 166.066 166.057 166.049 166.040 166.031 166.022 166.013 166.004 166.005 166.014 166.023 166.032 166.041 166.042 166.042 166.042 166.042 166.040 166.032 166.023 166.014 166.005 165.822 165.398 164.974 164.550 164.126 163.546 162.901 162.256 161.611 160.967 +1176.09 170.459 170.536 170.612 170.689 170.765 170.842 170.919 170.996 171.073 171.150 171.204 171.243 171.281 171.320 171.359 171.733 172.157 172.581 173.006 173.451 174.010 174.569 175.127 175.686 176.135 176.443 176.751 177.059 177.366 177.298 177.086 176.874 176.662 176.451 176.451 176.451 176.451 176.450 176.388 176.176 175.964 175.752 175.540 175.228 174.843 174.457 174.072 173.687 172.970 172.200 171.429 170.659 169.939 169.514 169.090 168.666 168.242 167.926 167.753 167.579 167.406 167.233 167.060 166.887 166.714 166.541 166.367 166.328 166.289 166.250 166.211 166.172 166.134 166.095 166.056 166.017 166.022 166.061 166.100 166.139 166.177 166.183 166.183 166.183 166.183 166.178 166.139 166.100 166.061 166.022 165.822 165.398 164.974 164.550 164.125 163.525 162.850 162.175 161.500 160.825 +1246.22 170.036 170.172 170.309 170.445 170.582 170.719 170.855 170.992 171.129 171.266 171.363 171.432 171.500 171.569 171.638 172.015 172.440 172.864 173.288 173.724 174.223 174.722 175.221 175.720 176.096 176.313 176.531 176.749 176.967 176.874 176.662 176.450 176.237 176.027 176.027 176.026 176.026 176.026 175.964 175.752 175.540 175.328 175.116 174.821 174.466 174.110 173.755 173.400 172.739 172.028 171.318 170.608 169.939 169.514 169.090 168.666 168.242 167.939 167.795 167.652 167.509 167.366 167.223 167.080 166.937 166.793 166.650 166.581 166.512 166.443 166.374 166.305 166.237 166.168 166.099 166.030 166.039 166.108 166.177 166.246 166.314 166.325 166.325 166.325 166.324 166.315 166.246 166.177 166.109 166.040 165.822 165.398 164.973 164.549 164.125 163.503 162.798 162.094 161.389 160.684 +1316.35 169.613 169.809 170.005 170.202 170.398 170.595 170.792 170.989 171.185 171.382 171.522 171.621 171.719 171.818 171.916 172.298 172.722 173.147 173.571 173.997 174.436 174.875 175.314 175.753 176.056 176.184 176.312 176.440 176.568 176.450 176.238 176.025 175.813 175.602 175.602 175.602 175.602 175.602 175.540 175.328 175.116 174.904 174.691 174.414 174.089 173.764 173.438 173.113 172.508 171.857 171.207 170.556 169.939 169.514 169.090 168.666 168.242 167.951 167.838 167.725 167.612 167.499 167.386 167.272 167.159 167.046 166.933 166.834 166.735 166.636 166.537 166.438 166.339 166.241 166.142 166.043 166.056 166.155 166.254 166.353 166.451 166.466 166.466 166.466 166.466 166.452 166.354 166.255 166.156 166.057 165.822 165.397 164.973 164.549 164.125 163.482 162.747 162.012 161.277 160.543 +1386.48 169.189 169.445 169.702 169.958 170.215 170.471 170.728 170.985 171.242 171.499 171.681 171.809 171.938 172.067 172.195 172.581 173.005 173.429 173.853 174.271 174.650 175.029 175.408 175.787 176.017 176.055 176.093 176.131 176.168 176.026 175.814 175.601 175.389 175.178 175.178 175.178 175.178 175.178 175.116 174.904 174.692 174.479 174.267 174.007 173.712 173.417 173.121 172.826 172.277 171.686 171.096 170.505 169.939 169.515 169.090 168.666 168.242 167.964 167.881 167.798 167.715 167.632 167.548 167.465 167.382 167.299 167.216 167.087 166.958 166.829 166.700 166.571 166.442 166.313 166.185 166.056 166.073 166.202 166.331 166.460 166.588 166.607 166.607 166.607 166.607 166.590 166.461 166.332 166.203 166.075 165.821 165.397 164.973 164.549 164.125 163.460 162.696 161.931 161.166 160.401 +1456.61 168.766 169.082 169.398 169.715 170.031 170.348 170.665 170.981 171.298 171.615 171.840 171.998 172.157 172.315 172.474 172.863 173.288 173.712 174.136 174.544 174.863 175.183 175.502 175.820 175.977 175.925 175.873 175.821 175.769 175.602 175.389 175.177 174.965 174.754 174.754 174.754 174.754 174.754 174.692 174.480 174.267 174.055 173.843 173.600 173.335 173.070 172.804 172.539 172.046 171.515 170.984 170.454 169.939 169.515 169.090 168.666 168.242 167.977 167.924 167.871 167.818 167.764 167.711 167.658 167.605 167.552 167.498 167.340 167.181 167.022 166.863 166.704 166.545 166.386 166.228 166.069 166.090 166.249 166.408 166.567 166.725 166.749 166.749 166.749 166.749 166.727 166.568 166.409 166.251 166.092 165.821 165.397 164.973 164.549 164.125 163.439 162.644 161.849 161.055 160.260 +1526.74 168.342 168.718 169.095 169.471 169.848 170.224 170.601 170.978 171.354 171.731 171.998 172.187 172.376 172.564 172.753 173.146 173.570 173.994 174.419 174.818 175.077 175.336 175.595 175.854 175.938 175.796 175.654 175.512 175.370 175.177 174.965 174.753 174.541 174.330 174.330 174.330 174.330 174.329 174.268 174.056 173.843 173.631 173.419 173.193 172.958 172.723 172.487 172.252 171.814 171.344 170.873 170.403 169.939 169.515 169.090 168.666 168.242 167.990 167.967 167.944 167.920 167.897 167.874 167.851 167.828 167.804 167.781 167.593 167.404 167.215 167.026 166.837 166.648 166.459 166.270 166.082 166.107 166.296 166.485 166.674 166.862 166.890 166.890 166.890 166.890 166.864 166.675 166.487 166.298 166.109 165.821 165.397 164.973 164.549 164.125 163.417 162.593 161.768 160.943 160.118 +1596.87 167.976 168.394 168.812 169.230 169.648 170.071 170.507 170.944 171.381 171.818 172.123 172.336 172.548 172.760 172.972 173.362 173.780 174.197 174.615 175.001 175.214 175.426 175.638 175.850 175.879 175.674 175.468 175.263 175.057 174.838 174.612 174.387 174.161 173.937 173.930 173.924 173.917 173.910 173.844 173.631 173.419 173.207 172.995 172.779 172.560 172.341 172.122 171.903 171.514 171.096 170.679 170.261 169.845 169.434 169.024 168.613 168.202 167.971 167.978 167.984 167.991 167.998 168.005 168.012 168.018 168.025 168.032 167.820 167.608 167.396 167.184 166.972 166.760 166.548 166.336 166.123 166.145 166.343 166.542 166.740 166.939 166.974 166.981 166.988 166.994 166.971 166.759 166.547 166.335 166.123 165.824 165.406 164.989 164.571 164.153 163.436 162.594 161.752 160.911 160.069 +1667.00 167.834 168.222 168.610 168.998 169.386 169.806 170.302 170.799 171.295 171.792 172.123 172.335 172.548 172.760 172.972 173.336 173.724 174.111 174.499 174.860 175.072 175.284 175.496 175.708 175.751 175.576 175.400 175.225 175.049 174.794 174.509 174.224 173.938 173.654 173.617 173.581 173.544 173.507 173.419 173.207 172.995 172.783 172.571 172.337 172.089 171.840 171.591 171.342 170.974 170.586 170.199 169.811 169.429 169.079 168.728 168.377 168.027 167.842 167.879 167.916 167.953 167.989 168.026 168.063 168.100 168.137 168.173 167.962 167.749 167.537 167.325 167.113 166.901 166.689 166.477 166.265 166.252 166.391 166.529 166.668 166.807 166.858 166.895 166.932 166.968 166.971 166.759 166.547 166.335 166.123 165.836 165.449 165.061 164.674 164.286 163.598 162.787 161.975 161.163 160.351 +1737.14 167.692 168.050 168.408 168.766 169.124 169.540 170.097 170.653 171.210 171.767 172.123 172.335 172.547 172.759 172.972 173.310 173.668 174.025 174.383 174.719 174.931 175.143 175.355 175.567 175.623 175.477 175.332 175.186 175.041 174.751 174.406 174.061 173.715 173.371 173.304 173.238 173.171 173.104 172.995 172.783 172.571 172.359 172.147 171.896 171.617 171.338 171.059 170.780 170.434 170.077 169.719 169.362 169.014 168.723 168.432 168.142 167.851 167.714 167.781 167.847 167.914 167.981 168.048 168.114 168.181 168.248 168.315 168.103 167.891 167.679 167.467 167.255 167.042 166.830 166.618 166.406 166.359 166.438 166.517 166.595 166.674 166.742 166.809 166.876 166.943 166.971 166.759 166.547 166.335 166.122 165.849 165.491 165.134 164.776 164.418 163.761 162.979 162.197 161.415 160.633 +1807.27 167.550 167.878 168.206 168.534 168.862 169.275 169.891 170.508 171.125 171.741 172.123 172.335 172.547 172.759 172.971 173.284 173.611 173.939 174.267 174.577 174.789 175.001 175.213 175.425 175.495 175.379 175.263 175.148 175.032 174.708 174.303 173.898 173.492 173.088 172.992 172.895 172.798 172.701 172.571 172.359 172.147 171.935 171.722 171.455 171.146 170.837 170.528 170.219 169.894 169.567 169.239 168.912 168.598 168.368 168.137 167.906 167.676 167.585 167.682 167.779 167.876 167.972 168.069 168.166 168.263 168.359 168.456 168.244 168.032 167.820 167.608 167.396 167.184 166.972 166.760 166.548 166.467 166.485 166.504 166.523 166.541 166.627 166.723 166.820 166.917 166.971 166.759 166.547 166.334 166.122 165.861 165.534 165.206 164.879 164.551 163.923 163.171 162.419 161.667 160.915 +1877.40 167.408 167.706 168.004 168.302 168.600 169.010 169.686 170.363 171.039 171.716 172.123 172.335 172.547 172.759 172.971 173.258 173.555 173.853 174.151 174.436 174.648 174.860 175.072 175.284 175.366 175.281 175.195 175.110 175.024 174.665 174.200 173.735 173.269 172.805 172.679 172.552 172.425 172.298 172.147 171.935 171.723 171.510 171.298 171.013 170.674 170.336 169.997 169.658 169.354 169.057 168.759 168.462 168.183 168.012 167.841 167.671 167.500 167.457 167.584 167.710 167.837 167.964 168.090 168.217 168.344 168.471 168.597 168.386 168.174 167.962 167.749 167.537 167.325 167.113 166.901 166.689 166.574 166.533 166.491 166.450 166.409 166.511 166.638 166.764 166.891 166.971 166.759 166.547 166.334 166.122 165.874 165.576 165.279 164.981 164.683 164.085 163.363 162.642 161.920 161.198 +1947.53 167.267 167.535 167.802 168.070 168.338 168.744 169.480 170.217 170.954 171.690 172.123 172.335 172.547 172.759 172.971 173.232 173.499 173.767 174.035 174.294 174.506 174.718 174.930 175.142 175.238 175.182 175.127 175.071 175.016 174.622 174.097 173.572 173.046 172.522 172.366 172.209 172.052 171.896 171.723 171.511 171.298 171.086 170.874 170.572 170.203 169.834 169.465 169.097 168.815 168.547 168.280 168.012 167.767 167.656 167.546 167.435 167.324 167.328 167.485 167.642 167.798 167.955 168.112 168.269 168.425 168.582 168.739 168.527 168.315 168.103 167.891 167.679 167.467 167.254 167.042 166.830 166.681 166.580 166.479 166.377 166.276 166.395 166.552 166.708 166.865 166.971 166.759 166.546 166.334 166.122 165.887 165.619 165.351 165.084 164.816 164.248 163.556 162.864 162.172 161.480 +2017.66 167.125 167.363 167.601 167.838 168.076 168.478 169.275 170.071 170.868 171.665 172.123 172.335 172.547 172.759 172.971 173.205 173.443 173.681 173.919 174.153 174.365 174.577 174.789 175.001 175.110 175.084 175.058 175.033 175.007 174.579 173.994 173.409 172.823 172.240 172.053 171.866 171.679 171.493 171.299 171.086 170.874 170.662 170.450 170.131 169.732 169.333 168.934 168.535 168.275 168.037 167.800 167.562 167.352 167.301 167.250 167.199 167.149 167.200 167.386 167.573 167.760 167.947 168.133 168.320 168.507 168.693 168.880 168.668 168.456 168.244 168.032 167.820 167.608 167.396 167.184 166.972 166.788 166.627 166.466 166.305 166.144 166.279 166.466 166.653 166.839 166.971 166.758 166.546 166.334 166.122 165.899 165.662 165.424 165.186 164.949 164.410 163.748 163.086 162.424 161.762 +2087.79 167.002 167.222 167.442 167.663 167.883 168.285 169.126 169.966 170.806 171.646 172.120 172.328 172.536 172.744 172.952 173.148 173.343 173.538 173.732 173.929 174.136 174.343 174.551 174.758 174.879 174.888 174.896 174.905 174.914 174.468 173.845 173.222 172.599 171.978 171.766 171.554 171.342 171.129 170.917 170.705 170.493 170.281 170.069 169.738 169.318 168.898 168.479 168.059 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.089 167.296 167.504 167.711 167.919 168.126 168.334 168.541 168.749 168.956 168.749 168.542 168.334 168.127 167.918 167.706 167.494 167.282 167.070 166.860 166.653 166.445 166.238 166.030 166.181 166.393 166.605 166.817 166.971 166.764 166.556 166.348 166.141 165.929 165.713 165.496 165.279 165.063 164.552 163.920 163.288 162.656 162.024 +2157.92 167.002 167.282 167.563 167.843 168.123 168.550 169.330 170.111 170.891 171.671 172.103 172.281 172.459 172.636 172.814 172.903 172.978 173.053 173.127 173.217 173.395 173.572 173.749 173.927 174.057 174.125 174.194 174.262 174.331 173.967 173.434 172.901 172.368 171.837 171.625 171.412 171.200 170.988 170.776 170.564 170.352 170.140 169.927 169.614 169.224 168.834 168.445 168.055 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.076 167.254 167.431 167.609 167.786 167.964 168.141 168.319 168.496 168.674 168.496 168.319 168.141 167.964 167.777 167.565 167.353 167.140 166.928 166.736 166.558 166.381 166.203 166.026 166.181 166.393 166.605 166.817 166.975 166.798 166.620 166.442 166.265 166.058 165.811 165.565 165.318 165.072 164.573 163.971 163.369 162.767 162.165 +2228.05 167.003 167.343 167.683 168.023 168.363 168.815 169.535 170.256 170.976 171.696 172.085 172.233 172.381 172.529 172.677 172.658 172.613 172.568 172.523 172.506 172.653 172.801 172.948 173.095 173.234 173.363 173.491 173.620 173.749 173.467 173.024 172.580 172.137 171.695 171.483 171.271 171.059 170.847 170.635 170.423 170.210 169.998 169.786 169.489 169.130 168.770 168.410 168.051 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.063 167.211 167.358 167.506 167.653 167.801 167.948 168.096 168.243 168.391 168.244 168.096 167.949 167.801 167.635 167.423 167.211 166.999 166.787 166.612 166.464 166.317 166.169 166.021 166.181 166.393 166.605 166.818 166.979 166.832 166.684 166.536 166.389 166.186 165.910 165.633 165.357 165.080 164.594 164.022 163.450 162.878 162.306 +2298.18 167.003 167.403 167.803 168.203 168.604 169.080 169.740 170.400 171.061 171.721 172.068 172.186 172.304 172.422 172.539 172.413 172.248 172.083 171.918 171.794 171.912 172.029 172.146 172.264 172.412 172.600 172.789 172.977 173.166 172.966 172.613 172.260 171.907 171.554 171.342 171.130 170.918 170.705 170.493 170.281 170.069 169.857 169.645 169.365 169.036 168.706 168.376 168.047 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.050 167.168 167.285 167.403 167.520 167.638 167.755 167.873 167.991 168.108 167.991 167.873 167.756 167.638 167.494 167.282 167.070 166.858 166.646 166.487 166.370 166.252 166.135 166.017 166.181 166.393 166.605 166.818 166.984 166.866 166.748 166.631 166.513 166.315 166.008 165.702 165.395 165.089 164.615 164.073 163.531 162.989 162.447 +2368.32 167.003 167.463 167.923 168.383 168.844 169.345 169.945 170.545 171.146 171.746 172.051 172.139 172.227 172.314 172.402 172.169 171.884 171.599 171.313 171.083 171.170 171.258 171.345 171.432 171.589 171.838 172.086 172.335 172.583 172.465 172.202 171.939 171.675 171.413 171.200 170.988 170.776 170.564 170.352 170.140 169.928 169.716 169.503 169.241 168.941 168.642 168.342 168.042 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.038 167.125 167.213 167.300 167.388 167.475 167.563 167.650 167.738 167.825 167.738 167.650 167.563 167.475 167.352 167.140 166.928 166.716 166.504 166.363 166.275 166.188 166.100 166.013 166.181 166.393 166.606 166.818 166.988 166.900 166.812 166.725 166.637 166.443 166.107 165.770 165.434 165.097 164.636 164.124 163.612 163.100 162.588 +2438.45 167.003 167.523 168.043 168.563 169.084 169.610 170.150 170.691 171.231 171.771 172.033 172.091 172.149 172.207 172.265 171.924 171.519 171.114 170.709 170.371 170.429 170.486 170.544 170.601 170.767 171.075 171.384 171.692 172.001 171.964 171.791 171.617 171.444 171.271 171.059 170.847 170.635 170.423 170.211 169.998 169.786 169.574 169.362 169.117 168.847 168.578 168.308 168.038 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.025 167.082 167.140 167.197 167.255 167.312 167.370 167.427 167.485 167.543 167.485 167.428 167.370 167.313 167.211 166.999 166.787 166.575 166.363 166.239 166.181 166.124 166.066 166.008 166.181 166.393 166.606 166.818 166.992 166.934 166.877 166.819 166.761 166.572 166.205 165.839 165.472 165.106 164.657 164.175 163.693 163.211 162.729 +2508.58 167.003 167.583 168.163 168.743 169.323 169.875 170.355 170.836 171.316 171.796 172.016 172.044 172.072 172.100 172.128 171.680 171.155 170.630 170.104 169.660 169.687 169.715 169.742 169.770 169.944 170.313 170.681 171.050 171.418 171.463 171.380 171.296 171.213 171.130 170.918 170.706 170.494 170.281 170.069 169.857 169.645 169.433 169.221 168.993 168.753 168.513 168.274 168.034 167.818 167.606 167.394 167.182 167.000 167.000 167.000 167.000 167.000 167.012 167.039 167.067 167.094 167.122 167.150 167.177 167.205 167.232 167.260 167.232 167.205 167.177 167.150 167.070 166.857 166.645 166.433 166.221 166.114 166.087 166.059 166.032 166.004 166.181 166.394 166.606 166.818 166.996 166.968 166.941 166.913 166.885 166.700 166.304 165.907 165.511 165.114 164.678 164.226 163.774 163.322 162.870 +2578.71 166.985 167.620 168.254 168.888 169.522 170.096 170.519 170.943 171.367 171.791 171.969 171.965 171.960 171.956 171.951 171.401 170.762 170.123 169.484 168.939 168.941 168.943 168.944 168.946 169.130 169.554 169.978 170.402 170.826 170.949 170.954 170.958 170.962 170.967 170.757 170.547 170.337 170.127 169.917 169.708 169.498 169.288 169.078 168.869 168.659 168.449 168.239 168.030 167.818 167.606 167.394 167.182 167.000 166.997 166.995 166.992 166.990 166.988 166.988 166.988 166.988 166.988 166.988 166.988 166.988 166.988 166.988 166.991 166.993 166.996 166.998 166.940 166.731 166.521 166.311 166.101 166.013 166.015 166.017 166.020 166.022 166.202 166.411 166.621 166.831 167.010 167.006 167.001 166.996 166.992 166.809 166.387 165.966 165.544 165.122 164.698 164.274 163.850 163.425 163.001 +2648.84 166.702 167.306 167.911 168.515 169.119 169.671 170.095 170.519 170.943 171.367 171.510 171.446 171.382 171.317 171.253 170.668 170.000 169.331 168.662 168.095 168.127 168.159 168.190 168.222 168.423 168.847 169.271 169.695 170.119 170.285 170.350 170.414 170.478 170.543 170.363 170.183 170.003 169.823 169.643 169.463 169.284 169.104 168.924 168.744 168.565 168.385 168.205 168.026 167.818 167.606 167.394 167.182 166.995 166.963 166.930 166.898 166.866 166.847 166.847 166.847 166.847 166.847 166.847 166.847 166.847 166.847 166.847 166.880 166.912 166.944 166.977 166.949 166.769 166.589 166.410 166.230 166.171 166.204 166.236 166.268 166.301 166.459 166.639 166.818 166.998 167.143 167.079 167.014 166.949 166.885 166.681 166.289 165.897 165.505 165.113 164.698 164.274 163.849 163.425 163.001 +2718.97 166.419 166.993 167.567 168.142 168.716 169.247 169.671 170.095 170.519 170.942 171.052 170.927 170.803 170.679 170.554 169.936 169.237 168.538 167.840 167.251 167.313 167.374 167.436 167.498 167.716 168.140 168.564 168.988 169.412 169.621 169.745 169.870 169.994 170.118 169.969 169.819 169.669 169.519 169.369 169.219 169.069 168.920 168.770 168.620 168.470 168.321 168.171 168.021 167.818 167.606 167.394 167.182 166.991 166.929 166.866 166.804 166.741 166.706 166.706 166.706 166.706 166.706 166.706 166.706 166.706 166.706 166.706 166.768 166.831 166.893 166.955 166.957 166.808 166.658 166.508 166.358 166.330 166.392 166.454 166.517 166.579 166.716 166.866 167.016 167.165 167.276 167.151 167.027 166.902 166.778 166.552 166.190 165.828 165.466 165.104 164.698 164.274 163.849 163.425 163.001 +2789.10 166.136 166.680 167.224 167.768 168.313 168.822 169.246 169.670 170.094 170.518 170.593 170.409 170.225 170.040 169.856 169.204 168.475 167.746 167.017 166.407 166.499 166.590 166.682 166.774 167.009 167.433 167.857 168.281 168.705 168.957 169.141 169.326 169.510 169.694 169.574 169.454 169.335 169.215 169.095 168.975 168.855 168.735 168.616 168.496 168.376 168.256 168.137 168.017 167.818 167.606 167.394 167.182 166.987 166.894 166.802 166.709 166.617 166.564 166.564 166.564 166.564 166.564 166.564 166.564 166.564 166.564 166.564 166.657 166.749 166.842 166.934 166.966 166.846 166.726 166.607 166.487 166.488 166.581 166.673 166.765 166.857 166.973 167.093 167.213 167.332 167.409 167.224 167.040 166.855 166.671 166.423 166.091 165.759 165.427 165.095 164.698 164.273 163.849 163.425 163.001 +2859.23 165.852 166.367 166.881 167.395 167.910 168.398 168.822 169.246 169.670 170.094 170.135 169.890 169.646 169.402 169.157 168.471 167.712 166.954 166.195 165.563 165.684 165.806 165.928 166.050 166.302 166.726 167.150 167.573 167.997 168.293 168.537 168.782 169.026 169.270 169.180 169.090 169.000 168.911 168.821 168.731 168.641 168.551 168.462 168.372 168.282 168.192 168.103 168.013 167.818 167.606 167.394 167.182 166.982 166.860 166.738 166.615 166.493 166.423 166.423 166.423 166.423 166.423 166.423 166.423 166.423 166.423 166.423 166.545 166.668 166.790 166.913 166.974 166.885 166.795 166.705 166.615 166.647 166.769 166.891 167.014 167.136 167.230 167.320 167.410 167.500 167.542 167.297 167.053 166.808 166.564 166.295 165.993 165.691 165.389 165.087 164.697 164.273 163.849 163.425 163.001 +2929.37 165.569 166.054 166.538 167.022 167.506 167.973 168.397 168.821 169.245 169.669 169.676 169.372 169.068 168.763 168.459 167.739 166.950 166.161 165.372 164.719 164.870 165.022 165.174 165.326 165.594 166.018 166.442 166.866 167.290 167.629 167.933 168.237 168.542 168.846 168.786 168.726 168.666 168.606 168.547 168.487 168.427 168.367 168.307 168.248 168.188 168.128 168.068 168.009 167.818 167.606 167.394 167.182 166.978 166.826 166.673 166.521 166.369 166.281 166.281 166.281 166.281 166.281 166.281 166.281 166.281 166.281 166.281 166.434 166.586 166.739 166.891 166.983 166.923 166.863 166.804 166.744 166.805 166.958 167.110 167.262 167.415 167.488 167.547 167.607 167.667 167.675 167.370 167.065 166.761 166.456 166.166 165.894 165.622 165.350 165.078 164.697 164.273 163.849 163.425 163.000 +2999.50 165.286 165.741 166.195 166.649 167.103 167.549 167.973 168.397 168.821 169.245 169.218 168.854 168.489 168.125 167.761 167.006 166.188 165.369 164.550 163.874 164.056 164.238 164.420 164.602 164.887 165.311 165.735 166.159 166.583 166.964 167.329 167.693 168.058 168.422 168.392 168.362 168.332 168.302 168.272 168.242 168.213 168.183 168.153 168.123 168.093 168.064 168.034 168.004 167.818 167.606 167.394 167.182 166.974 166.792 166.609 166.427 166.244 166.140 166.140 166.140 166.140 166.140 166.140 166.140 166.140 166.140 166.140 166.322 166.505 166.687 166.870 166.992 166.962 166.932 166.902 166.872 166.964 167.146 167.329 167.511 167.693 167.745 167.774 167.804 167.834 167.807 167.443 167.078 166.714 166.349 166.037 165.795 165.553 165.311 165.069 164.697 164.273 163.849 163.424 163.000 +3069.63 165.003 165.428 165.852 166.276 166.700 167.125 167.548 167.972 168.396 168.820 168.760 168.335 167.911 167.487 167.062 166.274 165.425 164.576 163.728 163.030 163.242 163.455 163.667 163.879 164.182 164.606 165.030 165.455 165.879 166.303 166.727 167.152 167.576 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 168.000 167.818 167.606 167.394 167.182 166.970 166.758 166.545 166.333 166.121 166.000 166.000 166.000 166.000 166.000 166.000 166.000 166.000 166.000 166.000 166.212 166.424 166.636 166.848 167.000 167.000 167.000 167.000 167.000 167.121 167.333 167.545 167.758 167.970 168.000 168.000 168.000 168.000 167.939 167.515 167.091 166.667 166.242 165.909 165.697 165.485 165.273 165.061 164.697 164.273 163.848 163.424 163.000 diff --git a/examples/GulfOfMaine_soil_layered_100x100.txt b/examples/GulfOfMaine_soil_layered_100x100.txt new file mode 100644 index 00000000..50ba5b79 --- /dev/null +++ b/examples/GulfOfMaine_soil_layered_100x100.txt @@ -0,0 +1,112 @@ +--- MoorPy Soil Input File --- +nGridX 100 +nGridY 100 + -4420.52 -4345.53 -4270.54 -4195.55 -4120.57 -4045.58 -3970.59 -3895.60 -3820.61 -3745.62 -3670.63 -3595.64 -3520.66 -3445.67 -3370.68 -3295.69 -3220.70 -3145.71 -3070.72 -2995.74 -2920.75 -2845.76 -2770.77 -2695.78 -2620.79 -2545.80 -2470.81 -2395.83 -2320.84 -2245.85 -2170.86 -2095.87 -2020.88 -1945.89 -1870.90 -1795.92 -1720.93 -1645.94 -1570.95 -1495.96 -1420.97 -1345.98 -1270.99 -1196.01 -1121.02 -1046.03 -971.04 -896.05 -821.06 -746.07 -671.08 -596.10 -521.11 -446.12 -371.13 -296.14 -221.15 -146.16 -71.17 3.81 78.80 153.79 228.78 303.77 378.76 453.75 528.74 603.72 678.71 753.70 828.69 903.68 978.67 1053.66 1128.64 1203.63 1278.62 1353.61 1428.60 1503.59 1578.58 1653.57 1728.55 1803.54 1878.53 1953.52 2028.51 2103.50 2178.49 2253.48 2328.46 2403.45 2478.44 2553.43 2628.42 2703.41 2778.40 2853.39 2928.37 3003.36 +-3873.36 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 +-3803.23 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 +-3733.10 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 +-3662.97 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3592.83 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3522.70 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3452.57 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3382.44 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3312.31 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3242.18 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3172.05 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-3101.92 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 +-3031.78 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 +-2961.65 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2891.52 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2821.39 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2751.26 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2681.13 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2611.00 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-2540.87 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 +-2470.74 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 +-2400.60 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 +-2330.47 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 +-2260.34 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 +-2190.21 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-2120.08 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-2049.95 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 +-1979.82 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 +-1909.69 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 +-1839.55 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 +-1769.42 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 +-1699.29 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_1 +-1629.16 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 +-1559.03 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 +-1488.90 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 +-1418.77 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 +-1348.64 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 +-1278.51 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 +-1208.37 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 +-1138.24 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 +-1068.11 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-997.98 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-927.85 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-857.72 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-787.59 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-717.46 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-647.32 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 +-577.19 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 +-507.06 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 +-436.93 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 +-366.80 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +-296.67 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +-226.54 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +-156.41 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +-86.28 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +-16.14 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +53.99 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +124.12 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +194.25 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +264.38 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +334.51 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +404.64 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +474.77 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +544.91 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +615.04 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +685.17 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +755.30 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +825.43 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_4 pro_4 pro_4 pro_4 pro_4 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +895.56 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +965.69 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1035.82 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1105.95 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1176.09 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1246.22 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1316.35 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1386.48 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1456.61 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1526.74 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1596.87 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1667.00 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1737.14 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1807.27 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1877.40 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +1947.53 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 +2017.66 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2087.79 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_3 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2157.92 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2228.05 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2298.18 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2368.32 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2438.45 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2508.58 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2578.71 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2648.84 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2718.97 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2789.10 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2859.23 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_2 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2929.37 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_2 pro_2 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +2999.50 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +3069.63 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_0 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_1 pro_0 pro_0 pro_0 pro_0 pro_0 +--- SOIL TYPES --- +Class gamma Su0 k alpha phi UCS Em +(name) (kN/m^3) (kPa) (kPa/m) (-) (deg) (MPa) (MPa) +pro_0 8.00 14.0 2.8 0.7 - - - +pro_1 8.00 12.0 2.4 0.7 - - - +pro_2 8.00 10.0 2.0 0.7 - - - +pro_3 8.00 8.0 1.6 0.7 - - - +pro_4 8.00 6.0 1.2 0.7 - - - \ No newline at end of file diff --git a/examples/GulfOfMaine_soil_profiles.yaml b/examples/GulfOfMaine_soil_profiles.yaml new file mode 100644 index 00000000..71b43efd --- /dev/null +++ b/examples/GulfOfMaine_soil_profiles.yaml @@ -0,0 +1,67 @@ +pro_0: + layers: + - soil_type: clay + top: 0 + bottom: 10 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 10.0 + Su_bot: 20.0 + - soil_type: clay + top: 10 + bottom: 20 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 15.0 + Su_bot: 25.0 +pro_1: + layers: + - soil_type: clay + top: 0 + bottom: 20 + gamma_top: 8.2 + gamma_bot: 8.2 + Su_top: 12.0 + Su_bot: 22.0 +pro_2: + layers: + - soil_type: clay + top: 0 + bottom: 5 + gamma_top: 8.4 + gamma_bot: 8.4 + Su_top: 14.0 + Su_bot: 24.0 + - soil_type: clay + top: 5 + bottom: 20 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 15.0 + Su_bot: 25.0 + +pro_3: + layers: + - soil_type: clay + top: 0 + bottom: 5 + gamma_top: 8.6 + gamma_bot: 8.6 + Su_top: 16.0 + Su_bot: 26.0 + - soil_type: clay + top: 5 + bottom: 20 + gamma_top: 8.0 + gamma_bot: 8.0 + Su_top: 25.0 + Su_bot: 35.0 +pro_4: + layers: + - soil_type: clay + top: 0 + bottom: 20 + gamma_top: 8.8 + gamma_bot: 8.8 + Su_top: 18.0 + Su_bot: 28.0 \ No newline at end of file diff --git a/examples/GulfOfMaine_soil_uniform_100x100.txt b/examples/GulfOfMaine_soil_uniform_100x100.txt new file mode 100644 index 00000000..14d5d515 --- /dev/null +++ b/examples/GulfOfMaine_soil_uniform_100x100.txt @@ -0,0 +1,112 @@ +--- MoorPy Soil Input File --- +nGridX 100 +nGridY 100 + -4420.52 -4345.53 -4270.54 -4195.55 -4120.57 -4045.58 -3970.59 -3895.60 -3820.61 -3745.62 -3670.63 -3595.64 -3520.66 -3445.67 -3370.68 -3295.69 -3220.70 -3145.71 -3070.72 -2995.74 -2920.75 -2845.76 -2770.77 -2695.78 -2620.79 -2545.80 -2470.81 -2395.83 -2320.84 -2245.85 -2170.86 -2095.87 -2020.88 -1945.89 -1870.90 -1795.92 -1720.93 -1645.94 -1570.95 -1495.96 -1420.97 -1345.98 -1270.99 -1196.01 -1121.02 -1046.03 -971.04 -896.05 -821.06 -746.07 -671.08 -596.10 -521.11 -446.12 -371.13 -296.14 -221.15 -146.16 -71.17 3.81 78.80 153.79 228.78 303.77 378.76 453.75 528.74 603.72 678.71 753.70 828.69 903.68 978.67 1053.66 1128.64 1203.63 1278.62 1353.61 1428.60 1503.59 1578.58 1653.57 1728.55 1803.54 1878.53 1953.52 2028.51 2103.50 2178.49 2253.48 2328.46 2403.45 2478.44 2553.43 2628.42 2703.41 2778.40 2853.39 2928.37 3003.36 +-3873.36 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 +-3803.23 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 +-3733.10 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 +-3662.97 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-3592.83 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-3522.70 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-3452.57 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-3382.44 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-3312.31 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-3242.18 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-3172.05 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-3101.92 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 +-3031.78 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 +-2961.65 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-2891.52 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-2821.39 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-2751.26 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-2681.13 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-2611.00 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-2540.87 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 +-2470.74 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 +-2400.60 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 +-2330.47 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 +-2260.34 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 +-2190.21 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-2120.08 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-2049.95 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 +-1979.82 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 +-1909.69 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 +-1839.55 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 +-1769.42 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 +-1699.29 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_1 +-1629.16 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 +-1559.03 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 +-1488.90 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 +-1418.77 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 +-1348.64 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 +-1278.51 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 +-1208.37 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 +-1138.24 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 +-1068.11 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-997.98 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-927.85 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-857.72 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-787.59 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-717.46 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-647.32 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 +-577.19 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 +-507.06 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 +-436.93 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 +-366.80 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +-296.67 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +-226.54 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +-156.41 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +-86.28 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +-16.14 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +53.99 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +124.12 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +194.25 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +264.38 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +334.51 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +404.64 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +474.77 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +544.91 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +615.04 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +685.17 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +755.30 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +825.43 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_4 mud_4 mud_4 mud_4 mud_4 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +895.56 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +965.69 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1035.82 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1105.95 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1176.09 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1246.22 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1316.35 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1386.48 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1456.61 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1526.74 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1596.87 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1667.00 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1737.14 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1807.27 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1877.40 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +1947.53 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 +2017.66 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2087.79 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_3 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2157.92 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2228.05 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2298.18 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2368.32 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2438.45 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2508.58 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2578.71 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2648.84 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2718.97 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2789.10 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2859.23 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_2 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2929.37 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_2 mud_2 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +2999.50 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +3069.63 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_0 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_1 mud_0 mud_0 mud_0 mud_0 mud_0 +--- SOIL TYPES --- +Class gamma Su0 k alpha phi UCS Em +(name) (kN/m^3) (kPa) (kPa/m) (-) (deg) (MPa) (MPa) +mud_0 8.00 14.0 2.8 0.7 - - - +mud_1 8.00 12.0 2.4 0.7 - - - +mud_2 8.00 10.0 2.0 0.7 - - - +mud_3 8.00 8.0 1.6 0.7 - - - +mud_4 8.00 6.0 1.2 0.7 - - - \ No newline at end of file diff --git a/examples/OntologySample200m.yaml b/examples/OntologySample200m.yaml index 64bcd8f6..c37ab097 100644 --- a/examples/OntologySample200m.yaml +++ b/examples/OntologySample200m.yaml @@ -43,23 +43,42 @@ site: soil_types: mud_soft: - Su0 : [2.39] # [kPa] - k : [1.41] # [kPa/m] - gamma : [10] # [kN/m^3] - depth: [0] # [m] + layers: + - soil_type: clay + top: 0 + bottom: 50 + gamma_top: 10.0 + gamma_bot: 10.0 + Su_top: 2.39 + Su_bot: 59.39 mud_firm: - Su0 : [23.94] # [kPa] - k : [2.67] # [kPa/m] - gamma: [15] - depth: [0] # [m] - mud_hard: - Su0: [50] - k: [1.0] - gamma: [9.5] - depth: [0] + layers: + - soil_type: clay + top: 0 + bottom: 50 + gamma_top: 10.0 + gamma_bot: 50.0 + Su_top: 23.4 + Su_bot: 157.44 + mud_hard: + layers: + - soil_type: clay + top: 0 + bottom: 50 + gamma_top: 8.5 + gamma_bot: 8.5 + Su_top: 50.0 + Su_bot: 100.00 rock: - UCS: [5] # [MPa] - Em: [7] # [MPa] + layers: + - soil_type: rock + top: 0 + bottom: 50 + UCS_top: 5.0 + UCS_bot: 5.0 + Em_top: 7.0 + Em_bot: 7.0 + metocean: extremes: # extreme values for specified return periods (in years) @@ -331,26 +350,27 @@ mooring_connector_types: anchor_types: drag-embedment1: - type : DEA # type of anchor - A : 10 # net area of anchor's fluke [m^2] - zlug : 20 # embedded depth of padeye [m] + type : DEA # type of anchor + B : 5 # net area of anchor's fluke [m^2] + L : 2 + zlug : 10 # embedded depth of padeye [m] suction_pile1: - type : suction_pile + type : suction L : 16.4 # length of pile [m] D : 5.45 # diameter of pile [m] zlug : 9.32 # embedded depth of padeye [m] dandg_pile1: - type : dandg_pile + type : dandg L : 50 # length of pile [m] D : 3 # diameter of pile [m] zlug : 0 # embedded depth [m] driven_pile1: - type : driven_pile + type : driven L : 20 # pile length [m] D : 1.5 # pile diameter [m] zlug : 3 # embedded depth [m] driven_pile2: - type : driven_pile + type : driven L : 20 # pile length [m] D : 1.5 # pile diameter [m] zlug : -3 # embedded depth [m] @@ -360,14 +380,14 @@ anchor_types: zlug : 10 #beta: 30 torpedo_pile1: - type: torpedo_pile + type: torpedo D1 : 3 D2: 1.1 L1: 10 L2: 4 zlug: 16 helical_pile1: - type: helical_pile + type: helical L : 25.1 d : 1 D : 5.01 diff --git a/examples/OntologySample200m_1turb.yaml b/examples/OntologySample200m_1turb.yaml index 3ff93e9e..738755bd 100644 --- a/examples/OntologySample200m_1turb.yaml +++ b/examples/OntologySample200m_1turb.yaml @@ -1295,7 +1295,7 @@ anchor_types: zlug : 10 # embedded depth of padeye [m] suction1: - type : suction_pile + type : suction L : 16.4 # length of pile [m] D : 5.45 # diameter of pile [m] zlug : 9.32 # embedded depth of padeye [m] diff --git a/examples/OntologySample200mbis_1turb.yaml b/examples/OntologySample200mbis_1turb.yaml new file mode 100644 index 00000000..1cd07b83 --- /dev/null +++ b/examples/OntologySample200mbis_1turb.yaml @@ -0,0 +1,1323 @@ +type: draft/example of floating array ontology under construction +name: +comments: +# Site condition information +site: + general: + water_depth : 200 # [m] uniform water depth + rho_water : 1025.0 # [kg/m^3] water density + rho_air : 1.225 # [kg/m^3] air density + mu_air : 1.81e-05 # air dynamic viscosity + #... + + boundaries: # project or lease area boundary, via file or vertex list + file: # filename of x-y vertex coordinates [m] + x_y: # list of polygon vertices in order [m] + - [-3000, -3000] + - [-3000, 3000] + - [3000, 3000] + - [3000, -3000] + + bathymetry: + file: './bathymetry200m_sample.txt' + + seabed: + x : [-10901, 0, 10000] + y : [-10900, 0, 10000 ] + + type_array: + - [mud_soft , mud_firm , mud_soft] + - [mud_soft , mud_firm , mud_soft] + - [mud_soft , mud_firm , mud_soft] + + soil_types: + mud_soft: + layers: + - soil_type: clay + top: 0 + bottom: 50 + gamma_top: 10.0 + gamma_bot: 10.0 + Su_top: 2.39 + Su_bot: 59.39 + mud_firm: + layers: + - soil_type: clay + top: 0 + bottom: 50 + gamma_top: 10.0 + gamma_bot: 50.0 + Su_top: 23.4 + Su_bot: 157.44 + sand_dense: + layers: + - soil_type: sand + top: 0 + bottom: 20 + gamma_top: 9.0 + gamma_bot: 9.0 + phi_top: 28 + phi_bot: 33 + Dr_top: 50 + Dr_bot: 55 + + metocean: + extremes: # extreme values for specified return periods (in years) + keys : [ Hs , Tp , WindSpeed, TI, Shear, Gamma, CurrentSpeed ] + data : + 1: [ 1 ,2 ,3 ] + 10: [ 1 , 2 , 3 ] + 50: [ 1 , 2 , 3 ] + 500: [ 1 , 2 , 3 ] + + probabalistic_bins: + keys : [ prob , Hs , Tp, WindSpeed, TI, Shear, Gamma, CurrentSpeed, WindDir, WaveDir, CurrentDir ] + data : + - [ 0.010 , 1 , 1 ] + - [ 0.006 , 1 , 1 ] + - [ 0.005 , 1 , 1 ] + + time_series : + file: 'metocean_timeseries.csv' + + resource : + file: 'windresource' + + RAFT_cases: + keys : [wind_speed, wind_heading, turbulence, turbine_status, yaw_misalign, wave_spectrum, wave_period, wave_height, wave_heading ] + data : # m/s deg % or e.g. IIB_NTM string deg string (s) (m) (deg) + - [ 0, 0, 0, operating, 0, JONSWAP, 12, 6, 0 ] + # - [ 16, 0, IIB_NTM, operating, 0, JONSWAP, 12, 6, 30 ] + # - [ 10.59, 0, 0.05, operating, 0, JONSWAP, 15.75, 11.86, 0 ] + + RAFT_settings: + min_freq : 0.001 # [Hz] lowest frequency to consider, also the frequency bin width + max_freq : 0.20 # [Hz] highest frequency to consider + XiStart : 0 # sets initial amplitude of each DOF for all frequencies + nIter : 4 # sets how many iterations to perform in Model.solveDynamics() +# ----- Array-level inputs ----- + +# Wind turbine array layout +array: + keys : [ID, topsideID, platformID, mooringID, x_location, y_location, heading_adjust] + data : # ID# ID# ID# [m] [m] [deg] + - [fowt0, 1, 1, ms1, -1600, -1600, 180 ] # 2 array, shared moorings + # - [FOWT3, 1, 1, ms3, 1600, -1600, 0 ] + # - [FOWT4, 1, 2, ms4, -1600, 0, 0 ] + # - [FOWT5, 1, 1, ms5, 0, 0, 45 ] + # - [FOWT6, 1, 1, ms10, 1600, 0, 0 ] + # - [FOWT7, 1, 1, ms6, -1600, 1600, 0 ] + # - [FOWT8, 1, 1, ms6, 0, 1600, 0 ] + # - [FOWT9, 1, 1, ms6, 1600, 1600, 0 ] + +# ----- turbines and platforms ----- + +topsides: + + - type : turbine + mRNA : 991000 # [kg] RNA mass + IxRNA : 0 # [kg-m2] RNA moment of inertia about local x axis (assumed to be identical to rotor axis for now, as approx) [kg-m^2] + IrRNA : 0 # [kg-m2] RNA moment of inertia about local y or z axes [kg-m^2] + xCG_RNA : 0 # [m] x location of RNA center of mass [m] (Actual is ~= -0.27 m) + hHub : 150.0 # [m] hub height above water line [m] + Fthrust : 1500.0E3 # [N] temporary thrust force to use + + I_drivetrain: 318628138.0 # full rotor + drivetrain inertia as felt on the high-speed shaft + + nBlades : 3 # number of blades + Zhub : 150.0 # hub height [m] + Rhub : 3.97 # hub radius [m] + precone : 4.0 # [deg] + shaft_tilt : 6.0 # [deg] + overhang : -12.0313 # [m] + aeroMod : 1 # 0 aerodynamics off; 1 aerodynamics on + + + blade: + precurveTip : -3.9999999999999964 # + presweepTip : 0.0 # + Rtip : 120.96999999936446 # rotor radius + + # r chord theta precurve presweep + geometry: + - [ 8.004, 5.228, 15.474, 0.035, 0.000 ] + - [ 12.039, 5.321, 14.692, 0.084, 0.000 ] + - [ 16.073, 5.458, 13.330, 0.139, 0.000 ] + - [ 20.108, 5.602, 11.644, 0.192, 0.000 ] + - [ 24.142, 5.718, 9.927, 0.232, 0.000 ] + - [ 28.177, 5.767, 8.438, 0.250, 0.000 ] + - [ 32.211, 5.713, 7.301, 0.250, 0.000 ] + - [ 36.246, 5.536, 6.232, 0.246, 0.000 ] + - [ 40.280, 5.291, 5.230, 0.240, 0.000 ] + - [ 44.315, 5.035, 4.348, 0.233, 0.000 ] + - [ 48.349, 4.815, 3.606, 0.218, 0.000 ] + - [ 52.384, 4.623, 2.978, 0.178, 0.000 ] + - [ 56.418, 4.432, 2.423, 0.100, 0.000 ] + - [ 60.453, 4.245, 1.924, 0.000, 0.000 ] + - [ 64.487, 4.065, 1.467, -0.112, 0.000 ] + - [ 68.522, 3.896, 1.056, -0.244, 0.000 ] + - [ 72.556, 3.735, 0.692, -0.415, 0.000 ] + - [ 76.591, 3.579, 0.355, -0.620, 0.000 ] + - [ 80.625, 3.425, 0.019, -0.846, 0.000 ] + - [ 84.660, 3.268, -0.358, -1.080, 0.000 ] + - [ 88.694, 3.112, -0.834, -1.330, 0.000 ] + - [ 92.729, 2.957, -1.374, -1.602, 0.000 ] + - [ 96.763, 2.800, -1.848, -1.895, 0.000 ] + - [ 100.798, 2.637, -2.136, -2.202, 0.000 ] + - [ 104.832, 2.464, -2.172, -2.523, 0.000 ] + - [ 108.867, 2.283, -2.108, -2.864, 0.000 ] + - [ 112.901, 2.096, -1.953, -3.224, 0.000 ] + - [ 116.936, 1.902, -1.662, -3.605, 0.000 ] + # station(rel) airfoil name + airfoils: + - [ 0.00000, circular ] + - [ 0.02000, circular ] + - [ 0.15000, SNL-FFA-W3-500 ] + - [ 0.24517, FFA-W3-360 ] + - [ 0.32884, FFA-W3-330blend ] + - [ 0.43918, FFA-W3-301 ] + - [ 0.53767, FFA-W3-270blend ] + - [ 0.63821, FFA-W3-241 ] + - [ 0.77174, FFA-W3-211 ] + - [ 1.00000, FFA-W3-211 ] + + + airfoils: + - name : circular # + relative_thickness : 1.0 # + data: # alpha c_l c_d c_m + - [ -179.9087, 0.00010, 0.35000, -0.00010 ] + - [ 179.9087, 0.00010, 0.35000, -0.00010 ] + - name : SNL-FFA-W3-500 # + relative_thickness : 0.5 # + data: # alpha c_l c_d c_m + - [ -179.9660, 0.00000, 0.08440, 0.00000 ] + - [ -170.0000, 0.44190, 0.08440, 0.31250 ] + - [ -160.0002, 0.88370, 0.12680, 0.28310 ] + - [ -149.9998, 0.96740, 0.29270, 0.26320 ] + - [ -139.9999, 0.78010, 0.49700, 0.20480 ] + - [ -130.0001, 0.62930, 0.71610, 0.19320 ] + - [ -120.0003, 0.47850, 0.92460, 0.20080 ] + - [ -109.9999, 0.31890, 1.09850, 0.21360 ] + - [ -100.0000, 0.15530, 1.21820, 0.22210 ] + - [ -90.0002, 0.00000, 1.27070, 0.21980 ] + - [ -79.9998, -0.15530, 1.21820, 0.19600 ] + - [ -70.0000, -0.31890, 1.09850, 0.16350 ] + - [ -60.0001, -0.47840, 0.92460, 0.12850 ] + - [ -49.9997, -0.62930, 0.71610, 0.09650 ] + - [ -39.9999, -0.78010, 0.49700, 0.07160 ] + - [ -30.0001, -0.96740, 0.29270, 0.05220 ] + - [ -20.0002, -1.02810, 0.14990, -0.00630 ] + - [ -19.7499, -1.02430, 0.14720, -0.00890 ] + - [ -19.2502, -1.00520, 0.14470, -0.00990 ] + - [ -18.9999, -0.99710, 0.14330, -0.01050 ] + - [ -18.7500, -1.00520, 0.14030, -0.01100 ] + - [ -18.5002, -0.99950, 0.13860, -0.01160 ] + - [ -18.2499, -0.99080, 0.13730, -0.01200 ] + - [ -18.0000, -0.98150, 0.13600, -0.01260 ] + - [ -17.4998, -0.97640, 0.13220, -0.01350 ] + - [ -17.2500, -0.97050, 0.13060, -0.01390 ] + - [ -17.0002, -0.96550, 0.12900, -0.01430 ] + - [ -16.7498, -0.96620, 0.12680, -0.01470 ] + - [ -16.5000, -0.95440, 0.12580, -0.01510 ] + - [ -16.2502, -0.94440, 0.12460, -0.01550 ] + - [ -15.9998, -0.94050, 0.12290, -0.01580 ] + - [ -15.7500, -0.94330, 0.12060, -0.01610 ] + - [ -15.5002, -0.93300, 0.11950, -0.01640 ] + - [ -15.2498, -0.92110, 0.11850, -0.01680 ] + - [ -14.7502, -0.91580, 0.11500, -0.01730 ] + - [ -14.4998, -0.90700, 0.11380, -0.01750 ] + - [ -14.2500, -0.89590, 0.11270, -0.01780 ] + - [ -14.0002, -0.89260, 0.11100, -0.01810 ] + - [ -13.7498, -0.88080, 0.11000, -0.01840 ] + - [ -13.5000, -0.87220, 0.10890, -0.01860 ] + - [ -13.2502, -0.86600, 0.10750, -0.01880 ] + - [ -12.9998, -0.86260, 0.10590, -0.01880 ] + - [ -12.7500, -0.84890, 0.10510, -0.01920 ] + - [ -12.5002, -0.83630, 0.10420, -0.01940 ] + - [ -12.2498, -0.83630, 0.10230, -0.01940 ] + - [ -12.0000, -0.82710, 0.10130, -0.01960 ] + - [ -11.7502, -0.81410, 0.10040, -0.01980 ] + - [ -11.4998, -0.80040, 0.09970, -0.02000 ] + - [ -11.0002, -0.78900, 0.09710, -0.01990 ] + - [ -10.7498, -0.78620, 0.09560, -0.01960 ] + - [ -10.5000, -0.77470, 0.09480, -0.01940 ] + - [ -10.2502, -0.77010, 0.09400, -0.01840 ] + - [ -9.9998, -0.76740, 0.09250, -0.01830 ] + - [ -9.7500, -0.75060, 0.09170, -0.01920 ] + - [ -9.5002, -0.72900, 0.09120, -0.02050 ] + - [ -9.2498, -0.70950, 0.09020, -0.02240 ] + - [ -9.0000, -0.68550, 0.08950, -0.02470 ] + - [ -8.7502, -0.65900, 0.08910, -0.02670 ] + - [ -8.4998, -0.63190, 0.08870, -0.02870 ] + - [ -8.2500, -0.60190, 0.08790, -0.03200 ] + - [ -8.0002, -0.57180, 0.08750, -0.03450 ] + - [ -7.7498, -0.54240, 0.08730, -0.03670 ] + - [ -7.5000, -0.50980, 0.08680, -0.03990 ] + - [ -7.2502, -0.47670, 0.08640, -0.04300 ] + - [ -6.9998, -0.44540, 0.08620, -0.04530 ] + - [ -6.7500, -0.41420, 0.08600, -0.04760 ] + - [ -6.5002, -0.37910, 0.08560, -0.05100 ] + - [ -6.2498, -0.34600, 0.08530, -0.05380 ] + - [ -6.0000, -0.31440, 0.08520, -0.05600 ] + - [ -5.7502, -0.28170, 0.08500, -0.05860 ] + - [ -5.4998, -0.24610, 0.08470, -0.06190 ] + - [ -5.2500, -0.21330, 0.08460, -0.06440 ] + - [ -5.0002, -0.18270, 0.08450, -0.06630 ] + - [ -4.7498, -0.14940, 0.08430, -0.06880 ] + - [ -4.5000, -0.11580, 0.08420, -0.07150 ] + - [ -4.2502, -0.08370, 0.08400, -0.07370 ] + - [ -3.9998, -0.05290, 0.08400, -0.07560 ] + - [ -3.7500, -0.02250, 0.08390, -0.07740 ] + - [ -3.5002, 0.00890, 0.08380, -0.07930 ] + - [ -3.2498, 0.03920, 0.08380, -0.08110 ] + - [ -3.0000, 0.06860, 0.08380, -0.08260 ] + - [ -2.7502, 0.09740, 0.08380, -0.08380 ] + - [ -2.4998, 0.12600, 0.08380, -0.08520 ] + - [ -2.2500, 0.15550, 0.08380, -0.08670 ] + - [ -2.0002, 0.18530, 0.08380, -0.08830 ] + - [ -1.7498, 0.21460, 0.08370, -0.08970 ] + - [ -1.5000, 0.24300, 0.08370, -0.09100 ] + - [ -1.2502, 0.27130, 0.08380, -0.09210 ] + - [ -0.9998, 0.30060, 0.08380, -0.09360 ] + - [ -0.7500, 0.32950, 0.08380, -0.09490 ] + - [ -0.5002, 0.35780, 0.08380, -0.09610 ] + - [ -0.2498, 0.38570, 0.08380, -0.09720 ] + - [ 0.0000, 0.41350, 0.08380, -0.09830 ] + - [ 0.2298, 0.44250, 0.08390, -0.09950 ] + - [ 0.4698, 0.47150, 0.08390, -0.10080 ] + - [ 0.7002, 0.50030, 0.08390, -0.10190 ] + - [ 0.9402, 0.52860, 0.08400, -0.10290 ] + - [ 1.1700, 0.55670, 0.08400, -0.10400 ] + - [ 1.3997, 0.58500, 0.08410, -0.10500 ] + - [ 1.6398, 0.61350, 0.08410, -0.10610 ] + - [ 1.8701, 0.64170, 0.08420, -0.10720 ] + - [ 2.1102, 0.66970, 0.08420, -0.10820 ] + - [ 2.3400, 0.69750, 0.08430, -0.10910 ] + - [ 2.5697, 0.72510, 0.08430, -0.11000 ] + - [ 2.8098, 0.75280, 0.08440, -0.11090 ] + - [ 3.0401, 0.78070, 0.08450, -0.11190 ] + - [ 3.2802, 0.80830, 0.08460, -0.11280 ] + - [ 3.5099, 0.83580, 0.08460, -0.11370 ] + - [ 3.7403, 0.86310, 0.08470, -0.11460 ] + - [ 3.9798, 0.89020, 0.08470, -0.11530 ] + - [ 4.2101, 0.91730, 0.08480, -0.11610 ] + - [ 4.4502, 0.94440, 0.08490, -0.11700 ] + - [ 4.6799, 0.97130, 0.08500, -0.11780 ] + - [ 4.9102, 0.99810, 0.08510, -0.11850 ] + - [ 5.1497, 1.02490, 0.08520, -0.11920 ] + - [ 5.3801, 1.05150, 0.08530, -0.11990 ] + - [ 5.6201, 1.07790, 0.08530, -0.12060 ] + - [ 5.8499, 1.10410, 0.08540, -0.12120 ] + - [ 6.0802, 1.13020, 0.08560, -0.12180 ] + - [ 6.3197, 1.15600, 0.08570, -0.12240 ] + - [ 6.5501, 1.18180, 0.08580, -0.12300 ] + - [ 6.7901, 1.20760, 0.08590, -0.12350 ] + - [ 7.0199, 1.23340, 0.08600, -0.12400 ] + - [ 7.2502, 1.25890, 0.08610, -0.12450 ] + - [ 7.4903, 1.28410, 0.08620, -0.12500 ] + - [ 7.7200, 1.30880, 0.08640, -0.12540 ] + - [ 7.9601, 1.33310, 0.08650, -0.12570 ] + - [ 8.1899, 1.35700, 0.08670, -0.12590 ] + - [ 8.4202, 1.38100, 0.08690, -0.12620 ] + - [ 8.6603, 1.40540, 0.08700, -0.12650 ] + - [ 8.8900, 1.42950, 0.08710, -0.12670 ] + - [ 9.1198, 1.45310, 0.08730, -0.12700 ] + - [ 9.8801, 1.51540, 0.08790, -0.12650 ] + - [ 10.6398, 1.57490, 0.08860, -0.12560 ] + - [ 11.4001, 1.61510, 0.08950, -0.12140 ] + - [ 12.1501, 1.64430, 0.09120, -0.11630 ] + - [ 12.9099, 1.68240, 0.09300, -0.11330 ] + - [ 13.6702, 1.71460, 0.09540, -0.11070 ] + - [ 14.4202, 1.73620, 0.09890, -0.10800 ] + - [ 15.1799, 1.76270, 0.10240, -0.10630 ] + - [ 15.9403, 1.77060, 0.10760, -0.10420 ] + - [ 16.6903, 1.76390, 0.11440, -0.10250 ] + - [ 17.4500, 1.76040, 0.12110, -0.10130 ] + - [ 18.2097, 1.72510, 0.13100, -0.10010 ] + - [ 18.9701, 1.70350, 0.13990, -0.09980 ] + - [ 19.7201, 1.67840, 0.14920, -0.10010 ] + - [ 20.4798, 1.65050, 0.15910, -0.10160 ] + - [ 21.2401, 1.62270, 0.16910, -0.10360 ] + - [ 21.9901, 1.60670, 0.17780, -0.10640 ] + - [ 22.7499, 1.59720, 0.18580, -0.10990 ] + - [ 23.5102, 1.58920, 0.19370, -0.11360 ] + - [ 24.2602, 1.58150, 0.20140, -0.11800 ] + - [ 25.0199, 1.55630, 0.21350, -0.12490 ] + - [ 25.7802, 1.52720, 0.22670, -0.13250 ] + - [ 26.5302, 1.49820, 0.23990, -0.14000 ] + - [ 27.2900, 1.46910, 0.25310, -0.14760 ] + - [ 28.0497, 1.44010, 0.26630, -0.15510 ] + - [ 28.8100, 1.41100, 0.27950, -0.16270 ] + - [ 29.5600, 1.38200, 0.29270, -0.17030 ] + - [ 30.3198, 1.36220, 0.30780, -0.17400 ] + - [ 31.0801, 1.34240, 0.32300, -0.17770 ] + - [ 31.8301, 1.32250, 0.33810, -0.18150 ] + - [ 32.5898, 1.30270, 0.35320, -0.18520 ] + - [ 33.3502, 1.28290, 0.36840, -0.18890 ] + - [ 34.1002, 1.26310, 0.38350, -0.19260 ] + - [ 34.8599, 1.24330, 0.39870, -0.19640 ] + - [ 35.6202, 1.22340, 0.41380, -0.20010 ] + - [ 36.3800, 1.20360, 0.42890, -0.20390 ] + - [ 37.1300, 1.18380, 0.44410, -0.20760 ] + - [ 37.8903, 1.16400, 0.45920, -0.21130 ] + - [ 38.6500, 1.14420, 0.47430, -0.21500 ] + - [ 39.4000, 1.12430, 0.48950, -0.21880 ] + - [ 40.1598, 1.10640, 0.50520, -0.22180 ] + - [ 40.9201, 1.09050, 0.52140, -0.22420 ] + - [ 41.6701, 1.07450, 0.53760, -0.22660 ] + - [ 42.4298, 1.05860, 0.55380, -0.22890 ] + - [ 43.1901, 1.04260, 0.57010, -0.23130 ] + - [ 43.9401, 1.02670, 0.58630, -0.23370 ] + - [ 44.6999, 1.01070, 0.60250, -0.23610 ] + - [ 45.4602, 0.99480, 0.61880, -0.23840 ] + - [ 46.2199, 0.97880, 0.63500, -0.24080 ] + - [ 46.9699, 0.96280, 0.65120, -0.24320 ] + - [ 47.7302, 0.94690, 0.66750, -0.24550 ] + - [ 48.4900, 0.93090, 0.68370, -0.24790 ] + - [ 49.2400, 0.91500, 0.69990, -0.25030 ] + - [ 49.9997, 0.89900, 0.71610, -0.25270 ] + - [ 60.0001, 0.68360, 0.92460, -0.28330 ] + - [ 70.0000, 0.45560, 1.09850, -0.31560 ] + - [ 79.9998, 0.22190, 1.21820, -0.34820 ] + - [ 90.0002, 0.00000, 1.27070, -0.37730 ] + - [ 100.0000, -0.15530, 1.21820, -0.38770 ] + - [ 109.9999, -0.31890, 1.09850, -0.38650 ] + - [ 120.0003, -0.47840, 0.92460, -0.38060 ] + - [ 130.0001, -0.62930, 0.71610, -0.38030 ] + - [ 139.9999, -0.78010, 0.49700, -0.40320 ] + - [ 149.9998, -0.96740, 0.29270, -0.48540 ] + - [ 160.0002, -0.88370, 0.12680, -0.53250 ] + - [ 170.0000, -0.44180, 0.08440, -0.39060 ] + - [ 179.9660, 0.00000, 0.08440, 0.00000 ] + - name : FFA-W3-211 # + relative_thickness : 0.211 # + data: # alpha c_l c_d c_m + - [ -179.9087, 0.00000, 0.02464, 0.00000 ] + - [ -177.7143, 0.05403, 0.02534, 0.09143 ] + - [ -175.4286, 0.10805, 0.02742, 0.18286 ] + - [ -173.1429, 0.16208, 0.03088, 0.27429 ] + - [ -170.8572, 0.21610, 0.03570, 0.36571 ] + - [ -168.5716, 0.27013, 0.05599, 0.39192 ] + - [ -166.2857, 0.32415, 0.08143, 0.37898 ] + - [ -164.0000, 0.37818, 0.11112, 0.36605 ] + - [ -161.7145, 0.43220, 0.14485, 0.35312 ] + - [ -159.4284, 0.48623, 0.18242, 0.34768 ] + - [ -157.1428, 0.54025, 0.22359, 0.36471 ] + - [ -154.8573, 0.59428, 0.26810, 0.38175 ] + - [ -152.5714, 0.64830, 0.31566, 0.39878 ] + - [ -150.2857, 0.70233, 0.36597, 0.41581 ] + - [ -148.0000, 0.75635, 0.41871, 0.41955 ] + - [ -143.8571, 0.73188, 0.51941, 0.42287 ] + - [ -139.7143, 0.70655, 0.62488, 0.42632 ] + - [ -135.5714, 0.67760, 0.73293, 0.43163 ] + - [ -131.4286, 0.64333, 0.84130, 0.43694 ] + - [ -127.2857, 0.60277, 0.94773, 0.44389 ] + - [ -123.1429, 0.55550, 1.05001, 0.45171 ] + - [ -119.0000, 0.50156, 1.14600, 0.45897 ] + - [ -114.8571, 0.44131, 1.23371, 0.46448 ] + - [ -110.7143, 0.37542, 1.31129, 0.46998 ] + - [ -106.5714, 0.30482, 1.37714, 0.47096 ] + - [ -102.4286, 0.23063, 1.42988, 0.47101 ] + - [ -98.2857, 0.15413, 1.46842, 0.46824 ] + - [ -94.1429, 0.07675, 1.49196, 0.46149 ] + - [ -90.0000, 0.00000, 1.50000, 0.45474 ] + - [ -85.8571, -0.07675, 1.49196, 0.44026 ] + - [ -81.7143, -0.15413, 1.46842, 0.42578 ] + - [ -77.5714, -0.23063, 1.42988, 0.40821 ] + - [ -73.4286, -0.30482, 1.37714, 0.38846 ] + - [ -69.2857, -0.37542, 1.31129, 0.36815 ] + - [ -65.1429, -0.44131, 1.23371, 0.34519 ] + - [ -61.0000, -0.50156, 1.14600, 0.32223 ] + - [ -56.8571, -0.55550, 1.05001, 0.29864 ] + - [ -52.7143, -0.60277, 0.94773, 0.27486 ] + - [ -48.5714, -0.64333, 0.84130, 0.25128 ] + - [ -44.4286, -0.67760, 0.73293, 0.22810 ] + - [ -40.2857, -0.70655, 0.62488, 0.20491 ] + - [ -36.1429, -0.73188, 0.51941, 0.15416 ] + - [ -32.0000, -0.75635, 0.41871, 0.10137 ] + - [ -28.0000, -0.85636, 0.28691, 0.06527 ] + - [ -24.0000, -1.18292, 0.13960, 0.01647 ] + - [ -20.0000, -1.23596, 0.08345, -0.00352 ] + - [ -18.0000, -1.22536, 0.06509, -0.00672 ] + - [ -16.0000, -1.20476, 0.04888, -0.00881 ] + - [ -14.0000, -1.18332, 0.03417, -0.01101 ] + - [ -12.0000, -1.10093, 0.02132, -0.02269 ] + - [ -10.0000, -0.88209, 0.01386, -0.04397 ] + - [ -8.0000, -0.62981, 0.01075, -0.05756 ] + - [ -6.0000, -0.37670, 0.00882, -0.06747 ] + - [ -4.0000, -0.12177, 0.00702, -0.07680 ] + - [ -2.0000, 0.12810, 0.00663, -0.08283 ] + - [ -1.0000, 0.25192, 0.00664, -0.08534 ] + - [ 0.0000, 0.37535, 0.00670, -0.08777 ] + - [ 1.0000, 0.49828, 0.00681, -0.09011 ] + - [ 2.0000, 0.62052, 0.00698, -0.09234 ] + - [ 3.0000, 0.74200, 0.00720, -0.09447 ] + - [ 4.0000, 0.86238, 0.00751, -0.09646 ] + - [ 5.0000, 0.98114, 0.00796, -0.09828 ] + - [ 6.0000, 1.09662, 0.00872, -0.09977 ] + - [ 7.0000, 1.20904, 0.00968, -0.10095 ] + - [ 8.0000, 1.31680, 0.01097, -0.10163 ] + - [ 9.0000, 1.42209, 0.01227, -0.10207 ] + - [ 10.0000, 1.52361, 0.01369, -0.10213 ] + - [ 11.0000, 1.61988, 0.01529, -0.10174 ] + - [ 12.0000, 1.70937, 0.01717, -0.10087 ] + - [ 13.0000, 1.78681, 0.01974, -0.09936 ] + - [ 14.0000, 1.84290, 0.02368, -0.09720 ] + - [ 15.0000, 1.85313, 0.03094, -0.09410 ] + - [ 16.0000, 1.80951, 0.04303, -0.09144 ] + - [ 18.0000, 1.66033, 0.07730, -0.09242 ] + - [ 20.0000, 1.56152, 0.11202, -0.09871 ] + - [ 24.0000, 1.43327, 0.18408, -0.11770 ] + - [ 28.0000, 1.29062, 0.27589, -0.14566 ] + - [ 32.0000, 1.08050, 0.41871, -0.18266 ] + - [ 36.1429, 1.04554, 0.51941, -0.20913 ] + - [ 40.2857, 1.00936, 0.62488, -0.23534 ] + - [ 44.4286, 0.96801, 0.73293, -0.25784 ] + - [ 48.5714, 0.91904, 0.84130, -0.28035 ] + - [ 52.7143, 0.86109, 0.94773, -0.30163 ] + - [ 56.8571, 0.79357, 1.05001, -0.32226 ] + - [ 61.0000, 0.71651, 1.14600, -0.34247 ] + - [ 65.1429, 0.63044, 1.23371, -0.36135 ] + - [ 69.2857, 0.53632, 1.31129, -0.38024 ] + - [ 73.4286, 0.43546, 1.37714, -0.39704 ] + - [ 77.5714, 0.32947, 1.42988, -0.41341 ] + - [ 81.7143, 0.22019, 1.46842, -0.42844 ] + - [ 85.8571, 0.10965, 1.49196, -0.44159 ] + - [ 90.0000, 0.00000, 1.50000, -0.45474 ] + - [ 94.1429, -0.07675, 1.49196, -0.46149 ] + - [ 98.2857, -0.15413, 1.46842, -0.46824 ] + - [ 102.4286, -0.23063, 1.42988, -0.47101 ] + - [ 106.5714, -0.30482, 1.37714, -0.47096 ] + - [ 110.7143, -0.37542, 1.31129, -0.46998 ] + - [ 114.8571, -0.44131, 1.23371, -0.46448 ] + - [ 119.0000, -0.50156, 1.14600, -0.45897 ] + - [ 123.1429, -0.55550, 1.05001, -0.45171 ] + - [ 127.2857, -0.60277, 0.94773, -0.44389 ] + - [ 131.4286, -0.64333, 0.84130, -0.43694 ] + - [ 135.5714, -0.67760, 0.73293, -0.43163 ] + - [ 139.7143, -0.70655, 0.62488, -0.42632 ] + - [ 143.8571, -0.73188, 0.51941, -0.42287 ] + - [ 148.0000, -0.75635, 0.41871, -0.41955 ] + - [ 150.2857, -0.70233, 0.36597, -0.41581 ] + - [ 152.5714, -0.64830, 0.31566, -0.39878 ] + - [ 154.8571, -0.59428, 0.26810, -0.38175 ] + - [ 157.1429, -0.54025, 0.22359, -0.36471 ] + - [ 159.4286, -0.48623, 0.18242, -0.34768 ] + - [ 161.7143, -0.43220, 0.14485, -0.37026 ] + - [ 164.0000, -0.37818, 0.11112, -0.40605 ] + - [ 166.2857, -0.32415, 0.08143, -0.44184 ] + - [ 168.5714, -0.27013, 0.05599, -0.47763 ] + - [ 170.8571, -0.21610, 0.03570, -0.45714 ] + - [ 173.1429, -0.16208, 0.03088, -0.34286 ] + - [ 175.4286, -0.10805, 0.02742, -0.22857 ] + - [ 177.7143, -0.05403, 0.02534, -0.11429 ] + - [ 179.9087, 0.00000, 0.02464, 0.00000 ] + - name : FFA-W3-241 # + relative_thickness : 0.241 # + data: # alpha c_l c_d c_m + - [ -179.9087, 0.00000, 0.01178, 0.00000 ] + - [ -177.7143, 0.05818, 0.01248, 0.09143 ] + - [ -175.4286, 0.11636, 0.01460, 0.18286 ] + - [ -173.1429, 0.17453, 0.01811, 0.27429 ] + - [ -170.8572, 0.23271, 0.02300, 0.36571 ] + - [ -168.5716, 0.29089, 0.02922, 0.39568 ] + - [ -166.2857, 0.34907, 0.05382, 0.38876 ] + - [ -164.0000, 0.40725, 0.08379, 0.38184 ] + - [ -161.7145, 0.46542, 0.11786, 0.37492 ] + - [ -159.4284, 0.52360, 0.15581, 0.37408 ] + - [ -157.1428, 0.58178, 0.19740, 0.39148 ] + - [ -154.8573, 0.63996, 0.24237, 0.40888 ] + - [ -152.5714, 0.69814, 0.29043, 0.42628 ] + - [ -150.2857, 0.75631, 0.34128, 0.44368 ] + - [ -148.0000, 0.81449, 0.39460, 0.44537 ] + - [ -143.8571, 0.77925, 0.49645, 0.44436 ] + - [ -139.7143, 0.74511, 0.60319, 0.44360 ] + - [ -135.5714, 0.70881, 0.71263, 0.44609 ] + - [ -131.4286, 0.66835, 0.82249, 0.44858 ] + - [ -127.2857, 0.62253, 0.93051, 0.45370 ] + - [ -123.1429, 0.57080, 1.03447, 0.46020 ] + - [ -119.0000, 0.51307, 1.13222, 0.46633 ] + - [ -114.8571, 0.44965, 1.22176, 0.47130 ] + - [ -110.7143, 0.38115, 1.30123, 0.47627 ] + - [ -106.5714, 0.30846, 1.36903, 0.47705 ] + - [ -102.4286, 0.23266, 1.42376, 0.47695 ] + - [ -98.2857, 0.15503, 1.46433, 0.47409 ] + - [ -94.1429, 0.07698, 1.48990, 0.46732 ] + - [ -90.0000, 0.00000, 1.50000, 0.46055 ] + - [ -85.8571, -0.07698, 1.48990, 0.44509 ] + - [ -81.7143, -0.15503, 1.46433, 0.42964 ] + - [ -77.5714, -0.23266, 1.42376, 0.41125 ] + - [ -73.4286, -0.30846, 1.36903, 0.39081 ] + - [ -69.2857, -0.38115, 1.30123, 0.36988 ] + - [ -65.1429, -0.44965, 1.22176, 0.34663 ] + - [ -61.0000, -0.51307, 1.13222, 0.32339 ] + - [ -56.8571, -0.57080, 1.03447, 0.29984 ] + - [ -52.7143, -0.62253, 0.93051, 0.27618 ] + - [ -48.5714, -0.66835, 0.82249, 0.25280 ] + - [ -44.4286, -0.70881, 0.71263, 0.22992 ] + - [ -40.2857, -0.74511, 0.60319, 0.20705 ] + - [ -36.1429, -0.77925, 0.49645, 0.14561 ] + - [ -32.0000, -0.81449, 0.39460, 0.08131 ] + - [ -28.0000, -1.07781, 0.22252, 0.04592 ] + - [ -24.0000, -1.12692, 0.15159, 0.01901 ] + - [ -20.0000, -1.14480, 0.09699, 0.00063 ] + - [ -18.0000, -1.12797, 0.07744, -0.00342 ] + - [ -16.0000, -1.09392, 0.06122, -0.00587 ] + - [ -14.0000, -1.05961, 0.04667, -0.00652 ] + - [ -12.0000, -1.03121, 0.03302, -0.00755 ] + - [ -10.0000, -0.93706, 0.02027, -0.02243 ] + - [ -8.0000, -0.67380, 0.01168, -0.05583 ] + - [ -6.0000, -0.40391, 0.00918, -0.07159 ] + - [ -4.0000, -0.14226, 0.00839, -0.08123 ] + - [ -2.0000, 0.11580, 0.00810, -0.08892 ] + - [ -1.0000, 0.24382, 0.00808, -0.09235 ] + - [ 0.0000, 0.37113, 0.00813, -0.09556 ] + - [ 1.0000, 0.49766, 0.00824, -0.09857 ] + - [ 2.0000, 0.62334, 0.00842, -0.10139 ] + - [ 3.0000, 0.74798, 0.00867, -0.10403 ] + - [ 4.0000, 0.87137, 0.00901, -0.10645 ] + - [ 5.0000, 0.99320, 0.00945, -0.10863 ] + - [ 6.0000, 1.11325, 0.00998, -0.11057 ] + - [ 7.0000, 1.23037, 0.01070, -0.11214 ] + - [ 8.0000, 1.34496, 0.01153, -0.11337 ] + - [ 9.0000, 1.45407, 0.01269, -0.11396 ] + - [ 10.0000, 1.55911, 0.01396, -0.11403 ] + - [ 11.0000, 1.65779, 0.01545, -0.11336 ] + - [ 12.0000, 1.74834, 0.01724, -0.11187 ] + - [ 13.0000, 1.82666, 0.01961, -0.10935 ] + - [ 14.0000, 1.88831, 0.02293, -0.10606 ] + - [ 15.0000, 1.92579, 0.02795, -0.10238 ] + - [ 16.0000, 1.92722, 0.03609, -0.09887 ] + - [ 18.0000, 1.80055, 0.06534, -0.09497 ] + - [ 20.0000, 1.63088, 0.10459, -0.09996 ] + - [ 24.0000, 1.43345, 0.19148, -0.12589 ] + - [ 28.0000, 1.28805, 0.28629, -0.15453 ] + - [ 32.0000, 1.16356, 0.39460, -0.18396 ] + - [ 36.1429, 1.11321, 0.49645, -0.21099 ] + - [ 40.2857, 1.06444, 0.60319, -0.23768 ] + - [ 44.4286, 1.01259, 0.71263, -0.25992 ] + - [ 48.5714, 0.95478, 0.82249, -0.28216 ] + - [ 52.7143, 0.88932, 0.93051, -0.30323 ] + - [ 56.8571, 0.81542, 1.03447, -0.32368 ] + - [ 61.0000, 0.73296, 1.13222, -0.34380 ] + - [ 65.1429, 0.64236, 1.22176, -0.36292 ] + - [ 69.2857, 0.54450, 1.30123, -0.38204 ] + - [ 73.4286, 0.44065, 1.36903, -0.39944 ] + - [ 77.5714, 0.33237, 1.42376, -0.41648 ] + - [ 81.7143, 0.22148, 1.46433, -0.43231 ] + - [ 85.8571, 0.10997, 1.48990, -0.44643 ] + - [ 90.0000, 0.00000, 1.50000, -0.46055 ] + - [ 94.1429, -0.07698, 1.48990, -0.46732 ] + - [ 98.2857, -0.15503, 1.46433, -0.47409 ] + - [ 102.4286, -0.23266, 1.42376, -0.47695 ] + - [ 106.5714, -0.30846, 1.36903, -0.47705 ] + - [ 110.7143, -0.38115, 1.30123, -0.47627 ] + - [ 114.8571, -0.44965, 1.22176, -0.47130 ] + - [ 119.0000, -0.51307, 1.13222, -0.46633 ] + - [ 123.1429, -0.57080, 1.03447, -0.46020 ] + - [ 127.2857, -0.62253, 0.93051, -0.45370 ] + - [ 131.4286, -0.66835, 0.82249, -0.44858 ] + - [ 135.5714, -0.70881, 0.71263, -0.44609 ] + - [ 139.7143, -0.74511, 0.60319, -0.44360 ] + - [ 143.8571, -0.77925, 0.49645, -0.44436 ] + - [ 148.0000, -0.81449, 0.39460, -0.44537 ] + - [ 150.2857, -0.75631, 0.34128, -0.44368 ] + - [ 152.5714, -0.69814, 0.29043, -0.42628 ] + - [ 154.8571, -0.63996, 0.24237, -0.40888 ] + - [ 157.1429, -0.58178, 0.19740, -0.39148 ] + - [ 159.4286, -0.52360, 0.15581, -0.37408 ] + - [ 161.7143, -0.46542, 0.11786, -0.39207 ] + - [ 164.0000, -0.40725, 0.08379, -0.42184 ] + - [ 166.2857, -0.34907, 0.05382, -0.45162 ] + - [ 168.5714, -0.29089, 0.02922, -0.48139 ] + - [ 170.8571, -0.23271, 0.02300, -0.45714 ] + - [ 173.1429, -0.17453, 0.01811, -0.34286 ] + - [ 175.4286, -0.11636, 0.01460, -0.22857 ] + - [ 177.7143, -0.05818, 0.01248, -0.11429 ] + - [ 179.9087, 0.00000, 0.01178, 0.00000 ] + - name : FFA-W3-270blend # + relative_thickness : 0.27 # + data: # alpha c_l c_d c_m + - [ -179.9087, 0.00000, 0.01545, 0.00000 ] + - [ -177.7143, 0.06213, 0.01611, 0.09143 ] + - [ -175.4286, 0.12426, 0.01807, 0.18286 ] + - [ -173.1429, 0.18639, 0.02133, 0.27429 ] + - [ -170.8572, 0.24852, 0.02587, 0.36571 ] + - [ -168.5716, 0.31064, 0.03289, 0.39874 ] + - [ -166.2857, 0.37277, 0.05681, 0.39672 ] + - [ -164.0000, 0.43490, 0.08471, 0.39470 ] + - [ -161.7145, 0.49703, 0.11643, 0.39268 ] + - [ -159.4284, 0.55916, 0.15176, 0.39544 ] + - [ -157.1428, 0.62129, 0.19048, 0.41254 ] + - [ -154.8573, 0.68342, 0.23234, 0.42964 ] + - [ -152.5714, 0.74555, 0.27708, 0.44674 ] + - [ -150.2857, 0.80768, 0.32441, 0.46384 ] + - [ -148.0000, 0.86981, 0.37404, 0.46186 ] + - [ -143.8571, 0.81660, 0.46882, 0.45335 ] + - [ -139.7143, 0.76812, 0.56814, 0.44523 ] + - [ -135.5714, 0.72040, 0.66995, 0.44237 ] + - [ -131.4286, 0.67095, 0.77214, 0.43951 ] + - [ -127.2857, 0.61828, 0.87258, 0.44072 ] + - [ -123.1429, 0.56158, 0.96921, 0.44407 ] + - [ -119.0000, 0.50057, 1.06002, 0.44739 ] + - [ -114.8571, 0.43540, 1.14315, 0.45063 ] + - [ -110.7143, 0.36655, 1.21688, 0.45387 ] + - [ -106.5714, 0.29475, 1.27969, 0.45377 ] + - [ -102.4286, 0.22098, 1.33030, 0.45298 ] + - [ -98.2857, 0.14639, 1.36768, 0.44973 ] + - [ -94.1429, 0.07227, 1.39107, 0.44302 ] + - [ -90.0000, 0.00000, 1.40000, 0.43630 ] + - [ -85.8571, -0.07227, 1.39107, 0.42180 ] + - [ -81.7143, -0.14639, 1.36768, 0.40730 ] + - [ -77.5714, -0.22098, 1.33030, 0.39020 ] + - [ -73.4286, -0.29475, 1.27969, 0.37125 ] + - [ -69.2857, -0.36655, 1.21688, 0.35190 ] + - [ -65.1429, -0.43540, 1.14315, 0.33068 ] + - [ -61.0000, -0.50057, 1.06002, 0.30945 ] + - [ -56.8571, -0.56158, 0.96921, 0.28815 ] + - [ -52.7143, -0.61828, 0.87258, 0.26684 ] + - [ -48.5714, -0.67095, 0.77214, 0.24576 ] + - [ -44.4286, -0.72040, 0.66995, 0.22512 ] + - [ -40.2857, -0.76812, 0.56814, 0.20447 ] + - [ -36.1429, -0.81660, 0.46882, 0.13957 ] + - [ -32.0000, -0.86981, 0.37404, 0.07138 ] + - [ -28.0000, -1.09837, 0.21880, 0.04400 ] + - [ -24.0000, -1.08339, 0.15982, 0.02166 ] + - [ -20.0000, -1.06990, 0.10744, 0.00422 ] + - [ -18.0000, -1.05454, 0.08690, -0.00035 ] + - [ -16.0000, -1.03432, 0.06844, -0.00334 ] + - [ -14.0000, -1.08360, 0.04733, -0.00283 ] + - [ -12.0000, -1.09489, 0.03085, -0.00556 ] + - [ -10.0000, -0.92665, 0.01984, -0.02952 ] + - [ -8.0000, -0.69676, 0.01439, -0.04822 ] + - [ -6.0000, -0.43628, 0.01155, -0.06483 ] + - [ -4.0000, -0.16252, 0.01026, -0.07919 ] + - [ -2.0000, 0.10709, 0.00976, -0.09041 ] + - [ -1.0000, 0.23993, 0.00967, -0.09517 ] + - [ 0.0000, 0.37158, 0.00968, -0.09953 ] + - [ 1.0000, 0.50210, 0.00976, -0.10355 ] + - [ 2.0000, 0.63139, 0.00993, -0.10725 ] + - [ 3.0000, 0.75951, 0.01016, -0.11068 ] + - [ 4.0000, 0.88638, 0.01045, -0.11385 ] + - [ 5.0000, 1.01172, 0.01082, -0.11673 ] + - [ 6.0000, 1.13430, 0.01140, -0.11923 ] + - [ 7.0000, 1.25536, 0.01198, -0.12145 ] + - [ 8.0000, 1.37379, 0.01267, -0.12328 ] + - [ 9.0000, 1.48841, 0.01353, -0.12460 ] + - [ 10.0000, 1.59782, 0.01460, -0.12526 ] + - [ 11.0000, 1.70005, 0.01597, -0.12505 ] + - [ 12.0000, 1.79190, 0.01777, -0.12370 ] + - [ 13.0000, 1.86782, 0.02035, -0.12093 ] + - [ 14.0000, 1.92687, 0.02385, -0.11725 ] + - [ 15.0000, 1.90901, 0.03236, -0.10931 ] + - [ 16.0000, 1.88548, 0.04259, -0.10525 ] + - [ 18.0000, 1.72106, 0.07672, -0.10292 ] + - [ 20.0000, 1.54737, 0.11914, -0.11017 ] + - [ 24.0000, 1.37176, 0.20189, -0.13431 ] + - [ 28.0000, 1.33611, 0.27981, -0.15777 ] + - [ 32.0000, 1.24258, 0.37404, -0.18432 ] + - [ 36.1429, 1.16657, 0.46882, -0.21002 ] + - [ 40.2857, 1.09731, 0.56814, -0.23531 ] + - [ 44.4286, 1.02914, 0.66995, -0.25508 ] + - [ 48.5714, 0.95850, 0.77214, -0.27485 ] + - [ 52.7143, 0.88325, 0.87258, -0.29346 ] + - [ 56.8571, 0.80225, 0.96921, -0.31145 ] + - [ 61.0000, 0.71510, 1.06002, -0.32925 ] + - [ 65.1429, 0.62200, 1.14315, -0.34641 ] + - [ 69.2857, 0.52364, 1.21688, -0.36357 ] + - [ 73.4286, 0.42107, 1.27969, -0.37949 ] + - [ 77.5714, 0.31569, 1.33030, -0.39517 ] + - [ 81.7143, 0.20913, 1.36768, -0.40983 ] + - [ 85.8571, 0.10324, 1.39107, -0.42306 ] + - [ 90.0000, 0.00000, 1.40000, -0.43630 ] + - [ 94.1429, -0.07227, 1.39107, -0.44302 ] + - [ 98.2857, -0.14639, 1.36768, -0.44973 ] + - [ 102.4286, -0.22098, 1.33030, -0.45298 ] + - [ 106.5714, -0.29475, 1.27969, -0.45377 ] + - [ 110.7143, -0.36655, 1.21688, -0.45387 ] + - [ 114.8571, -0.43540, 1.14315, -0.45063 ] + - [ 119.0000, -0.50057, 1.06002, -0.44739 ] + - [ 123.1429, -0.56158, 0.96921, -0.44407 ] + - [ 127.2857, -0.61828, 0.87258, -0.44072 ] + - [ 131.4286, -0.67095, 0.77214, -0.43951 ] + - [ 135.5714, -0.72040, 0.66995, -0.44237 ] + - [ 139.7143, -0.76812, 0.56814, -0.44523 ] + - [ 143.8571, -0.81660, 0.46882, -0.45335 ] + - [ 148.0000, -0.86981, 0.37404, -0.46186 ] + - [ 150.2857, -0.80768, 0.32441, -0.46384 ] + - [ 152.5714, -0.74555, 0.27708, -0.44674 ] + - [ 154.8571, -0.68342, 0.23234, -0.42964 ] + - [ 157.1429, -0.62129, 0.19048, -0.41254 ] + - [ 159.4286, -0.55916, 0.15176, -0.39544 ] + - [ 161.7143, -0.49703, 0.11643, -0.40982 ] + - [ 164.0000, -0.43490, 0.08471, -0.43470 ] + - [ 166.2857, -0.37277, 0.05681, -0.45958 ] + - [ 168.5714, -0.31064, 0.03289, -0.48445 ] + - [ 170.8571, -0.24852, 0.02587, -0.45714 ] + - [ 173.1429, -0.18639, 0.02133, -0.34286 ] + - [ 175.4286, -0.12426, 0.01807, -0.22857 ] + - [ 177.7143, -0.06213, 0.01611, -0.11429 ] + - [ 179.9087, 0.00000, 0.01545, 0.00000 ] + - name : FFA-W3-301 # + relative_thickness : 0.301 # + data: # alpha c_l c_d c_m + - [ -179.9087, 0.00000, 0.02454, 0.00000 ] + - [ -177.7143, 0.06508, 0.02514, 0.09143 ] + - [ -175.4286, 0.13016, 0.02694, 0.18286 ] + - [ -173.1429, 0.19525, 0.02993, 0.27429 ] + - [ -170.8572, 0.26033, 0.03408, 0.36571 ] + - [ -168.5716, 0.32541, 0.03938, 0.40085 ] + - [ -166.2857, 0.39049, 0.05910, 0.40220 ] + - [ -164.0000, 0.45557, 0.08495, 0.40356 ] + - [ -161.7145, 0.52066, 0.11433, 0.40492 ] + - [ -159.4284, 0.58574, 0.14704, 0.41010 ] + - [ -157.1428, 0.65082, 0.18290, 0.42678 ] + - [ -154.8573, 0.71590, 0.22166, 0.44345 ] + - [ -152.5714, 0.78098, 0.26309, 0.46013 ] + - [ -150.2857, 0.84607, 0.30692, 0.47680 ] + - [ -148.0000, 0.91115, 0.35287, 0.47162 ] + - [ -143.8571, 0.84257, 0.44061, 0.45656 ] + - [ -139.7143, 0.78187, 0.53255, 0.44202 ] + - [ -135.5714, 0.72448, 0.62677, 0.43452 ] + - [ -131.4286, 0.66755, 0.72131, 0.42701 ] + - [ -127.2857, 0.60928, 0.81421, 0.42483 ] + - [ -123.1429, 0.54868, 0.90355, 0.42544 ] + - [ -119.0000, 0.48530, 0.98748, 0.42634 ] + - [ -114.8571, 0.41915, 1.06425, 0.42813 ] + - [ -110.7143, 0.35056, 1.13227, 0.42992 ] + - [ -106.5714, 0.28017, 1.19015, 0.42916 ] + - [ -102.4286, 0.20881, 1.23669, 0.42788 ] + - [ -98.2857, 0.13754, 1.27093, 0.42444 ] + - [ -94.1429, 0.06751, 1.29218, 0.41794 ] + - [ -90.0000, 0.00000, 1.30000, 0.41144 ] + - [ -85.8571, -0.06751, 1.29218, 0.39804 ] + - [ -81.7143, -0.13754, 1.27093, 0.38464 ] + - [ -77.5714, -0.20881, 1.23669, 0.36892 ] + - [ -73.4286, -0.28017, 1.19015, 0.35157 ] + - [ -69.2857, -0.35056, 1.13227, 0.33391 ] + - [ -65.1429, -0.41915, 1.06425, 0.31474 ] + - [ -61.0000, -0.48530, 0.98748, 0.29557 ] + - [ -56.8571, -0.54868, 0.90355, 0.27653 ] + - [ -52.7143, -0.60928, 0.81421, 0.25754 ] + - [ -48.5714, -0.66755, 0.72131, 0.23873 ] + - [ -44.4286, -0.72448, 0.62677, 0.22027 ] + - [ -40.2857, -0.78187, 0.53255, 0.20181 ] + - [ -36.1429, -0.84257, 0.44061, 0.13644 ] + - [ -32.0000, -0.91115, 0.35287, 0.06760 ] + - [ -28.0000, -1.10349, 0.21721, 0.04231 ] + - [ -24.0000, -1.10737, 0.15629, 0.02026 ] + - [ -20.0000, -1.11815, 0.10335, 0.00407 ] + - [ -18.0000, -1.12332, 0.08180, 0.00017 ] + - [ -16.0000, -1.11865, 0.06331, -0.00167 ] + - [ -14.0000, -1.11620, 0.04718, -0.00120 ] + - [ -12.0000, -1.09588, 0.03280, -0.00463 ] + - [ -10.0000, -0.91767, 0.02351, -0.02494 ] + - [ -8.0000, -0.69311, 0.01793, -0.04304 ] + - [ -6.0000, -0.45396, 0.01431, -0.05868 ] + - [ -4.0000, -0.17779, 0.01242, -0.07601 ] + - [ -2.0000, 0.10480, 0.01160, -0.09121 ] + - [ -1.0000, 0.24383, 0.01143, -0.09763 ] + - [ 0.0000, 0.38111, 0.01138, -0.10341 ] + - [ 1.0000, 0.51660, 0.01143, -0.10861 ] + - [ 2.0000, 0.65044, 0.01156, -0.11333 ] + - [ 3.0000, 0.78267, 0.01177, -0.11762 ] + - [ 4.0000, 0.91326, 0.01204, -0.12154 ] + - [ 5.0000, 1.04207, 0.01239, -0.12510 ] + - [ 6.0000, 1.16873, 0.01283, -0.12828 ] + - [ 7.0000, 1.29296, 0.01338, -0.13104 ] + - [ 8.0000, 1.41390, 0.01406, -0.13332 ] + - [ 9.0000, 1.53088, 0.01488, -0.13503 ] + - [ 10.0000, 1.64208, 0.01592, -0.13599 ] + - [ 11.0000, 1.74568, 0.01726, -0.13605 ] + - [ 12.0000, 1.83887, 0.01908, -0.13514 ] + - [ 13.0000, 1.91764, 0.02169, -0.13322 ] + - [ 14.0000, 1.97413, 0.02572, -0.13020 ] + - [ 15.0000, 1.99916, 0.03222, -0.12641 ] + - [ 16.0000, 1.99377, 0.04157, -0.12265 ] + - [ 18.0000, 1.91720, 0.06731, -0.11675 ] + - [ 20.0000, 1.73683, 0.10526, -0.11652 ] + - [ 24.0000, 1.47321, 0.19229, -0.13790 ] + - [ 28.0000, 1.36017, 0.27449, -0.16242 ] + - [ 32.0000, 1.30164, 0.35287, -0.18463 ] + - [ 36.1429, 1.20367, 0.44061, -0.20894 ] + - [ 40.2857, 1.11695, 0.53255, -0.23276 ] + - [ 44.4286, 1.03498, 0.62677, -0.25011 ] + - [ 48.5714, 0.95364, 0.72131, -0.26746 ] + - [ 52.7143, 0.87040, 0.81421, -0.28365 ] + - [ 56.8571, 0.78383, 0.90355, -0.29923 ] + - [ 61.0000, 0.69329, 0.98748, -0.31472 ] + - [ 65.1429, 0.59878, 1.06425, -0.32988 ] + - [ 69.2857, 0.50080, 1.13227, -0.34505 ] + - [ 73.4286, 0.40024, 1.19015, -0.35942 ] + - [ 77.5714, 0.29831, 1.23669, -0.37363 ] + - [ 81.7143, 0.19648, 1.27093, -0.38702 ] + - [ 85.8571, 0.09644, 1.29218, -0.39923 ] + - [ 90.0000, 0.00000, 1.30000, -0.41144 ] + - [ 94.1429, -0.06751, 1.29218, -0.41794 ] + - [ 98.2857, -0.13754, 1.27093, -0.42444 ] + - [ 102.4286, -0.20881, 1.23669, -0.42788 ] + - [ 106.5714, -0.28017, 1.19015, -0.42916 ] + - [ 110.7143, -0.35056, 1.13227, -0.42992 ] + - [ 114.8571, -0.41915, 1.06425, -0.42813 ] + - [ 119.0000, -0.48530, 0.98748, -0.42634 ] + - [ 123.1429, -0.54868, 0.90355, -0.42544 ] + - [ 127.2857, -0.60928, 0.81421, -0.42483 ] + - [ 131.4286, -0.66755, 0.72131, -0.42701 ] + - [ 135.5714, -0.72448, 0.62677, -0.43452 ] + - [ 139.7143, -0.78187, 0.53255, -0.44202 ] + - [ 143.8571, -0.84257, 0.44061, -0.45656 ] + - [ 148.0000, -0.91115, 0.35287, -0.47162 ] + - [ 150.2857, -0.84607, 0.30692, -0.47680 ] + - [ 152.5714, -0.78098, 0.26309, -0.46013 ] + - [ 154.8571, -0.71590, 0.22166, -0.44345 ] + - [ 157.1429, -0.65082, 0.18290, -0.42678 ] + - [ 159.4286, -0.58574, 0.14704, -0.41010 ] + - [ 161.7143, -0.52066, 0.11433, -0.42206 ] + - [ 164.0000, -0.45557, 0.08495, -0.44356 ] + - [ 166.2857, -0.39049, 0.05910, -0.46506 ] + - [ 168.5714, -0.32541, 0.03938, -0.48656 ] + - [ 170.8571, -0.26033, 0.03408, -0.45714 ] + - [ 173.1429, -0.19525, 0.02993, -0.34286 ] + - [ 175.4286, -0.13016, 0.02694, -0.22857 ] + - [ 177.7143, -0.06508, 0.02514, -0.11429 ] + - [ 179.9087, 0.00000, 0.02454, 0.00000 ] + - name : FFA-W3-330blend # + relative_thickness : 0.33 # + data: # alpha c_l c_d c_m + - [ -179.9087, 0.00000, 0.03169, 0.00000 ] + - [ -177.7143, 0.06960, 0.03228, 0.09143 ] + - [ -175.4286, 0.13920, 0.03406, 0.18286 ] + - [ -173.1429, 0.20880, 0.03702, 0.27429 ] + - [ -170.8572, 0.27841, 0.04114, 0.36571 ] + - [ -168.5716, 0.34801, 0.04638, 0.40308 ] + - [ -166.2857, 0.41761, 0.05732, 0.40801 ] + - [ -164.0000, 0.48721, 0.08319, 0.41294 ] + - [ -161.7145, 0.55681, 0.11258, 0.41788 ] + - [ -159.4284, 0.62641, 0.14533, 0.42586 ] + - [ -157.1428, 0.69601, 0.18121, 0.44302 ] + - [ -154.8573, 0.76562, 0.22000, 0.46017 ] + - [ -152.5714, 0.83522, 0.26146, 0.47732 ] + - [ -150.2857, 0.90482, 0.30532, 0.49447 ] + - [ -148.0000, 0.97442, 0.35131, 0.48743 ] + - [ -143.8571, 0.89412, 0.43913, 0.46839 ] + - [ -139.7143, 0.82382, 0.53115, 0.44996 ] + - [ -135.5714, 0.75845, 0.62546, 0.43985 ] + - [ -131.4286, 0.69477, 0.72010, 0.42974 ] + - [ -127.2857, 0.63079, 0.81310, 0.42589 ] + - [ -123.1429, 0.56532, 0.90255, 0.42535 ] + - [ -119.0000, 0.49783, 0.98659, 0.42528 ] + - [ -114.8571, 0.42823, 1.06348, 0.42673 ] + - [ -110.7143, 0.35680, 1.13162, 0.42817 ] + - [ -106.5714, 0.28412, 1.18963, 0.42745 ] + - [ -102.4286, 0.21103, 1.23629, 0.42628 ] + - [ -98.2857, 0.13851, 1.27067, 0.42303 ] + - [ -94.1429, 0.06775, 1.29204, 0.41683 ] + - [ -90.0000, 0.00000, 1.30000, 0.41063 ] + - [ -85.8571, -0.06775, 1.29204, 0.39752 ] + - [ -81.7143, -0.13851, 1.27067, 0.38441 ] + - [ -77.5714, -0.21103, 1.23629, 0.36905 ] + - [ -73.4286, -0.28412, 1.18963, 0.35212 ] + - [ -69.2857, -0.35680, 1.13162, 0.33491 ] + - [ -65.1429, -0.42823, 1.06348, 0.31634 ] + - [ -61.0000, -0.49783, 0.98659, 0.29777 ] + - [ -56.8571, -0.56532, 0.90255, 0.27947 ] + - [ -52.7143, -0.63079, 0.81310, 0.26125 ] + - [ -48.5714, -0.69477, 0.72010, 0.24322 ] + - [ -44.4286, -0.75845, 0.62546, 0.22556 ] + - [ -40.2857, -0.82382, 0.53115, 0.20789 ] + - [ -36.1429, -0.89412, 0.43913, 0.13731 ] + - [ -32.0000, -0.97442, 0.35131, 0.06280 ] + - [ -28.0000, -1.16308, 0.20648, 0.03905 ] + - [ -24.0000, -1.14892, 0.15001, 0.01853 ] + - [ -20.0000, -1.09451, 0.10600, 0.00441 ] + - [ -18.0000, -1.05801, 0.08732, -0.00061 ] + - [ -16.0000, -1.02281, 0.07051, -0.00342 ] + - [ -14.0000, -0.99810, 0.05474, -0.00401 ] + - [ -12.0000, -0.98515, 0.04052, -0.00272 ] + - [ -10.0000, -0.89583, 0.02929, -0.01198 ] + - [ -8.0000, -0.67539, 0.02207, -0.03458 ] + - [ -6.0000, -0.43247, 0.01735, -0.05466 ] + - [ -4.0000, -0.15881, 0.01473, -0.07425 ] + - [ -2.0000, 0.13456, 0.01362, -0.09270 ] + - [ -1.0000, 0.28014, 0.01339, -0.10074 ] + - [ 0.0000, 0.42386, 0.01330, -0.10802 ] + - [ 1.0000, 0.56519, 0.01333, -0.11450 ] + - [ 2.0000, 0.70410, 0.01345, -0.12028 ] + - [ 3.0000, 0.84071, 0.01366, -0.12546 ] + - [ 4.0000, 0.97500, 0.01397, -0.13011 ] + - [ 5.0000, 1.10680, 0.01437, -0.13425 ] + - [ 6.0000, 1.23603, 0.01486, -0.13793 ] + - [ 7.0000, 1.36223, 0.01547, -0.14108 ] + - [ 8.0000, 1.48424, 0.01623, -0.14363 ] + - [ 9.0000, 1.60097, 0.01718, -0.14545 ] + - [ 10.0000, 1.71010, 0.01841, -0.14636 ] + - [ 11.0000, 1.80957, 0.02010, -0.14635 ] + - [ 12.0000, 1.89473, 0.02258, -0.14544 ] + - [ 13.0000, 1.95698, 0.02671, -0.14378 ] + - [ 14.0000, 1.98576, 0.03380, -0.14185 ] + - [ 15.0000, 1.99260, 0.04333, -0.14004 ] + - [ 16.0000, 1.99617, 0.05354, -0.13823 ] + - [ 18.0000, 1.96398, 0.07706, -0.13351 ] + - [ 20.0000, 1.81179, 0.11169, -0.13135 ] + - [ 24.0000, 1.56073, 0.19103, -0.14660 ] + - [ 28.0000, 1.46798, 0.27199, -0.17242 ] + - [ 32.0000, 1.39203, 0.35131, -0.19417 ] + - [ 36.1429, 1.27731, 0.43913, -0.21792 ] + - [ 40.2857, 1.17689, 0.53115, -0.24115 ] + - [ 44.4286, 1.08350, 0.62546, -0.25734 ] + - [ 48.5714, 0.99253, 0.72010, -0.27354 ] + - [ 52.7143, 0.90112, 0.81310, -0.28862 ] + - [ 56.8571, 0.80760, 0.90255, -0.30311 ] + - [ 61.0000, 0.71119, 0.98659, -0.31757 ] + - [ 65.1429, 0.61175, 1.06348, -0.33194 ] + - [ 69.2857, 0.50971, 1.13162, -0.34631 ] + - [ 73.4286, 0.40589, 1.18963, -0.36014 ] + - [ 77.5714, 0.30146, 1.23629, -0.37385 ] + - [ 81.7143, 0.19788, 1.27067, -0.38681 ] + - [ 85.8571, 0.09679, 1.29204, -0.39872 ] + - [ 90.0000, 0.00000, 1.30000, -0.41063 ] + - [ 94.1429, -0.06775, 1.29204, -0.41683 ] + - [ 98.2857, -0.13851, 1.27067, -0.42303 ] + - [ 102.4286, -0.21103, 1.23629, -0.42628 ] + - [ 106.5714, -0.28412, 1.18963, -0.42745 ] + - [ 110.7143, -0.35680, 1.13162, -0.42817 ] + - [ 114.8571, -0.42823, 1.06348, -0.42673 ] + - [ 119.0000, -0.49783, 0.98659, -0.42528 ] + - [ 123.1429, -0.56532, 0.90255, -0.42535 ] + - [ 127.2857, -0.63079, 0.81310, -0.42589 ] + - [ 131.4286, -0.69477, 0.72010, -0.42974 ] + - [ 135.5714, -0.75845, 0.62546, -0.43985 ] + - [ 139.7143, -0.82382, 0.53115, -0.44996 ] + - [ 143.8571, -0.89412, 0.43913, -0.46839 ] + - [ 148.0000, -0.97442, 0.35131, -0.48743 ] + - [ 150.2857, -0.90482, 0.30532, -0.49447 ] + - [ 152.5714, -0.83522, 0.26146, -0.47732 ] + - [ 154.8571, -0.76562, 0.22000, -0.46017 ] + - [ 157.1429, -0.69601, 0.18121, -0.44302 ] + - [ 159.4286, -0.62641, 0.14533, -0.42586 ] + - [ 161.7143, -0.55681, 0.11258, -0.43502 ] + - [ 164.0000, -0.48721, 0.08319, -0.45294 ] + - [ 166.2857, -0.41761, 0.05732, -0.47087 ] + - [ 168.5714, -0.34801, 0.04638, -0.48880 ] + - [ 170.8571, -0.27841, 0.04114, -0.45714 ] + - [ 173.1429, -0.20880, 0.03702, -0.34286 ] + - [ 175.4286, -0.13920, 0.03406, -0.22857 ] + - [ 177.7143, -0.06960, 0.03228, -0.11429 ] + - [ 179.9087, 0.00000, 0.03169, 0.00000 ] + - name : FFA-W3-360 # + relative_thickness : 0.36 # + data: # alpha c_l c_d c_m + - [ -179.9087, 0.00000, 0.03715, 0.00000 ] + - [ -177.7143, 0.07178, 0.03774, 0.09143 ] + - [ -175.4286, 0.14356, 0.03951, 0.18286 ] + - [ -173.1429, 0.21534, 0.04245, 0.27429 ] + - [ -170.8572, 0.28713, 0.04653, 0.36571 ] + - [ -168.5716, 0.35891, 0.05174, 0.40313 ] + - [ -166.2857, 0.43069, 0.06068, 0.40814 ] + - [ -164.0000, 0.50247, 0.08651, 0.41315 ] + - [ -161.7145, 0.57425, 0.11586, 0.41816 ] + - [ -159.4284, 0.64603, 0.14856, 0.42627 ] + - [ -157.1428, 0.71781, 0.18439, 0.44370 ] + - [ -154.8573, 0.78960, 0.22313, 0.46114 ] + - [ -152.5714, 0.86138, 0.26453, 0.47857 ] + - [ -150.2857, 0.93316, 0.30832, 0.49600 ] + - [ -148.0000, 1.00494, 0.35424, 0.48830 ] + - [ -143.8571, 0.91898, 0.44192, 0.46784 ] + - [ -139.7143, 0.84406, 0.53379, 0.44803 ] + - [ -135.5714, 0.77483, 0.62793, 0.43697 ] + - [ -131.4286, 0.70790, 0.72238, 0.42591 ] + - [ -127.2857, 0.64116, 0.81520, 0.42150 ] + - [ -123.1429, 0.57335, 0.90444, 0.42058 ] + - [ -119.0000, 0.50388, 0.98826, 0.42024 ] + - [ -114.8571, 0.43261, 1.06493, 0.42168 ] + - [ -110.7143, 0.35981, 1.13285, 0.42312 ] + - [ -106.5714, 0.28603, 1.19061, 0.42258 ] + - [ -102.4286, 0.21209, 1.23704, 0.42163 ] + - [ -98.2857, 0.13899, 1.27116, 0.41864 ] + - [ -94.1429, 0.06787, 1.29229, 0.41277 ] + - [ -90.0000, 0.00000, 1.30000, 0.40690 ] + - [ -85.8571, -0.06787, 1.29229, 0.39426 ] + - [ -81.7143, -0.13899, 1.27116, 0.38162 ] + - [ -77.5714, -0.21209, 1.23704, 0.36676 ] + - [ -73.4286, -0.28603, 1.19061, 0.35033 ] + - [ -69.2857, -0.35981, 1.13285, 0.33362 ] + - [ -65.1429, -0.43261, 1.06493, 0.31561 ] + - [ -61.0000, -0.50388, 0.98826, 0.29759 ] + - [ -56.8571, -0.57335, 0.90444, 0.27989 ] + - [ -52.7143, -0.64116, 0.81520, 0.26230 ] + - [ -48.5714, -0.70790, 0.72238, 0.24491 ] + - [ -44.4286, -0.77483, 0.62793, 0.22794 ] + - [ -40.2857, -0.84406, 0.53379, 0.21097 ] + - [ -36.1429, -0.91898, 0.44192, 0.13525 ] + - [ -32.0000, -1.00494, 0.35424, 0.05517 ] + - [ -28.0000, -1.11306, 0.20494, 0.03211 ] + - [ -24.0000, -1.05425, 0.15434, 0.01268 ] + - [ -20.0000, -0.98247, 0.10967, -0.00282 ] + - [ -18.0000, -0.94173, 0.09249, -0.00741 ] + - [ -16.0000, -0.89333, 0.07597, -0.01107 ] + - [ -14.0000, -0.85472, 0.06054, -0.01250 ] + - [ -12.0000, -0.82348, 0.04641, -0.01177 ] + - [ -10.0000, -0.79541, 0.03441, -0.01082 ] + - [ -8.0000, -0.63650, 0.02548, -0.02769 ] + - [ -6.0000, -0.39095, 0.01994, -0.05107 ] + - [ -4.0000, -0.13071, 0.01653, -0.07148 ] + - [ -2.0000, 0.16173, 0.01507, -0.09179 ] + - [ -1.0000, 0.31121, 0.01477, -0.10119 ] + - [ 0.0000, 0.45956, 0.01465, -0.10988 ] + - [ 1.0000, 0.60566, 0.01466, -0.11776 ] + - [ 2.0000, 0.74868, 0.01481, -0.12477 ] + - [ 3.0000, 0.88862, 0.01507, -0.13098 ] + - [ 4.0000, 1.02544, 0.01544, -0.13648 ] + - [ 5.0000, 1.15878, 0.01593, -0.14130 ] + - [ 6.0000, 1.28822, 0.01654, -0.14540 ] + - [ 7.0000, 1.41282, 0.01731, -0.14875 ] + - [ 8.0000, 1.53090, 0.01831, -0.15118 ] + - [ 9.0000, 1.64065, 0.01963, -0.15262 ] + - [ 10.0000, 1.73926, 0.02150, -0.15310 ] + - [ 11.0000, 1.81971, 0.02445, -0.15254 ] + - [ 12.0000, 1.87065, 0.02966, -0.15121 ] + - [ 13.0000, 1.89221, 0.03770, -0.14969 ] + - [ 14.0000, 1.87910, 0.04824, -0.14562 ] + - [ 15.0000, 1.88111, 0.05838, -0.14358 ] + - [ 16.0000, 1.86359, 0.06992, -0.14095 ] + - [ 18.0000, 1.73324, 0.10166, -0.13711 ] + - [ 20.0000, 1.59357, 0.13916, -0.14082 ] + - [ 24.0000, 1.46708, 0.21002, -0.15693 ] + - [ 28.0000, 1.44834, 0.28200, -0.17979 ] + - [ 32.0000, 1.43563, 0.35424, -0.20147 ] + - [ 36.1429, 1.31283, 0.44192, -0.22409 ] + - [ 40.2857, 1.20580, 0.53379, -0.24619 ] + - [ 44.4286, 1.10690, 0.62793, -0.26133 ] + - [ 48.5714, 1.01129, 0.72238, -0.27648 ] + - [ 52.7143, 0.91594, 0.81520, -0.29062 ] + - [ 56.8571, 0.81907, 0.90444, -0.30424 ] + - [ 61.0000, 0.71982, 0.98826, -0.31787 ] + - [ 65.1429, 0.61801, 1.06493, -0.33154 ] + - [ 69.2857, 0.51401, 1.13285, -0.34522 ] + - [ 73.4286, 0.40862, 1.19061, -0.35846 ] + - [ 77.5714, 0.30299, 1.23704, -0.37161 ] + - [ 81.7143, 0.19855, 1.27116, -0.38405 ] + - [ 85.8571, 0.09695, 1.29229, -0.39547 ] + - [ 90.0000, 0.00000, 1.30000, -0.40690 ] + - [ 94.1429, -0.06787, 1.29229, -0.41277 ] + - [ 98.2857, -0.13899, 1.27116, -0.41864 ] + - [ 102.4286, -0.21209, 1.23704, -0.42163 ] + - [ 106.5714, -0.28603, 1.19061, -0.42258 ] + - [ 110.7143, -0.35981, 1.13285, -0.42312 ] + - [ 114.8571, -0.43261, 1.06493, -0.42168 ] + - [ 119.0000, -0.50388, 0.98826, -0.42024 ] + - [ 123.1429, -0.57335, 0.90444, -0.42058 ] + - [ 127.2857, -0.64116, 0.81520, -0.42150 ] + - [ 131.4286, -0.70790, 0.72238, -0.42591 ] + - [ 135.5714, -0.77483, 0.62793, -0.43697 ] + - [ 139.7143, -0.84406, 0.53379, -0.44803 ] + - [ 143.8571, -0.91898, 0.44192, -0.46784 ] + - [ 148.0000, -1.00494, 0.35424, -0.48830 ] + - [ 150.2857, -0.93316, 0.30832, -0.49600 ] + - [ 152.5714, -0.86138, 0.26453, -0.47857 ] + - [ 154.8571, -0.78960, 0.22313, -0.46114 ] + - [ 157.1429, -0.71781, 0.18439, -0.44370 ] + - [ 159.4286, -0.64603, 0.14856, -0.42627 ] + - [ 161.7143, -0.57425, 0.11586, -0.43530 ] + - [ 164.0000, -0.50247, 0.08651, -0.45315 ] + - [ 166.2857, -0.43069, 0.06068, -0.47100 ] + - [ 168.5714, -0.35891, 0.05174, -0.48884 ] + - [ 170.8571, -0.28713, 0.04653, -0.45714 ] + - [ 173.1429, -0.21534, 0.04245, -0.34286 ] + - [ 175.4286, -0.14356, 0.03951, -0.22857 ] + - [ 177.7143, -0.07178, 0.03774, -0.11429 ] + - [ 179.9087, 0.00000, 0.03715, 0.00000 ] + + + + pitch_control: + GS_Angles: [0.06019804, 0.08713416, 0.10844806, 0.12685912, 0.14339822, 0.1586021 , 0.17279614, 0.18618935, 0.19892772, 0.21111989, 0.22285021, 0.23417256, 0.2451469 , 0.25580691, 0.26619545, 0.27632495, 0.28623134, 0.29593266, 0.30544521, 0.314779 , 0.32395154, 0.33297489, 0.3418577 , 0.35060844, 0.35923641, 0.36774807, 0.37614942, 0.38444655, 0.39264363, 0.40074407] + GS_Kp: [-0.9394215 , -0.80602855, -0.69555026, -0.60254912, -0.52318192, -0.45465531, -0.39489024, -0.34230736, -0.29568537, -0.25406506, -0.2166825 , -0.18292183, -0.15228099, -0.12434663, -0.09877533, -0.0752794 , -0.05361604, -0.0335789 , -0.01499149, 0.00229803, 0.01842102, 0.03349169, 0.0476098 , 0.0608629 , 0.07332812, 0.0850737 , 0.0961602 , 0.10664158, 0.11656607, 0.12597691] + GS_Ki: [-0.07416547, -0.06719673, -0.0614251 , -0.05656651, -0.0524202 , -0.04884022, -0.04571796, -0.04297091, -0.04053528, -0.03836094, -0.03640799, -0.03464426, -0.03304352, -0.03158417, -0.03024826, -0.02902079, -0.02788904, -0.02684226, -0.02587121, -0.02496797, -0.02412567, -0.02333834, -0.02260078, -0.02190841, -0.0212572 , -0.02064359, -0.0200644 , -0.01951683, -0.01899836, -0.01850671] + Fl_Kp: -9.35 + wt_ops: + v: [3.0, 3.266896551724138, 3.533793103448276, 3.800689655172414, 4.067586206896552, 4.334482758620689, 4.601379310344828, 4.868275862068966, 5.135172413793104, 5.402068965517241, 5.6689655172413795, 5.935862068965518, 6.2027586206896554, 6.469655172413793, 6.736551724137931, 7.00344827586207, 7.270344827586207, 7.537241379310345, 7.804137931034483, 8.071034482758622, 8.337931034482759, 8.604827586206897, 8.871724137931036, 9.138620689655173, 9.405517241379311, 9.672413793103448, 9.939310344827586, 10.206206896551725, 10.473103448275863, 10.74, 11.231724137931035, 11.723448275862069, 12.215172413793104, 12.706896551724139, 13.198620689655172, 13.690344827586207, 14.182068965517242, 14.673793103448276, 15.16551724137931, 15.657241379310346, 16.14896551724138, 16.640689655172416, 17.13241379310345, 17.624137931034483, 18.11586206896552, 18.607586206896553, 19.099310344827586, 19.591034482758623, 20.082758620689653, 20.57448275862069, 21.066206896551726, 21.557931034482756, 22.049655172413793, 22.54137931034483, 23.03310344827586, 23.524827586206897, 24.016551724137933, 24.508275862068963, 25.0] + pitch_op: [-0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, 3.57152, 5.12896, 6.36736, 7.43866, 8.40197, 9.28843, 10.1161, 10.8974, 11.641, 12.3529, 13.038, 13.6997, 14.3409, 14.9642, 15.5713, 16.1639, 16.7435, 17.3109, 17.8673, 18.4136, 18.9506, 19.4788, 19.9989, 20.5112, 21.0164, 21.5147, 22.0067, 22.4925, 22.9724] + omega_op: [2.1486, 2.3397, 2.5309, 2.722, 2.9132, 3.1043, 3.2955, 3.4866, 3.6778, 3.8689, 4.0601, 4.2512, 4.4424, 4.6335, 4.8247, 5.0159, 5.207, 5.3982, 5.5893, 5.7805, 5.9716, 6.1628, 6.3539, 6.5451, 6.7362, 6.9274, 7.1185, 7.3097, 7.5008, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56] + gear_ratio: 1 + torque_control: + VS_KP: -38609162.66552 + VS_KI: -4588245.18720 + + + tower: # (could remove some entries that don't apply for the tower) + dlsMax : 5.0 # maximum node splitting section amount; can't be 0 + + name : tower # [-] an identifier (no longer has to be number) + type : 1 # [-] + rA : [ 0, 0, 15] # [m] end A coordinates + rB : [ 0, 0, 144.582] # [m] and B coordinates + shape : circ # [-] circular or rectangular + gamma : 0.0 # [deg] twist angle about the member's z-axis + + # --- outer shell including hydro--- + stations : [ 15, 28, 28.001, 41, 41.001, 54, 54.001, 67, 67.001, 80, 80.001, 93, 93.001, 106, 106.001, 119, 119.001, 132, 132.001, 144.582 ] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB + d : [ 10, 9.964, 9.964, 9.967, 9.967, 9.927, 9.927, 9.528, 9.528, 9.149, 9.149, 8.945, 8.945, 8.735, 8.735, 8.405, 8.405, 7.321, 7.321, 6.5 ] # [m] diameters if circular or side lengths if rectangular (can be pairs) + t : [ 0.082954, 0.082954, 0.083073, 0.083073, 0.082799, 0.082799, 0.0299, 0.0299, 0.027842, 0.027842, 0.025567, 0.025567, 0.022854, 0.022854, 0.02025, 0.02025, 0.018339, 0.018339, 0.021211, 0.021211 ] # [m] wall thicknesses (scalar or list of same length as stations) + Cd : 0.0 # [-] transverse drag coefficient (optional, scalar or list of same length as stations) + Ca : 0.0 # [-] transverse added mass coefficient (optional, scalar or list of same length as stations) + # (neglecting axial coefficients for now) + CdEnd : 0.0 # [-] end axial drag coefficient (optional, scalar or list of same length as stations) + CaEnd : 0.0 # [-] end axial added mass coefficient (optional, scalar or list of same length as stations) + rho_shell : 7850 # [kg/m3] material density + +platform: + + type : FOWT + potModMaster : 1 # [int] master switch for potMod variables; 0=keeps all member potMod vars the same, 1=turns all potMod vars to False (no HAMS), 2=turns all potMod vars to True (no strip) + dlsMax : 5.0 # maximum node splitting section amount for platform members; can't be 0 + qtfPath : 'IEA-15-240-RWT-UMaineSemi.12d' # path to the qtf file for the platform + rFair : 58 + zFair : -14 + + members: # list all members here + + - name : center_column # [-] an identifier (no longer has to be number) + type : 2 # [-] + rA : [ 0, 0, -20] # [m] end A coordinates + rB : [ 0, 0, 15] # [m] and B coordinates + shape : circ # [-] circular or rectangular + gamma : 0.0 # [deg] twist angle about the member's z-axis + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + # --- outer shell including hydro--- + stations : [0, 1] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB + d : 10.0 # [m] diameters if circular or side lengths if rectangular (can be pairs) + t : 0.05 # [m] wall thicknesses (scalar or list of same length as stations) + Cd : 0.6 # [-] transverse drag coefficient (optional, scalar or list of same length as stations) + Ca : 0.93 # [-] transverse added mass coefficient (optional, scalar or list of same length as stations) + CdEnd : 0.6 # [-] end axial drag coefficient (optional, scalar or list of same length as stations) + CaEnd : 1.0 # [-] end axial added mass coefficient (optional, scalar or list of same length as stations) + rho_shell : 7850 # [kg/m3] + # --- handling of end caps or any internal structures if we need them --- + cap_stations : [ 0 ] # [m] location along member of any inner structures (in same scaling as set by 'stations') + cap_t : [ 0.001 ] # [m] thickness of any internal structures + cap_d_in : [ 0 ] # [m] inner diameter of internal structures (0 for full cap/bulkhead, >0 for a ring shape) + + + - name : outer_column # [-] an identifier (no longer has to be number) + type : 2 # [-] + rA : [51.75, 0, -20] # [m] end A coordinates + rB : [51.75, 0, 15] # [m] and B coordinates + heading : [ 60, 180, 300] # [deg] heading rotation of column about z axis (for repeated members) + shape : circ # [-] circular or rectangular + gamma : 0.0 # [deg] twist angle about the member's z-axis + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + # --- outer shell including hydro--- + stations : [0, 35] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB + d : 12.5 # [m] diameters if circular or side lengths if rectangular (can be pairs) + t : 0.05 # [m] wall thicknesses (scalar or list of same length as stations) + Cd : 0.6 # [-] transverse drag coefficient (optional, scalar or list of same length as stations) + Ca : 0.93 # [-] transverse added mass coefficient (optional, scalar or list of same length as stations) + CdEnd : 1.0 # [-] end axial drag coefficient (optional, scalar or list of same length as stations) + CaEnd : 0.7 # value of 3.0 gives more heave response # [-] end axial added mass coefficient (optional, scalar or list of same length as stations) + rho_shell : 7850 # [kg/m3] + # --- ballast --- + l_fill : 1.4 # [m] + rho_fill : 5000 # [kg/m3] + # --- handling of end caps or any internal structures if we need them --- + cap_stations : [ 0 ] # [m] location along member of any inner structures (in same scaling as set by 'stations') + cap_t : [ 0.001 ] # [m] thickness of any internal structures + cap_d_in : [ 0 ] # [m] inner diameter of internal structures (0 for full cap/bulkhead, >0 for a ring shape) + + + - name : pontoon # [-] an identifier (no longer has to be number) + type : 2 # [-] + rA : [ 5 , 0, -16.5] # [m] end A coordinates + rB : [ 45.5, 0, -16.5] # [m] and B coordinates + heading : [ 60, 180, 300] # [deg] heading rotation of column about z axis (for repeated members) + shape : rect # [-] circular or rectangular + gamma : 0.0 # [deg] twist angle about the member's z-axis + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + # --- outer shell including hydro--- + stations : [0, 40.5] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB + d : [12.4, 7.0] # [m] diameters if circular or side lengths if rectangular (can be pairs) + t : 0.05 # [m] wall thicknesses (scalar or list of same length as stations) + Cd : [1.5, 2.2 ] # [-] transverse drag coefficient (optional, scalar or list of same length as stations) + Ca : [2.2, 0.2 ] # [-] transverse added mass coefficient (optional, scalar or list of same length as stations) + CdEnd : 0.0 # [-] end axial drag coefficient (optional, scalar or list of same length as stations) + CaEnd : 0.0 # [-] end axial added mass coefficient (optional, scalar or list of same length as stations) + rho_shell : 7850 # [kg/m3] + l_fill : 40.5 # [m] + rho_fill : 1025.0 # [kg/m3] + + + - name : upper_support # [-] an identifier (no longer has to be number) + type : 2 # [-] + rA : [ 5 , 0, 14.545] # [m] end A coordinates + rB : [ 45.5, 0, 14.545] # [m] and B coordinates + heading : [ 60, 180, 300] # [deg] heading rotation of column about z axis (for repeated members) + shape : circ # [-] circular or rectangular + gamma : 0.0 # [deg] twist angle about the member's z-axis + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + # --- outer shell including hydro--- + stations : [0, 1] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB + d : 0.91 # [m] diameters if circular or side lengths if rectangular (can be pairs) + t : 0.01 # [m] wall thicknesses (scalar or list of same length as stations) + Cd : 0.0 # [-] transverse drag coefficient (optional, scalar or list of same length as stations) + Ca : 0.0 # [-] transverse added mass coefficient (optional, scalar or list of same length as stations) + CdEnd : 0.0 # [-] end axial drag coefficient (optional, scalar or list of same length as stations) + CaEnd : 0.0 # [-] end axial added mass coefficient (optional, scalar or list of same length as stations) + rho_shell : 7850 # [kg/m3] + + +# ----- Mooring system ----- + +# Mooring system descriptions (each for an individual FOWT with no sharing) +mooring_systems: + + ms1: + name: 2-line semi-taut polyester mooring system with a third line shared + + keys: [MooringConfigID, heading, anchorType, lengthAdjust] + data: + - [ semitaut-poly_1, 150 , suction1, 0 ] + - [ semitaut-poly_1, 270 , suction1, 0 ] + - [ semitaut-poly_1, 30 , suction1, 0 ] + + +# Mooring line configurations +mooring_line_configs: + + semitaut-poly_1: # mooring line configuration identifier + + name: Semitaut polyester configuration 1 # descriptive name + + span: 642 + + sections: #in order from anchor to fairlead + - mooringFamily: chain # ID of a mooring line section type + d_nom: .1549 + length: 497.7 # [m] usntretched length of line section + adjustable: True # flags that this section could be adjusted to accommodate different spacings... + - connectorType: h_link + - mooringFamily: polyester # ID of a mooring line section type + d_nom: .182 + length: 199.8 # [m] length (unstretched) + +# Mooring connector properties +mooring_connector_types: + + h_link: + m : 140 # [kg] component mass + v : 0.13 # [m^3] component volumetric displacement + +# Anchor type properties +anchor_types: + + drag-embedment1: + type : DEA # type of anchor + A : 10 # net area of anchor's fluke [m^2] + zlug : 8 # embedded depth of padeye [m] + + suction1: + type : suction + L : 8.40 # length of pile [m] + D : 2.45 # diameter of pile [m] + zlug : 5.32 # embedded depth of padeye [m] + diff --git a/examples/OntologySample600m_shared.yaml b/examples/OntologySample600m_shared.yaml index 7052f83f..a26591dd 100644 --- a/examples/OntologySample600m_shared.yaml +++ b/examples/OntologySample600m_shared.yaml @@ -37,7 +37,7 @@ site: type_array: - [mud_soft , mud_firm , mud_soft] - - [mud_soft , mud_soft , mud_soft] + - [mud_soft , mud_soft , mud_soft] - [mud_soft , mud_firm , mud_soft] soil_types: # dictionary-based approach @@ -1224,7 +1224,7 @@ platforms: rB : [ 0, 0, 15] # [m] and B coordinates shape : circ # [-] circular or rectangular gamma : 0.0 # [deg] twist angle about the member's z-axis - potMod : True # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory # --- outer shell including hydro--- stations : [0, 1] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB d : 10.0 # [m] diameters if circular or side lengths if rectangular (can be pairs) @@ -1247,7 +1247,7 @@ platforms: heading : [ 60, 180, 300] # [deg] heading rotation of column about z axis (for repeated members) shape : circ # [-] circular or rectangular gamma : 0.0 # [deg] twist angle about the member's z-axis - potMod : True # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory # --- outer shell including hydro--- stations : [0, 35] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB d : 12.5 # [m] diameters if circular or side lengths if rectangular (can be pairs) @@ -1562,17 +1562,17 @@ mooring_connector_types: # Anchor type properties anchor_types: suction_pile1: - type : suction_pile + type : suction L : 16.4 # length of pile [m] D : 5.45 # diameter of pile [m] zlug : 9.32 # embedded depth of padeye [m] d-g_pile1: - type : dandg_pile + type : dandg L : 50 # length of pile [m] D : 3 # diameter of pile [m] zlug : 0 # embedded depth [m] driven_pile1: - type : driven_pile + type : driven L : 20 # pile length [m] D : 1.5 # pile diameter [m] zlug : 3 # embedded depth [m diff --git a/examples/README.md b/examples/README.md index 2a14129a..e5b846d4 100644 --- a/examples/README.md +++ b/examples/README.md @@ -54,7 +54,3 @@ This example shows how to make an FAModel project with platforms, anchors, and m There are many ways to manually fill in a project class with array components and site information. In this case, site information is loaded in from files, and a platform, moorings, and anchors are loaded in from a moorpy array (which comes from a MoorDyn file). Further platforms are added by using the duplicate() function to "copy" the platform and associated moorings and anchors and place in a specific location. - -## Anchor capacity examples -This example calculates the anchor capacity for each different type of anchor, determines the load on the anchor, and then determines the safety factor. -This is provided to show an example of what information is required for each anchor type, and how results can differ for different anchor types. \ No newline at end of file diff --git a/examples/checkyaml.yaml b/examples/checkyaml.yaml new file mode 100644 index 00000000..59a84805 --- /dev/null +++ b/examples/checkyaml.yaml @@ -0,0 +1,1331 @@ +site: + seabed: + x: [-10901.0, 0.0, 10000.0] + y: [-10900.0, 0.0, 10000.0] + type_array: + - [mud_soft, mud_firm, mud_soft] + - [mud_soft, mud_firm, mud_soft] + - [mud_soft, mud_firm, mud_soft] + soil_types: + mud_soft: + layers: + - Su0: [2.39] + k: [1.41] + depth: [0] + top: 0 + bottom: 50 + soil_type: mud_soft + Su0: [2.39] + k: [1.41] + alpha: [0.7] + gamma: [8.7] + phi: [0.0] + UCS: [7.0] + Em: [50.0] + mud_firm: + layers: + - Su0: [23.94] + k: [2.67] + depth: [0] + top: 0 + bottom: 50 + soil_type: mud_firm + Su0: [2.39] + k: [1.41] + alpha: [0.7] + gamma: [8.7] + phi: [0.0] + UCS: [7.0] + Em: [50.0] + bathymetry: + x: [-3000.0, 3500.0, 10000.0] + y: [-3000.0, 3500.0, 10000.0] + depths: + - [200.1, 207.25625, 240.0] + - [200.34375, 206.133984375, 208.3125] + - [210.7, 196.29375000000002, 185.0] + boundaries: + x_y: + - [-2000.0, -2000.0] + - [-2000.0, 8000.0] + - [8000.0, 8000.0] + - [8000.0, -2000.0] + - [-2000.0, -2000.0] + general: + water_depth: 200.0 + rho_air: 1.225 + rho_water: 1025.0 + mu_air: 1.81e-05 +array: + keys: [ID, topsideID, platformID, mooringID, x_location, y_location, + z_location, heading_adjust] + data: + - [fowt0, 1, 1, ms0, -600.0, -800.0, 0.0, 0.0] + - [fowt1, 1, 1, ms0, 1100.0, -800.0, 0.0, 0.0] + - [fowt2, 1, 1, ms0, 2800.0, -800.0, 0.0, 0.0] + - [fowt3, 1, 1, ms0, 4500.0, -800.0, 0.0, 0.0] + - [fowt4, 1, 1, ms0, 6200.0, -800.0, 0.0, 0.0] + - [fowt5, 1, 1, ms0, -600.0, 1100.0, 0.0, 0.0] + - [fowt6, 1, 1, ms0, 1100.0, 1100.0, 0.0, 0.0] + - [fowt7, 1, 1, ms0, 2800.0, 1100.0, 0.0, 0.0] + - [fowt8, 1, 1, ms0, 4500.0, 1100.0, 0.0, 0.0] + - [fowt9, 1, 1, ms0, 6200.0, 1100.0, 0.0, 0.0] + - [fowt10, 1, 1, ms0, -600.0, 3000.0, 0.0, 0.0] + - [fowt11, 1, 1, ms0, 1100.0, 3000.0, 0.0, 0.0] + - [fowt12, 1, 1, ms0, 2800.0, 3000.0, 0.0, 0.0] + - [fowt13, 1, 1, ms0, 4500.0, 3000.0, 0.0, 0.0] + - [fowt14, 1, 1, ms0, 6200.0, 3000.0, 0.0, 0.0] + - [fowt15, 1, 1, ms0, -600.0, 4900.0, 0.0, 0.0] + - [fowt16, 1, 1, ms0, 1100.0, 4900.0, 0.0, 0.0] + - [fowt17, 1, 1, ms0, 2800.0, 4900.0, 0.0, 0.0] + - [fowt18, 1, 1, ms0, 4500.0, 4900.0, 0.0, 0.0] + - [fowt19, 1, 1, ms0, 6200.0, 4900.0, 0.0, 0.0] + - [fowt20, 1, 1, ms0, -600.0, 6800.0, 0.0, 0.0] + - [fowt21, 1, 1, ms0, 1100.0, 6800.0, 0.0, 0.0] + - [fowt22, 1, 1, ms0, 2800.0, 6800.0, 0.0, 0.0] + - [fowt23, 1, 1, ms0, 4500.0, 6800.0, 0.0, 0.0] + - [fowt24, 1, 1, ms0, 6200.0, 6800.0, 0.0, 0.0] +platform: + type: FOWT + potModMaster: 1 + dlsMax: 5.0 + qtfPath: IEA-15-240-RWT-UMaineSemi.12d + rFair: 58 + zFair: -14 + members: + - name: center_column + type: 2 + rA: [0, 0, -20] + rB: [0, 0, 15] + shape: circ + gamma: 0.0 + potMod: false + stations: [0, 1] + d: 10.0 + t: 0.05 + Cd: 0.6 + Ca: 0.93 + CdEnd: 0.6 + CaEnd: 1.0 + rho_shell: 7850 + cap_stations: [0] + cap_t: [0.001] + cap_d_in: [0] + dlsMax: 5.0 + headings: 0.0 + - name: outer_column + type: 2 + rA: [51.75, 0, -20] + rB: [51.75, 0, 15] + heading: [60, 180, 300] + shape: circ + gamma: 0.0 + potMod: false + stations: [0, 35] + d: 12.5 + t: 0.05 + Cd: 0.6 + Ca: 0.93 + CdEnd: 1.0 + CaEnd: 0.7 + rho_shell: 7850 + l_fill: 1.4 + rho_fill: 5000 + cap_stations: [0] + cap_t: [0.001] + cap_d_in: [0] + dlsMax: 5.0 + headings: [60.0, 180.0, 300.0] + - name: pontoon + type: 2 + rA: [5, 0, -16.5] + rB: [45.5, 0, -16.5] + heading: [60, 180, 300] + shape: rect + gamma: 0.0 + potMod: false + stations: [0, 40.5] + d: [12.4, 7.0] + t: 0.05 + Cd: [1.5, 2.2] + Ca: [2.2, 0.2] + CdEnd: 0.0 + CaEnd: 0.0 + rho_shell: 7850 + l_fill: 40.5 + rho_fill: 1025.0 + dlsMax: 5.0 + headings: [60.0, 180.0, 300.0] + - name: upper_support + type: 2 + rA: [5, 0, 14.545] + rB: [45.5, 0, 14.545] + heading: [60, 180, 300] + shape: circ + gamma: 0.0 + potMod: false + stations: [0, 1] + d: 0.91 + t: 0.01 + Cd: 0.0 + Ca: 0.0 + CdEnd: 0.0 + CaEnd: 0.0 + rho_shell: 7850 + dlsMax: 5.0 + headings: [60.0, 180.0, 300.0] +topsides: +- type: Turbine + mRNA: 991000 + IxRNA: 0 + IrRNA: 0 + xCG_RNA: 0 + hHub: 150.0 + Fthrust: '1500.0E3' + I_drivetrain: 318628138.0 + nBlades: 3 + Zhub: 150.0 + Rhub: 3.97 + precone: 4.0 + shaft_tilt: 6.0 + overhang: -12.0313 + aeroMod: 1 + blade: + precurveTip: -3.9999999999999964 + presweepTip: 0.0 + Rtip: 120.96999999936446 + geometry: + - [8.004, 5.228, 15.474, 0.035, 0.0] + - [12.039, 5.321, 14.692, 0.084, 0.0] + - [16.073, 5.458, 13.33, 0.139, 0.0] + - [20.108, 5.602, 11.644, 0.192, 0.0] + - [24.142, 5.718, 9.927, 0.232, 0.0] + - [28.177, 5.767, 8.438, 0.25, 0.0] + - [32.211, 5.713, 7.301, 0.25, 0.0] + - [36.246, 5.536, 6.232, 0.246, 0.0] + - [40.28, 5.291, 5.23, 0.24, 0.0] + - [44.315, 5.035, 4.348, 0.233, 0.0] + - [48.349, 4.815, 3.606, 0.218, 0.0] + - [52.384, 4.623, 2.978, 0.178, 0.0] + - [56.418, 4.432, 2.423, 0.1, 0.0] + - [60.453, 4.245, 1.924, 0.0, 0.0] + - [64.487, 4.065, 1.467, -0.112, 0.0] + - [68.522, 3.896, 1.056, -0.244, 0.0] + - [72.556, 3.735, 0.692, -0.415, 0.0] + - [76.591, 3.579, 0.355, -0.62, 0.0] + - [80.625, 3.425, 0.019, -0.846, 0.0] + - [84.66, 3.268, -0.358, -1.08, 0.0] + - [88.694, 3.112, -0.834, -1.33, 0.0] + - [92.729, 2.957, -1.374, -1.602, 0.0] + - [96.763, 2.8, -1.848, -1.895, 0.0] + - [100.798, 2.637, -2.136, -2.202, 0.0] + - [104.832, 2.464, -2.172, -2.523, 0.0] + - [108.867, 2.283, -2.108, -2.864, 0.0] + - [112.901, 2.096, -1.953, -3.224, 0.0] + - [116.936, 1.902, -1.662, -3.605, 0.0] + airfoils: + - [0.0, circular] + - [0.02, circular] + - [0.15, SNL-FFA-W3-500] + - [0.24517, FFA-W3-360] + - [0.32884, FFA-W3-330blend] + - [0.43918, FFA-W3-301] + - [0.53767, FFA-W3-270blend] + - [0.63821, FFA-W3-241] + - [0.77174, FFA-W3-211] + - [1.0, FFA-W3-211] + airfoils: + - name: circular + relative_thickness: 1.0 + data: + - [-179.9087, 0.0001, 0.35, -0.0001] + - [179.9087, 0.0001, 0.35, -0.0001] + - name: SNL-FFA-W3-500 + relative_thickness: 0.5 + data: + - [-179.966, 0.0, 0.0844, 0.0] + - [-170.0, 0.4419, 0.0844, 0.3125] + - [-160.0002, 0.8837, 0.1268, 0.2831] + - [-149.9998, 0.9674, 0.2927, 0.2632] + - [-139.9999, 0.7801, 0.497, 0.2048] + - [-130.0001, 0.6293, 0.7161, 0.1932] + - [-120.0003, 0.4785, 0.9246, 0.2008] + - [-109.9999, 0.3189, 1.0985, 0.2136] + - [-100.0, 0.1553, 1.2182, 0.2221] + - [-90.0002, 0.0, 1.2707, 0.2198] + - [-79.9998, -0.1553, 1.2182, 0.196] + - [-70.0, -0.3189, 1.0985, 0.1635] + - [-60.0001, -0.4784, 0.9246, 0.1285] + - [-49.9997, -0.6293, 0.7161, 0.0965] + - [-39.9999, -0.7801, 0.497, 0.0716] + - [-30.0001, -0.9674, 0.2927, 0.0522] + - [-20.0002, -1.0281, 0.1499, -0.0063] + - [-19.7499, -1.0243, 0.1472, -0.0089] + - [-19.2502, -1.0052, 0.1447, -0.0099] + - [-18.9999, -0.9971, 0.1433, -0.0105] + - [-18.75, -1.0052, 0.1403, -0.011] + - [-18.5002, -0.9995, 0.1386, -0.0116] + - [-18.2499, -0.9908, 0.1373, -0.012] + - [-18.0, -0.9815, 0.136, -0.0126] + - [-17.4998, -0.9764, 0.1322, -0.0135] + - [-17.25, -0.9705, 0.1306, -0.0139] + - [-17.0002, -0.9655, 0.129, -0.0143] + - [-16.7498, -0.9662, 0.1268, -0.0147] + - [-16.5, -0.9544, 0.1258, -0.0151] + - [-16.2502, -0.9444, 0.1246, -0.0155] + - [-15.9998, -0.9405, 0.1229, -0.0158] + - [-15.75, -0.9433, 0.1206, -0.0161] + - [-15.5002, -0.933, 0.1195, -0.0164] + - [-15.2498, -0.9211, 0.1185, -0.0168] + - [-14.7502, -0.9158, 0.115, -0.0173] + - [-14.4998, -0.907, 0.1138, -0.0175] + - [-14.25, -0.8959, 0.1127, -0.0178] + - [-14.0002, -0.8926, 0.111, -0.0181] + - [-13.7498, -0.8808, 0.11, -0.0184] + - [-13.5, -0.8722, 0.1089, -0.0186] + - [-13.2502, -0.866, 0.1075, -0.0188] + - [-12.9998, -0.8626, 0.1059, -0.0188] + - [-12.75, -0.8489, 0.1051, -0.0192] + - [-12.5002, -0.8363, 0.1042, -0.0194] + - [-12.2498, -0.8363, 0.1023, -0.0194] + - [-12.0, -0.8271, 0.1013, -0.0196] + - [-11.7502, -0.8141, 0.1004, -0.0198] + - [-11.4998, -0.8004, 0.0997, -0.02] + - [-11.0002, -0.789, 0.0971, -0.0199] + - [-10.7498, -0.7862, 0.0956, -0.0196] + - [-10.5, -0.7747, 0.0948, -0.0194] + - [-10.2502, -0.7701, 0.094, -0.0184] + - [-9.9998, -0.7674, 0.0925, -0.0183] + - [-9.75, -0.7506, 0.0917, -0.0192] + - [-9.5002, -0.729, 0.0912, -0.0205] + - [-9.2498, -0.7095, 0.0902, -0.0224] + - [-9.0, -0.6855, 0.0895, -0.0247] + - [-8.7502, -0.659, 0.0891, -0.0267] + - [-8.4998, -0.6319, 0.0887, -0.0287] + - [-8.25, -0.6019, 0.0879, -0.032] + - [-8.0002, -0.5718, 0.0875, -0.0345] + - [-7.7498, -0.5424, 0.0873, -0.0367] + - [-7.5, -0.5098, 0.0868, -0.0399] + - [-7.2502, -0.4767, 0.0864, -0.043] + - [-6.9998, -0.4454, 0.0862, -0.0453] + - [-6.75, -0.4142, 0.086, -0.0476] + - [-6.5002, -0.3791, 0.0856, -0.051] + - [-6.2498, -0.346, 0.0853, -0.0538] + - [-6.0, -0.3144, 0.0852, -0.056] + - [-5.7502, -0.2817, 0.085, -0.0586] + - [-5.4998, -0.2461, 0.0847, -0.0619] + - [-5.25, -0.2133, 0.0846, -0.0644] + - [-5.0002, -0.1827, 0.0845, -0.0663] + - [-4.7498, -0.1494, 0.0843, -0.0688] + - [-4.5, -0.1158, 0.0842, -0.0715] + - [-4.2502, -0.0837, 0.084, -0.0737] + - [-3.9998, -0.0529, 0.084, -0.0756] + - [-3.75, -0.0225, 0.0839, -0.0774] + - [-3.5002, 0.0089, 0.0838, -0.0793] + - [-3.2498, 0.0392, 0.0838, -0.0811] + - [-3.0, 0.0686, 0.0838, -0.0826] + - [-2.7502, 0.0974, 0.0838, -0.0838] + - [-2.4998, 0.126, 0.0838, -0.0852] + - [-2.25, 0.1555, 0.0838, -0.0867] + - [-2.0002, 0.1853, 0.0838, -0.0883] + - [-1.7498, 0.2146, 0.0837, -0.0897] + - [-1.5, 0.243, 0.0837, -0.091] + - [-1.2502, 0.2713, 0.0838, -0.0921] + - [-0.9998, 0.3006, 0.0838, -0.0936] + - [-0.75, 0.3295, 0.0838, -0.0949] + - [-0.5002, 0.3578, 0.0838, -0.0961] + - [-0.2498, 0.3857, 0.0838, -0.0972] + - [0.0, 0.4135, 0.0838, -0.0983] + - [0.2298, 0.4425, 0.0839, -0.0995] + - [0.4698, 0.4715, 0.0839, -0.1008] + - [0.7002, 0.5003, 0.0839, -0.1019] + - [0.9402, 0.5286, 0.084, -0.1029] + - [1.17, 0.5567, 0.084, -0.104] + - [1.3997, 0.585, 0.0841, -0.105] + - [1.6398, 0.6135, 0.0841, -0.1061] + - [1.8701, 0.6417, 0.0842, -0.1072] + - [2.1102, 0.6697, 0.0842, -0.1082] + - [2.34, 0.6975, 0.0843, -0.1091] + - [2.5697, 0.7251, 0.0843, -0.11] + - [2.8098, 0.7528, 0.0844, -0.1109] + - [3.0401, 0.7807, 0.0845, -0.1119] + - [3.2802, 0.8083, 0.0846, -0.1128] + - [3.5099, 0.8358, 0.0846, -0.1137] + - [3.7403, 0.8631, 0.0847, -0.1146] + - [3.9798, 0.8902, 0.0847, -0.1153] + - [4.2101, 0.9173, 0.0848, -0.1161] + - [4.4502, 0.9444, 0.0849, -0.117] + - [4.6799, 0.9713, 0.085, -0.1178] + - [4.9102, 0.9981, 0.0851, -0.1185] + - [5.1497, 1.0249, 0.0852, -0.1192] + - [5.3801, 1.0515, 0.0853, -0.1199] + - [5.6201, 1.0779, 0.0853, -0.1206] + - [5.8499, 1.1041, 0.0854, -0.1212] + - [6.0802, 1.1302, 0.0856, -0.1218] + - [6.3197, 1.156, 0.0857, -0.1224] + - [6.5501, 1.1818, 0.0858, -0.123] + - [6.7901, 1.2076, 0.0859, -0.1235] + - [7.0199, 1.2334, 0.086, -0.124] + - [7.2502, 1.2589, 0.0861, -0.1245] + - [7.4903, 1.2841, 0.0862, -0.125] + - [7.72, 1.3088, 0.0864, -0.1254] + - [7.9601, 1.3331, 0.0865, -0.1257] + - [8.1899, 1.357, 0.0867, -0.1259] + - [8.4202, 1.381, 0.0869, -0.1262] + - [8.6603, 1.4054, 0.087, -0.1265] + - [8.89, 1.4295, 0.0871, -0.1267] + - [9.1198, 1.4531, 0.0873, -0.127] + - [9.8801, 1.5154, 0.0879, -0.1265] + - [10.6398, 1.5749, 0.0886, -0.1256] + - [11.4001, 1.6151, 0.0895, -0.1214] + - [12.1501, 1.6443, 0.0912, -0.1163] + - [12.9099, 1.6824, 0.093, -0.1133] + - [13.6702, 1.7146, 0.0954, -0.1107] + - [14.4202, 1.7362, 0.0989, -0.108] + - [15.1799, 1.7627, 0.1024, -0.1063] + - [15.9403, 1.7706, 0.1076, -0.1042] + - [16.6903, 1.7639, 0.1144, -0.1025] + - [17.45, 1.7604, 0.1211, -0.1013] + - [18.2097, 1.7251, 0.131, -0.1001] + - [18.9701, 1.7035, 0.1399, -0.0998] + - [19.7201, 1.6784, 0.1492, -0.1001] + - [20.4798, 1.6505, 0.1591, -0.1016] + - [21.2401, 1.6227, 0.1691, -0.1036] + - [21.9901, 1.6067, 0.1778, -0.1064] + - [22.7499, 1.5972, 0.1858, -0.1099] + - [23.5102, 1.5892, 0.1937, -0.1136] + - [24.2602, 1.5815, 0.2014, -0.118] + - [25.0199, 1.5563, 0.2135, -0.1249] + - [25.7802, 1.5272, 0.2267, -0.1325] + - [26.5302, 1.4982, 0.2399, -0.14] + - [27.29, 1.4691, 0.2531, -0.1476] + - [28.0497, 1.4401, 0.2663, -0.1551] + - [28.81, 1.411, 0.2795, -0.1627] + - [29.56, 1.382, 0.2927, -0.1703] + - [30.3198, 1.3622, 0.3078, -0.174] + - [31.0801, 1.3424, 0.323, -0.1777] + - [31.8301, 1.3225, 0.3381, -0.1815] + - [32.5898, 1.3027, 0.3532, -0.1852] + - [33.3502, 1.2829, 0.3684, -0.1889] + - [34.1002, 1.2631, 0.3835, -0.1926] + - [34.8599, 1.2433, 0.3987, -0.1964] + - [35.6202, 1.2234, 0.4138, -0.2001] + - [36.38, 1.2036, 0.4289, -0.2039] + - [37.13, 1.1838, 0.4441, -0.2076] + - [37.8903, 1.164, 0.4592, -0.2113] + - [38.65, 1.1442, 0.4743, -0.215] + - [39.4, 1.1243, 0.4895, -0.2188] + - [40.1598, 1.1064, 0.5052, -0.2218] + - [40.9201, 1.0905, 0.5214, -0.2242] + - [41.6701, 1.0745, 0.5376, -0.2266] + - [42.4298, 1.0586, 0.5538, -0.2289] + - [43.1901, 1.0426, 0.5701, -0.2313] + - [43.9401, 1.0267, 0.5863, -0.2337] + - [44.6999, 1.0107, 0.6025, -0.2361] + - [45.4602, 0.9948, 0.6188, -0.2384] + - [46.2199, 0.9788, 0.635, -0.2408] + - [46.9699, 0.9628, 0.6512, -0.2432] + - [47.7302, 0.9469, 0.6675, -0.2455] + - [48.49, 0.9309, 0.6837, -0.2479] + - [49.24, 0.915, 0.6999, -0.2503] + - [49.9997, 0.899, 0.7161, -0.2527] + - [60.0001, 0.6836, 0.9246, -0.2833] + - [70.0, 0.4556, 1.0985, -0.3156] + - [79.9998, 0.2219, 1.2182, -0.3482] + - [90.0002, 0.0, 1.2707, -0.3773] + - [100.0, -0.1553, 1.2182, -0.3877] + - [109.9999, -0.3189, 1.0985, -0.3865] + - [120.0003, -0.4784, 0.9246, -0.3806] + - [130.0001, -0.6293, 0.7161, -0.3803] + - [139.9999, -0.7801, 0.497, -0.4032] + - [149.9998, -0.9674, 0.2927, -0.4854] + - [160.0002, -0.8837, 0.1268, -0.5325] + - [170.0, -0.4418, 0.0844, -0.3906] + - [179.966, 0.0, 0.0844, 0.0] + - name: FFA-W3-211 + relative_thickness: 0.211 + data: + - [-179.9087, 0.0, 0.02464, 0.0] + - [-177.7143, 0.05403, 0.02534, 0.09143] + - [-175.4286, 0.10805, 0.02742, 0.18286] + - [-173.1429, 0.16208, 0.03088, 0.27429] + - [-170.8572, 0.2161, 0.0357, 0.36571] + - [-168.5716, 0.27013, 0.05599, 0.39192] + - [-166.2857, 0.32415, 0.08143, 0.37898] + - [-164.0, 0.37818, 0.11112, 0.36605] + - [-161.7145, 0.4322, 0.14485, 0.35312] + - [-159.4284, 0.48623, 0.18242, 0.34768] + - [-157.1428, 0.54025, 0.22359, 0.36471] + - [-154.8573, 0.59428, 0.2681, 0.38175] + - [-152.5714, 0.6483, 0.31566, 0.39878] + - [-150.2857, 0.70233, 0.36597, 0.41581] + - [-148.0, 0.75635, 0.41871, 0.41955] + - [-143.8571, 0.73188, 0.51941, 0.42287] + - [-139.7143, 0.70655, 0.62488, 0.42632] + - [-135.5714, 0.6776, 0.73293, 0.43163] + - [-131.4286, 0.64333, 0.8413, 0.43694] + - [-127.2857, 0.60277, 0.94773, 0.44389] + - [-123.1429, 0.5555, 1.05001, 0.45171] + - [-119.0, 0.50156, 1.146, 0.45897] + - [-114.8571, 0.44131, 1.23371, 0.46448] + - [-110.7143, 0.37542, 1.31129, 0.46998] + - [-106.5714, 0.30482, 1.37714, 0.47096] + - [-102.4286, 0.23063, 1.42988, 0.47101] + - [-98.2857, 0.15413, 1.46842, 0.46824] + - [-94.1429, 0.07675, 1.49196, 0.46149] + - [-90.0, 0.0, 1.5, 0.45474] + - [-85.8571, -0.07675, 1.49196, 0.44026] + - [-81.7143, -0.15413, 1.46842, 0.42578] + - [-77.5714, -0.23063, 1.42988, 0.40821] + - [-73.4286, -0.30482, 1.37714, 0.38846] + - [-69.2857, -0.37542, 1.31129, 0.36815] + - [-65.1429, -0.44131, 1.23371, 0.34519] + - [-61.0, -0.50156, 1.146, 0.32223] + - [-56.8571, -0.5555, 1.05001, 0.29864] + - [-52.7143, -0.60277, 0.94773, 0.27486] + - [-48.5714, -0.64333, 0.8413, 0.25128] + - [-44.4286, -0.6776, 0.73293, 0.2281] + - [-40.2857, -0.70655, 0.62488, 0.20491] + - [-36.1429, -0.73188, 0.51941, 0.15416] + - [-32.0, -0.75635, 0.41871, 0.10137] + - [-28.0, -0.85636, 0.28691, 0.06527] + - [-24.0, -1.18292, 0.1396, 0.01647] + - [-20.0, -1.23596, 0.08345, -0.00352] + - [-18.0, -1.22536, 0.06509, -0.00672] + - [-16.0, -1.20476, 0.04888, -0.00881] + - [-14.0, -1.18332, 0.03417, -0.01101] + - [-12.0, -1.10093, 0.02132, -0.02269] + - [-10.0, -0.88209, 0.01386, -0.04397] + - [-8.0, -0.62981, 0.01075, -0.05756] + - [-6.0, -0.3767, 0.00882, -0.06747] + - [-4.0, -0.12177, 0.00702, -0.0768] + - [-2.0, 0.1281, 0.00663, -0.08283] + - [-1.0, 0.25192, 0.00664, -0.08534] + - [0.0, 0.37535, 0.0067, -0.08777] + - [1.0, 0.49828, 0.00681, -0.09011] + - [2.0, 0.62052, 0.00698, -0.09234] + - [3.0, 0.742, 0.0072, -0.09447] + - [4.0, 0.86238, 0.00751, -0.09646] + - [5.0, 0.98114, 0.00796, -0.09828] + - [6.0, 1.09662, 0.00872, -0.09977] + - [7.0, 1.20904, 0.00968, -0.10095] + - [8.0, 1.3168, 0.01097, -0.10163] + - [9.0, 1.42209, 0.01227, -0.10207] + - [10.0, 1.52361, 0.01369, -0.10213] + - [11.0, 1.61988, 0.01529, -0.10174] + - [12.0, 1.70937, 0.01717, -0.10087] + - [13.0, 1.78681, 0.01974, -0.09936] + - [14.0, 1.8429, 0.02368, -0.0972] + - [15.0, 1.85313, 0.03094, -0.0941] + - [16.0, 1.80951, 0.04303, -0.09144] + - [18.0, 1.66033, 0.0773, -0.09242] + - [20.0, 1.56152, 0.11202, -0.09871] + - [24.0, 1.43327, 0.18408, -0.1177] + - [28.0, 1.29062, 0.27589, -0.14566] + - [32.0, 1.0805, 0.41871, -0.18266] + - [36.1429, 1.04554, 0.51941, -0.20913] + - [40.2857, 1.00936, 0.62488, -0.23534] + - [44.4286, 0.96801, 0.73293, -0.25784] + - [48.5714, 0.91904, 0.8413, -0.28035] + - [52.7143, 0.86109, 0.94773, -0.30163] + - [56.8571, 0.79357, 1.05001, -0.32226] + - [61.0, 0.71651, 1.146, -0.34247] + - [65.1429, 0.63044, 1.23371, -0.36135] + - [69.2857, 0.53632, 1.31129, -0.38024] + - [73.4286, 0.43546, 1.37714, -0.39704] + - [77.5714, 0.32947, 1.42988, -0.41341] + - [81.7143, 0.22019, 1.46842, -0.42844] + - [85.8571, 0.10965, 1.49196, -0.44159] + - [90.0, 0.0, 1.5, -0.45474] + - [94.1429, -0.07675, 1.49196, -0.46149] + - [98.2857, -0.15413, 1.46842, -0.46824] + - [102.4286, -0.23063, 1.42988, -0.47101] + - [106.5714, -0.30482, 1.37714, -0.47096] + - [110.7143, -0.37542, 1.31129, -0.46998] + - [114.8571, -0.44131, 1.23371, -0.46448] + - [119.0, -0.50156, 1.146, -0.45897] + - [123.1429, -0.5555, 1.05001, -0.45171] + - [127.2857, -0.60277, 0.94773, -0.44389] + - [131.4286, -0.64333, 0.8413, -0.43694] + - [135.5714, -0.6776, 0.73293, -0.43163] + - [139.7143, -0.70655, 0.62488, -0.42632] + - [143.8571, -0.73188, 0.51941, -0.42287] + - [148.0, -0.75635, 0.41871, -0.41955] + - [150.2857, -0.70233, 0.36597, -0.41581] + - [152.5714, -0.6483, 0.31566, -0.39878] + - [154.8571, -0.59428, 0.2681, -0.38175] + - [157.1429, -0.54025, 0.22359, -0.36471] + - [159.4286, -0.48623, 0.18242, -0.34768] + - [161.7143, -0.4322, 0.14485, -0.37026] + - [164.0, -0.37818, 0.11112, -0.40605] + - [166.2857, -0.32415, 0.08143, -0.44184] + - [168.5714, -0.27013, 0.05599, -0.47763] + - [170.8571, -0.2161, 0.0357, -0.45714] + - [173.1429, -0.16208, 0.03088, -0.34286] + - [175.4286, -0.10805, 0.02742, -0.22857] + - [177.7143, -0.05403, 0.02534, -0.11429] + - [179.9087, 0.0, 0.02464, 0.0] + - name: FFA-W3-241 + relative_thickness: 0.241 + data: + - [-179.9087, 0.0, 0.01178, 0.0] + - [-177.7143, 0.05818, 0.01248, 0.09143] + - [-175.4286, 0.11636, 0.0146, 0.18286] + - [-173.1429, 0.17453, 0.01811, 0.27429] + - [-170.8572, 0.23271, 0.023, 0.36571] + - [-168.5716, 0.29089, 0.02922, 0.39568] + - [-166.2857, 0.34907, 0.05382, 0.38876] + - [-164.0, 0.40725, 0.08379, 0.38184] + - [-161.7145, 0.46542, 0.11786, 0.37492] + - [-159.4284, 0.5236, 0.15581, 0.37408] + - [-157.1428, 0.58178, 0.1974, 0.39148] + - [-154.8573, 0.63996, 0.24237, 0.40888] + - [-152.5714, 0.69814, 0.29043, 0.42628] + - [-150.2857, 0.75631, 0.34128, 0.44368] + - [-148.0, 0.81449, 0.3946, 0.44537] + - [-143.8571, 0.77925, 0.49645, 0.44436] + - [-139.7143, 0.74511, 0.60319, 0.4436] + - [-135.5714, 0.70881, 0.71263, 0.44609] + - [-131.4286, 0.66835, 0.82249, 0.44858] + - [-127.2857, 0.62253, 0.93051, 0.4537] + - [-123.1429, 0.5708, 1.03447, 0.4602] + - [-119.0, 0.51307, 1.13222, 0.46633] + - [-114.8571, 0.44965, 1.22176, 0.4713] + - [-110.7143, 0.38115, 1.30123, 0.47627] + - [-106.5714, 0.30846, 1.36903, 0.47705] + - [-102.4286, 0.23266, 1.42376, 0.47695] + - [-98.2857, 0.15503, 1.46433, 0.47409] + - [-94.1429, 0.07698, 1.4899, 0.46732] + - [-90.0, 0.0, 1.5, 0.46055] + - [-85.8571, -0.07698, 1.4899, 0.44509] + - [-81.7143, -0.15503, 1.46433, 0.42964] + - [-77.5714, -0.23266, 1.42376, 0.41125] + - [-73.4286, -0.30846, 1.36903, 0.39081] + - [-69.2857, -0.38115, 1.30123, 0.36988] + - [-65.1429, -0.44965, 1.22176, 0.34663] + - [-61.0, -0.51307, 1.13222, 0.32339] + - [-56.8571, -0.5708, 1.03447, 0.29984] + - [-52.7143, -0.62253, 0.93051, 0.27618] + - [-48.5714, -0.66835, 0.82249, 0.2528] + - [-44.4286, -0.70881, 0.71263, 0.22992] + - [-40.2857, -0.74511, 0.60319, 0.20705] + - [-36.1429, -0.77925, 0.49645, 0.14561] + - [-32.0, -0.81449, 0.3946, 0.08131] + - [-28.0, -1.07781, 0.22252, 0.04592] + - [-24.0, -1.12692, 0.15159, 0.01901] + - [-20.0, -1.1448, 0.09699, 0.00063] + - [-18.0, -1.12797, 0.07744, -0.00342] + - [-16.0, -1.09392, 0.06122, -0.00587] + - [-14.0, -1.05961, 0.04667, -0.00652] + - [-12.0, -1.03121, 0.03302, -0.00755] + - [-10.0, -0.93706, 0.02027, -0.02243] + - [-8.0, -0.6738, 0.01168, -0.05583] + - [-6.0, -0.40391, 0.00918, -0.07159] + - [-4.0, -0.14226, 0.00839, -0.08123] + - [-2.0, 0.1158, 0.0081, -0.08892] + - [-1.0, 0.24382, 0.00808, -0.09235] + - [0.0, 0.37113, 0.00813, -0.09556] + - [1.0, 0.49766, 0.00824, -0.09857] + - [2.0, 0.62334, 0.00842, -0.10139] + - [3.0, 0.74798, 0.00867, -0.10403] + - [4.0, 0.87137, 0.00901, -0.10645] + - [5.0, 0.9932, 0.00945, -0.10863] + - [6.0, 1.11325, 0.00998, -0.11057] + - [7.0, 1.23037, 0.0107, -0.11214] + - [8.0, 1.34496, 0.01153, -0.11337] + - [9.0, 1.45407, 0.01269, -0.11396] + - [10.0, 1.55911, 0.01396, -0.11403] + - [11.0, 1.65779, 0.01545, -0.11336] + - [12.0, 1.74834, 0.01724, -0.11187] + - [13.0, 1.82666, 0.01961, -0.10935] + - [14.0, 1.88831, 0.02293, -0.10606] + - [15.0, 1.92579, 0.02795, -0.10238] + - [16.0, 1.92722, 0.03609, -0.09887] + - [18.0, 1.80055, 0.06534, -0.09497] + - [20.0, 1.63088, 0.10459, -0.09996] + - [24.0, 1.43345, 0.19148, -0.12589] + - [28.0, 1.28805, 0.28629, -0.15453] + - [32.0, 1.16356, 0.3946, -0.18396] + - [36.1429, 1.11321, 0.49645, -0.21099] + - [40.2857, 1.06444, 0.60319, -0.23768] + - [44.4286, 1.01259, 0.71263, -0.25992] + - [48.5714, 0.95478, 0.82249, -0.28216] + - [52.7143, 0.88932, 0.93051, -0.30323] + - [56.8571, 0.81542, 1.03447, -0.32368] + - [61.0, 0.73296, 1.13222, -0.3438] + - [65.1429, 0.64236, 1.22176, -0.36292] + - [69.2857, 0.5445, 1.30123, -0.38204] + - [73.4286, 0.44065, 1.36903, -0.39944] + - [77.5714, 0.33237, 1.42376, -0.41648] + - [81.7143, 0.22148, 1.46433, -0.43231] + - [85.8571, 0.10997, 1.4899, -0.44643] + - [90.0, 0.0, 1.5, -0.46055] + - [94.1429, -0.07698, 1.4899, -0.46732] + - [98.2857, -0.15503, 1.46433, -0.47409] + - [102.4286, -0.23266, 1.42376, -0.47695] + - [106.5714, -0.30846, 1.36903, -0.47705] + - [110.7143, -0.38115, 1.30123, -0.47627] + - [114.8571, -0.44965, 1.22176, -0.4713] + - [119.0, -0.51307, 1.13222, -0.46633] + - [123.1429, -0.5708, 1.03447, -0.4602] + - [127.2857, -0.62253, 0.93051, -0.4537] + - [131.4286, -0.66835, 0.82249, -0.44858] + - [135.5714, -0.70881, 0.71263, -0.44609] + - [139.7143, -0.74511, 0.60319, -0.4436] + - [143.8571, -0.77925, 0.49645, -0.44436] + - [148.0, -0.81449, 0.3946, -0.44537] + - [150.2857, -0.75631, 0.34128, -0.44368] + - [152.5714, -0.69814, 0.29043, -0.42628] + - [154.8571, -0.63996, 0.24237, -0.40888] + - [157.1429, -0.58178, 0.1974, -0.39148] + - [159.4286, -0.5236, 0.15581, -0.37408] + - [161.7143, -0.46542, 0.11786, -0.39207] + - [164.0, -0.40725, 0.08379, -0.42184] + - [166.2857, -0.34907, 0.05382, -0.45162] + - [168.5714, -0.29089, 0.02922, -0.48139] + - [170.8571, -0.23271, 0.023, -0.45714] + - [173.1429, -0.17453, 0.01811, -0.34286] + - [175.4286, -0.11636, 0.0146, -0.22857] + - [177.7143, -0.05818, 0.01248, -0.11429] + - [179.9087, 0.0, 0.01178, 0.0] + - name: FFA-W3-270blend + relative_thickness: 0.27 + data: + - [-179.9087, 0.0, 0.01545, 0.0] + - [-177.7143, 0.06213, 0.01611, 0.09143] + - [-175.4286, 0.12426, 0.01807, 0.18286] + - [-173.1429, 0.18639, 0.02133, 0.27429] + - [-170.8572, 0.24852, 0.02587, 0.36571] + - [-168.5716, 0.31064, 0.03289, 0.39874] + - [-166.2857, 0.37277, 0.05681, 0.39672] + - [-164.0, 0.4349, 0.08471, 0.3947] + - [-161.7145, 0.49703, 0.11643, 0.39268] + - [-159.4284, 0.55916, 0.15176, 0.39544] + - [-157.1428, 0.62129, 0.19048, 0.41254] + - [-154.8573, 0.68342, 0.23234, 0.42964] + - [-152.5714, 0.74555, 0.27708, 0.44674] + - [-150.2857, 0.80768, 0.32441, 0.46384] + - [-148.0, 0.86981, 0.37404, 0.46186] + - [-143.8571, 0.8166, 0.46882, 0.45335] + - [-139.7143, 0.76812, 0.56814, 0.44523] + - [-135.5714, 0.7204, 0.66995, 0.44237] + - [-131.4286, 0.67095, 0.77214, 0.43951] + - [-127.2857, 0.61828, 0.87258, 0.44072] + - [-123.1429, 0.56158, 0.96921, 0.44407] + - [-119.0, 0.50057, 1.06002, 0.44739] + - [-114.8571, 0.4354, 1.14315, 0.45063] + - [-110.7143, 0.36655, 1.21688, 0.45387] + - [-106.5714, 0.29475, 1.27969, 0.45377] + - [-102.4286, 0.22098, 1.3303, 0.45298] + - [-98.2857, 0.14639, 1.36768, 0.44973] + - [-94.1429, 0.07227, 1.39107, 0.44302] + - [-90.0, 0.0, 1.4, 0.4363] + - [-85.8571, -0.07227, 1.39107, 0.4218] + - [-81.7143, -0.14639, 1.36768, 0.4073] + - [-77.5714, -0.22098, 1.3303, 0.3902] + - [-73.4286, -0.29475, 1.27969, 0.37125] + - [-69.2857, -0.36655, 1.21688, 0.3519] + - [-65.1429, -0.4354, 1.14315, 0.33068] + - [-61.0, -0.50057, 1.06002, 0.30945] + - [-56.8571, -0.56158, 0.96921, 0.28815] + - [-52.7143, -0.61828, 0.87258, 0.26684] + - [-48.5714, -0.67095, 0.77214, 0.24576] + - [-44.4286, -0.7204, 0.66995, 0.22512] + - [-40.2857, -0.76812, 0.56814, 0.20447] + - [-36.1429, -0.8166, 0.46882, 0.13957] + - [-32.0, -0.86981, 0.37404, 0.07138] + - [-28.0, -1.09837, 0.2188, 0.044] + - [-24.0, -1.08339, 0.15982, 0.02166] + - [-20.0, -1.0699, 0.10744, 0.00422] + - [-18.0, -1.05454, 0.0869, -0.00035] + - [-16.0, -1.03432, 0.06844, -0.00334] + - [-14.0, -1.0836, 0.04733, -0.00283] + - [-12.0, -1.09489, 0.03085, -0.00556] + - [-10.0, -0.92665, 0.01984, -0.02952] + - [-8.0, -0.69676, 0.01439, -0.04822] + - [-6.0, -0.43628, 0.01155, -0.06483] + - [-4.0, -0.16252, 0.01026, -0.07919] + - [-2.0, 0.10709, 0.00976, -0.09041] + - [-1.0, 0.23993, 0.00967, -0.09517] + - [0.0, 0.37158, 0.00968, -0.09953] + - [1.0, 0.5021, 0.00976, -0.10355] + - [2.0, 0.63139, 0.00993, -0.10725] + - [3.0, 0.75951, 0.01016, -0.11068] + - [4.0, 0.88638, 0.01045, -0.11385] + - [5.0, 1.01172, 0.01082, -0.11673] + - [6.0, 1.1343, 0.0114, -0.11923] + - [7.0, 1.25536, 0.01198, -0.12145] + - [8.0, 1.37379, 0.01267, -0.12328] + - [9.0, 1.48841, 0.01353, -0.1246] + - [10.0, 1.59782, 0.0146, -0.12526] + - [11.0, 1.70005, 0.01597, -0.12505] + - [12.0, 1.7919, 0.01777, -0.1237] + - [13.0, 1.86782, 0.02035, -0.12093] + - [14.0, 1.92687, 0.02385, -0.11725] + - [15.0, 1.90901, 0.03236, -0.10931] + - [16.0, 1.88548, 0.04259, -0.10525] + - [18.0, 1.72106, 0.07672, -0.10292] + - [20.0, 1.54737, 0.11914, -0.11017] + - [24.0, 1.37176, 0.20189, -0.13431] + - [28.0, 1.33611, 0.27981, -0.15777] + - [32.0, 1.24258, 0.37404, -0.18432] + - [36.1429, 1.16657, 0.46882, -0.21002] + - [40.2857, 1.09731, 0.56814, -0.23531] + - [44.4286, 1.02914, 0.66995, -0.25508] + - [48.5714, 0.9585, 0.77214, -0.27485] + - [52.7143, 0.88325, 0.87258, -0.29346] + - [56.8571, 0.80225, 0.96921, -0.31145] + - [61.0, 0.7151, 1.06002, -0.32925] + - [65.1429, 0.622, 1.14315, -0.34641] + - [69.2857, 0.52364, 1.21688, -0.36357] + - [73.4286, 0.42107, 1.27969, -0.37949] + - [77.5714, 0.31569, 1.3303, -0.39517] + - [81.7143, 0.20913, 1.36768, -0.40983] + - [85.8571, 0.10324, 1.39107, -0.42306] + - [90.0, 0.0, 1.4, -0.4363] + - [94.1429, -0.07227, 1.39107, -0.44302] + - [98.2857, -0.14639, 1.36768, -0.44973] + - [102.4286, -0.22098, 1.3303, -0.45298] + - [106.5714, -0.29475, 1.27969, -0.45377] + - [110.7143, -0.36655, 1.21688, -0.45387] + - [114.8571, -0.4354, 1.14315, -0.45063] + - [119.0, -0.50057, 1.06002, -0.44739] + - [123.1429, -0.56158, 0.96921, -0.44407] + - [127.2857, -0.61828, 0.87258, -0.44072] + - [131.4286, -0.67095, 0.77214, -0.43951] + - [135.5714, -0.7204, 0.66995, -0.44237] + - [139.7143, -0.76812, 0.56814, -0.44523] + - [143.8571, -0.8166, 0.46882, -0.45335] + - [148.0, -0.86981, 0.37404, -0.46186] + - [150.2857, -0.80768, 0.32441, -0.46384] + - [152.5714, -0.74555, 0.27708, -0.44674] + - [154.8571, -0.68342, 0.23234, -0.42964] + - [157.1429, -0.62129, 0.19048, -0.41254] + - [159.4286, -0.55916, 0.15176, -0.39544] + - [161.7143, -0.49703, 0.11643, -0.40982] + - [164.0, -0.4349, 0.08471, -0.4347] + - [166.2857, -0.37277, 0.05681, -0.45958] + - [168.5714, -0.31064, 0.03289, -0.48445] + - [170.8571, -0.24852, 0.02587, -0.45714] + - [173.1429, -0.18639, 0.02133, -0.34286] + - [175.4286, -0.12426, 0.01807, -0.22857] + - [177.7143, -0.06213, 0.01611, -0.11429] + - [179.9087, 0.0, 0.01545, 0.0] + - name: FFA-W3-301 + relative_thickness: 0.301 + data: + - [-179.9087, 0.0, 0.02454, 0.0] + - [-177.7143, 0.06508, 0.02514, 0.09143] + - [-175.4286, 0.13016, 0.02694, 0.18286] + - [-173.1429, 0.19525, 0.02993, 0.27429] + - [-170.8572, 0.26033, 0.03408, 0.36571] + - [-168.5716, 0.32541, 0.03938, 0.40085] + - [-166.2857, 0.39049, 0.0591, 0.4022] + - [-164.0, 0.45557, 0.08495, 0.40356] + - [-161.7145, 0.52066, 0.11433, 0.40492] + - [-159.4284, 0.58574, 0.14704, 0.4101] + - [-157.1428, 0.65082, 0.1829, 0.42678] + - [-154.8573, 0.7159, 0.22166, 0.44345] + - [-152.5714, 0.78098, 0.26309, 0.46013] + - [-150.2857, 0.84607, 0.30692, 0.4768] + - [-148.0, 0.91115, 0.35287, 0.47162] + - [-143.8571, 0.84257, 0.44061, 0.45656] + - [-139.7143, 0.78187, 0.53255, 0.44202] + - [-135.5714, 0.72448, 0.62677, 0.43452] + - [-131.4286, 0.66755, 0.72131, 0.42701] + - [-127.2857, 0.60928, 0.81421, 0.42483] + - [-123.1429, 0.54868, 0.90355, 0.42544] + - [-119.0, 0.4853, 0.98748, 0.42634] + - [-114.8571, 0.41915, 1.06425, 0.42813] + - [-110.7143, 0.35056, 1.13227, 0.42992] + - [-106.5714, 0.28017, 1.19015, 0.42916] + - [-102.4286, 0.20881, 1.23669, 0.42788] + - [-98.2857, 0.13754, 1.27093, 0.42444] + - [-94.1429, 0.06751, 1.29218, 0.41794] + - [-90.0, 0.0, 1.3, 0.41144] + - [-85.8571, -0.06751, 1.29218, 0.39804] + - [-81.7143, -0.13754, 1.27093, 0.38464] + - [-77.5714, -0.20881, 1.23669, 0.36892] + - [-73.4286, -0.28017, 1.19015, 0.35157] + - [-69.2857, -0.35056, 1.13227, 0.33391] + - [-65.1429, -0.41915, 1.06425, 0.31474] + - [-61.0, -0.4853, 0.98748, 0.29557] + - [-56.8571, -0.54868, 0.90355, 0.27653] + - [-52.7143, -0.60928, 0.81421, 0.25754] + - [-48.5714, -0.66755, 0.72131, 0.23873] + - [-44.4286, -0.72448, 0.62677, 0.22027] + - [-40.2857, -0.78187, 0.53255, 0.20181] + - [-36.1429, -0.84257, 0.44061, 0.13644] + - [-32.0, -0.91115, 0.35287, 0.0676] + - [-28.0, -1.10349, 0.21721, 0.04231] + - [-24.0, -1.10737, 0.15629, 0.02026] + - [-20.0, -1.11815, 0.10335, 0.00407] + - [-18.0, -1.12332, 0.0818, 0.00017] + - [-16.0, -1.11865, 0.06331, -0.00167] + - [-14.0, -1.1162, 0.04718, -0.0012] + - [-12.0, -1.09588, 0.0328, -0.00463] + - [-10.0, -0.91767, 0.02351, -0.02494] + - [-8.0, -0.69311, 0.01793, -0.04304] + - [-6.0, -0.45396, 0.01431, -0.05868] + - [-4.0, -0.17779, 0.01242, -0.07601] + - [-2.0, 0.1048, 0.0116, -0.09121] + - [-1.0, 0.24383, 0.01143, -0.09763] + - [0.0, 0.38111, 0.01138, -0.10341] + - [1.0, 0.5166, 0.01143, -0.10861] + - [2.0, 0.65044, 0.01156, -0.11333] + - [3.0, 0.78267, 0.01177, -0.11762] + - [4.0, 0.91326, 0.01204, -0.12154] + - [5.0, 1.04207, 0.01239, -0.1251] + - [6.0, 1.16873, 0.01283, -0.12828] + - [7.0, 1.29296, 0.01338, -0.13104] + - [8.0, 1.4139, 0.01406, -0.13332] + - [9.0, 1.53088, 0.01488, -0.13503] + - [10.0, 1.64208, 0.01592, -0.13599] + - [11.0, 1.74568, 0.01726, -0.13605] + - [12.0, 1.83887, 0.01908, -0.13514] + - [13.0, 1.91764, 0.02169, -0.13322] + - [14.0, 1.97413, 0.02572, -0.1302] + - [15.0, 1.99916, 0.03222, -0.12641] + - [16.0, 1.99377, 0.04157, -0.12265] + - [18.0, 1.9172, 0.06731, -0.11675] + - [20.0, 1.73683, 0.10526, -0.11652] + - [24.0, 1.47321, 0.19229, -0.1379] + - [28.0, 1.36017, 0.27449, -0.16242] + - [32.0, 1.30164, 0.35287, -0.18463] + - [36.1429, 1.20367, 0.44061, -0.20894] + - [40.2857, 1.11695, 0.53255, -0.23276] + - [44.4286, 1.03498, 0.62677, -0.25011] + - [48.5714, 0.95364, 0.72131, -0.26746] + - [52.7143, 0.8704, 0.81421, -0.28365] + - [56.8571, 0.78383, 0.90355, -0.29923] + - [61.0, 0.69329, 0.98748, -0.31472] + - [65.1429, 0.59878, 1.06425, -0.32988] + - [69.2857, 0.5008, 1.13227, -0.34505] + - [73.4286, 0.40024, 1.19015, -0.35942] + - [77.5714, 0.29831, 1.23669, -0.37363] + - [81.7143, 0.19648, 1.27093, -0.38702] + - [85.8571, 0.09644, 1.29218, -0.39923] + - [90.0, 0.0, 1.3, -0.41144] + - [94.1429, -0.06751, 1.29218, -0.41794] + - [98.2857, -0.13754, 1.27093, -0.42444] + - [102.4286, -0.20881, 1.23669, -0.42788] + - [106.5714, -0.28017, 1.19015, -0.42916] + - [110.7143, -0.35056, 1.13227, -0.42992] + - [114.8571, -0.41915, 1.06425, -0.42813] + - [119.0, -0.4853, 0.98748, -0.42634] + - [123.1429, -0.54868, 0.90355, -0.42544] + - [127.2857, -0.60928, 0.81421, -0.42483] + - [131.4286, -0.66755, 0.72131, -0.42701] + - [135.5714, -0.72448, 0.62677, -0.43452] + - [139.7143, -0.78187, 0.53255, -0.44202] + - [143.8571, -0.84257, 0.44061, -0.45656] + - [148.0, -0.91115, 0.35287, -0.47162] + - [150.2857, -0.84607, 0.30692, -0.4768] + - [152.5714, -0.78098, 0.26309, -0.46013] + - [154.8571, -0.7159, 0.22166, -0.44345] + - [157.1429, -0.65082, 0.1829, -0.42678] + - [159.4286, -0.58574, 0.14704, -0.4101] + - [161.7143, -0.52066, 0.11433, -0.42206] + - [164.0, -0.45557, 0.08495, -0.44356] + - [166.2857, -0.39049, 0.0591, -0.46506] + - [168.5714, -0.32541, 0.03938, -0.48656] + - [170.8571, -0.26033, 0.03408, -0.45714] + - [173.1429, -0.19525, 0.02993, -0.34286] + - [175.4286, -0.13016, 0.02694, -0.22857] + - [177.7143, -0.06508, 0.02514, -0.11429] + - [179.9087, 0.0, 0.02454, 0.0] + - name: FFA-W3-330blend + relative_thickness: 0.33 + data: + - [-179.9087, 0.0, 0.03169, 0.0] + - [-177.7143, 0.0696, 0.03228, 0.09143] + - [-175.4286, 0.1392, 0.03406, 0.18286] + - [-173.1429, 0.2088, 0.03702, 0.27429] + - [-170.8572, 0.27841, 0.04114, 0.36571] + - [-168.5716, 0.34801, 0.04638, 0.40308] + - [-166.2857, 0.41761, 0.05732, 0.40801] + - [-164.0, 0.48721, 0.08319, 0.41294] + - [-161.7145, 0.55681, 0.11258, 0.41788] + - [-159.4284, 0.62641, 0.14533, 0.42586] + - [-157.1428, 0.69601, 0.18121, 0.44302] + - [-154.8573, 0.76562, 0.22, 0.46017] + - [-152.5714, 0.83522, 0.26146, 0.47732] + - [-150.2857, 0.90482, 0.30532, 0.49447] + - [-148.0, 0.97442, 0.35131, 0.48743] + - [-143.8571, 0.89412, 0.43913, 0.46839] + - [-139.7143, 0.82382, 0.53115, 0.44996] + - [-135.5714, 0.75845, 0.62546, 0.43985] + - [-131.4286, 0.69477, 0.7201, 0.42974] + - [-127.2857, 0.63079, 0.8131, 0.42589] + - [-123.1429, 0.56532, 0.90255, 0.42535] + - [-119.0, 0.49783, 0.98659, 0.42528] + - [-114.8571, 0.42823, 1.06348, 0.42673] + - [-110.7143, 0.3568, 1.13162, 0.42817] + - [-106.5714, 0.28412, 1.18963, 0.42745] + - [-102.4286, 0.21103, 1.23629, 0.42628] + - [-98.2857, 0.13851, 1.27067, 0.42303] + - [-94.1429, 0.06775, 1.29204, 0.41683] + - [-90.0, 0.0, 1.3, 0.41063] + - [-85.8571, -0.06775, 1.29204, 0.39752] + - [-81.7143, -0.13851, 1.27067, 0.38441] + - [-77.5714, -0.21103, 1.23629, 0.36905] + - [-73.4286, -0.28412, 1.18963, 0.35212] + - [-69.2857, -0.3568, 1.13162, 0.33491] + - [-65.1429, -0.42823, 1.06348, 0.31634] + - [-61.0, -0.49783, 0.98659, 0.29777] + - [-56.8571, -0.56532, 0.90255, 0.27947] + - [-52.7143, -0.63079, 0.8131, 0.26125] + - [-48.5714, -0.69477, 0.7201, 0.24322] + - [-44.4286, -0.75845, 0.62546, 0.22556] + - [-40.2857, -0.82382, 0.53115, 0.20789] + - [-36.1429, -0.89412, 0.43913, 0.13731] + - [-32.0, -0.97442, 0.35131, 0.0628] + - [-28.0, -1.16308, 0.20648, 0.03905] + - [-24.0, -1.14892, 0.15001, 0.01853] + - [-20.0, -1.09451, 0.106, 0.00441] + - [-18.0, -1.05801, 0.08732, -0.00061] + - [-16.0, -1.02281, 0.07051, -0.00342] + - [-14.0, -0.9981, 0.05474, -0.00401] + - [-12.0, -0.98515, 0.04052, -0.00272] + - [-10.0, -0.89583, 0.02929, -0.01198] + - [-8.0, -0.67539, 0.02207, -0.03458] + - [-6.0, -0.43247, 0.01735, -0.05466] + - [-4.0, -0.15881, 0.01473, -0.07425] + - [-2.0, 0.13456, 0.01362, -0.0927] + - [-1.0, 0.28014, 0.01339, -0.10074] + - [0.0, 0.42386, 0.0133, -0.10802] + - [1.0, 0.56519, 0.01333, -0.1145] + - [2.0, 0.7041, 0.01345, -0.12028] + - [3.0, 0.84071, 0.01366, -0.12546] + - [4.0, 0.975, 0.01397, -0.13011] + - [5.0, 1.1068, 0.01437, -0.13425] + - [6.0, 1.23603, 0.01486, -0.13793] + - [7.0, 1.36223, 0.01547, -0.14108] + - [8.0, 1.48424, 0.01623, -0.14363] + - [9.0, 1.60097, 0.01718, -0.14545] + - [10.0, 1.7101, 0.01841, -0.14636] + - [11.0, 1.80957, 0.0201, -0.14635] + - [12.0, 1.89473, 0.02258, -0.14544] + - [13.0, 1.95698, 0.02671, -0.14378] + - [14.0, 1.98576, 0.0338, -0.14185] + - [15.0, 1.9926, 0.04333, -0.14004] + - [16.0, 1.99617, 0.05354, -0.13823] + - [18.0, 1.96398, 0.07706, -0.13351] + - [20.0, 1.81179, 0.11169, -0.13135] + - [24.0, 1.56073, 0.19103, -0.1466] + - [28.0, 1.46798, 0.27199, -0.17242] + - [32.0, 1.39203, 0.35131, -0.19417] + - [36.1429, 1.27731, 0.43913, -0.21792] + - [40.2857, 1.17689, 0.53115, -0.24115] + - [44.4286, 1.0835, 0.62546, -0.25734] + - [48.5714, 0.99253, 0.7201, -0.27354] + - [52.7143, 0.90112, 0.8131, -0.28862] + - [56.8571, 0.8076, 0.90255, -0.30311] + - [61.0, 0.71119, 0.98659, -0.31757] + - [65.1429, 0.61175, 1.06348, -0.33194] + - [69.2857, 0.50971, 1.13162, -0.34631] + - [73.4286, 0.40589, 1.18963, -0.36014] + - [77.5714, 0.30146, 1.23629, -0.37385] + - [81.7143, 0.19788, 1.27067, -0.38681] + - [85.8571, 0.09679, 1.29204, -0.39872] + - [90.0, 0.0, 1.3, -0.41063] + - [94.1429, -0.06775, 1.29204, -0.41683] + - [98.2857, -0.13851, 1.27067, -0.42303] + - [102.4286, -0.21103, 1.23629, -0.42628] + - [106.5714, -0.28412, 1.18963, -0.42745] + - [110.7143, -0.3568, 1.13162, -0.42817] + - [114.8571, -0.42823, 1.06348, -0.42673] + - [119.0, -0.49783, 0.98659, -0.42528] + - [123.1429, -0.56532, 0.90255, -0.42535] + - [127.2857, -0.63079, 0.8131, -0.42589] + - [131.4286, -0.69477, 0.7201, -0.42974] + - [135.5714, -0.75845, 0.62546, -0.43985] + - [139.7143, -0.82382, 0.53115, -0.44996] + - [143.8571, -0.89412, 0.43913, -0.46839] + - [148.0, -0.97442, 0.35131, -0.48743] + - [150.2857, -0.90482, 0.30532, -0.49447] + - [152.5714, -0.83522, 0.26146, -0.47732] + - [154.8571, -0.76562, 0.22, -0.46017] + - [157.1429, -0.69601, 0.18121, -0.44302] + - [159.4286, -0.62641, 0.14533, -0.42586] + - [161.7143, -0.55681, 0.11258, -0.43502] + - [164.0, -0.48721, 0.08319, -0.45294] + - [166.2857, -0.41761, 0.05732, -0.47087] + - [168.5714, -0.34801, 0.04638, -0.4888] + - [170.8571, -0.27841, 0.04114, -0.45714] + - [173.1429, -0.2088, 0.03702, -0.34286] + - [175.4286, -0.1392, 0.03406, -0.22857] + - [177.7143, -0.0696, 0.03228, -0.11429] + - [179.9087, 0.0, 0.03169, 0.0] + - name: FFA-W3-360 + relative_thickness: 0.36 + data: + - [-179.9087, 0.0, 0.03715, 0.0] + - [-177.7143, 0.07178, 0.03774, 0.09143] + - [-175.4286, 0.14356, 0.03951, 0.18286] + - [-173.1429, 0.21534, 0.04245, 0.27429] + - [-170.8572, 0.28713, 0.04653, 0.36571] + - [-168.5716, 0.35891, 0.05174, 0.40313] + - [-166.2857, 0.43069, 0.06068, 0.40814] + - [-164.0, 0.50247, 0.08651, 0.41315] + - [-161.7145, 0.57425, 0.11586, 0.41816] + - [-159.4284, 0.64603, 0.14856, 0.42627] + - [-157.1428, 0.71781, 0.18439, 0.4437] + - [-154.8573, 0.7896, 0.22313, 0.46114] + - [-152.5714, 0.86138, 0.26453, 0.47857] + - [-150.2857, 0.93316, 0.30832, 0.496] + - [-148.0, 1.00494, 0.35424, 0.4883] + - [-143.8571, 0.91898, 0.44192, 0.46784] + - [-139.7143, 0.84406, 0.53379, 0.44803] + - [-135.5714, 0.77483, 0.62793, 0.43697] + - [-131.4286, 0.7079, 0.72238, 0.42591] + - [-127.2857, 0.64116, 0.8152, 0.4215] + - [-123.1429, 0.57335, 0.90444, 0.42058] + - [-119.0, 0.50388, 0.98826, 0.42024] + - [-114.8571, 0.43261, 1.06493, 0.42168] + - [-110.7143, 0.35981, 1.13285, 0.42312] + - [-106.5714, 0.28603, 1.19061, 0.42258] + - [-102.4286, 0.21209, 1.23704, 0.42163] + - [-98.2857, 0.13899, 1.27116, 0.41864] + - [-94.1429, 0.06787, 1.29229, 0.41277] + - [-90.0, 0.0, 1.3, 0.4069] + - [-85.8571, -0.06787, 1.29229, 0.39426] + - [-81.7143, -0.13899, 1.27116, 0.38162] + - [-77.5714, -0.21209, 1.23704, 0.36676] + - [-73.4286, -0.28603, 1.19061, 0.35033] + - [-69.2857, -0.35981, 1.13285, 0.33362] + - [-65.1429, -0.43261, 1.06493, 0.31561] + - [-61.0, -0.50388, 0.98826, 0.29759] + - [-56.8571, -0.57335, 0.90444, 0.27989] + - [-52.7143, -0.64116, 0.8152, 0.2623] + - [-48.5714, -0.7079, 0.72238, 0.24491] + - [-44.4286, -0.77483, 0.62793, 0.22794] + - [-40.2857, -0.84406, 0.53379, 0.21097] + - [-36.1429, -0.91898, 0.44192, 0.13525] + - [-32.0, -1.00494, 0.35424, 0.05517] + - [-28.0, -1.11306, 0.20494, 0.03211] + - [-24.0, -1.05425, 0.15434, 0.01268] + - [-20.0, -0.98247, 0.10967, -0.00282] + - [-18.0, -0.94173, 0.09249, -0.00741] + - [-16.0, -0.89333, 0.07597, -0.01107] + - [-14.0, -0.85472, 0.06054, -0.0125] + - [-12.0, -0.82348, 0.04641, -0.01177] + - [-10.0, -0.79541, 0.03441, -0.01082] + - [-8.0, -0.6365, 0.02548, -0.02769] + - [-6.0, -0.39095, 0.01994, -0.05107] + - [-4.0, -0.13071, 0.01653, -0.07148] + - [-2.0, 0.16173, 0.01507, -0.09179] + - [-1.0, 0.31121, 0.01477, -0.10119] + - [0.0, 0.45956, 0.01465, -0.10988] + - [1.0, 0.60566, 0.01466, -0.11776] + - [2.0, 0.74868, 0.01481, -0.12477] + - [3.0, 0.88862, 0.01507, -0.13098] + - [4.0, 1.02544, 0.01544, -0.13648] + - [5.0, 1.15878, 0.01593, -0.1413] + - [6.0, 1.28822, 0.01654, -0.1454] + - [7.0, 1.41282, 0.01731, -0.14875] + - [8.0, 1.5309, 0.01831, -0.15118] + - [9.0, 1.64065, 0.01963, -0.15262] + - [10.0, 1.73926, 0.0215, -0.1531] + - [11.0, 1.81971, 0.02445, -0.15254] + - [12.0, 1.87065, 0.02966, -0.15121] + - [13.0, 1.89221, 0.0377, -0.14969] + - [14.0, 1.8791, 0.04824, -0.14562] + - [15.0, 1.88111, 0.05838, -0.14358] + - [16.0, 1.86359, 0.06992, -0.14095] + - [18.0, 1.73324, 0.10166, -0.13711] + - [20.0, 1.59357, 0.13916, -0.14082] + - [24.0, 1.46708, 0.21002, -0.15693] + - [28.0, 1.44834, 0.282, -0.17979] + - [32.0, 1.43563, 0.35424, -0.20147] + - [36.1429, 1.31283, 0.44192, -0.22409] + - [40.2857, 1.2058, 0.53379, -0.24619] + - [44.4286, 1.1069, 0.62793, -0.26133] + - [48.5714, 1.01129, 0.72238, -0.27648] + - [52.7143, 0.91594, 0.8152, -0.29062] + - [56.8571, 0.81907, 0.90444, -0.30424] + - [61.0, 0.71982, 0.98826, -0.31787] + - [65.1429, 0.61801, 1.06493, -0.33154] + - [69.2857, 0.51401, 1.13285, -0.34522] + - [73.4286, 0.40862, 1.19061, -0.35846] + - [77.5714, 0.30299, 1.23704, -0.37161] + - [81.7143, 0.19855, 1.27116, -0.38405] + - [85.8571, 0.09695, 1.29229, -0.39547] + - [90.0, 0.0, 1.3, -0.4069] + - [94.1429, -0.06787, 1.29229, -0.41277] + - [98.2857, -0.13899, 1.27116, -0.41864] + - [102.4286, -0.21209, 1.23704, -0.42163] + - [106.5714, -0.28603, 1.19061, -0.42258] + - [110.7143, -0.35981, 1.13285, -0.42312] + - [114.8571, -0.43261, 1.06493, -0.42168] + - [119.0, -0.50388, 0.98826, -0.42024] + - [123.1429, -0.57335, 0.90444, -0.42058] + - [127.2857, -0.64116, 0.8152, -0.4215] + - [131.4286, -0.7079, 0.72238, -0.42591] + - [135.5714, -0.77483, 0.62793, -0.43697] + - [139.7143, -0.84406, 0.53379, -0.44803] + - [143.8571, -0.91898, 0.44192, -0.46784] + - [148.0, -1.00494, 0.35424, -0.4883] + - [150.2857, -0.93316, 0.30832, -0.496] + - [152.5714, -0.86138, 0.26453, -0.47857] + - [154.8571, -0.7896, 0.22313, -0.46114] + - [157.1429, -0.71781, 0.18439, -0.4437] + - [159.4286, -0.64603, 0.14856, -0.42627] + - [161.7143, -0.57425, 0.11586, -0.4353] + - [164.0, -0.50247, 0.08651, -0.45315] + - [166.2857, -0.43069, 0.06068, -0.471] + - [168.5714, -0.35891, 0.05174, -0.48884] + - [170.8571, -0.28713, 0.04653, -0.45714] + - [173.1429, -0.21534, 0.04245, -0.34286] + - [175.4286, -0.14356, 0.03951, -0.22857] + - [177.7143, -0.07178, 0.03774, -0.11429] + - [179.9087, 0.0, 0.03715, 0.0] + pitch_control: + GS_Angles: [0.06019804, 0.08713416, 0.10844806, 0.12685912, 0.14339822, + 0.1586021, 0.17279614, 0.18618935, 0.19892772, 0.21111989, 0.22285021, + 0.23417256, 0.2451469, 0.25580691, 0.26619545, 0.27632495, 0.28623134, + 0.29593266, 0.30544521, 0.314779, 0.32395154, 0.33297489, 0.3418577, + 0.35060844, 0.35923641, 0.36774807, 0.37614942, 0.38444655, 0.39264363, + 0.40074407] + GS_Kp: [-0.9394215, -0.80602855, -0.69555026, -0.60254912, -0.52318192, + -0.45465531, -0.39489024, -0.34230736, -0.29568537, -0.25406506, + -0.2166825, -0.18292183, -0.15228099, -0.12434663, -0.09877533, + -0.0752794, -0.05361604, -0.0335789, -0.01499149, 0.00229803, 0.01842102, + 0.03349169, 0.0476098, 0.0608629, 0.07332812, 0.0850737, 0.0961602, + 0.10664158, 0.11656607, 0.12597691] + GS_Ki: [-0.07416547, -0.06719673, -0.0614251, -0.05656651, -0.0524202, + -0.04884022, -0.04571796, -0.04297091, -0.04053528, -0.03836094, + -0.03640799, -0.03464426, -0.03304352, -0.03158417, -0.03024826, + -0.02902079, -0.02788904, -0.02684226, -0.02587121, -0.02496797, + -0.02412567, -0.02333834, -0.02260078, -0.02190841, -0.0212572, + -0.02064359, -0.0200644, -0.01951683, -0.01899836, -0.01850671] + Fl_Kp: -9.35 + wt_ops: + v: [3.0, 3.266896551724138, 3.533793103448276, 3.800689655172414, + 4.067586206896552, 4.334482758620689, 4.601379310344828, + 4.868275862068966, 5.135172413793104, 5.402068965517241, + 5.6689655172413795, 5.935862068965518, 6.2027586206896554, + 6.469655172413793, 6.736551724137931, 7.00344827586207, + 7.270344827586207, 7.537241379310345, 7.804137931034483, + 8.071034482758622, 8.337931034482759, 8.604827586206897, + 8.871724137931036, 9.138620689655173, 9.405517241379311, + 9.672413793103448, 9.939310344827586, 10.206206896551725, + 10.473103448275863, 10.74, 11.231724137931035, 11.723448275862069, + 12.215172413793104, 12.706896551724139, 13.198620689655172, + 13.690344827586207, 14.182068965517242, 14.673793103448276, + 15.16551724137931, 15.657241379310346, 16.14896551724138, + 16.640689655172416, 17.13241379310345, 17.624137931034483, + 18.11586206896552, 18.607586206896553, 19.099310344827586, + 19.591034482758623, 20.082758620689653, 20.57448275862069, + 21.066206896551726, 21.557931034482756, 22.049655172413793, + 22.54137931034483, 23.03310344827586, 23.524827586206897, + 24.016551724137933, 24.508275862068963, 25.0] + pitch_op: [-0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, + -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, + -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, + -0.25, 3.57152, 5.12896, 6.36736, 7.43866, 8.40197, 9.28843, 10.1161, + 10.8974, 11.641, 12.3529, 13.038, 13.6997, 14.3409, 14.9642, 15.5713, + 16.1639, 16.7435, 17.3109, 17.8673, 18.4136, 18.9506, 19.4788, 19.9989, + 20.5112, 21.0164, 21.5147, 22.0067, 22.4925, 22.9724] + omega_op: [2.1486, 2.3397, 2.5309, 2.722, 2.9132, 3.1043, 3.2955, 3.4866, + 3.6778, 3.8689, 4.0601, 4.2512, 4.4424, 4.6335, 4.8247, 5.0159, 5.207, + 5.3982, 5.5893, 5.7805, 5.9716, 6.1628, 6.3539, 6.5451, 6.7362, 6.9274, + 7.1185, 7.3097, 7.5008, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, + 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, + 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56, 7.56] + gear_ratio: 1 + torque_control: + VS_KP: -38609162.66552 + VS_KI: -4588245.1872 + tower: + dlsMax: 5.0 + name: tower + type: 1 + rA: [0, 0, 15] + rB: [0, 0, 144.582] + shape: circ + gamma: 0.0 + stations: [15, 28, 28.001, 41, 41.001, 54, 54.001, 67, 67.001, 80, 80.001, + 93, 93.001, 106, 106.001, 119, 119.001, 132, 132.001, 144.582] + d: [10, 9.964, 9.964, 9.967, 9.967, 9.927, 9.927, 9.528, 9.528, 9.149, 9.149, + 8.945, 8.945, 8.735, 8.735, 8.405, 8.405, 7.321, 7.321, 6.5] + t: [0.082954, 0.082954, 0.083073, 0.083073, 0.082799, 0.082799, 0.0299, + 0.0299, 0.027842, 0.027842, 0.025567, 0.025567, 0.022854, 0.022854, + 0.02025, 0.02025, 0.018339, 0.018339, 0.021211, 0.021211] + Cd: 0.0 + Ca: 0.0 + CdEnd: 0.0 + CaEnd: 0.0 + rho_shell: 7850 +array_mooring: + anchor_keys: [ID, type, x, y, embedment] + anchor_data: [] + line_keys: [MooringConfigID, endA, endB, headingA, headingB, lengthAdjust] + line_data: [] +mooring_systems: + ms0: + keys: [MooringConfigID, heading, anchorType, lengthAdjust] + data: + - ['0', 150.0, drag-embedment1, 0] + - ['0', 270.0, drag-embedment1, 0] + - ['0', 30.0, drag-embedment1, 0] +mooring_line_configs: + '0': + name: '0' + span: 642.0 + sections: + - type: 0 + length: 497.7 + - connectorType: h_link + - type: 1 + length: 199.8 +mooring_line_types: + 0: + name: 0 + d_vol: 0.27882 + m: 479.88020000000006 + EA: 2053741190.7845445 + w: 4093.6781602294 + MBL: 20893381.207590003 + EAd: 0.0 + EAd_Lm: 0.0 + d_nom: 0.1549 + cost: 2005.5584560000004 + notes: made with getLineProps + material: chain + Cd: 1.333 + CdAx: 0.639 + Ca: 1.0 + CaAx: 0.5 + 1: + name: 1 + d_vol: 0.14405282886514317 + m: 22.491196000000002 + EA: 142830688.0 + w: 56.75848886217392 + MBL: 10202192.0 + EAd: 118345427.2 + EAd_Lm: 40.0 + d_nom: 0.182 + cost: 441.9688 + notes: made with getLineProps + material: polyester + Cd: 2.021 + CdAx: 0.0 + Ca: 1.1 + CaAx: 0.15 +mooring_connector_types: + h_link: + m: 140.0 + v: 0.13 + type: h_link + CdA: 0 +anchor_types: + drag-embedment1: + type: DEA + A: 10 + zlug: 10 +cables: [] +dynamic_cable_configs: {} +cable_types: {} +cable_appendages: {} diff --git a/examples/example_anchors.py b/examples/example_anchors.py deleted file mode 100644 index 95bd77ed..00000000 --- a/examples/example_anchors.py +++ /dev/null @@ -1,148 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Example showing how to call forces and -anchor capacity functions, along with safety factors and material costs. -""" -# import necessary packages -from famodel.project import Project -import os - -dir = os.path.dirname(os.path.realpath(__file__)) - -# set yaml file location and name -ontology_file = dir+'\OntologySample200m_1turb.yaml' - -# create project class -project = Project(file=ontology_file) -project.getMoorPyArray() - -# let's choose a single anchor from the array to look at -anch = project.anchorList['fowt0a'] - -# now let's get the mudline and lug forces on this anchor -anch.getLugForces() # getLugForces calls getMudlineForces() to get the anchor forces at both locations - -# establish a factor of safety in horizontal (Ha) and vertical (Va) directions -minfs = {'Ha': 1.8, 'Va': 2} - -# let's get the loads with the factor of safety included -loads_with_FS = {'Ha':anch.loads['Ha']*minfs['Ha'],'Va':anch.loads['Va']*minfs['Va']} - -# get anchor capacity for one anchor (this case is for suction pile in clay) -anch.getAnchorCapacity(loads=loads_with_FS) # loads are used in capacity calculation, so let's send in the loads with factor of safety applied - -# get anchor cost -startGeom = [10,2,6.6] -geomKeys = ['L','D','zlug'] -geomBounds = [(5, 50), (1, 7), (3.3,16.7)] -FSDiff_max = {'Ha':5,'Va':5} -anch.getSize(startGeom,geomKeys,geomBounds,minfs=minfs,FSdiff_max=FSDiff_max, plot=True) -anch.getCost() -print('\nClay suction pile capacity is: ',anch.anchorCapacity) -print('Clay suction pile safety factor is: ',anch.getFS()) -print('Clay suction pile cost is: ', anch.cost,'\n') -# try suction pile with sand -newdd = anch.dd -anch.soilProps['sand'] = anch.soilProps.pop('mud_firm') -anch.soilProps['sand']['phi'] = 33 -anch.soilProps['sand']['Dr'] = 70 -anch.soilProps['sand']['delta'] = 25 -# update anchor loads at lug point (mudline load should be constant), then get anchor capacity -anch.getLugForces() -anch.getSize(startGeom,geomKeys,geomBounds,plot=True) -anch.getAnchorCapacity(loads=loads_with_FS) -anch.getCost() -print('\nSand suction pile capacity is: ',anch.anchorCapacity,' N') -print('Sand suction pile safety factor is: ',anch.getFS()) -print('Sand suction pile cost is: ', anch.cost,' USD\n') - -# check plate anchor type -newdd['type'] = 'DEA' -newdd['design'] = {'type':'DEA','A':20,'zlug':20,'beta':10} -anch.soilProps['clay'] = anch.soilProps.pop('sand') - -startGeom = [10,20] -geomKeys = ['A','zlug'] - -anch.getLugForces() -anch.getAnchorCapacity(loads=loads_with_FS) -# let's fix the zlug for the plate anchor - set fix_zlug=True to prevent it being changed -anch.getSize(startGeom,geomKeys,minfs={'Ha':2,'Va':0}, fix_zlug = True) -anch.getCost() -print('\nClay plate capacity is: ',anch.anchorCapacity,' N') -print('Clay plate safety factor is: ',anch.getFS()) -print('Clay plate cost is: ', anch.cost,' USD\n') - -# check drilled and grouted pile anchor type -newdd['type'] = 'dandg_pile' -newdd['design'] = {'type':'dandg_pile','L':50,'D':3,'zlug':0} -anch.soilProps['rock'] = anch.soilProps.pop('clay') # soil_properties has default rock info in there already, just change name - -# startGeom = [5,50] -# geomKeys = ['L','D'] -anch.getLugForces() -# anch.getSize(startGeom,geomKeys,minfs={'Ha':2,'Va':2}) -anch.getAnchorCapacity(loads=loads_with_FS) -print('\nRock drilled and grouted pile capacity is: ',anch.anchorCapacity,' N') -print('Rock drilled and grouted pile safety factor is: ',anch.getFS()) - -# check driven pile anchor in rock -newdd['type'] = 'driven' -anch.soilProps['weak_rock'] = anch.soilProps.pop('rock') -newdd['design'] = {'type':'driven','L':20,'D':1.5,'zlug':-3} # zlug should be negative (above mudline) for rock! - -anch.getLugForces() -anch.getAnchorCapacity(loads=loads_with_FS) -print('\nWeak rock driven pile capacity is: ',anch.anchorCapacity,' N') -print('Weak rock driven pile safety factor is: ',anch.getFS()) - -# check driven pile anchor in clay -anch.soilProps['clay'] = anch.soilProps.pop('weak_rock') -newdd['design'] = {'type':'driven','L':40,'D':4,'zlug':10} - -anch.getLugForces() -anch.getAnchorCapacity(loads=loads_with_FS) -print('\nClay driven pile capacity is: ',anch.anchorCapacity,' N') -print('Clay driven pile safety factor is: ',anch.getFS()) - -# check driven pile anchor in sand -anch.soilProps['sand'] = anch.soilProps.pop('clay') -anch.soilProps['sand']['Dr'] = 50 - -anch.getLugForces() -anch.getAnchorCapacity(loads=loads_with_FS) -print('\nSand driven pile capacity is: ',anch.anchorCapacity,' N') -print('Sand driven pile safety factor is: ',anch.getFS()) - -# check helical pile anchor with sand -newdd['type'] = 'helical_pile' -newdd['design'] = {'type':'helical_pile','L':25.1,'d':1,'D':5.01, 'zlug':5} - -anch.getLugForces() -anch.getAnchorCapacity(loads=loads_with_FS) -print('\nSand helical pile capacity is: ',anch.anchorCapacity,' N') -print('Sand helical pile safety factor is: ',anch.getFS()) - -# check helical pile anchor with clay -anch.soilProps['clay'] = anch.soilProps.pop('sand') -newdd['type'] = 'helical_pile' -newdd['design'] = {'type':'helical_pile','L':25.1,'d':1,'D':5.01,'zlug':5} - -anch.getLugForces() -anch.getAnchorCapacity(loads=loads_with_FS) -print('\nClay helical pile capacity is: ',anch.anchorCapacity,' N') -print('Clay helical pile safety factor is: ',anch.getFS()) - -# check torpedo anchor in clay -newdd['type'] = 'torpedo_pile' -newdd['design'] = {'type':'torpedo_pile','D1':3,'D2':1.1,'L1':10,'L2':4,'zlug':16} - -anch.getLugForces() -anch.getAnchorCapacity(loads=loads_with_FS) -print('\nClay torpedo pile capacity is: ',anch.anchorCapacity,' N') -print('Clay torpedo pile safety factor is: ',anch.getFS()) - - - - - diff --git a/examples/example_driver.py b/examples/example_driver.py index 730535c2..690062f9 100644 --- a/examples/example_driver.py +++ b/examples/example_driver.py @@ -76,27 +76,35 @@ # plot motion envelopes with 2d plot project.plot2d(save=True,plot_bathymetry=False) - +#%% Section 5: Anchor capabilities #### get anchor capacities, loads, and safety factors #### print('\nGetting anchor capacities, loads, and safety factors\n') # let's look at one anchor in the farm # define anchor to analyze anchor = project.anchorList['FOWT1a'] -# get anchor capacity -anchor.getAnchorCapacity() + +name, soil_def = project.getSoilAtLocation(anchor.r[0], anchor.r[1]) +profile_map = [{'name': name, 'layers': soil_def['layers']}] +anchor.setSoilProfile(profile_map) + +Hm = anchor.loads['Hm'] +Vm = anchor.loads['Vm'] +zlug = anchor.dd['design']['zlug'] + +# Now use these in lug and capacity checks +anchor.getLugForces(Hm, Vm, zlug) +anchor.getCapacityAnchor(Hm, Vm, zlug) capacities = anchor.anchorCapacity -# get anchor loads at mudline and anchor lug depth (if applicable) -loads = anchor.getLugForces() + # size an anchor -starting_geometry = [15,20] # geometry values -starting_geom_labels = ['A','zlug'] # corresponding labels for the geometry list -min_safety_factors = {'Ha':2,'Va':2} # minimum safety factors -FSdiff_max = {'Ha':.1,'Va':.1} # allowable difference between actual and desired FS for final result -anchor.getSize(starting_geometry, starting_geom_labels, minfs=min_safety_factors, - FSdiff_max=FSdiff_max) +geom_start = [anchor.dd['design']['B'], anchor.dd['design']['L']] # geometry values +geom_labels = ['B','L'] # corresponding labels for the geometry list +geom_bounds = [(0.5, 4.0), (0.5, 4.0)] +safety_factor = {'SF_combined': 1.0} # minimum safety factors +anchor.getSizeAnchor(geom_start, geom_labels, geom_bounds, loads = None, safety_factor={'SF_combined': 1.0}) # get safety factor -sfs = anchor.getFS() +sfs = anchor.getSafetyFactor() print('\nAnchor safety factors: ',sfs) # NOTE that Va will show as 'inf' because there is no vertical force on the anchor. diff --git a/famodel/anchors/AnchorDesign_temp.py b/famodel/anchors/AnchorDesign_temp.py new file mode 100644 index 00000000..2223096e --- /dev/null +++ b/famodel/anchors/AnchorDesign_temp.py @@ -0,0 +1,672 @@ +# -*- coding: utf-8 -*- +""" +temp storage of different anchor sizing functions that use different +optimization methods. These were built-in methods to Anchor class. + +Eventually can be converted into a full AnchorDesign class... +""" + +def getSizeAnchor(self, geom, geomKeys, geomBounds=None, loads=None, lambdap_con=[4, 8], + zlug_fix=True, safety_factor={}, plot=False, display=0): + ''' + Generalized optimization method for all anchor types, using dictionary-based safety factors. + ''' + self.display = display + + anchType_clean = self.dd['type'].strip().lower() + print(f"[Debug] Anchor type parsed: '{anchType_clean}'") + + if loads is None: + loads = self.loads + + sf_Hm = safety_factor.get('Hm', safety_factor.get('SF_horizontal', 1.0)) + sf_Vm = safety_factor.get('Vm', safety_factor.get('SF_vertical', 1.0)) + sf_uc = safety_factor.get('SF_combined', max(sf_Hm, sf_Vm)) # conservative by default + + Hm = loads['Hm']*sf_Hm + Vm = loads['Vm']*sf_Vm + + line_type = getattr(self, 'line_type', 'chain') + d = getattr(self, 'd', 0.16) + w = getattr(self, 'w', 5000.0) + + def update_zlug(): + if 'suction' in anchType_clean and not zlug_fix and 'zlug' not in geomKeys: + self.dd['design']['zlug'] = (2/3)*self.dd['design']['L'] + elif np.any([name in anchType_clean for name in ['driven', 'helical']]) and not zlug_fix: + ratio = self.dd['design'].get('zlug_ratio', self.dd['design']['zlug']/self.dd['design']['L']) + self.dd['design']['zlug_ratio'] = ratio + self.dd['design']['zlug'] = ratio*self.dd['design']['L'] + elif 'drilled' in anchType_clean: + self.dd['design']['zlug'] = 0 + + def get_lambda(): + if 'torpedo' in anchType_clean: + L = self.dd['design']['L1'] + self.dd['design']['L2'] + A_wing = (self.dd['design']['D1'] - self.dd['design']['D2']) * self.dd['design']['L1'] + A_shaft = self.dd['design']['D2'] * L + D = (A_wing + A_shaft) / L + elif np.any([name in anchType_clean for name in ['driven', 'drilled', 'helical', 'suction']]): + L = self.dd['design']['L'] + D = self.dd['design']['D'] + elif np.any([name in anchType_clean for name in ['plate', 'sepla', 'dea', 'depla', 'vla']]): + L = self.dd['design']['L'] + D = self.dd['design']['B'] + else: + raise ValueError(f'lambda not defined for anchor type: {anchType_clean}') + return L/D + + def constraint_lambda_min(vars): + for i, key in enumerate(geomKeys): + self.dd['design'][key] = vars[i] + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + return get_lambda() - lambdap_con[0] + + def constraint_lambda_max(vars): + return lambdap_con[1] - get_lambda() + + def constraint_bounds(vars): + con_bound_return = np.zeros(len(geomKeys)*2) + for i,var in enumerate(geomKeys): + con_bound_return[2*i] = self.dd['design'][var] - geomBounds[i][0] + con_bound_return[2*i+1] = geomBounds[i][1] - self.dd['design'][var] + return con_bound_return + + if np.any([name in anchType_clean for name in ['suction', 'torpedo', 'plate', 'sepla', 'dea', 'depla', 'vla']]): + target_UC = 1.0/sf_uc + + def objective_uc(vars): + ''' + for i, key in enumerate(geomKeys): + self.dd['design'][key] = vars[i] + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + ''' + #UC = self.anchorCapacity.get('UC', 2.0) + #return (UC - target_UC)**2 + #return self.anchorCapacity.get('Weight pile') + if any(name in anchType_clean for name in ['plate', 'sepla', 'dea', 'depla', 'vla']): + return self.anchorCapacity.get('Weight plate') + else: + return self.anchorCapacity.get('Weight pile') + + def constraint_uc_envelope(vars): + return self.anchorCapacity.get('UC', 0.0) - target_UC + + constraints_uc = [ + {'type': 'ineq', 'fun': constraint_lambda_min}, + {'type': 'ineq', 'fun': constraint_lambda_max}, + {'type': 'ineq', 'fun': constraint_uc_envelope}, + {'type': 'ineq', 'fun': constraint_bounds}, + ] + + result_uc = minimize( + objective_uc, + geom, + method='COBYLA', + constraints=constraints_uc, + options={'rhobeg': 0.1, 'catol': 0.01, 'maxiter': 500} + ) + + endGeom = dict(zip(geomKeys, result_uc.x)) + self.dd['design'].update(endGeom) + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=plot, display=display) + + print('\nFinal Optimized Anchor (UC-based):') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + + def near_border(): + UC_h = self.anchorCapacity['Ha']/self.anchorCapacity['Hmax'] + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + limit_lat = 0.05*self.dd['design']['D'] # 10% of the pile diameter + limit_rot = 10.0 # 10 deg + + near_UC_h = 0.95 <= UC_h <= 1.0 + near_UC_v = 0.95 <= UC_v <= 1.0 + near_disp_lat = 0.95*limit_lat <= disp_lat <= limit_lat + near_disp_rot = 4.75 <= disp_rot <= limit_rot + + return near_UC_h or near_UC_v or near_disp_lat or near_disp_rot + + def termination_condition(): + UC_h = self.anchorCapacity['Ha']/self.anchorCapacity['Hmax'] + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + limit_lat = 0.05*self.dd['design']['D'] # 10% of the pile diameter + limit_rot = 10.0 # 10 deg + + all_satisfied = (UC_h <= 1.0 and UC_v <= 1.0 and disp_lat <= limit_lat and disp_rot <= limit_rot) + + if all_satisfied: + if near_border(): + if self.display > 0: print('[Termination] All criteria satisfied and near border.') + return 'terminate' + else: + if self.display > 0: print('[Safe but not near border] Continue shrinking...') + return 'continue' + return 'continue' + + def termination_condition_drilled(): + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + limit_lat = 0.05*self.dd['design']['D'] # 10% of the pile diameter + limit_rot = 10.0 # 10 deg + + all_satisfied = (UC_v <= 1.0 and disp_lat <= limit_lat and disp_rot <= limit_rot) + + if all_satisfied: + if near_border(): + if self.display > 0: print('[Termination] All criteria satisfied and near border.') + return 'terminate' + else: + if self.display > 0: print('[Safe but not near border] Continue shrinking...') + return 'continue' + return 'continue' + + def is_valid(value): + return np.isfinite(value) and not np.isnan(value) and abs(value) < 1e6 + + if anchType_clean in ['helical', 'driven']: + L0, D0 = geom if len(geom) == 2 else [5.0, 1.0] + self.dd['design']['L'] = L0 + self.dd['design']['D'] = D0 + Lmin, Lmax = geomBounds[0] + Dmin, Dmax = geomBounds[1] + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + + UC_h = self.anchorCapacity['Ha']/self.anchorCapacity['Hmax'] + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + limit_disp = 0.10*D0 # 10% of the pile diameter + limit_rot = 10.0 # 10 deg + direction = 'shrink' if (UC_h <= 1.0 and UC_v <= 1.0 and disp_lat <= limit_disp and disp_rot <= limit_rot) else 'grow' + + max_iter = 200 + iter_count = 0 + + if direction == 'shrink': + for L in np.arange(L0, Lmin - 1e-6, -0.25): + self.dd['design']['L'] = L + for D in np.arange(Dmax, Dmin - 1e-6, -0.05): + if L/D > lambdap_con[1] or L/D < lambdap_con[0]: + continue + self.dd['design']['L'] = L + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + UC_h = self.anchorCapacity['Ha']/self.anchorCapacity['Hmax'] + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + if self.display > 0: print(f'[Iter {iter_count}] L={L:.2f}, D={D:.2f}, UC_h={UC_h:.3f}, UC_v={UC_v:.3f}, lat={disp_lat:.3f} m, rot={disp_rot:.3f} deg') + iter_count += 1 + if not all(is_valid(v) for v in [UC_h, UC_v, disp_lat, disp_rot]): + continue + if termination_condition(): + print(f'\nTermination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + elif direction == 'grow': + for L in np.arange(L0, Lmax + 1e-6, 0.25): + self.dd['design']['L'] = L + for D in np.arange(Dmin, Dmax + 1e-6, 0.05): + if L/D > lambdap_con[1] or L/D < lambdap_con[0]: + continue + self.dd['design']['L'] = L + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + UC_h = self.anchorCapacity['Ha']/self.anchorCapacity['Hmax'] + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + if self.display > 0: print(f'[Iter {iter_count}] L={L:.2f}, D={D:.2f}, UC_h={UC_h:.3f}, UC_v={UC_v:.3f}, lat={disp_lat:.3f} m, rot={disp_rot:.3f} deg') + iter_count += 1 + status = termination_condition() + if status == 'terminate': + print(f'Termination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + elif status == 'continue': + continue + status = termination_condition() + if status == 'terminate': + print(f'\nTermination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + else: + raise ValueError(f"Unknown optimization direction: {direction}") + + if self.display > 0: print('[Warning] While-loop search reached bounds without meeting criteria.') + + if 'drilled' in anchType_clean: + L0, D0 = geom if len(geom) == 2 else [5.0, 1.0] + self.dd['design']['L'] = L0 + self.dd['design']['D'] = D0 + Lmin, Lmax = geomBounds[0] + Dmin, Dmax = geomBounds[1] + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + limit_disp = 0.10*D0 # 10% of the pile diameter + limit_rot = 10.0 # 10 deg + direction = 'shrink' if (UC_v <= 1.0 and disp_lat <= limit_disp and disp_rot <= limit_rot) else 'grow' + + max_iter = 200 + iter_count = 0 + + if direction == 'shrink': + for L in np.arange(L0, Lmin - 1e-6, -0.25): + self.dd['design']['L'] = L + for D in np.arange(Dmax, Dmin - 1e-6, -0.05): + if L/D > lambdap_con[1] or L/D < lambdap_con[0]: + continue + self.dd['design']['L'] = L + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + if self.display > 0: print(f'[Iter {iter_count}] L={L:.2f}, D={D:.2f}, UC_v={UC_v:.3f}, lat={disp_lat:.3f} m, rot={disp_rot:.3f} deg') + iter_count += 1 + if not all(is_valid(v) for v in [UC_v, disp_lat, disp_rot]): + continue + if termination_condition_drilled(): + print(f'\nTermination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + elif direction == 'grow': + for L in np.arange(L0, Lmax + 1e-6, 0.25): + self.dd['design']['L'] = L + for D in np.arange(Dmin, Dmax + 1e-6, 0.05): + if L/D > lambdap_con[1] or L/D < lambdap_con[0]: + continue + self.dd['design']['L'] = L + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + if self.display > 0: print(f'[Iter {iter_count}] L={L:.2f}, D={D:.2f}, UC_v={UC_v:.3f}, lat={disp_lat:.3f} m, rot={disp_rot:.3f} deg') + iter_count += 1 + status = termination_condition_drilled() + if status == 'terminate': + print(f'Termination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + elif status == 'continue': + continue + status = termination_condition_drilled() + if status == 'terminate': + print(f'\nTermination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + else: + raise ValueError(f"Unknown optimization direction: {direction}") + + if self.display > 0: print('[Warning] While-loop search reached bounds without meeting criteria.') + + else: + raise ValueError(f"Anchor type '{anchType_clean}' not supported for safety factor input.") + +def getSizeAnchor2(self, geom, geomBounds=None, loads=None, lambdap_con=[3, 6], + zlug_fix=True, safety_factor={}, plot=False): + ''' + Grid-based optimization method for envelope anchors (suction, torpedo, plate). + Evaluates UC over a grid of L and D, and selects the point closest to target UC. + ''' + import matplotlib.pyplot as plt + from matplotlib import cm + import matplotlib.colors as mcolor + import numpy as np + + anchType_clean = self.dd['type'].lower().replace('', '') + + if loads is None: + loads = self.loads + + sf_uc = safety_factor.get('SF_combined', 1.0) + sf_Hm = safety_factor.get('Hm', 1.0) + sf_Vm = safety_factor.get('Vm', 1.0) + + Hm = loads['Hm']*sf_Hm + Vm = loads['Vm']*sf_Vm + + line_type = getattr(self, 'line_type', 'chain') + d = getattr(self, 'd', 0.16) + w = getattr(self, 'w', 5000.0) + + if anchType_clean not in ['suction', 'torpedo', 'plate']: + raise ValueError(f"Grid-based getSizeAnchor only supports envelope anchors, not '{anchType_clean}'") + + UC_target = 1.0/sf_uc + + # Unpack bounds and generate grid + L_vals = np.linspace(geomBounds[0][0], geomBounds[0][1], 10) + D_vals = np.linspace(geomBounds[1][0], geomBounds[1][1], 10) + + L_grid, D_grid = np.meshgrid(L_vals, D_vals) + UC_grid = np.full_like(L_grid, np.nan, dtype=float) + mask = np.full_like(L_grid, False, dtype=bool) + + best_UC, best_L, best_D = None, None, None + results = [] + + for i in range(D_grid.shape[0]): # loop over D + for j in range(D_grid.shape[1]): # loop over L + D = D_grid[i, j] + L = L_grid[i, j] + lambdap = L/D + + if not (lambdap_con[0] <= lambdap <= lambdap_con[1]): + continue + + mask[i, j] = True + self.dd['design']['L'] = L + self.dd['design']['D'] = D + + if anchType_clean == 'suction' and not zlug_fix: + self.dd['design']['zlug'] = (2/3)*L + + try: + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, + mass_update=True, plot=False) + UC = self.anchorCapacity.get('UC', np.nan) + results.append({ + 'L': L, + 'D': D, + 'UC': UC}) + + if UC > 1e-2 and UC < 10.0: + UC_grid[i, j] = UC + # Find UC closest to target + if best_UC is None or abs(UC - UC_target) < abs(best_UC - UC_target): + best_UC = UC + best_L = L + best_D = D + + except: + continue + + # Update best result + # if best_L is not None and best_D is not None: + self.dd['design']['L'] = best_L + self.dd['design']['D'] = best_D + if anchType_clean == 'suction' and not zlug_fix: + self.dd['design']['zlug'] = (2/3)*best_L + + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, + mass_update=True, plot=plot) + + print('\nFinal Optimized Anchor (Grid-based):') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + + # else: + # print('[Warning] No valid combination found in the grid.') + + # Optional plot + + if plot: + fig, ax = plt.subplots(figsize=(6, 8)) + vmin, vmax = 0.01, 10 + levels = np.logspace(np.log10(vmin), np.log10(vmax), 21) + cp = ax.contourf(D_grid, L_grid, UC_grid, levels=levels, cmap='coolwarm', norm=mcolor.LogNorm(vmin=vmin, vmax=vmax)) + fig.colorbar(cp, ax=ax, label='Unity check (UC)') + ax.contour(D_grid, L_grid, UC_grid, levels=levels, colors='k', linewidths=0.3, alpha=0.3) + ax.contour(D_grid, L_grid, UC_grid, levels=[1.0], colors='red', linewidths=2, linestyles='--') + ax.set_xlabel('Diameter (m)') + ax.set_ylabel('Length (m)') + ax.set_title('Unity Check (UC') + ax.plot(best_D, best_L, 'ro', label='Best match') + ax.annotate('Best match', (best_D, best_L), textcoords="offset points", xytext=(10,10), ha='center', color='red') + ax.legend() + plt.grid(True) + plt.tight_layout() + plt.show() + + #UC_target = 1.0 + closest = min(results, key=lambda x: abs(x['UC'] - UC_target)) + print("Closest to UC_target:") + print(closest) + + return results + +def getSizeAnchor_BO(self, + geom=[10.0, 2.0], + geomKeys=['L', 'D'], + geomBounds=[(5.0, 15.0), (1.0, 4.0)], + loads=None, + lambdap_con=[3, 6], + zlug_fix=False, + safety_factor={'SF_combined': 1.0}, + n_calls=25, + plot=False, + verbose=True): + ''' + Bayesian optimization to find (D, L) for UC closest to UC_target. + Uses scikit-optimize for surrogate model and efficient sampling. + ''' + from skopt import gp_minimize + from skopt.space import Real + from skopt.utils import use_named_args + import numpy as np + + if loads is None: + loads = self.loads + + Hm = loads['Hm'] + Vm = loads['Vm'] + + line_type = getattr(self, 'line_type', 'chain') + d = getattr(self, 'd', 0.16) + w = getattr(self, 'w', 5000.0) + + UC_target = 1.0 / safety_factor.get('SF_combined', 1.0) + + # Define the search space + space = [ + Real(geomBounds[1][0], geomBounds[1][1], name='D'), + Real(geomBounds[0][0], geomBounds[0][1], name='L') + ] + + @use_named_args(space) + def objective(**params): + D = params['D'] + L = params['L'] + + # Apply lambda constraint + lambdap = L/D + if not (lambdap_con[0] <= lambdap <= lambdap_con[1]): + return 100.0 + + self.dd['design']['D'] = D + self.dd['design']['L'] = L + if not zlug_fix: + self.dd['design']['zlug'] = (2/3)*L + + try: + self.getCapacityAnchor( + Hm=Hm, + Vm=Vm, + zlug=self.dd['design']['zlug'], + line_type=line_type, + d=d, + w=w, + mass_update=True, + plot=False) + + UC = self.anchorCapacity.get('UC', np.nan) + except: + UC = np.nan + + if verbose: + print(f"Evaluated D={D:.3f}, L={L:.3f} -> UC={UC:.3f}") + + if not np.isfinite(UC): + return 100.0 + + if UC < UC_target: + return (UC_target - UC)**2 * 0.5 # less penalty for overdesign + else: + return (UC - UC_target)**2 * 10 # higher penalty for failure + + # Run Bayesian optimization + res = gp_minimize( + objective, + space, + x0=[geom[1], geom[0]], + n_calls=n_calls, + random_state=42, + verbose=verbose + ) + + # Best result + best_D, best_L = res.x + self.dd['design']['D'] = best_D + self.dd['design']['L'] = best_L + if not zlug_fix: + self.dd['design']['zlug'] = (2/3)*best_L + + self.getCapacityAnchor( + Hm=Hm, + Vm=Vm, + zlug=self.dd['design']['zlug'], + line_type=line_type, + d=d, + w=w, + mass_update=True, + plot=plot + ) + UC = self.anchorCapacity.get('UC', np.nan) + + print('\nBayesian Optimized Anchor:') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + print(f'Best UC: {UC:.4f} (target: {UC_target})') + + results = {'D': best_D, 'L': best_L, 'UC': UC, 'result': res} + + return results +# PATCH for GRADIENT method: wrap getCapacityAnchor in safe evaluator +def safe_get_uc(self, Hm, Vm, zlug, line_type, d, w, verbose=False): + try: + self.getCapacityAnchor(Hm, Vm, zlug, line_type, d, w, True, False) + return self.anchorCapacity.get('UC', np.nan) + except Exception as e: + if verbose: + print(f"[Safe Error] {str(e)}") + return np.nan + +def getSizeAnchor_gradient(self, + geom=[10.0, 2.0], + geomKeys=['L', 'D'], + geomBounds=[(5.0, 15.0), (1.0, 4.0)], + loads=None, + lambdap_con=[3, 6], + zlug_fix=False, + safety_factor={'SF_combined': 1.0}, + step_size=0.2, + tol=0.05, + max_iter=30, + verbose=True): + ''' + Gradient-based optimization with early stopping to match UC_target. + ''' + import numpy as np + + if loads is None: + loads = self.loads + + Hm = loads['Hm'] + Vm = loads['Vm'] + + line_type = getattr(self, 'line_type', 'chain') + d = getattr(self, 'd', 0.16) + w = getattr(self, 'w', 5000.0) + + UC_target = 1.0 / safety_factor.get('SF_combined', 1.0) + + L, D = geom + + for iter in range(max_iter): + lambdap = L / D + if not (lambdap_con[0] <= lambdap <= lambdap_con[1]): + if verbose: + print(f"[Iter {iter}] λ = {lambdap:.2f} out of bounds. Terminating.") + break + + self.dd['design']['L'] = L + self.dd['design']['D'] = D + if not zlug_fix: + self.dd['design']['zlug'] = (2/3)*L + + UC0 = self.safe_get_uc(Hm, Vm, self.dd['design']['zlug'], line_type, d, w, verbose=verbose) + + if not np.isfinite(UC0): + break + + if verbose: + print(f"[Iter {iter}] L={L:.2f}, D={D:.2f}, UC={UC0:.3f}") + + if abs(UC0 - UC_target) < tol: + print("Early stopping: UC within tolerance.") + break + + # Gradient estimate + delta = 0.1 + UC_L = self.safe_get_uc(Hm, Vm, (2/3)*(L + delta), line_type, d, w, verbose=verbose) + UC_D = self.safe_get_uc(Hm, Vm, (2/3)*L, line_type, d, w, verbose=verbose) + + grad_L = (UC_L - UC0)/delta if np.isfinite(UC_L) else 0.0 + grad_D = (UC_D - UC0)/delta if np.isfinite(UC_D) else 0.0 + + # Update + L -= step_size * grad_L + D -= step_size * grad_D + L = np.clip(L, geomBounds[0][0], geomBounds[0][1]) + D = np.clip(D, geomBounds[1][0], geomBounds[1][1]) + + if not (lambdap_con[0] <= L/D <= lambdap_con[1]): + if verbose: + print("Terminated: lambda constraint violated after update.") + break + + self.dd['design']['L'] = L + self.dd['design']['D'] = D + self.dd['design']['zlug'] = (2/3)*L + self.getCapacityAnchor(Hm, Vm, self.dd['design']['zlug'], line_type, d, w, True, True) + + print('\nGradient Optimized Anchor:') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + + return {'D': D, 'L': L, 'UC': self.anchorCapacity.get('UC', np.nan)} \ No newline at end of file diff --git a/famodel/anchors/README.md b/famodel/anchors/README.md index 84788f66..bbce4321 100644 --- a/famodel/anchors/README.md +++ b/famodel/anchors/README.md @@ -1,229 +1,666 @@ # Anchors Library -This subpackage of FAModel contains the Anchor class as well as modules for anchor capacity -calculations. +This subpackage of FAModel contains the anchor class and all modules for the capacity under extreme loads and the installation assessments -## Anchor Class -The anchor class contains properties and methods related to mooring anchors. -The supported anchor types are below, with the associated FAModel name in italics. -- Plate anchors - - *DEA* (drag-embedment anchors) - - *SEPLA* (suction embedded plate anchors) - - *DEPLA* (dynamically embedded plate anchors) - - *VLA* (vertically loaded anchors) - - *plate* (unspecified plate anchor) -- *suction_pile* (Suction caisson/ suction bucket anchors) -- *torpedo_pile* (Torpedo pile anchors) -- *helical_pile* (Helical pile anchors) -- *driven_pile* (Driven pile anchors) -- *dandg_pile* (Drilled and grouted piles) - - -The anchor class stores properties and methods that enable a wide range of modeling - from capacity to cost to loads, and more. The [anchor capacity modules](#anchor-capacity-modules) are integrated with the anchor class through the getAnchorCapacity() method. -### Anchor Properties -- **r** : anchor [x,y,z] position -- **dd** : anchor design dictionary, containing geometric properties, soil properties at the anchor location, cost -- **ms** : moorpy system associated with this anchor point -- **aNum** : anchor index in array mooring list (generally only used for shared moorings) -- **mpAnchor** : moorpy point object that models this anchor -- **anchorCapacity** : dictionary with horizontal and vertical capacity of the anchor. Generally these are loads in [N], but can also be displacements (generally for driven or drilled and grouted piles) -- **loads** : dictionary of loads on the anchor, and the method used to obtain these loads (static or dynamic modeling). Loads include horizontal (H) and vertical (V) loads, as well as the angle of the load (theta). The keys for these loads will either include an m (for loads at the mudline) or a (for loads at the anchor lug). -- **soilProps** : dictionary of soil property information at the location of the anchor -- **failure_probability** : dictionary of probabilities for failure of the anchor +## Seabed Conditions +Introduction to different soil types -### Anchor Methods -- **makeMoorPyAnchor()** : Creates a MoorPy point object representing the anchor in a moorpy system -- **getAnchorCapacity()** : Calls anchor capacity functions for the correct anchor type -- **getFS()** : Computes safety factor for loads on the anchor -- **getCost()** : Finds costs of anchor from MoorProps and stores in design dictionary -- **getMass()** : Finds mass and/or UHC of anchor from MoorProps and stores in design dictionary -- **getMudlineForces()** : Finds forces on anchor at mudline using MoorPy Point.getForces method. Use max_force=True to obtain the maximum forces on that anchor from the platform.getWatchCircle() method. For more information on the getWatchCircle() calculations, see the [Platform ReadMe](../platform/README.md). An additional anchor.loads dictionary entry is included to describe the mudline load type. 'mudline_load_type'='max' if max_force=True, and 'mudline_load_type'='current_state' if max_force=False. -- **getLugForces()** : Finds forces at the anchor lug location with getTransferFunction function in capacity_loads.py. -The getTransferLoad function requires **maximum** mudline forces as an input. These forces can be sent in as a dictionary, or anchor.loads dictionary will be searched for 'Hm' and 'Vm' values with additional key-value pair 'mudline_force_type':'max' to indicate these mudline forces are maximums. -If there are no max mudline forces in the anchor.loads dictionary, getMudlineForces(max_force=True) will be called. Stores results in loads dictionary. If lug is at mudline or no lug provided, equates mudline forces with lug forces. ->[!NOTE] ->The getTransferFunction function called by getLugForces() is tuned to work with maximum loads on the anchor. Some anchor configuration, load, and soil condition combinations may produce invalid results in getTransferFunction. For example, the output Va may show as negative. In that case, getLugForces() will warn the user of the invalidity of the result and assign the anchor lug forces = mudline forces. +Heterogenous soil (mixed layers). Map of soil properties for horizontal and vertical spatial-variability. +The reference elevation of the pile is the pile head (z = 0 m), from here all elevations are derived. Thus, Z0 (mudline elevation) is the distance between the pile head and the top of the first layer of soil. Main padeye locations depend on their relative elevation to z0, if zlug > z0 mooring line is embedded below the mudline elevation +### Soil properties +##### Input +- profile_map + - location_name: CPT or reference in the system (-) + - x, y: coordinates of the anchor within the lease area (m), (m) + - layers (at least one): + - top, bottom: depth for top and bottom for each layer (m), (m) + - soil_type: clay/mud, sand and (weak) rock (-) + - soil properties: + - clay/mud: + - gamma: submerged soil unit weight (kN/m³) + - Su: undrained shear strength (kPa) + - sand: + - gamma: submerged soil unit weight: (kN/m³) + - phi: internal friction angle (deg) + - Dr: relative density (%) + - (weak) rock, + - UCS: unconfined compressive strength at failure (MPa) + - Em: rock mass modulus (MPa) -### Anchor Type Requirements +>[!NOTE] +Driven piles are only possible on weak rock, defined here as up to UCS = 5 MPa -Different geometric properties and soil conditions are needed for each anchor type. See the [Anchor Capacity Modules](#anchor-capacity-modules) section for details on the requirements of each anchor type. +> [!IMPORTANT] +Units within FAModel follow the SI exclusively. The input soil parameters units follow common industry convention. Soil parameters conversion units to Pa and N/m³ take place in the capacity_soils module exclusively. There is no need to convert units. + profile_map = [ + { + 'name': 'CPT_1', + 'x': 498234, 'y': 5725141, + 'layers': [ + { + 'top': 1.0, 'bottom': 6.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 8.0, + 'Su_top': 10, 'Su_bot': 50}, + { + 'top': 6.0, 'bottom': 15.0, + 'soil_type': 'sand', + 'gamma_top': 8.0, 'gamma_bot': 8.0, + 'phi_top': 32, 'phi_bot': 38, + 'Dr_top': 70, 'Dr_bot': 75}, + { + 'top': 15.0, 'bottom': 30.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 9.0, + 'Su_top': 100, 'Su_bot': 200}] + } + ] + Note: + - z0 = 1 m, meaning the pile head is 1 m above the mudline + - soil_type: clay, sand, clay + - this method allows different soil types and gaps in between soil layers of the same or different soil type +##### Output +- z0: depth of the mudline relative to the pile head (m) +- soil types: + - clay/mud: + - f_gamma: effective unit soil weigtht at depth (N/m³) + - f_Su: undrained shear strength at depth (Pa) + - f_sigma_v_eff: effective vertical stress at depth (Pa) + - f_alpha: adhesion factor from API correlation (-) + - sand: + - f_gamma: effective unit soil weigtht at depth (N/m³) + - f_phi: friction angle at depth (deg) + - f_sigma_v_eff: effective vertical stress at depth (Pa) + - f_Dr: relative density at depth (%) + - f_delta: skin friction angle at depth (-) + - rock: + - f_UCS: unconfined compressive strength at depth (Pa) + - f_Em: rock mass modulus at depth (deg) +------------------------------------------------------------------------------ -## Anchor Capacity Modules -The following list shows the required soil conditions, soil properties, geometry, and load information for anchor capacity calculations of each anchor type. Soil classification for clay and sand can be found in [Soil Classification Parameters](#soil-classification-parameters). +Soil classification for clay, sand and rock can be found in [Soil Classification Parameters](#soil-classification-parameters). >[!NOTE] ->Some anchor capacity functions require input loads at the anchor lug point. These loads can be sent in to the getAnchorCapacity() method, or the getAnchorCapacity() method will calculate the loads by calling getLugLoads(). The input loads must be maximum or large loads on the anchor. - -### DEA/SEPLA/DEPLA/VLA/plate - - soil condition: clay/mud - - Su0 (undrained shear strength of soil at mudline) [kPa] - - k (rate of change in shear strength with depth) [kPa/m] - - gamma (submerged soil unit weight) [kN/m^3] - - geometry - - A (area of plate) [m^2] - - zlug (embedded depth of bridle/padeye below mudline - positive is below mudline, negative is above mudline) [m] - - beta (OPTIONAL - angle of plate after keying) [deg] - - loads: None -### suction_pile (Suction caisson/ suction bucket anchors) - - soil conditions - - sand - - phi (internal friction angle) [deg] - - Dr (relative density) [%] - - delta (interface friction angle at soil-anchor line) [deg] ***only needed for loads calculation* - - clay/mud - - Su0 (undrained shear strength of soil at mudline) [kPa] - - k (rate of change in shear strength with depth) [kPa/m] - - alpha (adhesion factor) [-] - - geometry - - L (length of pile) [m] - - D (diameter of pile) [m] - - zlug (embedded depth of padeye below mudline) [m] - - loads - - Ha, Va (horizontal and vertical loads on padeye of anchor) -### torpedo_pile (Torpedo pile anchors) - - soil condition: clay/mud - - Su0 (undrained shear strength of soil at mudline) [kPa] - - k (rate of change in shear strength with depth) [kPa/m] - - alpha (adhesion factor) [-] - - geometry - - D1 (wing diameter) [m] - - D2 (shaft diameter) [m] - - L1 (wing length) [m] - - L2 (shaft length) [m] - - zlug (embedded depth of padeye below mudline) [m] - - loads: None -### helical_pile (Helical pile anchors) - - soil conditions - - sand - - phi (internal friction angle) [deg] - - gamma (submerged soil unit weight) [kN/m^3] - - alpha_star (empirical adhesion factor **can use alpha instead*) [-] - - clay/mud - - Su0 (undrained shear strength of soil at mudline) [kPa] - - k (rate of change in shear strength with depth) [kPa/m] - - gamma (submerged soil unit weight) [kN/m^3] - - alpha_star (empirical adhesion factor **can use alpha instead*) [-] - - geometry - - D (helix diameter) [m] - - L (shaft length) [m] - - d (shaft diameter) [m] - - loads: None -### driven_pile (Driven pile anchors) - - soil conditions: - - weak rock (up to UCS = 5 MPa) - - UCS (unconfined compressive strength at failure) - - Em (rock mass modulus) - - sand - - phi (internal friction angle) [deg] - - gamma (submerged soil unit weight) [kN/m^3] - - Dr (relative density) [%] - - clay/mud - - Su0 (undrained shear strength of soil at mudline) [kPa] - - k (rate of change in shear strength with depth) [kPa/m] - - gamma (submerged soil unit weight) [kN/m^3] - - geometry - - L (length of pile) [m] - - D (diameter of pile) [m] - - zlug (embedded depth of padeye below mudline) [m] - - loads - - Ha, Va (horizontal and vertical loads on padeye of anchor) - - #### Output notes - The general output is a lateral and rotational displacement or bending moment. In getAnchorCapacity, the driven pile capacity function is called in a while loop with incremented horizontal input forces until one of the displacements goes past set failure criteria, thus providing a horizontal force capacity output [N]. Vertical capacity [N] is already calculated within the driven pile capacity function. +>Some anchor capacity functions require input loads at the anchor lug point. These loads can be sent in to the getLugLoads() method, or the getAnchorCapacity() method will calculate the loads by calling getLugLoads(). +The input loads must be maximum or large loads on the anchor. + +### Soil classification parameters + +The soft, medium and hard clay soil classes are distinguished by the following parameter ranges: +| clay/mud | N-Value | Eff. unit weight, gamma (kN/m³) | Void ratio, e (-) | Water content, (%) | Undrained shear strength, Su (kN/m2) | +|:-----------------:|:--------:|:---------------------------------:|:----------:|:--------------------------------------:|:-------------------------------:| +| Very Soft | 0 - 2 | 5.5 - 8.5 | 0.9 - 1.4 | 30 - 50 | 0 - 12.5 | +| Soft | 2 - 4 | 5.5 - 8.5 | 0.9 - 1.4 | 30 - 50 | 12.5 - 25 | +| Medium | 4 - 8 | 5.5 - 8.5 | 0.9 - 1.4 | 30 - 50 | 25 - 50 | +| Stiff | 8 - 15 | 8.5 - 12 | ~ 0.6 | 20 - 30 | 50 - 100 | +| Very Stiff | 15 - 30 | 8.5 - 12 | ~ 0.6 | 20 - 30 | 100 - 200 | +| Hard | < 30 | 8.5 - 12 | ~ 0.6 | 20 - 30 | > 200 | + + +Sand can also be classified ranging from soft to hard. and are chracterize by the following ranges: + +| sand | N-Value | Eff. unit weight, gamma (kN/m³) | Void ratio, e (-) | Water content, (%)| Eff. friction angle, phi (deg) | Relative density, Dr (%) | +|:----------------:|:--------:|:----------------------------:|:----------:|:--------------------------------------:|:-------------------:|:--------------------:| +| Very Loose | > 4 | 7 - 9.5 | ~ 0.8 | 25 - 30 | < 30 | < 15 | +| Loose | 4 - 10 | 7 - 9.5 | ~ 0.8 | 25 - 30 | 30 - 35 | 15 - 35 | +| Compact | 10 - 30 | 9.5 - 11.5 | ~ 0.45 | 12 - 16 | 35 - 40 | 35 - 65 | +| Dense | 30 - 50 | 9.5 - 11.5 | ~ 0.45 | 12 - 16 | 40 - 45 | 65 - 85 | +| Very Dense | < 50 | 9.5 - 11.5 | ~ 0.45 | 12 - 16 | > 45 | > 85 | + +## Anchor Types +The supported anchor types are listed below with their associated FAModel labels in italics (*Labels are not case sensitive*). Anchors types have specific [anchor capacity](#anchor-capacity-modules) and [anchor installation](#anchor-installation-modules) application modules, these are shown for clarity below as well. + +| | Capacity | Installation | +|--------------------------------------------------------|----------------|--------------| +|*DEA* (drag-embedment anchors) | Plate | Drag | +|*SEPLA* (suction embedded plate anchors) | Plate | Suction | +|*DEPLA* (dynamically embedded plate anchors) | Plate | Dynamic | +|*VLA* (vertically loaded anchors) | Plate | Drag | +|*suction* (suction caisson/suction bucket anchors) | Suction | Suction | +|*torpedo* (torpedo pile anchors) | Torpedo | Dynamic | +|*helical* (helical pile anchors) | Helical/Driven | Torque-crowd | +|*driven* (driven pile anchors) | Driven | Driven | +|*dandg* (drilled and grouted pile anchors) | Drilled&Grout | Drilled | + +### Anchor geometrical properties +#### DEA/SEPLA/DEPLA/VLA/plate +##### Short definition of the anchor concepts included in plates. Variables involved in the design: +- soil condition: + - z, gamma, Su: clay soil parameters (m), (kN/m3), (kPa) +- geometry: + - B: width of plate - dimension contained in the vertical plane (m) + - L: length of plate - dimension perpendicular to the vertical plane (m) + - zlug: embedded depth of bridle/padeye below mudline (m) + - beta: angle of plate with horizontal plane (deg) +- loads: + - Ha, Va: horizontal and vertical loads on padeye of anchor (N), (N) - For non-rock soil, the hinge (bending moment) is also considered as a failure mode along with the lateral and rotational displacement *IF* the zlug is positive (below the mudline) -### dandg_pile (Drilled and grouted piles) - - soil condition: rock - - UCS (unconfined compressive strength at failure) - - Em (rock mass modulus) - - geometry - - L (length of pile) [m] - - D (diameter of pile) [m] - - zlug (lug location (lug above mudline has negative zlug)) [m] - - loads - - Ha, Va (horizontal and vertical loads on padeye of anchor) -#### Output notes - The general output is a lateral and rotational displacement. In getAnchorCapacity, the drilled and grouted pile function is called in a while loop with incremented horizontal input forces until one of the displacements goes past set failure criteria, thus providing a horizontal force capacity output [N]. Vertical capacity [N] is already calculated within the driven pile capacity function. +#### suction_pile (suction caisson/ suction bucket anchors) +##### Short definition of the suction anchor. Variables involved in the design: +- soil condition: + - location_name: + - x, y: CPT or reference name + - layers: + - z, gamma, Su: clay soil parameters (m), (kN/m3), (kPa) + - z, gamma, phi, Dr: sand soil parameters (m), (kN/m3), (deg), (%) + +- geometry: + - D: diameter of pile (m) + - L: length of pile (m) + - zlug: embedded depth of padeye below mudline (m) +- loads: + - Ha, Va: horizontal and vertical loads on padeye of anchor (N), (N) + +#### torpedo_pile (torpedo pile anchors) +##### Short definition of the suction anchor. Variables involved in the design: +- soil condition: + - z, gamma, Su: clay soil parameters () +- geometry + - D1: wing diameter (m) + - D2: shaft diameter (m) + - L1: wing length (m) + - L2: shaft length (m) + - zlug: embedded depth of padeye below mudline (m) +- loads + - Ha, Va: horizontal and vertical loads on padeye of anchor (N), (N) + +#### helical_pile (helical pile anchors) +##### Short definition of the helical anchor. Variables involved in the design: +- soil condition: + - z, gamma, Su: clay soil parameters (m), (kN/m3), (kPa) + - z, gamma, phi, Dr: sand soil parameters (m), (kN/m3), (deg), (%) +- geometry + - D: helix diameter (m) + - L: shaft length (m) + - d: shaft diameter (m) + - zlug: embedded depth of padeye below mudline (m) +- loads + - Ha, Va: horizontal and vertical loads on padeye of anchor (N), (N) + +#### driven_pile (driven pile anchors) +##### Short definition of the helical anchor. Variables involved in the design: +- soil condition: + - z, gamma, Su: clay soil parameters (m), (kN/m3), (kPa) + - z, gamma, phi, Dr: sand soil parameters (m), (kN/m3), (deg), (%) + - z, UCS, Em: (weak) rock parameters (m), (MPa), (MPa) +- geometry + - L: length of pile (m) + - D: diameter of pile (m) + - zlug: embedded depth of padeye below mudline (m) +- loads + - Ha, Va: horizontal and vertical loads on padeye of anchor (N), (N) + +> [IMPORTANT!] The general output is a lateral and rotational displacement. In getCapacityAnchor, the driven pile capacity function is called in a while loop with variable (increase or decrease) input geometrical properties until at least one of the accepting criteria past set failure criteria, thus providing a horizontal force capacity output. + + > [NOTE!] For non-rock soil, the hinge (bending moment) is also considered as a failure mode along with the lateral and rotational displacement -------------------------------------------------------------------------------- -> [!IMPORTANT] -> A positive zlug denotes a lug/padeye/bridle below the mudline, while a negative zlug denotes a lug/padeye/bridle above the mudline. Anchors in rock should have a zlug >= 0. +#### dandg_pile (drilled and grouted pile anchors) +##### Short definition of the helical anchor. Variables involved in the design: +- soil condition: + - z, UCS, Em: (weak) rock parameters (m), (MPa), (MPa) +- geometry + - L: length of pile (m) + - D: diameter of pile (m) + - zlug: lug location (m) +- loads + - Ha, Va: horizontal and vertical loads on padeye of anchor + +## Loads +Loads derived from MoorPy and DRAFT are considered at a fixed point at mudline elevation. These loads need to be transfered from mudline to lug penetration when the main padeye is below the mudline. The transfer function uses soil properties (profile), mooring line properties (line_type, d and w), loads and lueg depth (zlug) to calculate loads at lug elevation (main padeye) + +> [!NOTE] It is cautious to condiser as input the tension load magnitude at mudline since the load will be equal or larger to the tension at lug penetration. Conversely, the angle of the load at lug penetration will equal or larger to the angle at mudline. Therefore, yielding to more vertical componenent. Therefore, Tm >= Ta and thetam <= thetaa + +##### Input +- profile_map: soil profile +- Tm: tension of the load on mudline (N) +- thetam: angle of the load on mudline (deg) +- zlug: main padeye embeddment (m) +- line_type: type of mooring line ('chain' or 'wire') (-) +- d: mooring line diameter (m) +- w: mooring line unit weight (N/m) + +##### Output +- Ta: tension of the load on padeye of anchor (N) +- thetaa: angle of the load on padeye of anchor (deg) +- Ha: horizontal component of the load on padeye (N) +- Va: vertical component of the load on padeye (N) +- length: length of the embedded line (m) +- drag: depth of the embedded line (m) + + +The getTransferLoad function expects maximum mudline forces as input. These can be: + + - Passed directly as a dictionary + - Retrieved from the anchor.loads dictionary using the keys 'Hm' and 'Vm', with the flag 'mudline_force_type': 'max'. + +If no such values are found, getMudlineForces(max_force=True) will be called automatically to obtain them. + +When the lug is located at the mudline, or no lug depth is specified, the function assumes lug forces are equal to mudline forces. + +>[!NOTE] See getLugForces() (#anchor-capacity-modules) for more details on the load transfer mechanism from mudline to lug elevation (i.e., below the seabed). + +The getTransferFunction, used internally by getLugForces, is calibrated for **maximum load conditions**. In some cases—depending on anchor geometry, load magnitude, and soil conditions—the function may produce invalid results (e.g., negative vertical load Va). +When this occurs, getLugForces() issues a warning and defaults to assigning **lug forces equal to mudline forces.** + +>[!NOTE] Some anchor capacity functions (e.g., suction, driven, helical) require loads to be applied at the lug elevation. These can be passed directly into getCapacityAnchor(), or if not provided, the method will internally compute them using getLugForces(). + +Always ensure that the loads used in these methods represent maximum or near-maximum force levels to ensure valid and conservative capacity estimates. + + + +## Equipment + +### Installation vessel +#### Pullard force +Drag installation. Input + - Tmax: maximum pullard force (N) + +#### Crane capacity +Dynamic installation. Output + - Wp: dynamically installed plate/pile weight (N) + +### Installation device +#### Suction pump +Suction installation. Output + - delta_u_suction: maximum underpressure given by the suction pump during installation (Pa) + - delta_u_retrieve: maxumum overpressure given by the suction pump during retrieval/removal (Pa) -> [!NOTE] -> Load inputs to the capacity functions (with the exception of driven & drilled and grouted anchors) are in kN, while the anchor loads dictionary is in N. This conversion is automatically completed in the getAnchorCapacity() function so no manual load conversion is required. Load outputs are automatically converted in the getAnchorCapacity function where necessary. +#### Hydraulic drive head +Torque-crowd installation. Output + - Torque: torque (Nm) + - Force: crowd compressive force (N) + +#### Hammer +Driven installation. Input + - hammer_params: + - r_m: ram mass (kg) + - h: strock height (m) + - efficiency: efficiency of the hammer (-) + +#### Drill head +Drilled installation ----------------------------------------------------------------------------- -### Model Fidelity + +## Anchor Class +The anchor class contains properties and methods related to mooring anchors. -There are two levels of fidelity in these models: +The anchor class stores properties and methods that enable a wide range of modeling. +The [anchor capacity modules](#anchor-capacity-modules) and the [anchor installation modules](#anchor-installation-modules) are integrated with FAModel through the anchor class and its methods. + +### Anchor modules +Introduction + +Inspection of the folder: anchors_famodel -- Level 1 basic models are soil-dependent capacity curves for a - range of anchor types based on performing curve fits to - published information in anchor manuals and standards. -- Level 2 intermediate models are quantitative calculations for - suction caissons and plate anchors that account for quantitative - soil properties as well as their variation with embedment depth. +| | | | +|----------------------------------------------|----------------|--------------| +|![Plate anchor](images/Plateanchors/Plate.png)|![Suction pile anchor](images/Suctionpiles/Suction.png)|![Torpedo pile anchor](images/Torpedopiles/Torpedo.png)| +|![Helical pile anchor](images/Helicalpiles/Helical.png)|![Driven pile anchor](images/Drivenpiles/Driven.png)|![Drilled and grouted pile anchor](images/Drilledandgroutedpiles/Drilled.png)| -This plot gives an example of the capacity curves that can be -produced by the intermediate model (holding capacity for a suction -embedded plate anchor) as a function of surface shear strength: -![Capacities](images/SEPLA_curves_small.PNG) +#### Anchor capacity modules +Analytical static capacity models for extreme load conditions. These models include static soil-structure interaction but the cyclic loading conditions are not covered yet. They will need to follow from further research. -### Implemented level-1 model anchor and soil types +- **capacity_plate** : + - getCapacityPlate(profile_map, location_name, D, L, zlug, Ha, Va, plot) + - capacityPlate dict: + - 'Capacity' + - 'Horizontal max.', 'Vertical max.' + - 'Unity check' + - 'Weight plate' -| | DEA | Suction | VLA | SEPLA | -|-------------|-----------|---------|-----|-------| -| Soft clay | X | X | X | X | -| Medium clay | X | X | X | X | -| Hard clay | X | | | | -| Sand | X | | | | +- **capacity_suction** : + - getCapacitySuction(profile_map, location_name, D, L, zlug, Ha, Va, thetalug, psilug, plot) + - capacitySuction dict: + - 'Horizontal max.', 'Vertical max.' + - 'Unity check' + - 'Weight pile' + +- **capacity_torpedo** : + - getCapacityTorpedo(profile_map, location_name, D1, D2, L1, L2, zlug, ballast, Ha, Va, plot) + - capacityTorpedo dict: + - 'Horizontal max.', 'Vertical max.' + - 'Unity check' + - 'Weight pile' -### Parameters needed for level-2 anchor capacity models +- **capacity_helical** : + - getCapacityHelical(profile_map, location_name, D, L, d, zlug, Ha, Va, plot) + - capacityHelical dict: + - 'Horizontal max.', 'Vertical max.' + - 'Lateral displacement', 'Rotational displacement' + - 'Bending moment' + - 'Plastic moment' + - 'Unity check (vertical)', 'Unity check (horizontal)' + - 'Weight pile' -| **Anchor type** | **Suction** | **Suction** | **VLA** | **SEPLA** | -|------------------------|-------------|-------------|----------|-----------| -| **Soil type** | **Clay** | **Sand** | **Clay** | **Clay** | -| **Anchor parameters** | | | | | -| Diameter | x | x | | | -| Length | x | x | | | -| Area | | | X | X | -| Thickness | ratio | ratio | ratio | ratio | -| Embedment depth | | | X | X | -| **Soil parameters** | | | | | -| gamma | X | X | X | X | -| Su0 | X | | X | X | -| k | X | | X | X | -| alpha | X | | | | -| phi | | X | | | +- **capacity_driven** : + - getCapacityDriven(profile_map, location_name, L, D, zlug, Ha, Va, plot) + - capacityDriven dict: + - 'Horizontal max.', 'Vertical max.' + - 'Lateral displacement', 'Rotational displacement' + - 'Bending moment' + - 'Plastic moment' + - 'Unity check (vertical)', 'Unity check (horizontal)' + - 'Weight pile' + +- **capacity_dandg** : + - getCapacityDandG(profile_map, location_name, L, D, zlug, Ha, Va, plot) + - capacityDandG dict: + - 'Horizontal max.', 'Vertical max.' + - 'Lateral displacement', 'Rotational displacement' + - 'Bending moment' + - 'Plastic moment' + - 'Unity check (vertical)', 'Unity check (horizontal)' + - 'Weight pile' +- **capacity_load** : + - getTransferFunction(profile_map, Tm, thetam, zlug, line_type, d, w, plot) + - capacityLoads dict: + - 'Tm', 'thetam' + - 'Hm', 'Vm' + - 'Ta', 'thetaa' + - 'Ha', 'Va' + - 'length' + - 'drag_values' + - 'depth_values' -These models will continue to be expanded as data sources and time permit. +#### Anchor installation modules +Analytical installation models for main anchor types. -## Soil Classification Parameters +- **installation_drag** : + - getInstallationPlate(profile_map, location_name, B, Lf, Ls, Lca, Lj, plot) + - installationDrag dict: + - 'Capacity' + - 'embedment_depth' + - 'drag_distance' + - 'Weight plate' -The soft, medium, and hard clay soil classes are distinguished by the following parameter ranges: -| Soil Type (Clay) | N-Value | Effective Sat. Unit Weight, kN/m3 | Void Ratio | Natural Water Content in Sat. State, % | Undrained Shear Strength, kN/m2 | -|:-----------------:|:--------:|:---------------------------------:|:----------:|:--------------------------------------:|:-------------------------------:| -| Very Soft | 0 - 2 | 5.5 - 8.5 | 0.9 - 1.4 | 30 - 50 | 0 - 12.5 | -| Soft | 2 - 4 | 5.5 - 8.5 | 0.9 - 1.4 | 30 - 50 | 12.5 - 25 | -| Medium | 4 - 8 | 5.5 - 8.5 | 0.9 - 1.4 | 30 - 50 | 25 - 50 | -| Stiff | 8 - 15 | 8.5 - 12 | ~ 0.6 | 20 - 30 | 50 - 100 | -| Very Stiff | 15 - 30 | 8.5 - 12 | ~ 0.6 | 20 - 30 | 100 - 200 | -| Hard | < 30 | 8.5 - 12 | ~ 0.6 | 20 - 30 | > 200 | +- **installation_suction** : + - getInstallationSuction(profile_map, location_name, D, L, plot) + - installationSuction dict: + - 'Fi', 'Fo', 'Qw' + - 'Rsuction', 'Rretrieval' + - 'SWP_depth' +- **buckling_suction** : + - getBucklingSuction(profile_map, location_name, D, L, plot) + - installationBuckling dict: + - 'UC' + - 'PE' -Sand can also be classified ranging from soft to hard, however only a single sand class is supported at this time. In the future, sand classes will follow the parameter ranges in the following table: +- **installation_dynamic** : + - getInstallationTorpedo(profile_map, location, D1, D2, L1, L2, ballast, drop_height, plot) + - installationDynamic dict: + - 'final_depth' + - 'v_max', 'v_impact' + +- **installation_torque** : + - getInstallationHelical(profile_map, location_name, D1, D2, L1, L2, zlug, ballast, Ha, Va, plot) + - installationTorque dict: + - 'Force', 'Torque' + - 'sigma_helix', 'sigma_core', 'sigma_weld' + - 'failire_mode' + +- **installation_driven** : + - getInstallationDriven(profile_map, location_name, D, L, hammer_params, J_shaft, J_toe, plot) + - installationDriven dict + +- **installation_drill** : + - getInstallationDrill(profile_map, location_name, D, L, driller_params, plot) + - installationDrill dict + +#### Anchor support modules + +- **anchor_soils** : + - clay_profile(profile) + - **return:** z0, f_gamma, f_Su, f_sigma_v_eff, f_alpha + - sand_profile(profile) + - **return:** z0, f_gamma, f_phi, f_Dr, f_sigma_v_eff, f_delta + - rock_profile(profile) + - **return:** z0, f_UCS, f_Em + +- **anchor_solvers** : + - fd_solver(n, N, h, D, t, fy, EI, Ha, Va, zlug, z0, k_secant) + - **return:** y, Mi, Mp, hinge_formed, hinge_location + +- **anchor_pycurves** : + - py_Matlock(z, D, Su, sigma_v_eff, gamma, z0, return_curve) + - **return:** f, (y, p) + - py_API(z, D, phi, sigma_v_eff, Dr, z0, return_curve) + - **return:** f, (y, p) + - py_Reese(z, D, UCS, Em, z0, return_curve) + - **return:** f, (y, p) + - py_Lovera(z, D, UCS, Em, z0, delta_grout, E_grout, delta_crushed, return_curve) + - **return:** f, (y, p) + +- **anchor_plots** : + - plot_pile(layers, y, z, D, L, z0, zlug, hinge_location) + - plot_suction(layers, L, D, z0, zlug) + - plot_suction(layers, D1, D2, L1, L2, z0, zlug) + - plot_helical(layers, D, L, d, z0, zlug, n_helix, spacing) + - plot_plate(layers, B, L, z0, zlug, beta) + - plot_load(layers, drag_values, depth_values, Tm, thetam, Ta, thetaa, zlug) + - plot_pycurve(pycurve_data) + +### Anchor class methods + +- **Anchor.setSoilProfile(profile_map)** + + Assign a soil profile directly to the anchor from a single CPT (Cone Penetration Test) record. + + This method sets the internal soil_profile, extracts soil types, and organizes layer properties by soil type. It assumes that the input contains only one CPT entry. + + **Parameters** + - **profile_map** : list of dict. A list containing exactly one dictionary representing a CPT profile. The dictionary has: + - 'location_name': a string indicating the name of the CPT + - 'x', 'y': coordinates of the CPT location + - 'layers': a list of layer dictionaries, each with a 'soil_type' key and relevant soil parameters. + + **Raises** + - **ValueError** : If profile_map contains more than one CPT. + + **Attributes Updated** + - **self.soil_profile** : list of dict. Stores the soil layers from the CPT. + - **self.profile_name** : str. Name of the CPT, default is "CPT_Assigned" if not provided. + - **self.soil_type_list** : list of str. Unique soil types present in the profile. + - **self.soil_type** : str. If a single soil type is present, its name; otherwise, 'mixed'. + - **self.soilProps** : dict. Dictionary grouping layer properties (excluding soil_type) by soil type. + +- **Anchor.interpolateSoilProfile(profile_map)** + + Interpolate a soil profile for the anchor location from the four nearest CPTs using inverse distance weighting. + + This method assumes all CPTs share the same layer structure. Each soil parameter is interpolated layer-by-layer based on the relative proximity of the CPTs to the anchor. + + **Parameters** + - **profile_map** : list of dict. A list containing at least four CPT profile dictionaries. Each dictionary has: + - 'location_name': a string indicating the name of the CPT + - 'x', 'y': coordinates of the CPT location + - 'layers': a list of layer dictionaries, each with a 'soil_type' key and relevant soil parameters. + + **Raises** + - **ValueError** : If fewer than four CPTs are provided in profile_map. + + **Attributes Updated** + - **self.soil_profile** : list of dict. Stores the soil layers from the CPT. + - **self.profile_name** : str. Set to "Interpolated_2D". + - **self.soil_type_list** : list of str. Unique soil types present in the interpolated profile. + - **self.soil_type** : str. If a single soil type is present, its name; otherwise, 'mixed'. + - **self.soilProps** : dict. Dictionary grouping layer properties (excluding soil_type) by soil type. + +- **Anchor.makeMoorPyAnchor(ms)** + + Create and register a MoorPy anchor point within the given MoorPy system using the anchor's location and design properties. + + The anchor is added as a fixed point in the MoorPy model (Point object) and its mass and diameter are assigned if available. The method also sets the point type based on the anchor type. + + **Parameters** + - **ms** : MoorPy system instance. The MoorPy system in which the anchor will be created. + + **Attributes Updated** + - **self.mpAnchor** : MoorPy Point. Reference to the created MoorPy anchor point in the system. + +- **Anchor.getLineProperties()** + + Retrieve the mooring line type, diameter and unit weight from the anchor's attached mooring object. + + This method inspects the attached Mooring object and extracts relevant line properties from its first section. If no chain is present, the method assumes no load transfer below the mudline and returns None for diameter and weight. + + **Parameters** + - **line_type** : str. Type of mooring line (e.g., 'chain', 'wire'). + - **d** : float or None. Nominal diameter of the mooring line (m) or None if not applicable. + - **w** : float or None. Unit weight of the mooring line (N/m) or None if not applicable. + + **Raises** + - **ValueError** : If no mooring line attachment is found for the anchor. + +- **Anchor.getMudlineForces(max_force=False, lines_only=False, seabed=True, xyz=False, project=None)** + + Compute the forces acting on the anchor at the mudline, either from the current state of the MoorPy system or as the maximum expected force based on platform excursion. + + If max_force=True, the method retrieves the extreme load on the anchor using either the provided project’s arrayWatchCircle() method or the attached platform’s getWatchCircle() method. Otherwise, it calculates the current forces using MoorPy's getForces(). + + **Parameters** + - **max_force** : bool, optional. If True, compute the maximum expected mudline force based on platform excursion. Default is False. + - **lines_only** : bool, optional. If True, considers only mooring line forces (ignores seabed and body effects). Default is False. + - **seabed** : bool, optional. If True, includes seabed reaction force in the calculation. Default is True. + - **xyz** : bool, optional. If True, returns forces in the x, y, z directions. Otherwise returns only the relevant DOFs. Default is False + - **project** : bool, optional. Project object with a arrayWatchCircle() method. Used to compute global platform excursions when max_force=True. + + **Attributes Updated** + - **self.loads** : dict. Stores the computed mudline force components and metadata: + - 'Hm': horizontal force magnitude at mudline (N) + - 'Vm': vertical force at mudline (N) + - 'thetam': angle of applied load at mudline (deg) + - 'method': load computation method (currently 'static') + - 'mudline_load_type': 'current_state' or 'max_force', depending on the mode used + +- **Anchor.getLugForces(Hm, Vm, zlug, line_type=None, d=None, w=None, plot=False)** + + Calculate the horizontal and vertical loads at the anchor lug (Ha, Va) based on the mudline loads and the load transfer profile along the mooring line. + + If the padeye depth zlug is embedded below the mudline, the method computes the lug loads using the load transfer model. Otherwise, it assigns the mudline loads directly to the lug. + + **Parameters** + - **Hm** : float. Horizontal mudline load (N). + - **Vm** : float. Vertical mudline load (N). + - **zlug** : float. Padeye embedment depth (m). + - **line_type** : str, optional. Type of mooring line ('chain' or 'wire'). If not provided, inferred from attachments or defaults to 'chain'. + - **d** : float, optional. Mooring line diameter (m). + - **w** : float, optional. Mooring line unit weight (N/m). + - **plot** : bool, optional. If True, generates plots of load transfer and geometry. Default is False. + + **Raises** + - **ValueError** : If the soil profile is not assigned to the anchor before calling this method. + + **Attributes Updated** + - **self.anchorCapacity** : dict. Stores the anchor's computed capacity results, including: + - 'Hmax': maximum horizontal capacity (N). + - 'Vmax': maximum vertical capacity (N). + - 'Ha','Va': lug-level horizontal and vertical loads (N). + - 'UC' or 'Unity check (horizontal)', 'Unity check (vertical)' : capacity utilization checks. + - 'Lateral displacement', 'Rotational displacement' : optional displacement results (if available) + - 'Weight pile', 'Weight plate' : self-weight of pile or plate depending on type. + - 'zlug' : lug depth (m), and 'z0' : mudline reference elevation (m) + +- **Anchor.getCapacityAnchor(Hm, Vm, zlug, line_type=None, d=None, w=None, mass_update=False, plot=False)** + + Calculate the load capacity of the anchor based on its type, geometry and local soil profile. + + This method computes the anchor resistance against applied horizontal and vertical loads using the appropriate capacity model for the anchor type. It optionally performs load transfer from the mudline to the lug and updates the anchor's capacity results. + + **Parameters** + - **Hm** : float. Horizontal mudline load (N). + - **Vm** : float. Vertical mudline load (N). + - **zlug** : float. Padeye embedment depth (m). + - **line_type** : str, optional. Type of mooring line ('chain' or 'wire'). If not provided, inferred from attachments or defaults to 'chain'. + - **d** : float, optional. Mooring line diameter (m). + - **w** : float, optional. Mooring line unit weight (N/m). + - **mass_update** : bool, optional. If True, updates the anchor's weight based on computed capacity. Default is False. + - **plot** : bool, optional. Whether to generate a plot of the load transfer profile. Default is False. + + **Raises** + - **ValueError** : If the anchor type is unknown or if the soil profile is not properly assigned. + + **Attributes Updated** + - **layers** : list of dict. The soil profile layers used in the load transfer calculation. + - **Ha** : float. Horizontal load at the lug (N). + - **Va** : float. Vertical load at the lug (N). + +- **Anchor.getSizeAnchor(geom, geomKeys, geomBounds=None, loads=None, lambda_con=[3, 6], zlug_fix=True, safety_factor={'SF_combined':1.0}, plot=False)** + + Generalized optimization method to determine the appropriate geometry for all anchor types based on load conditions and safety factor requirements. + + For suction, torpedo, and plate-type anchors, the method minimizes the difference between the calculated and target Unity Check (UC). For driven, helical, and dandg anchors, the method iteratively searches for the smallest geometry that satisfies combined UC, lateral and rotational displacement limits. + + **Parameters** + - **geom** : : list of float. Initial geometry values (e.g., [L, D]). + - **geomKeys** : list of str. Keys that define the geometry variables to optimize (e.g., ['L', 'D']). + - **geomBounds** : list of tuple, optional. Bounds for geometry values, e.g., [(5.0, 20.0), (1.0, 4.0)]. + - **loads** : dict, optional. Dictionary containing mudline forces ('Hm', 'Vm'). Defaults to self.loads. + - **lambdap_con** : list of float, optional. Minimum and maximum slenderness ratio constraints [L/D_min, L/D_max]. Default is [4, 8]. + - **zlug_fix** : float, optional. If False, allows zlug to vary with geometry. Default is True. + - **safety_factor** : bool, optional. Dictionary with safety factor targets (e.g., {'SF_combined': 1.5}). Default is {'SF_combined': 1.0}. + - **plot** : bool, optional. If True, generates plots the final capacity results. Default is False. + + **Raises** + - **ValueError** : If the anchor type is not supported for this optimization method. + + **Attributes Updated** + - **self.dd['design']** : list of dict. The soil profile layers used in the load transfer calculation. + - **self.anchorCapacity** : float. Horizontal load at the lug (N). + - Ha, Va : float. Lug loads (N). + - Ha, Va : float. Lug loads (N). + - UC or 'Unity check (horizontal)', 'Unity check (vertical)' + - Optional displacements and weights if applicable + +- **Anchor.getSafetyFactor(ms=None)** + + Estimate the material cost of the anchor using the MoorPy Point object and its getCost_and_MBL() method. + + If no MoorPy system is provided, the method initializes one and registers the anchor. Cost is based on mass and design parameters, and the Minimum Breaking Load (MBL) is also computed. + + **Parameters** + - **ms** : MoorPy system instance, optional. If provided, uses the existing system. Otherwise, creates a new MoorPy system internally. + + **Raises** + - **KeyError** : If self.mass is not defined and neither 'Weight pile' nor 'Weight plate' is available in self.anchorCapacity. This typically indicates that getCapacityAnchor() has not been called before getCostAnchor(). + + **Attributes Updated** + - **self.cost** : dict. Stores cost-related metrics for the anchor: + - 'Material cost' : Estimated anchor material cost. + - 'MBL' : Minimum Breaking Load (from MoorPy). + - 'unit_cost' : Cost per unit mass (cost/mass). + - **self.mpAnchor.m** : float. Mass of the MoorPy anchor point (assigned if self.mass is not already set). + +### Anchor Object Properties + +- **r** : anchor [x, y, z] position +- **dd** : anchor design dictionary, containing geometric properties, soil properties at the anchor location, cost +- **ms** : MoorPy system associated with this anchor point +- **aNum** : anchor index in array mooring list (generally only used for shared moorings) +- **mpAnchor** : MoorPy point object that models this anchor +- **anchorCapacity** : dictionary with horizontal and vertical capacity of the anchor. Generally these are loads in [N], but can also be displacements (generally for driven or drilled and grouted piles) +- **loads** : dictionary of loads on the anchor, and the method used to obtain these loads (static or dynamic modeling). +Loads include mooring line tension (T) with the angle of the load (theta) as well as horizontal (H) and vertical (V) loads components. +The keys for these loads will either include an m (for loads at the mudline) or a (for loads at the anchor lug / main padeye). +- **soilProps** : dictionary of soil property information at the location of the anchor +- **failure_probability** : dictionary of probabilities for failure of the anchor + +### Anchor Type Requirements + +Different geometric properties and soil conditions are needed for each anchor type. See the [Anchor Capacity Modules](#anchor-capacity-modules) section for details on the requirements of each anchor type. + +## Anchor Capacity Modules +The following list shows the required soil conditions, load information and geometrical properties involved in the anchors' capacity calculations. + + +#### Output notes + The general output is a lateral and rotational displacement. In getAnchorCapacity, the drilled and grouted pile function is called in a while loop with incremented horizontal input forces + until one of the displacements goes past set failure criteria, thus providing a horizontal force capacity output [N]. Vertical capacity [N] is already calculated within the driven pile capacity function. + -| Soil Type (sand) | N-Value | Eff. Sat. Unit Weight, kN/m3 | Void Ratio | Natural Water Content in Sat. State, % | Eff. friction Angle | Relative density (%) | -|:----------------:|:--------:|:----------------------------:|:----------:|:--------------------------------------:|:-------------------:|:--------------------:| -| Very Loose | > 4 | 7 - 9.5 | ~ 0.8 | 25 - 30 | < 30 | < 15 | -| Loose | 4 - 10 | 7 - 9.5 | ~ 0.8 | 25 - 30 | 30 - 35 | 15 - 35 | -| Compact | 10 - 30 | 9.5 - 11.5 | ~ 0.45 | 12 - 16 | 35 - 40 | 35 - 65 | -| Dense | 30 - 50 | 9.5 - 11.5 | ~ 0.45 | 12 - 16 | 40 - 45 | 65 - 85 | -| Very Dense | < 50 | 9.5 - 11.5 | ~ 0.45 | 12 - 16 | > 45 | > 85 | -Conversion functions are under development to switch between categories (level 1 anchor models) -and quantitative soil metrics (level 2 anchor models). \ No newline at end of file diff --git a/famodel/anchors/README_FMO.md b/famodel/anchors/README_FMO.md deleted file mode 100644 index c4498589..00000000 --- a/famodel/anchors/README_FMO.md +++ /dev/null @@ -1,267 +0,0 @@ -# Anchors Library - -This subpackage of FAModel contains the Anchor class as well as modules for analytical static anchor capacity assessment. - -## Anchor Class -The anchor class contains properties and methods related to mooring anchors. - -The anchor class stores properties and methods that enable a wide range of modeling - from capacity to cost to loads, and more. -The [anchor capacity modules](#anchor-capacity-modules) are integrated with the anchor class through the getAnchorCapacity() method. - -### Anchor Files -Introduction -Inspection of the folder: anchors_famodel - -#### Anchor Capacity Files -- **capacity_plate** : getCapacityPlate -- **capacity_suction** : getCapacitySuction -- **capacity_torpedo** : getCapacityTorpedo -- **capacity_driven** : getCapacityDriven -- **capacity_dandg** : getCapacityDandG -- **capacity_helical** : getCapacityHelical -- **capacity_load** : getTransferFunction - -#### Anchor Support Files -- **capacity_soils** : clay_profile, sand_profile and rock_profile -- **capacity_solvers** : fd_solver for non-linear solver -- **capacity_pycurves** : py_Matlock, py_API, py_Reese and py_Lovera -- **capacity_plots** : plot_driven, plot_suction, plot_helical,plot_plate, plot_dandg, plot_load, plot_pycurve - -### Anchor Methods -- **setSoilProfile()** : Assign a bilinearly interpolated soil profile from the 4 nearest CPTs -- **makeMoorPyAnchor()** : Creates a MoorPy point object representing the anchor in a moorpy system -- **getMudlineForces()** : Finds forces on anchor at mudline using MoorPy Point.getForces method. Use max_force=True to obtain the maximum forces on that anchor from the platform.getWatchCircle() method. -For more information on the getWatchCircle() calculations, see the [Platform ReadMe](../platform/README.md). An additional anchor.loads dictionary entry is included to describe the mudline load type. -'mudline_load_type'='max' if max_force=True, and 'mudline_load_type'='current_state' if max_force=False. -- **getLugForces()** : Finds forces at the anchor lug location with getTransferFunction function in capacity_loads.py -- **getCapacityAnchor()** : Calls anchor capacity functions for the correct anchor type using the getLugForces embedded in the method -- **getSizeAnchor()** : Calls sizing anchor functions for the correct anchor type using the getLugForces embedded in the method -- **getFS()** : Computes safety factor for loads on the anchor -- **getCost()** : Finds costs of anchor from MoorProps and stores in design dictionary -- **getCombinedPlot()** : Create a plot showing the anchor and the inverse catenary overlay in the same coordinate system. - -### Anchor Object Properties -- **r** : anchor [x,y,z] position -- **dd** : anchor design dictionary, containing geometric properties, soil properties at the anchor location, cost -- **ms** : moorpy system associated with this anchor point -- **aNum** : anchor index in array mooring list (generally only used for shared moorings) -- **mpAnchor** : moorpy point object that models this anchor -- **anchorCapacity** : dictionary with horizontal and vertical capacity of the anchor. Generally these are loads in [N], but can also be displacements (generally for driven or drilled and grouted piles) -- **loads** : dictionary of loads on the anchor, and the method used to obtain these loads (static or dynamic modeling). -Loads include mooring line tension (T) with the angle of the load (theta) as well as horizontal (H) and vertical (V) loads components. -The keys for these loads will either include an m (for loads at the mudline) or a (for loads at the anchor lug / main padeye). -- **soilProps** : dictionary of soil property information at the location of the anchor -- **failure_probability** : dictionary of probabilities for failure of the anchor - -### Anchor Type Requirements - -Different geometric properties and soil conditions are needed for each anchor type. See the [Anchor Capacity Modules](#anchor-capacity-modules) section for details on the requirements of each anchor type. - -## Anchor Capacity Modules -The following list shows the required soil conditions, load information and geometrical properties involved in the anchors' capacity calculations. -Soil classification for clay, sand and rock can be found in [Soil Classification Parameters](#soil-classification-parameters). ->[!NOTE] ->Some anchor capacity functions require input loads at the anchor lug point. These loads can be sent in to the getAnchorCapacity() method, or the getAnchorCapacity() method will calculate the loads by calling getLugLoads(). -The input loads must be maximum or large loads on the anchor. - -### Soil Properties -Introduction to different soil types -- clay/mud - - gamma (submerged soil unit weight) (kN/m^3) - - Su (undrained shear strength of soil at mudline) (kPa) - -- sand - - gamma (submerged soil unit weight) (kN/m^3) - - phi (internal friction angle) (deg) - - Dr (relative density) (%) - -- rock (weak rock up to UCS = 5 MPa) - - UCS (unconfined compressive strength at failure) (MPa) - - Em (rock mass modulus) (MPa) - -### Soil Classification Parameters - -The soft, medium, and hard clay soil classes are distinguished by the following parameter ranges: -| Soil Type (clay) | N-Value | Eff. Sat. Unit Weight, kN/m3 | Void Ratio | Natural Water Content in Sat. State, % | Undrained Shear Strength, kN/m2 | -|:-----------------:|:--------:|:---------------------------------:|:----------:|:--------------------------------------:|:-------------------------------:| -| Very Soft | 0 - 2 | 5.5 - 8.5 | 0.9 - 1.4 | 30 - 50 | 0 - 12.5 | -| Soft | 2 - 4 | 5.5 - 8.5 | 0.9 - 1.4 | 30 - 50 | 12.5 - 25 | -| Medium | 4 - 8 | 5.5 - 8.5 | 0.9 - 1.4 | 30 - 50 | 25 - 50 | -| Stiff | 8 - 15 | 8.5 - 12 | ~ 0.6 | 20 - 30 | 50 - 100 | -| Very Stiff | 15 - 30 | 8.5 - 12 | ~ 0.6 | 20 - 30 | 100 - 200 | -| Hard | < 30 | 8.5 - 12 | ~ 0.6 | 20 - 30 | > 200 | - - -Sand can also be classified ranging from soft to hard, however only a single sand class is supported at this time. In the future, sand classes will follow the parameter ranges in the following table: - -| Soil Type (sand) | N-Value | Eff. Sat. Unit Weight, kN/m3 | Void Ratio | Natural Water Content in Sat. State, % | Eff. friction Angle | Relative density (%) | -|:----------------:|:--------:|:----------------------------:|:----------:|:--------------------------------------:|:-------------------:|:--------------------:| -| Very Loose | > 4 | 7 - 9.5 | ~ 0.8 | 25 - 30 | < 30 | < 15 | -| Loose | 4 - 10 | 7 - 9.5 | ~ 0.8 | 25 - 30 | 30 - 35 | 15 - 35 | -| Compact | 10 - 30 | 9.5 - 11.5 | ~ 0.45 | 12 - 16 | 35 - 40 | 35 - 65 | -| Dense | 30 - 50 | 9.5 - 11.5 | ~ 0.45 | 12 - 16 | 40 - 45 | 65 - 85 | -| Very Dense | < 50 | 9.5 - 11.5 | ~ 0.45 | 12 - 16 | > 45 | > 85 | - -Conversion Units - -Z0 explanaition on the pile head reference and how for zlug > z0 mooring line is embedded and below the mudline elevation - -### Loads -- Loads at mudline elevation - - Tm, thetam (Tension and angle of the load on mudline) - - Hm, Vm (Horizontal and vertical loads on mudline) -- Loads at mudline elevation - - Ta, thetaa (Tension and angle of the load on padeye of anchor) - - Ha, Va (Horizontal and vertical loads on padeye of anchor) -- Transfer functions: soil properties (profile) mooring line properties (line_type, d and w), loads and zlug - -> [!NOTE] check getLugForces for more details on this transfer function from mudline to lug elevation (below the seabed) -The getTransferLoad function requires **maximum** mudline forces as an input. These forces can be sent in as a dictionary, or anchor.loads dictionary will be searched for 'Hm' and 'Vm' values with additional -key-value pair 'mudline_force_type':'max' to indicate these mudline forces are maximums. - -If there are no max mudline forces in the anchor.loads dictionary, getMudlineForces(max_force=True) will be called. Stores results in loads dictionary. -If lug is at mudline or no lug provided, equates mudline forces with lug forces. ->[!NOTE] ->The getTransferFunction function called by getLugForces() is tuned to work with maximum loads on the anchor. Some anchor configuration, load, and soil condition combinations may produce invalid results in getTransferFunction. -For example, the output Va may show as negative. In that case, getLugForces() will warn the user of the invalidity of the result and assign the anchor lug forces = mudline forces. - -------------------------------------------------------------------------------- -> [!IMPORTANT] -> A positive zlug denotes a lug/padeye/bridle below the mudline, while a negative zlug denotes a lug/padeye/bridle above the mudline. Anchors in rock should have a zlug >= 0. - -> [!NOTE] -> Load inputs to the capacity functions (with the exception of driven & drilled and grouted anchors) are in kN, while the anchor loads dictionary is in N. This conversion is automatically completed in the getAnchorCapacity() -function so no manual load conversion is required. Load outputs are automatically converted in the getAnchorCapacity function where necessary. - ------------------------------------------------------------------------------ - -### Anchor Types -The supported anchor types are below, with the associated FAModel name in italics. -- Plate anchors - - *DEA* (drag-embedment anchors) - - *SEPLA* (suction embedded plate anchors) - - *DEPLA* (dynamically embedded plate anchors) - - *VLA* (vertically loaded anchors) - - *plate* (unspecified plate anchor) -- *suction_pile* (Suction caisson/ suction bucket anchors) -- *torpedo_pile* (Torpedo pile anchors) -- *helical_pile* (Helical pile anchors) -- *driven_pile* (Driven pile anchors) -- *dandg_pile* (Drilled and grouted piles) - -### Anchor geometrical properties -#### DEA/SEPLA/DEPLA/VLA/plate -- soil condition: clay -- geometry - - A (area of plate) (m^2) - - zlug (embedded depth of bridle/padeye below mudline - positive is below mudline, negative is above mudline) (m) - - beta (OPTIONAL - angle of plate with horizontal plane) (deg) -- loads - - Ha, Va (horizontal and vertical loads on padeye of anchor) - -#### suction_pile (Suction caisson/ suction bucket anchors) -- soil condition: clay and sand -- geometry - - L (length of pile) (m) - - D (diameter of pile) (m) - - zlug (embedded depth of padeye below mudline) (m) -- loads - - Ha, Va (horizontal and vertical loads on padeye of anchor) - -#### torpedo_pile (Torpedo pile anchors) -- soil condition: clay -- geometry - - D1 (wing diameter) (m) - - D2 (shaft diameter) (m) - - L1 (wing length) (m) - - L2 (shaft length) (m) - - zlug (embedded depth of padeye below mudline) (m) -- loads - - Ha, Va (horizontal and vertical loads on padeye of anchor) - -#### helical_pile (Helical pile anchors) -- soil condition: clay and sand -- geometry - - D (helix diameter) (m) - - L (shaft length) (m) - - d (shaft diameter) (m) - - zlug (embedded depth of padeye below mudline) (m) -- loads - - Ha, Va (horizontal and vertical loads on padeye of anchor) - -#### driven_pile (Driven pile anchors) -- soil condition: clay, sand and (weak) rock -- geometry - - L (length of pile) (m) - - D (diameter of pile) (m) - - zlug (embedded depth of padeye below mudline) (m) -- loads - - Ha, Va (horizontal and vertical loads on padeye of anchor) - -#### Output notes - The general output is a lateral and rotational displacement or bending moment. In getCapacityAnchor, the driven pile capacity function is called in a while loop with incremented horizontal - input forces until one of the displacements goes past set failure criteria, thus providing a horizontal force capacity output [N]. Vertical capacity [N] is already calculated within the driven pile capacity function. - - For non-rock soil, the hinge (bending moment) is also considered as a failure mode along with the lateral and rotational displacement - -#### dandg_pile (Drilled and grouted piles) -- soil condition: rock -- geometry - - L (length of pile) (m) - - D (diameter of pile) (m) - - zlug (lug location) (m) -- loads - - Ha, Va (horizontal and vertical loads on padeye of anchor) - -#### Output notes - The general output is a lateral and rotational displacement. In getAnchorCapacity, the drilled and grouted pile function is called in a while loop with incremented horizontal input forces - until one of the displacements goes past set failure criteria, thus providing a horizontal force capacity output [N]. Vertical capacity [N] is already calculated within the driven pile capacity function. - - -### Model Fidelity - -There are two levels of fidelity in these models: - -- Level 1 basic models are soil-dependent capacity curves for a - range of anchor types based on performing curve fits to - published information in anchor manuals and standards. -- Level 2 intermediate models are quantitative calculations for - suction caissons and plate anchors that account for quantitative - soil properties as well as their variation with embedment depth. - -This plot gives an example of the capacity curves that can be -produced by the intermediate model (holding capacity for a suction -embedded plate anchor) as a function of surface shear strength: - -![Capacities](images/SEPLA_curves_small.PNG) - -### Implemented level-1 model anchor and soil types - -| | DEA | Suction | VLA | SEPLA | -|-------------|-----------|---------|-----|-------| -| Soft clay | X | X | X | X | -| Medium clay | X | X | X | X | -| Hard clay | X | | | | -| Sand | X | | | | - -### Parameters needed for level-2 anchor capacity models - -| **Anchor type** | **Suction** | **Suction** | **VLA** | **SEPLA** | -|------------------------|-------------|-------------|----------|-----------| -| **Soil type** | **Clay** | **Sand** | **Clay** | **Clay** | -| **Anchor parameters** | | | | | -| Diameter | x | x | | | -| Length | x | x | | | -| Area | | | X | X | -| Thickness | ratio | ratio | ratio | ratio | -| Embedment depth | | | X | X | -| **Soil parameters** | | | | | -| gamma | X | X | X | X | -| Su0 | X | | X | X | -| k | X | | X | X | -| alpha | X | | | | -| phi | | X | | | - - -These models will continue to be expanded as data sources and time permit. - diff --git a/famodel/anchors/anchor.py b/famodel/anchors/anchor.py index 66c17943..f0399135 100644 --- a/famodel/anchors/anchor.py +++ b/famodel/anchors/anchor.py @@ -3,71 +3,78 @@ """ import moorpy as mp import numpy as np +from scipy.optimize import minimize from famodel.famodel_base import Node from famodel.mooring.mooring import Mooring +import matplotlib.pyplot as plt +from collections import defaultdict import famodel.platform.platform import shapely as sh - class Anchor(Node): - def __init__(self, dd=None, ms=None, r=[0,0,0], aNum=None, id=None, - g=9.81, rho=1025): + def __init__(self, dd=None, ms=None, r=[0,0,0], aNum=None, id=None, + g=9.81, rho=1025, profile_map=None, display=0): ''' + Initialize an Anchor object. + Parameters ---------- - dd: dictionary - Design dictionary that contains all information on an anchor for a mooring line/shared mooring - { - type: # anchor type (plate,suction_pile,torpedo_pile,helical_pile,driven_pile,dandg_pile) - design: # all geometric info from yaml file, only need to include info relevant to your anchor type - A plate anchor area - D anchor diameter (or helix diameter for helical piles) - D1 torpedo anchor wing diameter - D2 torpedo anchor shaft diameter - d helical pile shaft diameter - L pile anchor length - L1 torpedo anchor wing length - L2 torpedo anchor shaft length - zlug padeye z elevation (+ down into the soil) - beta angle of plate anchor after keying (optional) - cost: - matCost: # material cost - instCost: # installation cost - decomCost: # decomissioning cost - } - ms: system object - MoorPy system object the anchor is in - - r: list - Location of anchor in x,y,z - - aNum: int - entry number in project.anchorList dictionary (may remove...) - id: str/int - unique id of this object - g: float - acceleration due to gravity in m/s^2 - rho: float - density of water in kg/m^3 + dd : dict + Design dictionary containing all information on the anchor. + ms : MoorPy system object + MoorPy system instance. + r : list of float + Anchor position coordinates (x, y, z) (m) + aNum : int, optional + Index in anchor list. + id : str or int, optional + Unique anchor identifier. + g : float, optional + Gravity. + rho : float, optional + Water density. + profile_map : list of dict, optional + Full soil profile map for selecting local soil layers. ''' + # Initialize as a node - Node.__init__(self,id) - + Node.__init__(self, id) + # Design description dictionary for this Anchor self.dd = dd - # MoorPy system this anchor is in self.ms = ms - # x,y,z location of anchor self.r = r - - # anchor index in array mooring list (only used for shared moorings/anchors) + # anchor index in array mooring list self.aNum = aNum - - # MoorPy anchor object + + self.g = g + self.rho = rho + + if dd and 'type' in dd: + self.anchType = dd['type'] + else: + self.anchType = 'suction' + print(f"[Anchor] No type provided. Defaulting to 'suction'.") + + # raise errors/warnings if the anchor type is not what it needs to be + anchor_type_options = ['suction', 'sepla', 'dea', 'depla', 'vla', 'plate', 'torpedo', 'helical', 'driven', 'drilled'] + if self.anchType.lower() not in anchor_type_options: + raise ValueError(f"The anchor 'type' {self.anchType} needs to explicitly be one of {anchor_type_options} (Case not sensitive)") + # if self.anchType not in ['drag-embedment', 'gravity', 'suction', 'SEPLA', 'VLA', 'driven']: + # print('Warning: The anchor type provided does not have any cost coefficients. This will default to a suction pile') + + self.soil_type = None + self.soil_profile = None + self.profile_name = None + self.soil_type_list = [] + self.mpAnchor = None + self.capacity_format = None + self.mass = dd.get('design', {}).get('mass', None) if dd else None + self.point_num = 0 # initialize point number # get environment info self.g = g # acceleration due to gravity (m/s^2) @@ -101,530 +108,1058 @@ def __init__(self, dd=None, ms=None, r=[0,0,0], aNum=None, id=None, } ''' self.soilProps = {} + self.loads = {} + self.anchorCapacity = {} + self.cost = {} self.failure_probability = {} - - # environmental impact self.env_impact = {} - - # self.cost = {} + # Assign soil profile if map is provided + if profile_map is not None: + if len(profile_map) == 1: + self.setSoilProfile(profile_map) + elif len(profile_map) >= 4: + self.interpolateSoilProfile(profile_map) + else: + raise ValueError("profile_map must contain either 1 or ≥4 CPTs for soil assignment.") + self.display = display + + def setSoilProfile(self, profile_map): + ''' + Assign a soil profile directly from a single CPT. + Assumes profile_map is a list with only one entry. + ''' + if len(profile_map) != 1: + raise ValueError("setSoilProfile expects a profile_map with exactly one CPT.") + + cpt = profile_map[0] + self.soil_profile = profile_map + self.profile_name = cpt.get('name', 'CPT_Assigned') + + # Extract soil types from layers + layers = cpt['layers'] + soil_types = [layer['soil_type'] for layer in layers] + self.soil_type_list = list(set(soil_types)) + self.soil_type = soil_types[0] if len(self.soil_type_list) == 1 else 'mixed' + + # Group layers by soil type + soilProps = defaultdict(list) + for layer in layers: + layer_copy = layer.copy() + soil_type = layer_copy.pop('soil_type') + soilProps[soil_type].append(layer_copy) + self.soilProps = dict(soilProps) + + if self.display > 0: print(f"[Anchor] Assigned soil profile from {self.profile_name} with soil types {self.soil_type_list}") + + def interpolateSoilProfile(self, profile_map): + ''' + Interpolate a soil profile from the 4 nearest CPTs in profile_map. + ''' + if len(profile_map) < 4: + raise ValueError("interpolateSoilProfile requires at least 4 CPTs.") + + x_anchor, y_anchor = self.r[0], self.r[1] + + # Sort CPTs by distance + distances = [np.hypot(p['x'] - x_anchor, p['y'] - y_anchor) for p in profile_map] + idx_sorted = np.argsort(distances) + CPTs = [profile_map[i] for i in idx_sorted[:4]] + + # Inverse distance weighting + x = np.array([cpt['x'] for cpt in CPTs]) + y = np.array([cpt['y'] for cpt in CPTs]) + d = np.hypot(x - x_anchor, y - y_anchor) + w = 1 / np.maximum(d, 1e-3)**2 + w /= np.sum(w) + + # Interpolate layer-by-layer (assumes same layer structure) + layers_list = [cpt['layers'] for cpt in CPTs] + n_layers = len(layers_list[0]) + interpolated_layers = [] + + for i in range(n_layers): + base_layer = layers_list[0][i] + layer = {'soil_type': base_layer['soil_type']} + + for key in base_layer: + if key == 'soil_type': + continue + if all(key in l[i] for l in layers_list): + vals = [l[i][key] for l in layers_list] + layer[key] = np.dot(w, vals) + + interpolated_layers.append(layer) + + self.soil_profile = [{ + 'name': 'Interpolated_2D', + 'x': x_anchor, + 'y': y_anchor, + 'layers': interpolated_layers}] + self.profile_name = "Interpolated_2D" + + # Extract soil types + layers = self.soil_profile[0]['layers'] + soil_types = [layer['soil_type'] for layer in layers] + self.soil_type_list = list(set(soil_types)) + self.soil_type = soil_types[0] if len(self.soil_type_list) == 1 else 'mixed' + + # Group interpolated layers by soil type + soilProps = defaultdict(list) + for layer in self.soil_profile[0]['layers']: + layer_copy = layer.copy() + soil_type = layer_copy.pop('soil_type') + soilProps[soil_type].append(layer_copy) + self.soilProps = dict(soilProps) + + if self.display > 0: print(f"[Anchor] Interpolated soil profile: {self.profile_name} with soil types {self.soil_type_list}") def makeMoorPyAnchor(self, ms): - '''Create a MoorPy anchor object in a moorpy system + ''' + Create a MoorPy anchor object in a MoorPy system. + Parameters ---------- - ms : class instance - MoorPy system - + ms : MoorPy system instance + The MoorPy system to add the anchor to. + Returns ------- - ms : class instance - MoorPy system + ms : MoorPy system instance + The updated MoorPy system with the anchor added. + ''' + anchType = self.anchType or 'suction' ''' + # Create anchor as a fixed point in MoorPy system + ms.addPoint(1, self.r) + + # Assign this point as mpAnchor in the anchor class instance + self.mpAnchor = ms.pointList[-1] + ''' + # create anchor as a fixed body in MoorPy system and assign to mpAnchor property # r6 = [self.r[0],self.r[1],self.r[2],0,0,0] # self.mpAnchor = ms.addBody(1,r6) self.mpAnchor = ms.addPoint(1,self.r) - # add mass if available - if 'm' in self.dd['design'] and self.dd['design']['m']: - self.mpAnchor.m = self.dd['design']['m'] - # set anchor diameter - if 'd' in self.dd['design'] and self.dd['design']['d']: + # Set mass if available + if 'mass' in self.dd.get('design', {}): + self.mpAnchor.m = self.dd['design']['mass'] + + # Set diameter if available + if 'd' in self.dd.get('design', {}): self.mpAnchor.d = self.dd['design']['d'] - # set the point as an anchor entity - self.mpAnchor.entity= {'type': 'anchor'} - if 'type' in self.dd: - self.mpAnchor.entity['anchor_type']=self.dd['type'] - - return(ms) - - - def getAnchorCapacity(self,ground_cons=None,installAdj=1,profile=None,loads=None,plot=True): - ''' - Calls anchor capacity functions developed by Felipe Moreno for the correct anchor type + + # Set dummy design to get PointType from MoorPy + if anchType not in list(ms.pointProps['AnchorProps'].keys()): + anchType = 'suction' # default to a suction pile just to get the MoorPy pointProps working + design = {f"num_a_{anchType}": 1} + pointType = ms.setPointType(design, source=None) + self.mpAnchor.entity = pointType - Parameters - ---------- - ground_conds : dict, optional - Ground conditions dictionary with the key as the soil type name, values as soil info such as UCS,Em,phi,gamma,effective stress,etc. The default is None. - If no dict provided, the ground conds will be pulled from the anchor soilProps property - installAdj : float, optional - Adjustment to the capacity based on installation (dummy variable for now, but future installation functions - will dictate this value) - profile : 2D array, optional - 2d array of depths (m) and corresponding undrained shear strength (Pa). Su must not be zero - (change to small value such as .001), but z must always start at 0. Ex: array([z1,Su1],[z2,Su2],...) - Used only for driven pile and drilled and grouted pile anchors. - loads : dict, optional - Dictionary of loads on the anchor at the lug point in [N]. If not provided, will use the loads dictionary property - of the anchor. If this is empty and it is needed for the capacity function (i.e. driven piles) then - the anchor.getLugForces() function will be called. + return ms + + def getLineProperties(self): + ''' + Retrieve line_type, diameter and unit weight from attached mooring. Returns ------- - results : dict - Dictionary of capacity of the anchor (generally a max force [N] in H and V, but can be a max displacement (driven, dandg piles)) - + line_type : str + Type of mooring line ('chain' or 'wire') + d : float + Nominal diameter (m) + w : float + Unit weight (N/m) ''' - # - - - - set details - - - - - anchType = self.dd['type'] - geom = self.dd['design']# geometric anchor information - - if not ground_cons: - soil = next(iter(self.soilProps.keys()), None) # soil type - ground_conds = self.soilProps[soil] - else: - soil = next(iter(ground_cons.keys())) - ground_conds = ground_cons[soil] - - for key,prop in ground_conds.items(): - if isinstance(prop,list) or isinstance(prop,np.ndarray): - if len(prop)>1: - print('Warning: Only homogeneous soils are supported at this time. Only the first item in a property list will be used.') - break - else: - ground_conds[key] = prop[0] - - - if loads: - # find out if mudline loads or anchor loads - if not 'Ha' in loads: - # get loads at lug - loads = self.getLugForces(mudloads=loads,plot=plot) - else: - loads = self.loads - - - - # logic to determine what functions to call based on anchor type and soil type... - - # - - - - plate anchors - - - - - if anchType == 'SEPLA' or anchType == 'DEA' or anchType == 'DEPLA' or anchType == 'VLA' or anchType == 'plate': - from .anchors_famodel.capacity_plate import getCapacityPlate - if 'clay' in soil or 'mud' in soil: - # write or overwrite beta in geom dictionary from loads function - if anchType != 'DEA': - if not 'beta' in geom: - if not 'thetaa' in loads: - # calculate thetaa from Ha and Va - loads['thetaa'] = np.arctan2(loads['Va'],loads['Ha']) - # loads = self.getLugForces(plot=plot) - geom['beta'] = 90 - loads['thetaa'] - else: - geom['beta'] = 0 - if 'Su0' in ground_conds and 'k' in ground_conds and 'gamma' in ground_conds: - results = getCapacityPlate(geom['A'], geom['beta'], geom['zlug'], 'clay', ground_conds['gamma'], - Su0=ground_conds['Su0'], k=ground_conds['k']) - else: - raise Exception('Ground conditions dictionary needs Su0, k, gamma information for clay plate anchors') - else: - print(f'Warning: Soil type {soil} is not compatible with plate anchors (SEPLA/DEPLA/DEA/VLA)') - - # - - - - suction buckets - - - - - elif 'suction' in anchType: - from .anchors_famodel.capacity_suction import getCapacitySuction - # check loads have been calculated (needed for capacity function in this case) - if not 'Ha' in loads: - # call getMPForces function - loads = self.getLugForces(plot=plot) - if 'sand' in soil: - if 'phi' in ground_conds and 'Dr' in ground_conds: - results = getCapacitySuction(geom['D'], geom['L'], geom['zlug'], - loads['Ha']/1000, loads['Va']/1000, - 'sand', ground_conds['gamma'], - phi=ground_conds['phi'], - Dr=ground_conds['Dr'], plot=plot) - else: - raise Exception('Ground conditions dictionary needs phi and relative density information for sand suction pile anchor') - elif 'clay' in soil or 'mud' in soil: - if 'Su0' in ground_conds and 'k' in ground_conds and 'alpha' in ground_conds:# and 'gamma_sub' in ground_conds: - results = getCapacitySuction(geom['D'],geom['L'], geom['zlug'], - loads['Ha']/1000, loads['Va']/1000, - 'clay', ground_conds['gamma'], - Su0=ground_conds['Su0'], - k=ground_conds['k'], plot=plot) - results['Horizontal max.'] = results['Horizontal max.'] - results['Vertical max.'] = results['Vertical max.'] - - else: - raise Exception('Ground conditions dictionary needs Su0, k, and alpha information for clay suction pile anchor') - else: - print(f'Warning: Soil type {soil} is not compatible with suction pile anchor') - - # - - - - helical piles - - - - - elif 'helical' in anchType: - from .anchors_famodel.capacity_helical import getCapacityHelical - if 'sand' in soil: - if 'phi' in ground_conds and 'gamma' in ground_conds: - results = getCapacityHelical(geom['D'], geom['L'], geom['d'], - geom['zlug'], 'sand', - ground_conds['gamma'], - phi=ground_conds['phi'], - Dr=ground_conds['Dr']) - results['Vertical max.'] = results['Capacity'] - else: - raise Exception('Ground conditions dictionary needs phi, gamma and relative density information for clay helical pile anchor') - elif 'clay' in soil or 'mud' in soil: - if not 'alpha_star' in ground_conds: - ground_conds['alpha_star'] = ground_conds['alpha'] - if 'Su0' in ground_conds and 'k' in ground_conds and 'gamma' in ground_conds: - results = getCapacityHelical(geom['D'], geom['L'], geom['d'], - geom['zlug'], 'clay', - ground_conds['gamma'], - Su0=ground_conds['Su0'], - k=ground_conds['k']) - results['Vertical max.'] = results['Capacity'] - else: - raise Exception('Ground conditions dictionary needs Su0, k, gamma, and alpha_star information for clay helical pile anchor') - else: - print(f'Warning: Soil type {soil} is not compatible with helical pile anchor') - - # - - - - torpedo piles - - - - - elif 'torpedo' in anchType: - from .anchors_famodel.capacity_torpedo import getCapacityTorpedo - if 'clay' in soil or 'mud' in soil: - if 'Su0' in ground_conds and 'k' in ground_conds and 'alpha' in ground_conds: - results = getCapacityTorpedo(geom['D1'], geom['D2'], - geom['L1'], geom['L2'], - geom['zlug'], 'clay', - ground_conds['Su0'], - ground_conds['k'], - ground_conds['alpha']) - results['Horizontal max.'] = results['Horizontal max.'] - results['Vertical max.'] = results['Vertical max.'] - else: - raise Exception('Ground conditions dictionary needs Su0, k, and alpha information') - else: - print('Warning: Soil type {soil} is not compatible with torpedo pile anchor') - - # - - - - driven piles - - - - - elif 'driven' in anchType: # driven pile anchor - # check loads have been calculated (needed for capacity function in this case) - if not 'Ha' in loads: - # call getLugForces function - loads = self.getLugForces(plot=plot) - H_inc = loads['Ha']*0.1 # increment H by 10% of Ha load in the while loops to back-calc max H from displacements - H = 0 - # check soil - if 'weak_rock' in soil: - from .anchors_famodel.capacity_drivenrock import getCapacityDrivenRock - - if not profile: - if 'UCS' in ground_conds and 'Em' in ground_conds: - profile = [[0,ground_conds['UCS'],ground_conds['Em']], - [75,ground_conds['UCS'],ground_conds['Em']]] #profile = [list(x) for x in list(zip(ground_conds['depth'],ground_conds['UCS'],ground_conds['Em']))] - else: - raise Exception('Ground conditions dictionary needs UCS, Em, and depth information for weak rock driven pile anchor') - - y, z, results = getCapacityDrivenRock(profile, geom['L'], geom['D'], - geom['zlug'], loads['Va'], - loads['Ha'], plot=plot) - - # loop through, calling capacity with larger H values until a displacement value goes above limit - while results['Lateral displacement']< 0.05*geom['D'] and results['Rotational displacement'] < 0.25: - # increment H - H += H_inc - # call capacity function - y, z, results = getCapacityDrivenRock(profile, geom['L'], - geom['D'], geom['zlug'], - loads['Va'], H=H, plot=plot) - - - elif 'sand' in soil: - from .anchors_famodel.capacity_drivensoil import getCapacityDrivenSoil - if profile or ('gamma' in ground_conds and 'Dr' in ground_conds and 'phi' in ground_conds): - if not profile: - profile = [[0,ground_conds['phi'],ground_conds['gamma'],ground_conds['Dr']], - [75,ground_conds['phi'],ground_conds['gamma'],ground_conds['Dr']]] #profile = [list(x) for x in list(zip(ground_conds['depth'],ground_conds['phi'],ground_conds['gamma']))] - - y, z, results = getCapacityDrivenSoil(profile, 'sand', - geom['L'], geom['D'], - geom['zlug'], loads['Va'], - loads['Ha'], plot=plot) - if geom['zlug'] > 0: - # need to check bending moment if lug is below mudline (+ zlug) - # loop through, calling capacity with larger H values until a displacement value goes above limit - while results['Lateral displacement']<= 0.05*geom['D'] and results['Bending moment'] <= results['Plastic moment']: - # increment H by 10% of load - H += H_inc - # call capacity function - y, z, results = getCapacityDrivenSoil(profile,'clay', - geom['L'], geom['D'], - geom['zlug'], loads['Va'], - H=H, plot=plot) - - else: - while results['Lateral displacement']<= 0.05*geom['D'] and results['Rotational displacement'] <= 0.25: - # increment H by 10% of load - H += H_inc - # call capacity function - y, z, results = getCapacityDrivenSoil(profile, 'clay', - geom['L'], geom['D'], - geom['zlug'], loads['Va'], - H=H, plot=plot) + for att in self.attachments.values(): + if isinstance(att['obj'], Mooring): + mtype = att['obj'].sections()[0]['type']['material'].lower() + if 'chain' not in mtype: + print('No chain below seafloor, setting Ta=Tm (no load transfer).') + return mtype, None, None, True else: - raise Exception('Ground conditions dictionary needs phi, gamma, and depth information for sand driven pile anchor') - elif 'clay' in soil or 'mud' in soil: - from .anchors_famodel.capacity_drivensoil import getCapacityDrivenSoil - #if profile or ('Su' in ground_conds and 'gamma' in ground_conds and 'depth' in ground_conds) or ('Su0' in ground_conds and 'k' in ground_conds): - if not profile: - if 'Su' in ground_conds and 'depth' in ground_conds and 'gamma' in ground_conds: - profile = [list(x) for x in list(zip(ground_conds['depth'],ground_conds['Su'],ground_conds['gamma']))] - elif 'Su0' in ground_conds and 'k' in ground_conds and 'gamma' in ground_conds: - Su = ground_conds['Su0']+ground_conds['k']*75 - profile = [[0,ground_conds['Su0'],ground_conds['gamma']],[75,Su,ground_conds['gamma']]] - else: - raise Exception('Ground conditions dictionary needs information for clay driven pile anchor') + d_nom = att['obj'].sections()[0]['type']['d_nom'] + w_nom = att['obj'].sections()[0]['type']['w'] + return 'chain', d_nom, w_nom, False + raise ValueError('No mooring line attachment found for anchor.') - y, z, results = getCapacityDrivenSoil(profile,'clay',geom['L'],geom['D'],geom['zlug'],loads['Va'],loads['Ha'], plot=plot) - - if geom['zlug'] > 0: - # need to check bending moment if lug is below mudline (+ zlug) - # loop through, calling capacity with larger H values until a displacement value goes above limit - while results['Lateral displacement']<= 0.05*geom['D'] and results['Bending moment'] <= results['Plastic moment']: - # increment H by 10% of load - H += H_inc - # call capacity function - y, z, results = getCapacityDrivenSoil(profile,'clay',geom['L'],geom['D'],geom['zlug'],loads['Va'], H=H, plot=plot) - - else: - while results['Lateral displacement']<= 0.05*geom['D'] and results['Rotational displacement'] <= 0.25: - # increment H by 10% of load - H += H_inc - # call capacity function - y, z, results = getCapacityDrivenSoil(profile,'clay',geom['L'],geom['D'],geom['zlug'],loads['Va'], H=H, plot=plot) - - - else: - print(f'Warning: Soil type {soil} is not compatible with driven pile anchors') - - # - - - - drilled and grouted piles - - - - - elif 'dandg' in anchType: # drill and grout pile - from .anchors_famodel.capacity_dandg import getCapacityDandG - # check for correct soil - if 'rock' in soil: - # check loads have been calculated (needed for capacity function in this case) - if not 'Ha' in loads: - # call getMPForces function - loads = self.getLugForces(plot=plot) - # check for correct ground properties - if profile or ('UCS' in ground_conds and 'Em' in ground_conds): - if not profile: - profile = [[0,ground_conds['UCS'],ground_conds['Em']],[75,ground_conds['UCS'],ground_conds['Em']]] #[list(x) for x in list(zip(ground_conds['depth'],ground_conds['UCS'],ground_conds['Em']))] - - # call capacity function once to get displacement values - y, z, results = getCapacityDandG(profile,geom['L'],geom['D'], - geom['zlug'], loads['Va'], - loads['Ha'], plot=plot) - H_inc = loads['Ha']*0.1 # increment H by 10% of Ha load - H = H_inc # start H at 10% of Ha load - # loop through, calling capacity with larger H values until a displacement value goes above limit - while results['Lateral displacement']< 0.05*geom['D'] and results['Rotational displacement'] < 0.25: - # call capacity function - y, z, results = getCapacityDandG(profile, geom['L'], geom['D'], - geom['zlug'], loads['Va'], - H=H, plot=plot) - # increment H - H += H_inc - else: - raise Exception('Ground conditions dictionary need UCS and Em information for drill and grout pile') - else: - print(f'Warning: soil type {soil} is not compatible with drill and grout pile') - - # - - - - anchor type not recognized or supported - - - - - else: - raise Exception(f'Anchor type {anchType} is not supported at this time') - - # - - - - save relevant results in dictionary using common terms - - - - - # capacity = cap*installAdj ??? OR is installAdj an input to the capacity functions? - # save capacity - if 'dandg' in anchType or 'driven' in anchType: # will take in dandg, dandg_pile, driven, driven_pile - self.anchorCapacity['Lat_max'] = results['Lateral displacement'] # [deg] - if 'Rotational displacement' in results: - self.anchorCapacity['Rot_max'] = results['Rotational displacement'] # [deg] - elif 'Bending moment' in results: - self.anchorCapacity['Mbend_max'] = results['Bending moment'] - self.anchorCapacity['Va_max'] = results['Axial capacity'] # [N] - self.anchorCapacity['Ha_max'] = H + def getMudlineForces(self, max_force=False, lines_only=False, seabed=True, xyz=False, project=None): + ''' + Find forces on anchor at mudline using the platform.getWatchCircle method + or the MoorPy Point.getForces method. Optionally computes the maximum force + based on platform excursion using the project's arrayWatchCircle method or + the attached platform's getWatchCircle method. - else: - if 'Horizontal max.' in results: - self.anchorCapacity['Ha_max'] = results['Horizontal max.']*1000 # [N] - self.anchorCapacity['Va_max'] = results['Vertical max.']*1000 # [N] - self.mass = results['Weight']*1000/self.g # mass in [kg] - - # add on extra for drag-embedment anchors (flukes) - if 'DEA' in anchType: - self.mass *= 1.75 - - - return(results) - - def getMudlineForces(self, max_force=False,lines_only=False, seabed=True, xyz=False,project=None): - '''Find forces on anchor at mudline using the platform.getWatchCircle method or MoorPy Point.getForces method. - Optionally, get forces at anchor lug location with getTransferLoad function in capacity_loads.py. - Stores in loads dictionary Parameters ---------- - max_force : boolean, optional - Find and save the maximum force on the anchor (True) or just get force at the current MoorPy system state (False) - lines_only : boolean, optional - Calculate forces from just mooring lines (True) or not (False). Default is false - seabed : boolean, optional - Include effect of seabed pushing up the anchor (True) or not (False). Default is true - xyz : boolean, optional - Return forces in x,y,z DOFs (True) or only the enabled DOFs (False). Default is false - + max_force : bool, optional + If True, computes the maximum expected force on the anchor + using platform excursion. Default is False. + lines_only : bool, optional + Calculate forces from just mooring lines (True) or not (False). Default is False. + seabed : bool, optional + Include effect of seabed pushing up the anchor (True) or not (False). Default is True. + xyz : bool, optional + Return forces in x, y, z DOFs (True) or only the enabled DOFs (False). Default is False. + project : object, optional + Project object that can run arrayWatchCircle(). Used only if max_force is True. + + Returns + ------- + dict + Dictionary containing mudline forces. ''' Platform = famodel.platform.platform.Platform + if max_force: if project: - # get watch circle of platform(s) project.arrayWatchCircle() else: - # find platform associated with this anchor for att in self.attachments.values(): - if isinstance(att['obj'],Mooring): + if isinstance(att['obj'], Mooring): for attM in att['obj'].attached_to: - if isinstance(attM,Platform): - locx,locy,maxVals = attM.getWatchCircle() - # call getForces method from moorpy point object + if isinstance(attM, Platform): + locx, locy, maxVals = attM.getWatchCircle() + Hm = np.sqrt(maxVals[0]**2 + maxVals[1]**2) + Vm = maxVals[2] + thetam = np.degrees(np.arctan2(Vm, Hm)) + self.loads['Hm'] = Hm + self.loads['Vm'] = Vm + self.loads['thetam'] = thetam + self.loads['mudline_load_type'] = 'max_force' + break else: - loads = self.mpAnchor.getForces(lines_only=lines_only, seabed=seabed, xyz=xyz) - self.loads['Hm'] = np.sqrt(loads[0]**2+loads[1]**2) # mudline forces in [N] - self.loads['Vm'] = loads[2] # [N] - self.loads['thetam'] = np.degrees(np.arctan(self.loads['Vm']/self.loads['Hm'])) # [deg] + # loads = self.mpAnchor.getForces(lines_only=lines_only, seabed=seabed, xyz=xyz) + # MoorPy Body.getForces does not accept seabed/lines_only in current API. + # Get forces (total), optionally post-process seabed if needed. + loads = self.mpAnchor.getForces() + Hm = np.sqrt(loads[0]**2 + loads[1]**2) + Vm = loads[2] + thetam = np.degrees(np.arctan2(Vm, Hm)) + self.loads['Hm'] = Hm + self.loads['Vm'] = Vm + self.loads['thetam'] = thetam self.loads['mudline_load_type'] = 'current_state' - - # loads determined from moorpy are static + self.loads['method'] = 'static' - - return(self.loads) - - def getLugForces(self, mudloads=None, max_force=True, plot=False): + return self.loads + + def getLugForces(self, Hm, Vm, zlug, line_type=None, d=None, w=None, plot=False, display=0): ''' - Find forces on an anchor at the lug point based on the mudline forces and angles. Calls getTransferFunction script + Calculate the lug forces Ha and Va based on mudline loads using local soil profile. Parameters ---------- - mudloads : dict, optional - Dictionary of max mudline forces. The default is None. + Hm : float + Horizontal mudline load (N) + Vm : float + Vertical mudline load (N) + zlug : float + Padeye embedment depth (m) + line_type : str, optional + Type of mooring line ('chain' or 'wire') + d : float, optional + Mooring line diameter (m) + w : float, optional + Mooring line unit weight (N/m) + plot : bool, optional + Whether to plot the load transfer profile Returns ------- - loads: dict - Dictionary of loads at the lug point [N] - + Ha : float + Horizontal load at lug (N). + Va : float + Vertical load at lug (N). ''' from .anchors_famodel.capacity_load import getTransferLoad + from .anchors_famodel.support_plots import plot_load + + # Ensure soil profile is available + if self.soil_profile is None or self.soil_type is None: + raise ValueError("Anchor soil profile or soil type is not assigned. Use setSoilProfile first.") + + soil_profile = self.soil_profile + soil_type = self.soil_type + + # Determine mudline depth + z0 = soil_profile[0]['layers'][0]['top'] + + # Load transfer if padeye is embedded + if zlug > z0: + # Check if padeye is embedded in rock + if any(layer.get('soil_type') == 'rock' for layer in self.soil_profile[0]['layers']): + raise ValueError('[Warning] Padeye depth is embedded in rock. Embedded line in rock is not possible.') + + + if line_type is None or d is None or w is None: + try: + line_type, d, w = self.getLineProperties() + except ValueError: + print('[Warning] No mooring attachment found. Trying anchor-level line properties...') + line_type = getattr(self, 'line_type', None) + d = getattr(self, 'd', None) + w = getattr(self, 'w', None) + + if any(v is None for v in [line_type, d, w]): + print('[Fallback] Using default chain properties.') + line_type = 'chain' + d = 0.16 + w = 5500.0 + + layers, loads = getTransferLoad( + profile_map=self.soil_profile, + Tm=np.sqrt(Hm**2 + Vm**2), + thetam=np.degrees(np.arctan2(Vm, Hm)), + zlug=zlug, + line_type=line_type, + d=d, + w=w, + plot=plot, display=display) + + Ta = loads['Ta'] + thetaa = loads['thetaa'] + Ha = Ta*np.cos(np.deg2rad(thetaa)) + Va = Ta*np.sin(np.deg2rad(thetaa)) + + else: + Ha = Hm + Va = Vm + layers = self.soil_profile[0]['layers'] + + + if plot == True: + plot_load(layers, loads['drag_values'], loads['depth_values'], + loads['Tm'], loads['thetam'], loads['Ta'], + loads['thetaa'], zlug=zlug) + + return layers, Ha, Va + + def getCapacityAnchor(self, Hm, Vm, zlug, line_type=None, d=None, w=None, mass_update=False, plot=False, display=0): + ''' + Calculate anchor capacity based on anchor type and local soil profile. + + Parameters + ---------- + Hm : float + Horizontal mudline load (N) + Vm : float + Vertical mudline load (N) + zlug : float + Padeye embedment depth (m) + line_type : str, optional + Type of mooring line ('chain' or 'wire') + d : float, optional + Mooring line diameter (m) + w : float, optional + Mooring line unit weight (N/m) + mass_update : bool, optional + Whether to update the mass when is not assigned + plot : bool, optional + Whether to plot the load transfer and pile geometry + + Returns + ------- + results : dict + Capacity results dictionary from the selected capacity function. + ''' + + from .anchors_famodel.capacity_plate import getCapacityPlate + from .anchors_famodel.capacity_suction import getCapacitySuction + from .anchors_famodel.capacity_torpedo import getCapacityTorpedo + from .anchors_famodel.capacity_helical import getCapacityHelical + from .anchors_famodel.capacity_driven import getCapacityDriven + from .anchors_famodel.capacity_drilled import getCapacityDrilled + + capacity_dispatch = { + 'suction': getCapacitySuction, + 'sepla': getCapacityPlate, + 'dea': getCapacityPlate, + 'depla': getCapacityPlate, + 'vla': getCapacityPlate, + 'plate': getCapacityPlate, + 'torpedo': getCapacityTorpedo, + 'helical': getCapacityHelical, + 'driven': getCapacityDriven, + 'drilled': getCapacityDrilled} + + if self.display > 0: print('[DEBUG] profile_name:', self.profile_name) + if self.display > 0: print('[DEBUG] soil_profile passed as profile_map:') + for entry in self.soil_profile: + if self.display > 0: print(entry.get('name'), list(entry.keys())) + + + if self.display > 1: print(f'[Debug] mass_update = {mass_update}') + anchType_clean = self.dd['type'].lower().replace(' ', '') + capacity_func = capacity_dispatch.get(anchType_clean) + if capacity_func is None: + raise ValueError(f"Unknown anchor type '{self.anchType}' for anchor capacity calculation.") + + if self.soil_profile is None or self.soil_type is None: + raise ValueError("Soil profile or soil type not set for this anchor.") + + soil_profile = self.soil_profile + soil_type = self.soil_type + z0 = soil_profile[0]['layers'][0]['top'] + + if line_type is None or d is None or w is None: + try: + line_type, d, w = self.getLineProperties() + except ValueError: + if self.display > 0: print('[Warning] No mooring attachment found. Trying anchor-level line properties...') + line_type = getattr(self, 'line_type', None) + d = getattr(self, 'd', None) + w = getattr(self, 'w', None) + + if any(v is None for v in [line_type, d, w]): + if self.display > 0: print('[Fallback] Using default chain properties.') + line_type = 'chain' + d = 0.16 + w = 5500.0 + + # Load transfer if padeye is embedded below mudline + if zlug > z0: + layers, Ha, Va = self.getLugForces( + Hm, Vm, + zlug=zlug, + line_type=line_type, + d=d, + w=w, + plot=False, display=display) + + Ta = np.sqrt(Ha**2 + Va**2) + thetaa = np.degrees(np.arctan2(Va, Ha)) + + if self.display > 0: print(f"[Branch Check] Entered {'zlug>z0' if zlug>z0 else 'else'} for anchor {self.anchType}") + + else: + Ha = Hm + Va = Vm + Ta = np.sqrt(Ha**2 + Va**2) + thetaa = np.degrees(np.arctan2(Va, Ha)) + + if self.display > 0: print(f"[Branch Check] Entered {'zlug>z0' if zlug>z0 else 'else'} for anchor {self.anchType}") + + # --- Call the appropriate capacity function --- + if anchType_clean in ['sepla', 'dea', 'depla', 'vla', 'plate']: + self.capacity_format = 'plate' + B = self.dd['design']['B'] + L = self.dd['design']['L'] + if self.display > 1: print(f"[Final Check] Ha = {Ha}, Va = {Va}, anchor = {self.anchType}") + beta = 90.0 - np.degrees(np.arctan2(Va, Ha)) + self.dd['design']['beta'] = beta + layers, results = capacity_func( + profile_map=self.soil_profile, + location_name=self.profile_name, + B=B, L=L, zlug=zlug, + beta=beta, + Ha=Ha, Va=Va, + plot=plot, display=display) + + elif anchType_clean == 'suction': + self.capacity_format = 'envelope' + D = self.dd['design']['D'] + L = self.dd['design']['L'] + zlug = self.dd['design']['zlug'] + layers, results = capacity_func( + profile_map=self.soil_profile, + location_name=self.profile_name, + D=D, L=L, zlug=zlug, + Ha=Ha, Va=Va, + thetalug=5, psilug=7.5, + plot=plot, display=display) + + elif anchType_clean == 'torpedo': + self.capacity_format = 'envelope' + D1 = self.dd['design']['D1'] + D2 = self.dd['design']['D2'] + L1 = self.dd['design']['L1'] + L2 = self.dd['design']['L2'] + ballast = self.dd['design'].get('ballast', 0.0) + layers, results = capacity_func( + profile_map=self.soil_profile, + location_name=self.profile_name, + D1=D1, D2=D2, L1=L1, L2=L2, + zlug=zlug, + ballast=ballast, + Ha=Ha, Va=Va, + plot=plot, display=display) + + elif anchType_clean == 'helical': + self.capacity_format = 'component' + D = self.dd['design']['D'] + L = self.dd['design']['L'] + d = self.dd['design']['d'] + zlug = self.dd['design']['zlug'] + layers, results = capacity_func( + profile_map=self.soil_profile, + location_name=self.profile_name, + D=D, L=L, d=d, + zlug=zlug, + Ha=Ha, Va=Va, + plot=plot, display=display) + + elif anchType_clean == 'driven': + self.capacity_format = 'component' + L = self.dd['design']['L'] + D = self.dd['design']['D'] + zlug = self.dd['design']['zlug'] + layers, y, z, results = capacity_func( + profile_map=self.soil_profile, + location_name=self.profile_name, + L=L, D=D, zlug=zlug, + Ha=Ha, Va=Va, + plot=plot, display=display) + + elif anchType_clean == 'drilled': + self.capacity_format = 'component' + L = self.dd['design']['L'] + D = self.dd['design']['D'] + zlug = self.dd['design']['zlug'] + layers, y, z, results = capacity_func( + profile_map=self.soil_profile, + location_name=self.profile_name, + L=L, D=D, zlug=zlug, + Ha=Ha, Va=Va, + plot=plot, display=display) + + else: + raise ValueError(f"Anchor type '{self.anchType}' not supported.") + + # --- Store results --- + self.anchorCapacity = { + 'Hmax': results.get('Horizontal max.', np.nan), + 'Vmax': results.get('Vertical max.', np.nan), + 'Ha': Ha, + 'Va': Va, + 'zlug': zlug, + 'z0': z0} + + # Correct UC format + if anchType_clean in ['suction', 'torpedo', 'plate', 'sepla', 'dea', 'depla', 'vla']: + self.anchorCapacity['UC'] = results.get('Unity check', np.nan) - nolugload = False + elif anchType_clean in ['helical', 'driven', 'drilled']: + self.anchorCapacity['Unity check (horizontal)'] = results.get('Unity check (horizontal)', np.nan) + self.anchorCapacity['Unity check (vertical)'] = results.get('Unity check (vertical)', np.nan) - if not mudloads: - if not self.loads: - # get max mudline forces first - self.getMudlineForces(max_force=max_force) - elif not 'mudline_load_type' in self.loads: - raise KeyError("Loads dictionary must specify 'mudline_load_type'='current_state' or 'mudline_load_type'='max', where 'max' indicates the loads are maximum loads.") - elif max_force and self.loads['mudline_load_type'] != 'max': - # need max forces, not current state - self.getMudlineForces(max_force=True) - mudloads = self.loads + # Copy over lateral and rotational displacements + if 'Lateral displacement' in results: + self.anchorCapacity['Lateral displacement'] = results['Lateral displacement'] + if 'Rotational displacement' in results: + self.anchorCapacity['Rotational displacement'] = results['Rotational displacement'] + + # Weight calculated via dimensions + if not mass_update: + if 'Weight pile' in results: + self.anchorCapacity['Weight pile'] = results['Weight pile'] + if 'Weight plate' in results: + self.anchorCapacity['Weight plate'] = results['Weight plate'] else: - # check syntax - if not 'Hm' in mudloads or not 'Vm' in mudloads: - raise KeyError('Mudline load dictionary must have Hm and Vm for horizontal load and vertical load (in [N]) at the mudline') - if not 'thetam' in mudloads: - mudloads['thetam'] = np.degrees(np.arctan(mudloads['Vm']/mudloads['Hm'])) + if 'Weight pile' in results: + self.mass = results['Weight pile']/self.g + self.anchorCapacity['Weight pile'] = results['Weight pile'] + if 'Weight plate' in results: + self.mass = results['Weight plate']/self.g + self.anchorCapacity['Weight plate'] = results['Weight plate'] - def makeEqual_TaTm(mudloads): - mudloads['Ha'] = mudloads['Hm'] # [N] - mudloads['Va'] = mudloads['Vm'] # [N] - mudloads['thetaa'] = mudloads['thetam'] # [deg] + # print(f"[DEBUG] Stored Lateral displacement in anchorCapacity: {self.anchorCapacity['Lateral displacement']:.6f}") + + def getSizeAnchor(self, geom, geomKeys, geomBounds=None, loads=None, lambdap_con=[4, 8], + zlug_fix=True, safety_factor={}, plot=False, display=0): + ''' + Generalized optimization method for all anchor types, using dictionary-based safety factors. + ''' + self.display = display + + anchType_clean = self.dd['type'].strip().lower() + print(f"[Debug] Anchor type parsed: '{anchType_clean}'") + + if loads is None: + loads = self.loads - if 'zlug' in self.dd['design']: - if self.dd['design']['zlug'] > 0: - # get line type - for att in self.attachments.values(): - if isinstance(att['obj'],Mooring): - mtype = att['obj'].sections()[0]['type']['material'] - if not 'chain' in mtype: - print('No chain on seafloor, setting Ta=Tm') - nolugload = True - break - else: - md = att['obj'].sections()[0]['type']['d_nom'] - mw = att['obj'].sections()[0]['type']['w'] - soil = next(iter(self.soilProps.keys()), None) - ground_conds = self.soilProps[soil] - # update soil conds as needed to be homogeneous - for key,prop in ground_conds.items(): - if isinstance(prop,list) or isinstance(prop,np.ndarray): - if len(prop)>1: - print('Warning: Only homogeneous soils are supported at this time. Only the first item in a property list will be used.') - break - else: - ground_conds[key] = prop[0] - - Tm = np.sqrt(mudloads['Hm']**2+mudloads['Vm']**2) # [N] - if 'clay' in soil or 'mud' in soil and not nolugload: - # Tm, thetam, zlug, line_type, d, soil_type, Su0=None, k=None, w=None - try: - loadresults = getTransferLoad(Tm/1000,mudloads['thetam'], - self.dd['design']['zlug'],mtype,md, - 'clay',Su0=ground_conds['Su0'], - k=ground_conds['k'],w=mw/1000, - plot=plot) # output Ha and Va (convert weight to kN/m) - except Exception as e: - print(e) - print('Unable to get loads at anchor lug location. Setting Ta = Tm') - nolugload = True - elif 'sand' in soil and not nolugload: - soil = 'sand' - try: - loadresults = getTransferLoad(Tm/1000, self.loads['thetam'], - self.dd['design']['zlug'], - mtype, md, soil, - gamma=ground_conds['gamma'], - phi=ground_conds['phi'], - delta=ground_conds['delta'], - w=mw/1000,plot=plot) # output Ha and Va (convert weight to kN/m) - except Exception as e: - print(e) - print('Unable to get loads at anchor lug location. Setting Ta = Tm') - nolugload = True - elif 'rock' in soil and not nolugload: - raise ValueError('zlug should be <= 0 for rock.') - - # if loadresults['V']<0: - # # results are invalid - # print('Warning: invalid results for the combination of anchor ',self.dd['type'],' soil ',soil,' and loads ',mudloads,'. Setting Ha=Hm, Va=Vm, thetaa=thetam') - # makeEqual_TaTm(mudloads) - if nolugload: - makeEqual_TaTm(mudloads) + sf_Hm = safety_factor.get('Hm', safety_factor.get('SF_horizontal', 1.0)) + sf_Vm = safety_factor.get('Vm', safety_factor.get('SF_vertical', 1.0)) + sf_uc = safety_factor.get('SF_combined', max(sf_Hm, sf_Vm)) # conservative by default + + Hm = loads['Hm']*sf_Hm + Vm = loads['Vm']*sf_Vm + + line_type = getattr(self, 'line_type', 'chain') + d = getattr(self, 'd', 0.16) + w = getattr(self, 'w', 5000.0) + + def update_zlug(): + if 'suction' in anchType_clean and not zlug_fix and 'zlug' not in geomKeys: + self.dd['design']['zlug'] = (2/3)*self.dd['design']['L'] + elif np.any([name in anchType_clean for name in ['driven', 'helical']]) and not zlug_fix: + ratio = self.dd['design'].get('zlug_ratio', self.dd['design']['zlug']/self.dd['design']['L']) + self.dd['design']['zlug_ratio'] = ratio + self.dd['design']['zlug'] = ratio*self.dd['design']['L'] + elif 'drilled' in anchType_clean: + self.dd['design']['zlug'] = 0 + + def get_lambda(): + if 'torpedo' in anchType_clean: + L = self.dd['design']['L1'] + self.dd['design']['L2'] + A_wing = (self.dd['design']['D1'] - self.dd['design']['D2']) * self.dd['design']['L1'] + A_shaft = self.dd['design']['D2'] * L + D = (A_wing + A_shaft) / L + elif np.any([name in anchType_clean for name in ['driven', 'drilled', 'helical', 'suction']]): + L = self.dd['design']['L'] + D = self.dd['design']['D'] + elif np.any([name in anchType_clean for name in ['plate', 'sepla', 'dea', 'depla', 'vla']]): + L = self.dd['design']['L'] + D = self.dd['design']['B'] + else: + raise ValueError(f'lambda not defined for anchor type: {anchType_clean}') + return L/D + + def constraint_lambda_min(vars): + for i, key in enumerate(geomKeys): + self.dd['design'][key] = vars[i] + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + return get_lambda() - lambdap_con[0] + + def constraint_lambda_max(vars): + return lambdap_con[1] - get_lambda() + + def constraint_bounds(vars): + con_bound_return = np.zeros(len(geomKeys)*2) + for i,var in enumerate(geomKeys): + con_bound_return[2*i] = self.dd['design'][var] - geomBounds[i][0] + con_bound_return[2*i+1] = geomBounds[i][1] - self.dd['design'][var] + return con_bound_return + + if np.any([name in anchType_clean for name in ['suction', 'torpedo', 'plate', 'sepla', 'dea', 'depla', 'vla']]): + target_UC = 1.0/sf_uc + + def objective_uc(vars): + ''' + for i, key in enumerate(geomKeys): + self.dd['design'][key] = vars[i] + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + ''' + #UC = self.anchorCapacity.get('UC', 2.0) + #return (UC - target_UC)**2 + #return self.anchorCapacity.get('Weight pile') + if any(name in anchType_clean for name in ['plate', 'sepla', 'dea', 'depla', 'vla']): + return self.anchorCapacity.get('Weight plate') else: - mudloads['Ha'] = loadresults['H']*1000 # [N] - mudloads['Va'] = loadresults['V']*1000 # [N] - mudloads['thetaa'] = loadresults['angle'] # [deg] + return self.anchorCapacity.get('Weight pile') + + def constraint_uc_envelope(vars): + return self.anchorCapacity.get('UC', 0.0) - target_UC + + constraints_uc = [ + {'type': 'ineq', 'fun': constraint_lambda_min}, + {'type': 'ineq', 'fun': constraint_lambda_max}, + {'type': 'ineq', 'fun': constraint_uc_envelope}, + {'type': 'ineq', 'fun': constraint_bounds}, + ] + + result_uc = minimize( + objective_uc, + geom, + method='COBYLA', + constraints=constraints_uc, + options={'rhobeg': 0.1, 'catol': 0.01, 'maxiter': 500} + ) + + endGeom = dict(zip(geomKeys, result_uc.x)) + self.dd['design'].update(endGeom) + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=plot, display=display) + + print('\nFinal Optimized Anchor (UC-based):') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + + def near_border(): + UC_h = self.anchorCapacity['Ha']/self.anchorCapacity['Hmax'] + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + limit_lat = 0.05*self.dd['design']['D'] # 10% of the pile diameter + limit_rot = 10.0 # 10 deg + + near_UC_h = 0.95 <= UC_h <= 1.0 + near_UC_v = 0.95 <= UC_v <= 1.0 + near_disp_lat = 0.95*limit_lat <= disp_lat <= limit_lat + near_disp_rot = 4.75 <= disp_rot <= limit_rot + + return near_UC_h or near_UC_v or near_disp_lat or near_disp_rot + + def termination_condition(): + UC_h = self.anchorCapacity['Ha']/self.anchorCapacity['Hmax'] + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + limit_lat = 0.05*self.dd['design']['D'] # 10% of the pile diameter + limit_rot = 10.0 # 10 deg + + all_satisfied = (UC_h <= 1.0 and UC_v <= 1.0 and disp_lat <= limit_lat and disp_rot <= limit_rot) + + if all_satisfied: + if near_border(): + if self.display > 0: print('[Termination] All criteria satisfied and near border.') + return 'terminate' + else: + if self.display > 0: print('[Safe but not near border] Continue shrinking...') + return 'continue' + return 'continue' + + def termination_condition_drilled(): + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + limit_lat = 0.05*self.dd['design']['D'] # 10% of the pile diameter + limit_rot = 10.0 # 10 deg + + all_satisfied = (UC_v <= 1.0 and disp_lat <= limit_lat and disp_rot <= limit_rot) + + if all_satisfied: + if near_border(): + if self.display > 0: print('[Termination] All criteria satisfied and near border.') + return 'terminate' + else: + if self.display > 0: print('[Safe but not near border] Continue shrinking...') + return 'continue' + return 'continue' + + def is_valid(value): + return np.isfinite(value) and not np.isnan(value) and abs(value) < 1e6 + + if anchType_clean in ['helical', 'driven']: + L0, D0 = geom if len(geom) == 2 else [5.0, 1.0] + self.dd['design']['L'] = L0 + self.dd['design']['D'] = D0 + Lmin, Lmax = geomBounds[0] + Dmin, Dmax = geomBounds[1] + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + + UC_h = self.anchorCapacity['Ha']/self.anchorCapacity['Hmax'] + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + limit_disp = 0.10*D0 # 10% of the pile diameter + limit_rot = 10.0 # 10 deg + direction = 'shrink' if (UC_h <= 1.0 and UC_v <= 1.0 and disp_lat <= limit_disp and disp_rot <= limit_rot) else 'grow' + + max_iter = 200 + iter_count = 0 + + if direction == 'shrink': + for L in np.arange(L0, Lmin - 1e-6, -0.25): + self.dd['design']['L'] = L + for D in np.arange(Dmax, Dmin - 1e-6, -0.05): + if L/D > lambdap_con[1] or L/D < lambdap_con[0]: + continue + self.dd['design']['L'] = L + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + UC_h = self.anchorCapacity['Ha']/self.anchorCapacity['Hmax'] + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + if self.display > 0: print(f'[Iter {iter_count}] L={L:.2f}, D={D:.2f}, UC_h={UC_h:.3f}, UC_v={UC_v:.3f}, lat={disp_lat:.3f} m, rot={disp_rot:.3f} deg') + iter_count += 1 + if not all(is_valid(v) for v in [UC_h, UC_v, disp_lat, disp_rot]): + continue + if termination_condition(): + print(f'\nTermination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + elif direction == 'grow': + for L in np.arange(L0, Lmax + 1e-6, 0.25): + self.dd['design']['L'] = L + for D in np.arange(Dmin, Dmax + 1e-6, 0.05): + if L/D > lambdap_con[1] or L/D < lambdap_con[0]: + continue + self.dd['design']['L'] = L + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + UC_h = self.anchorCapacity['Ha']/self.anchorCapacity['Hmax'] + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + if self.display > 0: print(f'[Iter {iter_count}] L={L:.2f}, D={D:.2f}, UC_h={UC_h:.3f}, UC_v={UC_v:.3f}, lat={disp_lat:.3f} m, rot={disp_rot:.3f} deg') + iter_count += 1 + status = termination_condition() + if status == 'terminate': + print(f'Termination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + elif status == 'continue': + continue + status = termination_condition() + if status == 'terminate': + print(f'\nTermination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + else: + raise ValueError(f"Unknown optimization direction: {direction}") + + if self.display > 0: print('[Warning] While-loop search reached bounds without meeting criteria.') + + if 'drilled' in anchType_clean: + L0, D0 = geom if len(geom) == 2 else [5.0, 1.0] + self.dd['design']['L'] = L0 + self.dd['design']['D'] = D0 + Lmin, Lmax = geomBounds[0] + Dmin, Dmax = geomBounds[1] + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + limit_disp = 0.10*D0 # 10% of the pile diameter + limit_rot = 10.0 # 10 deg + direction = 'shrink' if (UC_v <= 1.0 and disp_lat <= limit_disp and disp_rot <= limit_rot) else 'grow' + + max_iter = 200 + iter_count = 0 + + if direction == 'shrink': + for L in np.arange(L0, Lmin - 1e-6, -0.25): + self.dd['design']['L'] = L + for D in np.arange(Dmax, Dmin - 1e-6, -0.05): + if L/D > lambdap_con[1] or L/D < lambdap_con[0]: + continue + self.dd['design']['L'] = L + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + if self.display > 0: print(f'[Iter {iter_count}] L={L:.2f}, D={D:.2f}, UC_v={UC_v:.3f}, lat={disp_lat:.3f} m, rot={disp_rot:.3f} deg') + iter_count += 1 + if not all(is_valid(v) for v in [UC_v, disp_lat, disp_rot]): + continue + if termination_condition_drilled(): + print(f'\nTermination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + elif direction == 'grow': + for L in np.arange(L0, Lmax + 1e-6, 0.25): + self.dd['design']['L'] = L + for D in np.arange(Dmin, Dmax + 1e-6, 0.05): + if L/D > lambdap_con[1] or L/D < lambdap_con[0]: + continue + self.dd['design']['L'] = L + update_zlug() + self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], + line_type=line_type, d=d, w=w, mass_update=True, plot=False, display=display) + UC_v = self.anchorCapacity['Va']/self.anchorCapacity['Vmax'] + disp_lat = abs(self.anchorCapacity.get('Lateral displacement', 0.0)) + disp_rot = abs(self.anchorCapacity.get('Rotational displacement', 0.0)) + if self.display > 0: print(f'[Iter {iter_count}] L={L:.2f}, D={D:.2f}, UC_v={UC_v:.3f}, lat={disp_lat:.3f} m, rot={disp_rot:.3f} deg') + iter_count += 1 + status = termination_condition_drilled() + if status == 'terminate': + print(f'Termination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return + elif status == 'continue': + continue + status = termination_condition_drilled() + if status == 'terminate': + print(f'\nTermination criteria met.') + print('Design:', self.dd['design']) + print('Capacity Results:', self.anchorCapacity) + return else: - # Ha = Hm because zlug is at mudline or above - makeEqual_TaTm(mudloads) + raise ValueError(f"Unknown optimization direction: {direction}") + + if self.display > 0: print('[Warning] While-loop search reached bounds without meeting criteria.') + else: - print('No zlug given, assuming loads at mudline = loads at anchor lug') - makeEqual_TaTm(mudloads) - - if not 'method' in mudloads: - # assume mudloads are static unless told otherwise - # loads determined from moorpy are static - mudloads['method'] = 'static' + raise ValueError(f"Anchor type '{anchType_clean}' not supported for safety factor input.") + + + def getSafetyFactor(self): + ''' + Calculate the safety factor based on the unity checks stored in capacity results. + + Returns + ------- + dict + Dictionary containing safety factors. + ''' + + anchType_clean = self.anchType.lower().replace(' ', '') + + if anchType_clean in ['helical', 'driven', 'drilled']: + UC_v = self.anchorCapacity.get('Unity check (vertical)', None) + UC_h = self.anchorCapacity.get('Unity check (horizontal)', None) + + if UC_v is None or UC_h is None: + print("Warning: Vertical or horizontal unity check (UC) not found in capacity results. Returning NaN.") + return {'SF_vertical': np.nan, 'SF_horizontal': np.nan} + + SF_v = 1.0/UC_v if UC_v != 0 else np.inf + SF_h = 1.0/UC_h if UC_h != 0 else np.inf + + return {'SF_vertical': SF_v, 'SF_horizontal': SF_h} + else: - mudloads['method'] = mudloads['method'] + UC = self.anchorCapacity.get('UC', None) + + if UC is None: + print("Warning: Unity check (UC) not found in capacity results. Returning NaN.") + return {'SF_combined': np.nan} + + SF = 1.0/UC if UC != 0 else np.inf + + return {'SF_combined': SF} + + def getCost(self, ms=None, mass_update=True): + ''' + Assign material cost using a Point object and getCost_and_MBL(). - return mudloads + Parameters + ---------- + ms : MoorPy System, optional + The mooring system to which the anchor point belongs. If None, a new one is created. + mass_update : bool, optional + If True, update mpAnchor mass from self.mass. + If False, preserve existing mpAnchor.m if already set. + ''' + + # Create or use existing MoorPy system + if ms is None: + ms = mp.System() + + # Create MoorPy Point using makeMoorPyAnchor + self.makeMoorPyAnchor(ms) + + # Assign self.mass if missing + if self.mass is None or mass_update: + if 'Weight pile' in self.anchorCapacity: + self.mass = self.anchorCapacity['Weight pile']/self.g + elif 'Weight plate' in self.anchorCapacity: + self.mass = self.anchorCapacity['Weight plate']/self.g + else: + raise KeyError("Missing 'Weight pile' or 'Weight plate' in anchorCapacity. \ + Run getCapacityAnchor() before getCostAnchor(), or define self.mass explicitly.") + + # Assign mass to MoorPy point + self.mpAnchor.m = self.mass + + cost, MBL, info = self.mpAnchor.getCost_and_MBL() + + # Store results + self.cost = { + 'Material cost': cost, + #'MBL': MBL, + #'unit_cost': cost/self.mpAnchor.m + } + + return self.cost + + def getCombinedPlot(self): + ''' + Create a plot showing the suction pile and the inverse catenary overlay in the same coordinate system. + ''' + from anchors_famodel.capacity_load import getTransferLoad + from anchors_famodel.capacity_plots import plot_suction + + if self.anchType.lower() != 'suction': + raise NotImplementedError("getCombinedPlot only supports suction piles.") + + # Extract design inputs + design = self.dd['design'] + D = design['D'] + L = design['L'] + zlug = design['zlug'] + + if self.soil_profile is None or self.soil_type is None: + raise ValueError("Soil profile or type not assigned. Use setSoilProfile first.") + + soil_profile = self.soil_profile + soil_type = self.soil_type + z0 = soil_profile[0]['top'] + + Hm = self.loads['Hm'] + Vm = self.loads['Vm'] + thetam = self.loads.get('thetam', np.degrees(np.arctan2(Vm, Hm))) + + line_type = getattr(self, 'line_type', 'chain') + d = getattr(self, 'd', 0.16) + w = getattr(self, 'w', 5000.0) + + # Get inverse catenary path + layers, result = getTransferLoad( + profile_map=[{'layers': self.soil_profile}], + Tm=np.sqrt(Hm**2 + Vm**2), + thetam=thetam, + zlug=zlug, + line_type=line_type, + d=d, + w=w, + plot=False + ) + + drag_values = np.array(result['drag_values']) + depth_values = -np.array(result['depth_values'])[::-1] + + x_start = D/2 + drag_values[0] + z_start = zlug + drag_transformed = x_start - drag_values + depth_transformed = z_start + (depth_values- depth_values[0]) + + # Plot suction pile + plot_suction(soil_profile, L, D, z0=z0, zlug=zlug, title='Suction Pile and Mooring Line Load Path') + + + # Overlay inverse catenary path + plt.plot(drag_transformed, depth_transformed, color='b', lw=2.0, label='Inverse catenary') + plt.plot(drag_transformed[-1], depth_transformed[-1], 'ro', label='Mudline end') + plt.plot( drag_transformed[0], depth_transformed[0], 'go', label='Embedded end') + + n = 2e6 + Tm = result['Tm'] + Ta = result['Ta'] + thetaa = result['thetaa'] + + plt.arrow(drag_transformed[-1], depth_transformed[-1], + Tm*np.cos(np.deg2rad(thetam))/n, -Tm*np.sin(np.deg2rad(thetam))/n, + head_width=0.25, head_length=0.5, color='r', label='Mudline load') + plt.arrow(drag_transformed[0], depth_transformed[0], + Ta*np.cos(np.deg2rad(thetaa))/n, -Ta*np.sin(np.deg2rad(thetaa))/n, + head_width=0.25, head_length=0.5, color='g', label='Padeye load') + + xmax = max(drag_transformed[-1] + D, 2*D) + plt.xlim(-D, xmax) + plt.legend() + plt.grid(True) + plt.tight_layout() + plt.show() + + + def getFS(self, loads=None, acceptance_crit=None): ''' Compute safety factor for loads on the anchor @@ -683,53 +1218,9 @@ def makeBuffer(self, buff_rad=50): point = sh.Point(self.r[:2]) buff = point.buffer(buff_rad) return buff - - def getCost(self,costDict='default'): - '''find costs of anchor and store in design dictionary - - Parameters - ---------- - costDict : dictionary or yaml, optional - Dictionary of various costs for anchors. Sub costs that can be included are: - material : material costs - - ''' - if isinstance(costDict,str) and costDict != 'default': - import yaml - costDict = yaml.load(costDict, Loader=yaml.FullLoader) - anchType = self.dd['type'] - if costDict == 'default': - matCostDict = {'DEA':5.705,'suction_pile':4.435,'gravity':1.905} # mean values from Task 49 Design Basis ranges - instCostDict = {} - decomCostDict = {} - else: - matCostDict = costDict['material'] - if 'install' in costDict: - instCostDict = costDict['install'] - if 'decom' in costDict: - decomCostDict = costDict['decom'] - keyFail = True - # check if mass info is available - if not self.mass: - if self.soilProps: - # need mass - call capacity functions - self.getAnchorCapacity(plot=False) - else: - print('Soil properties needed to calculate anchor mass for cost. Setting cost to 0.') - self.mass = 0 - - # sort by type of anchor - for Ckey,Cval in matCostDict.items(): - if anchType in Ckey: - self.cost['materials'] = matCostDict[Ckey]*self.mass - # self.cost['install'] = instCostDict[Ckey] - # self.cost['decom'] = decomCostDict[Ckey] - keyFail = False - # raise error if anchType not found in cost dictionary - if keyFail: - raise KeyError(f'anchor type {anchType} not found in material cost dictionary') - - return(sum(self.cost.values())) + + + @@ -890,7 +1381,7 @@ def conFun_Suction(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, mi # convalB = 1 - results['UC'] return(conval) - def conFun_DandG(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): + def conFun_Drilled(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): newGeom = dict(zip(geomKeys, vars)) self.dd['design'].update(newGeom) @@ -992,10 +1483,8 @@ def conBounds(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): input_loads = {'Hm':loads['Hm']*minfs['Hm'], 'Vm':loads['Vm']*minfs['Vm']} else: input_loads = {'Ha':loads['Ha']*minfs['Ha'],'Va':loads['Va']*minfs['Va']} - - - - + + # Initial guess for geometry initial_guess = geom # [val for val in startGeom.values()] # Input values for geometry # geomKeys = [key for key in startGeom.keys()] @@ -1011,9 +1500,9 @@ def conBounds(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): {'type':'ineq','fun':conFunV,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, {'type':'ineq','fun':conBounds,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}] - elif 'dandg' in anchType: + elif 'drilled' in anchType: constraints = [{'type':'ineq','fun':conFun_LD,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, - {'type':'ineq','fun':conFun_DandG,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, + {'type':'ineq','fun':conFun_Drilled,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, {'type':'ineq','fun':conFunH,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, {'type':'ineq','fun':conFunV,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, {'type':'ineq','fun':conBounds,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}] @@ -1025,7 +1514,7 @@ def conBounds(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): # Run the optimization to find sizing that satisfy UC close to 1 print('optimizing anchor size') - if 'suction' in anchType or 'dandg' in anchType: + if 'suction' in anchType or 'drilled' in anchType: solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs), method="COBYLA", constraints=constraints, options={'rhobeg':0.1, 'catol':0.001}) else: @@ -1058,7 +1547,7 @@ def conBounds(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): print('new initial guess',initial_guess) # re-run optimization - if 'suction' in anchType or 'dandg' in anchType: + if 'suction' in anchType or 'drilled' in anchType: solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs), method="COBYLA", constraints=constraints, options={'rhobeg':0.1, 'catol':0.001}) else: diff --git a/famodel/anchors/anchor_capacity.py b/famodel/anchors/anchor_capacity.py deleted file mode 100644 index e3acb56b..00000000 --- a/famodel/anchors/anchor_capacity.py +++ /dev/null @@ -1,153 +0,0 @@ -"""The anchor capacity calculation 'switchboard' that holds generic -anchor capacity functions and calls the specific calculation functions -from other modules depending on the soil and anchor information.""" - -import matplotlib.pyplot as plt -import numpy as np - -import moorpy.MoorProps as mprop - -from .capacity_plate import getCapacityPlate -from .capacity_suction import getCapacitySuction -from .capacity_dandg import * - - - - - -def anchorCapacity(anchor, soil, display=0): - '''Calculate anchor holding capacity based on specified anchor and soil - information. - - Parameters - ---------- - anchor : dictionary - anchor description - soil : dictionary - soil description. Can be a keyword ([_/soft/medium/hard] clay, or sand) - for the level 1 model, or a soilProps dict for the level 2 model. - model_level : int - 1 or 2. - - Returns - ------- - UHC: float - required anchor ultimate holding capacity [kN] - info: dict - dictionary with additional information depending on the model. - ''' - - - if model_level == 1: # soil keyword indicates level 1 models - - - # calls level 1 anchor capacity function, with anchor/soil types and default assumptions - uhc, mass, info = mprop.getAnchorMass(uhc_mode=True, mass_int=anchor['mass'], - anchor=anchor['type'], soil_type=soil['class'], - method='static', display=0) - - #fx, fz = anchor_curves.anchorCapacity(0, 0, 0, anchor=anchor['type'], - # soil_type=soil['class'], display=display) - - - elif model_level==2: # dict indicates a soilProps dictionary - - # >>> we probably need anchor details too then ... - - - # For now the anchor properties get checked in this function - # but in the future they coudl be moved to the individual functions. - - if anchor['type'] == 'DEA': - # make curves from - pass - - elif anchor['type'] == 'SCA': - - L = getFromDict(anchor, 'length') - D = getFromDict(anchor, 'diameter', default=L/6) - thick = getFromDict(anchor, 'thickness', default=L/100) - F_ang = np.degrees(np.atan2(Fz, Fx)) # load inclination angle [deg] - - if soil['class'] == 'clay': - - gamma = getFromDict(soil, 'gamma', default=4.7) - Su0 = getFromDict(soil, 'So0' , default=2.39) - k = getFromDict(soil, 'k' , default=1.41) - alpha = getFromDict(soil, 'alpha', default=0.7) - SF = 2 - - results = getCapacitySuction(L, L_D_aspect=L/D, D_t_aspect=D/thick, - A_angle=F_ang, Su0=Su0, k=k, - Alpha=alpha, gamma=gamma, J=1/SF) - - elif soil['class'] == 'sand': - - gamma = getFromDict(soil, 'gamma', default=9.0) - phi = getFromDict(soil, 'phi' , default=30) - results = getCapacitySuction(L, L_D_aspect=L/D, D_t_aspect=D/thick, - A_angle=F_ang, gamma=gamma, Phi=phi) - - else: - #raise Exception(f"soil class '{soil.class}' is not supported.") - pass - - - elif anchor['type'] == 'VLA': - - # same plate capacity calc as SEPLA for now - will in future consider angle - - A = getFromDict(anchor, 'area') - thick = getFromDict(anchor, 'thickness', default=np.sqrt(L)/40) - H = getFromDict(anchor, 'embedment') # embedment depth [m] - - if soil['class'] == 'clay': - - gamma = getFromDict(soil, 'gamma', default=4.7) - Su0 = getFromDict(soil, 'So0' , default=2.39) - k = getFromDict(soil, 'k' , default=1.41) - - results = getCapacityPlate(A, B_t_aspect=np.sqrt(L)/thick, - Hs=H, Bita=30, Los=0.05, - gamma=gamma, So0=So0, k=k) - else: - raise Exception("Only clay soil is supported for this anchor type.") - - - elif anchor['type'] == 'SEPLA': - - A = getFromDict(anchor, 'area') - thick = getFromDict(anchor, 'thickness', default=np.sqrt(L)/40) - H = getFromDict(anchor, 'embedment') # embedment depth [m] - - if soil['class'] == 'clay': - - gamma = getFromDict(soil, 'gamma', default=4.7) - Su0 = getFromDict(soil, 'So0' , default=2.39) - k = getFromDict(soil, 'k' , default=1.41) - - results = getCapacityPlate(A, B_t_aspect=np.sqrt(L)/thick, - Hs=H, Bita=30, Los=0.05, - gamma=gamma, So0=So0, k=k) - else: - raise Exception("Only clay soil is supported for this anchor type.") - - else: - raise Exception(f"Anchor type '{anchor.type}' is not yet supported in hte intermediate anchor model set") - - - - print(f"UHC input: fx:{fx} fz:{fz} -- Mass: {mass}, Cost: {cost}") - info["UHC input"] = fx,fz #[kN] - info["Capacity_sf"] = capacity_sf #[kN] - info["Mass"] = mass #[mT] - info["Cost"] = cost #[$/mT] - #info["Length"] = L - info["Area"] = area - - else: - raise Exception("Model level must be 1 or 2") - - - return capacity, info - diff --git a/famodel/anchors/anchor_conflict_backup.py b/famodel/anchors/anchor_conflict_backup.py new file mode 100644 index 00000000..ff882af2 --- /dev/null +++ b/famodel/anchors/anchor_conflict_backup.py @@ -0,0 +1,1153 @@ +"""Anchor class for FAModel, containing information and key methods for anchors of mooring lines + Work in progress +""" +import moorpy as mp +import numpy as np +from famodel.famodel_base import Node +from famodel.mooring.mooring import Mooring +import famodel.platform.platform +from collections import defaultdict +import shapely as sh + + +class Anchor(Node): + + def __init__(self, dd=None, ms=None, r=[0,0,0], aNum=None, id=None, + g=9.81, rho=1025): + ''' + Parameters + ---------- + dd: dictionary + Design dictionary that contains all information on an anchor for a mooring line/shared mooring + { + type: # anchor type (plate,suction_pile,torpedo_pile,helical_pile,driven_pile,dandg_pile) + design: # all geometric info from yaml file, only need to include info relevant to your anchor type + A plate anchor area + D anchor diameter (or helix diameter for helical piles) + D1 torpedo anchor wing diameter + D2 torpedo anchor shaft diameter + d helical pile shaft diameter + L pile anchor length + L1 torpedo anchor wing length + L2 torpedo anchor shaft length + zlug padeye z elevation (+ down into the soil) + beta angle of plate anchor after keying (optional) + cost: + matCost: # material cost + instCost: # installation cost + decomCost: # decomissioning cost + } + ms: system object + MoorPy system object the anchor is in + + r: list + Location of anchor in x,y,z + + aNum: int + entry number in project.anchorList dictionary (may remove...) + id: str/int + unique id of this object + g: float + acceleration due to gravity in m/s^2 + rho: float + density of water in kg/m^3 + ''' + # Initialize as a node + Node.__init__(self,id) + + # Design description dictionary for this Anchor + self.dd = dd + + # MoorPy system this anchor is in + self.ms = ms + + # x,y,z location of anchor + self.r = r + + # anchor index in array mooring list (only used for shared moorings/anchors) + self.aNum = aNum + + # MoorPy anchor object + self.mpAnchor = None + + # get environment info + self.g = g # acceleration due to gravity (m/s^2) + self.rho = rho # density of fluid (kg/m^3) + + # anchor mass + if 'mass' in self.dd['design']: + self.mass = self.dd['design']['mass'] + else: + self.mass = None + + # Dictionaries for additional information + # anchor capacity + self.anchorCapacity = {} + self.safety_factors = {} # calculated safety factor + self.safety_factors_required = {} # minimum allowable safety factor + + # anchor costs + self.cost = {} + + self.loads = {} + ''' + { + Hm: # horizontal maximum anchor loads at mudline [N] + Vm: # vertical maximum anchor loads at mudline [N] + thetam: # angle of load at the mudline [rad] + Ha: # horizontal maximum loads at lug + Va: # vertical maximum loads at lug + thetaa: # angle of load at lug + method: # dynamic or static method of calculation + } + ''' + self.soilProps = {} + self.failure_probability = {} + + # environmental impact + self.env_impact = {} + + + # self.cost = {} + + def setSoilProfile(self, profile_map): + ''' + Assign a soil profile directly from a single CPT. + Assumes profile_map is a list with only one entry. + ''' + if len(profile_map) != 1: + raise ValueError("setSoilProfile expects a profile_map with exactly one CPT.") + + cpt = profile_map[0] + self.soil_profile = cpt['layers'] + self.profile_name = cpt.get('name', 'CPT_Assigned') + + # Extract soil types from layers + soil_types = [layer['soil_type'] for layer in self.soil_profile] + self.soil_type_list = list(set(soil_types)) + self.soil_type = soil_types[0] if len(self.soil_type_list) == 1 else 'mixed' + + # Group layers by soil type + soilProps = defaultdict(list) + for layer in self.soil_profile: + layer_copy = layer.copy() + soil_type = layer_copy.pop('soil_type') + soilProps[soil_type].append(layer_copy) + self.soilProps = dict(soilProps) + + print(f"[Anchor] Assigned soil profile from {self.profile_name} with soil types {self.soil_type_list}") + + + def makeMoorPyAnchor(self, ms): + '''Create a MoorPy anchor object in a moorpy system + Parameters + ---------- + ms : class instance + MoorPy system + + Returns + ------- + ms : class instance + MoorPy system + + ''' + # create anchor as a fixed point in MoorPy system + ms.addPoint(1,self.r) + # assign this point as mpAnchor in the anchor class instance + self.mpAnchor = ms.pointList[-1] + + # add mass if available + if 'm' in self.dd['design'] and self.dd['design']['m']: + self.mpAnchor.m = self.dd['design']['m'] + # set anchor diameter + if 'd' in self.dd['design'] and self.dd['design']['d']: + self.mpAnchor.d = self.dd['design']['d'] + # set the point as an anchor entity + self.mpAnchor.entity= {'type': 'anchor'} + if 'type' in self.dd: + self.mpAnchor.entity['anchor_type']=self.dd['type'] + + return(ms) + + + def getAnchorCapacity(self,ground_cons=None,installAdj=1,profile=None,loads=None,plot=True): + ''' + Calls anchor capacity functions developed by Felipe Moreno for the correct anchor type + + Parameters + ---------- + ground_conds : dict, optional + Ground conditions dictionary with the key as the soil type name, values as soil info such as UCS,Em,phi,gamma,effective stress,etc. The default is None. + If no dict provided, the ground conds will be pulled from the anchor soilProps property + installAdj : float, optional + Adjustment to the capacity based on installation (dummy variable for now, but future installation functions + will dictate this value) + profile : 2D array, optional + 2d array of depths (m) and corresponding undrained shear strength (Pa). Su must not be zero + (change to small value such as .001), but z must always start at 0. Ex: array([z1,Su1],[z2,Su2],...) + Used only for driven pile and drilled and grouted pile anchors. + loads : dict, optional + Dictionary of loads on the anchor at the lug point in [N]. If not provided, will use the loads dictionary property + of the anchor. If this is empty and it is needed for the capacity function (i.e. driven piles) then + the anchor.getLugForces() function will be called. + + Returns + ------- + results : dict + Dictionary of capacity of the anchor (generally a max force [N] in H and V, but can be a max displacement (driven, dandg piles)) + + ''' + # - - - - set details - - - - + anchType = self.dd['type'] + geom = self.dd['design']# geometric anchor information + + if not ground_cons: + soil = next(iter(self.soilProps.keys()), None) # soil type + ground_conds = self.soilProps[soil] + else: + soil = next(iter(ground_cons.keys())) + ground_conds = ground_cons[soil] + + for key,prop in ground_conds.items(): + if isinstance(prop,list) or isinstance(prop,np.ndarray): + if len(prop)>1: + print('Warning: Only homogeneous soils are supported at this time. Only the first item in a property list will be used.') + break + else: + ground_conds[key] = prop[0] + + + if loads: + # find out if mudline loads or anchor loads + if not 'Ha' in loads: + # get loads at lug + loads = self.getLugForces(mudloads=loads,plot=plot) + else: + loads = self.loads + + + + # logic to determine what functions to call based on anchor type and soil type... + + # - - - - plate anchors - - - - + if anchType == 'SEPLA' or anchType == 'DEA' or anchType == 'DEPLA' or anchType == 'VLA' or anchType == 'plate': + from .anchors_famodel.capacity_plate import getCapacityPlate + if 'clay' in soil or 'mud' in soil: + # write or overwrite beta in geom dictionary from loads function + if anchType != 'DEA': + if not 'beta' in geom: + if not 'thetaa' in loads: + # calculate thetaa from Ha and Va + loads['thetaa'] = np.arctan2(loads['Va'],loads['Ha']) + # loads = self.getLugForces(plot=plot) + geom['beta'] = 90 - loads['thetaa'] + else: + geom['beta'] = 0 + if 'Su0' in ground_conds and 'k' in ground_conds and 'gamma' in ground_conds: + results = getCapacityPlate(geom['A'], geom['beta'], geom['zlug'], 'clay', ground_conds['gamma'], + Su0=ground_conds['Su0'], k=ground_conds['k']) + else: + raise Exception('Ground conditions dictionary needs Su0, k, gamma information for clay plate anchors') + else: + print(f'Warning: Soil type {soil} is not compatible with plate anchors (SEPLA/DEPLA/DEA/VLA)') + + # - - - - suction buckets - - - - + elif 'suction' in anchType: + from .anchors_famodel.capacity_suction import getCapacitySuction + # check loads have been calculated (needed for capacity function in this case) + if not 'Ha' in loads: + # call getMPForces function + loads = self.getLugForces(plot=plot) + if 'sand' in soil: + if 'phi' in ground_conds and 'Dr' in ground_conds: + results = getCapacitySuction(geom['D'], geom['L'], geom['zlug'], + loads['Ha']/1000, loads['Va']/1000, + 'sand', ground_conds['gamma'], + phi=ground_conds['phi'], + Dr=ground_conds['Dr'], plot=plot) + else: + raise Exception('Ground conditions dictionary needs phi and relative density information for sand suction pile anchor') + elif 'clay' in soil or 'mud' in soil: + if 'Su0' in ground_conds and 'k' in ground_conds and 'alpha' in ground_conds:# and 'gamma_sub' in ground_conds: + results = getCapacitySuction(geom['D'],geom['L'], geom['zlug'], + loads['Ha']/1000, loads['Va']/1000, + 'clay', ground_conds['gamma'], + Su0=ground_conds['Su0'], + k=ground_conds['k'], plot=plot) + results['Horizontal max.'] = results['Horizontal max.'] + results['Vertical max.'] = results['Vertical max.'] + + else: + raise Exception('Ground conditions dictionary needs Su0, k, and alpha information for clay suction pile anchor') + else: + print(f'Warning: Soil type {soil} is not compatible with suction pile anchor') + + # - - - - helical piles - - - - + elif 'helical' in anchType: + from .anchors_famodel.capacity_helical import getCapacityHelical + if 'sand' in soil: + if 'phi' in ground_conds and 'gamma' in ground_conds: + results = getCapacityHelical(geom['D'], geom['L'], geom['d'], + geom['zlug'], 'sand', + ground_conds['gamma'], + phi=ground_conds['phi'], + Dr=ground_conds['Dr']) + results['Vertical max.'] = results['Capacity'] + else: + raise Exception('Ground conditions dictionary needs phi, gamma and relative density information for clay helical pile anchor') + elif 'clay' in soil or 'mud' in soil: + if not 'alpha_star' in ground_conds: + ground_conds['alpha_star'] = ground_conds['alpha'] + if 'Su0' in ground_conds and 'k' in ground_conds and 'gamma' in ground_conds: + results = getCapacityHelical(geom['D'], geom['L'], geom['d'], + geom['zlug'], 'clay', + ground_conds['gamma'], + Su0=ground_conds['Su0'], + k=ground_conds['k']) + results['Vertical max.'] = results['Capacity'] + else: + raise Exception('Ground conditions dictionary needs Su0, k, gamma, and alpha_star information for clay helical pile anchor') + else: + print(f'Warning: Soil type {soil} is not compatible with helical pile anchor') + + # - - - - torpedo piles - - - - + elif 'torpedo' in anchType: + from .anchors_famodel.capacity_torpedo import getCapacityTorpedo + if 'clay' in soil or 'mud' in soil: + if 'Su0' in ground_conds and 'k' in ground_conds and 'alpha' in ground_conds: + results = getCapacityTorpedo(geom['D1'], geom['D2'], + geom['L1'], geom['L2'], + geom['zlug'], 'clay', + ground_conds['Su0'], + ground_conds['k'], + ground_conds['alpha']) + results['Horizontal max.'] = results['Horizontal max.'] + results['Vertical max.'] = results['Vertical max.'] + else: + raise Exception('Ground conditions dictionary needs Su0, k, and alpha information') + else: + print('Warning: Soil type {soil} is not compatible with torpedo pile anchor') + + # - - - - driven piles - - - - + elif 'driven' in anchType: # driven pile anchor + # check loads have been calculated (needed for capacity function in this case) + if not 'Ha' in loads: + # call getLugForces function + loads = self.getLugForces(plot=plot) + H_inc = loads['Ha']*0.1 # increment H by 10% of Ha load in the while loops to back-calc max H from displacements + H = 0 + # check soil + if 'weak_rock' in soil: + from .anchors_famodel.capacity_drivenrock import getCapacityDrivenRock + + if not profile: + if 'UCS' in ground_conds and 'Em' in ground_conds: + profile = [[0,ground_conds['UCS'],ground_conds['Em']], + [75,ground_conds['UCS'],ground_conds['Em']]] #profile = [list(x) for x in list(zip(ground_conds['depth'],ground_conds['UCS'],ground_conds['Em']))] + else: + raise Exception('Ground conditions dictionary needs UCS, Em, and depth information for weak rock driven pile anchor') + + y, z, results = getCapacityDrivenRock(profile, geom['L'], geom['D'], + geom['zlug'], loads['Va'], + loads['Ha'], plot=plot) + + # loop through, calling capacity with larger H values until a displacement value goes above limit + while results['Lateral displacement']< 0.05*geom['D'] and results['Rotational displacement'] < 0.25: + # increment H + H += H_inc + # call capacity function + y, z, results = getCapacityDrivenRock(profile, geom['L'], + geom['D'], geom['zlug'], + loads['Va'], H=H, plot=plot) + + + elif 'sand' in soil: + from .anchors_famodel.capacity_drivensoil import getCapacityDrivenSoil + if profile or ('gamma' in ground_conds and 'Dr' in ground_conds and 'phi' in ground_conds): + if not profile: + profile = [[0,ground_conds['phi'],ground_conds['gamma'],ground_conds['Dr']], + [75,ground_conds['phi'],ground_conds['gamma'],ground_conds['Dr']]] #profile = [list(x) for x in list(zip(ground_conds['depth'],ground_conds['phi'],ground_conds['gamma']))] + + y, z, results = getCapacityDrivenSoil(profile, 'sand', + geom['L'], geom['D'], + geom['zlug'], loads['Va'], + loads['Ha'], plot=plot) + if geom['zlug'] > 0: + # need to check bending moment if lug is below mudline (+ zlug) + # loop through, calling capacity with larger H values until a displacement value goes above limit + while results['Lateral displacement']<= 0.05*geom['D'] and results['Bending moment'] <= results['Plastic moment']: + # increment H by 10% of load + H += H_inc + # call capacity function + y, z, results = getCapacityDrivenSoil(profile,'clay', + geom['L'], geom['D'], + geom['zlug'], loads['Va'], + H=H, plot=plot) + + else: + while results['Lateral displacement']<= 0.05*geom['D'] and results['Rotational displacement'] <= 0.25: + # increment H by 10% of load + H += H_inc + # call capacity function + y, z, results = getCapacityDrivenSoil(profile, 'clay', + geom['L'], geom['D'], + geom['zlug'], loads['Va'], + H=H, plot=plot) + else: + raise Exception('Ground conditions dictionary needs phi, gamma, and depth information for sand driven pile anchor') + elif 'clay' in soil or 'mud' in soil: + from .anchors_famodel.capacity_drivensoil import getCapacityDrivenSoil + #if profile or ('Su' in ground_conds and 'gamma' in ground_conds and 'depth' in ground_conds) or ('Su0' in ground_conds and 'k' in ground_conds): + if not profile: + if 'Su' in ground_conds and 'depth' in ground_conds and 'gamma' in ground_conds: + profile = [list(x) for x in list(zip(ground_conds['depth'],ground_conds['Su'],ground_conds['gamma']))] + elif 'Su0' in ground_conds and 'k' in ground_conds and 'gamma' in ground_conds: + Su = ground_conds['Su0']+ground_conds['k']*75 + profile = [[0,ground_conds['Su0'],ground_conds['gamma']],[75,Su,ground_conds['gamma']]] + else: + raise Exception('Ground conditions dictionary needs information for clay driven pile anchor') + + y, z, results = getCapacityDrivenSoil(profile,'clay',geom['L'],geom['D'],geom['zlug'],loads['Va'],loads['Ha'], plot=plot) + + if geom['zlug'] > 0: + # need to check bending moment if lug is below mudline (+ zlug) + # loop through, calling capacity with larger H values until a displacement value goes above limit + while results['Lateral displacement']<= 0.05*geom['D'] and results['Bending moment'] <= results['Plastic moment']: + # increment H by 10% of load + H += H_inc + # call capacity function + y, z, results = getCapacityDrivenSoil(profile,'clay',geom['L'],geom['D'],geom['zlug'],loads['Va'], H=H, plot=plot) + + else: + while results['Lateral displacement']<= 0.05*geom['D'] and results['Rotational displacement'] <= 0.25: + # increment H by 10% of load + H += H_inc + # call capacity function + y, z, results = getCapacityDrivenSoil(profile,'clay',geom['L'],geom['D'],geom['zlug'],loads['Va'], H=H, plot=plot) + + + else: + print(f'Warning: Soil type {soil} is not compatible with driven pile anchors') + + # - - - - drilled and grouted piles - - - - + elif 'dandg' in anchType: # drill and grout pile + from .anchors_famodel.capacity_dandg import getCapacityDandG + # check for correct soil + if 'rock' in soil: + # check loads have been calculated (needed for capacity function in this case) + if not 'Ha' in loads: + # call getMPForces function + loads = self.getLugForces(plot=plot) + # check for correct ground properties + if profile or ('UCS' in ground_conds and 'Em' in ground_conds): + if not profile: + profile = [[0,ground_conds['UCS'],ground_conds['Em']],[75,ground_conds['UCS'],ground_conds['Em']]] #[list(x) for x in list(zip(ground_conds['depth'],ground_conds['UCS'],ground_conds['Em']))] + + # call capacity function once to get displacement values + y, z, results = getCapacityDandG(profile,geom['L'],geom['D'], + geom['zlug'], loads['Va'], + loads['Ha'], plot=plot) + H_inc = loads['Ha']*0.1 # increment H by 10% of Ha load + H = H_inc # start H at 10% of Ha load + # loop through, calling capacity with larger H values until a displacement value goes above limit + while results['Lateral displacement']< 0.05*geom['D'] and results['Rotational displacement'] < 0.25: + # call capacity function + y, z, results = getCapacityDandG(profile, geom['L'], geom['D'], + geom['zlug'], loads['Va'], + H=H, plot=plot) + # increment H + H += H_inc + else: + raise Exception('Ground conditions dictionary need UCS and Em information for drill and grout pile') + else: + print(f'Warning: soil type {soil} is not compatible with drill and grout pile') + + # - - - - anchor type not recognized or supported - - - - + else: + raise Exception(f'Anchor type {anchType} is not supported at this time') + + # - - - - save relevant results in dictionary using common terms - - - - + # capacity = cap*installAdj ??? OR is installAdj an input to the capacity functions? + # save capacity + if 'dandg' in anchType or 'driven' in anchType: # will take in dandg, dandg_pile, driven, driven_pile + self.anchorCapacity['Lat_max'] = results['Lateral displacement'] # [deg] + if 'Rotational displacement' in results: + self.anchorCapacity['Rot_max'] = results['Rotational displacement'] # [deg] + elif 'Bending moment' in results: + self.anchorCapacity['Mbend_max'] = results['Bending moment'] + self.anchorCapacity['Va_max'] = results['Axial capacity'] # [N] + self.anchorCapacity['Ha_max'] = H + + else: + if 'Horizontal max.' in results: + self.anchorCapacity['Ha_max'] = results['Horizontal max.']*1000 # [N] + self.anchorCapacity['Va_max'] = results['Vertical max.']*1000 # [N] + self.mass = results['Weight']*1000/self.g # mass in [kg] + + # add on extra for drag-embedment anchors (flukes) + if 'DEA' in anchType: + self.mass *= 1.75 + + + return(results) + + def getMudlineForces(self, max_force=False,lines_only=False, seabed=True, xyz=False,project=None): + '''Find forces on anchor at mudline using the platform.getWatchCircle method or MoorPy Point.getForces method. + Optionally, get forces at anchor lug location with getTransferLoad function in capacity_loads.py. + Stores in loads dictionary + Parameters + ---------- + max_force : boolean, optional + Find and save the maximum force on the anchor (True) or just get force at the current MoorPy system state (False) + lines_only : boolean, optional + Calculate forces from just mooring lines (True) or not (False). Default is false + seabed : boolean, optional + Include effect of seabed pushing up the anchor (True) or not (False). Default is true + xyz : boolean, optional + Return forces in x,y,z DOFs (True) or only the enabled DOFs (False). Default is false + + ''' + Platform = famodel.platform.platform.Platform + if max_force: + if project: + # get watch circle of platform(s) + project.arrayWatchCircle() + else: + # find platform associated with this anchor + for att in self.attachments.values(): + if isinstance(att['obj'],Mooring): + for attM in att['obj'].attached_to: + if isinstance(attM,Platform): + locx,locy,maxVals = attM.getWatchCircle() + # call getForces method from moorpy point object + else: + loads = self.mpAnchor.getForces(lines_only=lines_only, seabed=seabed, xyz=xyz) + self.loads['Hm'] = np.sqrt(loads[0]**2+loads[1]**2) # mudline forces in [N] + self.loads['Vm'] = loads[2] # [N] + self.loads['thetam'] = np.degrees(np.arctan(self.loads['Vm']/self.loads['Hm'])) # [deg] + self.loads['mudline_load_type'] = 'current_state' + + # loads determined from moorpy are static + self.loads['method'] = 'static' + + return(self.loads) + + def getLugForces(self, mudloads=None, max_force=True, plot=False): + ''' + Find forces on an anchor at the lug point based on the mudline forces and angles. Calls getTransferFunction script + + Parameters + ---------- + mudloads : dict, optional + Dictionary of max mudline forces. The default is None. + + Returns + ------- + loads: dict + Dictionary of loads at the lug point [N] + + ''' + from .anchors_famodel.capacity_load import getTransferLoad + + nolugload = False + + if not mudloads: + if not self.loads: + # get max mudline forces first + self.getMudlineForces(max_force=max_force) + elif not 'mudline_load_type' in self.loads: + raise KeyError("Loads dictionary must specify 'mudline_load_type'='current_state' or 'mudline_load_type'='max', where 'max' indicates the loads are maximum loads.") + elif max_force and self.loads['mudline_load_type'] != 'max': + # need max forces, not current state + self.getMudlineForces(max_force=True) + mudloads = self.loads + else: + # check syntax + if not 'Hm' in mudloads or not 'Vm' in mudloads: + raise KeyError('Mudline load dictionary must have Hm and Vm for horizontal load and vertical load (in [N]) at the mudline') + if not 'thetam' in mudloads: + mudloads['thetam'] = np.degrees(np.arctan(mudloads['Vm']/mudloads['Hm'])) + + def makeEqual_TaTm(mudloads): + mudloads['Ha'] = mudloads['Hm'] # [N] + mudloads['Va'] = mudloads['Vm'] # [N] + mudloads['thetaa'] = mudloads['thetam'] # [deg] + + if 'zlug' in self.dd['design']: + if self.dd['design']['zlug'] > 0: + # get line type + for att in self.attachments.values(): + if isinstance(att['obj'],Mooring): + mtype = att['obj'].dd['sections'][0]['type']['material'] + if not 'chain' in mtype: + print('No chain on seafloor, setting Ta=Tm') + nolugload = True + break + else: + md = att['obj'].dd['sections'][0]['type']['d_nom'] + mw = att['obj'].dd['sections'][0]['type']['w'] + soil = next(iter(self.soilProps.keys()), None) + ground_conds = self.soilProps[soil] + # update soil conds as needed to be homogeneous + for key,prop in ground_conds.items(): + if isinstance(prop,list) or isinstance(prop,np.ndarray): + if len(prop)>1: + print('Warning: Only homogeneous soils are supported at this time. Only the first item in a property list will be used.') + break + else: + ground_conds[key] = prop[0] + + Tm = np.sqrt(mudloads['Hm']**2+mudloads['Vm']**2) # [N] + if 'clay' in soil or 'mud' in soil and not nolugload: + # Tm, thetam, zlug, line_type, d, soil_type, Su0=None, k=None, w=None + try: + loadresults = getTransferLoad(Tm/1000,mudloads['thetam'], + self.dd['design']['zlug'],mtype,md, + 'clay',Su0=ground_conds['Su0'], + k=ground_conds['k'],w=mw/1000, + plot=plot) # output Ha and Va (convert weight to kN/m) + except Exception as e: + print(e) + print('Unable to get loads at anchor lug location. Setting Ta = Tm') + nolugload = True + elif 'sand' in soil and not nolugload: + soil = 'sand' + try: + loadresults = getTransferLoad(Tm/1000, self.loads['thetam'], + self.dd['design']['zlug'], + mtype, md, soil, + gamma=ground_conds['gamma'], + phi=ground_conds['phi'], + delta=ground_conds['delta'], + w=mw/1000,plot=plot) # output Ha and Va (convert weight to kN/m) + except Exception as e: + print(e) + print('Unable to get loads at anchor lug location. Setting Ta = Tm') + nolugload = True + elif 'rock' in soil and not nolugload: + raise ValueError('zlug should be <= 0 for rock.') + + # if loadresults['V']<0: + # # results are invalid + # print('Warning: invalid results for the combination of anchor ',self.dd['type'],' soil ',soil,' and loads ',mudloads,'. Setting Ha=Hm, Va=Vm, thetaa=thetam') + # makeEqual_TaTm(mudloads) + if nolugload: + makeEqual_TaTm(mudloads) + else: + mudloads['Ha'] = loadresults['H']*1000 # [N] + mudloads['Va'] = loadresults['V']*1000 # [N] + mudloads['thetaa'] = loadresults['angle'] # [deg] + else: + # Ha = Hm because zlug is at mudline or above + makeEqual_TaTm(mudloads) + else: + print('No zlug given, assuming loads at mudline = loads at anchor lug') + makeEqual_TaTm(mudloads) + + if not 'method' in mudloads: + # assume mudloads are static unless told otherwise + # loads determined from moorpy are static + mudloads['method'] = 'static' + else: + mudloads['method'] = mudloads['method'] + + return mudloads + + def getFS(self, loads=None, acceptance_crit=None): + ''' + Compute safety factor for loads on the anchor + + Parameters + ---------- + loads : dict, optional + Dictionary of loads on the anchor. + acceptance_crit : dict, optional + Dictionary of acceptable factors of safety for each load type. + Key is the load type, and value is the minimum acceptable safety factor. + Default is None (in which case no comparison between FS and acceptance criteria is calculated) + + Returns + ------- + FS : dict + Dictionary of safety factors (often horizontal and vertical load SFs, but could be displacement SFs (drilled and grouted/driven piles)) + acceptance : dict + Dictionary of bools that state whether the FS>=acceptance_crit for each load + acceptance_margin : dict + Dictionary of difference between FS and acceptance criteria for each load type + + + ''' + if not loads: + if not 'Ha' in self.loads: + self.getLugForces() + loads = self.loads + if not self.anchorCapacity: + self.getAnchorCapacity() + + # look for load dictionary key in capacity dictionary + FS = {} + acceptance = {} + acceptance_margin = {} + for Lkey,Lval in loads.items(): + for Ckey,Cval in self.anchorCapacity.items(): + if Lkey in Ckey: + if Lval == 0: + FS[Lkey] = float('inf') + else: + FS[Lkey] = Cval/Lval + if acceptance_crit and Lkey in acceptance_crit: + if Lval == 0 or acceptance_crit[Lkey] == 0: + acceptance[Lkey] = True + else: + acceptance[Lkey] = acceptance_crit[Lkey]<=FS[Lkey] + acceptance_margin[Lkey] = FS[Lkey] - acceptance_crit[Lkey] + + if acceptance_crit: + return(FS,acceptance,acceptance_margin) + else: + return(FS) + + def makeBuffer(self, buff_rad=50): + point = sh.Point(self.r[:2]) + buff = point.buffer(buff_rad) + return buff + + def getCost(self,costDict='default'): + '''find costs of anchor and store in design dictionary + + Parameters + ---------- + costDict : dictionary or yaml, optional + Dictionary of various costs for anchors. Sub costs that can be included are: + material : material costs + + ''' + if isinstance(costDict,str) and costDict != 'default': + import yaml + costDict = yaml.load(costDict, Loader=yaml.FullLoader) + anchType = self.dd['type'] + if costDict == 'default': + matCostDict = {'DEA':5.705,'suction_pile':4.435,'gravity':1.905} # mean values from Task 49 Design Basis ranges + instCostDict = {} + decomCostDict = {} + else: + matCostDict = costDict['material'] + if 'install' in costDict: + instCostDict = costDict['install'] + if 'decom' in costDict: + decomCostDict = costDict['decom'] + keyFail = True + # check if mass info is available + if not self.mass: + if 'soil_properties' in self.dd: + # need mass - call capacity functions + self.getAnchorCapacity(plot=False) + else: + print('Soil properties needed to calculate anchor mass for cost. Setting cost to 0.') + self.mass = 0 + + # sort by type of anchor + for Ckey,Cval in matCostDict.items(): + if anchType in Ckey: + self.cost['materials'] = matCostDict[Ckey]*self.mass + # self.cost['install'] = instCostDict[Ckey] + # self.cost['decom'] = decomCostDict[Ckey] + keyFail = False + # raise error if anchType not found in cost dictionary + if keyFail: + raise KeyError(f'anchor type {anchType} not found in material cost dictionary') + + return(sum(self.cost.values())) + + + + # def getSuctionSize(self,D,L,loads=None,minfs={'Ha':1.6,'Va':2},LD_con=[4,8]): + # ''' + + + # Parameters + # ---------- + # D : float + # Diameter of suction bucket + # L : float + # Length of suction bucket + # loads : dict, optional + # Dictionary of maximum anchor loads in horizontal and vertical directions. The default is None. + # minfs : dict,optoinal + # Minimum factors of safety in horizontal and vertical directions + # LD_con : float + # Constraint for L/D parameter + + # Returns + # ------- + # None. + + # ''' + # from scipy.optimize import minimize + # anchType = self.dd['type'] + # if not loads: + # loads = self.loads + + # if not 'Ha' in loads: + # loads = self.getLugForces(mudloads=loads) + + # loads['Ha'] = minfs['Ha']*loads['Ha'] + # loads['Va'] = minfs['Va']*loads['Va'] + + # if not 'zlug' in self.dd['design']: + # self.dd['design']['zlug'] = (2/3)*L + + # # Define the objective function: Minimize |UC - 1| (aim for UC to be 1) + # def objective(vars): + # D, L = vars + # self.dd['design']['D'] = D + # self.dd['design']['L'] = L + # self.dd['design']['zlug'] = (2/3)*L + # results = self.getAnchorCapacity(plot=False) + # return abs(results['UC'] - 1) + + # def conFun(vars,LD_con): + # D, L = vars + # if L/D >= LD_con[0] and L/D <= LD_con[1]: + # conval = 1 + # else: + # conval = -1 + + # return(conval) + + # # Initial guess for D and L + # initial_guess = [D, L] # Input values for D and L + + # # Bounds for D and L (adjust as needed) + # bounds = [(1, 5), (5, 50)] # Bounds for D and L + + # # constraints + # constraints = [{'type':'ineq','fun':conFun,'args':(LD_con,)}] + + # # Run the optimization to find D and L that satisfy UC close to 1 + # solution = minimize(objective, initial_guess, bounds=bounds,method="COBYLA", + # constraints=constraints,options={'rhobeg':0.1, 'catol':0.001}) + + # # Extract the optimized values of D and L + # self.dd['design']['D'], self.dd['design']['L'] = solution.x + # self.dd['design']['zlug'] = (2/3)*self.dd['design']['L'] + # results = self.getAnchorCapacity(plot=False) + + + def getSize(self, geom, geomKeys, geomBounds=None, loads=None, minfs={'Ha':1.6,'Va':2}, + LD_con=[4,8], fix_zlug=False, FSdiff_max=None, plot=False): + ''' + + + Parameters + ---------- + geom: list + starting guess geometry values + geomKeys : list + List of keys that match the geom list values i.e. 'L','D','zlug' + geomBounds : list,optional + List of upper and lower bounds for each geometry value. + Each entry should be a tuple of upper and lower bounds for each geometry i.e. [(5,10),(10,20)] + loads : dict, optional + Dictionary of maximum anchor loads in horizontal and vertical directions (not including factor of safety). The default is None. + minfs : dict,optional + Minimum factors of safety in horizontal and vertical directions + LD_con : float + Constraint for L/D parameter + fix_zlug : bool + Boolean to decide if zlug should be altered as geometric values are altered. + True = fixed zlug, False = zlug may be changed + plot : bool + Boolean controls if capacity plots are generated or not for the final configuration + + Returns + ------- + None. + + ''' + # - - - - Objective and Constraint Functions + + # Define the objective function: Minimize weight of anchor (cost is dependent on weight) + def objective(vars, args): + + geomKeys = args['geomKeys'] + input_loads = args['input_loads'] + fix_zlug = args['fix_zlug'] + + newGeom = dict(zip(geomKeys,vars)) + self.dd['design'].update(newGeom) + if 'suction' in self.dd['type'] and not fix_zlug: + self.dd['design']['zlug'] = (2/3)*newGeom['L'] + + if 'Hm' in input_loads or 'Vm' in input_loads: + anchor_loads = self.getLugForces(mudloads=input_loads) + input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary + # get results + results = self.getAnchorCapacity(loads=input_loads, plot=False) + + return(results['Weight']) + + # constraint for suction bucket sizing only. May add more constraints for other anchors in the future... + def conFun_LD(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): + newGeom = dict(zip(geomKeys, vars)) + self.dd['design'].update(newGeom) + + if 'Hm' in input_loads or 'Vm' in input_loads: + anchor_loads = self.getLugForces(mudloads=input_loads) + input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary + + results = self.getAnchorCapacity(loads=input_loads, plot=False) + + convalA = newGeom['L']/newGeom['D'] - LD_con[0] + convalB = LD_con[1] - newGeom['L']/newGeom['D'] + conval = min([convalA,convalB]) + # if newGeom['L']/newGeom['D'] >= LD_con[0] and newGeom['L']/newGeom['D'] <= LD_con[1]: + # conval = 1 + # else: + # conval = -1 + + return(conval) + # constraint to ensure unity check > 1 for suction buckets + def conFun_Suction(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): + if 'Hm' in input_loads or 'Vm' in input_loads: + anchor_loads = self.getLugForces(mudloads=input_loads) + input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary + results = self.getAnchorCapacity(loads=input_loads, plot=False) + #conval = results['UC'] - 1 + conval = 1 - results['UC'] + # convalB = 1 - results['UC'] + return(conval) + + def conFun_DandG(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): + + newGeom = dict(zip(geomKeys, vars)) + self.dd['design'].update(newGeom) + if 'Hm' in input_loads or 'Vm' in input_loads: + anchor_loads = self.getLugForces(mudloads=input_loads) + input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary + results = self.getAnchorCapacity(loads=input_loads, plot=False) + + return np.array([0.05*newGeom['D'] - results['Lateral displacement'] , 0.25 - results['Rotational displacement']]) + + def conFunH(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): + # if 'suction' in self.dd['type']: + # results = self.getAnchorCapacity(plot=False) + # conval = results['UC'] - 1 + # # if results['UC'] < 1: + # # conval = -1*(results['UC']) + # else: + if 'Hm' in input_loads or 'Vm' in input_loads: + anchor_loads = self.getLugForces(mudloads=input_loads) + input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary + minfs = dict(Ha=minfs['Hm'], Va=minfs['Vm']) + FS, _, _ = self.getFS(loads=input_loads, acceptance_crit=minfs) + conval = FS['Ha'] - 1 + # for key,val in FS.items(): + + # if val/minfs[key]<1: + # if -1*(1-val/minfs[key]) < conval: + # conval = -1*(1-val/minfs[key]) + return(conval) + + def conFunV(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): + if 'Hm' in input_loads or 'Vm' in input_loads: + anchor_loads = self.getLugForces(mudloads=input_loads) + input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary + minfs = dict(Ha=minfs['Hm'], Va=minfs['Vm']) + FS, _, _ = self.getFS(loads=input_loads, acceptance_crit=minfs) + # special case for DEAs + if minfs['Va'] == 0: + conval = 1 + else: + conval = FS['Va'] - 1 + + # print('FS_V',FS['Va']) + return(conval) + + def conBounds(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs): + + newGeom = dict(zip(geomKeys, vars)) + self.dd['design'].update(newGeom) + + if 'Hm' in input_loads or 'Vm' in input_loads: + anchor_loads = self.getLugForces(mudloads=input_loads) + input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary + results = self.getAnchorCapacity(loads=input_loads, plot=False) + + bound_L_lower = newGeom['L'] - geomBounds[0][0] + bound_L_upper = geomBounds[0][1] - newGeom['L'] + bound_D_lower = newGeom['D'] - geomBounds[1][0] + bound_D_upper = geomBounds[1][1] - newGeom['D'] + + return np.array([bound_L_lower, bound_L_upper, bound_D_lower, bound_D_upper]) + + # - - - - - Setup & Optimization + from scipy.optimize import minimize + from copy import deepcopy + + anchType = self.dd['type'] + + # loads['Ha'] = minfs['Ha']*loads['Ha'] + # loads['Va'] = minfs['Va']*loads['Va'] + startGeom = dict(zip(geomKeys,geom)) + print('start geometry: ',startGeom) + # apply initial guess geometry + self.dd['design'].update(startGeom) + + if not 'zlug' in self.dd['design']: + if 'suction' in anchType and not fix_zlug: + self.dd['design']['zlug'] = (2/3)*startGeom['L'] + else: + self.dd['design']['zlug'] = 0 + + # if zlug is fixed, remove it from design variables + if fix_zlug and 'zlug' in geomKeys: + zlug_loc = geomKeys.index('zlug') + startGeom.pop('zlug') + geomKeys.remove('zlug') + geom.pop(zlug_loc) + if geomBounds: + geomBounds.pop(zlug_loc) + + if not loads: + loads = self.loads + + if not 'Ha' in loads: + loads = self.getLugForces(mudloads=loads) + + # suction bucket needs to be loads*FS because of capacity envelope calculations in capacity function + if ('Hm' in loads and 'Vm' in loads) and ('Hm' in minfs and 'Vm' in minfs): + input_loads = {'Hm':loads['Hm']*minfs['Hm'], 'Vm':loads['Vm']*minfs['Vm']} + else: + input_loads = {'Ha':loads['Ha']*minfs['Ha'],'Va':loads['Va']*minfs['Va']} + + + + + # Initial guess for geometry + initial_guess = geom # [val for val in startGeom.values()] # Input values for geometry + # geomKeys = [key for key in startGeom.keys()] + + # Bounds and constraints + if 'suction' in anchType: + # bounds = [(1, 7), (5, 50),()] # Bounds for D and L + # constraints + + constraints = [{'type':'ineq','fun':conFun_LD,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, + {'type':'ineq','fun':conFun_Suction,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, + {'type':'ineq','fun':conFunH,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, + {'type':'ineq','fun':conFunV,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, + {'type':'ineq','fun':conBounds,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}] + + elif 'dandg' in anchType: + constraints = [{'type':'ineq','fun':conFun_LD,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, + {'type':'ineq','fun':conFun_DandG,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, + {'type':'ineq','fun':conFunH,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, + {'type':'ineq','fun':conFunV,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, + {'type':'ineq','fun':conBounds,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}] + + else: + constraints = [{'type':'ineq','fun':conFunH,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}, + {'type':'ineq','fun':conFunV,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}] + + # Run the optimization to find sizing that satisfy UC close to 1 + print('optimizing anchor size') + + if 'suction' in anchType or 'dandg' in anchType: + solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs), + method="COBYLA", constraints=constraints, options={'rhobeg':0.1, 'catol':0.001}) + else: + solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs), + method="COBYLA", constraints=constraints, options={'rhobeg':0.1, 'catol':0.001}) + + FS, acceptance, FSdiff = self.getFS(loads=input_loads, acceptance_crit=minfs) + + # adjust starting value if you're far off from the acceptance criteria (in either direction) + if FSdiff_max: + count = 0 + while count<10 and (np.any([abs(FSdiff[key])>FSdiff_max[key] for key in FSdiff.keys()]) or np.any([diff<0 for diff in FSdiff.values()])): + if np.any([diff<.02 for key,diff in FSdiff.items() if minfs[key]>0]) and np.all([diff>=0 for diff in FSdiff.values()]): + # exit loop if you're as close as can be on one of the FS even if other is above diff requirements UNLESS an FS is below minimum reqiured FS + break + print('Factor of Safety not close enough to minimum factor of safety, trying again with adjusted initial guess.') + print(FS) + # calculate new percent difference of FS from min fs + diffPCT = [FSdiff[key]/FS[key] for key in FSdiff] + # create adjustment coefficient based on this or .25, whichever is lower + adjust_coeff = np.min([np.min(diffPCT),0.25]) + # adjust initial guess values by adjustment coefficient + for i,val in enumerate(initial_guess): + initial_guess[i] = val - val*adjust_coeff + # update zlug for suction buckets as needed to be 2/3L + if 'suction' in anchType and not fix_zlug: + zlug_loc = geomKeys.index('zlug') + L_loc = geomKeys.index('L') + initial_guess[zlug_loc] = (2/3)*initial_guess[L_loc] + + print('new initial guess',initial_guess) + # re-run optimization + if 'suction' in anchType or 'dandg' in anchType: + solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs), + method="COBYLA", constraints=constraints, options={'rhobeg':0.1, 'catol':0.001}) + else: + solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs), + method="COBYLA", constraints=constraints, options={'rhobeg':0.1, 'catol':0.001}) + # re-determine FS and diff from minFS + FS, acceptance, FSdiff = self.getFS(loads=input_loads, acceptance_crit=minfs) + count += 1 + + # Extract the optimized values of geometry + endGeom = dict(zip(geomKeys,solution.x)) + print('End geometry: ',endGeom) + self.dd['design'].update(endGeom) + if 'suction' in anchType and not fix_zlug: + self.dd['design']['zlug'] = (2/3)*self.dd['design']['L'] + results = self.getAnchorCapacity(loads=input_loads,plot=plot) + + # # check if anchor loads are available + # if not self.loads: + # # if not, check if theres a moorpy anchor object and calculate loads from that + # if self.mpAnchor: + # print("Need anchor loads to obtain cost, using getMPForces to determine loads in MoorPy") + # self.getLugForces() + # elif self.ms: + # print('Need anchor loads to obtain cost, creating a MoorPy anchor object and using getMPForces to determine loads in MoorPy') + # self.makeMoorPyAnchor(self.ms) + # self.getLugForces() + # else: + # raise Exception("Need anchor loads to obtain cost") + # # check again if there are loads + # if self.loads: + # c = self.dd['cost'] # set location for clarity + # # calculate individual costs and total cost for the anchor + # c['matCost'], c['instCost'], c['decomCost'] = mp.Point.getcost(self.mpAnchor) + # c['totCost'] = c['matCost'] + c['instCost'] + c['decomCost'] + + + # def getMass(self,uhc_mode): + # '''find mass and/or UHC of anchor from MoorProps and store in design dictionary + # Parameters + # ---------- + # uhc_mode : boolean + # True : obtain UHC from mass + # False : obtain Masss and UHC from loads + # ''' + # if uhc_mode: # if looking for UHC given mass + # if self.dd['design']['m']: # check anchor mass is given + # self.dd['design']['UHC'], self.dd['design']['m'], info = mp.MoorProps.getAnchorMass(uhc_mode=1, mass_int=self.dd['design']['m'], anchor=self.dd['type'], soil_type=self.anchorProps['soil_type']) + # else: + # raise Exception("Need anchor mass to calculate UHC when uhc_mode = 1") + # else: # if looking for mass and UHC given loads + # if self.loads: # check the loads section exists + # self.dd['design']['UHC'], self.dd['design']['m'], info = mp.MoorProps.getAnchorMass(uhc_mode=0, fx=self.loads['ff'], fz=self.loads['fz'], anchor=self.dd['type'],soil_type=self.dd['soil_type'],method=self.loads['method']) + # elif self.mpAnchor: + # print("Need anchor loads to obtain mass, using getMPForces to determine loads in MoorPy") + # self.getLugForces() + # self.dd['design']['UHC'], self.dd['design']['m'], info = mp.MoorProps.getAnchorMass(uhc_mode=0, fx=self.loads['ff'], fz=self.loads['fz'], anchor=self.dd['type'],soil_type=self.dd['soil_type'],method=self.loads['method']) + # elif self.ms: + # print('Need anchor loads to obtain mass, creating a MoorPy anchor object and using getMPForces to determine loads in MoorPy') + # self.makeMoorPyAnchor(self.ms) + # self.getLugForces() + # self.dd['design']['UHC'], self.dd['design']['m'], info = mp.MoorProps.getAnchorMass(uhc_mode=0, fx=self.loads['ff'], fz=self.loads['fz'], anchor=self.dd['type'],soil_type=self.dd['soil_type'],method=self.loads['method']) + # else: + # raise Exception("Need anchor loads to obtain mass") \ No newline at end of file diff --git a/famodel/anchors/anchor_map.py b/famodel/anchors/anchor_map.py deleted file mode 100644 index 525d569f..00000000 --- a/famodel/anchors/anchor_map.py +++ /dev/null @@ -1,889 +0,0 @@ -"""Anchor class for FAModel, containing information and key methods for anchors of mooring lines - Work in progress -""" -import moorpy as mp -import numpy as np -from scipy.optimize import minimize -from famodel.famodel_base import Node -from famodel.mooring.mooring import Mooring -import famodel.platform.platform -import matplotlib.pyplot as plt - -class Anchor(Node): - - def __init__(self, dd=None, ms=None, r=[0,0,0], aNum=None, id=None, - g=9.81, rho=1025, profile_map=None): - ''' - Initialize an Anchor object. - - Parameters - ---------- - dd : dict - Design dictionary containing all information on the anchor. - ms : MoorPy system object - MoorPy system instance. - r : list of float - Anchor position coordinates (x, y, z) (m) - aNum : int, optional - Index in anchor list. - id : str or int, optional - Unique anchor identifier. - g : float, optional - Gravity. - rho : float, optional - Water density. - profile_map : list of dict, optional - Full soil profile map for selecting local soil layers. - ''' - - from famodel.famodel_base import Node - Node.__init__(self, id) - - self.dd = dd - self.ms = ms - self.r = r - self.aNum = aNum - self.g = g - self.rho = rho - - self.anchType = dd.get('type') if dd else None - self.soil_type = None - self.soil_profile = None - self.profile_name = None - self.soil_type_list = [] - - self.mpAnchor = None - self.capacity_format = None - self.mass = dd.get('design', {}).get('mass', None) if dd else None - - self.anchorCapacity = {} - self.cost = {} - self.loads = {} - self.soilProps = {} - self.failure_probability = {} - self.env_impact = {} - - # --- Assign soil profile if map is provided --- - if profile_map is not None: - self.setSoilProfile(profile_map) - - def setSoilProfile(self, profile_map): - ''' - Assign a bilinearly interpolated soil profile from the 4 nearest CPTs. - - Parameters - ---------- - profile_map : list of dict - Each CPT must have keys: 'x', 'y', and 'layers' - - Returns - ------- - None - ''' - import numpy as np - - x_anchor, y_anchor = self.r[0], self.r[1] - - # Sort all CPTs by distance - distances = [np.hypot(p['x'] - x_anchor, p['y'] - y_anchor) for p in profile_map] - idx_sorted = np.argsort(distances) - CPTs = [profile_map[i] for i in idx_sorted[:4]] - - # Extract positions and weights (inverse distance squared) - x = np.array([cpt['x'] for cpt in CPTs]) - y = np.array([cpt['y'] for cpt in CPTs]) - dx = x - x_anchor - dy = y - y_anchor - d = np.hypot(dx, dy) - w = 1/np.maximum(d, 1e-3)**2 - w /= np.sum(w) - - # Interpolate layer-by-layer - layers_list = [cpt['layers'] for cpt in CPTs] - n_layers = len(layers_list[0]) - interpolated_layers = [] - - for i in range(n_layers): - layer = {'soil_type': layers_list[0][i]['soil_type']} - keys = layers_list[0][i].keys() - - for key in keys: - if key == 'soil_type': - continue - if all(key in l[i] for l in layers_list): - vals = [l[i][key] for l in layers_list] - layer[key] = np.dot(w, vals) - - interpolated_layers.append(layer) - - self.soil_profile = interpolated_layers - self.profile_name = f'Interpolated_2D' - - # Assign soil type - soil_types = [layer['soil_type'] for layer in self.soil_profile] - self.soil_type_list = list(set(soil_types)) - self.soil_type = soil_types[0] if len(self.soil_type_list) == 1 else 'mixed' - - print(f"[Anchor] Assigned interpolated soil profile: {self.profile_name} weighting with soil types {self.soil_type_list}") - - def makeMoorPyAnchor(self, ms): - ''' - Create a MoorPy anchor object in a MoorPy system. - - Parameters - ---------- - ms : MoorPy system instance - The MoorPy system to add the anchor to. - - Returns - ------- - ms : MoorPy system instance - The updated MoorPy system with the anchor added. - ''' - import moorpy as mp - - # Create anchor as a fixed point in MoorPy system - ms.addPoint(1, self.r) - - # Assign this point as mpAnchor in the anchor class instance - self.mpAnchor = ms.pointList[-1] - - # Set mass if available - if 'mass' in self.dd.get('design', {}): - self.mpAnchor.m = self.dd['design']['mass'] - - # Set diameter if available - if 'd' in self.dd.get('design', {}): - self.mpAnchor.d = self.dd['design']['d'] - - # Set the point as an anchor entity - self.mpAnchor.entity = {'type': 'anchor'} - if 'type' in self.dd: - self.mpAnchor.entity['anchor_type'] = self.dd['type'] - - return ms - - def getLineProperties(self): - ''' - Retrieve line_type, diameter and unit weight from attached mooring. - - Returns - ------- - line_type : str - Type of mooring line ('chain' or 'wire') - d : float - Nominal diameter (m) - w : float - Unit weight (N/m) - ''' - for att in self.attachments.values(): - if isinstance(att['obj'], Mooring): - mtype = att['obj'].dd['sections'][0]['type']['material'].lower() - if 'chain' not in mtype: - print('No chain below seafloor, setting Ta=Tm (no load transfer).') - return mtype, None, None, True - else: - d_nom = att['obj'].dd['sections'][0]['type']['d_nom'] - w_nom = att['obj'].dd['sections'][0]['type']['w'] - return 'chain', d_nom, w_nom, False - raise ValueError('No mooring line attachment found for anchor.') - - def getMudlineForces(self, lines_only=False, seabed=True, xyz=False): - ''' - Find forces on anchor at mudline using the platform.getWatchCircle method or MoorPy Point.getForces method. - - Parameters - ---------- - lines_only : boolean, optional - Calculate forces from just mooring lines (True) or not (False). Default is False. - seabed : boolean, optional - Include effect of seabed pushing up the anchor (True) or not (False). Default is True. - xyz : boolean, optional - Return forces in x,y,z DOFs (True) or only the enabled DOFs (False). Default is False. - - Returns - ------- - dict - Dictionary containing mudline forces. - ''' - loads = self.mpAnchor.getForces(lines_only=lines_only, seabed=seabed, xyz=xyz) - - self.loads = { - 'Hm': np.sqrt(loads[0]**2 + loads[1]**2), - 'Vm': loads[2], - 'thetam': np.degrees(np.arctan2(loads[2], np.sqrt(loads[0]**2 + loads[1]**2))), - 'method': 'static', - 'mudline_load_type': 'current_state' - } - - return self.loads - - def getLugForces(self, Hm, Vm, zlug, line_type=None, d=None, w=None, plot=False): - ''' - Calculate the lug forces Ha and Va based on mudline loads using local soil profile. - - Parameters - ---------- - Hm : float - Horizontal mudline load (N) - Vm : float - Vertical mudline load (N) - zlug : float - Padeye embedment depth (m) - line_type : str, optional - Type of mooring line ('chain' or 'wire') - d : float, optional - Mooring line diameter (m) - w : float, optional - Mooring line unit weight (N/m) - plot : bool, optional - Whether to plot the load transfer profile - - Returns - ------- - Ha : float - Horizontal load at lug (N). - Va : float - Vertical load at lug (N). - ''' - from famodel.anchors.anchors_famodel_map.capacity_load_map import getTransferLoad - - # Ensure soil profile is available - if self.soil_profile is None or self.soil_type is None: - raise ValueError("Anchor soil profile or soil type is not assigned. Use setSoilProfile first.") - - soil_profile = self.soil_profile - soil_type = self.soil_type - - # Determine mudline depth - z0 = soil_profile[0]['top'] - - # Load transfer if padeye is embedded - if zlug > z0: - if line_type is None or d is None or w is None: - try: - line_type, d, w = self.getLineProperties() - except ValueError: - print('[Warning] No mooring attachment found. Trying anchor-level line properties...') - line_type = getattr(self, 'line_type', None) - d = getattr(self, 'd', None) - w = getattr(self, 'w', None) - - if any(v is None for v in [line_type, d, w]): - print('[Fallback] Using default chain properties.') - line_type = 'chain' - d = 0.16 - w = 5000.0 - - layers, loads = getTransferLoad( - profile_map=[{'layers': self.soil_profile}], - Tm=np.sqrt(Hm**2 + Vm**2), - thetam=np.degrees(np.arctan2(Vm, Hm)), - zlug=zlug, - line_type=line_type, - d=d, - w=w, - plot=plot - ) - - Ta = loads['Ta'] - thetaa = loads['thetaa'] - Ha = Ta*np.cos(np.deg2rad(thetaa)) - Va = Ta*np.sin(np.deg2rad(thetaa)) - - else: - Ha = Hm - Va = Vm - - return layers, Ha, Va - - def getCapacityAnchor(self, Hm, Vm, zlug, line_type=None, d=None, w=None, plot=False): - ''' - Calculate anchor capacity based on anchor type and local soil profile. - - Parameters - ---------- - Hm : float - Horizontal mudline load (N) - Vm : float - Vertical mudline load (N) - zlug : float - Padeye embedment depth (m) - line_type : str, optional - Type of mooring line ('chain' or 'wire') - d : float, optional - Mooring line diameter (m) - w : float, optional - Mooring line unit weight (N/m) - plot : bool, optional - Whether to plot the load transfer and pile geometry - - Returns - ------- - results : dict - Capacity results dictionary from the selected capacity function. - ''' - from famodel.anchors.anchors_famodel_map.capacity_plate_map import getCapacityPlate - from famodel.anchors.anchors_famodel_map.capacity_suction_map import getCapacitySuction - from famodel.anchors.anchors_famodel_map.capacity_torpedo_map import getCapacityTorpedo - from famodel.anchors.anchors_famodel_map.capacity_helical_map import getCapacityHelical - from famodel.anchors.anchors_famodel_map.capacity_driven_map import getCapacityDriven - from famodel.anchors.anchors_famodel_map.capacity_dandg_map import getCapacityDandG - from famodel.anchors.anchors_famodel_map.capacity_load_map import getTransferLoad - from famodel.anchors.anchors_famodel_map.capacity_plots_map import plot_load - # import numpy as np - - capacity_dispatch = { - 'suction': getCapacitySuction, - 'sepla': getCapacityPlate, - 'dea': getCapacityPlate, - 'depla': getCapacityPlate, - 'vla': getCapacityPlate, - 'plate': getCapacityPlate, - 'torpedo': getCapacityTorpedo, - 'helical': getCapacityHelical, - 'driven': getCapacityDriven, - 'dandg': getCapacityDandG - } - - anchType_clean = self.anchType.lower().replace(' ', '') - capacity_func = capacity_dispatch.get(anchType_clean) - if capacity_func is None: - raise ValueError(f"Unknown anchor type '{self.anchType}' for anchor capacity calculation.") - - if self.soil_profile is None or self.soil_type is None: - raise ValueError("Soil profile or soil type not set for this anchor.") - - soil_profile = self.soil_profile - soil_type = self.soil_type - z0 = soil_profile[0]['top'] - - # Load transfer if padeye is embedded below mudline - if zlug > z0: - if line_type is None or d is None or w is None: - try: - line_type, d, w = self.getLineProperties() - except ValueError: - print('[Warning] No mooring attachment found. Trying anchor-level line properties...') - line_type = getattr(self, 'line_type', None) - d = getattr(self, 'd', None) - w = getattr(self, 'w', None) - - if any(v is None for v in [line_type, d, w]): - print('[Fallback] Using default chain properties.') - line_type = 'chain' - d = 0.16 - w = 5000.0 - - else: - layers, resultsLoad = getTransferLoad( - profile_map=[{'layers': soil_profile}], - Tm=np.sqrt(Hm**2 + Vm**2), - thetam=np.degrees(np.arctan2(Vm, Hm)), - zlug=zlug, - line_type=line_type, - d=d, - w=w, - plot=False - ) - if plot: - plot_load( - layers, - resultsLoad['drag_values'], - resultsLoad['depth_values'], - resultsLoad['Tm'], - resultsLoad['thetam'], - resultsLoad['Ta'], - resultsLoad['thetaa'], - zlug=zlug - ) - - Ta = resultsLoad['Ta'] - thetaa = resultsLoad['thetaa'] - Ha = Ta*np.cos(np.deg2rad(thetaa)) - Va = Ta*np.sin(np.deg2rad(thetaa)) - - print(f'Input Hm = {Hm}, Vm = {Vm}, zlug = {zlug}') - print(f'Input Ha = {Ha}, Va = {Va}, zlug = {zlug}') - print(f'Input Ta = {Ta}, thetaa = {(thetaa)}') - else: - Ha = Hm - Va = Vm - - # --- Call the appropriate capacity function --- - if anchType_clean in ['sepla', 'dea', 'depla', 'vla', 'plate']: - self.capacity_format = 'plate' - B = self.dd['design']['B'] - L = self.dd['design']['L'] - beta = self.dd['design'].get('beta', 0.0) - layers, results = capacity_func( - profile_map=[{'name': self.profile_name, 'layers': self.soil_profile}], - location_name=self.profile_name, - B=B, L=L, zlug=zlug, - beta=beta, - Ha=Ha, Va=Va, - plot=plot - ) - - elif anchType_clean == 'suction': - self.capacity_format = 'envelope' - D = self.dd['design']['D'] - L = self.dd['design']['L'] - zlug = self.dd['design']['zlug'] - layers, results = capacity_func( - profile_map=[{'name': self.profile_name, 'layers': self.soil_profile}], - location_name=self.profile_name, - D=D, L=L, zlug=zlug, - Ha=Ha, Va=Va, - thetalug=5, psilug=7.5, - plot=plot - ) - - elif anchType_clean == 'torpedo': - self.capacity_format = 'envelope' - D1 = self.dd['design']['D1'] - D2 = self.dd['design']['D2'] - L1 = self.dd['design']['L1'] - L2 = self.dd['design']['L2'] - ballast = self.dd['design'].get('ballast', 0.0) - layers, results = capacity_func( - profile_map=[{'name': self.profile_name, 'layers': self.soil_profile}], - location_name=self.profile_name, - D1=D1, D2=D2, L1=L1, L2=L2, - zlug=zlug, - ballast=ballast, - Ha=Ha, Va=Va, - plot=plot - ) - - elif anchType_clean == 'helical': - self.capacity_format = 'component' - D = self.dd['design']['D'] - L = self.dd['design']['L'] - d = self.dd['design']['d'] - zlug = self.dd['design']['zlug'] - layers, results = capacity_func( - profile_map=[{'name': self.profile_name, 'layers': self.soil_profile}], - location_name=self.profile_name, - D=D, L=L, d=d, - zlug=zlug, - Ha=Ha, Va=Va, - plot=plot - ) - - elif anchType_clean in ['driven', 'dandg']: - self.capacity_format = 'component' - L = self.dd['design']['L'] - D = self.dd['design']['D'] - zlug = self.dd['design']['zlug'] - layers, y, z, results = capacity_func( - profile_map=[{'name': self.profile_name, 'layers': self.soil_profile}], - location_name=self.profile_name, - L=L, D=D, zlug=zlug, - Ha=Ha, Va=Va, - plot=plot - ) - - else: - raise ValueError(f"Anchor type '{self.anchType}' not supported.") - - # --- Store results --- - self.capacity_results = { - 'Hmax': results.get('Horizontal max.', np.nan), - 'Vmax': results.get('Vertical max.', np.nan), - 'UC': results.get('Unity check', np.nan), - 'Ha': Ha, - 'Va': Va, - 'zlug': zlug, - 'z0': z0 - } - - if 'Weight pile' in results: - self.capacity_results['Weight pile'] = results['Weight pile'] - if 'Weight plate' in results: - self.capacity_results['Weight plate'] = results['Weight plate'] - - if anchType_clean in ['driven', 'dandg']: - self.capacity_results['Lateral displacement'] = results.get('Lateral displacement', np.nan) - self.capacity_results['Rotational displacement'] = results.get('Rotational displacement', np.nan) - - return results - - def getSafetyFactor(self): - ''' - Calculate the safety factor based on the unity checks stored in capacity results. - - Returns - ------- - dict - Dictionary containing safety factors. - ''' - anchType_clean = self.anchType.lower().replace(' ', '') - - if anchType_clean in ['helical', 'driven', 'dandg']: - UC_v = self.capacity_results.get('Unity check (vertical)', None) - UC_h = self.capacity_results.get('Unity check (horizontal)', None) - - if UC_v is None or UC_h is None: - print("Warning: Vertical or horizontal unity check (UC) not found in capacity results. Returning NaN.") - return {'SF_vertical': np.nan, 'SF_horizontal': np.nan} - - SF_v = 1.0/UC_v if UC_v != 0 else np.inf - SF_h = 1.0/UC_h if UC_h != 0 else np.inf - - return {'SF_vertical': SF_v, 'SF_horizontal': SF_h} - - else: - UC = self.capacity_results.get('UC', None) - - if UC is None: - print("Warning: Unity check (UC) not found in capacity results. Returning NaN.") - return {'SF_combined': np.nan} - - SF = 1.0/UC if UC != 0 else np.inf - - return {'SF_combined': SF} - - def getCostAnchor(self, costDict='default'): - ''' - Calculate the cost of the anchor based on material, installation, and decommissioning costs. - - Parameters - ---------- - costDict : str or dict, optional - If 'default', uses mean values from Task 49 Design Basis ranges. - If dict or yaml path, loads user-defined cost dictionaries. - - Returns - ------- - float - Total cost of the anchor. - ''' - if isinstance(costDict, str) and costDict != 'default': - import yaml - costDict = yaml.load(costDict, Loader=yaml.FullLoader) - - anchType = self.dd['type'] - - if costDict == 'default': - matCostDict = { - 'suction_pile': 4.435, - 'DEA': 5.705, - 'SEPLA': 5.705, - 'DEPLA': 5.705, - 'VLA': 5.705, - 'torpedo_pile': 5.0, - 'helical_pile': 6.0, - 'driven_pile': 4.0, - 'dandg_pile': 5.5 - } - instCostDict = { - 'suction_pile': 2.0, - 'DEA': 1.5, - 'SEPLA': 1.5, - 'DEPLA': 1.5, - 'VLA': 1.5, - 'torpedo_pile': 2.5, - 'helical_pile': 3.0, - 'driven_pile': 2.0, - 'dandg_pile': 2.2 - } - decomCostDict = { - 'suction_pile': 1.0, - 'DEA': 0.8, - 'SEPLA': 0.8, - 'DEPLA': 0.8, - 'VLA': 0.8, - 'torpedo_pile': 1.2, - 'helical_pile': 1.5, - 'driven_pile': 1.0, - 'dandg_pile': 1.1 - } - else: - matCostDict = costDict.get('material', {}) - instCostDict = costDict.get('install', {}) - decomCostDict = costDict.get('decom', {}) - - keyFail = True - - # Ensure mass is available - if self.mass is None or self.mass == 0: - # Try to extract from capacity_results if already available - if 'Weight pile' in self.capacity_results: - self.mass = self.capacity_results['Weight pile']/self.g - elif 'Weight plate' in self.capacity_results: - self.mass = self.capacity_results['Weight plate']/self.g - else: - # If capacity_results missing, attempt to calculate capacity to retrieve weight - if 'soil_properties' in self.dd: - self.getAnchorCapacity(plot=False) - if 'Weight pile' in self.capacity_results: - self.mass = self.capacity_results['Weight pile']/self.g - elif 'Weight plate' in self.capacity_results: - self.mass = self.capacity_results['Weight plate']/self.g - else: - print('Warning: Weight not found after capacity calculation, setting mass to 0.') - self.mass = 0 - else: - print('Soil properties needed to calculate anchor mass for cost. Setting mass to 0.') - self.mass = 0 - - # Calculate material cost based on mass - if anchType in matCostDict: - self.cost['Material Cost'] = matCostDict[anchType]*self.mass - keyFail = False - else: - raise KeyError(f'Anchor type {anchType} not found in material cost dictionary.') - - # Install and decom costs if available - self.cost['Installation Cost'] = instCostDict.get(anchType, 0.0) - self.cost['Decommissioning Cost'] = decomCostDict.get(anchType, 0.0) - - # Total cost - self.cost['Total Cost'] = (self.cost['Material Cost'] + - self.cost['Installation Cost'] + - self.cost['Decommissioning Cost']) - - return sum(self.cost.values()) - - def getSizeAnchor(self, geom, geomKeys, geomBounds=None, loads=None, - minfs={'Ha': 1.6, 'Va': 2.0}, lambdap_con=[4, 8], zlug_fix=False, plot=False): - ''' - Generalized optimization method for all anchor types. - ''' - - anchType_clean = self.dd['type'].lower().replace(' ', '') - - if loads is None: - loads = self.loads - - Hm = loads['Hm'] - Vm = loads['Vm'] - - line_type = getattr(self, 'line_type', 'chain') - d = getattr(self, 'd', 0.16) - w = getattr(self, 'w', 5000.0) - - def update_zlug_if_suction(): - if anchType_clean == 'suction' and not zlug_fix and 'zlug' not in geomKeys: - self.dd['design']['zlug'] = (2/3)*self.dd['design']['L'] - - # --- Stage 1: Safety Optimization to reach UC <= 1 --- - def safety_objective(vars): - for i, key in enumerate(geomKeys): - self.dd['design'][key] = vars[i] - update_zlug_if_suction() - - _, Ha, Va = self.getLugForces(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], line_type=line_type, d=d, w=w, plot=False) - - self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], line_type=line_type, d=d, w=w, plot=False) - - if self.capacity_format == 'envelope': - UC = self.capacity_results.get('UC', 2.0) - elif self.capacity_format == 'component': - UC = max( - self.capacity_results.get('Unity check (horizontal)', 2.0), - self.capacity_results.get('Unity check (vertical)', 2.0) - ) - elif self.capacity_format == 'plate': - UC = self.capacity_results.get('UC', 2.0) - else: - UC = 2.0 - return (UC - 1.0)**2 - - minimize( - safety_objective, - geom, - method='COBYLA', - bounds=geomBounds if geomBounds else None, - options={'rhobeg': 0.02, 'catol': 0.001, 'maxiter': 1500} - ) - - # --- Stage 2: Weight Minimization with constraints --- - if anchType_clean != 'torpedo': - def weight_objective(vars): - for i, key in enumerate(geomKeys): - self.dd['design'][key] = vars[i] - update_zlug_if_suction() - - _, Ha, Va = self.getLugForces(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], line_type=line_type, d=d, w=w, plot=False) - - self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], line_type=line_type, d=d, w=w, plot=False) - - return self.capacity_results.get('Weight pile', - self.capacity_results.get('Weight plate', - self.capacity_results.get('Weight', 1e9))) - - def constraint_uc_envelope(vars): - return 1.0 - self.capacity_results.get('UC', 2.0) - - def constraint_uc_component(vars): - return 1.0 - max( - self.capacity_results.get('Unity check (horizontal)', 2.0), - self.capacity_results.get('Unity check (vertical)', 2.0) - ) - - def constraint_fs_horizontal(vars): - return (self.capacity_results.get('Horizontal max.', 0)/self.capacity_results.get('Ha', 1)) - minfs['Ha'] - - def constraint_fs_vertical(vars): - return (self.capacity_results.get('Vertical max.', 0)/self.capacity_results.get('Va', 1)) - minfs['Va'] - - def constraint_lambda_min(vars): - anchType_clean = self.dd['type'].lower().replace(' ', '') - - if anchType_clean == 'torpedo': - L = self.dd['design']['L1'] + self.dd['design']['L2'] - A_wing = (self.dd['design']['D1'] - self.dd['design']['D2'])*self.dd['design']['L1'] - A_shaft = self.dd['design']['D2']*L - D = (A_wing + A_shaft)/L - elif anchType_clean in ['driven', 'dandg', 'helical', 'suction']: - L = self.dd['design']['L'] - D = self.dd['design']['D'] - elif anchType_clean in ['plate', 'sepla', 'dea', 'depla', 'vla']: - L = self.dd['design']['L'] - D = self.dd['design']['B'] - else: - raise ValueError(f'lambda constraints not defined for anchor type: {anchType_clean}') - return (L/D) - lambdap_con[0] - - def constraint_lambda_max(vars): - anchType_clean = self.dd['type'].lower().replace(' ', '') - - if anchType_clean == 'torpedo': - L = self.dd['design']['L1'] + self.dd['design']['L2'] - A_wing = (self.dd['design']['D1'] - self.dd['design']['D2'])*self.dd['design']['L1'] - A_shaft = self.dd['design']['D2']*L - D = (A_wing + A_shaft)/L - elif anchType_clean in ['driven', 'dandg', 'helical', 'suction']: - L = self.dd['design']['L'] - D = self.dd['design']['D'] - elif anchType_clean in ['plate', 'sepla', 'dea', 'depla', 'vla']: - L = self.dd['design']['L'] - D = self.dd['design']['B'] # use plate width - else: - raise ValueError(f'lambda constraints not defined for anchor type: {anchType_clean}') - return lambdap_con[1] - (L/D) - - if self.capacity_format == 'envelope': - constraints = [ - {'type': 'ineq', 'fun': constraint_uc_envelope}, - {'type': 'ineq', 'fun': constraint_fs_horizontal}, - {'type': 'ineq', 'fun': constraint_fs_vertical}, - {'type': 'ineq', 'fun': constraint_lambda_min}, - {'type': 'ineq', 'fun': constraint_lambda_max}, - ] - elif self.capacity_format == 'component': - constraints = [ - {'type': 'ineq', 'fun': constraint_uc_component}, - {'type': 'ineq', 'fun': constraint_lambda_min}, - {'type': 'ineq', 'fun': constraint_lambda_max}, - ] - elif self.capacity_format == 'plate': - constraints = [ - {'type': 'ineq', 'fun': constraint_uc_envelope} - ] - else: - raise ValueError(f"Unknown capacity_format: {self.capacity_format}") - - result = minimize( - weight_objective, - [self.dd['design'][key] for key in geomKeys], - method='COBYLA', - constraints=constraints, - bounds=geomBounds if geomBounds else None, - options={'rhobeg': 0.5, 'catol': 0.01, 'maxiter': 100} - ) - - endGeom = dict(zip(geomKeys, result.x)) - print('Optimized geometry:', endGeom) - self.dd['design'].update(endGeom) - - update_zlug_if_suction() - - self.getCapacityAnchor(Hm=Hm, Vm=Vm, zlug=self.dd['design']['zlug'], line_type=line_type, d=d, w=w, plot=plot) - - print('\nFinal Optimized Anchor:') - print('Design:', self.dd['design']) - print('Capacity Results:', self.capacity_results) - - - def getCombinedPlot(self): - ''' - Create a plot showing the suction pile and the inverse catenary overlay in the same coordinate system. - ''' - from famodel.anchors.anchors_famodel_map.capacity_load_map import getTransferLoad - from famodel.anchors.anchors_famodel_map.capacity_plots_map import plot_suction - - if self.anchType.lower() != 'suction': - raise NotImplementedError("getCombinedPlot only supports suction piles.") - - # Extract design inputs - design = self.dd['design'] - D = design['D'] - L = design['L'] - zlug = design['zlug'] - - if self.soil_profile is None or self.soil_type is None: - raise ValueError("Soil profile or type not assigned. Use setSoilProfile first.") - - soil_profile = self.soil_profile - soil_type = self.soil_type - z0 = soil_profile[0]['top'] - - Hm = self.loads['Hm'] - Vm = self.loads['Vm'] - thetam = self.loads.get('thetam', np.degrees(np.arctan2(Vm, Hm))) - - line_type = getattr(self, 'line_type', 'chain') - d = getattr(self, 'd', 0.16) - w = getattr(self, 'w', 5000.0) - - # Get inverse catenary path - layers, result = getTransferLoad( - profile_map=[{'layers': self.soil_profile}], - Tm=np.sqrt(Hm**2 + Vm**2), - thetam=thetam, - zlug=zlug, - line_type=line_type, - d=d, - w=w, - plot=False - ) - - drag_values = np.array(result['drag_values']) - depth_values = -np.array(result['depth_values'])[::-1] - - x_start = D/2 + drag_values[0] - z_start = zlug - drag_transformed = x_start - drag_values - depth_transformed = z_start + (depth_values- depth_values[0]) - - # Plot suction pile - plot_suction(soil_profile, L, D, z0=z0, zlug=zlug, title='Suction Pile and Mooring Line Load Path') - - - # Overlay inverse catenary path - plt.plot(drag_transformed, depth_transformed, color='b', lw=2.0, label='Inverse catenary') - plt.plot(drag_transformed[-1], depth_transformed[-1], 'ro', label='Mudline end') - plt.plot( drag_transformed[0], depth_transformed[0], 'go', label='Embedded end') - - n = 2e6 - Tm = result['Tm'] - Ta = result['Ta'] - thetaa = result['thetaa'] - - plt.arrow(drag_transformed[-1], depth_transformed[-1], - Tm*np.cos(np.deg2rad(thetam))/n, -Tm*np.sin(np.deg2rad(thetam))/n, - head_width=0.25, head_length=0.5, color='r', label='Mudline load') - - plt.arrow(drag_transformed[0], depth_transformed[0], - Ta*np.cos(np.deg2rad(thetaa))/n, -Ta*np.sin(np.deg2rad(thetaa))/n, - head_width=0.25, head_length=0.5, color='g', label='Padeye load') - - xmax = max(drag_transformed[-1] + D, 2*D) - plt.xlim(-D, xmax) - plt.legend() - plt.grid(True) - plt.tight_layout() - plt.show() diff --git a/famodel/anchors/anchor_profile.py b/famodel/anchors/anchor_profile.py deleted file mode 100644 index 611c5b0a..00000000 --- a/famodel/anchors/anchor_profile.py +++ /dev/null @@ -1,915 +0,0 @@ -"""Anchor class for FAModel, containing information and key methods for anchors of mooring lines - Work in progress -""" -import moorpy as mp -import numpy as np -from scipy.optimize import minimize -from famodel.famodel_base import Node -from famodel.mooring.mooring import Mooring -import famodel.platform.platform - -class Anchor(Node): - - def __init__(self, dd=None, ms=None, r=[0,0,0], aNum=None, id=None, g=9.81, rho=1025): - ''' - Initialize an Anchor object. - - Parameters - ---------- - dd : dict - Design dictionary containing all information on the anchor: - { - type : str - Anchor type ('plate', 'suction_pile', 'torpedo_pile', 'helical_pile', 'driven_pile', 'dandg_pile') - design : dict - Geometric properties (e.g., A, D, D1, D2, d, L, L1, L2, zlug, beta) - cost : dict - Cost breakdown (matCost, instCost, decomCost) - } - ms : MoorPy system object - The MoorPy system instance the anchor is added to. - r : list of float - Location of the anchor in (x, y, z) coordinates (m). - aNum : int, optional - Entry number for anchor within the project anchorList dictionary. - id : str or int, optional - Unique identifier for the anchor object. - g : float, optional - Gravitational acceleration (m/s²). Default is 9.81. - rho : float, optional - Water density (kg/m³). Default is 1025. - ''' - - from famodel.famodel_base import Node - Node.__init__(self, id) - - self.dd = dd - self.ms = ms - self.r = r - self.aNum = aNum - self.g = g - self.rho = rho - - # Initialize anchor type and soil type - self.anchType = dd.get('type') if dd else None - self.soil_type = None - - # Initialize MoorPy anchor object - self.mpAnchor = None - - # Extract mass if available - self.mass = dd.get('design', {}).get('mass', None) if dd else None - - # Initialize other dictionaries - self.anchorCapacity = {} - self.cost = {} - self.loads = {} - self.soilProps = {} - self.failure_probability = {} - self.env_impact = {} - - def makeMoorPyAnchor(self, ms): - ''' - Create a MoorPy anchor object in a MoorPy system. - - Parameters - ---------- - ms : MoorPy system instance - The MoorPy system to add the anchor to. - - Returns - ------- - ms : MoorPy system instance - The updated MoorPy system with the anchor added. - ''' - import moorpy as mp - - # Create anchor as a fixed point in MoorPy system - ms.addPoint(1, self.r) - - # Assign this point as mpAnchor in the anchor class instance - self.mpAnchor = ms.pointList[-1] - - # Set mass if available - if 'mass' in self.dd.get('design', {}): - self.mpAnchor.m = self.dd['design']['mass'] - - # Set diameter if available - if 'd' in self.dd.get('design', {}): - self.mpAnchor.d = self.dd['design']['d'] - - # Set the point as an anchor entity - self.mpAnchor.entity = {'type': 'anchor'} - if 'type' in self.dd: - self.mpAnchor.entity['anchor_type'] = self.dd['type'] - - return ms - - def getLineProperties(self): - ''' - Retrieve line_type, diameter and unit weight from attached mooring. - - Returns - ------- - line_type : str - Type of mooring line ('chain' or 'wire'). - d : float - Nominal diameter (m). - w : float - Unit weight (N/m). - nolugload : bool - True if no lug load transfer should be applied. - ''' - for att in self.attachments.values(): - if isinstance(att['obj'], Mooring): - mtype = att['obj'].dd['sections'][0]['type']['material'].lower() - if 'chain' not in mtype: - print('No chain on seafloor, setting Ta=Tm (no load transfer).') - return mtype, None, None, True - else: - d_nom = att['obj'].dd['sections'][0]['type']['d_nom'] - w_nom = att['obj'].dd['sections'][0]['type']['w'] - return 'chain', d_nom, w_nom, False - raise ValueError('No mooring line attachment found for anchor.') - - def getMudlineForces(self, lines_only=False, seabed=True, xyz=False): - ''' - Find forces on anchor at mudline using the platform.getWatchCircle method or MoorPy Point.getForces method. - - Parameters - ---------- - lines_only : boolean, optional - Calculate forces from just mooring lines (True) or not (False). Default is False. - seabed : boolean, optional - Include effect of seabed pushing up the anchor (True) or not (False). Default is True. - xyz : boolean, optional - Return forces in x,y,z DOFs (True) or only the enabled DOFs (False). Default is False. - - Returns - ------- - dict - Dictionary containing mudline forces. - ''' - loads = self.mpAnchor.getForces(lines_only=lines_only, seabed=seabed, xyz=xyz) - - self.loads = { - 'Hm': np.sqrt(loads[0]**2 + loads[1]**2), - 'Vm': loads[2], - 'thetam': np.degrees(np.arctan2(loads[2], np.sqrt(loads[0]**2 + loads[1]**2))), - 'method': 'static', - 'mudline_load_type': 'current_state' - } - - return self.loads - - def getLugForces(self, ground_conds, Hm, Vm, thetam, zlug, line_type=None, d=None, w=None, plot=False): - ''' - Calculate the lug forces Ha and Va based on mudline loads. - - Parameters - ---------- - ground_conds : dict - Dictionary of ground conditions where keys are soil types. - Hm : float - Horizontal mudline load (N). - Vm : float - Vertical mudline load (N). - thetam : float - Mudline load angle (deg). - zlug : float - Padeye embedment depth (m). - line_type : str, optional - Type of mooring line ('chain' or 'wire'). - d : float, optional - Mooring line diameter (m). - w : float, optional - Mooring line unit weight (N/m). - plot : bool, optional - Whether to plot the load transfer profile. - - Returns - ------- - Ha : float - Horizontal load at lug (N). - Va : float - Vertical load at lug (N). - ''' - from famodel.anchors.anchors_famodel_profile.capacity_load import getTransferLoad - - if self.soil_type is None: - self.soil_type = self.dd.get('design', {}).get('soil_type') - - soil_profile = self.dd.get('soil_properties', {}).get(self.soil_type) - - # Determine mudline depth - z0 = soil_profile[0][0] - - # Load transfer if padeye is embedded - if zlug > z0: - # Fallback mechanism for line properties - if line_type is None or d is None or w is None: - try: - line_type, d, w, _ = self.getLineProperties() - except ValueError: - print('[Warning] No mooring attachment found. Trying anchor-level line properties...') - line_type = getattr(self, 'line_type', None) - d = getattr(self, 'd', None) - w = getattr(self, 'w', None) - - if any(v is None for v in [line_type, d, w]): - print('[Fallback] Using default chain properties.') - line_type = 'chain' - d = 0.16 - w = 5000.0 - - loads = getTransferLoad( - soil_profile, self.soil_type, np.sqrt(Hm**2 + Vm**2), - thetam, zlug, line_type, d, w, plot=plot - ) - Ta = loads['Ta'] - thetaa = loads['thetaa'] - Ha = Ta*np.cos(thetaa) - Va = Ta*np.sin(thetaa) - - else: - Ha = Hm - Va = Vm - - return Ha, Va - - - def getCapacityAnchor(self, ground_conds, Hm, Vm, thetam, zlug, line_type=None, d=None, w=None, plot=False): - ''' - Calculate anchor capacity based on anchor type and ground conditions. - - Parameters - ---------- - ground_conds : dict - Dictionary of ground conditions where keys are soil types. - Hm : float - Horizontal mudline load (N). - Vm : float - Vertical mudline load (N). - thetam : float - Mudline load angle (deg). - zlug : float - Padeye embedment depth (m). - line_type : str, optional - Type of mooring line ('chain' or 'wire'). - d : float, optional - Mooring line diameter (m). - w : float, optional - Mooring line unit weight (N/m). - plot : bool, optional - Whether to plot the results. - - Returns - ------- - None - Updates anchor object with capacity results. - ''' - from famodel.anchors.anchors_famodel_profile.capacity_plate import getCapacityPlate - from famodel.anchors.anchors_famodel_profile.capacity_suction import getCapacitySuction - from famodel.anchors.anchors_famodel_profile.capacity_torpedo import getCapacityTorpedo - from famodel.anchors.anchors_famodel_profile.capacity_helical import getCapacityHelical - from famodel.anchors.anchors_famodel_profile.capacity_driven import getCapacityDriven - from famodel.anchors.anchors_famodel_profile.capacity_dandg import getCapacityDandG - from famodel.anchors.anchors_famodel_profile.capacity_load import getTransferLoad - import numpy as np - - # --- Dispatch dictionary --- - capacity_dispatch = { - 'suction': getCapacitySuction, - 'sepla': getCapacityPlate, - 'dea': getCapacityPlate, - 'depla': getCapacityPlate, - 'vla': getCapacityPlate, - 'plate': getCapacityPlate, - 'torpedo': getCapacityTorpedo, - 'helical': getCapacityHelical, - 'driven': getCapacityDriven, - 'dandg': getCapacityDandG - } - - # Normalize anchor type - anchType_clean = self.anchType.lower().replace(' ', '') - - # Find function - capacity_func = capacity_dispatch.get(anchType_clean) - if capacity_func is None: - raise ValueError(f"Unknown anchor type '{self.anchType}' for anchor capacity calculation.") - - # Get ground conditions - soil_profile = ground_conds.get(self.soil_type) - if soil_profile is None: - raise ValueError(f"Ground condition '{self.soil_type}' not found in provided ground_conds.") - - # Determine if load transfer is needed - z0 = soil_profile[0][0] - - # Load transfer if padeye is embedded - if zlug > z0: - if line_type is None or d is None or w is None: - try: - line_type, d, w, nolugload = self.getLineProperties() - except ValueError: - print('[Warning] No mooring attachment found. Trying anchor-level line properties...') - line_type = getattr(self, 'line_type', None) - d = getattr(self, 'd', None) - w = getattr(self, 'w', None) - nolugload = False - - if line_type is None or d is None or w is None: - print('[Fallback] Using default chain properties.') - line_type = 'chain' - d = 0.16 - w = 5000.0 - - if nolugload: - Ha, Va = Hm, Vm - else: - loads = getTransferLoad(soil_profile, self.soil_type, Tm=np.sqrt(Hm**2 + Vm**2), thetam=thetam, zlug=zlug, line_type=line_type, d=d, w=w, plot=plot) - Ta = loads['Ta'] - thetaa = loads['thetaa'] - Ha = Ta*np.cos(thetaa) - Va = Ta*np.sin(thetaa) - else: - loads = getTransferLoad(soil_profile, self.soil_type, Tm=np.sqrt(Hm**2 + Vm**2), thetam=thetam, zlug=zlug, line_type=line_type, d=d, w=w, plot=plot) - Ta = loads['Ta'] - thetaa = loads['thetaa'] - Ha = Ta*np.cos(thetaa) - Va = Ta*np.sin(thetaa) - else: - Ha = Hm - Va = Vm - - # Call the capacity function based on anchor type - if anchType_clean == 'suction': - D = self.dd['design']['D'] - L = self.dd['design']['L'] - zlug = self.dd['design']['zlug'] - - results = capacity_func(soil_profile, self.soil_type, D, L, zlug, Ha, Va, plot=plot) - - elif anchType_clean in ['sepla', 'dea', 'depla', 'vla', 'plate']: - results = capacity_func(soil_profile, self.soil_type, self.B, self.L, zlug, self.beta, Ha, Va, plot=plot) - - elif anchType_clean == 'torpedo': - results = capacity_func(soil_profile, self.soil_type, self.D1, self.D2, self.L1, self.L2, zlug, self.ballast, Ha, Va, plot=plot) - - elif anchType_clean == 'helical': - results = capacity_func(soil_profile, self.soil_type, self.D, self.L, self.d, zlug, Ha, Va, plot=plot) - - elif anchType_clean == 'driven': - y, z, results = capacity_func(soil_profile, self.soil_type, self.L, self.D, zlug, Ha, Va, plot=plot) - - elif anchType_clean == 'dandg': - y, z, results = capacity_func(soil_profile, self.soil_type, self.L, self.D, zlug, Ha, Va, plot=plot) - - else: - raise ValueError(f"Anchor type '{self.anchType}' not supported.") - - # --- Standardize and store capacity results --- - self.capacity_results = { - 'Hmax': results.get('Horizontal max.', np.nan), - 'Vmax': results.get('Vertical max.', np.nan), - 'UC': results.get('Unity check', np.nan), - 'Ha': Ha, - 'Va': Va, - 'zlug': zlug, - 'z0': z0 - } - - # Add mass if weight is available - if 'Weight pile' in results: - self.capacity_results['Weight pile'] = results['Weight pile'] - if 'Weight plate' in results: - self.capacity_results['Weight plate'] = results['Weight plate'] - - # Special cases for displacement-based anchors - if anchType_clean in ['driven_pile', 'dandg_pile']: - self.capacity_results['Lateral displacement'] = results.get('Lateral displacement', np.nan) - self.capacity_results['Rotational displacement'] = results.get('Rotational displacement', np.nan) - - return results - - def getSafetyFactor(self): - ''' - Calculate the safety factor based on the unity checks stored in capacity results. - - Returns - ------- - dict - Dictionary containing safety factors. - ''' - anchType_clean = self.anchType.lower().replace(' ', '') - - if anchType_clean in ['helical', 'driven', 'dandg']: - UCv = self.capacity_results.get('Unity check (vertical)', None) - UCh = self.capacity_results.get('Unity check (horizontal)', None) - - if UCv is None or UCh is None: - print("Warning: Vertical or Horizontal Unity Check not found in capacity results. Returning NaN.") - return {'SF_vertical': np.nan, 'SF_horizontal': np.nan} - - SFv = 1.0/UCv if UCv != 0 else np.inf - SFh = 1.0/UCh if UCh != 0 else np.inf - - return {'SF_vertical': SFv, 'SF_horizontal': SFh} - - else: - UC = self.capacity_results.get('UC', None) - - if UC is None: - print("Warning: Unity Check (UC) not found in capacity results. Returning NaN.") - return {'SF_combined': np.nan} - - SF = 1.0/UC if UC != 0 else np.inf - - return {'SF_combined': SF} - - def getCost(self, costDict='default'): - ''' - Calculate the cost of the anchor based on material, installation, and decommissioning costs. - - Parameters - ---------- - costDict : str or dict, optional - If 'default', uses mean values from Task 49 Design Basis ranges. - If dict or yaml path, loads user-defined cost dictionaries. - - Returns - ------- - float - Total cost of the anchor. - ''' - if isinstance(costDict, str) and costDict != 'default': - import yaml - costDict = yaml.load(costDict, Loader=yaml.FullLoader) - - anchType = self.dd['type'] - - if costDict == 'default': - matCostDict = { - 'suction_pile': 4.435, - 'DEA': 5.705, - 'SEPLA': 5.705, - 'DEPLA': 5.705, - 'VLA': 5.705, - 'torpedo_pile': 5.0, - 'helical_pile': 6.0, - 'driven_pile': 4.0, - 'dandg_pile': 5.5 - } - instCostDict = { - 'suction_pile': 2.0, - 'DEA': 1.5, - 'SEPLA': 1.5, - 'DEPLA': 1.5, - 'VLA': 1.5, - 'torpedo_pile': 2.5, - 'helical_pile': 3.0, - 'driven_pile': 2.0, - 'dandg_pile': 2.2 - } - decomCostDict = { - 'suction_pile': 1.0, - 'DEA': 0.8, - 'SEPLA': 0.8, - 'DEPLA': 0.8, - 'VLA': 0.8, - 'torpedo_pile': 1.2, - 'helical_pile': 1.5, - 'driven_pile': 1.0, - 'dandg_pile': 1.1 - } - else: - matCostDict = costDict.get('material', {}) - instCostDict = costDict.get('install', {}) - decomCostDict = costDict.get('decom', {}) - - keyFail = True - - # Ensure mass is available - if self.mass is None or self.mass == 0: - # Try to extract from capacity_results if already available - if 'Weight pile' in self.capacity_results: - self.mass = self.capacity_results['Weight pile']/self.g - elif 'Weight plate' in self.capacity_results: - self.mass = self.capacity_results['Weight plate']/self.g - else: - # If capacity_results missing, attempt to calculate capacity to retrieve weight - if 'soil_properties' in self.dd: - self.getAnchorCapacity(plot=False) - if 'Weight pile' in self.capacity_results: - self.mass = self.capacity_results['Weight pile']/self.g - elif 'Weight plate' in self.capacity_results: - self.mass = self.capacity_results['Weight plate']/self.g - else: - print('Warning: Weight not found after capacity calculation, setting mass to 0.') - self.mass = 0 - else: - print('Soil properties needed to calculate anchor mass for cost. Setting mass to 0.') - self.mass = 0 - - # Calculate material cost based on mass - if anchType in matCostDict: - self.cost['Material Cost'] = matCostDict[anchType]*self.mass - keyFail = False - else: - raise KeyError(f'Anchor type {anchType} not found in material cost dictionary.') - - # Install and decom costs if available - self.cost['Installation Cost'] = instCostDict.get(anchType, 0.0) - self.cost['Decommissioning Cost'] = decomCostDict.get(anchType, 0.0) - - # Total cost - self.cost['Total Cost'] = (self.cost['Material Cost'] + - self.cost['Installation Cost'] + - self.cost['Decommissioning Cost']) - - return sum(self.cost.values()) - - - def getSize(self, geom, geomKeys, geomBounds=None, loads=None, minfs={'Ha':1.0,'Va':1.0}, - lambdap_con=[4,6], zlug_fix=False, FSdiff_max=None, plot=False): - ''' - Resize the anchor dimensions to meet the target safety factor and geometric constraints. - - Parameters - ---------- - geom : list - Starting guess geometry values. - geomKeys : list - List of keys matching the geom list values (e.g., 'L', 'D', 'zlug'). - geomBounds : list, optional - List of tuples of upper and lower bounds for each geometry value. - loads : dict, optional - Dictionary of maximum anchor loads. - minfs : dict, optional - Minimum factors of safety in horizontal and vertical directions. - lambdap_con : list, optional - Constraint for L/D parameter as [min, max]. - zlug_fix : bool, optional - Whether zlug should be fixed (True) or updated (False). - FSdiff_max : dict, optional - Maximum allowable difference between achieved FS and target FS. - plot : bool, optional - Whether to plot results. - - Returns - ------- - None - ''' - from scipy.optimize import minimize - import numpy as np - - anchType = self.dd['type'] - - if loads is None: - loads = self.loads - - # Compute thetam internally from Hm and Vm - Hm = loads['Hm'] - Vm = loads['Vm'] - thetam = np.degrees(np.arctan2(Vm, Hm)) - zlug = loads['zlug'] - - # Read mooring properties from anchor attributes - line_type = self.line_type - d = self.d - w = self.w - - Ha, Va = self.getLugForces( - ground_conds=self.dd.get('soil_properties'), - Hm=Hm, - Vm=Vm, - thetam=thetam, - zlug=zlug, - line_type=line_type, - d=d, - w=w, - plot=plot - ) - - ground_conds = self.dd.get('soil_properties') - - input_loads = {'Ha': Ha*minfs['Ha'], 'Va': Va*minfs['Va']} - - # Objective: minimize weight - def objective_(vars, geomKeys, Ha, Va, ground_conds, thetam, zlug, plot): - newGeom = dict(zip(geomKeys, vars)) - self.dd['design'].update(newGeom) - if 'suction' in self.dd['type'] and not zlug_fix: - self.dd['design']['zlug'] = (2/3)*newGeom['L'] - results = self.getCapacityAnchor(ground_conds, Ha, Va, thetam, zlug, plot=plot) - return results.get('Weight pile', results.get('Weight plate', 1e6)) - - # Constraints - def conFun_lambdap_(vars, lambdap_con, geomKeys): - newGeom = dict(zip(geomKeys, vars)) - lambdap = newGeom['L']/newGeom['D'] - return min(lambdap - lambdap_con[0], lambdap_con[1] - lambdap) - - def conFun_UC_(vars, Ha, Va, ground_conds, thetam, zlug, plot): - results = self.getCapacityAnchor(ground_conds, Ha, Va, thetam, zlug, plot=plot) - return results.get('Unity check', 0) - 1 - - def conFun_H_(vars, Ha, Va, ground_conds, thetam, zlug, plot): - results = self.getCapacityAnchor(ground_conds, Ha, Va, thetam, zlug, plot=plot) - FS = self.getFS() - return FS.get('SF_horizontal', FS.get('SF_combined', 0)) - 1 - - def conFun_V_(vars, minfs, Ha, Va, ground_conds, thetam, zlug, plot): - results = self.getCapacityAnchor(ground_conds, Ha, Va, thetam, zlug, plot=plot) - FS = self.getFS() - if minfs['Va'] == 0: - return 1 - return FS.get('SF_vertical', FS.get('SF_combined', 0)) - 1 - - # Initial geometry setup - startGeom = dict(zip(geomKeys, geom)) - self.dd['design'].update(startGeom) - - if not 'zlug' in self.dd['design']: - if 'suction' in anchType and not zlug_fix: - self.dd['design']['zlug'] = (2/3)*startGeom['L'] - else: - self.dd['design']['zlug'] = 0 - - if zlug_fix and 'zlug' in geomKeys: - zlug_loc = geomKeys.index('zlug') - geomKeys.pop(zlug_loc) - geom.pop(zlug_loc) - if geomBounds: - geomBounds.pop(zlug_loc) - - initial_guess = geom - - # Setup constraints - constraints = [] - - if 'suction' in anchType: - constraints.append({'type': 'ineq', 'fun': conFun_lambdap_, 'args': (lambdap_con, geomKeys)}) - - if 'torpedo' in anchType or 'suction' in anchType: - constraints.append({'type': 'ineq', 'fun': conFun_UC_, 'args': (Ha, Va, ground_conds, thetam, zlug, plot)}) - else: - constraints.append({'type': 'ineq', 'fun': conFun_H_, 'args': (Ha, Va, ground_conds, thetam, zlug, plot)}) - constraints.append({'type': 'ineq', 'fun': conFun_V_, 'args': (minfs, Ha, Va, ground_conds, thetam, zlug, plot)}) - - print('Starting optimization of anchor size') - - if geomBounds is None: - solution = minimize(objective_, initial_guess, args=(geomKeys, Ha, Va, ground_conds, thetam, zlug, plot), - method='COBYLA', constraints=constraints, - options={'rhobeg': 0.1, 'catol': 0.001}) - else: - solution = minimize(objective_, initial_guess, args=(geomKeys, Ha, Va, ground_conds, thetam, zlug, plot), - method='COBYLA', constraints=constraints, bounds=geomBounds, - options={'rhobeg': 0.1, 'catol': 0.001}) - - # Update final geometry - endGeom = dict(zip(geomKeys, solution.x)) - print('Optimized geometry: ', endGeom) - self.dd['design'].update(endGeom) - - if 'suction' in anchType and not zlug_fix: - self.dd['design']['zlug'] = (2/3)*self.dd['design']['L'] - zlug = self.dd['design']['zlug'] # update local zlug - - self.getCapacityAnchor(ground_conds, Ha, Va, thetam, zlug, plot=plot) - - def getSizeSuction(self, geom, geomKeys, geomBounds=None, loads=None, minfs={'Ha':1.6,'Va':2}, - lambdap_con=[4,8], zlug_fix=False, plot=False): - ''' - Two-stage optimization: - Stage 1 - Grow anchor to satisfy UC <= 1. - Stage 2 - Minimize weight while keeping UC <= 1 and satisfying L/D constraints. - ''' - - anchType = self.dd['type'] - - if loads is None: - loads = self.loads - - Hm = loads['Hm'] - Vm = loads['Vm'] - zlug = self.dd['design']['zlug'] - thetam = np.degrees(np.arctan2(Vm, Hm)) - - line_type = self.line_type - d = self.d - w = self.w - - initial_guess = [self.dd['design']['L'], self.dd['design']['D']] - bounds = geomBounds if geomBounds else [(5.0, 30.0), (2.0, 5.0)] - - ground_conds = self.dd.get('soil_properties') - - # --- Stage 1: Safety First --- - def safety_objective(vars): - L, D = vars - self.dd['design']['L'] = L - self.dd['design']['D'] = D - self.dd['design']['zlug'] = (2/3) * L - - Ha, Va = self.getLugForces( - ground_conds=ground_conds, - Hm=Hm, - Vm=Vm, - thetam=thetam, - zlug=self.dd['design']['zlug'], - line_type=line_type, - d=d, - w=w, - plot=False - ) - - self.getCapacityAnchor( - ground_conds=ground_conds, - Hm=Hm, - Vm=Vm, - thetam=thetam, - zlug=self.dd['design']['zlug'], - line_type=line_type, - d=d, - w=w, - plot=False - ) - - UC = self.capacity_results.get('UC', 2.0) - return max(0.0, UC - 1.0)**2 - - minimize( - safety_objective, - initial_guess, - method='COBYLA', - bounds=bounds, - options={'rhobeg': 0.1, 'catol': 0.001, 'maxiter': 300} - ) - - # --- Stage 2: Weight Minimization --- - def weight_objective(vars): - L, D = vars - self.dd['design']['L'] = L - self.dd['design']['D'] = D - self.dd['design']['zlug'] = (2/3) * L - - Ha, Va = self.getLugForces( - ground_conds=ground_conds, - Hm=Hm, - Vm=Vm, - thetam=thetam, - zlug=self.dd['design']['zlug'], - line_type=line_type, - d=d, - w=w, - plot=False - ) - - self.getCapacityAnchor( - ground_conds=ground_conds, - Hm=Hm, - Vm=Vm, - thetam=thetam, - zlug=self.dd['design']['zlug'], - line_type=line_type, - d=d, - w=w, - plot=False - ) - - return self.capacity_results.get('Weight pile', 1e9) - - def constraint_uc(vars): - L, D = vars - return 1.0 - self.capacity_results.get('UC', 2.0) - - def constraint_fs_horizontal(vars): - L, D = vars - return (self.capacity_results.get('Hmax', 0) / self.capacity_results.get('Ha', 1)) - minfs['Ha'] - - def constraint_fs_vertical(vars): - L, D = vars - return (self.capacity_results.get('Vmax', 0) / self.capacity_results.get('Va', 1)) - minfs['Va'] - - def constraint_lambda_min(vars): - L, D = vars - return (L/D) - lambdap_con[0] - - def constraint_lambda_max(vars): - L, D = vars - return lambdap_con[1] - (L/D) - - result = minimize( - weight_objective, - [self.dd['design']['L'], self.dd['design']['D']], - method='COBYLA', - constraints=[ - {'type': 'ineq', 'fun': constraint_fs_horizontal}, - {'type': 'ineq', 'fun': constraint_fs_vertical}, - {'type': 'ineq', 'fun': constraint_lambda_min}, - {'type': 'ineq', 'fun': constraint_lambda_max} - ], - bounds=bounds, - options={'rhobeg': 0.5, 'catol': 0.01, 'maxiter': 100} - ) - - # Update final geometry - endGeom = dict(zip(geomKeys, result.x)) - print('Optimized geometry:', endGeom) - self.dd['design'].update(endGeom) - - if 'suction' in anchType and not zlug_fix: - self.dd['design']['zlug'] = (2/3) * self.dd['design']['L'] - - self.getCapacityAnchor( - ground_conds=ground_conds, - Hm=Hm, - Vm=Vm, - thetam=thetam, - zlug=self.dd['design']['zlug'], - line_type=line_type, - d=d, - w=w, - plot=plot - ) - - print('\nFinal Optimized Anchor:') - print('Design:', self.dd['design']) - print('Capacity Results:', self.capacity_results) - - def getCombinedPlot(self): - ''' - Create a single plot showing the suction pile and the inverse catenary overlay in the same coordinate system. - ''' - from famodel.anchors.anchors_famodel_profile.capacity_load import getTransferLoad - from famodel.anchors.anchors_famodel_profile.capacity_plots import plot_suction - import numpy as np - import matplotlib.pyplot as plt - - if self.anchType.lower() != 'suction': - raise NotImplementedError("getCombinedPlot only supports suction piles for now.") - - # Extract key parameters - design = self.dd['design'] - D = design['D'] - L = design['L'] - zlug = design['zlug'] - soil_type = self.soil_type - soil_profile = self.dd['soil_properties'][soil_type] - z0 = soil_profile[0][0] - - Hm = self.loads['Hm'] - Vm = self.loads['Vm'] - thetam = self.loads.get('thetam', np.degrees(np.arctan2(Vm, Hm))) - - line_type = getattr(self, 'line_type', 'chain') - d = getattr(self, 'd', 0.16) - w = getattr(self, 'w', 5000.0) - - # Get inverse catenary path - result = getTransferLoad( - soil_profile, soil_type, np.sqrt(Hm**2 + Vm**2), thetam, zlug, line_type, d, w, plot=False - ) - drag_values = np.array(result['drag_values']) - depth_values = np.array(result['depth_values']) - depth_values = -depth_values[::-1] - Tm = result['Tm']; thetam = result['thetam'] - Ta = result['Ta']; thetaa = result['thetaa'] - - # Transform to suction pile coordinate system - x_start = D/2 + drag_values[0] - z_start = zlug - drag_transformed = x_start - drag_values - depth_transformed = z_start + (depth_values - depth_values[0]) - - # Set up plot - fig, ax = plt.subplots(figsize=(5, 5)) - - # Plot suction pile - plot_suction(soil_profile, soil_type, L, D, zlug=zlug, title='', ax=ax) - - # Overlay inverse catenary - ax.plot(drag_transformed, depth_transformed, color='b', lw=2.0, label='Inverse Catenary') - - # Annotate ends - ax.plot(drag_transformed[-1], depth_transformed[-1], 'ro', label='Mudline End') - ax.plot(drag_transformed[0], depth_transformed[0], 'go', label='Embedded End') - - n = 2e6 - # Add load vectors - ax.arrow(drag_transformed[-1], depth_transformed[-1], Tm*np.cos(np.deg2rad(thetam))/n, -Tm*np.sin(np.deg2rad(thetam))/n, - head_width=0.25, head_length=0.5, color='r', label='Mudline Load') - ax.arrow(drag_transformed[0], depth_transformed[0], Ta*np.cos(thetaa)/n, -Ta*np.sin(thetaa)/n, - head_width=0.25, head_length=0.5, color='g', label='Padeye Load') - - # Finalize plot - xmax = max(drag_transformed[-1] + D, 2*D) - ax.set_xlim(-D, xmax) - ax.set_title('Suction Pile with Inverse Catenary') - ax.legend() - ax.grid(True) - plt.tight_layout() - plt.show() diff --git a/famodel/anchors/anchors_famodel/__init__.py b/famodel/anchors/anchors_famodel/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/famodel/anchors/anchors_famodel/capacity_dandg.py b/famodel/anchors/anchors_famodel/capacity_dandg.py deleted file mode 100644 index 284c4339..00000000 --- a/famodel/anchors/anchors_famodel/capacity_dandg.py +++ /dev/null @@ -1,373 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from scipy.interpolate import interp1d -from scipy import linalg -import inspect - -################################### -#### Pile Geometry and Loading #### -################################### - -def getCapacityDandG(profile, L, D, zlug, V, H, plot=True): - ''' - Models a laterally loaded pile using the p-y method. The solution for - lateral displacements is obtained by solving the 4th order ODE, - EI*d4y/dz4 - V*d2y/dz2 + ky = 0 using the finite difference method. - EI*d4y/dz4 - V*d2y/dz2 + K*z*dy/dz + ky = 0 using the finite difference method. - - Assumes that EI remains constant with respect to curvature i.e. pile - material remains in the elastic region. - - Input: - ----- - profile - A 2D array of depths (m) and corresponding undrained shear strength(Pa) - Eg: array([[z1,UCS1],[z2,UCS2],[z3,UCS3]...]) - Use small values for Su (eg: 0.001) instead of zeros to avoid divisions - by zero but always start z at 0.0 - Example of a valid data point at the mudline is [0.0, 0.001] - L - Length of pile (m) - D - Outer diameter of pile (m) - V - Axial force at pile head (N) - H - Force at pile head (N) - M - Moment at pile head (N*m) - n - Number of elements (50 by default) - iterations - Number of iterations to repeat calculation in order obtain convergence of 'y' - (A better approach is to iterate until a predefined tolerance is achieved) - - Output: - ------ - y - Lateral displacement at each node, length = n + 5, (n+1) real nodes and 4 imaginary nodes - z - Vector of node locations along pile - resultsDandG- Dictionary with results - ''' - - # Extract optional keyword arguments - # ls = 'x' - - n = 50; iterations = 10; loc = 2 - - # Resistance factor - nhuc = 1; nhu = 0.3 - delta_r = 0.08 # Mean roughness height [m] - - # Convert L and D to floating point numbers to avoid rounding errors - L = float(L) - D = float(D) - t = (6.35 + D*20)/1e3 # Pile wall thickness (m), API RP2A-WSD - E = 200e9 # Elastic modulus of pile material (Pa) - rhows = 66.90e3 # Submerged steel specific weight (N/m3) - rhow = 10e3 # Water specific weight (N/m3) - - # Pile geometry - I = (np.pi/64.0)*(D**4 - (D - 2*t)**4) - EI = E*I - h = L/n # Element size - N = (n + 1) + 4 # (n+1) Real + 4 Imaginary nodes - - # Dry and wet mass of the pile - def PileWeight(Len, Dia, tw, rho): - Wp = ((np.pi/4)*(Dia**2 - (Dia - 2*tw)**2)*Len)*rho - return Wp - - # Array for displacements at nodes, including imaginary nodes. - y = np.ones(N)*(0.01*D) # An initial value of 0.01D was arbitrarily chosen - - # Initialize and assemble array/list of p-y curves at each real node - z = np.zeros(N) - py_funs = [] - k_secant = np.zeros(N) - DQ = [] - - for i in [0,1]: # Top two imaginary nodes - z[i] = (i - 2)*h - py_funs.append(0) - k_secant[i] = 0.0 - - for i in range(2,n+3): # Real nodes - z[i] = (i - 2)*h - # Extract rock profile data - zlug, f_UCS, f_Em = rock_profile(profile) - UCS, Em = f_UCS(z[i]), f_Em(z[i]) - py_funs.append(py_Reese(z[i], D, zlug, UCS, Em, plot=plot)) - k_secant[i] = py_funs[i](y[i])/y[i] - SCR = nhuc*Em/(UCS*(1 + nhu))*delta_r/D - alpha = 0.36*SCR - 0.0005 - fs = alpha*UCS - Dq = np.pi*D*fs*z[i] - DQ.append(Dq) - - for i in [n+3, n+4]: # Bottom two imaginary nodes - z[i] = (i - 2)*h - py_funs.append(0) - k_secant[i] = 0.0 - - # Track k_secant and current displacements - - y1 = np.linspace(-2.*D, 2.*D, 500) - if plot: - plt.plot(y1, py_funs[loc](y1)) - plt.xlabel('y (m)'), plt.ylabel('p (N/m)') - plt.grid(True) - - for j in range(iterations): - # if j == 0: print 'FD Solver started!' - y = fd_solver(n, N, h, EI, V, H, zlug, k_secant) - if plot: - plt.plot(y[loc], k_secant[loc]*y[loc]) - - for i in range(2, n+3): - k_secant[i] = py_funs[i](y[i])/y[i] - - # print(f'y_max = {max(y):.3f} m') - # print(f'rot_max = {np.rad2deg((y[2] - y[3])/h):.3f} deg') - - resultsDandG = {} - resultsDandG['Lateral displacement'] = y[2] - resultsDandG['Rotational displacement'] = np.rad2deg((y[2] - y[3])/h) - resultsDandG['Axial capacity'] = DQ[-1] - resultsDandG['Weight'] = PileWeight(L, D, t, (rhows + rhow)) - - return y[2:-2], z[2:-2], resultsDandG - -################# -#### Solvers #### -################# - -def fd_solver(n, N, h, EI, V, H, zlug, k_secant): - ''' - Solves the finite difference equations from 'py_analysis_1'. This function should be run iteratively for - non-linear p-y curves by updating 'k_secant' using 'y'. A single iteration is sufficient if the p-y curves - are linear. - - Input: - ----- - n - Number of elements - N - Total number of nodes - h - Element size - EI - Flexural rigidity of pile - V - Axial force at pile head - H - Shear at pile head/tip - M - Moment at pile head/tip - k_secant - Secant stiffness from p-y curves - - Output: - ------ - y - Lateral displacement at each node - ''' - M = H*zlug - - # Initialize and assemble matrix - X = np.zeros((N,N)) - - # (n+1) finite difference equations for (n+1) real nodes - for i in range(0,n+1): - X[i,i] = 1.0 - X[i,i+1] = -4.0 + V*h**2/EI - X[i,i+2] = 6.0 - 2*V*h**2/EI + k_secant[i+2]*h**4/EI - X[i,i+3] = -4.0 + V*h**2/EI - X[i,i+4] = 1.0 - - # Curvature at pile head - X[n+1,1] = 1.0 - X[n+1,2] = -2.0 - X[n+1,3] = 1.0 - - # Shear at pile head - X[n+2,0] = -1.0 - X[n+2,1] = 2.0 - V*h**2/EI - X[n+2,2] = 0.0 - X[n+2,3] = -2.0 + V*h**2/EI - X[n+2,4] = 1.0 - - # Curvature at pile tip - X[n+3,-2] = 1.0 - X[n+3,-3] = -2.0 - X[n+3,-4] = 1.0 - - # Shear at pile tip - X[n+4,-1] = 1.0 - X[n+4,-2] = -2.0 + V*h**2/EI - X[n+4,-3] = 0.0 - X[n+4,-4] = 2.0 - V*h**2/EI - X[n+4,-5] = -1.0 - - # Initialize vector q - q = np.zeros(N) - - # Populate q with boundary conditions - q[-3] = 2*H*h**3 # Shear at pile head - # q[-4] = M*h**2 # Moment at pile head - - y = linalg.solve(EI*X, q) - - return y - -############################### -#### P-Y Curve Definitions #### -############################### - - -def py_Reese(z, D, zlug, UCS, Em, plot=True): - - ''' - Returns an interp1d interpolation function which represents the Reese (1997) p-y curve at the depth of interest. - - Important: Make sure to import the interp1 function by running 'from scipy.interpolate import interp1d' in the main program. - - Input: - ----- - z - Depth relative to pile head (m) - D - Pile diameter (m) - zlug - Load eccentricity above the mudline or depth to mudline relative to the pile head (m) - UCS - Undrained shear strength (Pa) - Em - Effectve vertical stress (Pa) - RQD - Rock quality designation, measures the quality of the rock core taken from a borehole. - Typically ranges from 25% (very weathered rock) to 100% (fresh rock). - - Output: - ------ - Returns an interp1d interpolation function which represents the p-y curve at the depth of interest. - 'p' (N/m) and 'y' (m). - ''' - z0 = 0 - - #from scipy.interpolate import interp1d - #global var_Reese - - RQD = 69 # Assumed good rock quality (hard rock) - Dref = 0.305; nhu = 0.3; E = 200e9 - t = (6.35 + D*20)/1e3 # Pile wall thickness (m), API RP2A-WSD - I = np.pi*(D**4 - (D - 2*t)**4)/64.0 - EI = E*I - alpha = -0.00667*RQD + 1 - krm = 0.0005 - - if (z - z0) < 0: - p_ur = 0 - else: - if z < 3*D: - p_ur = alpha*UCS*D*(1 + 1.4*z/D) - #kir = (100 +400*z/(3*D)) - else: - p_ur = 5.2*alpha*UCS*D - #kir = 500 - - kir = (D/Dref)*2**(-2*nhu)*(EI/(Em*D**4))**0.284 - Kir = kir*Em - y_rm = krm*D - y_a = (p_ur/(2*y_rm**0.25*Kir))**1.333 - - # Normalized lateral displacement - N = 20 - y = np.concatenate((-np.logspace(5,-3,N),[0],np.logspace(-3,5,N))) - - p=[]; P=[]; - for i in range (len(y)): - if abs(y[i]) < y_a: - P = np.sign(y[i])*Kir*y[i] - elif abs(y[i]) > y_a: - P = min((p_ur/2)*(abs(y[i])/y_rm)**0.25,p_ur) - p.append(P) - - p = np.array(p).squeeze() - for j in range(len(y)): - if y[j] < 0: - p[j] = -1*p[j] - elif y[j] > 0: - p[j] = p[j] - - #var_Reese = inspect.currentframe().f_locals - - f = interp1d(y, p) # Interpolation function for p-y curve - if plot: - plt.plot(y, p) - plt.xlabel('y (m)') - plt.ylabel('p (N/m)'), - plt.title('PY Curves - Reese (1997)') - plt.grid(True) - plt.xlim([-0.03*D, 0.03*D]) - plt.ylim([min(p), max(p)]) - - return f # This is f (linear interpolation of y-p) - -####################### -#### Rock Profile ##### -####################### - -def rock_profile(profile): - ''' - Define the (weak) rock profile used by the p-y analyzer. Outputs 'interp1d' functions containing - UCS and Em profiles to be used by the p-y curve functions. - - Input: - ----- - profile - A 2D tuple in the following format: ([depth (m), UCS (MPa), Em (MPa), py-model]) - The soil profile should be defined relative to the pile/tower head (i.e. point of lateral load application) - so that any load eccentricities can be taken into account. An example soil profile is shown below. - Eg: array([[z0,UCS0,Em0, 'Reese'], - [z1,UCS1,Em1, 'Reese'], - [z2,UCS2,Em2, 'Reese'], - ...]) - *The current program cannot define layers with different p-y models. But it will added in the future. - - Output: - ------ - z0 - Depth of mudline relative to the pile head (m) - f_UCS - 'interp1d' function containing undrained shear strength profile (Pa) - f_Em - 'interp1d' function containing effective vertical stress profile (Pa) - ''' - - # Depth of mudline relative to pile head - z0 = float(profile[0][0]) - - # Extract data from soil_profile array and zero strength virtual soil layer - # from the pile head down to the mudline - depth = np.concatenate([np.array([z0]),np.array([row[0] for row in profile],dtype=float)]) # m - UCS = np.concatenate([np.array([0]), np.array([row[1] for row in profile],dtype=float)]) # MPa - Em = np.concatenate([np.array([0]), np.array([row[2] for row in profile],dtype=float)]) # MPa - - # Define interpolation functions - f_UCS = interp1d(depth, UCS*1e6, kind='linear') # Pa - f_Em = interp1d(depth, Em*1e6, kind='linear') # Pa - - #var_rock_profile = inspect.currentframe().f_locals - - return z0, f_UCS, f_Em - -if __name__ == '__main__': - - profile = np.array([[0.0, 5, 7, 'Name of p-y model'], - [25.0, 5, 7, 'Name of p-y model']]) - - L = 15 - D = 1 - zlug = 0 - H0 = 318763.5 - V0 = 297554.3 - - H = 1e4; V = 1e4 - - values_H =[]; values_V =[] - - y, z, results = getCapacityDandG(profile, L=L, D=D, zlug=zlug, V=V0, H=H0) - - while results['Lateral displacement']< 0.05*D and results['Rotational displacement'] < 0.25: - - y, z, results = getCapacityDandG(profile, L=L, D=D, zlug=zlug, V=V, H=H) - - H += 10000 - - values_H.append(H); H_ratio = np.array(values_H)/H0 - - y0 = np.zeros(len(z)) - #Plot deflection profile of pile - fig, ax = plt.subplots(figsize=(3,5)) - ax.plot(y0,z,'black') - ax.plot(y,z,'r') - ax.set_xlabel('Displacement [m]') - ax.set_ylabel('Depth below pile head [m]') - ax.set_ylim([L + 2, -2]) - ax.set_xlim([-0.1*D, 0.1*D]) - ax.grid(ls='--') - fig.show() \ No newline at end of file diff --git a/famodel/anchors/anchors_famodel_map/capacity_dandg_map.py b/famodel/anchors/anchors_famodel/capacity_drilled.py similarity index 85% rename from famodel/anchors/anchors_famodel_map/capacity_dandg_map.py rename to famodel/anchors/anchors_famodel/capacity_drilled.py index aafc2af4..929e2af5 100644 --- a/famodel/anchors/anchors_famodel_map/capacity_dandg_map.py +++ b/famodel/anchors/anchors_famodel/capacity_drilled.py @@ -1,12 +1,12 @@ import numpy as np import matplotlib.pyplot as plt -from .capacity_soils_map import rock_profile -from .capacity_solvers import fd_solver -from .capacity_pycurves_map import py_Lovera -from .capacity_plots_map import plot_pile, plot_pycurve +from .support_soils import rock_profile +from .support_solvers import fd_solver +from .support_pycurves import py_Lovera +from .support_plots import plot_pile, plot_pycurve -def getCapacityDandG(profile_map, location_name, L, D, zlug, Ha, Va, plot=True): +def getCapacityDrilled(profile_map, location_name, L, D, zlug, Ha, Va, plot=False, display=0): '''Models a laterally loaded pile using the p-y method. The solution for lateral displacements is obtained by solving the 4th order ODE, EI*d4y/dz4 - V*d2y/dz2 + ky = 0 using the finite difference method. @@ -96,7 +96,7 @@ def PileWeight(Len, Dia, tw, rho): DQ.append(0.0) continue - profile = [[matched_layer['top'], matched_layer['UCS_top'], matched_layer['Em_top']], + profile = [[matched_layer['top'], matched_layer['UCS_top'], matched_layer['Em_top']], [matched_layer['bottom'], matched_layer['UCS_bot'], matched_layer['Em_bot']]] z0_local, f_UCS, f_Em = rock_profile(profile) @@ -108,7 +108,7 @@ def PileWeight(Len, Dia, tw, rho): UCS = f_UCS(z_depth) Em = f_Em(z_depth) - py_f, (y_vals, p_vals) = py_Lovera(z_depth, D, f_UCS, f_Em, zlug, z0, return_curve=True) + py_f, (y_vals, p_vals) = py_Lovera(z_depth, D, UCS, Em, zlug, z0, return_curve=True) py_funs.append(py_f) pycurve_data.append((y_vals, p_vals, z_depth, 'rock')) # print(f"z_depth = {z_depth:.2f} m, UCS = {f_UCS(z_depth):.2e} Pa, Em = {f_Em(z_depth):.2e} Pa") @@ -141,10 +141,10 @@ def PileWeight(Len, Dia, tw, rho): # Check convergence if np.linalg.norm(y - y_old, ord=2) < tol: - print(f'[Converged in {j+1} iterations]') + if display > 0: print(f'[Converged in {j+1} iterations]') break else: - print('[Warning: Solver did not converge]') + if display > 0: print('[Warning: Solver did not converge]') if plot: @@ -164,22 +164,23 @@ def PileWeight(Len, Dia, tw, rho): ax.legend() # Relevant index of nodes - zlug_index = int(zlug/h); print(zlug_index) - ymax_index = np.argmax(y); print(ymax_index) + zlug_index = int(zlug/h) + if display > 0: print(zlug_index) + ymax_index = np.argmax(y) + if display > 0: print(ymax_index) resultsDandG = { - 'Weight pile': PileWeight(L, D, t, rhows + rhow), 'Vertical max.': Vmax, 'Lateral displacement': y[ymax_index], 'Rotational displacement': np.rad2deg(abs(y[ymax_index - 1] - y[ymax_index])/h), - 'Unity check (vertical)': Va/Vmax if Vmax != 0 else np.inf, - 'Unity check (horizontal)': 0.0, # Placeholder; no Mp or Mi in current model 'Bending moment': None, 'Plastic moment': None, 'Plastic hinge': None, - 'Hinge location': None, - 'p-y model': 'Lovera (2023)', - } + 'Hinge location': None, + 'Unity check (vertical)': Va/Vmax if Vmax != 0 else np.inf, + 'Unity check (horizontal)': 0.0, # Placeholder; no Mp or Mi in current model + 'Weight pile': PileWeight(L, D, t, rhows + rhow), + 'p-y model': 'Lovera (2023)'} return layers, y[2:-2], z[2:-2], resultsDandG @@ -194,19 +195,19 @@ def PileWeight(Len, Dia, tw, rho): { 'top': 2.0, 'bottom': 5.0, 'soil_type': 'rock', - 'UCS_top': 1.0, 'UCS_bot': 2.0, # MPa + 'UCS_top': 8.0, 'UCS_bot': 8.0, # MPa 'Em_top': 100, 'Em_bot': 200 # MPa }, { 'top': 5.0, 'bottom': 9.0, 'soil_type': 'rock', - 'UCS_top': 2.0, 'UCS_bot': 3.0, # MPa + 'UCS_top': 10.0, 'UCS_bot': 10.0, # MPa 'Em_top': 200, 'Em_bot': 300 # MPa }, { 'top': 9.0, 'bottom': 30.0, 'soil_type': 'rock', - 'UCS_top': 3.0, 'UCS_bot': 6.0, # MPa + 'UCS_top': 20.0, 'UCS_bot': 20.0, # MPa 'Em_top': 300, 'Em_bot': 400 # MPa } ] @@ -216,12 +217,12 @@ def PileWeight(Len, Dia, tw, rho): D = 3.0 # Diameter (m) L = 10.0 # Length (m) zlug = 1 # Padeye elevation (m) - Ha = 8.0e6 # Horizontal load (N) - Va = 3.0e6 # Vertical load (N) + Ha = 5.0e6 # Horizontal load (N) + Va = 3.0e5 # Vertical load (N) - layers, y, z, results = getCapacityDandG(profile_map, 'CPT_rock_1', L, D, zlug, Ha, Va, plot=True) + layers, y, z, results = getCapacityDrilled(profile_map, 'CPT_rock_1', L, D, zlug, Ha, Va, plot=True, display=0) - print('\n--- Results for DandG Pile in Layered Rock ---') + print('\n--- Results for Drilled Pile in Layered Rock ---') for key, val in results.items(): print(f'{key}: {val:.3f}' if isinstance(val, float) else f'{key}: {val}') diff --git a/famodel/anchors/anchors_famodel_map/capacity_driven_map.py b/famodel/anchors/anchors_famodel/capacity_driven.py similarity index 79% rename from famodel/anchors/anchors_famodel_map/capacity_driven_map.py rename to famodel/anchors/anchors_famodel/capacity_driven.py index cd7c58ee..83961540 100644 --- a/famodel/anchors/anchors_famodel_map/capacity_driven_map.py +++ b/famodel/anchors/anchors_famodel/capacity_driven.py @@ -1,12 +1,12 @@ import numpy as np import matplotlib.pyplot as plt -from .capacity_soils_map import clay_profile, sand_profile, rock_profile -from .capacity_solvers import fd_solver -from .capacity_pycurves_map import py_Matlock, py_API, py_Reese -from .capacity_plots_map import plot_pile, plot_pycurve +from .support_soils import clay_profile, sand_profile, rock_profile +from .support_solvers import fd_solver +from .support_pycurves import py_Matlock, py_API, py_Reese +from .support_plots import plot_pile, plot_pycurve -def getCapacityDriven(profile_map, location_name, D, L, zlug, Ha, Va, plot=True): +def getCapacityDriven(profile_map, location_name, D, L, zlug, Ha, Va, plot=False, display=0): '''Models a laterally loaded pile using the p-y method. The solution for lateral displacements is obtained by solving the 4th order ODE, EI*d4y/dz4 EI*d4y/dz4 - V*d2y/dz2 + ky = 0 using the finite difference method. @@ -51,7 +51,7 @@ def getCapacityDriven(profile_map, location_name, D, L, zlug, Ha, Va, plot=True) layers = profile_entry['layers'] n = 50; loc = 2 # Number of nodes (-) - tol = 1e-16; max_iter = 50 # Iteration parameters (-) + tol = 1e-16; max_iter = 100 # Iteration parameters (-) nhuc = 1; nhu = 0.3 # Resistance factor (-) delta_r = 0.08 # Mean roughness height (m) @@ -101,9 +101,9 @@ def SoilWeight(Len, Dia, tw, gamma_soil): continue soil_type = matched_layer['soil_type'] - + if soil_type == 'clay': - profile = [[matched_layer['top'], matched_layer['Su_top'], matched_layer['gamma_top']], + profile = [[matched_layer['top'], matched_layer['Su_top'], matched_layer['gamma_top']], [matched_layer['bottom'], matched_layer['Su_bot'], matched_layer['gamma_bot']]] z0_local, f_Su, f_sigma_v_eff, f_gamma, f_alpha = clay_profile(profile) if z_depth < z0_local: @@ -115,7 +115,7 @@ def SoilWeight(Len, Dia, tw, gamma_soil): sigma_v_eff = f_sigma_v_eff(z_depth) gamma = f_gamma(z_depth) alpha = f_alpha(z_depth) - py_f, (y_vals, p_vals) = py_Matlock(z_depth, D, zlug, f_Su, f_sigma_v_eff, f_gamma, z0=z0_local, return_curve=True) + py_f, (y_vals, p_vals) = py_Matlock(z_depth, D, gamma, Su, sigma_v_eff, z0=z0_local, return_curve=True) py_funs.append(py_f) pycurve_data.append((y_vals, p_vals, z_depth, 'clay')) Vo = np.pi*D*alpha*Su*z_depth**2 @@ -124,7 +124,7 @@ def SoilWeight(Len, Dia, tw, gamma_soil): k_secant[i] = k_val/y[i] if y[i] != 0 else 0.0 elif soil_type == 'sand': - profile = [[matched_layer['top'], matched_layer['phi_top'], matched_layer['gamma_top'], matched_layer['Dr_top']], + profile = [[matched_layer['top'], matched_layer['phi_top'], matched_layer['gamma_top'], matched_layer['Dr_top']], [matched_layer['bottom'], matched_layer['phi_bot'], matched_layer['gamma_bot'], matched_layer['Dr_bot']]] z0_local, f_phi, f_sigma_v_eff, f_gamma, f_Dr, f_delta = sand_profile(profile) if z_depth < z0_local: @@ -132,9 +132,11 @@ def SoilWeight(Len, Dia, tw, gamma_soil): k_secant[i] = 0.0 PileShaft.append(0.0) continue + phi = f_phi(z_depth) sigma_v_eff = f_sigma_v_eff(z_depth) + Dr = f_Dr(z_depth) delta = f_delta(z_depth) - py_f, (y_vals, p_vals) = py_API(z_depth, D, zlug, f_phi, f_sigma_v_eff, f_Dr, z0=z0_local, return_curve=True) + py_f, (y_vals, p_vals) = py_API(z_depth, D, phi, sigma_v_eff, Dr, z0=z0_local, return_curve=True) py_funs.append(py_f) pycurve_data.append((y_vals, p_vals, z_depth, 'sand')) fs = delta * sigma_v_eff @@ -144,7 +146,7 @@ def SoilWeight(Len, Dia, tw, gamma_soil): k_secant[i] = k_val/y[i] if y[i] != 0 else 0.0 elif soil_type in ['rock', 'weak_rock']: - profile = [[matched_layer['top'], matched_layer['UCS_top'], matched_layer['Em_top']], + profile = [[matched_layer['top'], matched_layer['UCS_top'], matched_layer['Em_top']], [matched_layer['bottom'], matched_layer['UCS_bot'], matched_layer['Em_bot']]] z0_local, f_UCS, f_Em = rock_profile(profile) if z_depth < z0_local: @@ -154,7 +156,7 @@ def SoilWeight(Len, Dia, tw, gamma_soil): continue UCS = f_UCS(z_depth) Em = f_Em(z_depth) - py_f, (y_vals, p_vals) = py_Reese(z_depth, D, zlug, f_UCS, f_Em, z0=z0_local, return_curve=True) + py_f, (y_vals, p_vals) = py_Reese(z_depth, D, UCS, Em, z0=z0_local, return_curve=True) py_funs.append(py_f) pycurve_data.append((y_vals, p_vals, z_depth, 'rock')) SCR = nhuc*Em/(UCS*(1 + nhu))*delta_r/D @@ -166,7 +168,7 @@ def SoilWeight(Len, Dia, tw, gamma_soil): k_secant[i] = k_val/y[i] if y[i] != 0 else 0.0 else: - raise ValueError(f"Unsupported soil type: {matched_layer['soil_type']}") + raise ValueError(f"Unsupported soil type: {matched_layer.get('soil_type')} at depth z = {z_depth:.2f} m") for i in [n+3, n+4]: z[i] = (i - 2)*h @@ -194,10 +196,10 @@ def SoilWeight(Len, Dia, tw, gamma_soil): # Check convergence if np.linalg.norm(y - y_old, ord=2) < tol: - print(f'[Converged in {j+1} iterations]') + if display > 0: print(f'[Converged in {j+1} iterations]') break else: - print('[Warning: Solver did not converge]') + if display > 0: print('[Warning: Solver did not converge]') if plot: plot_pycurve(pycurve_data) @@ -216,22 +218,25 @@ def SoilWeight(Len, Dia, tw, gamma_soil): ax.legend() # Relevant index of nodes - zlug_index = int(zlug/h) - ymax_index = np.argmax(y) + y_pile = y[2:-2] + z_pile = z[2:-2] + ymax_index = np.argmax(np.abs(y_pile)) resultsDriven = { - 'Weight': PileWeight(L, D, t, rhows + rhow), + 'Horizontal max.': abs(Mi)/abs(zlug) if zlug != 0 else 1e-6, 'Vertical max.': Vmax, - 'Lateral displacement': y[ymax_index], - 'Rotational displacement': np.rad2deg(abs(y[ymax_index - 1] - y[ymax_index])/h), + 'Lateral displacement': y_pile[ymax_index], + 'Rotational displacement': np.rad2deg(abs(y_pile[ymax_index - 1] - y_pile[ymax_index])/h), 'Bending moment': abs(Mi), 'Plastic moment': Mp, 'Plastic hinge': hinge_formed, - 'Hinge location': hinge_location, - 'Horizontal max.': abs(Mi)/abs(zlug) if zlug != 0 else 1e-6, + 'Hinge location': hinge_location, 'Unity check (vertical)': Va/Vmax if Vmax != 0 else np.inf, - 'Unity check (horizontal)': Ha/(abs(Mi)/abs(zlug)) if zlug != 0 else np.inf - } + 'Unity check (horizontal)': Ha/(abs(Mi)/abs(zlug)) if zlug != 0 else np.inf, + 'Weight pile': PileWeight(L, D, t, rhows + rhow)} + + if display > 0: print(f"Max lateral displacement: {y_pile[ymax_index]:.6f} m at z = {z_pile[ymax_index]:.2f} m") + if display > 0: print(f"Deflected tip: {y_pile[-1]:.6f} m at z = {z_pile[-1]:.2f} m") return layers, y[2:-2], z[2:-2], resultsDriven @@ -246,28 +251,33 @@ def SoilWeight(Len, Dia, tw, gamma_soil): 'top': 1.0, 'bottom': 6.0, 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 8.0, - 'Su_top': 60, 'Su_bot': 200}, - # { - # 'top': 6.0, 'bottom': 15.0, - # 'soil_type': 'clay', - # 'gamma_top': 8.0, 'gamma_bot': 8.0, - # 'Su_top': 200, 'Su_bot': 400}, + 'Su_top': 60, 'Su_bot': 80}, { 'top': 6.0, 'bottom': 15.0, - 'soil_type': 'sand', + 'soil_type': 'clay', 'gamma_top': 8.0, 'gamma_bot': 8.0, - 'phi_top': 32, 'phi_bot': 38, - 'Dr_top': 70, 'Dr_bot': 75}, + 'Su_top': 80, 'Su_bot': 400}, + # { + # 'top': 6.0, 'bottom': 15.0, + # 'soil_type': 'sand', + # 'gamma_top': 8.0, 'gamma_bot': 8.0, + # 'phi_top': 32, 'phi_bot': 38, + # 'Dr_top': 70, 'Dr_bot': 75}, { 'top': 15.0, 'bottom': 30.0, 'soil_type': 'clay', - 'gamma_top': 8.0, 'gamma_bot': 9.0, + 'gamma_top': 8.0, 'gamma_bot': 8.0, 'Su_top': 200, 'Su_bot': 400}] + # { + # 'top': 0.0, 'bottom': 30.0, + # 'soil_type': 'rock', + # 'UCS_top': 5.0, 'UCS_bot': 5.0, + # 'Em_top': 7.0, 'Em_bot': 7.0}] } ] D = 2.5 # Diameter (m) - L = 25.0 # Length (m) + L = 15.0 # Length (m) zlug = 3 # Padeye depth (m) Ha = 5.0e5 # Horizontal load (N) Va = 1.5e5 # Vertical load (N) diff --git a/famodel/anchors/anchors_famodel/capacity_drivenrock.py b/famodel/anchors/anchors_famodel/capacity_drivenrock.py deleted file mode 100644 index d44f6e2f..00000000 --- a/famodel/anchors/anchors_famodel/capacity_drivenrock.py +++ /dev/null @@ -1,373 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from scipy.interpolate import interp1d -from scipy import linalg -import inspect - -################################### -#### Pile Geometry and Loading #### -################################### - -def getCapacityDrivenRock(profile, L, D, zlug, V, H, plot=True): - ''' - Models a laterally loaded pile using the p-y method. The solution for - lateral displacements is obtained by solving the 4th order ODE, - EI*d4y/dz4 - V*d2y/dz2 + ky = 0 using the finite difference method. - EI*d4y/dz4 - V*d2y/dz2 + K*z*dy/dz + ky = 0 using the finite difference method. - - Assumes that EI remains constant with respect to curvature i.e. pile - material remains in the elastic region. - - Input: - ----- - profile - A 2D array of depths (m) and corresponding undrained shear strength(Pa) - Eg: array([[z1,UCS1],[z2,UCS2],[z3,UCS3]...]) - Use small values for Su (eg: 0.001) instead of zeros to avoid divisions - by zero but always start z at 0.0 - Example of a valid data point at the mudline is [0.0, 0.001] - L - Length of pile (m) - D - Outer diameter of pile (m) - V - Axial force at pile head (N) - H - Force at pile head (N) - M - Moment at pile head (N*m) - n - Number of elements (50 by default) - iterations - Number of iterations to repeat calculation in order obtain convergence of 'y' - (A better approach is to iterate until a predefined tolerance is achieved) - - Output: - ------ - y - Lateral displacement at each node, length = n + 5, (n+1) real nodes and 4 imaginary nodes - z - Vector of node locations along pile - resultsDrivenRock - Dictionary with results - ''' - - # Extract optional keyword arguments - # ls = 'x' - n = 50; iterations = 10; loc = 2 - - # Resistance factor - nhuc = 1; nhu = 0.3 - delta_r = 0.08 # Mean roughness height [m] - - # Convert L and D to floating point numbers to avoid rounding errors - L = float(L) - D = float(D) - t = (6.35 + D*20)/1e3 # Pile wall thickness (m), API RP2A-WSD - E = 200e9 # Elastic modulus of pile material (Pa) - rhows = 66.90e3 # Submerged steel specific weight (N/m3) - rhow = 10e3 # Water specific weight (N/m3) - - # Pile geometry - I = (np.pi/64.0)*(D**4 - (D - 2*t)**4) - EI = E*I - h = L/n # Element size - N = (n + 1) + 4 # (n+1) Real + 4 Imaginary nodes - - # Dry and wet mass of the pile - def PileWeight(Len, Dia, tw, rho): - Wp = ((np.pi/4)*(Dia**2 - (Dia - 2*tw)**2)*Len)*rho - return Wp - - # Array for displacements at nodes, including imaginary nodes. - y = np.ones(N)*(0.01*D) # An initial value of 0.01D was arbitrarily chosen - - # Initialize and assemble array/list of p-y curves at each real node - z = np.zeros(N) - py_funs = [] - k_secant = np.zeros(N) - DQ = [] - - for i in [0,1]: # Top two imaginary nodes - z[i] = (i - 2)*h - py_funs.append(0) - k_secant[i] = 0.0 - - for i in range(2,n+3): # Real nodes - z[i] = (i - 2)*h - # Extract rock profile data - zlug, f_UCS, f_Em = rock_profile(profile) - UCS, Em = f_UCS(z[i]), f_Em(z[i]) - py_funs.append(py_Reese(z[i], D, zlug, UCS, Em)) - k_secant[i] = py_funs[i](y[i])/y[i] - SCR = nhuc*Em/(UCS*(1 + nhu))*delta_r/D - alpha = 0.36*SCR - 0.0005 - fs = alpha*UCS - Dq = np.pi*D*fs*z[i] - DQ.append(Dq) - - for i in [n+3, n+4]: # Bottom two imaginary nodes - z[i] = (i - 2)*h - py_funs.append(0) - k_secant[i] = 0.0 - - # Track k_secant and current displacements - - y1 = np.linspace(-2.*D, 2.*D, 500) - if plot: - plt.plot(y1, py_funs[loc](y1)) - plt.xlabel('y (m)'), plt.ylabel('p (N/m)') - plt.grid(True) - - for j in range(iterations): - # if j == 0: print 'FD Solver started!' - y = fd_solver(n, N, h, EI, V, H, zlug, k_secant) - - if plot: - plt.plot(y[loc], k_secant[loc]*y[loc]) - - for i in range(2, n+3): - k_secant[i] = py_funs[i](y[i])/y[i] - - # print(f'y_max = {y[2]:.3f} m') - # print(f'rot_max = {np.rad2deg((y[2] - y[3])/h):.3f} deg') - - resultsDrivenRock = {} - resultsDrivenRock['Lateral displacement'] = y[2] - resultsDrivenRock['Rotational displacement'] = np.rad2deg((y[2] - y[3])/h) - resultsDrivenRock['Axial capacity'] = DQ[-1] - resultsDrivenRock['Weight'] = PileWeight(L, D, t, (rhows + rhow)) - - return y[2:-2], z[2:-2], resultsDrivenRock - -################# -#### Solvers #### -################# - -def fd_solver(n, N, h, EI, V, H, zlug, k_secant): - ''' - Solves the finite difference equations from 'py_analysis_1'. This function should be run iteratively for - non-linear p-y curves by updating 'k_secant' using 'y'. A single iteration is sufficient if the p-y curves - are linear. - - Input: - ----- - n - Number of elements - N - Total number of nodes - h - Element size - EI - Flexural rigidity of pile - V - Axial force at pile head - H - Shear at pile head/tip - M - Moment at pile head/tip - k_secant - Secant stiffness from p-y curves - - Output: - ------ - y - Lateral displacement at each node - ''' - M = H*zlug - - # Initialize and assemble matrix - X = np.zeros((N,N)) - - # (n+1) finite difference equations for (n+1) real nodes - for i in range(0,n+1): - X[i,i] = 1.0 - X[i,i+1] = -4.0 + V*h**2/EI - X[i,i+2] = 6.0 - 2*V*h**2/EI + k_secant[i+2]*h**4/EI - X[i,i+3] = -4.0 + V*h**2/EI - X[i,i+4] = 1.0 - - # Curvature at pile head - X[n+1,1] = 1.0 - X[n+1,2] = -2.0 - X[n+1,3] = 1.0 - - # Shear at pile head - X[n+2,0] = -1.0 - X[n+2,1] = 2.0 - V*h**2/EI - X[n+2,2] = 0.0 - X[n+2,3] = -2.0 + V*h**2/EI - X[n+2,4] = 1.0 - - # Curvature at pile tip - X[n+3,-2] = 1.0 - X[n+3,-3] = -2.0 - X[n+3,-4] = 1.0 - - # Shear at pile tip - X[n+4,-1] = 1.0 - X[n+4,-2] = -2.0 + V*h**2/EI - X[n+4,-3] = 0.0 - X[n+4,-4] = 2.0 - V*h**2/EI - X[n+4,-5] = -1.0 - - # Initialize vector q - q = np.zeros(N) - - # Populate q with boundary conditions - q[-3] = 2*H*h**3 # Shear at pile head - # q[-4] = M*h**2 # Moment at pile head - - y = linalg.solve(EI*X, q) - - return y - -############################### -#### P-Y Curve Definitions #### -############################### - -def py_Reese(z, D, zlug, UCS, Em): - ''' - Returns an interp1d interpolation function which represents the Reese (1997) p-y curve at the depth of interest. - - Important: Make sure to import the interp1 function by running 'from scipy.interpolate import interp1d' in the main program. - - Input: - ----- - z - Depth relative to pile head (m) - D - Pile diameter (m) - zlug - Load eccentricity above the mudline or depth to mudline relative to the pile head (m) - UCS - Undrained shear strength (Pa) - Em - Effectve vertical stress (Pa) - RQD - Rock quality designation, measures the quality of the rock core taken from a borehole. - Typically ranges from 25% (very weathered rock) to 100% (fresh rock). - - Output: - ------ - Returns an interp1d interpolation function which represents the p-y curve at the depth of interest. - 'p' (N/m) and 'y' (m). - ''' - z0 = 0 - - #from scipy.interpolate import interp1d - #global var_Reese - - RQD = 52 # Assumed fair rock quality (moderately weathered rocks) - Dref = 0.305; nhu = 0.3; E = 200e9 - t = (6.35 + D*20)/1e3 # Pile wall thickness (m), API RP2A-WSD - I = np.pi*(D**4 - (D - 2*t)**4)/64.0 - EI = E*I - alpha = -0.00667*RQD + 1 - krm = 0.0005 - - if (z - z0) < 0: - p_ur = 0 - else: - if z < 3*D: - p_ur = alpha*UCS*D*(1 + 1.4*z/D) - #kir = (100 +400*z/(3*D)) - else: - p_ur = 5.2*alpha*UCS*D - #kir = 500 - - kir = (D/Dref)*2**(-2*nhu)*(EI/(Em*D**4))**0.284 - Kir = kir*Em - y_rm = krm*D - y_a = (p_ur/(2*y_rm**0.25*Kir))**1.333 - - # Normalized lateral displacement - N = 20 - y = np.concatenate((-np.logspace(5,-3,N),[0],np.logspace(-3,5,N))) - - p=[]; P=[]; - for i in range (len(y)): - if abs(y[i]) < y_a: - P = np.sign(y[i])*Kir*y[i] - elif abs(y[i]) > y_a: - P = min((p_ur/2)*(abs(y[i])/y_rm)**0.25,p_ur) - p.append(P) - - p = np.array(p).squeeze() - for j in range(len(y)): - if y[j] < 0: - p[j] = -1*p[j] - elif y[j] > 0: - p[j] = p[j] - - #var_Reese = inspect.currentframe().f_locals - - f = interp1d(y, p) # Interpolation function for p-y curve - - plt.plot(y, p) - plt.xlabel('y (m)') - plt.ylabel('p (N/m)'), - plt.title('PY Curves - Reese (1997)') - plt.grid(True) - plt.xlim([-0.03*D, 0.03*D]) - plt.ylim([min(p), max(p)]) - - return f # This is f (linear interpolation of y-p) - -####################### -#### Rock Profile ##### -####################### - -def rock_profile(profile): - ''' - Define the (weak) rock profile used by the p-y analyzer. Outputs 'interp1d' functions containing - UCS and Em profiles to be used by the p-y curve functions. - - Input: - ----- - profile - A 2D tuple in the following format: ([depth (m), UCS (MPa), Em (MPa), py-model]) - The soil profile should be defined relative to the pile/tower head (i.e. point of lateral load application) - so that any load eccentricities can be taken into account. An example soil profile is shown below. - Eg: array([[z0,UCS0,Em0, 'Reese'], - [z1,UCS1,Em1, 'Reese'], - [z2,UCS2,Em2, 'Reese'], - ...]) - *The current program cannot define layers with different p-y models. But it will added in the future. - - plot_profile - Plot Su vs depth profile. Choose 'Yes' to plot. - - Output: - ------ - z0 - Depth of mudline relative to the pile head (m) - f_UCS - 'interp1d' function containing undrained shear strength profile (Pa) - f_Em - 'interp1d' function containing effective vertical stress profile (Pa) - ''' - - # Depth of mudline relative to pile head - z0 = float(profile[0][0]) - - # Extract data from soil_profile array and zero strength virtual soil layer - # from the pile head down to the mudline - depth = np.concatenate([np.array([z0]),np.array([row[0] for row in profile],dtype=float)]) # m - UCS = np.concatenate([np.array([0]), np.array([row[1] for row in profile],dtype=float)]) # MPa - Em = np.concatenate([np.array([0]), np.array([row[2] for row in profile],dtype=float)]) # MPa - - # Define interpolation functions - f_UCS = interp1d(depth, UCS*1e6, kind='linear') # Pa - f_Em = interp1d(depth, Em*1e6, kind='linear') # Pa - - #var_rock_profile = inspect.currentframe().f_locals - - return z0, f_UCS, f_Em - -if __name__ == '__main__': - - profile = np.array([[0.0, 5, 7, 'Name of p-y model'], - [25.0, 5, 7, 'Name of p-y model']]) - - L = 20 - D = 1.5 - zlug = 2*D - H0 = 3187635 - V0 = 2975543 - - H = 1e4; V = 1e4 - - values_H =[]; values_V =[] - - y, z, results = getCapacityDrivenRock(profile, L=L, D=D, zlug=zlug, V=V0, H=H0) - - while results['Lateral displacement']< 0.05*D and results['Rotational displacement'] < 0.25: - - y, z, results = getCapacityDrivenRock(profile, L=L, D=D, zlug=zlug, V=V, H=H) - - H += 10000 - - values_H.append(H); H_ratio = np.array(values_H)/H0 - - y0 = np.zeros(len(z)) - #Plot deflection profile of pile - fig, ax = plt.subplots(figsize=(3,5)) - ax.plot(y0,z,'black') - ax.plot(y,z,'r') - ax.set_xlabel('Displacement [m]') - ax.set_ylabel('Depth below pile head [m]') - ax.set_ylim([L + 2,-2]) - ax.set_xlim([-0.1*D, 0.1*D]) - ax.grid(ls='--') - fig.show() \ No newline at end of file diff --git a/famodel/anchors/anchors_famodel/capacity_drivensoil.py b/famodel/anchors/anchors_famodel/capacity_drivensoil.py deleted file mode 100644 index b4cee31c..00000000 --- a/famodel/anchors/anchors_famodel/capacity_drivensoil.py +++ /dev/null @@ -1,628 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt - -################################### -#### Pile Geometry and Loading #### -################################### - -def getCapacityDrivenSoil(profile, soil_type, L, D, zlug, V, H, plot=True): - - '''Models a laterally loaded pile using the p-y method. The solution for - lateral displacements is obtained by solving the 4th order ODE, EI*d4y/dz4 - - F*d2y/dz2 + ky = 0 using the finite difference method. - - Assumes that EI remains constant with respect to curvature i.e. pile - material remains in the elastic region. - - Input: - ----- - profile - A 2D array of depths (m) and corresponding undrained shear strength(Pa) - Eg: array([[z1,Su1],[z2,Su2],[z3,Su3]...]) - Use small values for Su (eg: 0.001) instead of zeros to avoid divisions by zero but always start z at 0.0 - Example of a valid data point at the mudline is [0.0, 0.001] - soil_type - Select soil condition, 'clay' or 'sand' - Assigns which p-y model to use, 'Matlock' or 'API'. - L - Length of pile (m) - D - Outer diameter of pile (m) - zlug - Load eccentricity above the mudline or depth to mudline relative to the pile head (m) - V - Axial force at pile head (N), vertically downwards is postive. - H - Force at pile head (N), shear causing clockwise rotation of pile is positive. - M - Moment at pile head (N*m), moments causing tension on left side of pile is positive. - n - Number of elements (50 by default) - iterations - Number of iterations to repeat calculation in order obtain convergence of 'y' - (A better approach is to iterate until a predefined tolerance is achieved but this requires additional - coding so, I will implement this later.) - - Output: - ------ - y - Lateral displacement at each node, length = n + 5, (n+1) real nodes and 4 imaginary nodes - z - Vector of node locations along pile - ''' - - # Extract optional keyword arguments - - ls = 'x' - n = 25; iterations = 10; loc=2 - - # Convert L and D to floating point numbers to avoid rounding errors - L = float(L) - D = float(D) - t = (6.35 + D*20)/1e3 # Pile wall thickness (m), API RP2A-WSD - E = 200e9 # Elastic modulus of pile material (Pa) - fy = 350e6 # Yield strength of pile material (Pa) - rhows = 66.90e3 # Submerged steel specific weight (N/m3) - rhow = 10e3 # Water specific weight (N/m3) - - # Pile geometry - I = (np.pi/64.0)*(D**4 - (D - 2*t)**4) - EI = E*I - h = L/n # Element size - N = (n + 1) + 4 # (n+1) Real + 4 Imaginary nodes - - # Outer and inner surface of the pile skirt - def PileSurface(Len, Dia): - Sp = np.pi*Dia*Len - return Sp - # Dry and wet mass of the pile - def PileWeight(Len, Dia, tw, rho): - Wp = ((np.pi/4)*(Dia**2 - (Dia - 2*tw)**2)*Len)*rho - return Wp - # Mass of the soil plug - def SoilWeight(Len, Dia, tw, gamma_soil): - Wsoil =(np.pi/4)*(Dia - 2*tw)**2*Len*gamma_soil - return Wsoil - - # Array for displacements at nodes, including imaginary nodes. - y = np.ones(N)*(0.01*D) # An initial value of 0.01D was arbitrarily chosen - - # Initialize and assemble array/list of p-y curves at each real node - z = np.zeros(N) - py_funs = []; PileShaft =[] - k_secant = np.zeros(N) - - for i in [0, 1]: # Top two imaginary nodes - z[i] = (i - 2)*h - py_funs.append(0) - k_secant[i] = 0.0 - - # Extract soil profile data - if soil_type == 'clay': - z0, f_Su, f_sigma_v_eff, f_gamma, f_alpha = clay_profile(profile) - - elif soil_type == 'sand': - z0, f_phi, f_sigma_v_eff, f_gamma, f_Dr, f_delta = sand_profile(profile) - - for i in range(2, n+3): # Real nodes - z[i] = (i - 2)*h - if soil_type == 'clay': - Su, sigma_v_eff, gamma, alpha = f_Su(z[i]), f_sigma_v_eff(z[i]), f_gamma(z[i]), f_alpha(z[i]) - py_funs.append(py_Matlock(z[i], D, zlug, Su, sigma_v_eff, gamma, plot=plot)) - Vo = np.pi*D*alpha*Su*z[i]**2 - PileShaft.append(Vo) - Vmax = PileWeight(L, D, t, rhows) + SoilWeight(L, D, t, gamma) + PileShaft[-1] - - elif soil_type == 'sand': - phi, sigma_v_eff, gamma, Dr, delta = f_phi(z[i]), f_sigma_v_eff(z[i]), f_gamma(z[i]), f_Dr(z[i]), f_delta(z[i]) - py_funs.append(py_API(z[i], D, zlug, phi, sigma_v_eff, Dr, plot=plot)) - fs = delta*sigma_v_eff - Vo = np.pi*D*fs*z[i] - PileShaft.append(Vo) - Vmax = PileWeight(L, D, t, rhows) + SoilWeight(L, D, t, gamma) + PileShaft[-1] - - k_secant[i] = py_funs[i](y[i])/y[i] - - for i in [n+3, n+4]: # Bottom two imaginary nodes - z[i] = (i - 2)*h - py_funs.append(0) - k_secant[i] = 0.0 - - y1 = np.linspace(-2.*D, 2.*D, 500) - if plot: - plt.plot(y1, py_funs[loc](y1)) - plt.xlabel('y (m)'), plt.ylabel('p (N/m)') - plt.grid(True) - - for j in range(iterations): - # if j == 0: print 'FD Solver started!' - y, Mi, Mp, hinge_formed, hinge_location = fd_solver(n, N, h, D, t, fy, EI, V, H, zlug, k_secant) - - for i in range(2, n+3): - k_secant[i] = py_funs[i](y[i])/y[i] - - - resultsDrivenSoil = {} - # Populate q with boundary conditions - if zlug <= 0: - # print(f'y_max = {max(y):.3f} m') - # print(f'rot_max = {np.rad2deg((y[2] - y[3])/h):.3f} deg') - - resultsDrivenSoil['Lateral displacement'] = max(y) - resultsDrivenSoil['Rotational displacement'] = np.rad2deg((y[2] - y[3])/h) - resultsDrivenSoil['Axial capacity'] = Vmax - resultsDrivenSoil['Pile weight'] = PileWeight(L, D, t, (rhows + rhow)) - - else: - # print(f'y_max = {max(y):.3f} m') - # print(f'Mi = {Mi:.3f} Nm') - - resultsDrivenSoil['Lateral displacement'] = max(y) - resultsDrivenSoil['Bending moment'] = Mi - resultsDrivenSoil['Plastic moment'] = Mp - resultsDrivenSoil['Plastic hinge'] = hinge_formed - resultsDrivenSoil['Hinge location'] = hinge_location - resultsDrivenSoil['Axial capacity'] = Vmax - resultsDrivenSoil['Weight'] = PileWeight(L, D, t, (rhows + rhow)) - - return y[2:-2], z[2:-2], resultsDrivenSoil - -################# -#### Solvers #### -################# - -def fd_solver(n, N, h, D, t, fy, EI, V, H, zlug, k_secant): - '''Solves the finite difference equations from 'py_analysis_1'. This function should be run iteratively for - non-linear p-y curves by updating 'k_secant' using 'y'. A single iteration is sufficient if the p-y curves - are linear. - - Input: - ----- - n - Number of elements - N - Total number of nodes - h - Element size - EI - Flexural rigidity of pile - V - Axial force at pile head/zlug depth - H - Shear at pile head/zlug depth - M - Moment at pile head/zlug depth - zlug - Load eccentricity above the mudline or depth to mudline relative to the pile head (m) - k_secant - Secant stiffness from p-y curves - - Output: - ------ - y_updated - Lateral displacement at each node - ''' - - from scipy import linalg - - # Identify the node corresponding to zlug - zlug_index = int(zlug/h) # Index for the node corresponding to zlug - - # Initialize and assemble matrix - X = np.zeros((N, N)) - - # (n+1) finite difference equations for (n+1) real nodes - for i in range(0, n+1): - X[i,i] = 1.0 - X[i,i+1] = -4.0 + V*h**2/EI - X[i,i+2] = 6.0 - 2*V*h**2/EI + k_secant[i+2]*h**4/EI - X[i,i+3] = -4.0 + V*h**2/EI - X[i,i+4] = 1.0 - - # Curvature at pile head - X[n+1,1] = 1.0 - X[n+1,2] = -2.0 - X[n+1,3] = 1.0 - - # Shear at pile head - X[n+2,0] = -1.0 - X[n+2,1] = 2.0 - V*h**2/EI - X[n+2,2] = 0.0 - X[n+2,3] = -2.0 + V*h**2/EI - X[n+2,4] = 1.0 - - # Curvature at pile tip - X[n+3,-2] = 1.0 - X[n+3,-3] = -2.0 - X[n+3,-4] = 1.0 - - # Shear at pile tip - X[n+4,-1] = 1.0 - X[n+4,-2] = -2.0 + V*h**2/EI - X[n+4,-3] = 0.0 - X[n+4,-4] = 2.0 - V*h**2/EI - X[n+4,-5] = -1.0 - - # Initialize vector q - q = np.zeros(N) - #M = H*abs(zlug) - - # Populate q with boundary conditions - if zlug <= 0: - q[-3] = 2*H*h**3 # Shear at pile head - #q[-4] = M*h**2 # Moment at pile head - else: - q[zlug_index] = 2*H*h**3 # Shear at pile head - #q[zlug_index + 1] = M*h**2 # Moment at pile head - - y = linalg.solve(EI*X, q) - - # Compute the plastic moment capacity Mp - Zp = (1/6)*(D**3 - (D - 2*t)**3) # Plastic section modulus for hollow pile (m3) - Mp = Zp*fy # Plastic moment capacity (N/m) - - # Check for plastic hinge formation - Mi, Mp, hinge_formed, hinge_location = plastic_hinge(y, h, EI, Mp) - - return y, Mi, Mp, hinge_formed, hinge_location - -############################### -#### P-Y Curve Definitions #### -############################### - -def py_Matlock(z, D, zlug, Su, sigma_v_eff, gamma, plot=True): - - '''Returns an interp1d interpolation function which represents the Matlock (1970) p-y curve at the depth of interest. - Important: Make sure to import the interp1 function by running 'from scipy.interpolate import interp1d' in the main program. - - Input: - ----- - z - Depth relative to pile head (m) - D - Pile diameter (m) - zlug - Load eccentricity above the mudline or depth to mudline relative to the pile head (m) - Su - Undrained shear strength (Pa) - sigma_v_eff - Effective vertical stress (Pa) - gamma - Effective unit weight of the soil (kN/m3) - - Output: - ------ - Returns an interp1d interpolation function which represents the p-y curve at the depth of interest. - 'p' (N/m) and 'y' (m). - ''' - - from scipy.interpolate import interp1d - - z0 = 0 - - # Strain at half the strength as defined by Matlock (1970). - # Typically ranges from 0.005 (stiff clay) to 0.02 (soft clay). - epsilon_50 = 0.02 - # p-y curve properties - J = 0.5 - - if zlug < 0: - # Scenario 1: zlug is negative (above mudline) - if (z - z0) < 0: - # No p-y curve between z = 0 and zlug - Nc = 0.0 - z_cr = 1.0 # Dummy value to avoid crashing - else: - # Calculate p-y curve below zlug - Nc = 3.0 + sigma_v_eff/Su + J*(z - abs(zlug))/D - if Nc > 9.0: - Nc = 9.0 - z_cr = 6.0*D/(gamma*D/Su + J) - - else: - # Scenario 2: zlug is positive (below mudline) - # Calculate p-y curve for the entire pile (all depths) - Nc = 3.0 + sigma_v_eff/Su + J*(z - zlug)/D - if Nc > 9.0: - Nc = 9.0 - z_cr = 6.0 * D/(gamma*D/Su + J) - - p_ult = Su*Nc*D - y_50 = 2.5*epsilon_50*D - - # Normalized lateral displacement - Y = np.concatenate((-np.logspace(3,-4,100),[0],np.logspace(-4,3,100))) - - # Normalized p-y curves - P = 0.5*np.sign(Y)*abs(Y)**(1.0/3.0) # sign(Y) and abs(Y) used since negative numbers cannot be raised to fractional powers - # Expression equivalent to P = 0.5*Y**(1.0/3.0) for Y>=0 - for i in range(0,len(Y)): - if P[i] > 1.0: P[i] = 1.0 - elif P[i] < -1.0: P[i] = -1.0 - - # Un-normallized p-y curves - p = P*p_ult - y = Y*y_50 - - f = interp1d(y, p, kind='linear') # Interpolation function for p-y curve - - # Plot of p-y curve and check if 'k' is calculated correctly - if plot: - plt.plot(y, p,'-') - plt.xlabel('y (m)') - plt.ylabel('p (N/m)') - plt.title('PY Curves - Matlock (1970)') - plt.grid(True) - plt.xlim([-2*D, 2*D]) - - return f # This is f (linear interpolation of y-p) - -def py_API(z, D, zlug, phi, sigma_v_eff, Dr, plot=True): - - '''Returns an interp1d interpolation function which represents the Matlock (1970) p-y curve at the depth of interest. - - Important: Make sure to import the interp1 function by running 'from scipy.interpolate import interp1d' in the main program. - - Input: - ----- - z - Depth relative to pile head (m) - D - Pile diameter (m) - zlug - Load eccentricity above the mudline or depth to mudline relative to the pile head (m) - phi - Internal friction angle (deg) - sigma_v_eff - Effectve vertical stress (Pa) - - Output: - ------ - Returns an interp1d interpolation function which represents the p-y curve at the depth of interest. - 'p' (N/m) and 'y' (m). - ''' - - from scipy.interpolate import interp1d - - # Interpolate coefficients depending on the effective friction angle - phi_ref = [ 20, 25, 30, 35, 40] - C1_ref = [0.80, 1.25, 1.90, 3.00, 4.50] - C2_ref = [1.60, 2.10, 2.60, 3.40, 4.30] - C3_ref = [ 10, 15, 30, 55, 105] - - C1 = np.interp(phi, phi_ref, C1_ref) - C2 = np.interp(phi, phi_ref, C2_ref) - C3 = np.interp(phi, phi_ref, C3_ref) - - if (z - zlug) < 0: - # p-y curves for the virtual soil layer between the pile head and the mudline should have p=0 - p_ult = 0.0 - else: - try: - p_ult = min(C1*z + C2*D, C3*D)*sigma_v_eff - except ZeroDivisionError: - print("Division by zero! phi = 0.0 so z_cr cannot be calculated.") - - # Dr = 0.75 # Relative density of the soil (assumed) - k = (54.6*Dr**2 + 0.8*Dr + 1.8)*1e3 - - # Normalized lateral displacement - N = 20 - y = np.concatenate((-np.logspace(3,-4,N),[0],np.logspace(-4,3,N))) - A = max(3 - 0.8*z/D, 0.9) - ε = 1e-6 - p = A*p_ult*np.tanh(k*z*y/(A*p_ult + ε)) - - f = interp1d(y, p, kind='linear') # Interpolation function for p-y curve - - if plot: - # Plot of p-y curve and check if 'k' is calculated correctly - plt.plot(y, p,'-') - plt.xlabel('y (m)') - plt.ylabel('p (N/m)') - plt.title('PY Curves - API (1993)') - plt.grid(True) - plt.xlim([-0.10*D, 0.10*D]) - # plt.ylim([min(y), max(y)]) # Adjust x-axis limits to match y values - - return f # This is f (linear interpolation of y-p) - -######################## -#### Plastic Hinge ##### -######################## - -def plastic_hinge(y, h, EI, Mp): - ''' - Check for plastic hinge formation along the pile. - - Parameters: - ---------- - y : ndarray - Lateral displacements at each node. - h : float - Element size (distance between nodes). - EI : float - Flexural rigidity of the pile (N*m²). - Mp : float - Plastic moment capacity of the pile section. - - Returns: - ------- - Mp : float - Plastic moment of the pile section (Nm) - hinge_formed : bool - True if a plastic hinge forms, False otherwise. - hinge_location : int - Index of the node where the plastic hinge forms (if any). - ''' - - hinge_formed = False - hinge_location = -1 - Mi = [] - - # Loop through each internal node and compute the bending moment - for i in range(1, len(y)-1): - # Approximate the bending moment at node i - Mint = EI*(y[i+1] - 2*y[i] + y[i-1])/h**2 - Mi.append(Mint) - - # Check if the moment exceeds the plastic moment capacity - if Mint >= Mp: - hinge_formed = True - hinge_location = i - break # Stop at the first plastic hinge formation - - return max(Mi), Mp, hinge_formed, hinge_location - - -######################## -#### Soil Profiles ##### -######################## - -def clay_profile(profile): - '''Define the clay profile used by the p-y analyzer. Outputs 'interp1d' functions containing Su and sigma'_v - profiles to be used by the p-y curve functions. - - Input: - ----- - profile - A 2D tuple in the following format: ([Depth (m), Su (kPa), gamma (kN/m^3), py-model, model parameter]) - The soil profile should be defined relative to the pile/tower head (i.e. point of lateral load application) - so that any load eccentricities can be taken into account. An example soil profile is shown below. - Eg: array([[z0, Su0, gamma0, 'Matlock', 0.02], - ...]) - - *The current program cannot define layers with different p-y models. But it will added in the future. - - Output: - ------ - z0 - Depth of mudline relative to the pile head (m) - f_Su - 'interp1d' function containing undrained shear strength profile (Pa) - f_sigma_v_eff - 'interp1d' function containing effective vertical stress profile (Pa) - f_gamma - 'interp1d' function containing effective unit weight (kN/m3) - f_alpha - Adhesion factor for clays - ''' - - from scipy.interpolate import interp1d - - # Depth of mudline relative to pile head - z0 = float(profile[0][0]) - - # Extract data from profile array and zero strength virtual soil layer - # from the pile head down to the mudline - depth = np.concatenate([np.array([z0]),np.array([row[0] for row in profile],dtype=float)]) # m - Su = np.concatenate([np.array([0]), np.array([row[1] for row in profile],dtype=float)]) # kPa - gamma = np.concatenate([np.array([0]), np.array([row[2] for row in profile],dtype=float)]) # kN/m3 - - # Calculate sigma_v_eff at each depth - sigma_v_eff = np.zeros(len(depth)) - - for i in range(1, len(depth)): - sigma_v_eff[i] = sigma_v_eff[i-1] + gamma[i-1]*(depth[i] - depth[i-1]) - - # Define interpolation functions - f_Su = interp1d(depth, Su*1000, kind='linear') # Pa - f_sigma_v_eff = interp1d(depth, sigma_v_eff*1000, kind='linear') # Pa - f_gamma = interp1d(depth, gamma*1000, kind='linear') # N/m3 - - # Calculate f_psi and f_alpha at each depth (not as a scalar) - f_psi = lambda z: f_Su(z) / f_sigma_v_eff(z) - - def calc_alpha(z): - psi_val = f_psi(z) - if psi_val <= 1.0: - return min(0.5*psi_val**-0.50, 1) - else: - return min(0.5*psi_val**-0.25, 1) - - # Create an interpolated adhesion factor function - f_alpha = lambda z: calc_alpha(z) - - return z0, f_Su, f_sigma_v_eff, f_gamma, f_alpha - -def sand_profile(profile): - '''Define the sand profile used by the p-y analyzer. Outputs 'interp1d' functions containing Su and sigma'_v - profiles to be used by the p-y curve functions. - - Input: - ----- - profile - A 2D tuple in the following format: ([Depth (m), Su (kPa), gamma (kN/m^3), py-model, model parameter]) - The soil profile should be defined relative to the pile/tower head (i.e. point of lateral load application) - so that any load eccentricities can be taken into account. An example soil profile is shown below. - Eg: array([[z0, phi, gamma0, Dr, 'API', 0.02], - ...]) - - *The current program cannot define layers with different p-y models. But it will added in the future. - - Output: - ------ - z0 - Depth of mudline relative to the pile head (m) - f_phi - 'interp1d' function containing effective friction angle (deg) - f_sigma_v_eff - 'interp1d' function containing effective vertical stress profile (Pa) - f_gamma - 'interp1d' function containing effective unit weight (N/m3) - f_Dr - Relative density of the soil (%) - f_delta - Skin friction factor (sand/steel) - ''' - - from scipy.interpolate import interp1d - - # Depth of mudline relative to pile head - z0 = float(profile[0][0]) - - # Extract data from profile array and zero strength virtual soil layer - # from the pile head down to the mudline - depth = np.concatenate([np.array([z0]),np.array([row[0] for row in profile],dtype=float)]) # m - phi = np.concatenate([np.array([0]), np.array([row[1] for row in profile],dtype=float)]) # deg - gamma = np.concatenate([np.array([0]), np.array([row[2] for row in profile],dtype=float)]) # kN/m3 - Dr = np.concatenate([np.array([0]), np.array([row[3] for row in profile],dtype=float)]) # % - - # Calculate sigma_v_eff and static loading factor at each depth - sigma_v_eff = np.zeros(len(depth)) - - for i in range(1, len(depth)): - sigma_v_eff[i] = sigma_v_eff[i-1] + gamma[i-1]*(depth[i] - depth[i-1]) - - # Define interpolation functions - f_phi = interp1d(depth, phi, kind='linear') # deg - f_sigma_v_eff = interp1d(depth, sigma_v_eff*1000, kind='linear') # Pa - f_gamma = interp1d(depth, gamma*1000, kind='linear') # N/m3 - f_Dr = interp1d(depth, Dr, kind='linear') # % - - # Define delta as a function of Dr - def calc_delta(Dr_val): - if 35 <= Dr_val < 50: - return 0.29 - elif 50 <= Dr_val < 65: - return 0.37 - elif 65 <= Dr_val < 85: - return 0.46 - elif Dr_val >= 85: - return 0.56 - else: - return 0 # Default or error value for very low Dr values - - # Apply delta calculation to Dr profile - delta_values = np.array([calc_delta(Dr_val) for Dr_val in Dr]) - f_delta = interp1d(depth, delta_values, kind='linear') # Interpolated delta values - - return z0, f_phi, f_sigma_v_eff, f_gamma, f_Dr, f_delta - -if __name__ == '__main__': - - # CLAY - profile = np.array([[ 0.0, 10, 8], - [75.0, 245, 5]]) - # SAND - # profile = np.array([[ 0.0, 32, 8, 75], - # [75.0, 38, 9, 85]]) - - L = 20 - D = 1.5 - zlug = 5*D - - H0 = 4260000 - V0 = 1590000 - - H = 1e6; V = 1e6 - - values_H =[]; values_V =[] - - y, z, results = getCapacityDrivenSoil(profile, soil_type='clay', L=L, D=D, zlug=zlug, V=V, H=H) - - # while results['Lateral displacement']<= 0.05*D and results['Rotational displacement'] <= 0.25: - - # y, z, results = getCapacityDrivenSoil(profile, soil_type='clay', L=L, D=D, zlug=zlug, V=V, H=H) - - # H += 10000 - - # values_H.append(H); H_ratio = np.array(values_H)/H0 - - while results['Lateral displacement']<= 0.05*D and results['Bending moment'] <= results['Plastic moment']: - - y, z, results = getCapacityDrivenSoil(profile, soil_type='sand', L=L, D=D, zlug=zlug, V=V, H=H) - - H += 100000 - - values_H.append(H); H_ratio = np.array(values_H)/H0 - - # y, z, results = getCapacityDrivenSoil(profile, soil_type='sand', L=L, D=D, zlug=zlug, V=V, H=H) - - - y0 = np.zeros(len(z)) - #Plot deflection profile of pile - fig, ax = plt.subplots(figsize=(3,5)) - ax.plot(y0,z,'black') - ax.plot(y,z,'r') - ax.set_xlabel('Displacement [m]') - ax.set_ylabel('Depth below pile head [m]') - ax.set_ylim([L + 2,-2]) - ax.set_xlim([-0.1*D, 0.1*D]) - ax.grid(ls='--') - fig.show() \ No newline at end of file diff --git a/famodel/anchors/anchors_famodel/capacity_helical.py b/famodel/anchors/anchors_famodel/capacity_helical.py index 0ccae2f4..f88fe892 100644 --- a/famodel/anchors/anchors_famodel/capacity_helical.py +++ b/famodel/anchors/anchors_famodel/capacity_helical.py @@ -1,93 +1,173 @@ import numpy as np +from .capacity_driven import getCapacityDriven, plot_pile +from .support_soils import clay_profile, sand_profile +from .support_plots import plot_helical + +def getCapacityHelical(profile_map, location_name, D, L, d, zlug, Ha, Va, plot=False, display=0): + '''Calculate the vertical and horizontal capacity of a helical pile using a soil profile. + The calculation is based on the soil profile, anchor geometry and inclined load. -def getCapacityHelical(D, L, d, zlug, soil_type, gamma, Su0=None, k=None, phi=None, Dr=None): - - '''Calculate the inclined vertical load capacity of a helical pile in clay. - The calculation is based on the soil properties and anchor geometry. - Parameters ---------- + profile : array + Soil profiles (z, parameters) + Clay soil profile (z, Su, gamma) + Sand soil profile (z, phi, gamma, Dr) + soil_type : string + Select soil condition, 'clay' or 'sand' D : float - Helix diameter [m] + Helix diameter (m) L : float - Length shaft [m] + Shaft length (m) d : float - Pile shaft diameter [m] + Shaft diameter (m) zlug : float - Embedded depth of the lug [m] - soil_type : string - Select soil condition, 'clay' or 'sand' - gamma: float - Effective unit weight of the soil [kN/m3] - Su0 : float - Undrained shear strength at the mudline (clay only) [kPa] - k : float - Undrained shear strength gradient (clay only) [kPa/m] - phi : float - Angle of internal friction (sand only) [deg] - Dr : float - Relative density of the soil (%) (sand only) [-] - - + Depth to padeye (m) + Ha : float + Horizontal load applied at padeye (N) + Va : float + Vertical load applied at padeye (N) + plot : bool + Plot the p-y curve and the deflection pile condition if True + Returns ------- - Qu: float - Maximum vertical capacity [kN] + y : array + Lateral displacement at each node (real nodes only) + z : array + Node depth positions corresponding to y (m) + resultsHelical : dict + Dictionary containing displacements, moment capacity, hinge state and vertical capacity ''' - - rhos= 78.50 # Dry steel unit weight (kN/m3) - t = (6.35 + D*20)/1e3 # Suction pile wall thickness (m), API RP2A-WSD - - # Dry and wet mass of the pile + + profile_entry = next(p for p in profile_map if p['name'] == location_name) + layers = profile_entry['layers'] + + t = (6.35 + D*20)/1e3 # Helical pile wall thickness (m), API RP2A-WSD + rhows = 66.90e3 # Submerged steel specific weight (kN/m3) + rhow = 10e3 # Water specific weight (kN/m3) + def PileWeight(Len, Dia1, Dia2, tw, rho): - Wp = ((np.pi/4)*((Dia1**2 - (Dia1 - 2*tw)**2)*Len + (np.pi/4)*Dia2**2*tw))*rho - return Wp - # Define alpha coefficient (clay) - if soil_type == 'clay': - Su_av_L = Su0 + k*(L - D) # Undrained shear strength values (average) - sigma_v_eff = gamma*zlug # Effective soil stress (kN/m2) - psi_val = Su_av_L/sigma_v_eff # Su/p0' for point in question (API DP 2A-WSD) - if psi_val <= 1.0: - alpha = min(0.5*psi_val**-0.50, 1) - else: - alpha = min(0.5*psi_val**-0.25, 1) + return ((np.pi/4)*((Dia1**2 - (Dia1 - 2*tw)**2)*Len + (np.pi/4)*Dia2**2*tw))*rho + + z_helix = zlug + (L - D) + matched_layer = next((layer for layer in layers if layer['top'] <= z_helix <= layer['bottom']), None) + if matched_layer is None: + raise ValueError(f"No soil layer found at z = {z_helix:.2f} m") + + if matched_layer['soil_type'] == 'clay': + profile = [[matched_layer['top'], matched_layer['Su_top'], matched_layer['gamma_top']], + [matched_layer['bottom'], matched_layer['Su_bot'], matched_layer['gamma_bot']]] + z0, f_Su, f_sigma_v_eff, f_gamma, f_alpha = clay_profile(profile) + + z_helix = np.clip(z_helix, matched_layer['top'], matched_layer['bottom']) + Su = f_Su(z_helix) + sigma_v_eff = max(f_sigma_v_eff(z_helix), 1.0) + psi_val = Su/sigma_v_eff + alpha = min(0.5*psi_val**-0.50, 1) if psi_val <= 1.0 else min(0.5 * psi_val**-0.25, 1) + + Nc = min(6.0*(1 + 0.2*d/D), 9) + Qh = ((np.pi/4)*(D**2 - d**2)*Nc*Su + f_gamma(z_helix)*D)*0.75 + Qs = np.pi*d*L*alpha*Su + Qu = PileWeight(L, D, d, t, rhows) + Qh + Qs + + elif matched_layer['soil_type'] == 'sand': + profile = [[matched_layer['top'], matched_layer['phi_top'], matched_layer['gamma_top'], matched_layer['Dr_top']], + [matched_layer['bottom'], matched_layer['phi_bot'], matched_layer['gamma_bot'], matched_layer['Dr_bot']]] + z0, f_phi, f_sigma_v_eff, f_gamma, f_Dr, f_delta = sand_profile(profile) + + z_helix = np.clip(z_helix, matched_layer['top'], matched_layer['bottom']) + gamma = f_gamma(z_helix) + Dr = f_Dr(z_helix) + delta = f_delta(z_helix) + phi = f_phi(z_helix) + + Nq = 0.5*(12*phi)**(phi/54) + Qh = (np.pi/4)*(D**2 - d**2)*Nq*gamma*z_helix + Qs = np.pi*d*L*delta*gamma*z_helix + Qu = PileWeight(L, D, d, t, rhows) + Qh + Qs - # Define delta as a function of Dr (sand) - def calc_delta(Dr_val): - if 35 <= Dr_val < 50: - return 0.29 - elif 50 <= Dr_val < 65: - return 0.37 - elif 65 <= Dr_val < 85: - return 0.46 - elif Dr_val >= 85: - return 0.56 + + Wp = PileWeight(L, D, d, t, (rhows + rhow)) + + # Unity Check based only on vertical capacity + UC_vertical = Va/Qu + + # Compute horizontal capacity using p-y method + layers, y, z, results_lateral = getCapacityDriven(profile_map, location_name, D, L, zlug, Ha, Va, plot=False) + # Plotting + if plot: + plot_pile(layers, y, z, D, L, z0=layers[0]['top'], zlug=zlug, hinge_location=None) + + Hcap = results_lateral['Horizontal max.'] + UC_horizontal = Ha/Hcap if Hcap != 0 else np.inf + + resultsHelical = { + 'Horizontal max.': Hcap, + 'Vertical max.': Qu, + 'Lateral displacement': results_lateral['Lateral displacement'], + 'Rotational displacement': results_lateral['Rotational displacement'], + 'Unity check (horizontal)': UC_horizontal, + 'Unity Check (vertical)': UC_vertical, + 'Weight pile': Wp,} + + if matched_layer['soil_type'] == 'clay': + resultsHelical['Su @ helix'] = Su + resultsHelical['alpha'] = alpha + elif matched_layer['soil_type'] == 'sand': + resultsHelical['Dr @ helix'] = Dr + resultsHelical['delta'] = delta + resultsHelical['phi'] = phi + + return layers, resultsHelical + +if __name__ == '__main__': + + profile_map = [ + { + 'name': 'CPT_1', + 'x': 498234, 'y': 5725141, + 'layers': [ + { + 'top': 1.0, 'bottom': 3.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 9.0, + 'Su_top': 60, 'Su_bot': 50}, + # { + # 'top': 3.0, 'bottom': 7.0, + # 'soil_type': 'clay', + # 'gamma_top': 15.0, 'gamma_bot': 25.0, + # 'Su_top': 100, 'Su_bot': 150}, + { + 'top': 3.0, 'bottom': 7.0, + 'soil_type': 'sand', + 'gamma_top': 8.0, 'gamma_bot': 8.0, + 'phi_top': 32, 'phi_bot': 38, + 'Dr_top': 70, 'Dr_bot': 75}, + { + 'top': 7.0, 'bottom': 15.0, + 'soil_type': 'clay', + 'gamma_top': 25.0, 'gamma_bot': 50.0, + 'Su_top': 200, 'Su_bot': 400}] + } + ] + + D = 1.5 # Helix diameter (m) + L = 12.0 # Pile length (m) + d = 0.5 # Shaft diameter (m) + zlug = 3 # Padeye depth (m) + Ha = 30e3 # Horizontal load (N) + Va = 50e3 # Vertical load (N) + + layers, resultsHelical = getCapacityHelical(profile_map, 'CPT_1', D, L, d, zlug, Ha, Va, plot=True) + for key, val in resultsHelical.items(): + if isinstance(val, float): + print(f"{key}: {val:.3f}") else: - return 0 # Default or error value for very low Dr values - - Wp = PileWeight(L, D, d, t, rhos) + print(f"{key}: {val}") - # ----- Clay case ----- - if soil_type == 'clay': - Nc = 6.0*(1 + 0.2*d/D); - Nc = np.where(Nc < 9, Nc, 9) - # Su is calculated, at the depth of the helix minus one helical plate diameter - # A reduction of 25% is applied for a moderately sensitive clay - Qh = ((np.pi/4)*(D**2 - d**2)*Nc*(Su0 + k*(L - D)) + gamma*D)*0.75 - Qs = np.pi*d*L*alpha*(Su0 + k*(L - D)) - Qu = Qh + Qs - - # ----- Sand case ----- - else: - delta = calc_delta(Dr) - Nq = 0.5*(12*phi)**(phi/54) - Qh = (np.pi/4)*(D**2 - d**2)*Nq*gamma*L - Qs = np.pi*d*L*delta*gamma*L - Qu = Qh + Qs - - resultsHelical = {} - resultsHelical['Capacity'] = Qu # Vertical capacity - resultsHelical['Weight'] = Wp # Dry weight of the helical pile (kN) - - return resultsHelical \ No newline at end of file + plot_helical(layers, D=D, L=L, d=d, z0=layers[0]['top'], zlug=zlug, n_helix=1, spacing=1.0) + + + diff --git a/famodel/anchors/anchors_famodel/capacity_load.py b/famodel/anchors/anchors_famodel/capacity_load.py index 33553bdd..cece7f19 100644 --- a/famodel/anchors/anchors_famodel/capacity_load.py +++ b/famodel/anchors/anchors_famodel/capacity_load.py @@ -1,225 +1,210 @@ -# -*- coding: utf-8 -*- -""" -Created on Wed May 29 15:53:52 2024 -@author: fmoreno -""" - -import yaml # Allow access to config file for user inputs import numpy as np import matplotlib.pyplot as plt -from scipy.optimize import fsolve +from .support_soils import clay_profile, sand_profile +from .support_plots import plot_load +def getTransferLoad(profile_map, Tm, thetam, zlug, line_type, d, w=None, plot=False, display=0): + '''Calculate the transfer load from mudline to main padeye using a layered soil profile. -def getAnchorLoad(Tm, thetam, zlug, d, soil_type, gamma, Su0, k): - - '''Calculate the inclined load capacity of a Suction Caisson Anchor in sand or clay. - The calculation is based on the soil properties, anchor geometry, and the angle of inclined load. - Offshore Geotechnical Engineering (Randolph , page 323) - Parameters ---------- - Tm : float - Mooring line load at mudlevel [kN] - thetam : float - Mooring line angle at mudlevel [deg] - zlug : float - Embedded depth of the lug [m] - soil_type: string - Select soil condition, 'clay' or 'sand' + profile_map : list of dicts + Soil profile in profile_map format + Tm : float + Mooring line load at mudlevel (N) + thetam : float + Mooring line angle at mudlevel (deg) + zlug : float + Embedment depth of the lug (m) + line_type : str + 'chain' or 'wire' d : float - Chain diameter [m] - Su0 : float - Undrained shear strength at the mudline (clay) [kPa] - k : float - Undrained shear strength gradient (clay) [kPa/m] - - Returns - ------- - Ta : float - Inclined load magnitude at the anchor lug [kN] - thetaa : float - Inclined load angle at the anchor lug [deg] - ''' - - # Setting bearing capacity values per soil type - if soil_type == 'clay': - Nc = 8.5; Ab=2.5; nhu=0.40 # Nc - Bearing capacity factor (9 and 14) DNV-RP-E301 - elif soil_type == 'sand': # Ab - Effective unit bearing area (2.5 - 2.6 times chain dia) - Nc = 9; Ab=2.5; nhu=0.35 # nhu - Friction coefficient between the mooring line and soil - - thetam = np.radians(thetam) - - if soil_type == 'clay': - Su_av_lug = Su0*zlug + k*zlug**2/2 - zaQav = Ab*d*Nc*Su_av_lug - - elif soil_type == 'sand': - zaQav = Ab*d*Nc*gamma*zlug**2/2 - - def LoadTransfer(beta): - return(2*zaQav*np.e**(nhu*(beta - thetam)) - Tm*(beta**2 - thetam**2)) - - thetaa = fsolve(LoadTransfer, thetam) - thetaa = thetaa[0] - Ta = Tm/(np.e**(nhu*(thetaa - thetam))) - - H = Ta*np.cos(thetaa) - V = Ta*np.sin(thetaa) - - resultsLoad = {} - resultsLoad['load'] = Ta # Load magnitude @ lug - resultsLoad['angle'] = np.rad2deg(thetaa) # Load angle @ lug - resultsLoad['H'] = H # Horizontal component @ lug - resultsLoad['V'] = V # Vertical component @ lug - - return resultsLoad - -def getTransferLoad(Tm, thetam, zlug, line_type, d, soil_type, Su0=None, - k=None, gamma=None, phi= None, delta=None, w=None, plot=False): - '''Calculate the transfer load from the mudline to the main padeye - elevation using the DNV standards. The calculation is based on the - mooring line properties, anchor geometry and the load from MoorPy and - RAFT. - - Parameters - ---------- - Tm : float - Mooring line load at mudlevel [kN] - thetam : float - Mooring line angle at mudlevel [deg] - zlug : float - Embedded depth of the lug [m] - line_type = string - Select line type, 'chain' or 'wire' - d : float - Chain diameter [m] - soil_type = string - Select soil condition, 'clay' or 'sand' - Su0 : float - Undrained shear strength at the mudline (clay only) [Pa] - k : float - Undrained shear strength gradient (clay only) [Pa/m] - gamma: float - Effective unit weight of the soil (sand only) [N/m3] - phi : float - Friction angle (sand only) [deg] - delta: float - Interface friction angle at soil-anchor line (sand only) [deg] + Chain diameter (m) w : float - Mooring line unit weight [N/m] - + Mooring line unit weight (N/m) + plot : bool + Show plot + Returns ------- - Ta : float - Inclined load magnitude at the anchor lug [kN] - thetaa : float - Inclined load angle at the anchor lug [deg] + dict + Dictionary with transferred load components and depth. ''' - - deltas = 0.2 - - # Include element weight in terms of d and match it with deltas - if line_type == 'chain': - Et = 10; En = 2.5; W = w*deltas; + + deltas = 0.2 # discretization step + + # Line mechanical properties + if line_type == 'chain': + Et, En = 10, 2.5 elif line_type == 'wire': - Et = np.pi; En = 1; W = w*deltas; - - T = Tm; theta = np.deg2rad(thetam); - Su = Su0; - drag = 0; depth = 0.1 - - T_values = []; Su_values = []; - drag_values = []; depth_values = []; + Et, En = np.pi, 1 + W = w*deltas + + # Soil layer access + layers = profile_map[0]['layers'] + z0 = min(layer['top'] for layer in layers) + Nc = 8.5 + + if all(layer['soil_type'] in ['rock', 'weak_rock'] for layer in layers): + if display > 0: print('[Bypass] Skipping load transfer — soil is all rock.') + Ha = Tm*np.cos(np.deg2rad(thetam)) + Va = Tm*np.cos(np.deg2rad(thetam)) + return Ha, Va + + # Initial values + z0 = min(layer['top'] for layer in layers) + T = Tm + theta = np.deg2rad(thetam) + drag = 0 + depth = z0 + 0.01 + + # Tracing lists + drag_values, depth_values = [], [] - # Setting bearing capacity values per soil type - if soil_type == 'clay': - Nc = 8.5; alpha = 0.7; - elif soil_type == 'sand': - nhu = 0.5 - Nq = np.exp(np.pi*np.tan(np.deg2rad(phi)))*(np.tan(np.deg2rad(45 + phi/2)))**2 - # print(Nq) - while (zlug - depth) >= 0: - if soil_type =='clay': - dtheta = (En*d*Nc*Su - W*np.cos(theta))/T*deltas - dT = (Et*d*alpha*Su + W*np.sin(theta))*deltas - - elif soil_type =='sand': - dtheta = (En*d*Nq*gamma*depth - W*np.cos(theta))/T*deltas - dT = (Et*d*gamma*depth*np.tan(np.rad2deg(delta)) + W*np.sin(theta))*deltas + matched_layer = next((layer for layer in layers if layer['top'] <= depth <= layer['bottom']), None) + if matched_layer is None: + break - ddrag = deltas*np.cos(theta) - ddepth = deltas*np.sin(theta) - theta += dtheta; T -= dT; - - drag += ddrag; depth += ddepth - if Su: - Su = Su0 + k*depth - - # Ensure consistency in load transfer - if abs(Tm - T) > 0.75*Tm: # More than 75% loss - raise Exception(f"Warning: Load transfer is unrealistic. Initial load Tm = {Tm/1e6:.2f} MN and current load T = {T/1e6:.2f} MN differ by more than 75 %") - break # Exit the loop if load transfer is unrealistic + if matched_layer['soil_type'] == 'clay': + matched_layer = next((layer for layer in layers if layer['soil_type'] == 'clay' and layer['top'] <= depth <= layer['bottom']), None) + if matched_layer is None: + break + profile = [[matched_layer['top'], matched_layer['gamma_top'], matched_layer['Su_top']], + [matched_layer['bottom'], matched_layer['gamma_bot'], matched_layer['Su_bot']]] + z0_local, f_gamma, f_Su, f_sigma_v_eff, f_alpha = clay_profile(profile) + + Su = f_Su(depth) + alpha = f_alpha(depth) + d_theta = (En*d*Nc*Su - W*np.cos(theta))/T*deltas + dT = (Et*d*alpha*Su + W*np.sin(theta))*deltas + + elif matched_layer['soil_type'] == 'sand': + matched_layer = next((layer for layer in layers if layer['soil_type'] == 'sand' and layer['top'] <= depth <= layer['bottom']), None) + if matched_layer is None: + break - # Check for excessive load angles - if not (0 < np.rad2deg(theta) < 90): - raise Exception(f"Warning: Load angle is unrealistic: {np.rad2deg(theta):.2f} deg") - break # Exit the loop if the angle becomes unreasonable + profile = [[matched_layer['top'], matched_layer['gamma_top'], matched_layer['phi_top'], matched_layer['Dr_top']], + [matched_layer['bottom'], matched_layer['gamma_bot'], matched_layer['phi_bot'], matched_layer['Dr_bot']]] + z0_local, f_gamma, f_phi, f_Dr, f_sigma_v_eff, f_delta = sand_profile(profile) + + gamma_z = f_gamma(depth) + delta_z = f_delta(depth) + phi = f_phi(depth) + Nq = np.exp(np.pi*np.tan(np.deg2rad(phi)))*(np.tan(np.deg2rad(45 + phi/2)))**2 + if display > 0: print(f'Nq = {Nq:.2f}, depth = {depth:.2f} m') + d_theta = (En*d*Nq*gamma_z*depth - W*np.cos(theta))/T*deltas + dT = (Et*d*gamma_z*depth*np.tan(np.deg2rad(delta_z)) + W*np.sin(theta))*deltas - T_values.append(T); Su_values.append(Su) - drag_values.append(drag); depth_values.append(depth); - - Ta = T; thetaa = theta - # print(thetaa); print(Ta) - H = Ta*np.cos(thetaa); V = Ta*np.sin(thetaa) - length_values = deltas*len(drag_values) - - resultsLoad = {} - resultsLoad['diff'] = (Tm - Ta)/1e6 # Difference - resultsLoad['load'] = Ta/1e6 # Load magnitude @ lug - resultsLoad['angle'] = np.rad2deg(thetaa) # Load angle @ lug - resultsLoad['H'] = H # Horizontal component @ lug - resultsLoad['V'] = V # Vertical component @ lug - resultsLoad['length'] = length_values # Length of the embedded line - - # Plot of the line and extreme line tension - drag_values = [-1*i for i in drag_values] - depth_values = [-1*j for j in depth_values] - - if plot: - fig, ax = plt.subplots(figsize=(20, 5)); n = 2000000 - ax.scatter(drag_values[-1], depth_values[-1], color='g', zorder=5) - ax.scatter(0, 0, color='r', zorder=4) - ax.arrow(0, 0, Tm*np.cos(np.deg2rad(thetam))/n, Tm*np.sin(np.deg2rad(thetam))/n, - head_width=0.25, head_length=0.5, color='r', zorder=3) - ax.arrow(drag_values[-1], depth_values[-1], Ta*np.cos(thetaa)/n, Ta*np.sin(thetaa)/n, - head_width=0.25, head_length=0.5, color='g',zorder=2) - ax.plot(drag_values, depth_values,color='b', zorder=1) - - #Set labels and title - plt.xlabel('Drag distance [m]') - plt.ylabel('Embedded depth [m]') - plt.suptitle('Inverse catenary profile in soil DNV') - plt.grid(True) - - return resultsLoad + elif matched_layer['soil_type'] in ['rock', 'weak_rock']: + raise ValueError(f"Unsupported soil type: {matched_layer['soil_type']}. Mooring line cannot be embedded in rock.") + + d_drag = deltas*np.cos(theta) + d_depth = deltas*np.sin(theta) + + theta += d_theta + T -= dT + drag += d_drag + depth += d_depth + + if not (0 < np.rad2deg(theta) < 90): + if display > 0: print(f"[Warning] Line angle reached {np.rad2deg(theta):.2f}°, stopping at drag = {-drag:.2f} m") + break + + drag_values.append(-drag); + depth_values.append(-depth); + + if np.rad2deg(theta) >= 90: + if display > 0: print(f"[Correction] Clipping angle to 90° to avoid negative horizontal load (Ha).") + theta = np.deg2rad(90) + Ta = T; thetaa = theta + Hm = Tm*np.cos(np.deg2rad(thetam)); Vm = Tm*np.sin(np.deg2rad(thetam)) + Ha = Ta*np.cos(thetaa); Va = Ta*np.sin(thetaa) + + if display > 0: print(f'Input Tm = {Tm} N, thetam = {thetam}°, zlug = {zlug} m') + if display > 0: print(f'Output Hm = {Hm} N, Vm = {Vm} N') + if display > 0: print(f'Output Ta = {Ta} N, thetaa = {np.rad2deg(thetaa)}°') + if display > 0: print(f'Output Ha = {Ha} N, Va = {Va} N') + + resultsLoad = { + 'Tm': Tm, 'thetam': thetam, + 'Hm': Hm, 'Vm': Vm, + 'Ta': Ta, 'thetaa': np.rad2deg(thetaa), + 'Ha': Hm, 'Va': Va, + 'length': deltas*len(drag_values), + 'drag_values': drag_values, + 'depth_values': depth_values} + + return layers, resultsLoad if __name__ == '__main__': - - Tm = 1.16e6 - thetam = 0 - zlug = 10 - line_type ='chain' - d = 0.160 - soil_type ='sand' - Su0 = 2.4*1e3 - k = 1.41*1e3 - gamma = 9e3 - phi = 35 - delta = 27 - w = 4093 - - resultsDNV = getTransferLoad(Tm, thetam, zlug, line_type, d, soil_type, Su0, k, gamma, phi, delta, w) - #results = getAnchorLoad(Tm, thetam, zlug, d, soil_type, gamma, Su0, k) \ No newline at end of file + + # profile_map = [ + # { + # 'name': 'CPT_1', + # 'x': 498234, 'y': 5725141, + # 'layers': [ + # { + # 'top': 1.0, 'bottom': 2.0, + # 'soil_type': 'clay', + # 'gamma_top': 8.0, 'gamma_bot': 8.0, + # 'Su_top': 10, 'Su_bot': 25}, + # { + # 'top': 2.0, 'bottom': 8.0, + # 'soil_type': 'clay', + # 'gamma_top': 8.0, 'gamma_bot': 8.0, + # 'Su_top': 25, 'Su_bot': 50}, + # { + # 'top': 8.0, 'bottom': 16.0, + # 'soil_type': 'clay', + # 'gamma_top': 8.0, 'gamma_bot': 8.0, + # 'Su_top': 50, 'Su_bot': 100} + # ] + # } + # ] + profile_map = [ + { + 'name': 'CPT_1', + 'x': 498234, 'y': 5725141, + 'layers': [ + # { + # 'top': 0.0, 'bottom': 5.0, + # 'soil_type': 'sand', + # 'gamma_top': 9.5, 'gamma_bot': 9.5, + # 'phi_top': 28, 'phi_bot': 30, + # 'Dr_top': 70, 'Dr_bot': 70}, + { + 'top': 0.0, 'bottom': 5.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 8.0, + 'Su_top': 25, 'Su_bot': 25}, + # { + # 'top': 0.0, 'bottom': 3.0, + # 'soil_type': 'sand', + # 'gamma_top': 9.5, 'gamma_bot': 9.5, + # 'phi_top': 30, 'phi_bot': 38, + # 'Dr_top': 65, 'Dr_bot': 75}, + { + 'top': 5.0, 'bottom': 15.0, + 'soil_type': 'sand', + 'gamma_top': 9.5, 'gamma_bot': 9.5, + 'phi_top': 35, 'phi_bot': 40, + 'Dr_top': 77, 'Dr_bot': 85} + ] + } + ] + + Tm = 4978442 # Load at mudline (N) + thetam = 30 # Angle at mudline (deg) + zlug = 8.5 # Padeye depth (m) + line_type = 'chain' + d = 0.25 # Chain diameter (m) + w = 5000 # Line weight (N/m) + + layers, resultsLoad = getTransferLoad(profile_map, Tm, thetam, zlug, line_type, d, w, plot=True, display=1) + + plot_load(layers, resultsLoad['drag_values'], resultsLoad['depth_values'], + resultsLoad['Tm'], resultsLoad['thetam'], resultsLoad['Ta'], + resultsLoad['thetaa'], zlug=zlug) \ No newline at end of file diff --git a/famodel/anchors/anchors_famodel/capacity_plate.py b/famodel/anchors/anchors_famodel/capacity_plate.py index bc371ff7..59a1f91d 100644 --- a/famodel/anchors/anchors_famodel/capacity_plate.py +++ b/famodel/anchors/anchors_famodel/capacity_plate.py @@ -1,102 +1,177 @@ import numpy as np +import matplotlib.pyplot as plt +from .support_soils import clay_profile +from .support_plots import plot_plate + +def getCapacityPlate(profile_map, location_name, B, L, zlug, beta, Ha, Va, plot=False, display=0): + '''Calculate the plate anchor capacity using clay soil layers from profile_map. + The calculation is based on the soil profile, anchor geometry and inclined load. -def getCapacityPlate(A, beta, zlug, soil_type, gamma, Su0=None, k=None): - - '''Calculate the inclined load capacity of a plate in clay at a given depth. - The calculation is based on the soil properties, anchor geometry and the angle of inclined load. - The plate is assumed to be inclined perpendicular to the tension at the main padeye depth. - Parameters ---------- - A : float - Plate area, assumed to be square so that width B = sqrt(A). [m^2] + profile_map : list of dict + Soil profile map with coordinates and layers per location. + location_name : str + Name of the location to select the soil profile. + B : float + Plate width (m) + L : float + Plate length (m) + zlug : float + Embedment depth of the main padeye (m) beta : float - Angle of the plate after keying process [deg] - zlug: float - Embedded depth of the main padeye [m] - soil_type : string - Specify 'sand' or 'clay'. This affects what other soil parameters are used. - gamma: float - Effective unit weight of the soil [kN/m3] - Su0 : float - Undrained shear strength at the mudline [kPa] - k : float - Undrained shear strength gradient [kPa/m] - + Inclination angle of the plate (deg) + Ha : float + Applied horizontal load (N) + Va : float + Applied vertical load (N) + plot : bool + Whether to generate plots. + Returns ------- - Tmax: float - Maximum capacity [kN] + Dictionary with Capacity, Weight, UC, etc. ''' - - - Los=0.05 # Key lost fraction due to the keying process, default 0.05 (-) - rhos= 78.50 # Dry steel unit weight (kN/m3) - - B = round(np.sqrt(A),2) # Anchor width (and length, approximated as square) (m) - zlug_B = zlug/B # Anchor depth range/ width of the plate - B_t = 40 # Aspect ratio plate width to thickness, default is 40 - t = round(B/B_t, 2) # Thickness of the plate, which it depends on the width (m) + + # Extract and filter clay layers from profile_map + profile_entry = next(p for p in profile_map if p['name'] == location_name) + layers = [layer for layer in profile_entry['layers'] if layer['soil_type'] == 'clay'] + + if not layers: + raise ValueError('Plate anchor capacity model only supports clay soils.') + + # Build the profile array: [[z, Su, gamma], ...] + profile = [] + for layer in layers: + profile.append([layer['top'], layer['gamma_top'], layer['Su_top']]) + profile.append([layer['bottom'], layer['gamma_bot'], layer['Su_bot']]) + + if display > 0: print("layer gamma_top (raw):", layer['gamma_top']) + if display > 0: print("layer gamma_bot (raw):", layer['gamma_bot']) + + profile = np.array(sorted(profile, key=lambda x: x[0])) + + # Parameters and constants + Los = 0.05 + B_t = 40 + rhows = 66.90e3 # Submerged steel (N/m3) + rhow = 10e3 # Seawater (N/m3) + + # Evaluate interpolated Su and gamma + z0, f_gamma, f_Su, f_sigma_v_eff, f_alpha = clay_profile(profile) + t = round(B/B_t, 2) + V_steel = round(B*L*t, 2) + zlug_B = zlug/B + + # Profile check points + npts = 10 + z_offsets = np.linspace(-0.5, 0.5, npts)*B*np.sin(np.deg2rad(beta)) + z_points = zlug + z_offsets; print(z_points) + + Su_vals = [f_Su(z) for z in z_points] + gamma_10 = f_gamma(z_points[2]); print(gamma_10) + gamma_vals = [f_gamma(z) for z in z_points]; print("gamma_vals:", [f"{val:.2f}" for val in gamma_vals], "N/m3") + Su = np.mean(Su_vals); print(f"Su: {Su:.2f} Pa") + gamma = np.mean(gamma_vals); print(f"gamma: {gamma:.2f} N/m3") - #t=np.sqrt(0.006*A)/4 - V = round(A*t,2) # Steel volume (m3) - W = V*rhos # Plate weight (kg) - Su = Su0 + k*zlug # Undrained shear strength at plate depth + if display > 0: print("Profile being sent to clay_profile():") + for row in profile: + if display > 0: print(f"z = {row[0]:.2f} m, gamma = {row[1]:.2f} kN/m³, Su = {row[2]:.2f} kPa") - # ----- anchor pullout capacity ----- + # Shear strength gradient + k = np.polyfit(z_points, Su_vals, 1)[0] + if display > 0: print(f"k: {k:.2f}") - # Anchor Pullout capacity factor in weightless clay with breakaway base, soil homogeneous - Nco_0_0 = 2.483*np.log(zlug_B) + 1.974 # angle = 0 deg - Nco_90_0 = 2.174*np.log(zlug_B) + 3.391 # angle = 90 deg + # Pile weight including auxiliary parts + Wp = 1.35*V_steel*(rhows + rhow) - kBSh = k*B/Su # Degree of soil non-homogeneity + # Capacity factors + Nco_0_0 = 2.483*np.log(zlug_B) + 1.974 + Nco_90_0 = 2.174*np.log(zlug_B) + 3.391 + kBSh = k*B/Su + if display > 0: print(f"kBSh: {kBSh:.2f}") f0 = np.where(zlug_B < 4, 1.77*(zlug_B**0.3) - 1.289, 0.192*zlug_B + 0.644) - f90 = np.where(zlug_B < 4, 0.68*(zlug_B**0.5) - 0.41 , 0.153*zlug_B + 0.341) + f90 = np.where(zlug_B < 4, 0.68*(zlug_B**0.5) - 0.410, 0.153*zlug_B + 0.341) - # Non-homogeneity adjustment factor for anchor ultimate pullout capacity - S_kB_0 = 1 - f0 *kBSh + S_kB_0 = 1 - f0*kBSh S_kB_90 = 1 - f90*kBSh + Nco_0 = S_kB_0*Nco_0_0 + Nco_90 = S_kB_90*Nco_90_0 + Nco = Nco_0 + (Nco_90 - Nco_0)*(beta/90)**2 - # Anchor Pullout capacity factor in weightless clay with breakaway base, soil nonhomogeneous - Nco_0 = S_kB_0*Nco_0_0 - Nco_90 = S_kB_90*Nco_90_0 - - # Anchor pullout capacity factor in weightless clay with no breakaway base - Nco = Nco_0 + (Nco_90 - Nco_0)*(beta/90)**2 - - # Uplift bearing capacity factor, soil homogeneous Nco_s_0_0 = np.where(2.90*zlug_B + 6.02 <= 11.59, 2.90*zlug_B + 6.02, 11.596) Nco_s_90_0 = np.where(2.72*zlug_B + 4.02 <= 11.59, 2.72*zlug_B + 4.02, 11.596) - # ----- ultimate anchor capacity factor ----- - - # Non-homogeneity factor for anchor ultimate pullout capacity - S_s_kB_0 = np.where(zlug_B <= 2, 1 + (0.8 - 0.3*zlug_B)*kBSh - (0.383*kBSh**1.36), 1) # Angle = 0 - + S_s_kB_0 = np.where(zlug_B <= 2, 1 + (0.8 - 0.3*zlug_B)*kBSh - (0.383*kBSh**1.36), 1) f90s = np.where(zlug_B <= 3, 0.267*zlug_B, 0.6) - S_s_kB_90 = 1 - f90s*kBSh # Angle = 90 - - # Anchor ultimate holding capacity in with breakaway base, soil nonhomogeneous - Nco_s_0 = S_s_kB_0 *Nco_s_0_0 + S_s_kB_90 = 1 - f90s*kBSh + Nco_s_0 = S_s_kB_0*Nco_s_0_0 Nco_s_90 = S_s_kB_90*Nco_s_90_0 - - # Anchor ultimate holding capacity in with no breakaway base, soil nonhomogeneous Nco_s = Nco_s_90 + (Nco_s_0 - Nco_s_90)*((90 - beta)/90)**2 - - # ----- final results ----- - Nc_final = np.minimum(Nco + (gamma*zlug)/Su, Nco_s) # anchor pullout capacity factor [kN] - qu = Nc_final*Su # The bearing pressure capacity of the anchor plate - Tmax = round(qu*(1 - Los)*A,2) # The bearing tension force capacity of the anchor plate - Hmax = Tmax*np.cos(np.deg2rad(beta)) - Vmax = Tmax*np.sin(np.deg2rad(beta)) - - resultsPlate = {} - resultsPlate['Capacity'] = Tmax # Capacity at specified loading angle - resultsPlate['Horizontal max.'] = Hmax # Maximum horizontal capacity in clay - resultsPlate['Vertical max.'] = Vmax # Maximum vertical capacity in clay - resultsPlate['Weight'] = W # Dry weight of the plate (kN) + Nc_final = max(Nco + (gamma*zlug)/Su, Nco_s) + if display > 0: print(f"Nc_star: {Nco + (gamma*zlug)/Su:.2f}") + if display > 0: print(f"Nc_star: {Nco_s:.2f}") + qu = Nc_final*Su + Tmax = round(qu*(1 - Los)*B*L, 2) + Hmax = Tmax*np.cos(np.deg2rad(90 - beta)) + Vmax = Tmax*np.sin(np.deg2rad(90 - beta)) + + Ta = np.sqrt(Ha**2 + Va**2) + UC = Ta/Tmax + + resultsPlate = { + 'Capacity': Tmax, + 'Horizontal max.': Hmax, + 'Vertical max.': Vmax, + 'Unity check': UC, + 'Weight plate': Wp + } - return resultsPlate \ No newline at end of file + return layers, resultsPlate + +if __name__ == '__main__': + profile_map = [ + { + 'name': 'CPT_1', + 'x': 498234, 'y': 5725141, + 'layers': [ + { + 'top': 0.0, 'bottom': 9.5, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 8.5, + 'Su_top': 10, 'Su_bot': 25 + }, + { + 'top': 9.5, 'bottom': 11.5, + 'soil_type': 'clay', + 'gamma_top': 8.5, 'gamma_bot': 8.5, + 'Su_top': 25, 'Su_bot': 45 + }, + { + 'top': 11.5, 'bottom': 25.0, + 'soil_type': 'clay', + 'gamma_top': 8.5, 'gamma_bot': 9.0, + 'Su_top': 45, 'Su_bot': 50 + } + ] + } + ] + + B = 2.0 + L = 2.0 + zlug = 10.0 + Ha = 350e3 + Va = 400e3 + alpha = np.rad2deg(np.arctan2(Va, Ha)) + beta = 90 - alpha + + layers, results = getCapacityPlate(profile_map, 'CPT_1', B, L, zlug, beta, Ha, Va) + + print("\n--- Plate Anchor Capacity Results ---") + for key, val in results.items(): + print(f"{key}: {val:.2f}") + + plot_plate(layers, B, L, z0 = layers[0]['top'], zlug=zlug, beta=beta, title='Plate Anchor in Layered Soil') diff --git a/famodel/anchors/anchors_famodel/capacity_suction.py b/famodel/anchors/anchors_famodel/capacity_suction.py index d16b75a1..328c97ee 100644 --- a/famodel/anchors/anchors_famodel/capacity_suction.py +++ b/famodel/anchors/anchors_famodel/capacity_suction.py @@ -1,53 +1,54 @@ -import yaml import numpy as np import matplotlib.pyplot as plt -from scipy.optimize import fsolve -#from famodel.anchors.capacity_load import getAnchorLoad -#from famodel.anchors.anchors_famodel.capacity_load import getTransferLoad +import matplotlib.colors as mcolors +from .support_soils import clay_profile, sand_profile -def getCapacitySuction(D, L, zlug, H, V, soil_type, gamma, Su0=None, k=None, phi=None, Dr=None, plot=True): - +def getCapacitySuction(profile_map, location_name, D, L, zlug, Ha, Va, thetalug=5, psilug=7.5, plot=False, display=0): '''Calculate the inclined load capacity of a suction pile in sand or clay following S. Kay methodology. - The calculation is based on the soil properties, anchor geometry and inclined load. + The calculation is based on the soil profile, anchor geometry and inclined load. Parameters ---------- + profile : array + Soil profile as a 2D array: (z, parameters) + Clay soil profile (z (m), Su (kPa), gamma (kN/m³)) + Sand soil profile (z (m), phi (deg), gamma (kN/m³), Dr (%)) + soil_type : string + Select soil condition, 'clay' or 'sand' D : float - Suction pile diameter [m] + Suction pile diameter (m) L : float - Suction anchor length [m] + Suction pile length from pile head (m) zlug: float - Embedded depth of the main padeye [m] - soil_type : string - Select soil condition, 'clay' or 'sand' - gamma: float - The effective unit weight of the soil. [kN/m3] - Su0 : float - Undrained shear strength at the mudline (clay only) [kPa] - k : float - Undrained shear strength gradient (clay only) [kPa/m] - phi : float - Angle of internal friction (sand only) [deg] - Dr : float - Relative density of the soil (%) (sand only) [-] - + Embedded depth of the main padeye (m) + thetalug: float + Angle of tilt misaligment (deg) (default value: 5.0) + psilug: float + Angle of twist misaligment (deg) (default value: 7.5) + Ha : float + Horizontal load at pile lug elevation (N) + Va : float + Vertical load at pile lug elevation (N) + plot : bool + Plot the capacity envelope if True + Returns ------- - Hmax : float - Maximum horizontal capacity [kN] - Vmax : float - Maximum vertical capacity [kN] - ''' - - lambdap = L/D; m = 2/3; # Suction pile slenderness ratio + Dictionary with capcity, weigths and UC. + ''' + + # Retrieve soil layers from map + profile_entry = next(p for p in profile_map if p['name'] == location_name) + layers = profile_entry['layers'] + + z0 = layers[0]['top'] # Mudline elevation + lambdap = (L - z0)/D # Suction pile slenderness ratio t = (6.35 + D*20)/1e3 # Suction pile wall thickness (m), API RP2A-WSD rlug = D/2 # Radial position of the lug - thetalug = 5 # Angle of tilt misaligment, default is 5. (deg) - psilug = 7.5 # Angle of twist misaligment, default is 7.5. (deg) - rhows = 66.90 # Submerged steel specific weight (kN/m3) - rhow = 10 # Water specific weight (kN/m3) - + rhows = 66.90e3 # Submerged steel specific weight (N/m3) + rhow = 10e3 # Water specific weight (N/m3) + # Outer and inner surface of the pile skirt def PileSurface(Len, Dia): Sp = np.pi*Dia*Len @@ -67,267 +68,459 @@ def rlugTilt(r, z, theta): def zlugTilt(r, z, theta): Z = r*np.sin(np.deg2rad(theta)) + z*np.cos(np.deg2rad(theta)) return Z - # Define delta as a function of Dr - def calc_delta(Dr_val): - if 35 <= Dr_val < 50: - return 0.29 - elif 50 <= Dr_val < 65: - return 0.37 - elif 65 <= Dr_val < 85: - return 0.46 - elif Dr_val >= 85: - return 0.56 - else: - return 0 # Default or error value for very low Dr values - - if soil_type == 'clay': - # Definitions for cohesive soils - Nc = min (6.2*(1 + 0.34*np.arctan(lambdap)),9) # End-bearing capacity factor - ez = (Su0*L**2/2 + k*L**3/3)/(Su0*L + k*L**2/2)#; print(ez) - Np_fixed = 10.25; Np_free = 4 # From Np vs L/D chart from CAISSON_VHM - Su_av_L = Su0 + k*zlug # Undrained shear strength values (average) - Su_tip = Su0 + k*L # Undrained shear strength values (tip) - sigma_v_eff = gamma*zlug # Effective soil stress (kN/m2) - psi_val = Su_av_L/sigma_v_eff # Su/p0' for point in question (API DP 2A-WSD) - #zlug = ez # Optimized depth of the lug - - if psi_val <= 1.0: - alpha = min(0.5*psi_val**-0.50, 1) - else: - alpha = min(0.5*psi_val**-0.25, 1) - - Hmax = Np_fixed*L*D*Su_av_L; - H0 = Np_free*L*D*Su_av_L; - Mmax = Np_fixed*L*L*D*Su_av_L; + # Ellipse crossing with constant values + def horizontal_cross(H, M, M_target): + crossings = [] + for i in range(len(M_rot) - 1): + if (M[i] - M_target) * (M[i+1] - M_target) < 0: + # Interpolation to get more precise value at crossing + H_cross = np.interp(M_target, [M[i], M[i+1]], [H[i], H[i+1]]) + crossings.append(H_cross) + return crossings + def vertical_cross(H, M, H_target): + crossings = [] + for i in range(len(H) - 1): + if (H[i] - H_target) * (H[i+1] - H_target) < 0: + # Interpolation to get more precise value at crossing + M_cross = np.interp(H_target, [H[i], H[i+1]], [M[i], M[i+1]]) + crossings.append(M_cross) + return crossings + + Np_fixed = 11.65 + Np_free = 3.5 + Nc = min(6.2*(1 + 0.34*np.arctan(lambdap)), 9) + + # Initialize + sum_ez_weighted = 0.0 + Hmax_final = 0.0 + Vmax_final = 0.0 + layer_data = [] + + # Profile check points + npts = 10 + + for layer in layers: + soil_type = layer['soil_type'] + z_top = layer['top'] + z_bot = layer['bottom'] + + if soil_type == 'clay': + # Prepare soil profile for clay + profile = [ + [z_top, layer['gamma_top'], layer['Su_top']], + [z_bot, layer['gamma_bot'], layer['Su_bot']] + ] + + z_ref, f_gamma, f_Su, f_sigma_v_eff, f_alpha = clay_profile(profile) + + # Clip the layer first + z_top_clip = max(z_top, z0) + z_bot_clip = min(z_bot, z0 + (L - z0)) + dz_clip = z_bot_clip - z_top_clip + if display > 1: print(f'dz_clip = {dz_clip:.2f} m') + + if dz_clip <= 0: + continue # Skip layers fully above or below + + # Calculate properties over clipped dz + z_vals = np.linspace(z_top_clip, z_bot_clip, npts) + Su_vals = f_Su(z_vals) + Su_total = np.trapz(Su_vals, z_vals) + Su_moment = np.trapz(Su_vals*z_vals, z_vals) + + ez_layer = Su_moment/Su_total + Su_av_z = f_Su(ez_layer) + + if display > 1: print(f'ez_layer = {ez_layer:.2f} m') + if display > 1: print(f'Su_av_z (at ez_layer) = {Su_av_z:.2f} Pa') + + Su_bot = f_Su(z_bot_clip) + gamma_vals = f_gamma(z_vals) + gamma_av = np.mean(gamma_vals) + + # Calculate Hmax for clay + Hmax_layer = Np_fixed*D*dz_clip*Su_av_z + + layer_data.append({ + 'z_top': z_top_clip, + 'z_bot': z_bot_clip, + 'dz': dz_clip, + 'Hmax_layer': Hmax_layer, + 'ez_layer': ez_layer + }) + + sigma_v_eff = f_sigma_v_eff(np.mean(z_vals)) + alpha_av = float(f_alpha(np.mean(z_vals))) + + # Side shear To and Ti + To = PileSurface(dz_clip, D)*alpha_av*Su_av_z + Ti = PileSurface(dz_clip, D - 2*t)*alpha_av*Su_av_z + + # Tip resistance + if abs(z_bot_clip - (z0 + (L - z0))) < 1e-3: # tip check + Tbase = (np.pi/12)*D**3*Su_bot + else: + Tbase = 0.0 + + Tmax = min(To + Ti, To + Tbase) + + # Torque induced by horizontal load + T = Ha*rlug*np.sin(np.deg2rad(psilug)) + + nhuT = T/Tmax + nhuV = Ha/To + nhuVstar = np.sqrt(nhuV**2 - nhuT**2) + alphastar = alpha_av*(nhuVstar/nhuV) + if display > 1: print(f"alphastar = {alphastar:.3f}") + + # Constant weight + Pile_Head = PileWeight(z0, D, t, rhows) + + # Vertical failure modes + Vmax1 = None + if np.isclose(z_bot_clip, z0 + (L - z0), atol=0.1): + Vmax1 = PileWeight(dz_clip, D, t, rhows) + PileSurface(dz_clip, D)*alphastar*Su_av_z + Nc*Su_bot*(np.pi/4)*D**2 + # else: + # Vmax1 = np.inf # No tip resistance unless at tip + + Vmax2 = PileWeight(dz_clip, D, t, rhows) + PileSurface(dz_clip, D)*alphastar*Su_av_z + PileSurface(dz_clip, D - 2*t)*alphastar*Su_av_z + Vmax3 = PileWeight(dz_clip, D, t, rhows) + PileSurface(dz_clip, D)*alphastar*Su_av_z + SoilWeight(dz_clip, D, t, gamma_av) + + Vmax_candidates = [v for v in [Vmax1, Vmax2, Vmax3] if v is not None] + Vmax_layer = max(Vmax_candidates) + + # Sum vertical capacities + Vmax_final += Vmax_layer + + # Print layer debug info + if display > 0: print(f"Vmax_layer = {Vmax_layer:.2f} N") + if display > 0: print(f"Vmax1 = {Vmax1:.2f} N" if Vmax1 is not None else "Vmax1 = not applicable") + if display > 0: print(f"Vmax2 = {Vmax2:.2f} N") + if display > 0: print(f"Vmax3 = {Vmax3:.2f} N") + + elif soil_type == 'sand': + # Prepare soil profile for sand + profile = [ + [z_top, layer['gamma_top'], layer['phi_top'], layer['Dr_top']], + [z_bot, layer['gamma_bot'], layer['phi_bot'], layer['Dr_bot']] + ] - # M modifies the Hmax capacity - M = - V*rlugTilt(rlug,zlug,thetalug) - H*(zlugTilt(rlug,zlug,thetalug) - ez) - def f(Hmax): - return m*(Hmax/(L*D*(Su0 + k*zlug)) - Np_fixed) + M*(Hmax/(L*D*(Su0 + k*zlug))/(Hmax*L)) - Hmax = fsolve(f,5) + z_ref, f_gamma, f_phi, _, f_sigma_v_eff, f_delta = sand_profile(profile) - # Torsion capacity - Fo = PileSurface(L, D)*alpha*Su_av_L - To = Fo - Ti = PileSurface(L,(D - 2*t))*alpha*Su_av_L - Tbase = np.pi*D**3*Su_tip/12 - Tmax = min(To + Ti, To + Tbase) + # Clip the layer within pile embedded length + z_top_clip = max(z_top, z0) + z_bot_clip = min(z_bot, z0 + (L - z0)) + dz_clip = z_bot_clip - z_top_clip - # Introduce twist effects due to installation misaligment - T = H*rlug*np.sin(np.deg2rad(psilug)) - nhuT = T/Tmax; nhuV = H/Fo; - nhuVstar = np.sqrt(nhuV**2 - nhuT**2) - alphastar = alpha*(nhuVstar/nhuV) + if dz_clip <= 0: + continue # Skip non-overlapping layers - # "Plugged" (Reverse end bearing capacity - passive suction) - Vmax1 = (PileWeight(L, D, t, rhows) + PileSurface(L, D)*alphastar*Su_av_L + Nc*Su_tip*(np.pi/4)*D**2) - # "Coring" - Vmax2 = (PileWeight(L, D, t, rhows) + PileSurface(L, D)*alphastar*Su_av_L + PileSurface(L,(D - 2*t))*alphastar*Su_av_L) - # "Leaking" - Vmax3 = (PileWeight(L, D, t, rhows) + PileSurface(L, D)*alphastar*Su_av_L + SoilWeight(L, D, t, gamma)) - Vmax = min(Vmax1, Vmax2, Vmax3) - ''' - print("\n--- Parameter-Based Version ---") - print(f"Su_av_L = {Su_av_L:.3f} kPa") - print(f"sigma'_v(zlug) = {sigma_v_eff:.3f} kPa") - print(f"psi_val = {psi_val:.3f}") - print(f"alpha (API) = {alpha:.3f}") - print(f"Hmax = {Hmax[0]:.2f} kN") - print(f"Vmax = {Vmax:.2f} kN") - ''' - - elif soil_type == 'sand': - # Definition for non-cohesive soils - Nq = np.e**(np.pi*np.tan(np.radians(phi)))*np.tan(np.radians(45) + np.radians(phi)/2)**2 # Lateral-bearing capacity factor - sigma_av_L = gamma*L/2 # Effective stress (average) - sigma_tip = gamma*L # Effective stress (tip) - Hmax = 0.5*D*Nq*gamma*L**2 - - M = - V*rlugTilt(rlug,zlug,thetalug) - H*(zlugTilt(rlug,zlug,thetalug) - zlug) + # Calculate properties over clipped dz + z_vals = np.linspace(z_top_clip, z_bot_clip, npts) + phi_vals = f_phi(z_vals) + sigma_vals = f_sigma_v_eff(z_vals) + delta_vals = f_delta(z_vals) - # Torsion capacity - delta = calc_delta(Dr) - To = PileSurface(L, D)*delta*sigma_av_L - Ti = PileSurface(L, (D -2*t))*delta*sigma_av_L - Tbase = np.pi*D**3*sigma_tip/12 - Tmax = min(To + Ti, To + Tbase) + phi_av = np.mean(phi_vals) + sigma_av = np.mean(sigma_vals) + delta_av = np.mean(delta_vals) - # Introduce twist effects due to installation misaligment - T = H*rlug*np.sin(np.deg2rad(psilug)) - Fo = delta*sigma_av_L*L*np.pi*D - nhuT = T/Tmax; nhuV = H/Fo; - nhuVstar = np.sqrt(nhuV**2 - nhuT**2) - deltastar = delta*(nhuVstar/nhuV) - - # "Coring" - Vmax2 = PileWeight(L, D, t, rhows) + PileSurface(L, D)*deltastar*sigma_av_L + PileSurface(L,(D - 2*t))*deltastar*sigma_av_L - # "Leaking" - Vmax3 = (PileWeight(L, D, t, rhows) + PileSurface(L, D)*deltastar*sigma_av_L + SoilWeight(L, D, t, gamma)) - Vmax = min(Vmax2, Vmax3) - # def y(depth): - # return np.e**(-depth) - 1 + depth - # Ze = D/(4*7); Zi = D/(4*5) - # Vmax = 7*gamma*Ze**2*y(L/Ze)*PileSurface(L, D)/L + 5*gamma*Zi**2*y(L/Zi)*PileSurface(L,(D - 2*t))/L - ''' - print("\n--- Parameter-Based (Sand) ---") - print(f"phi = {phi:.2f} deg") - print(f"gamma = {gamma:.2f} kN/m3") - print(f"deltastar = {deltastar:.2f} -") - print(f"sigma_av_L = {sigma_av_L:.2f} kN") - print(f"sigma_tip = {sigma_tip:.2f} kN") - ''' - # Pile weight (inc. stiffening plus vent) assessed as a factor - Wp = 1.10*PileWeight(L, D, t, (rhows + rhow)) - # Submerged weight of the soil plug - Ws = SoilWeight(L, D, t, gamma) - - # Capacity envelope - aVH = 0.5 + lambdap; bVH = 4.5 + lambdap/3 - #print('Env. exp = ' +str(aVH)+' '+str(bVH)) - UC = (H/Hmax)**aVH + (V/Vmax)**bVH - x = np.cos(np.linspace (0, np.pi/2, 100)) - y = (1 - x**bVH)**(1/aVH) - X = Hmax*x; Y = Vmax*y - if plot: - plt.plot(X, Y, color = 'b') - plt.plot(H, V, '*', color = 'r') + sigma_tip = f_sigma_v_eff(z_bot_clip) + gamma_vals = f_gamma(z_vals) + gamma_av = np.mean(gamma_vals) - # Set labels and title - plt.xlabel('Horizontal capacity [kN]') - plt.ylabel('Vertical capacity [kN]') - plt.suptitle('VH suction pile capacity envelope') - plt.axis([0, 1.3*max(X[0], H), 0, 1.3*max(Y[-1], V)]) - plt.grid(True) - plt.show() - - resultsSuction = {} - if soil_type == 'clay': - resultsSuction['Horizontal max.'] = Hmax[0] # Maximum horizontal capacity in clay - elif soil_type == 'sand': - resultsSuction['Horizontal max.'] = Hmax # Maximum horizontal capacity in sand - resultsSuction['Vertical max.'] = Vmax # Maximum vertical capacity - if soil_type == 'clay': - resultsSuction['UC'] = UC[0] # Unity check in clay - elif soil_type == 'sand': - resultsSuction['UC'] = UC # Unity check in sand - resultsSuction['Weight'] = Wp # Dry weight of the suction pile (kN) - resultsSuction['Weight Soil'] = Ws # Submerged weight of the soil plug (kN) - resultsSuction['t'] = t # Pile thikness in [m] - - return resultsSuction + Nq = np.e**(np.pi*np.tan(np.radians(phi_av)))*(np.tan(np.radians(45) + np.radians(phi_av)/2))**2 + + # Calculate Hmax for sand + Hmax_layer = 0.5*Nq*D*gamma_av*dz_clip**2 + + layer_data.append({ + 'z_top': z_top_clip, + 'z_bot': z_bot_clip, + 'dz': dz_clip, + 'Hmax_layer': Hmax_layer, + 'ez_layer': np.mean(z_vals) + }) + + # Side friction + To = PileSurface(dz_clip, D)*delta_av*sigma_av + Ti = PileSurface(dz_clip, D - 2*t)*delta_av*sigma_av + + if abs(z_bot_clip - (z0 + (L - z0))) < 1e-3: + Tbase = np.pi/4*D**2*sigma_tip + else: + Tbase = 0.0 + + Tmax = min(To + Ti, To + Tbase) + + # Torque induced by horizontal load + T = Ha*rlug*np.sin(np.deg2rad(psilug)) + nhuT = T/Tmax + nhuV = Ha/To + nhuVstar = np.sqrt(nhuV**2 - nhuT**2) + deltastar = delta_av*(nhuVstar/nhuV) + + # Constant weight + Pile_Head = PileWeight(z0, D, t, rhows) + + # Vertical failure modes + Vmax2 = Pile_Head + PileWeight(dz_clip, D, t, rhows) + PileSurface(dz_clip, D)*deltastar*sigma_av + PileSurface(dz_clip, D - 2*t)*deltastar*sigma_av + Vmax3 = Pile_Head + PileWeight(dz_clip, D, t, rhows) + PileSurface(dz_clip, D)*deltastar*sigma_av + SoilWeight(dz_clip, D, t, gamma_av) + + Vmax_layer = min(Vmax2, Vmax3) + + # Sum vertical capacities + Vmax_final += Vmax_layer -def getCapacitySuctionSimp(D, L, zlug, H, V, gamma, Su0, k, alpha): + if display > 0: print(f"Vmax_layer (sand) = {Vmax_layer:.2f} N") + if display > 0: print(f"Vmax2 (sand) = {Vmax2:.2f} N") + if display > 0: print(f"Vmax3 (sand) = {Vmax3:.2f} N") - ''' - Parameters - ---------- - D : float - Suction pile diameter [m] - L : float - Suction anchor length [m] - Tm : float - Mooring line load at mudlevel [kN] - thetam : float - Mooring line angle at mudlevel [deg] - zlug : float - Embedded depth of the lug [m] - gamma: float - - Su0 : float - Undrained shear strength at the mudline (clay only)[kPa] - k : float - Undrained shear strength gradient (clay only) [kPa/m] - alpha : float - Skin friction coefficient (outer and inner - clay only) [-] - rhows : float - Submerged steel density [t/m3] + # Hmax_final and weighted ez + for data in layer_data: + z_top = data['z_top'] + z_bot = data['z_bot'] + Hmax_layer = data['Hmax_layer'] + ez_layer = data['ez_layer'] + dz_layer = data['dz'] - Returns - ------- - Hmax : float - Maximum horizontal capacity [kN] - Vmax : float - Maximum vertical capacity [kN] - UC: float - Capacity unity check for given load [-] - ''' - - lambdap = L/D; # Suction pile slenderness ratio - t = 10*D/1e3 # Thickness of the pile - Np_fixed = 10.25; # From Np vs L/D chart from CAISSON_VHM - rhows=66.90 - - Su_av_L = Su0 + k*zlug; # Undrained shear strength values (average) - Su_tip = Su0 + k*L; # Undrained shear strength values (tip) - Nc = min (6.2*(1 + 0.34*np.arctan(lambdap)),9) # End-bearing capacity factor - - # Outer and inner surface of the pile skirt - def PileSurface(Len, Dia): - Sp = np.pi*Dia*Len - return Sp - # Dry and wet mass of the pile - def PileWeight(Len, Dia, tw, rho): - Wp = ((np.pi/4)*((Dia**2 - (Dia - 2*tw)**2)*Len + (np.pi/4)*Dia**2*tw))*rho - return Wp - # Weight of the soil plug - def SoilWeight(Len, Dia, tw, gamma_soil): - Wsoil =(np.pi/4)*(Dia - 2*tw)**2*Len*gamma_soil - return Wsoil - - Hmax = Np_fixed*L*D*Su_av_L - # "Plugged" (Reverse end bearing capacity - passive suction) - Vmax1 = (PileWeight(L, D, t, rhows) + PileSurface(L, D)*alpha*Su_av_L + Nc*Su_tip*(np.pi/4)*D**2) - # "Coring" - Vmax2 = (PileWeight(L, D, t, rhows) + PileSurface(L, D)*alpha*Su_av_L + PileSurface(L,(D - 2*t))*alpha*Su_av_L) - # "Leaking" - Vmax3 = (PileWeight(L, D, t, rhows) + PileSurface(L, D)*alpha*Su_av_L + SoilWeight(L, D, t, gamma)) - # print(Vmax1); print(Vmax2); print(Vmax3) - Vmax = min(Vmax1,Vmax2,Vmax3) - - # Submerged pile weight (inc. stiffening plus vent) assessed as a factor - Wp = 1.00*PileWeight(L, D, t, (rhows)) - # Submerged weight of the soil plug - Ws = SoilWeight(L, D, t, gamma) + z_embedded_start = z0 + z_embedded_end = L - z0 + + if z_top >= z_embedded_start and z_bot <= z_embedded_end: + sum_ez_weighted += Hmax_layer*ez_layer + Hmax_final += Hmax_layer + if display > 0: print(f'Hmax_layer = {Hmax_layer:.2f} m') + + elif z_top < z_embedded_end and z_bot > z_embedded_start: + dz_inside = min(z_bot, z_embedded_end) - max(z_top, z_embedded_start) + if dz_inside > 0: + ratio = dz_inside/dz_layer + sum_ez_weighted += Hmax_layer*ratio*ez_layer + Hmax_final += Hmax_layer*ratio + # print(f'ez_layer (partial) = {ez_layer:.2f} m') + + ez_global = sum_ez_weighted/Hmax_final + if display > 1: print(f'ez_global = {ez_global:.2f} m') + if display > 0: print(f'Hmax_final = {Hmax_final:.2f} m') + + # Calculate coupled moment + M = -Va*rlugTilt(rlug, zlug, thetalug) - Ha*(zlugTilt(rlug, zlug, thetalug) - ez_global) + Mv = -Va*rlugTilt(rlug, zlug, thetalug) + if display > 1: print(f"rlug_eff = {rlugTilt(rlug, zlug, thetalug):.2f} m") + if display > 1: print(f"zlug_eff = {zlugTilt(rlug, zlug, thetalug):.2f} m") + if display > 1: print(f"M = {M:.2f} Nm") - # H = Tm*np.cos(np.deg2rad(thetam)); V = Tm*np.sin(np.deg2rad(thetam)) + # MH Ellipse Parameters for Clay (Kay 2014) + # ΔφMH (piecewise based on L/D) + if 0.5 <= lambdap < 1.125: + delta_phi = 0.32 + 4.32*lambdap; #print(delta_phi) + elif 1.125 <= lambdap < 2.0: + delta_phi = 7.13 - 1.71*lambdap; #print(delta_phi) + elif 2.0 <= lambdap <= 8.0: + delta_phi = 2.25 - 0.25*lambdap; #print(delta_phi) + else: + raise ValueError('L/D out of bounds for MH ellipse.') + + phi_MH = -np.arctan(ez_global/(L - z0)) - np.deg2rad(delta_phi) + a_MH = Np_fixed/np.cos(phi_MH) + delta_bMH = 0.45*(lambdap)**(-0.9) if lambdap <= 1.5 else 0 + b_MH = -Np_free*np.sin(phi_MH) + delta_bMH + if display > 1: print(f"delta_phi = {delta_phi:.2f} deg") + if display > 1: print(f"phi_MH = {np.rad2deg(phi_MH):.2f} deg") + if display > 1: print(f"a_MH = {a_MH:.2f}") + if display > 1: print(f"b_MH = {b_MH:.2f}") + + # MH Ellipse Parameters for Clay (Kay 2015) + # VH (piecewise based on L/D) + if 0.5 <= lambdap < 1.5: + a_VH = 9/4 + (5/3)*lambdap; + elif 0.5 <= lambdap < 1.25: + b_VH = 23/4 - (13/5)*lambdap; + elif 1.5 <= lambdap < 20.0: # need to set a maximum of 6 based on installation pump requirements + a_VH = 47/12 - (5/9)*lambdap; + b_VH = 50/19 - (2/19)*lambdap; + else: + raise ValueError('L/D ratio out of bounds for MH ellipse formulation.') + a_VH = 0.5 + lambdap; b_VH = 4.5 + lambdap/3 + # a_VH = 4.5 + lambdap/2; b_VH = 4.5 + lambdap/4 + if display > 0: print(f"a_VH = {a_VH:.2f}") + if display > 0: print(f"b_VH = {b_VH:.2f}") + + # Scale VH ellipse based on vertical load ratio (Kay 2015) + shrink_factor = 1 - ((Va/Vmax_final)**b_VH)**(2/a_VH) + + if plot: plt.figure(figsize=(10, 5)) + theta = np.linspace(0, 2*np.pi, 400) + shrink_factors = np.linspace(0.0, 1.0, 5) + # Define colormap + if plot: cmap = plt.colormaps['Greys'] + norm = mcolors.Normalize(vmin=min(shrink_factors), vmax=max(shrink_factors)) - # Capacity envelope - aVH = 0.5 + lambdap; bVH = 4.5 + lambdap/3 - # print('Env. exp =' +str(aVH)+str(bVH)) - UC = (H/Hmax)**aVH + (V/Vmax)**bVH + for s_f in shrink_factors: + if plot: color = cmap(norm(s_f)) + x_ellipse = Hmax_final*s_f*np.cos(theta) + y_ellipse = Vmax_final*s_f*np.sin(theta) + H_rot = np.cos(phi_MH)*x_ellipse - np.sin(phi_MH)*y_ellipse + M_rot = np.sin(phi_MH)*x_ellipse + np.cos(phi_MH)*y_ellipse + if plot: plt.plot(H_rot, M_rot, color=color, alpha=0.5) + + x_ellipse_prime = Hmax_final*shrink_factor*np.cos(theta) + y_ellipse_prime = Vmax_final*shrink_factor*np.sin(theta) + H_rot_prime = np.cos(phi_MH)*x_ellipse_prime - np.sin(phi_MH)*y_ellipse_prime + M_rot_prime = np.sin(phi_MH)*x_ellipse_prime + np.cos(phi_MH)*y_ellipse_prime + Hlim = 1.2*Hmax_final + if plot: plt.xlim(-Hlim, Hlim) + if plot: plt.ylim(-Hlim, Hlim) + if plot: plt.grid(True, color='gray', linestyle='--', lw=0.5, alpha=0.8) - x = np.cos(np.linspace (0,np.pi/2,1000)) - y = (1 - x**bVH)**(1/aVH) - X = Hmax*x; Y = Vmax*y + # Highlight the actual one + if plot: plt.plot(H_rot_prime, M_rot_prime, 'b', label= f'MH ellipse w/ V/Vmax = {shrink_factor:.3f}') + if plot: plt.axhline(0, color='k', linestyle='--', lw=1.0) + if plot: plt.axvline(0, color='k', linestyle='--', lw=1.0) - #H_good = Hmax*np.exp(np.log(0.5)/aVH) - #V_good = Vmax*np.exp(np.log(0.5)/bVH) + # Plot horizontal line at constant M and Mv + H_plot = np.linspace(min(1.3*H_rot), max(1.3*H_rot), 100) + M_plot = np.full_like(H_plot, M) # Constant moment + Mv_plot = np.full_like(H_plot, Mv) # Constant moment + if plot: plt.plot(H_plot, M_plot, 'r', lw=1.0, label='Moment line') + if plot: plt.plot(H_plot, Mv_plot, 'r', lw=0.5, label='Vertical moment line') + if plot: plt.legend(loc='lower left', fontsize='small') - resultsSuctionSimp = {} - resultsSuctionSimp['Horizontal max.'] = Hmax # Capacity at specified loading angle - resultsSuctionSimp['Vertical max.'] = Vmax # Capacity at specified loading angle - resultsSuctionSimp['UC'] = UC # Unity check - resultsSuctionSimp['Weight'] = Wp # Pile weight in kN - resultsSuctionSimp['Weight Soil'] = Ws # in kN - resultsSuctionSimp['t'] = t - - return resultsSuctionSimp + H_roots = horizontal_cross(H_rot_prime, M_rot_prime, M) + Hmax_v = 0.1 + if H_roots: + Hmax_pos = max([r for r in H_roots if r >= 0], default=None) + Hmax_neg = min([r for r in H_roots if r < 0], default=None) + if M > 0 and Hmax_neg is not None: + Hmax_v = abs(Hmax_neg) + if plot: plt.plot(Hmax_neg, M, 'ro', label=f'Hmax,v = {Hmax_neg/1e6:.1f} MN', zorder=20) + if plot: plt.legend(loc='lower left') + elif M <= 0 and Hmax_pos is not None: + Hmax_v = abs(Hmax_pos) + if plot: plt.plot(Hmax_pos, M, 'ro', label=f'Hmax,v = {Hmax_pos/1e6:.1f} MN', zorder=20) + if plot: plt.legend(loc='lower left') + else: + if display > 0: print('[WARNING] No valid Hmax crossing found for moment cut.') + else: + if display > 0: print('[WARNING] No intersection between moment line and ellipse.') -if __name__ == '__main__': + # Find relevant intercept + H_v_roots = horizontal_cross(H_rot_prime, M_rot_prime, 0.0) + M_v_roots = vertical_cross(H_rot_prime, M_rot_prime, 0.0) + idx_maxH = np.argmax(H_rot_prime) + H_at_maxH = H_rot_prime[idx_maxH] + M_at_maxH = M_rot_prime[idx_maxH] + idx_minM = np.argmin(M_rot_prime) + H_at_minM = H_rot_prime[idx_minM] + M_at_minM = M_rot_prime[idx_minM] - D = 2.0 # Diameter in meters - L = 10.0 # Length in meters - zlug = (2/3)*L # Padeye depth - H = 1500.0 # Horizontal load in kN - V = 1000.0 # Vertical load in kN + # Plotting + if plot: + plt.scatter(H_v_roots[0], 0.0, s=25, facecolors='white', edgecolors='blue', + marker='s',label=f'Ho ≈ {H_v_roots[0]/1e6:.1f} MN', zorder=10) + plt.legend(loc='lower left', fontsize='small') + plt.scatter(0.0, M_v_roots[0], s=25, facecolors='white', edgecolors='blue', + marker='s', label=f'Mo ≈ {M_v_roots[0]/1e6:.1f} MNm', zorder=10) + plt.legend(loc='lower left', fontsize='small') + plt.scatter(H_at_maxH, M_at_maxH, s=25, facecolors='white', edgecolors='blue', + marker='D', label=f'Hmax ≈ {H_at_maxH/1e6:.1f} MN', zorder=10) + plt.legend(loc='lower left', fontsize='small') + plt.scatter(H_at_minM, M_at_minM, s=25, facecolors='white', edgecolors='blue', + marker='D', label=f'Mmax ≈ {M_at_minM/1e6:.1f} MNm', zorder=10) + plt.legend(loc='lower left', fontsize='small') - gamma = 8 - Su0 = 25 - k = 0 + # Constant weight + pile_head = PileWeight(z0, D, t, rhows) + if display > 0: print(f"pile_head = {pile_head:.2f} N") + Vmax_final += pile_head + if display > 0: print(f"Vmax_final = {Vmax_final:.2f} N") - phi = 50 - Dr = 75 + Wp = 1.10*PileWeight(L, D, t, rhows + rhow) - results_clay = getCapacitySuction(D, L, zlug, H, V, 'clay', gamma, Su0=Su0, k=k, phi=phi, Dr=Dr, plot=True) + # Capacity envelope + a_VH = 0.5 + lambdap; b_VH = 4.5 + lambdap/3 + # Unity check + UC = (Ha/Hmax_v)**a_VH + (Va/Vmax_final)**b_VH + if plot: plt.figure(figsize=(6, 5)) + x = np.linspace(0, 1, 100) + y = (1 - x**b_VH)**(1/a_VH) + + # Plotting + if plot: + plt.figure(figsize=(6, 5)) + plt.plot(Hmax_v*x, Vmax_final*y, 'b', label='VH Envelope') + plt.plot(Ha, Va, 'go', label='Applied load') + plt.xlabel('Horizontal capacity (N)') + plt.ylabel('Vertical capacity (N)') + plt.title('VH suction pile capacity envelope') + plt.axis([0, 1.3*max(Hmax_v, Ha), 0, 1.3*max(Vmax_final, Va)]) + plt.grid(True) + plt.legend() + plt.show() - # results_sand = getCapacitySuction(D, L, zlug, H, V, 'sand', gamma, Su0=Su0, k=k, phi=phi, Dr=Dr, plot=True) \ No newline at end of file + resultsSuction = { + 'Horizontal max.': Hmax_v, + 'Vertical max.': Vmax_final, + 'Unity check': UC, + 'Weight pile': Wp} + + return layers, resultsSuction + +if __name__ == '__main__': + + profile_map = [ + { + 'name': 'CPT_1', + 'x': 498234, 'y': 5725141, + 'layers': [ + { + 'top': 0.0, 'bottom': 20.0, + 'soil_type': 'clay', + 'gamma_top': 8.5, 'gamma_bot': 8.5, + 'Su_top': 2.4, 'Su_bot': 30.3}] + # { + # 'top': 10.0, 'bottom': 20.0, + # 'soil_type': 'clay', + # 'gamma_top': 8.5, 'gamma_bot': 8.5, + # 'Su_top': 13.95, 'Su_bot': 30.3}] + # { + # 'top': 30.0, 'bottom': 36.0, + # 'soil_type': 'clay', + # 'gamma_top': 9.0, 'gamma_bot': 9.5, + # 'Su_top': 75, 'Su_bot': 100}, + # { + # 'top': 36.0, 'bottom': 55.0, + # 'soil_type': 'clay', + # 'gamma_top': 9.5, 'gamma_bot': 9.5, + # 'Su_top': 100, 'Su_bot': 100}] + } + ] + + + # Pile and load properties + D = 3.34 # Pile diameter (m) + L = 20.0 # Pile length (m) + zlug = (2/3)*L # Lug depth (m) + theta = 5 # Tilt misalignment angle (deg) + psi = 7.5 # Twist misalignment angle (deg) + Ha = 1e6 # Applied horizontal load (N) + Va = 5.7e6 # Applied vertical load (N) + + # Calculate + layers, resultsSuction = getCapacitySuction( + profile_map, 'CPT_1', # Soil properties and location of the pile + D, L, zlug, # Pile geometrical properties + Ha, Va, # Pile loading conditions + thetalug=theta, psilug=psi, # Pile misaligment tolerances + plot=True, + display=1 + ) + + # print('\n--- Suction Pile Capacity Results ---') + # print(f"Hmax_final = {resultsSuction['Hmax_final']:.2f} N") + # print(f"Vmax_final = {resultsSuction['Vmax_final']:.2f} N") + # print(f"Unity check (UC) = {resultsSuction['UnityCheck']:.4f}") + # print(f"Total Moment (M_total) = {resultsSuction['M_total']:.2f} Nm") + + # plot_suction(layers, L, D, z0 = layers[0]['top'], zlug=zlug) diff --git a/famodel/anchors/anchors_famodel/capacity_torpedo.py b/famodel/anchors/anchors_famodel/capacity_torpedo.py index 1d493f1e..7c7e13aa 100644 --- a/famodel/anchors/anchors_famodel/capacity_torpedo.py +++ b/famodel/anchors/anchors_famodel/capacity_torpedo.py @@ -1,95 +1,271 @@ -import yaml import numpy as np import matplotlib.pyplot as plt -from scipy.optimize import fsolve -from matplotlib import cm -from mpl_toolkits import mplot3d - -def getCapacityTorpedo(D1, D2, L1, L2, zlug, soil_type, Su0, k, alpha): - +from .support_soils import clay_profile +from .support_plots import plot_torpedo + +def getCapacityTorpedo(profile_map, location_name, D1, D2, L1, L2, zlug, ballast, Ha, Va, plot=False, display=0): '''Calculate the inclined load capacity of a torpedo pile in clay following S. Kay methodology. - The calculation is based on the holding capacity of the suction pile as if it fully was embedded in soil. - + The calculation is based on the soil profile, anchor geometry and inclined load. + Parameters ---------- + profile : array + Clay soil profile (z, Su, gamma) + Clay soil profile (z (m), Su (kPa), gamma (kN/m³)) + soil_type : string + Select soil condition, 'clay' D1 : float - Torpedo pile wing diameter. [m] + Wing diameter (m) D2 : float - Torpedo pile shaft diameter. [m] + Shaft diameter (m) L1 : float - Torpedo pile wing length. [m] + Winged section length (m) L2 : float - Torpedo pile shaft length, excluding wing. [m] + Shaft section length (m) zlug : float - Torpedo pile embedded depth at main padeye elevation. [m] - soil_type : string - Select soil condition, 'clay' or 'sand' - gamma: float - The effective unit weight of the soil. [kN/m3] - Su0 : float - The Undrained shear strength at the mudline. [kPa] - k : float - The Undrained shear strength gradient. [kPa/m] - alpha : float - The skin friction coefficient. [-] - + Padeye embedment depth (m) + Ha : float + Horizontal load at pile lug elevation (N) + Va : float + Vertical load at pile lug elevation (N) + plot : bool + Plot the capacity envelope if True + Returns ------- - Hmax : float - Maximum horizontal capacity [kN] - Vmax : float - Maximum vertical capacity [kN] + Dictionary with capcity, weigth and UC. ''' - rhos= 78.50 # Dry steel unit weight (kN/m3) - t = (6.35 + D2*20)/1e3 # Torpedo pile wall thickness (m), API RP2A-WSD - - L = L1 + L2; - Dstar = (D1*L1 + (D1 + 2*D2)*L2)/L # Plane 1 (four fins) - #Dstar = (D1*L1 + np.sqrt(2)*(D1/2 + D2)*L2)/L # Plane 2 (four fins) - #rlug = D2/2; zlug = zlug; - lambdap = L/Dstar; print('lambdap = ' +str(lambdap)) - a = zlug; b = zlug + L1; c = zlug + L1 + L2; - Wp = 850 # Weight of the pile with ballast [kN] - # Dry and wet mass of the pile + # Retrieve soil layers from map + profile_entry = next(p for p in profile_map if p['name'] == location_name) + layers = profile_entry['layers'] + + L = L1 + L2 + t = (6.35 + D2*20)/1e3 + rhows = 66.90e3 + rhow = 10e3 + def PileWeight(Len1, Len2, Dia1, Dia2, tw, rho): - Wp = ((np.pi/4)*(Dia1**2 - (Dia1 - 2*tw)**2)*(Len1 + Len2) + 4*Len2*Dia2*tw)*rho - return(Wp) - W = PileWeight(L1, L2, D1, D2, t, rhos) # Weight of the steel pile [kN] + return ((np.pi/4)*(Dia1**2 - (Dia1 - 2*tw)**2)*(Len1 + Len2) + 4*Len2*Dia2*tw)*rho + + def PileWingedSurface(length, diameter): + return np.pi*diameter*length + + def PileShaftSurface(length, diameter1, diameter2): + return 8*length*(diameter1 - diameter2) + + z_start = zlug + z_wing = zlug + L1 + z_end = zlug + L + + layer_data = [] + Vmax_total = 0.0 - # Dry and wet mass of the pile - def PileSurface(Len1, Len2, Dia1, Dia2): - Sp = np.pi*Dia1*(Len1 + Len2) + 8*Len2*Dia2*0.9 - return(Sp) + # Profile check points + npts = 10 + + for layer in layers: + if layer['soil_type'] != 'clay': + raise ValueError('Torpedo pile capacity model only supports clay soils.') + + z_layer_top = layer['top'] + z_layer_bot = layer['bottom'] + + z_clip_top = max(z_layer_top, z_start) + z_clip_bot = min(z_layer_bot, z_end) + + if z_clip_bot <= z_clip_top: + continue + + segments = [] + if z_clip_bot <= z_wing: + segments.append((z_clip_top, z_clip_bot, D1)) + elif z_clip_top >= z_wing: + segments.append((z_clip_top, z_clip_bot, D2)) + else: + segments.append((z_clip_top, z_wing, D1)) + segments.append((z_wing, z_clip_bot, D2)) + + for z_seg_top, z_seg_bot, D in segments: + dz_seg = z_seg_bot - z_seg_top + if dz_seg <= 0: + continue + + profile = [ + [z_seg_top, layer['Su_top'], layer['gamma_top']], + [z_seg_bot, layer['Su_bot'], layer['gamma_bot']] + ] + z_ref, f_Su, _, f_gamma, f_alpha = clay_profile(profile) + + z_vals = np.linspace(z_seg_top, z_seg_bot, npts) + Su_vals = f_Su(z_vals) + alpha_vals = np.array([f_alpha(z) for z in z_vals]) + Su_total = np.trapz(Su_vals, z_vals) + Su_moment = np.trapz(z_vals*Su_vals, z_vals) + Su_av_z = Su_total/dz_seg + if display > 0: print(f"Su_av_z = {Su_av_z:.2f} Pa") + ez_layer = Su_moment /Su_total + if display > 0: print(f"dz_seg = {dz_seg:.2f} m") + if display > 0: print(f"ez_layer = {ez_layer:.2f} m") + alpha_av = np.mean(alpha_vals) + if display > 0: print(f"alpha_av = {alpha_av:.2f}") + + Np_free = 3.45 + Hmax_layer = Np_free*dz_seg*D*Su_av_z + if display > 0: print(f"Hmax_layer = {Hmax_layer:.2f} N") + if display > 0: print(f"D = {D:.2f} m") + + surface_area = PileWingedSurface(dz_seg, D) if D == D1 else PileShaftSurface(dz_seg, D1, D2) + Vmax_layer = surface_area*alpha_av*Su_av_z + Vmax_total += Vmax_layer + if display > 0: print(f"Vmax_layer = {Vmax_layer:.2f} N") + + layer_data.append({ + 'z_top': z_seg_top, + 'z_bot': z_seg_bot, + 'dz': dz_seg, + 'Hmax_layer': Hmax_layer, + 'ez_layer': ez_layer, + 'Su_av_z': Su_av_z, + 'D_used': D + }) + + if not layer_data: + raise ValueError('No overlapping clay layers within pile depth.') + + sum_Hmax = 0.0 + sum_ez_weighted = 0.0 + + for data in layer_data: + z_top = data['z_top'] + z_bot = data['z_bot'] + Hmax_layer = data['Hmax_layer'] + ez_layer = data['ez_layer'] + dz_layer = data['dz'] + + z_embedded_start = zlug + z_embedded_end = zlug + L + + if z_top >= z_embedded_start and z_bot <= z_embedded_end: + sum_ez_weighted += Hmax_layer*ez_layer + sum_Hmax += Hmax_layer + elif z_top < z_embedded_end and z_bot > z_embedded_start: + dz_inside = min(z_bot, z_embedded_end) - max(z_top, z_embedded_start) + if dz_inside > 0: + ratio = dz_inside/dz_layer + sum_ez_weighted += Hmax_layer*ratio*ez_layer + sum_Hmax += Hmax_layer * ratio + + ez_global = sum_ez_weighted/sum_Hmax + if display > 0: print(f'ez_global = {ez_global:.2f} m') + if display > 0: print(f'sum_Hmax = {sum_Hmax:.2f} N') + + Vmax_total += PileWeight(L1, L2, D1, D2, t, rhows) + ballast + Wp = 1.10 * PileWeight(L1, L2, D1, D2, t, rhows + rhow) + ballast + + ez_ratio = (ez_global - zlug)/L; + if display > 0: print(f"ez_ratio = {ez_ratio:.2f} m") + + # Average effective width + L = L1 + L2 + A_wing_plane_1 = (D1 - D2)*L1 + A_wing_plane_2 = (D1 - D2)*np.cos(np.deg2rad(45))/2*L1 + A_shaft = D2*L - ez_Su_den = D1*Su0*(b - a) + 0.5*D1*k*(b**2 - a**2) + D2*Su0*(c - b) + 0.5*D2*k*(c**2 - b**2) - ez_Su_num = D1*Su0*(a**2 - a*b) + 0.33*D1*k*(b**3 - a**3) + b**2*(0.5*D1*Su0 - 0.5*D1*a*k) - a**2*(0.5*D1*Su0 - 0.5*D1*a*k)\ - + D2*Su0*(b**2 - b*c) + 0.33*D2*k*(c**3 - b**3) + c**2*(0.5*D2*Su0 - 0.5*D2*b*k) - b**2*(0.5*D2*Su0 - 0.5*D2*b*k) - ez_Su = ez_Su_num/ez_Su_den - ez_Su_L = ez_Su/L - # print('ez_Su = ' +str(ez_Su)) - Np_free = 3.45 # From Np vs L/D chart from CAISSON_VHM - - Hmax = L*Dstar*Np_free*(Su0 + k*(zlug + ez_Su)) - # print('Hmax = ' +str(Hmax)) - Vmax = PileSurface(L1, L2, D1, D2)*alpha*(Su0 + k*(zlug + ez_Su)) + Wp - # print('Vmax = ' +str(Vmax)) - - #aVH = 0.5 + L/Dstar; bVH = 4.5 - L/(3*Dstar) - aVH = 4.5 + L/(2*Dstar); bVH = 3.5 - L/(4*Dstar) - #H = Ta*np.cos(np.deg2rad(resultsLoad['angle'])); V = Ta*np.sin(np.deg2rad(resultsLoad['angle'])) - #UC = (H/Hmax)**aVH + (V/Vmax)**bVH + # Choose based on direction: + plane = '1' # or '2' - deg = [0, 15, 30, 45, 60, 75, 90] - x = np.cos(np.deg2rad(deg)) - y = (1 - x**bVH)**(1/aVH) - X = Hmax*x/1e3; Y = Vmax*y/1e3 # in MN - - resultsTorpedo = {} - resultsTorpedo['Horizontal max.'] = Hmax #Hmax[0] # Capacity at specified loading angle - resultsTorpedo['Vertical max.'] = Vmax # Capacity at specified loading angle - resultsTorpedo['Weight'] = W # Dry weight of the helical pile (kN) - - return resultsTorpedo \ No newline at end of file + if plane == '1': + Dstar = (A_wing_plane_1 + A_shaft)/L + elif plane == '2': + Dstar = (A_wing_plane_2 + A_shaft)/L + + # Assign aVH and bVH based on ez_su/L + if np.isclose(ez_ratio, 2/3, atol=0.05): + aVH = 0.5 + L/Dstar + bVH = 4.5 - L/(3*Dstar) + mode = 'deep mobilization (2/3)' + elif 0.40 <= ez_ratio <= 0.75: + aVH = 4.5 + L/(2*Dstar) + bVH = 3.5 - L/(4*Dstar) + mode = 'moderate mobilization (1/2 – 3/4)' + # else: + # aVH = 4.0 + # bVH = 4.0 + # mode = 'default exponents (fallback)' + if display > 0: print(f'Interaction exponents set to aVH = {aVH:.2f}, bVH = {bVH:.2f} [{mode}]') + + UC = (Ha/sum_Hmax)**aVH + (Va/Vmax_total)**bVH + + if plot: + deg = np.linspace(0, 90, 20) + x = np.cos(np.deg2rad(deg)) + y = (1 - x**bVH)**(1/aVH) + X = sum_Hmax*x + Y = Vmax_total*y + + plt.figure(figsize=(6, 5)) + plt.plot(X, Y, color='blue', label='VH Envelope') + plt.plot(Ha, Va, 'o', color='red', label='Load Point') + plt.xlabel('Horizontal Capacity (N)') + plt.ylabel('Vertical Capacity (N)') + plt.title('VH torpedo pile capacity envelope') + plt.grid(True) + plt.legend() + plt.tight_layout() + plt.show() + + resultsTorpedo = { + 'Horizontal max.': sum_Hmax, + 'Vertical max.': Vmax_total, + 'Unity check': UC, + 'Weight pile': Wp, + 'ez_global': ez_global, + 'layer_data': layer_data} + + return layers, resultsTorpedo + +if __name__ == '__main__': + + profile_map = [ + { + 'name': 'CPT_1', + 'x': 498234, 'y': 5725141, + 'layers': [ + { + 'top': 0.0, 'bottom': 20.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 8.5, + 'Su_top': 50, 'Su_bot': 70}, + { + 'top': 20.0, 'bottom': 25.0, + 'soil_type': 'clay', + 'gamma_top': 8.5, 'gamma_bot': 8.5, + 'Su_top': 80, 'Su_bot': 100}, + { + 'top': 25.0, 'bottom': 50.0, + 'soil_type': 'clay', + 'gamma_top': 8.5, 'gamma_bot': 9.0, + 'Su_top': 125, 'Su_bot': 150}] + } + ] + + D1 = 3.0 + D2 = 1.5 + L1 = 11.0 + L2 = 5.0 + zlug = 15.0 + ballast = 10000 + Ha = 6.0e6 + Va = 8.0e6 + + layers, results = getCapacityTorpedo(profile_map, 'CPT_1', D1, D2, L1, L2, zlug, ballast, Ha, Va) + + # print("\n--- Torpedo Pile Capacity Results ---") + # for key, val in results.items(): + # if key != 'layer_data': + # print(f"{key}: {val:.2f}") + + plot_torpedo(layers, D1, D2, L1, L2, z0 = layers[0]['top'], zlug=zlug) diff --git a/famodel/anchors/anchors_famodel/installatioin_torque.py b/famodel/anchors/anchors_famodel/installatioin_torque.py new file mode 100644 index 00000000..1829ab0e --- /dev/null +++ b/famodel/anchors/anchors_famodel/installatioin_torque.py @@ -0,0 +1,176 @@ + +import numpy as np +import matplotlib.pyplot as plt +from support_soils import sand_profile + +def getInstallationHelical(profile_map, location_name, D, L, d, plot=True): + # Constants and geometry + dH = 0.05 # m + psi_p = 16.5 # degrees + delta_crit = 24 # degrees + Fr = 0.01 + + Dh = D # Helix diameter + Dc = d # Core diameter + ph = Dh/3 # Pitch + E = 210e9 # Pa + th = 0.10 # m + tc = 0.03 # m + f_y = 350e6 # Pa + f_y_weld = 250e6 # Pa (typical weld yield strength) + k = 1.04 # Bending coefficient + + profile_entry = next((p for p in profile_map if p['name'] == location_name), None) + if not profile_entry: + raise ValueError(f"Location '{location_name}' not found in profile_map") + + layers = profile_entry['layers'] + + # Assemble sand profile + profile = [] + for layer in layers: + if layer['soil_type'] == 'sand': + profile.append([layer['top'], layer['gamma_top'], layer['phi_top'], layer['Dr_top']]) + profile.append([layer['bottom'], layer['gamma_bot'], layer['phi_bot'], layer['Dr_bot']]) + + z0, f_gamma, f_phi, f_Dr, f_sigma_v_eff, f_delta = sand_profile(profile) + + def qc_depth(H): + qc0, depth0 = 0, 0 + qc1, depth1 = 8e6, 6 + qc2, depth2 = 40e6, 16 + m1 = (qc1 - qc0)/(depth1 - depth0) + m2 = (qc2 - qc1)/(depth2 - depth1) + if H <= depth1: + return m1 * H + elif H <= depth2: + return m2 * (H - depth1) + qc1 + else: + return qc2 + + def qc_average(H, Dh): + depths = np.linspace(max(0, H - 1.5*Dh), min(H + 1.5*Dh, 20), int(1.5*Dh/dH)) + return np.mean([qc_depth(z) for z in depths]) + + def calculate_torque(Dc, Dh, Fr, ph, th, dH, H): + gamma = f_gamma(H) + delta_crit_rad = np.radians(delta_crit) + a = Fr/np.tan(delta_crit_rad) + theta = np.arctan(ph/(np.pi*Dh)) + K0 = 1 - np.sin(np.radians(32)) + Tc = np.sum([a*qc_average(z, Dh)*np.tan(delta_crit_rad)*dH*(Dc**2/2) for z in np.arange(0, H, dH)]) + Tb = qc_average(H, Dh)*np.pi*(Dc**3)*np.tan(delta_crit_rad)/12 + Th = (a*qc_average(H, Dh)*np.tan(delta_crit_rad + theta)*np.pi*(Dh**3 - Dc**3)/(12*K0) + + a*qc_average(H, Dh)*th*np.tan(delta_crit_rad)*np.pi*(Dh**2)/2 + + a*qc_average(H, Dh)*th*(Dh**2 - Dc**2)/8) + return Tc + Tb + Th + + def calculate_force(Dc, Dh, Fr, ph, th, dH, H): + gamma = f_gamma(H) + delta_crit_rad = np.radians(delta_crit) + a = Fr/np.tan(delta_crit_rad) + K0 = 1 - np.sin(np.radians(32)) + Fc = np.sum([0.6*a*qc_average(z, Dh)*np.tan(delta_crit_rad)*dH*np.pi*Dc for z in np.arange(0, H, dH)]) + Fb = 0.6*qc_average(H, Dh)*np.pi*(Dc**2)/4 + Fh = (a*qc_average(H, Dh)*np.pi*(Dh**2 - Dc**2)/(4*K0) + + a*qc_average(H, Dh)*th*np.pi*Dh/K0 + + qc_average(H, Dh)*th*(Dh - Dc)/2) + return Fc + Fb + Fh + + def calculate_core(T, Fy_c, Dc, tc, E, H, K=2): + tau = 16*(T/np.pi)*(Dc/(Dc**4 - (Dc - 2*tc)**4)) + sigma_y = 4*(Fy_c/np.pi)/((Dc**2 - (Dc - 2*tc)**2)) + sigma_eq_c = np.sqrt(sigma_y**2 + 3 * tau**2) + I = (np.pi/64)*(Dc**4 - (Dc - 2*tc)**4) + Fy_cr = np.pi**2*E*I/(K*H)**2 + return sigma_eq_c, Fy_cr + + def calculate_helix(Fy_max, Dh, Dc, th, k): + q = 4*Fy_max/(np.pi*(Dh**2 - Dc**2)) + return k*q*Dh**2/(4*th**2) + + def calculate_weld_stress(Fy_max, th, Dh, weld_length): + M = Fy_max * th + Q = Fy_max + Aw = weld_length * th + sigma_w = M / (weld_length * th**2 / 6) + tau_w = Q / Aw + sigma_eq_w = np.sqrt(sigma_w**2 + 3 * tau_w**2) + return sigma_eq_w + + def calculate_axial_capacity(Dh, H): + gamma = f_gamma(H) + # phi_p = 6.6 + 11*np.log10(qc_average(H, Dh)/np.sqrt(gamma*H)) + phi_p = f_phi(H) + Fps = np.tan(np.radians(psi_p)) + np.cos(np.radians(phi_p - psi_p))*\ + (np.tan(np.radians(phi_p) - np.tan(np.radians(psi_p)))) + Fs1 = 2*Fps + Fs2 = (4/3)*Fps*np.tan(np.radians(psi_p)) + Fu = (1 + Fs1*(H/Dh) + Fs2*(H/Dh)**2)*gamma*(np.pi/4)*(Dh**2)*H + return Fu + + Tmax = 8e6 + H_max = L + H_values = np.linspace(0.1, H_max, 100) + results = { + 'H': [], 'Fu': [], 'Torque': [], 'Force': [], + 'SigmaHelix': [], 'SigmaCore': [], 'BucklingLimit': [], 'SigmaWeld': [], 'FailureMode': [] + } + + for H in H_values: + T = calculate_torque(Dc, Dh, Fr, ph, th, dH, H) + F_inst = calculate_force(Dc, Dh, Fr, ph, th, dH, H) + sigma_helix = calculate_helix(F_inst, Dh, Dc, th, k) + sigma_core, Fy_cr = calculate_core(T, F_inst, Dc, tc, E, H) + sigma_weld = calculate_weld_stress(F_inst, th, Dh, weld_length=np.pi*Dc) + Fu = calculate_axial_capacity(Dh, H) + + if T > Tmax: + failure_mode = 'Torque limit' + elif F_inst > Fy_cr: + failure_mode = 'Core buckling' + elif sigma_helix > f_y: + failure_mode = 'Helix stress' + elif sigma_weld > f_y_weld: + failure_mode = 'Weld stress' + else: + failure_mode = 'OK' + + if failure_mode == 'OK': + results['H'].append(H) + results['Fu'].append(Fu) + results['Torque'].append(T) + results['Force'].append(F_inst) + results['SigmaHelix'].append(sigma_helix) + results['SigmaCore'].append(sigma_core) + results['BucklingLimit'].append(Fy_cr) + results['SigmaWeld'].append(sigma_weld) + results['FailureMode'].append(failure_mode) + + if plot: + plt.figure(figsize=(7, 5)) + plt.plot(results['H'], results['Fu'], label=f'Dh/Dc = {Dh/Dc:.2f}') + plt.title("Fu vs H") + plt.xlabel("Depth H (m)") + plt.ylabel("Axial Capacity Fu (N)") + plt.grid(True) + plt.legend() + plt.tight_layout() + plt.show() + + return results + +if __name__ == '__main__': + profile_map = [ + { + 'name': 'CPT_1', + 'x': 0, 'y': 0, + 'layers': [ + {'top': 0.0, 'bottom': 5.0, 'soil_type': 'sand', 'gamma_top': 10, 'gamma_bot': 11, 'phi_top': 32, 'phi_bot': 36, 'Dr_top': 55, 'Dr_bot': 65}, + {'top': 5.0, 'bottom': 20.0, 'soil_type': 'sand', 'gamma_top': 11, 'gamma_bot': 12, 'phi_top': 36, 'phi_bot': 38, 'Dr_top': 65, 'Dr_bot': 80} + ] + } + ] + + results = getInstallationHelical(profile_map, 'CPT_1', D=1.5, L=10.0, d=0.5, plot=True) + \ No newline at end of file diff --git a/famodel/anchors/anchors_famodel/installation_buckling.py b/famodel/anchors/anchors_famodel/installation_buckling.py new file mode 100644 index 00000000..ee00f615 --- /dev/null +++ b/famodel/anchors/anchors_famodel/installation_buckling.py @@ -0,0 +1,164 @@ +import numpy as np +import matplotlib.pyplot as plt +from support_soils import clay_profile, sand_profile +from installation_suction import getInstallationSuction + +def compute_Zs(s, r, t, nu): + return (s**2/(r*t))*np.sqrt(1 - nu**2) + +def compute_C(psi, rho, xi): + return psi*np.sqrt(1 + (rho*xi/psi)**2) + +def gamma_M(lam_bar): + if lam_bar < 0.5: + return 1.15 + elif lam_bar <= 1.0: + return 0.85 + 0.6 * lam_bar + else: + return 1.45 + +def getBucklingSuction(profile_map, location_name, D, L, t=None, fy=345e6): + ''' + Shell buckling capacity during suction pile installation using DNV-RP-C202 and Colliard & Wallerand effective length. + ''' + E = 2.1e11 + nu = 0.3 + + if t is None: + t = D / 200 + + r = D/2 - t/2 + + profile_entry = next(p for p in profile_map if p['name'] == location_name) + layers = profile_entry['layers'] + main_type = layers[0]['soil_type'].lower() + if main_type == 'clay': + clay_input = [[layers[0]['top'], layers[0]['gamma_top'], layers[0]['Su_top']], + [layers[0]['bottom'], layers[0]['gamma_bot'], layers[0]['Su_bot']]] + _, f_gamma, _, _, _ = clay_profile(clay_input) + elif main_type == 'sand': + sand_input = [[layers[0]['top'], layers[0]['gamma_top'], layers[0]['phi_top']], + [layers[0]['bottom'], layers[0]['gamma_bot'], layers[0]['phi_bot']]] + _, f_gamma, _, _, _ = sand_profile(sand_input) + else: + raise ValueError("Unsupported soil type") + + depths = np.arange(0.1, L + 0.1, 0.1) # start from 0.1 to avoid division by zero + suction_results = getInstallationSuction(profile_map, location_name, D, L, gamma_m_install=1.5, gamma_m_retrieval=1.25) + pe_values = suction_results['delta_u_suction'] + pe_values = np.full_like(pe_values, 300e3) + + UC_list = [] + LB_list = [] + PE_list = [] + for z, pe in zip(depths, pe_values): + # Colliard & Wallerand effective length + x = L - z # exposed length + L_B = L*(1 + 2*(x/L) - 0.0435*(x/L)**2) + s = L_B + LB_list.append(s) + PE_list.append(pe/1e3) + + Zs = compute_Zs(s, r, t, nu) + + # fEa (Axial) + psi_a = 4.0 + xi_a = 0.702*Zs + rho_a = 0.5*(1 + r/(150 * t))**-0.5 + C_a = compute_C(psi_a, rho_a, xi_a) + fEa = C_a*(np.pi**2*E/(12*(1 - nu**2)))*(t/s)**2 + + # fEm (Bending) + C_m = C_a + fEm = fEa + + # fEtau (Shear) + psi_t = 5.34 + (s/L)**2 + xi_t = 0.856*(s/L)*Zs**(3/4) + rho_t = 0.6 + C_t = compute_C(psi_t, rho_t, xi_t) + fEtau = C_t*(np.pi**2*E/(12*(1 - nu**2)))*(t/s)**2 + + # fEh (Hoop) + psi_h = (1 + (s/L)**2)**2 + xi_h = 1.04*(s/L)*np.sqrt(Zs) + rho_h = 0.6 + C_h = compute_C(psi_h, rho_h, xi_h) + fEh = C_h*(np.pi**2*E/(12*(1 - nu**2)))*(t/s)**2 + + sigma_a = 0.5*pe*r/t + sigma_m = 0 + sigma_h = pe*r/t + tau = 0 + + sigma_j = np.sqrt((sigma_a)**2 - (sigma_a)*sigma_h + sigma_h**2 + 3*tau**2) + + sigma_a0 = max(0, -sigma_a) + sigma_m0 = max(0, -sigma_m) + sigma_h0 = max(0, -sigma_h) + + lam_bar_sq = (fy/sigma_j)*( + (sigma_a0/fEa) + + (sigma_m0/fEm) + + (sigma_h0/fEh) + + (tau/fEtau) + ) + lam_bar = np.sqrt(lam_bar_sq) + + gammaM = gamma_M(lam_bar) + fksd = fy/np.sqrt(1 + lam_bar**4)/gammaM + + UC = sigma_j/fksd + UC_list.append(UC) + + fig, axs = plt.subplots(1, 3, figsize=(18, 6)) + + axs[0].plot(UC_list, depths, label='UC', color='blue') + axs[0].invert_yaxis() + axs[0].set_xlabel('Unity check') + axs[0].set_ylabel('Depth (m)') + axs[0].set_title('Shell buckling UC vs. Depth') + axs[0].grid(True) + axs[0].legend() + + axs[1].plot(LB_list, depths, label='Buckling Length (L_B)', color='blue') + axs[1].invert_yaxis() + axs[1].set_xlabel('Effective buckling length (m)') + axs[1].set_ylabel('Depth (m)') + axs[1].set_title('Buckling Length vs. Depth') + axs[1].grid(True) + axs[1].legend() + + axs[2].plot(PE_list, depths, label='Underpressure', color='green') + axs[2].invert_yaxis() + axs[2].set_xlabel('Underpressure (kPa)') + axs[2].set_ylabel('Depth (m)') + axs[2].set_title('Suction Pressure vs. Depth') + axs[2].grid(True) + axs[2].legend() + + plt.tight_layout() + plt.show() + + return { + 'depths': depths.tolist(), + 'UC_list': UC_list, + 'LB_list': LB_list + } + +if __name__ == '__main__': + profile_map = [ + { + 'name': 'CPT_1', + 'x': 0, 'y': 0, + 'layers': [ + { + 'top': 0.0, 'bottom': 20.0, + 'soil_type': 'clay', + 'gamma_top': 9.0, 'gamma_bot': 9.0, + 'Su_top': 5.0, 'Su_bot': 45.0 + } + ] + } + ] + getBucklingSuction(profile_map, 'CPT_1', D=2.0, L=10.4) diff --git a/famodel/anchors/anchors_famodel/installation_buckling2.py b/famodel/anchors/anchors_famodel/installation_buckling2.py new file mode 100644 index 00000000..39e13aa1 --- /dev/null +++ b/famodel/anchors/anchors_famodel/installation_buckling2.py @@ -0,0 +1,157 @@ +import numpy as np +import matplotlib.pyplot as plt +from support_soils import clay_profile, sand_profile +from support_pycurves import py_Matlock, py_API +from installation_suction import getInstallationSuction + +def compute_Zs(s, r, t, nu): + return (s**2/(r*t))*np.sqrt(1 - nu**2) + +def compute_C(psi, rho, xi): + return psi*np.sqrt(1 + (rho*xi/psi)**2) + +def gamma_M(lam_bar): + if lam_bar < 0.5: + return 1.15 + elif lam_bar <= 1.0: + return 0.85 + 0.6*lam_bar + else: + return 1.45 + +def getBucklingSuction(profile_map, location_name, D, L): + E = 2.1e11 + fy = 325e6 + nu = 0.3 + t = (2.35 + D*20)/1e3; print(t) # Suction pile wall thickness (m), API RP2A-WSD + + R = D/2 - t/2 + + profile_entry = next(p for p in profile_map if p['name'] == location_name) + layers = profile_entry['layers'] + main_type = layers[0]['soil_type'].lower() + if main_type == 'clay': + clay_input = [[layers[0]['top'], layers[0]['gamma_top'], layers[0]['Su_top']], + [layers[0]['bottom'], layers[0]['gamma_bot'], layers[0]['Su_bot']]] + _, f_gamma, f_Su, f_sigma_v_eff, _ = clay_profile(clay_input) + elif main_type == 'sand': + sand_input = [[layers[0]['top'], layers[0]['gamma_top'], layers[0]['phi_top']], + [layers[0]['bottom'], layers[0]['gamma_bot'], layers[0]['phi_bot']]] + _, f_gamma, f_phi, f_Dr, f_sigma_v_eff, _ = sand_profile(sand_input) + else: + raise ValueError("Unsupported soil type") + + depths = np.arange(0.1, L + 0.1, 0.1) + suction_results = getInstallationSuction(profile_map, location_name, D, L, gamma_m_install=1.5, gamma_m_retrieval=1.25) + pe_values = np.interp(depths, suction_results['depths'], suction_results['delta_u_suction']) + + def soil_type_map(z): + for layer in layers: + if layer['top'] <= z <= layer['bottom']: + return layer['soil_type'].lower() + raise ValueError(f"No soil type defined at depth {z}") + + alpha_list = [] + y_disp = 0.001 + for z in depths: + stype = soil_type_map(z) + if stype == 'clay': + py_func, _ = py_Matlock(z, D, f_gamma(z), f_Su(z), f_sigma_v_eff(z), return_curve=True) + elif stype == 'sand': + py_func, _ = py_API(z, D, f_phi(z), f_sigma_v_eff(z), f_Dr(z), return_curve=True) + else: + raise ValueError(f"Unsupported soil type at depth {z}") + stiffness = py_func(y_disp)/y_disp if y_disp != 0 else 0 + alpha_list.append(stiffness) + alpha_array = np.array(alpha_list) + integral_total = np.trapz(alpha_array, depths) + alpha_z = np.cumsum(alpha_array)*(depths[1] - depths[0])/integral_total + + UC_list = [] + PE_list = [] + + for z, pe, alpha in zip(depths[:-1], pe_values[:-1], alpha_z[:-1]): + s = L # constant buckling length + PE_list.append(pe) + + Zs = compute_Zs(s, R, t, nu) + + psi_a = 4.0 + xi_a = 0.702*Zs + rho_a = 0.5*(1 + R/(150*t))**-0.5 + C_a = compute_C(psi_a, rho_a, xi_a) + fEa = C_a*(np.pi**2*E/(12*(1 - nu**2)))*(t/s)**2 + + C_m = C_a + fEm = fEa + + psi_h = (1 + (s/L)**2)**2 + xi_h = 1.04*(s/L)*np.sqrt(Zs) + rho_h = 0.6 + C_h = compute_C(psi_h, rho_h, xi_h) + fEh = C_h*(np.pi**2 *E/(12*(1 - nu**2)))*(t/s)**2 + + psi_t = 5.34 + (s/L)**2 + xi_t = 0.856*(s/L)*Zs**(3/4) + rho_t = 0.6 + C_t = compute_C(psi_t, rho_t, xi_t) + fEtau = C_t*(np.pi**2*E/(12*(1 - nu**2)))*(t/s)**2 + + sigma_a = 0.5*pe*R*(1 - alpha)/t + sigma_m = 0 + sigma_h = pe*R*(1 - alpha)/t + tau = 0 + + sigma_j = np.sqrt((sigma_a)**2 - (sigma_a)*sigma_h + sigma_h**2 + 3*tau**2) + + sigma_a0 = max(0, -sigma_a) + sigma_m0 = max(0, -sigma_m) + sigma_h0 = max(0, -sigma_h) + + lam_bar_sq = (fy/sigma_j)*( + (sigma_a0/fEa) + + (sigma_m0/fEm) + + (sigma_h0/fEh) + + (tau/fEtau) + ) + lam_bar = np.sqrt(lam_bar_sq) + + gammaM = gamma_M(lam_bar) + fksd = fy/np.sqrt(1 + lam_bar**4)/gammaM + + UC = sigma_j/fksd + UC_list.append(UC) + + plt.figure(figsize=(6, 6)) + plt.plot(UC_list, depths[:-1], label='UC (with confinement)', color='darkred') + plt.gca().invert_yaxis() + plt.xlabel('Unity Check') + plt.ylabel('Depth (m)') + plt.title('Shell Buckling') + plt.grid(True) + plt.legend() + plt.tight_layout() + plt.show() + + return { + 'depths': depths.tolist(), + 'UC_list': UC_list, + 'PE_list': PE_list, + 'alpha_z': alpha_z.tolist() + } + +if __name__ == '__main__': + profile_map = [ + { + 'name': 'CLAY_INSTALL', + 'x': 0, 'y': 0, + 'layers': [ + { + 'top': 0.0, 'bottom': 20.0, + 'soil_type': 'clay', + 'gamma_top': 9.0, 'gamma_bot': 9.0, + 'Su_top': 5.0, 'Su_bot': 85.0 + } + ] + } + ] + getBucklingSuction(profile_map, 'CLAY_INSTALL', D=4.0, L=17.0) diff --git a/famodel/anchors/anchors_famodel/capacity_drag.py b/famodel/anchors/anchors_famodel/installation_drag.py similarity index 95% rename from famodel/anchors/anchors_famodel/capacity_drag.py rename to famodel/anchors/anchors_famodel/installation_drag.py index d17969e2..c476c3ce 100644 --- a/famodel/anchors/anchors_famodel/capacity_drag.py +++ b/famodel/anchors/anchors_famodel/installation_drag.py @@ -1,14 +1,9 @@ -""" -Drag embedment anchor capacity calculation functions in intermidiate model, -currently set up for clay soils. -Lead author: Felipe Moreno. -""" import yaml # Allow access to config file for user inputs import numpy as np import matplotlib.pyplot as plt -def getCapacityDrag(Af, Lf, Ls, Lca, Lj, thetafs, bm, En, +def getInstallationDrag(Af, Lf, Ls, Lca, Lj, thetafs, bm, En, nhu, Su0, k, Ne, thetae0, z0, Nn_max, Nt_max, Nm_max, m, n, p, q, plot=True): @@ -78,7 +73,7 @@ def getCapacityDrag(Af, Lf, Ls, Lca, Lj, thetafs, bm, En, Vf = Af*tf Vs = Ls*ts*Ws*2 Va = round(Vf + Vs,1) - W = Va*rhos + Wp = Va*rhos # The Anchor Initial Condition Su = Su0 + k*z0 # Undrained shear strength at the initial embedded depth, kPa @@ -104,7 +99,7 @@ def getCapacityDrag(Af, Lf, Ls, Lca, Lj, thetafs, bm, En, thetaf_values = [] z = z0; x = x0; Ta = Ta0 - xmax = 60; Tmax = 30000; + xmax = 60; Tmax = 3000; for _ in range(3000): thetaaf = thetaf + thetaa @@ -164,10 +159,10 @@ def getCapacityDrag(Af, Lf, Ls, Lca, Lj, thetafs, bm, En, plt.show() resultsDrag = {} - resultsDrag['capacity'] = max(Ta_values) - resultsDrag['W'] = W + resultsDrag['Capacity'] = max(Ta_values) resultsDrag['embedment_depth'] = z resultsDrag['drag_distance'] = x + resultsDrag['Weight plate'] = Wp return resultsDrag @@ -189,7 +184,7 @@ def getCapacityDrag(Af, Lf, Ls, Lca, Lj, thetafs, bm, En, m = configDrag['m']; n = configDrag['n']; p = configDrag['p']; q = configDrag['q']; z0 = configDrag['z0']; - resultsDrag = getCapacityDrag(Af, Lf, Ls, Lca, Lj, thetafs, bm,En, + resultsDrag = getInstallationDrag(Af, Lf, Ls, Lca, Lj, thetafs, bm,En, nhu, Su0, k, Ne, thetae0, z0, Nn_max, Nt_max, Nm_max, m, n, p, q) diff --git a/famodel/anchors/anchors_famodel/installation_driven.py b/famodel/anchors/anchors_famodel/installation_driven.py new file mode 100644 index 00000000..9bb85e9d --- /dev/null +++ b/famodel/anchors/anchors_famodel/installation_driven.py @@ -0,0 +1,186 @@ +import numpy as np +import matplotlib.pyplot as plt +from capacity_soils_map import clay_profile, sand_profile, rock_profile + +def getInstallationDriven(profile_map, location_name, D, L, hammer, J_shaft, J_toe, plot=True, refusal_threshold=0.002, refusal_count=10): + dz = 0.24 + z0 = 1.0 + max_depth = L + N = int((max_depth - z0) / dz) + + t_wall = (6.35 + D * 20) / 1e3 + D_inner = D - 2 * t_wall + A = np.pi / 4 * (D**2 - D_inner**2) + E = 2.1e11 + rhos = 7850 + g = 9.81 + + m = rhos*A*dz + k = E*A/dz + dt = N/np.sqrt(E/rhos) + + m_r = hammer['m_r'] + h = hammer['h'] + eta = hammer['efficiency'] + E_hammer = eta*m_r*g*h + v0 = np.sqrt(2 * E_hammer / m_r) + + soil = profile_map[location_name] + layers = soil['layers'] + + def compute_Rdynamic(v_local, z, J): + for layer in layers: + if layer['top'] <= z <= layer['bottom']: + if layer['soil_type'] == 'clay': + profile = [[layer['top'], layer['gamma_top'], layer['Su_top']], + [layer['bottom'], layer['gamma_bot'], layer['Su_bot']]] + _, _, _, _, f_alpha = clay_profile(profile) + return J*f_alpha(z)*v_local*np.pi*D + elif layer['soil_type'] == 'sand': + profile = [[layer['top'], layer['gamma_top'], layer['phi_top'], layer['Dr_top']], + [layer['bottom'], layer['gamma_bot'], layer['phi_bot'], layer['Dr_bot']]] + _, _, _, _, _, f_delta = sand_profile(profile) + return J*f_delta(z)*v_local*np.pi*D + elif layer['soil_type'] == 'rock': + profile = [[layer['top'], layer['UCS_top'], layer['Em_top']], + [layer['bottom'], layer['UCS_bot'], layer['Em_bot']]] + _, f_UCS, _ = rock_profile(profile) + return J*f_UCS(z)*v_local*np.pi*D + return 0.0 + + def compute_Rstatic(z): + for layer in layers: + if layer['top'] <= z <= layer['bottom']: + if layer['soil_type'] == 'clay': + profile = [[layer['top'], layer['gamma_top'], layer['Su_top']], + [layer['bottom'], layer['gamma_bot'], layer['Su_bot']]] + _, _, _, _, f_alpha = clay_profile(profile) + return f_alpha(z)*np.pi*D*dz + elif layer['soil_type'] == 'sand': + profile = [[layer['top'], layer['gamma_top'], layer['phi_top'], layer['Dr_top']], + [layer['bottom'], layer['gamma_bot'], layer['phi_bot'], layer['Dr_bot']]] + _, _, _, _, _, f_delta = sand_profile(profile) + return f_delta(z)*np.pi*D*dz + elif layer['soil_type'] == 'rock': + profile = [[layer['top'], layer['UCS_top'], layer['Em_top']], + [layer['bottom'], layer['UCS_bot'], layer['Em_bot']]] + _, f_UCS, _ = rock_profile(profile) + return f_UCS(z)*np.pi*D*dz + return 0.0 + + penetration = 0.0 + total_energy = 0.0 + toe_displacement = [] + blow_counts = [] + consecutive_small_blows = 0 + + blow = 0 + while penetration < (max_depth - z0): + u = np.zeros(N + 1) + v = np.zeros(N + 1) + a = np.zeros(N + 1) + + # Apply initial velocity to first node to help energy propagate + v[0] = v0 + T = 0.5 + nsteps = int(T/dt) + + for step in range(nsteps): + F_internal = np.zeros(N + 1) + for i in range(1, N): + F_internal[i] = k*(u[i - 1] - 2*u[i] + u[i + 1]) + + F_internal[N] = k*(u[N - 1] - u[N]) + + for i in range(N + 1): + z = dz*i + z0 + + if i == N: + F_internal[i] -= compute_Rdynamic(v[i], z, J_toe) + F_internal[i] += compute_Rstatic(z) + else: + F_internal[i] -= compute_Rdynamic(v[i], z, J_shaft) + + if step < 10: + print(f" Step {step}: z = {z:.2f}, Rd = {compute_Rdynamic(v[i], z, J_shaft):.2f}, v = {v[i]:.4f}, u = {u[i]:.4f}") + + a = np.nan_to_num(F_internal / m, nan=0.0, posinf=0.0, neginf=0.0) + v += a * dt + u += v * dt + + if np.any(np.abs(u) > 5): + print("Displacement blew up. Stopping.") + break + + delta_z = u[-1] + penetration += delta_z + + toe_displacement.append(penetration) + blow_counts.append(blow + 1) + total_energy += E_hammer + + print(f"Blow {blow + 1}: Δz = {delta_z:.5f} m, Total Penetration = {penetration:.3f} m") + + if abs(delta_z) < refusal_threshold: + consecutive_small_blows += 1 + else: + consecutive_small_blows = 0 + + if consecutive_small_blows >= refusal_count: + print("Refusal criteria met: 10 consecutive blows with <2 mm displacement") + break + + blow += 1 + + if plot: + plt.figure(figsize=(8, 4)) + plt.plot(blow_counts, toe_displacement, marker='o') + plt.xlabel('Blow Count') + plt.ylabel('Cumulative Toe Displacement (m)') + plt.title('Toe Displacement vs Blow Count') + plt.grid(True) + plt.tight_layout() + plt.show() + + return { + 'blow_counts': blow_counts, + 'toe_displacement': toe_displacement, + 'total_energy': total_energy, + 'final_depth': penetration, + 'total_counts': len(blow_counts) + } + +if __name__ == '__main__': + profile_map = { + 'CPT_1': { + 'type': 'clay', + 'x': 498234, 'y': 5725141, + 'layers': [ + { + 'top': 1.0, 'bottom': 6.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 8.0, + 'Su_top': 10, 'Su_bot': 20}, + { + 'top': 6.0, 'bottom': 15.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 8.0, + 'Su_top': 80, 'Su_bot': 100}, + { + 'top': 15.0, 'bottom': 30.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 9.0, + 'Su_top': 100, 'Su_bot': 200} + ] + } + } + + D = 1.0 + L = 12.0 + hammer = {'m_r': 85000, 'h': 5.5, 'efficiency': 0.85} + J_shaft = 0.05 + J_toe = 0.05 + + results = getInstallationDriven(profile_map, 'CPT_1', D, L, hammer, J_shaft, J_toe, plot=True) + for key, val in results.items(): + print(f"{key}: {val}") diff --git a/famodel/anchors/anchors_famodel/installation_driven2.py b/famodel/anchors/anchors_famodel/installation_driven2.py new file mode 100644 index 00000000..db007b64 --- /dev/null +++ b/famodel/anchors/anchors_famodel/installation_driven2.py @@ -0,0 +1,167 @@ +import numpy as np +import matplotlib.pyplot as plt +from capacity_soils_map import clay_profile, sand_profile, rock_profile + +def compute_Rstatic(z): + for layer in layers: + if layer['top'] <= z <= layer['bottom']: + if layer['soil_type'] == 'clay': + profile = [[layer['top'], layer['gamma_top'], layer['Su_top']], + [layer['bottom'], layer['gamma_bot'], layer['Su_bot']]] + _, _, _, _, f_alpha = clay_profile(profile) + return f_alpha(z)*np.pi*D*dz + elif layer['soil_type'] == 'sand': + profile = [[layer['top'], layer['gamma_top'], layer['phi_top'], layer['Dr_top']], + [layer['bottom'], layer['gamma_bot'], layer['phi_bot'], layer['Dr_bot']]] + _, _, _, _, _, f_delta = sand_profile(profile) + return f_delta(z)*np.pi*D*dz + elif layer['soil_type'] == 'rock': + profile = [[layer['top'], layer['UCS_top'], layer['Em_top']], + [layer['bottom'], layer['UCS_bot'], layer['Em_bot']]] + _, f_UCS, _ = rock_profile(profile) + return f_UCS(z)*np.pi*D*dz + return 0.0 + +def compute_Rdynamic(v_local, z, J): + for layer in layers: + if layer['top'] <= z <= layer['bottom']: + if layer['soil_type'] == 'clay': + profile = [[layer['top'], layer['gamma_top'], layer['Su_top']], + [layer['bottom'], layer['gamma_bot'], layer['Su_bot']]] + _, _, _, _, f_alpha = clay_profile(profile) + return J*f_alpha(z)*v_local*np.pi*D + elif layer['soil_type'] == 'sand': + profile = [[layer['top'], layer['gamma_top'], layer['phi_top'], layer['Dr_top']], + [layer['bottom'], layer['gamma_bot'], layer['phi_bot'], layer['Dr_bot']]] + _, _, _, _, _, f_delta = sand_profile(profile) + return J*f_delta(z)*v_local*np.pi*D + elif layer['soil_type'] == 'rock': + profile = [[layer['top'], layer['UCS_top'], layer['Em_top']], + [layer['bottom'], layer['UCS_bot'], layer['Em_bot']]] + _, f_UCS, _ = rock_profile(profile) + return J*f_UCS(z)*v_local*np.pi*D + return 0.0 + +def getInstallationDriven(profile_map, location_name, D_input, L, hammer, J_shaft, J_toe, plot): + global D, dz, layers + D = D_input + soil = profile_map[location_name] + layers = soil['layers'] + z0 = layers[0]['top'] + + N = 100 + z = np.linspace(z0, L, N) + dz = z[1] - z[0] + + dt = 0.001 + t_max = 2.0 + time = np.arange(0, t_max, dt) + + u = np.zeros((len(time), N)) + v = np.zeros((len(time), N)) + F = np.zeros((len(time), N)) + + rho_steel = 7850 + t = 0.05 + A = np.pi * ((D / 2)**2 - ((D / 2) - t)**2) + m_total = A * L * rho_steel + M_prime = m_total / N + + m_r = hammer['m_r'] + h = hammer['h'] + eff = hammer['efficiency'] + E = m_r * 9.81 * h * eff + + blow_count = 0 + penetration = 0.0 + z_vals = [] + blow_vals = [] + refusal_counter = 0 + refusal_limit = 10 + min_set = 0.002 + + while penetration < L and refusal_counter < refusal_limit: + blow_count += 1 + v0 = np.sqrt(2 * E / m_r) + v[0, 0] = v0 + + for n in range(1, len(time)): + for i in range(1, N - 1): + u_xx = (u[n - 1, i + 1] - 2 * u[n - 1, i] + u[n - 1, i - 1]) / dz**2 + F[n, i] = M_prime * u_xx + + v[n] = v[n - 1] + (F[n] / M_prime) * dt + u[n] = u[n - 1] + v[n] * dt + + delta_z = max(u[-1, :]) + tip_depth = penetration + delta_z + + Rs = compute_Rstatic(tip_depth) + Rt = 9.0 * compute_Rstatic(tip_depth) + R_total = Rs + Rt + compute_Rdynamic(v[-1, -1], tip_depth, J_shaft) + + penetration += delta_z + z_vals.append(penetration) + blow_vals.append(blow_count) + + if delta_z < min_set: + refusal_counter += 1 + else: + refusal_counter = 0 + + if plot: + plt.figure() + plt.plot(z_vals, blow_vals, label='Blows vs Penetration') + plt.xlabel('Penetration Depth [m]') + plt.ylabel('Blow Count') + plt.title('Driveability Simulation') + plt.grid(True) + plt.legend() + plt.show() + + return { + 'z': z, + 'z_vals': z_vals, + 'blow_vals': blow_vals, + 'u': u, + 'v': v, + 'F': F, + 'dt': dt, + 'dz': dz + } + + +if __name__ == '__main__': + profile_map = { + 'CPT_1': { + 'type': 'clay', + 'x': 498234, 'y': 5725141, + 'layers': [ + { + 'top': 1.0, 'bottom': 6.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 8.0, + 'Su_top': 10, 'Su_bot': 20}, + { + 'top': 6.0, 'bottom': 15.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 8.0, + 'Su_top': 80, 'Su_bot': 100}, + { + 'top': 15.0, 'bottom': 30.0, + 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 9.0, + 'Su_top': 100, 'Su_bot': 200} + ] + } + } + + D = 1.0 + L = 12.0 + hammer = {'m_r': 155000, 'h': 5.5, 'efficiency': 0.85} + J_shaft = 0.05 + J_toe = 0.05 + + results = getInstallationDriven(profile_map, 'CPT_1', D, L, hammer, J_shaft, J_toe, plot=True) + for key, val in results.items(): + print(f"{key}: {val}") \ No newline at end of file diff --git a/famodel/anchors/anchors_famodel/installation_dynamic.py b/famodel/anchors/anchors_famodel/installation_dynamic.py new file mode 100644 index 00000000..95c97834 --- /dev/null +++ b/famodel/anchors/anchors_famodel/installation_dynamic.py @@ -0,0 +1,164 @@ + +import numpy as np +import matplotlib.pyplot as plt +from support_soils import clay_profile + +def PileWeight(L1, L2, D1, D2, tw, rho): + return ((np.pi/4)*(D1**2 - (D1 - 2*tw)**2)*(L1 + L2) + 4*L2*D2*tw)*rho + +def PileVolume(L1, L2, D1, D2, tw): + return (np.pi/4)*D1**2*(L1 + L2) + 4*L2*D2*tw + +def PileWingedSurface(length, diameter1, diameter2): + return 8*length*(diameter1 - diameter2) + +def PileShaftSurface(length, diameter): + return np.pi*diameter*length + +def getInstallationDynamic(profile_map, location_name, D1, D2, L1, L2, ballast, drop_height, plot=True): + """ + Deterministic installation model of a torpedo pile in clay based on time-domain integration. + Implements the model by True (1976) as adapted in Kazue et al. (2020), accounting for layered soil. + """ + # Constants + rhows = 66.90e3 # Submerged steel specific weight (N/m3) + rhow = 10e3 # Water specific weight (N/m3) + Sti = 3.0 + Se = 5.0 + Ce = 0.02 + delta = 0.9 + Nc = 9.0 + CD = 2.7 + dt = 0.002 + tmax = 15.0 + beta = 28/27 + g = 9.81 + + # Geometry + D = D1 # use the wing diameter for frontal area + L = L1 + L2 + t = (6.35 + D2*20)/1e3 # assumed same as in getCapacityTorpedo + + # Retrieve soil profile and construct full profile list + profile_entry = next(p for p in profile_map if p['name'] == location_name) + layers = profile_entry['layers'] + profile = [] + for layer in layers: + if layer['soil_type'] != 'clay': + continue + profile.append([layer['top'], layer['Su_top'], layer['gamma_top']]) + profile.append([layer['bottom'], layer['Su_bot'], layer['gamma_bot']]) + + # Sort and remove duplicates if needed + # profile = sorted(list({(z, su, g) for z, su, g in profile}), key=lambda x: x[0]) + z_ref, f_gamma, f_Su, _, f_delta = clay_profile(profile) + + # Precompute parameters + Af = np.pi*(D2**2)/4 + 4*(D2 - D1)*t + As = PileWingedSurface(L1, D1, D2) + PileShaftSurface(L1 + L2, D2) + Vol = PileVolume(L1, L2, D1, D2, t) + Wp = PileWeight(L1, L2, D1, D2, t, rhows) + ballast; #print(f'Wp = {Wp:.2f} N') + M = Wp/g + Mprime = M + 2*rhow*Vol + + # Closed-form solution for v_impact from free fall in water + CD_water = 1.2 + A_water = Af + vt = np.sqrt((2*Mprime*g)/(rhow*CD_water*A_water)) + t_impact = (vt/g)*np.arccosh(np.exp(g*drop_height/vt**2)) + v_impact = vt*np.tanh(g*t_impact/vt) + + # Initial conditions + t = [0.0] + z = [0.0] + v = [v_impact] + a = [Wp/Mprime] + + # Integration constants + beta1 = dt**2*(0.5 - beta) + beta2 = dt**2*beta + gamma1 = -0.5*dt + gamma2 = 1.5*dt + nsteps = int(tmax/dt) + + for i in range(nsteps): + zn = z[-1] + vn = v[-1] + an = a[-1] + + Su = f_Su(zn) + gamma = f_gamma(zn) + delta = f_delta(zn) + rho = gamma/g + Se_dot = Se/(1 + (1/np.sqrt(Ce*vn/(Su*D2)) + 0.06)) if vn > 0 else 1.0 + + Mprime_local = M + 2*rho*Vol + FD = 0.5*rhow*CD*Af*vn*abs(vn) + FT = Su*Nc*Af*Se_dot + FS = Su*As*delta*Se_dot/Sti + + f_total = (Wp - Vol*gamma) - FD - FT - FS + an1 = f_total/Mprime_local + + zn1 = zn + dt*vn + beta1*an + beta2*an1 + vn1 = vn + gamma1*an + gamma2*an1 + + if vn1 < 0: + break # penetration stops + + t.append(t[-1] + dt) + z.append(zn1) + v.append(vn1) + a.append(an1) + + if plot: + fig, ax1 = plt.subplots() + ax1.plot(t, z, 'b', label='Penetration depth (m)') + ax1.set_xlabel('Time (s)') + ax1.set_ylabel('Depth (m)') + ax1.grid(True) + + ax2 = ax1.twinx() + ax2.plot(t, v, 'r', label='Velocity (m/s)') + ax2.set_ylabel('Velocity (m/s)') + + fig.suptitle('Torpedo Pile Installation Response') + fig.legend(loc='upper right') + plt.tight_layout() + plt.show() + + return { + 'final_depth': z[-1], + 'max_velocity': max(v), + 'penetration_time': t[-1] + } + +if __name__ == '__main__': + profile_map = [ + { + 'name': 'CPT_1', + 'x': 0, 'y': 0, + 'layers': [ + {'top': 0.0, 'bottom': 30.0, 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 8.5, + 'Su_top': 5, 'Su_bot': 20}, + {'top': 30.0, 'bottom': 100.0, 'soil_type': 'clay', + 'gamma_top': 8.5, 'gamma_bot': 9.0, + 'Su_top': 20, 'Su_bot': 60} + ] + } + ] + + location = 'CPT_1' + D1 = 3.0 + D2 = 1.5 + L1 = 5.0 + L2 = 5.0 + ballast = 350000 + drop_height = 200 + + results = getInstallationDynamic(profile_map, location, D1, D2, L1, L2, ballast, drop_height) + + print("\n--- Torpedo Installation Results ---") + for k, v in results.items(): + print(f"{k}: {v:.2f}") diff --git a/famodel/anchors/anchors_famodel/installation_dynamic2.py b/famodel/anchors/anchors_famodel/installation_dynamic2.py new file mode 100644 index 00000000..f55c7f21 --- /dev/null +++ b/famodel/anchors/anchors_famodel/installation_dynamic2.py @@ -0,0 +1,152 @@ +import numpy as np +import matplotlib.pyplot as plt +from support_soils import clay_profile + +def PileWeight(L1, L2, D1, D2, tw, gamma): + return ((np.pi/4)*(D1**2 - (D1 - 2*tw)**2)*(L1 + L2) + 4*L2*D2*tw)*gamma + +def PileVolume(L1, L2, D1, D2, tw): + return (np.pi/4)*D1**2*(L1 + L2) + 4*L2*D2*tw + +def PileWingedSurface(length, diameter1, diameter2): + return 8*length*(diameter1 - diameter2) + +def PileShaftSurface(length, diameter): + return np.pi*diameter*length + +def getInstallationDynamic(profile_map, location_name, D1, D2, L1, L2, ballast, drop_height, plot=True): + """ + Penetration of torpedo pile using depth-based formulation (Eq. 2.10). + """ + # Constants + rhows = 66.90e3 # Submerged unit weight of steel (N/m³) + rhow = 10e3 # Unit weight of water (N/m³) + Sti = 2.0 # Installation strain-rate index (-), affects side friction strain-rate correction + Se = 5.0 # Strain-rate multiplier (-), empirical factor for rate effects + Ce = 0.02 # Strain-rate coefficient (-), controls shape of strain-rate correction + Nc = 9.0 # Bearing capacity factor for undrained clay [-], used in tip resistance (q = Nc * Su) + CD = 2.7 # Drag coefficient (-), for a cylindrical body falling in water + dz = 1 # Depth increment (m), used in depth-stepping integration + g = 9.81 # Gravitational acceleration (m/s²) + + + # Geometry + D = D1 + L = L1 + L2 + t = (6.35 + D2*20)/1e3 + + # Soil profile + profile_entry = next(p for p in profile_map if p['name'] == location_name) + layers = profile_entry['layers'] + profile = [] + for layer in layers: + if layer['soil_type'] != 'clay': continue + profile.append([layer['top'], layer['gamma_top'], layer['Su_top']]) + profile.append([layer['bottom'], layer['gamma_bot'], layer['Su_bot']]) + # profile = sorted(list({(z, su, g) for z, su, g in profile}), key=lambda x: x[0]) + z0, f_gamma, f_Su, _, f_delta = clay_profile(profile) + # print('\n--- f_gamma and f_Su vs Depth ---') + # z_start = z0 + # z_end = profile[-1][0] + # z_vals = np.linspace(z_start, z_end, 10) + # for z_val in z_vals: + # gamma_val = f_gamma(z_val) + # Su_val = f_Su(z_val) + # print(f'z = {z_val:.1f} m → gamma = {gamma_val:.2f} N/m³, Su = {Su_val:.2f} Pa') + + # Parameters + Af = np.pi*(D2**2)/4 + 4*(D2 - D1)*t + As = PileWingedSurface(L1, D1, D2) + PileShaftSurface(L1 + L2, D2) + Vol = PileVolume(L1, L2, D1, D2, t) + Wp = PileWeight(L1, L2, D1, D2, t, rhows + rhow) + ballast; print(f'Wp = {Wp:.2f} N') + M = Wp/g + Mprime = M + 2*f_gamma(2*L/3)*Vol + + CD_water = 1.2 + vt = np.sqrt((2*Mprime*g)/(rhow*CD_water*Af)) + t_impact = (vt/g)*np.arccosh(np.exp(g*drop_height/vt**2)) + v_impact = vt*np.tanh(g*t_impact/vt) + + # Loop + v = [v_impact]; #print(v) + z = [0.0] + term1_values, term2_values = [0.0], [0.0] + i = 0 + while v[-1] > 0: + zi = z[-1] + vi = v[-1] + Sui = f_Su(zi); #print(f'Sui = {Sui:.2f} Pa') + gammai = f_gamma(zi); #print(f'gammai = {gammai:.2f} N/m3') + rhoi = gammai/g; #print(f'rhoi = {rhoi:.2f} kg/m3') + deltai = f_delta(zi) + Mprime_local = M + 2*rhoi*Vol + term1 = (Wp - Vol*gammai) - (0.5*CD*rhoi*Af*vi**2); #print(f'term1 = {term1:.2f} N') + term2 = Sui*(Af*Nc + As*deltai/Sti) + Se_dot = Se/(1 + (1/np.sqrt(Ce*vi/(Sui*D)) + 0.06)); #print(f'Se_dot = {Se_dot:.2f}') + top = 2*dz*(term1 - term2)*Se_dot; #print(f'top = {top:.2f}') + bottom = vi*Mprime_local; #print(f'bottom = {bottom:.2f}') + vi1 = vi + top/bottom + if vi1 < 0.01: + print(f'Stopping due to low velocity at z = {zi:.2f} m') + break + + v.append(vi1) + z.append(zi + dz) + term1_values.append(term1) + term2_values.append(term2) + i += 1 + #print(f'z = {zi:.2f} m | term1 (drive) = {term1:.2f} N | term2 (resist) = {term2:.2f} N | net = {term1 - term2:.2f} N') + + if plot: + fig, ax1 = plt.subplots() + ax1.plot(z, v, 'b', label='Velocity vs Depth') + ax1.set_xlabel('Depth (m)') + ax1.set_ylabel('Velocity (m/s)') + + ax2 = ax1.twinx() + ax2.plot(z, term1_values, 'r', label='Drive (N)') + ax2.plot(z, term2_values, 'g', label='Resist (N)') + ax2.set_ylabel('Forces (N)') + + ax1.grid(True) + plt.title('Depth-based Penetration of Torpedo Pile') + plt.legend(loc='upper right') + plt.tight_layout() + plt.show() + + return { + 'final_depth': z[-1], + 'v_max': max(v), + 'v_impact': v_impact, + 'steps': i + } + +if __name__ == '__main__': + profile_map = [ + { + 'name': 'CPT_1', + 'x': 0, 'y': 0, + 'layers': [ + {'top': 0.0, 'bottom': 60.0, 'soil_type': 'clay', + 'gamma_top': 8.5, 'gamma_bot': 8.5, + 'Su_top': 5, 'Su_bot': 85}, + {'top': 40.0, 'bottom': 400.0, 'soil_type': 'clay', + 'gamma_top': 8.5, 'gamma_bot': 8.5, + 'Su_top': 85, 'Su_bot': 805} + ] + } + ] + + location = 'CPT_1' + D1 = 3.0 + D2 = 1.5 + L1 = 10.0 + L2 = 5.0 + ballast = 10000 + drop_height = 20 + + results = getInstallationDynamic(profile_map, location, D1, D2, L1, L2, ballast, drop_height) + + print("\n--- Torpedo Installation Results ---") + for k, v in results.items(): + print(f"{k}: {v:.2f}") diff --git a/famodel/anchors/anchors_famodel/installation_dynamic3.py b/famodel/anchors/anchors_famodel/installation_dynamic3.py new file mode 100644 index 00000000..625b4161 --- /dev/null +++ b/famodel/anchors/anchors_famodel/installation_dynamic3.py @@ -0,0 +1,126 @@ + +import numpy as np +import matplotlib.pyplot as plt +from installation_dynamic import getInstallationDynamic +from scipy.stats import lognorm + +def getInstallationDynamicMC(profile_map, location, D1, D2, L1, L2, ballast, drop_height, N_sim=2000): + np.random.seed(16) + + # Lognormal distribution parameters + Suk_mean, Suk_std = 1.9, 0.9 + Sti_mean, Sti_std = 3.2, 1.0 + + Suk_samples = np.random.lognormal(mean=np.log(Suk_mean), sigma=Suk_std/Suk_mean, size=N_sim) + Sti_samples = np.random.lognormal(mean=np.log(Sti_mean), sigma=Sti_std/Sti_mean, size=N_sim) + + final_depths = [] + + for Suk, Sti in zip(Suk_samples, Sti_samples): + # Update profile with consistent linear Su(z) + profile = [dict(profile_map[0])] + Su0 = profile[0]['layers'][0]['Su_top'] + for layer in profile[0]['layers']: + z_top = layer['top'] + z_bot = layer['bottom'] + layer['Su_top'] = Su0 + Suk*z_top + layer['Su_bot'] = Su0 + Suk*z_bot + + # Override getInstallationDynamic with fixed Sti + result = getInstallationDynamic(profile, location, D1, D2, L1, L2, ballast, drop_height, plot=False) + + final_depths.append(result['final_depth']) + + # Fit lognormal distribution to the data + shape, loc, scale = lognorm.fit(final_depths, floc=0) + x = np.linspace(min(final_depths), max(final_depths), 500) + pdf = lognorm.pdf(x, shape, loc=loc, scale=scale) + + # Create subplot + fig, axs = plt.subplots(1, 2, figsize=(12, 5)) + + # Fit lognormals + s_Suk, loc_Suk, scale_Suk = lognorm.fit(Suk_samples, floc=0) + s_Sti, loc_Sti, scale_Sti = lognorm.fit(Sti_samples, floc=0) + + # Generate x values for plotting + x_Suk = np.linspace(min(Suk_samples), max(Suk_samples), 500) + x_Sti = np.linspace(min(Sti_samples), max(Sti_samples), 500) + + # Compute PDFs + pdf_Suk = lognorm.pdf(x_Suk, s_Suk, loc=loc_Suk, scale=scale_Suk) + pdf_Sti = lognorm.pdf(x_Sti, s_Sti, loc=loc_Sti, scale=scale_Sti) + + # Compute max density from histograms and PDFs for setting common ylim + hist_Suk_vals, _ = np.histogram(Suk_samples, bins=40, density=True) + hist_Sti_vals, _ = np.histogram(Sti_samples, bins=40, density=True) + y_max = max(max(hist_Suk_vals), max(hist_Sti_vals), max(pdf_Suk), max(pdf_Sti)) * 1.1 + + # Plot Suk PDF + axs[0].hist(Suk_samples, bins=40, density=True, alpha=0.6, color='lightgreen', edgecolor='g', label='Samples') + axs[0].plot(x_Suk, pdf_Suk, 'r', label='Fitted Lognormal') + axs[0].set_title('Lognormal Fit for $S_{uk}$') + axs[0].set_xlabel('Suk (kPa/m)') + axs[0].set_ylabel('Density') + axs[0].set_ylim(0, y_max) + axs[0].legend() + axs[0].grid(True) + + # Plot Sti PDF + axs[1].hist(Sti_samples, bins=40, density=True, alpha=0.6, color='lightblue', edgecolor='b', label='Samples') + axs[1].plot(x_Sti, pdf_Sti, 'r', label='Fitted Lognormal') + axs[1].set_title('Lognormal Fit for $S_{ti}$') + axs[1].set_xlabel('Sti (dimensionless)') + axs[1].set_ylabel('Density') + axs[1].set_ylim(0, y_max) + axs[1].legend() + axs[1].grid(True) + + # Plot histogram with fitted lognormal + plt.figure(figsize=(8, 5)) + plt.hist(final_depths, bins=40, alpha=0.6, density=True, color='lightsalmon', edgecolor='r', label='Simulated PDF') + plt.plot(x, pdf, 'r', lw=2, label='Fitted Lognormal') + plt.axvline(np.median(final_depths), color='k', linestyle='--', label=f'Median = {np.median(final_depths):.2f} m') + plt.title('Monte Carlo Simulation with Fitted Lognormal Distribution') + plt.xlabel('Penetration (m)') + plt.ylabel('Density') + plt.legend() + plt.grid(True) + plt.tight_layout() + plt.show() + + # Print parameters + print(f'Lognormal fit parameters:') + print(f' mean = {np.mean(final_depths):.2f}') + print(f' mean - 1 std deviation = {np.mean(final_depths) - np.std(final_depths):.2f}') + print(f' mean + 1 std deviation = {np.mean(final_depths) + np.std(final_depths):.2f}') + + return final_depths + +# Example usage in main +if __name__ == '__main__': + profile_map = [ + { + 'name': 'CPT_1', + 'x': 0, 'y': 0, + 'layers': [ + {'top': 0.0, 'bottom': 30.0, 'soil_type': 'clay', + 'gamma_top': 8.0, 'gamma_bot': 8.5, + 'Su_top': 5, 'Su_bot': 20}, + {'top': 30.0, 'bottom': 180.0, 'soil_type': 'clay', + 'gamma_top': 8.5, 'gamma_bot': 9.0, + 'Su_top': 20, 'Su_bot': 150} + ] + } + ] + + location = 'CPT_1' + D1 = 3.0 + D2 = 1.2 + L1 = 5.0 + L2 = 5.0 + ballast = 300000 + drop_height = 200 + + # Run Monte Carlo Simulation + depths = getInstallationDynamicMC(profile_map, location, D1, D2, L1, L2, ballast, drop_height) diff --git a/famodel/anchors/anchors_famodel/installation_suction.py b/famodel/anchors/anchors_famodel/installation_suction.py new file mode 100644 index 00000000..7c474082 --- /dev/null +++ b/famodel/anchors/anchors_famodel/installation_suction.py @@ -0,0 +1,215 @@ +import numpy as np +import matplotlib.pyplot as plt +from support_soils import clay_profile + +def PileWeight(Len, Dia, tw, rho): + return ((np.pi/4)*((Dia**2 - (Dia - 2*tw)**2)*Len + (np.pi/4)*Dia**2*tw))*rho + +def getInstallationSuction(profile_map, location_name, D, L, gamma_m_install=1.5, gamma_m_retrieval=1.25): + ''' + Installation and retrieval pressure assessment for suction piles in clay using a layered profile. + Returns a dictionary with pressure values and resistances. + ''' + # Constants and geometry + profile_entry = next(p for p in profile_map if p['name'] == location_name) + layers = profile_entry['layers'] + + rhows = 66.90e3 # Submerged steel specific weight (N/m3) + rhow = 10e3 # Water specific weight (N/m3) + + WT = D/200; print(WT) + t = (6.35 + D*20)/1e3; print(t) # Suction pile wall thickness (m), API RP2A-WSD + Di = D - 2*WT + Asi = np.pi * Di + Aso = np.pi * D + Awall = 0.25 # m² + Aplug = np.pi * Di**2 / 4 + Nc_strip_deep = 7.5 + Nc_circle = 9.0 + alphaD_su = 0.25 + Wp = PileWeight(L, D, WT, rhows); print(Wp) + Wsub_steel = 750e3 # in N + + # Convert layer data into clay profile format + z0 = layers[0]['top'] + z_bot = layers[0]['bottom'] + gamma_top = layers[0]['gamma_top'] + gamma_bot = layers[0]['gamma_bot'] + Su_top = layers[0]['Su_top'] + Su_bot = layers[0]['Su_bot'] + + clay_input = [ + [z0, gamma_top, Su_top], + [z_bot, gamma_bot, Su_bot] + ] + + _, f_gamma, f_Su, f_sigma_v_eff, f_alpha = clay_profile(clay_input) + + # Diagnostic: evaluate and plot alpha(z) + z_plot = np.linspace(z0, z_bot, 100) + alpha_plot = f_alpha(z_plot) + + # print('\n--- Adhesion Factor α(z) ---') + # for z_check in [0, 2, 4, 6, 8, 10, 12, 14, 17]: + # print(f"z = {z_check:>5.2f} m → α = {f_alpha(z_check):.3f}") + + # plt.figure(figsize=(5, 4)) + # plt.plot(alpha_plot, z_plot, label='α(z)', color='purple') + # plt.gca().invert_yaxis() + # plt.grid(True) + # plt.xlabel('Adhesion Factor α') + # plt.ylabel('Depth (m)') + # plt.title('API Clay Adhesion Factor vs Depth') + # plt.tight_layout() + # plt.show() + + # Prepare output arrays + depths = np.arange(0, L + 0.1, 0.1) + Rsuction_list = [] + delta_u_suction_list = [] + delta_u_retrieval_list = [] + delta_u_all_install_list = [] + delta_u_all_retrieval_list = [] + SWP_depth = None + + for L in depths: + z_tip = L + z_mid = L/2 + z_tip_ext = L + alphaD_su*Di + + su_av_L = f_Su(z_mid) + int_su = (su_av_L)*L + su_tip = f_Su(z_tip) + su_av_tip = f_Su(z_tip_ext) + # alpha_i = alpha_o = float(f_alpha(z_mid)) + alpha_i = alpha_o = 0.3 + + Fi = Asi*alpha_i*int_su + Fo = Aso*alpha_o*int_su + Qw = Awall*Nc_strip_deep*su_tip + + Rsuction = Fi + Fo + Qw + Rretrieval = Rsuction + delta_u_suction = max((Rsuction - Wp)/Aplug, 0.0) + delta_u_retrieval = (Rretrieval + Wp)/Aplug + delta_u_all_install = Fi/Aplug + Nc_circle*su_av_tip/gamma_m_install + delta_u_all_retrieval = Fi/Aplug + Nc_circle*su_av_tip/gamma_m_retrieval + + Rsuction_list.append(Rsuction) + delta_u_suction_list.append(delta_u_suction) + delta_u_retrieval_list.append(delta_u_retrieval) + delta_u_all_install_list.append(delta_u_all_install) + delta_u_all_retrieval_list.append(delta_u_all_retrieval) + + if SWP_depth is None and Rsuction >= Wp: + SWP_depth = L + + # Plotting + fig, axs = plt.subplots(1, 3, figsize=(10, 7)) + + axs[0].plot(Rsuction_list, depths, label='Installation Resistance', color='blue') + if SWP_depth is not None: + axs[0].axvline(Wp, color='red', linestyle='--', label=f'SWP = {SWP_depth:.2f} m') + axs[0].set_xlabel('Installation Resistance (N)') + axs[0].set_ylabel('Penetration (m)') + axs[0].set_title('Installation Resistance vs Penetration') + axs[0].grid(True) + axs[0].invert_yaxis() + axs[0].legend() + + axs[1].plot(delta_u_suction_list, depths, label='Underpressure', color='green') + axs[1].plot(delta_u_all_install_list, depths, label='Δu allowable install', color='orange') + if SWP_depth is not None: + axs[1].axhline(SWP_depth, color='red', linestyle='--', label=f'SWP = {SWP_depth:.2f} m') + axs[1].set_xlabel('Underpressure (Pa)') + axs[1].set_ylabel('Penetration (m)') + axs[1].set_title('Underpressure vs Penetration') + axs[1].grid(True) + axs[1].invert_yaxis() + axs[1].legend() + + axs[2].plot(delta_u_retrieval_list, depths, label='Overpressure', color='green') + axs[2].plot(delta_u_all_retrieval_list, depths, label='Δu allowable retrieve', color='orange') + axs[2].set_xlabel('Overpressure (Pa)') + axs[2].set_ylabel('Penetration (m)') + axs[2].set_title('Overpressure vs Penetration') + axs[2].grid(True) + axs[2].invert_yaxis() + axs[2].legend() + + plt.tight_layout() + plt.show() + + # Final state outputs + L = L + z_tip = L + z_mid = L/2 + z_tip_ext = L + alphaD_su*Di + + su_av_L = f_Su(z_mid) + int_su = su_av_L*L + su_tip = f_Su(z_tip) + su_av_tip = f_Su(z_tip_ext) + alpha_i = alpha_o = float(f_alpha(z_mid)) + alpha_i = alpha_o = 0.3 + + Fi = Asi*alpha_i*int_su + Fo = Aso*alpha_o*int_su + Qw = Awall*Nc_strip_deep*su_tip + + Rsuction = Fi + Fo + Qw + Rretrieval = Rsuction + + delta_u_suction = max((Rsuction - Wp)/Aplug, 0.0) + delta_u_retrieval = (Rretrieval + Wp)/Aplug + + delta_u_all_install = Fi/Aplug + Nc_circle*su_av_tip/gamma_m_install + delta_u_all_retrieval = Fi/Aplug + Nc_circle*su_av_tip/gamma_m_retrieval + + return { + 'layers': layers, + 'depths': depths, + 'z0': z0, + 'D': D, + 'L': L, + 'Di': Di, + 'Asi': Asi, # m + 'Aso': Aso, # m + 'Aplug': Aplug, # m² + 'su_av_L': su_av_L/1e3, # kPa + 'int_su': int_su/1e3, # kN/m + 'su_tip': su_tip/1e3, # kPa + 'su_av_tip': su_av_tip/1e3, # kPa + 'Fi': Fi/1e3, # kN + 'Fo': Fo/1e3, # kN + 'Qw': Qw/1e3, # kN + 'Rsuction': Rsuction/1e6, # MN + 'Rretrieval': Rretrieval/1e6, # MN + 'delta_u_suction': delta_u_suction_list, # kPa + 'delta_u_retrieval': delta_u_retrieval/1e3, # kPa + 'delta_u_all_install': delta_u_all_install/1e3, # kPa + 'delta_u_all_retrieval': delta_u_all_retrieval/1e3, # kPa + 'SWP_depth': SWP_depth} + +if __name__ == '__main__': + profile_map = [ + { + 'name': 'CLAY_INSTALL', + 'x': 0, 'y': 0, + 'layers': [ + { + 'top': 0.0, 'bottom': 20.0, + 'soil_type': 'clay', + 'gamma_top': 9.0, 'gamma_bot': 9.0, + 'Su_top': 5.0, 'Su_bot': 45.0 + } + ] + } + ] + + results = getInstallationSuction(profile_map, 'CLAY_INSTALL', D=4.0, L=17.0) + for k, v in results.items(): + if isinstance(v, float): + print(f"{k:<25} = {v:.2f}") + else: + print(f"{k:<25} = {v}") \ No newline at end of file diff --git a/famodel/anchors/anchors_famodel_map/capacity_plots_map.py b/famodel/anchors/anchors_famodel/support_plots.py similarity index 89% rename from famodel/anchors/anchors_famodel_map/capacity_plots_map.py rename to famodel/anchors/anchors_famodel/support_plots.py index d733fade..c01a68fc 100644 --- a/famodel/anchors/anchors_famodel_map/capacity_plots_map.py +++ b/famodel/anchors/anchors_famodel/support_plots.py @@ -3,6 +3,28 @@ import matplotlib.pyplot as plt def plot_pile(layers, y, z, D, L, z0=None, zlug=None, hinge_location=None): + '''Plot the soil profile and a driven pile with deflected shape in layered soil. + + Parameters + ---------- + layers : list of dicts + Each layer has 'top', 'bottom', 'soil_type', and strength parameters + such as 'Su_top' (clay), 'phi_top' (sand) or 'UCS_top' (rock) + y : array-like + Lateral displacement profile from FD solution (typically y[2:-2]) + z : array-like + Depth values associated with displacement points (typically z[2:-2]) + D : float + Pile diameter (m) + L : float + Embedded pile length (m) + z0 : float, optional + Mudline elevation m) from pile head reference (z = 0) + zlug : float, optional + Depth of the padeye below pile head (m) + hinge_location : int, optional + Index of plastic hinge location in y/z arrays. + ''' fig, ax = plt.subplots(figsize=(5, 5)) lambdap = L / D @@ -74,7 +96,7 @@ def plot_pile(layers, y, z, D, L, z0=None, zlug=None, hinge_location=None): plt.tight_layout() plt.show() -def plot_suction(layers, L, D, z0=None, zlug=None, title='Suction Pile and Soil Layers'): +def plot_suction(layers, L, D, z0=None, zlug=None): '''Plot the soil profile and a suction pile geometry using updated profile_map structure. Parameters: @@ -87,8 +109,6 @@ def plot_suction(layers, L, D, z0=None, zlug=None, title='Suction Pile and Soil Pile diameter (m) zlug : float Padeye depth (m, referenced to pile head = 0) - title : string - Plot title ''' fig, ax = plt.subplots(figsize=(8, 5)) xmax = 2*D @@ -142,13 +162,13 @@ def plot_suction(layers, L, D, z0=None, zlug=None, title='Suction Pile and Soil ax.set_ylabel('Depth (m)') ax.set_xlim(-xmax, xmax) ax.set_ylim(L + 2*D, -D) - ax.set_title(title) + ax.set_title('Suction Pile and Soil Layers') ax.grid() ax.legend() plt.tight_layout() plt.show() -def plot_torpedo(layers, D1, D2, L1, L2, z0, zlug, title='Torpedo Pile and Soil Layers'): +def plot_torpedo(layers, D1, D2, L1, L2, z0, zlug): '''Plot the soil layers and geometry of a torpedo pile using absolute depth for soil and pile head at z=0. Parameters: @@ -165,8 +185,6 @@ def plot_torpedo(layers, D1, D2, L1, L2, z0, zlug, title='Torpedo Pile and Soil Winged length (m) L2 : float Shaft length (m) - title : str - Plot title ''' fig, ax = plt.subplots(figsize=(7, 7)) @@ -226,13 +244,13 @@ def plot_torpedo(layers, D1, D2, L1, L2, z0, zlug, title='Torpedo Pile and Soil ax.set_ylim(zmax, zmin) ax.set_xlabel('Horizontal extent (m)') ax.set_ylabel('Depth (m)') - ax.set_title(title) + ax.set_title('Torpedo Pile and Soil Layers') ax.grid() ax.legend() plt.tight_layout() plt.show() -def plot_helical(layers, D, L, d, z0, zlug, n_helix=1, spacing=1.0, title='Helical Pile and Soil Layers'): +def plot_helical(layers, D, L, d, z0, zlug, n_helix=1, spacing=1.0): '''Plot a helical pile in layered soil with shaft and angled helices, starting at zlug. Parameters: @@ -251,8 +269,6 @@ def plot_helical(layers, D, L, d, z0, zlug, n_helix=1, spacing=1.0, title='Helic Number of helices (typically 1) spacing : float Vertical spacing between helices (m) - title : str - Plot title ''' fig, ax = plt.subplots(figsize=(5, 6)) @@ -322,13 +338,13 @@ def plot_helical(layers, D, L, d, z0, zlug, n_helix=1, spacing=1.0, title='Helic ax.set_ylim(L + D, min(zlug - D, min(layer['top'] for layer in layers) - 2)) ax.set_xlabel('Horizontal extent (m)') ax.set_ylabel('Depth (m)') - ax.set_title(title) + ax.set_title('Helical Pile and Soil Layers') ax.grid() ax.legend() plt.tight_layout() plt.show() -def plot_plate(layers, B, L, z0, zlug, beta, title='Plate Anchor in Layered Soil'): +def plot_plate(layers, B, L, z0, zlug, beta): '''Plot soil layers and an inclined plate anchor centered at zlug. Parameters: @@ -345,8 +361,6 @@ def plot_plate(layers, B, L, z0, zlug, beta, title='Plate Anchor in Layered Soil Center embedment of the plate (m) beta : float Inclination angle of plate (deg) - title : str - Plot title ''' fig, ax = plt.subplots(figsize=(5, 5)) xmax = 3*B @@ -397,7 +411,7 @@ def plot_plate(layers, B, L, z0, zlug, beta, title='Plate Anchor in Layered Soil ax.set_ylim(zmax, zmin) ax.set_xlabel("Horizontal extent (m)") ax.set_ylabel("Depth (m)") - ax.set_title(title) + ax.set_title('Plate Anchor in Layered Soil') ax.legend(loc='lower right') ax.grid(True) plt.tight_layout() @@ -454,7 +468,7 @@ def plot_load(layers, drag_values, depth_values, Tm, thetam, Ta, thetaa, zlug): elif soil == 'sand': phi = layer.get('phi_top', 30) gamma = layer.get('gamma_top', 10) - color_fill = plt.cm.YlOrBr(phi / max_phi) + color_fill = plt.cm.YlOrBr(phi/max_phi) label_soil = f'ϕ = {phi:.0f}°, γ = {gamma:.1f} kN/m³' else: color = 'gray' @@ -469,7 +483,7 @@ def plot_load(layers, drag_values, depth_values, Tm, thetam, Ta, thetaa, zlug): scale = 2e6 # Arrow scaling factor for better visual readability # Plot the inverse catenary profile - ax.plot(drag_values, depth_values, color='b', label='Mooring line') + ax.plot(drag_values, depth_values, color='k', label='Mooring line') # Load arrows ax.arrow(0, -layers[0]['top'], @@ -478,19 +492,29 @@ def plot_load(layers, drag_values, depth_values, Tm, thetam, Ta, thetaa, zlug): ax.arrow(drag_values[-1], depth_values[-1], Ta*np.cos(np.deg2rad(thetaa))/scale, Ta*np.sin(np.deg2rad(thetaa))/scale, - head_width=0.25, head_length=0.5, color='g', label='Padeye Load') + head_width=0.25, head_length=0.5, color='g', label='Lug load') + + ax.plot(0, -layers[0]['top'], 'ro', zorder=5) if zlug is not None: ax.plot(drag_values[-1], -zlug, 'go', label=f'Padeye (zlug = {zlug:.2f} m)') + # Coordinates of lug arrow tail + xlug = drag_values[-1] + ylug = depth_values[-1] + + # Mark the base of the lug vector with a green dot and depth label + ax.plot(xlug, ylug, 'go', zorder=5) + ax.annotate(f'z = {-ylug:.2f} m', (xlug - 0.5, ylug - 0.75), color='g') + # Add mudline and padeye markers - ax.axhline(-layers[0]['top'], color='k', linestyle='--', lw=1.5, label=f'Mudline') + ax.axhline(-layers[0]['top'], color='b', linestyle='--', lw=1.5, label=f'Mudline') # Annotate loads ax.annotate(f"{Tm/1e6:.2f} MN", (Tm*np.cos(np.deg2rad(thetam))/scale, - -layers[0]['top'] + Tm*np.sin(np.deg2rad(thetam))/scale), color='r') + -layers[0]['top']), color='r') ax.annotate(f"{Ta/1e6:.2f} MN", (drag_values[-1] + Ta*np.cos(np.deg2rad(thetaa))/scale, - depth_values[-1] + Ta*np.sin(np.deg2rad(thetaa))/scale), color='g') + depth_values[-1]), color='g') # Deduplicate legend entries handles, labels = ax.get_legend_handles_labels() @@ -501,8 +525,8 @@ def plot_load(layers, drag_values, depth_values, Tm, thetam, Ta, thetaa, zlug): ax.set_ylabel('Embedded depth (m)') ax.set_title('Inverse Catenary in Layered Soil') ax.grid(True) - #ax.set_ylim(min(zlug - 10, min(depth_values) - 5), max(15, max(depth_values) + 5)) - ax.legend(loc='lower left') + ax.set_ylim(min(zlug - 10, min(depth_values) - 5), max(5, max(depth_values) + 5)) + ax.legend(loc='lower right') plt.tight_layout() plt.show() @@ -515,7 +539,7 @@ def plot_pycurve(pycurve_data): pycurve_data : list of tuples Each tuple must be (y_vals, p_vals, z_depth, soil_type) ''' - fig, ax = plt.subplots(figsize=(6, 5)) + fig, ax = plt.subplots(figsize=(6, 5), constrained_layout=True) for y, p, z, soil in pycurve_data: label = f'{soil.capitalize()} @ z = {z:.1f} m' @@ -525,6 +549,5 @@ def plot_pycurve(pycurve_data): ax.set_ylabel('Soil resistance p (N/m)') ax.set_title('p–y Curves at Various Depths') ax.grid(True) - ax.legend() - plt.tight_layout() + # ax.legend(fontsize='small') plt.show() diff --git a/famodel/anchors/anchors_famodel_map/capacity_pycurves_map.py b/famodel/anchors/anchors_famodel/support_pycurves.py similarity index 86% rename from famodel/anchors/anchors_famodel_map/capacity_pycurves_map.py rename to famodel/anchors/anchors_famodel/support_pycurves.py index 377a9a8f..c8cf40e0 100644 --- a/famodel/anchors/anchors_famodel_map/capacity_pycurves_map.py +++ b/famodel/anchors/anchors_famodel/support_pycurves.py @@ -3,7 +3,7 @@ import matplotlib.pyplot as plt from scipy.interpolate import interp1d -def py_Matlock(z, D, zlug, f_Su, f_sigma_v_eff, f_gamma, z0=None, return_curve=False): +def py_Matlock(z, D, gamma, Su, sigma_v_eff, z0=None, return_curve=False): ''' Generate Matlock (1970) p–y curve at a given depth in clay. Parameters @@ -12,8 +12,6 @@ def py_Matlock(z, D, zlug, f_Su, f_sigma_v_eff, f_gamma, z0=None, return_curve=F Depth relative to pile head (m) D : float Pile diameter (m) - zlug : float - Load eccentricity above or below mudline (m) f_Su : function Undrained shear strength (Pa) f_sigma_v_eff : function @@ -31,9 +29,9 @@ def py_Matlock(z, D, zlug, f_Su, f_sigma_v_eff, f_gamma, z0=None, return_curve=F Interpolation function for p–y relationship (N/m vs m) ''' - Su = f_Su(z) - sigma_v_eff = f_sigma_v_eff(z) - gamma = f_gamma(z) + # Su = f_Su(z) + # sigma_v_eff = f_sigma_v_eff(z) + # gamma = f_gamma(z) # Strain at half the strength as defined by Matlock (1970). # Typically ranges from 0.005 (stiff clay) to 0.02 (soft clay). @@ -63,11 +61,11 @@ def py_Matlock(z, D, zlug, f_Su, f_sigma_v_eff, f_gamma, z0=None, return_curve=F y = Y*y_50 p = P*p_ult - f = interp1d(y, p, kind='linear', bounds_error=False, fill_value=0.0) # Interpolation function for p-y curve + f = interp1d(y, p, kind='linear', bounds_error=False, fill_value=0.0) return (f, (y, p)) if return_curve else f -def py_API(z, D, zlug, f_phi, f_sigma_v_eff, f_Dr, z0=None, return_curve=False): +def py_API(z, D, phi, sigma_v_eff, Dr, z0=None, return_curve=False): ''' Generate API RP2A (1993) p–y curve at a given depth in sand. Parameters @@ -76,8 +74,6 @@ def py_API(z, D, zlug, f_phi, f_sigma_v_eff, f_Dr, z0=None, return_curve=False): Depth relative to pile head (m) D : float Pile diameter (m) - zlug : float - Load eccentricity above or below mudline (m) f_phi : function Friction angle (deg) f_sigma_v_eff : function @@ -95,9 +91,9 @@ def py_API(z, D, zlug, f_phi, f_sigma_v_eff, f_Dr, z0=None, return_curve=False): Interpolation function for p–y relationship (N/m vs m) ''' - phi = f_phi(z) - sigma_v_eff = f_sigma_v_eff(z) - Dr = f_Dr(z) + # phi = f_phi(z) + # sigma_v_eff = f_sigma_v_eff(z) + # Dr = f_Dr(z) # Interpolate coefficients depending on the effective friction angle phi_ref = [ 20, 25, 30, 35, 40] @@ -128,14 +124,14 @@ def py_API(z, D, zlug, f_phi, f_sigma_v_eff, f_Dr, z0=None, return_curve=False): A = max(3 - 0.8*z/D, 0.9) # Apply API p–y formulation - ε = 1e-6 # prevent division by zero - p = A*p_ult*np.tanh(k*z*y/(A*p_ult + ε)) + epsilon = 1e-6 # prevent division by zero + p = A*p_ult*np.tanh(k*z*y/(A*p_ult + epsilon)) f = interp1d(y, p, kind='linear', bounds_error=False, fill_value=0.0) return (f, (y, p)) if return_curve else f -def py_Reese(z, D, zlug, f_UCS, f_Em, z0=None, return_curve=False): +def py_Reese(z, D, UCS, Em, z0=None, return_curve=False): ''' Generate Reese (1997) p–y curve at a given depth in weak rock. Parameters @@ -144,8 +140,6 @@ def py_Reese(z, D, zlug, f_UCS, f_Em, z0=None, return_curve=False): Depth relative to pile head (m) D : float Pile diameter (m) - zlug : float - Load eccentricity above or below mudline (m) f_UCS : function Unconfined compressive strength UCS(z) (Pa) f_Em : function @@ -161,8 +155,8 @@ def py_Reese(z, D, zlug, f_UCS, f_Em, z0=None, return_curve=False): Interpolation function for p–y relationship (N/m vs m) ''' - UCS = f_UCS(z) - Em = f_Em(z) + # UCS = f_UCS(z) + # Em = f_Em(z) RQD = 52 # Assumed fair rock quality (moderately weathered rocks) Dref = 0.305; # Reference diamter (m) @@ -191,13 +185,13 @@ def py_Reese(z, D, zlug, f_UCS, f_Em, z0=None, return_curve=False): # Normalized lateral displacement N = 20 - y = np.concatenate((-np.logspace(4,-3,N),[0],np.logspace(-3,4,N))) - y = np.linspace(-0.02*D, 0.02*D, 200) # ±2 cm + y = np.concatenate((-np.logspace(.1,-2,N),[0],np.logspace(-2,.1,N))) + # y = np.linspace(-0.2*D, 0.2*D, 200) # ±2 cm p = [] for val in y: if abs(val) < y_a: - p_val = np.sign(val)*Kir*val + p_val = Kir*val else: p_val = np.sign(val)*min((p_ur/2)*(abs(val)/y_rm)**0.25, p_ur) p.append(p_val) @@ -206,7 +200,7 @@ def py_Reese(z, D, zlug, f_UCS, f_Em, z0=None, return_curve=False): return (f, (y, p)) if return_curve else f -def py_Lovera(z, D, f_UCS, f_Em, zlug, z0, delta_grout=0.075, E_grout=20e9, delta_crushed=0.025, return_curve=False): +def py_Lovera(z, D, UCS, Em, zlug, z0, delta_grout=0.075, E_grout=20e9, delta_crushed=0.025, return_curve=False): ''' Generate Lovera (2019) p–y curve at a given depth for layered rock interfaces. Parameters @@ -242,7 +236,7 @@ def py_Lovera(z, D, f_UCS, f_Em, zlug, z0, delta_grout=0.075, E_grout=20e9, delt return lambda y: np.zeros_like(y) # Retrieve elastic modulus at depth - Em = f_Em(z) + # Em = f_Em(z) nu = 0.3 # Typical Poisson's ratio for rock G_rock = Em/(2*(1 + nu)) k_rock = 4*G_rock diff --git a/famodel/anchors/anchors_famodel_map/capacity_soils_map.py b/famodel/anchors/anchors_famodel/support_soils.py similarity index 100% rename from famodel/anchors/anchors_famodel_map/capacity_soils_map.py rename to famodel/anchors/anchors_famodel/support_soils.py diff --git a/famodel/anchors/anchors_famodel_map/capacity_solvers.py b/famodel/anchors/anchors_famodel/support_solvers.py similarity index 97% rename from famodel/anchors/anchors_famodel_map/capacity_solvers.py rename to famodel/anchors/anchors_famodel/support_solvers.py index b63b0826..e73b9251 100644 --- a/famodel/anchors/anchors_famodel_map/capacity_solvers.py +++ b/famodel/anchors/anchors_famodel/support_solvers.py @@ -50,8 +50,11 @@ def fd_solver(n, N, h, D, t, fy, EI, Ha, Va, zlug, z0, k_secant): Index of the node with hinge formation ''' - # Initialize and assemble matrix + # Initialize + N = n + 5 X = np.zeros((N, N)) + q = np.zeros(N) + # k_secant = np.zeros(N) # (n+1) finite difference equations for (n+1) real nodes for i in range(0, n+1): @@ -84,13 +87,11 @@ def fd_solver(n, N, h, D, t, fy, EI, Ha, Va, zlug, z0, k_secant): X[n+4, -3] = 0.0 X[n+4, -4] = 2.0 - Va*h**2/EI X[n+4, -5] = -1.0 - - # Initialize vector q - q = np.zeros(N) # Always apply shear # Index of the node where the horizontal load is applied (padeye) zlug_index = int(zlug/h) + #zlug_index = max(1, int(zlug/h)) # avoid node 0 q[zlug_index] = 2*Ha*h**3 y = linalg.solve(EI*X, q) diff --git a/famodel/anchors/anchors_famodel_map/capacity_helical_map.py b/famodel/anchors/anchors_famodel_map/capacity_helical_map.py deleted file mode 100644 index 4a495a4e..00000000 --- a/famodel/anchors/anchors_famodel_map/capacity_helical_map.py +++ /dev/null @@ -1,172 +0,0 @@ - -import numpy as np -from .capacity_driven_map import getCapacityDriven, plot_pile -from .capacity_soils_map import clay_profile, sand_profile -from .capacity_plots_map import plot_helical - -def getCapacityHelical(profile_map, location_name, D, L, d, zlug, Ha, Va, plot=True): - '''Calculate the vertical and horizontal capacity of a helical pile using a soil profile. - The calculation is based on the soil profile, anchor geometry and inclined load. - - Parameters - ---------- - profile : array - Soil profiles (z, parameters) - Clay soil profile (z, Su, gamma) - Sand soil profile (z, phi, gamma, Dr) - soil_type : string - Select soil condition, 'clay' or 'sand' - D : float - Helix diameter (m) - L : float - Shaft length (m) - d : float - Shaft diameter (m) - zlug : float - Depth to padeye (m) - Ha : float - Horizontal load applied at padeye (N) - Va : float - Vertical load applied at padeye (N) - plot : bool - Plot the p-y curve and the deflection pile condition if True - - Returns - ------- - y : array - Lateral displacement at each node (real nodes only) - z : array - Node depth positions corresponding to y (m) - resultsHelical : dict - Dictionary containing displacements, moment capacity, hinge state and vertical capacity - ''' - - profile_entry = next(p for p in profile_map if p['name'] == location_name) - layers = profile_entry['layers'] - - t = (6.35 + D*20)/1e3 # Helical pile wall thickness (m), API RP2A-WSD - rhows = 66.90e3 # Submerged steel specific weight (kN/m3) - rhow = 10e3 # Water specific weight (kN/m3) - - def PileWeight(Len, Dia1, Dia2, tw, rho): - return ((np.pi/4)*((Dia1**2 - (Dia1 - 2*tw)**2)*Len + (np.pi/4)*Dia2**2*tw))*rho - - z_helix = zlug + (L - D) - matched_layer = next((layer for layer in layers if layer['top'] <= z_helix <= layer['bottom']), None) - if matched_layer is None: - raise ValueError(f"No soil layer found at z = {z_helix:.2f} m") - - if matched_layer['soil_type'] == 'clay': - profile = [[matched_layer['top'], matched_layer['Su_top'], matched_layer['gamma_top']], - [matched_layer['bottom'], matched_layer['Su_bot'], matched_layer['gamma_bot']]] - z0, f_Su, f_sigma_v_eff, f_gamma, f_alpha = clay_profile(profile) - - z_helix = np.clip(z_helix, matched_layer['top'], matched_layer['bottom']) - Su = f_Su(z_helix) - sigma_v_eff = max(f_sigma_v_eff(z_helix), 1.0) - psi_val = Su/sigma_v_eff - alpha = min(0.5*psi_val**-0.50, 1) if psi_val <= 1.0 else min(0.5 * psi_val**-0.25, 1) - - Nc = min(6.0*(1 + 0.2*d/D), 9) - Qh = ((np.pi/4)*(D**2 - d**2)*Nc*Su + f_gamma(z_helix)*D)*0.75 - Qs = np.pi*d*L*alpha*Su - Qu = PileWeight(L, D, d, t, rhows) + Qh + Qs - - elif matched_layer['soil_type'] == 'sand': - profile = [[matched_layer['top'], matched_layer['phi_top'], matched_layer['gamma_top'], matched_layer['Dr_top']], - [matched_layer['bottom'], matched_layer['phi_bot'], matched_layer['gamma_bot'], matched_layer['Dr_bot']]] - z0, f_phi, f_sigma_v_eff, f_gamma, f_Dr, f_delta = sand_profile(profile) - - z_helix = np.clip(z_helix, matched_layer['top'], matched_layer['bottom']) - gamma = f_gamma(z_helix) - Dr = f_Dr(z_helix) - delta = f_delta(z_helix) - phi = f_phi(z_helix) - - Nq = 0.5*(12*phi)**(phi/54) - Qh = (np.pi/4)*(D**2 - d**2)*Nq*gamma*z_helix - Qs = np.pi*d*L*delta*gamma*z_helix - Qu = PileWeight(L, D, d, t, rhows) + Qh + Qs - - - Wp = PileWeight(L, D, d, t, (rhows + rhow)) - - # Unity Check based only on vertical capacity - UC_vertical = Va/Qu - - # Compute horizontal capacity using p-y method - layers, y, z, results_lateral = getCapacityDriven(profile_map, location_name, D, L, zlug, Ha, Va, plot=True) - - plot_pile(layers, y, z, D, L, z0=layers[0]['top'], zlug=zlug, hinge_location=None) - - Hcap = results_lateral['Horizontal max.'] - UC_horizontal = Ha/Hcap if Hcap != 0 else np.inf - - resultsHelical = { - 'Vertical max.': Qu, - 'Weight': Wp, - 'Unity Check (Vertical)': UC_vertical, - 'Horizontal max.': Hcap, - 'Unity Check (Horizontal)': UC_horizontal - } - - if matched_layer['soil_type'] == 'clay': - resultsHelical['Su @ helix'] = Su - resultsHelical['Alpha'] = alpha - elif matched_layer['soil_type'] == 'sand': - resultsHelical['Dr @ helix'] = Dr - resultsHelical['Delta'] = delta - resultsHelical['Phi'] = phi - - return layers, resultsHelical - -if __name__ == '__main__': - - profile_map = [ - { - 'name': 'CPT_1', - 'x': 498234, 'y': 5725141, - 'layers': [ - { - 'top': 1.0, 'bottom': 3.0, - 'soil_type': 'clay', - 'gamma_top': 8.0, 'gamma_bot': 9.0, - 'Su_top': 60, 'Su_bot': 50}, - { - 'top': 3.0, 'bottom': 7.0, - 'soil_type': 'clay', - 'gamma_top': 15.0, 'gamma_bot': 25.0, - 'Su_top': 100, 'Su_bot': 150}, - # { - # 'top': 6.0, 'bottom': 15.0, - # 'soil_type': 'sand', - # 'gamma_top': 8.0, 'gamma_bot': 8.0, - # 'phi_top': 32, 'phi_bot': 38, - # 'Dr_top': 70, 'Dr_bot': 75}, - { - 'top': 7.0, 'bottom': 15.0, - 'soil_type': 'clay', - 'gamma_top': 25.0, 'gamma_bot': 50.0, - 'Su_top': 200, 'Su_bot': 400}] - } - ] - - D = 1.5 # Helix diameter (m) - L = 12.0 # Pile length (m) - d = 0.5 # Shaft diameter (m) - zlug = 3 # Padeye depth (m) - Ha = 30e3 # Horizontal load (N) - Va = 50e3 # Vertical load (N) - - print("--- Clay Profile ---") - layers, resultsHelical = getCapacityHelical(profile_map, 'CPT_1', D, L, d, zlug, Ha, Va, plot=True) - for key, val in resultsHelical.items(): - if isinstance(val, float): - print(f"{key}: {val:.3f}") - else: - print(f"{key}: {val}") - - plot_helical(layers, D=D, L=L, d=d, z0=layers[0]['top'], zlug=zlug, n_helix=1, spacing=1.0, title='Helical Pile in Sand Profile') - - - diff --git a/famodel/anchors/anchors_famodel_map/capacity_load_map.py b/famodel/anchors/anchors_famodel_map/capacity_load_map.py deleted file mode 100644 index 7ebca3b7..00000000 --- a/famodel/anchors/anchors_famodel_map/capacity_load_map.py +++ /dev/null @@ -1,212 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from .capacity_soils_map import clay_profile, sand_profile -from .capacity_plots_map import plot_load - -def getTransferLoad(profile_map, Tm, thetam, zlug, line_type, d, w=None, plot=False): - '''Calculate the transfer load from mudline to main padeye using a layered soil profile. - - Parameters - ---------- - profile_map : list of dicts - Soil profile in profile_map format - Tm : float - Mooring line load at mudlevel (N) - thetam : float - Mooring line angle at mudlevel (deg) - zlug : float - Embedment depth of the lug (m) - line_type : str - 'chain' or 'wire' - d : float - Chain diameter (m) - w : float - Mooring line unit weight (N/m) - plot : bool - Show plot - - Returns - ------- - dict - Dictionary with transferred load components and depth. - ''' - - deltas = 0.2 # discretization step - - # Line mechanical properties - if line_type == 'chain': - Et, En = 10, 2.5 - elif line_type == 'wire': - Et, En = np.pi, 1 - W = w*deltas - - # Soil layer access - layers = profile_map[0]['layers'] - z0 = min(layer['top'] for layer in layers) - Nc = 8.5 - - # Initial values - z0 = min(layer['top'] for layer in layers) - T = Tm - theta = np.deg2rad(thetam) - drag = 0 - depth = z0 + 0.01 - - # Tracing lists - drag_values, depth_values = [], [] - - while (zlug - depth) >= 0: - matched_layer = next((layer for layer in layers if layer['top'] <= depth <= layer['bottom']), None) - if matched_layer is None: - break - - if matched_layer['soil_type'] == 'clay': - matched_layer = next((layer for layer in layers if layer['soil_type'] == 'clay' and layer['top'] <= depth <= layer['bottom']), None) - if matched_layer is None: - break - profile = [[matched_layer['top'], matched_layer['gamma_top'], matched_layer['Su_top']], - [matched_layer['bottom'], matched_layer['gamma_bot'], matched_layer['Su_bot']]] - z0_local, f_gamma, f_Su, f_sigma_v_eff, f_alpha = clay_profile(profile) - - Su = f_Su(depth) - alpha = f_alpha(depth) - d_theta = (En*d*Nc*Su - W*np.cos(theta))/T*deltas - dT = (Et*d*alpha*Su + W*np.sin(theta))*deltas - - elif matched_layer['soil_type'] == 'sand': - matched_layer = next((layer for layer in layers if layer['soil_type'] == 'sand' and layer['top'] <= depth <= layer['bottom']), None) - if matched_layer is None: - break - - profile = [[matched_layer['top'], matched_layer['gamma_top'], matched_layer['phi_top'], matched_layer['Dr_top']], - [matched_layer['bottom'], matched_layer['gamma_bot'], matched_layer['phi_bot'], matched_layer['Dr_bot']]] - z0_local, f_gamma, f_phi, f_Dr, f_sigma_v_eff, f_delta = sand_profile(profile) - - gamma_z = f_gamma(depth) - delta_z = f_delta(depth) - phi = f_phi(depth) - Nq = np.exp(np.pi*np.tan(np.deg2rad(phi)))*(np.tan(np.deg2rad(45 + phi/2)))**2 - print(f'Nq = {Nq:.2f}, depth = {depth:.2f} m') - d_theta = (En*d*Nq*gamma_z*depth - W*np.cos(theta))/T*deltas - dT = (Et*d*gamma_z*depth*np.tan(np.deg2rad(delta_z)) + W*np.sin(theta))*deltas - - else: - raise ValueError(f"Unsupported soil type: {matched_layer['soil_type']}") - - d_drag = deltas*np.cos(theta) - d_depth = deltas*np.sin(theta) - - theta += d_theta - T -= dT - drag += d_drag - depth += d_depth - - if abs(Tm - T) > 0.75*Tm: - raise Exception(f"Load transfer unrealistic: Tm = {Tm/1e6:.2f} MN vs T = {T/1e6:.2f} MN") - if not (0 < np.rad2deg(theta) < 90): - raise Exception(f"Load angle unrealistic: {np.rad2deg(theta):.2f} deg") - - drag_values.append(-drag); - depth_values.append(-depth); - - Ta = T; thetaa = theta - - print(f'Input Tm = {Tm}, thetam = {thetam}, zlug = {zlug}') - print(f'Output Hm = {Tm*np.cos(np.deg2rad(thetam))}, Vm = {Tm*np.sin(np.deg2rad(thetam))}') - print(f'Output Ta = {Ta}, thetaa = {np.rad2deg(thetaa)}') - print(f'Output Ha = {Ta*np.cos(thetaa)}, Va = {Ta*np.sin(thetaa)}') - - resultsLoad = { - 'Tm': Tm, - 'thetam': thetam, - 'Ta': Ta, - 'thetaa': np.rad2deg(thetaa), - 'length': deltas*len(drag_values), - 'drag_values': drag_values, - 'depth_values': depth_values - } - - return layers, resultsLoad - - -if __name__ == '__main__': - - profile_map = [ - { - 'name': 'CPT_1', - 'x': 498234, 'y': 5725141, - 'layers': [ - { - 'top': 1.0, 'bottom': 2.0, - 'soil_type': 'clay', - 'gamma_top': 8.0, 'gamma_bot': 8.0, - 'Su_top': 10, 'Su_bot': 25}, - { - 'top': 2.0, 'bottom': 8.0, - 'soil_type': 'clay', - 'gamma_top': 8.0, 'gamma_bot': 8.0, - 'Su_top': 25, 'Su_bot': 50}, - { - 'top': 8.0, 'bottom': 16.0, - 'soil_type': 'clay', - 'gamma_top': 8.0, 'gamma_bot': 8.0, - 'Su_top': 50, 'Su_bot': 100} - ] - } - ] - # profile_map = [ - # { - # 'name': 'CPT_1', - # 'x': 498234, 'y': 5725141, - # 'layers': [ - # # { - # # 'top': 0.0, 'bottom': 5.0, - # # 'soil_type': 'sand', - # # 'gamma_top': 9.5, 'gamma_bot': 9.5, - # # 'phi_top': 28, 'phi_bot': 30, - # # 'Dr_top': 70, 'Dr_bot': 70}, - # { - # 'top': 0.0, 'bottom': 5.0, - # 'soil_type': 'clay', - # 'gamma_top': 8.0, 'gamma_bot': 8.0, - # 'Su_top': 25, 'Su_bot': 25}, - # { - # 'top': 5.0, 'bottom': 10.0, - # 'soil_type': 'sand', - # 'gamma_top': 9.5, 'gamma_bot': 9.5, - # 'phi_top': 32, 'phi_bot': 36, - # 'Dr_top': 70, 'Dr_bot': 70}, - # { - # 'top': 10.0, 'bottom': 15.0, - # 'soil_type': 'sand', - # 'gamma_top': 9.5, 'gamma_bot': 9.5, - # 'phi_top': 42, 'phi_bot': 45, - # 'Dr_top': 70, 'Dr_bot': 70} - # ] - # } - # ] - - Tm = 6e6 # Load at mudline (N) - thetam = 10 # Angle at mudline (deg) - zlug = 8 # Padeye depth (m) - line_type = 'chain' - d = 0.16 # Chain diameter (m) - w = 5000 # Line weight (N/m) - - layers, resultsLoad = getTransferLoad(profile_map, Tm, thetam, zlug, line_type, d, w, plot=True) - - # print("\n--- Transfer Load Results ---") - # for key, val in resultsLoad.items(): - # if isinstance(val, float): - # print(f"{key}: {val:.3f}") - # elif isinstance(val, list): - # print(f"{key}:") - # for v in val: - # print(f" {v:.3f}") - # else: - # print(f"{key}: {val}") - - plot_load(layers, resultsLoad['drag_values'], resultsLoad['depth_values'], - resultsLoad['Tm'], resultsLoad['thetam'], resultsLoad['Ta'], - resultsLoad['thetaa'], zlug=zlug) \ No newline at end of file diff --git a/famodel/anchors/anchors_famodel_map/capacity_plate_map.py b/famodel/anchors/anchors_famodel_map/capacity_plate_map.py deleted file mode 100644 index 56e50b44..00000000 --- a/famodel/anchors/anchors_famodel_map/capacity_plate_map.py +++ /dev/null @@ -1,177 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from .capacity_soils_map import clay_profile -from .capacity_plots_map import plot_plate - -def getCapacityPlate(profile_map, location_name, B, L, zlug, beta, Ha, Va, plot=True): - '''Calculate the plate anchor capacity using clay soil layers from profile_map. - The calculation is based on the soil profile, anchor geometry and inclined load. - - Parameters - ---------- - profile_map : list of dict - Soil profile map with coordinates and layers per location. - location_name : str - Name of the location to select the soil profile. - B : float - Plate width (m) - L : float - Plate length (m) - zlug : float - Embedment depth of the main padeye (m) - beta : float - Inclination angle of the plate (deg) - Ha : float - Applied horizontal load (N) - Va : float - Applied vertical load (N) - plot : bool - Whether to generate plots. - - Returns - ------- - Dictionary with Capacity, Weight, UC, etc. - ''' - - # Extract and filter clay layers from profile_map - profile_entry = next(p for p in profile_map if p['name'] == location_name) - layers = [layer for layer in profile_entry['layers'] if layer['soil_type'] == 'clay'] - - if not layers: - raise ValueError('Plate anchor capacity model only supports clay soils.') - - # Build the profile array: [[z, Su, gamma], ...] - profile = [] - for layer in layers: - profile.append([layer['top'], layer['gamma_top'], layer['Su_top']]) - profile.append([layer['bottom'], layer['gamma_bot'], layer['Su_bot']]) - - print("layer gamma_top (raw):", layer['gamma_top']) - print("layer gamma_bot (raw):", layer['gamma_bot']) - - profile = np.array(sorted(profile, key=lambda x: x[0])) - - # Parameters and constants - Los = 0.05 - B_t = 40 - rhows = 66.90e3 # Submerged steel (N/m3) - rhow = 10e3 # Seawater (N/m3) - - # Evaluate interpolated Su and gamma - z0, f_gamma, f_Su, f_sigma_v_eff, f_alpha = clay_profile(profile) - t = round(B/B_t, 2) - V_steel = round(B*L*t, 2) - zlug_B = zlug/B - - # Profile check points - npts = 10 - z_offsets = np.linspace(-0.5, 0.5, npts)*B*np.sin(np.deg2rad(beta)) - z_points = zlug + z_offsets; print(z_points) - - Su_vals = [f_Su(z) for z in z_points] - gamma_10 = f_gamma(z_points[2]); print(gamma_10) - gamma_vals = [f_gamma(z) for z in z_points]; print("gamma_vals:", [f"{val:.2f}" for val in gamma_vals], "N/m3") - Su = np.mean(Su_vals); print(f"Su: {Su:.2f} Pa") - gamma = np.mean(gamma_vals); print(f"gamma: {gamma:.2f} N/m3") - - print("Profile being sent to clay_profile():") - for row in profile: - print(f"z = {row[0]:.2f} m, gamma = {row[1]:.2f} kN/m³, Su = {row[2]:.2f} kPa") - - # Shear strength gradient - k = np.polyfit(z_points, Su_vals, 1)[0] - print(f"k: {k:.2f}") - - # Pile weight including auxiliary parts - Wp = 1.35*V_steel*(rhows + rhow) - - # Capacity factors - Nco_0_0 = 2.483*np.log(zlug_B) + 1.974 - Nco_90_0 = 2.174*np.log(zlug_B) + 3.391 - kBSh = k*B/Su - print(f"kBSh: {kBSh:.2f}") - - f0 = np.where(zlug_B < 4, 1.77*(zlug_B**0.3) - 1.289, 0.192*zlug_B + 0.644) - f90 = np.where(zlug_B < 4, 0.68*(zlug_B**0.5) - 0.410, 0.153*zlug_B + 0.341) - - S_kB_0 = 1 - f0*kBSh - S_kB_90 = 1 - f90*kBSh - Nco_0 = S_kB_0*Nco_0_0 - Nco_90 = S_kB_90*Nco_90_0 - Nco = Nco_0 + (Nco_90 - Nco_0)*(beta/90)**2 - - Nco_s_0_0 = np.where(2.90*zlug_B + 6.02 <= 11.59, 2.90*zlug_B + 6.02, 11.596) - Nco_s_90_0 = np.where(2.72*zlug_B + 4.02 <= 11.59, 2.72*zlug_B + 4.02, 11.596) - - S_s_kB_0 = np.where(zlug_B <= 2, 1 + (0.8 - 0.3*zlug_B)*kBSh - (0.383*kBSh**1.36), 1) - f90s = np.where(zlug_B <= 3, 0.267*zlug_B, 0.6) - S_s_kB_90 = 1 - f90s*kBSh - Nco_s_0 = S_s_kB_0*Nco_s_0_0 - Nco_s_90 = S_s_kB_90*Nco_s_90_0 - Nco_s = Nco_s_90 + (Nco_s_0 - Nco_s_90)*((90 - beta)/90)**2 - - Nc_final = max(Nco + (gamma*zlug)/Su, Nco_s) - print(f"Nc_star: {Nco + (gamma*zlug)/Su:.2f}") - print(f"Nc_star: {Nco_s:.2f}") - qu = Nc_final*Su - Tmax = round(qu*(1 - Los)*B*L, 2) - Hmax = Tmax*np.cos(np.deg2rad(90 - beta)) - Vmax = Tmax*np.sin(np.deg2rad(90 - beta)) - - Ta = np.sqrt(Ha**2 + Va**2) - UC = Ta/Tmax - - resultsPlate = { - 'Capacity': Tmax, - 'Horizontal max.': Hmax, - 'Vertical max.': Vmax, - 'Unity check': UC, - 'Weight plate': Wp - } - - return layers, resultsPlate - -if __name__ == '__main__': - profile_map = [ - { - 'name': 'CPT_1', - 'x': 498234, 'y': 5725141, - 'layers': [ - { - 'top': 0.0, 'bottom': 9.5, - 'soil_type': 'clay', - 'gamma_top': 8.0, 'gamma_bot': 8.5, - 'Su_top': 10, 'Su_bot': 25 - }, - { - 'top': 9.5, 'bottom': 11.5, - 'soil_type': 'clay', - 'gamma_top': 8.5, 'gamma_bot': 8.5, - 'Su_top': 25, 'Su_bot': 45 - }, - { - 'top': 11.5, 'bottom': 25.0, - 'soil_type': 'clay', - 'gamma_top': 8.5, 'gamma_bot': 9.0, - 'Su_top': 45, 'Su_bot': 50 - } - ] - } - ] - - B = 2.0 - L = 2.0 - zlug = 10.0 - Ha = 350e3 - Va = 400e3 - alpha = np.rad2deg(np.arctan2(Va, Ha)) - beta = 90 - alpha - - layers, results = getCapacityPlate(profile_map, 'CPT_1', B, L, zlug, beta, Ha, Va) - - print("\n--- Plate Anchor Capacity Results ---") - for key, val in results.items(): - print(f"{key}: {val:.2f}") - - plot_plate(layers, B, L, z0 = layers[0]['top'], zlug=zlug, beta=beta, title='Plate Anchor in Layered Soil') diff --git a/famodel/anchors/anchors_famodel_map/capacity_suction_map.py b/famodel/anchors/anchors_famodel_map/capacity_suction_map.py deleted file mode 100644 index db296616..00000000 --- a/famodel/anchors/anchors_famodel_map/capacity_suction_map.py +++ /dev/null @@ -1,401 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from scipy.optimize import fsolve -from .capacity_soils_map import clay_profile, sand_profile -from .capacity_plots_map import plot_suction - - -def PileSurface(Len, Dia): - return np.pi*Dia*Len - -def PileWeight(Len, Dia, tw, rho): - return ((np.pi/4)*((Dia**2 - (Dia - 2*tw)**2)*Len + (np.pi/4)*Dia**2*tw))*rho - -def SoilWeight(Len, Dia, tw, gamma_soil): - return (np.pi/4)*(Dia - 2*tw)**2*Len*gamma_soil - -def rlugTilt(r, z, theta): - return r*np.cos(np.deg2rad(theta)) - z*np.sin(np.deg2rad(theta)) - -def zlugTilt(r, z, theta): - return r*np.sin(np.deg2rad(theta)) + z*np.cos(np.deg2rad(theta)) - -def getCapacitySuction(profile_map, location_name, D, L, zlug, Ha, Va, thetalug=5, psilug=7.5, plot=True): - '''Calculate the inclined load capacity of a suction pile in sand or clay following S. Kay methodology. - The calculation is based on the soil profile, anchor geometry and inclined load. - - Parameters - ---------- - profile : array - Soil profile as a 2D array: (z, parameters) - Clay soil profile (z (m), Su (kPa), gamma (kN/m³)) - Sand soil profile (z (m), phi (deg), gamma (kN/m³), Dr (%)) - soil_type : string - Select soil condition, 'clay' or 'sand' - D : float - Suction pile diameter (m) - L : float - Suction pile length from pile head (m) - zlug: float - Embedded depth of the main padeye (m) - thetalug: float - Angle of tilt misaligment (deg) (default value: 5.0) - psilug: float - Angle of twist misaligment (deg) (default value: 7.5) - Ha : float - Horizontal load at pile lug elevation (N) - Va : float - Vertical load at pile lug elevation (N) - plot : bool - Plot the capacity envelope if True - - Returns - ------- - Dictionary with capcity, weigths and UC. - ''' - - # Retrieve soil layers from map - profile_entry = next(p for p in profile_map if p['name'] == location_name) - layers = profile_entry['layers'] - - z0 = layers[0]['top'] # Mudline elevation - lambdap = (L - z0)/D # Suction pile slenderness ratio - t = (6.35 + D*20)/1e3 # Suction pile wall thickness (m), API RP2A-WSD - rlug = D/2 # Radial position of the lug - thetalug = 5 # Angle of tilt misaligment, default is 5. (deg) - psilug = 7.5 # Angle of twist misaligment, default is 7.5. (deg) - rhows = 66.90e3 # Submerged steel specific weight (N/m3) - rhow = 10e3 # Water specific weight (N/m3) - - Np_fixed = 10.25 - Np_free = 4.0 - Nc = min(6.2*(1 + 0.34*np.arctan(lambdap)), 9) - - # Initialize - sum_ez_weighted = 0.0 - sum_Hmax = 0.0 - Vmax_final = 0.0 - layer_data = [] - - # Profile check points - npts = 10 - - for layer in layers: - soil_type = layer['soil_type'] - z_top = layer['top'] - z_bot = layer['bottom'] - - if soil_type == 'clay': - # Prepare soil profile for clay - profile = [ - [z_top, layer['gamma_top'], layer['Su_top']], - [z_bot, layer['gamma_bot'], layer['Su_bot']] - ] - - z_ref, f_gamma, f_Su, f_sigma_v_eff, f_alpha = clay_profile(profile) - - # Clip the layer first - z_top_clip = max(z_top, z0) - z_bot_clip = min(z_bot, z0 + (L - z0)) - dz_clip = z_bot_clip - z_top_clip; # print(f'dz_clip = {dz_clip:.2f} m') - - if dz_clip <= 0: - continue # Skip layers fully above or below - - # Calculate properties over clipped dz - z_vals = np.linspace(z_top_clip, z_bot_clip, npts) - Su_vals = f_Su(z_vals) - Su_total = np.trapz(Su_vals, z_vals) - Su_moment = np.trapz(Su_vals*z_vals, z_vals) - - Su_av_z = Su_total/dz_clip; # print(f'Su_av_z = {Su_av_z:.2f} Pa') - ez_layer = Su_moment/Su_total; - Su_bot = f_Su(z_bot_clip) - gamma_vals = f_gamma(z_vals) - gamma_av = np.mean(gamma_vals) - - # Calculate Hmax for clay - Hmax_layer = Np_fixed*D*dz_clip*Su_av_z; print(f'Su_av_z = {Su_av_z:.2f} Pa') - - layer_data.append({ - 'z_top': z_top_clip, - 'z_bot': z_bot_clip, - 'dz': dz_clip, - 'Hmax_layer': Hmax_layer, - 'ez_layer': ez_layer - }) - - sigma_v_eff = f_sigma_v_eff(np.mean(z_vals)) - alpha_av = float(f_alpha(np.mean(z_vals))) - - # Side shear To and Ti - To = PileSurface(dz_clip, D)*alpha_av*Su_av_z - Ti = PileSurface(dz_clip, D - 2*t)*alpha_av*Su_av_z - - # Tip resistance - if abs(z_bot_clip - (z0 + (L - z0))) < 1e-3: # tip check - Tbase = (np.pi/12)*D**3*Su_bot - else: - Tbase = 0.0 - - Tmax = min(To + Ti, To + Tbase) - - # Torque induced by horizontal load - T = Ha*rlug*np.sin(np.deg2rad(psilug)) - - nhuT = T/Tmax - nhuV = Ha/To - nhuVstar = np.sqrt(nhuV**2 - nhuT**2) - alphastar = alpha_av*(nhuVstar/nhuV); print(f"alphastar = {alphastar:.3f}") - - # Constant weight - Pile_Head = PileWeight(z0, D, t, rhows) - - # Vertical failure modes - if np.isclose(z_bot_clip, z0 + (L - z0), atol=0.1): - Vmax1 = PileWeight(dz_clip, D, t, rhows) + PileSurface(dz_clip, D)*alphastar*Su_av_z + Nc*Su_bot*(np.pi/4)*D**2 - else: - Vmax1 = np.inf # No tip resistance unless at tip - - Vmax2 = PileWeight(dz_clip, D, t, rhows) + PileSurface(dz_clip, D)*alphastar*Su_av_z + PileSurface(dz_clip, D - 2*t)*alphastar*Su_av_z - Vmax3 = PileWeight(dz_clip, D, t, rhows) + PileSurface(dz_clip, D)*alphastar*Su_av_z + SoilWeight(dz_clip, D, t, gamma_av) - - Vmax_layer = min(Vmax1, Vmax2, Vmax3) - - # Sum vertical capacities - Vmax_final += Vmax_layer - - # Print layer debug info - print(f"Vmax_layer = {Vmax_layer:.2f} N") - print(f"Vmax1 = {Vmax1:.2f} N") - print(f"Vmax2 = {Vmax2:.2f} N") - print(f"Vmax3 = {Vmax3:.2f} N") - - elif soil_type == 'sand': - # Prepare soil profile for sand - profile = [ - [z_top, layer['gamma_top'], layer['phi_top'], layer['Dr_top']], - [z_bot, layer['gamma_bot'], layer['phi_bot'], layer['Dr_bot']] - ] - - z_ref, f_gamma, f_phi, _, f_sigma_v_eff, f_delta = sand_profile(profile) - - # Clip the layer within pile embedded length - z_top_clip = max(z_top, z0) - z_bot_clip = min(z_bot, z0 + (L - z0)) - dz_clip = z_bot_clip - z_top_clip - - if dz_clip <= 0: - continue # Skip non-overlapping layers - - # Calculate properties over clipped dz - z_vals = np.linspace(z_top_clip, z_bot_clip, npts) - phi_vals = f_phi(z_vals) - sigma_vals = f_sigma_v_eff(z_vals) - delta_vals = f_delta(z_vals) - - phi_av = np.mean(phi_vals) - sigma_av = np.mean(sigma_vals) - delta_av = np.mean(delta_vals) - - sigma_tip = f_sigma_v_eff(z_bot_clip) - - Nq = np.e**(np.pi*np.tan(np.radians(phi_av)))*(np.tan(np.radians(45) + np.radians(phi_av)/2))**2 - - # Calculate Hmax for sand - Hmax_layer = 0.5*Nq*D*gamma_av*dz_clip**2 - - layer_data.append({ - 'z_top': z_top_clip, - 'z_bot': z_bot_clip, - 'dz': dz_clip, - 'Hmax_layer': Hmax_layer, - 'ez_layer': np.mean(z_vals) - }) - - # Side friction - To = PileSurface(dz_clip, D)*delta_av*sigma_av - Ti = PileSurface(dz_clip, D - 2*t)*delta_av*sigma_av - - if abs(z_bot_clip - (z0 + (L - z0))) < 1e-3: - Tbase = np.pi/4*D**2*sigma_tip - else: - Tbase = 0.0 - - Tmax = min(To + Ti, To + Tbase) - - # Torque induced by horizontal load - T = Ha*rlug*np.sin(np.deg2rad(psilug)) - nhuT = T/Tmax - nhuV = Ha/To - nhuVstar = np.sqrt(nhuV**2 - nhuT**2) - deltastar = delta_av*(nhuVstar/nhuV) - - # Vertical failure modes - Vmax2 = Pile_Head + PileWeight(dz_clip, D, t, rhows) + PileSurface(dz_clip, D)*deltastar*sigma_av + PileSurface(dz_clip, D - 2*t)*deltastar*sigma_av - Vmax3 = Pile_Head + PileWeight(dz_clip, D, t, rhows) + PileSurface(dz_clip, D)*deltastar*sigma_av + SoilWeight(dz_clip, D, t, gamma_av) - - Vmax_layer = min(Vmax2, Vmax3) - - # Sum vertical capacities - Vmax_final += Vmax_layer - - print(f"Vmax_layer (sand) = {Vmax_layer:.2f} N") - print(f"Vmax2 (sand) = {Vmax2:.2f} N") - print(f"Vmax3 (sand) = {Vmax3:.2f} N") - - # sum Hmax and weighted ez - for data in layer_data: - z_top = data['z_top'] - z_bot = data['z_bot'] - Hmax_layer = data['Hmax_layer'] - ez_layer = data['ez_layer'] - dz_layer = data['dz'] - - z_embedded_start = z0 - z_embedded_end = z0 + (L - z0) - - if z_top >= z_embedded_start and z_bot <= z_embedded_end: - sum_ez_weighted += Hmax_layer*ez_layer - sum_Hmax += Hmax_layer - # print(f'ez_layer (full) = {ez_layer:.2f} m') - - elif z_top < z_embedded_end and z_bot > z_embedded_start: - dz_inside = min(z_bot, z_embedded_end) - max(z_top, z_embedded_start) - if dz_inside > 0: - ratio = dz_inside/dz_layer - sum_ez_weighted += Hmax_layer*ratio*ez_layer - sum_Hmax += Hmax_layer * ratio - # print(f'ez_layer (partial) = {ez_layer:.2f} m') - - ez_global = sum_ez_weighted/sum_Hmax - # print(f'sum_ez_weighted = {sum_ez_weighted:.2f}') - print(f'ez_global = {ez_global:.2f} m') - print(f'Hmax = {sum_Hmax:.2f} m') - - # Calculate moment and Hmax_final - M_total = -Va*rlugTilt(rlug, zlug, thetalug) - Ha*(zlugTilt(rlug, zlug, thetalug) - ez_global) - # print(f"rlug_eff = {rlugTilt(rlug, zlug, thetalug):.2f} m") - # print(f"zlug_eff = {zlugTilt(rlug, zlug, thetalug):.2f} m") - print(f"M_total = {M_total:.2f} Nm") - - # ΔφMH from Kay 2014 - if 0.5 <= lambdap < 1.125: - delta_phi = 0.32 + 4.32*lambdap; #print(delta_phi) - elif 1.125 <= lambdap < 2.0: - delta_phi = 7.13 - 1.71*lambdap; #print(delta_phi) - elif 2.0 <= lambdap <= 6.0: - delta_phi = 4.55 - 0.425*lambdap; #print(delta_phi) - else: - raise ValueError('L/D out of bounds for MH ellipse.') - - phi_MH = -np.arctan(ez_global/(L - z0)) - np.deg2rad(delta_phi) - a_MH = Np_fixed/np.cos(phi_MH) - delta_bMH = 0.45*(lambdap)**(-0.9) if lambdap <= 1.5 else 0 - b_MH = -Np_free*np.sin(phi_MH) + delta_bMH - print('M cos(phi)/a_MH =', (M_total*np.cos(phi_MH))/a_MH) - print('M sin(phi)/b_MH =', (M_total*np.sin(phi_MH))/b_MH) - - def f(H_var): - term1 = ((M_total*np.cos(phi_MH) + H_var*np.sin(phi_MH))/a_MH)**2 - term2 = ((M_total*np.sin(phi_MH) - H_var*np.cos(phi_MH))/b_MH)**2 - return term1 + term2 - 1 - - try: - Hmax_final = max(fsolve(f, sum_Hmax*0.8)[0], 0.0) - except: - Hmax_final = 0.0 - - print(f"Hmax_final (MH ellipse) = {Hmax_final:.2f} N") - - # Constant weight - pile_head = PileWeight(z0, D, t, rhows); print(f"pile_head = {pile_head:.2f} N") - Vmax_final += pile_head; print(f"Vmax_final = {Vmax_final:.2f} N") - - # Unity check - UC = (Ha/Hmax_final)**(0.5 + lambdap) + (Va/Vmax_final)**(4.5 + lambdap/3) if Hmax_final and sum_Hmax else np.inf - - # Plotting - if plot: - x = np.linspace(0, 1, 100) - y = (1 - x**(4.5 + lambdap/3))**(1/(0.5 + lambdap)) - - plt.figure(figsize=(6, 5)) - plt.plot(Hmax_final*x, Vmax_final*y, 'b', label='VH Envelope') - plt.plot(Ha, Va, 'ro', label='Applied Load') - plt.xlabel('Horizontal Capacity (N)') - plt.ylabel('Vertical Capacity (N)') - plt.title('VH suction pile capacity envelope') - plt.grid(True) - plt.legend() - plt.tight_layout() - plt.show() - - resultsSuction = { - 'Horizontal max.': Hmax_final, - 'Vertical max.': Vmax_final, - 'Unity check': UC, - # 'Weight pile': Wp, - # 'Weight soil': Wsoil, - 't': t - } - - return layers, resultsSuction - -if __name__ == '__main__': - - profile_map = [ - { - 'name': 'CPT_1', - 'x': 498234, 'y': 5725141, - 'layers': [ - { - 'top': 2.0, 'bottom': 4.0, - 'soil_type': 'clay', - 'gamma_top': 8.0, 'gamma_bot': 8.5, - 'Su_top': 25, 'Su_bot': 50}, - { - 'top': 4.0, 'bottom': 8.0, - 'soil_type': 'clay', - 'gamma_top': 8.5, 'gamma_bot': 9.0, - 'Su_top': 50, 'Su_bot': 75}, - { - 'top': 8.0, 'bottom': 16.0, - 'soil_type': 'clay', - 'gamma_top': 9.0, 'gamma_bot': 9.5, - 'Su_top': 75, 'Su_bot': 100}, - { - 'top': 16.0, 'bottom': 25.0, - 'soil_type': 'clay', - 'gamma_top': 9.5, 'gamma_bot': 9.5, - 'Su_top': 100, 'Su_bot': 100}] - } - ] - - - # Pile and load properties - D = 2.5 # Pile diameter (m) - L = 10.0 # Pile length (m) - zlug = 8.0 # Lug depth (m) - theta = 5 # Tilt misalignment angle (deg) - psi = 7.5 # Twist misalignment angle (deg) - Ha = 6e6 # Applied horizontal load (N) - Va = 2e6 # Applied vertical load (N) - - # Calculate - layers, resultsSuction = getCapacitySuction( - profile_map, 'CPT_1', # Soil properties and location of the pile - D, L, zlug, # Pile geometrical properties - Ha, Va, # Pile loading conditions - thetalug=theta, psilug=psi, # Pile misaligment tolerances - plot=True - ) - - # print('\n--- Suction Pile Capacity Results ---') - # print(f"Hmax_final = {resultsSuction['Hmax_final']:.2f} N") - # print(f"Vmax_final = {resultsSuction['Vmax_final']:.2f} N") - # print(f"Unity check (UC) = {resultsSuction['UnityCheck']:.4f}") - # print(f"Total Moment (M_total) = {resultsSuction['M_total']:.2f} Nm") - - plot_suction(layers, L, D, z0 = layers[0]['top'], zlug=zlug, title='Suction Pile and Soil Layers') diff --git a/famodel/anchors/anchors_famodel_map/capacity_torpedo_map.py b/famodel/anchors/anchors_famodel_map/capacity_torpedo_map.py deleted file mode 100644 index adf5580f..00000000 --- a/famodel/anchors/anchors_famodel_map/capacity_torpedo_map.py +++ /dev/null @@ -1,272 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from .capacity_soils_map import clay_profile -from .capacity_plots_map import plot_torpedo - -def getCapacityTorpedo(profile_map, location_name, D1, D2, L1, L2, zlug, ballast, Ha, Va, plot=True): - '''Calculate the inclined load capacity of a torpedo pile in clay following S. Kay methodology. - The calculation is based on the soil profile, anchor geometry and inclined load. - - Parameters - ---------- - profile : array - Clay soil profile (z, Su, gamma) - Clay soil profile (z (m), Su (kPa), gamma (kN/m³)) - soil_type : string - Select soil condition, 'clay' - D1 : float - Wing diameter (m) - D2 : float - Shaft diameter (m) - L1 : float - Winged section length (m) - L2 : float - Shaft section length (m) - zlug : float - Padeye embedment depth (m) - Ha : float - Horizontal load at pile lug elevation (N) - Va : float - Vertical load at pile lug elevation (N) - plot : bool - Plot the capacity envelope if True - - Returns - ------- - Dictionary with capcity, weigth and UC. - ''' - - # Retrieve soil layers from map - profile_entry = next(p for p in profile_map if p['name'] == location_name) - layers = profile_entry['layers'] - - L = L1 + L2 - t = (6.35 + D2*20)/1e3 - rhows = 66.90e3 - rhow = 10e3 - - def PileWeight(Len1, Len2, Dia1, Dia2, tw, rho): - return ((np.pi/4)*(Dia1**2 - (Dia1 - 2*tw)**2)*(Len1 + Len2) + 4*Len2*Dia2*tw)*rho - - def PileWingedSurface(length, diameter): - return np.pi*diameter*length - - def PileShaftSurface(length, diameter1, diameter2): - return 8*length*(diameter1 - diameter2) - - z_start = zlug - z_wing = zlug + L1 - z_end = zlug + L - - layer_data = [] - Vmax_total = 0.0 - - # Profile check points - npts = 10 - - for layer in layers: - if layer['soil_type'] != 'clay': - raise ValueError('Torpedo pile capacity model only supports clay soils.') - - z_layer_top = layer['top'] - z_layer_bot = layer['bottom'] - - z_clip_top = max(z_layer_top, z_start) - z_clip_bot = min(z_layer_bot, z_end) - - if z_clip_bot <= z_clip_top: - continue - - segments = [] - if z_clip_bot <= z_wing: - segments.append((z_clip_top, z_clip_bot, D1)) - elif z_clip_top >= z_wing: - segments.append((z_clip_top, z_clip_bot, D2)) - else: - segments.append((z_clip_top, z_wing, D1)) - segments.append((z_wing, z_clip_bot, D2)) - - for z_seg_top, z_seg_bot, D in segments: - dz_seg = z_seg_bot - z_seg_top - if dz_seg <= 0: - continue - - profile = [ - [z_seg_top, layer['Su_top'], layer['gamma_top']], - [z_seg_bot, layer['Su_bot'], layer['gamma_bot']] - ] - z_ref, f_Su, _, f_gamma, f_alpha = clay_profile(profile) - - z_vals = np.linspace(z_seg_top, z_seg_bot, npts) - Su_vals = f_Su(z_vals) - alpha_vals = np.array([f_alpha(z) for z in z_vals]) - - Su_total = np.trapz(Su_vals, z_vals) - Su_moment = np.trapz(z_vals*Su_vals, z_vals) - print("xxxxxxxxxxxxxxxxxxxxxxxxx") - Su_av_z = Su_total/dz_seg - print(f"Su_av_z = {Su_av_z:.2f} Pa") - ez_layer = Su_moment /Su_total - print(f"dz_seg = {dz_seg:.2f} m") - print(f"ez_layer = {ez_layer:.2f} m") - alpha_av = np.mean(alpha_vals) - print(f"alpha_av = {alpha_av:.2f}") - - Np_free = 3.45 - Hmax_layer = Np_free*dz_seg*D*Su_av_z - print(f"Hmax_layer = {Hmax_layer:.2f} N") - print(f"D = {D:.2f} m") - - surface_area = PileWingedSurface(dz_seg, D) if D == D1 else PileShaftSurface(dz_seg, D1, D2) - Vmax_layer = surface_area*alpha_av*Su_av_z - Vmax_total += Vmax_layer - print(f"Vmax_layer = {Vmax_layer:.2f} N") - - layer_data.append({ - 'z_top': z_seg_top, - 'z_bot': z_seg_bot, - 'dz': dz_seg, - 'Hmax_layer': Hmax_layer, - 'ez_layer': ez_layer, - 'Su_av_z': Su_av_z, - 'D_used': D - }) - - if not layer_data: - raise ValueError('No overlapping clay layers within pile depth.') - - sum_Hmax = 0.0 - sum_ez_weighted = 0.0 - - for data in layer_data: - z_top = data['z_top'] - z_bot = data['z_bot'] - Hmax_layer = data['Hmax_layer'] - ez_layer = data['ez_layer'] - dz_layer = data['dz'] - - z_embedded_start = zlug - z_embedded_end = zlug + L - - if z_top >= z_embedded_start and z_bot <= z_embedded_end: - sum_ez_weighted += Hmax_layer*ez_layer - sum_Hmax += Hmax_layer - elif z_top < z_embedded_end and z_bot > z_embedded_start: - dz_inside = min(z_bot, z_embedded_end) - max(z_top, z_embedded_start) - if dz_inside > 0: - ratio = dz_inside/dz_layer - sum_ez_weighted += Hmax_layer*ratio*ez_layer - sum_Hmax += Hmax_layer * ratio - - ez_global = sum_ez_weighted/sum_Hmax - print(f'ez_global = {ez_global:.2f} m') - print(f'sum_Hmax = {sum_Hmax:.2f} N') - - Vmax_total += PileWeight(L1, L2, D1, D2, t, rhows) + ballast - Wp = 1.10 * PileWeight(L1, L2, D1, D2, t, rhows + rhow) + ballast - - ez_ratio = (ez_global - zlug)/L; print(f"ez_ratio = {ez_ratio:.2f} m") - - # Average effective width - L = L1 + L2 - A_wing_plane_1 = (D1 - D2)*L1 - A_wing_plane_2 = (D1 - D2)*np.cos(np.deg2rad(45))/2*L1 - A_shaft = D2*L - - # Choose based on direction: - plane = '1' # or '2' - - if plane == '1': - Dstar = (A_wing_plane_1 + A_shaft)/L - elif plane == '2': - Dstar = (A_wing_plane_2 + A_shaft)/L - - # Assign aVH and bVH based on ez_su/L - if np.isclose(ez_ratio, 2/3, atol=0.05): - aVH = 0.5 + L/Dstar - bVH = 4.5 - L/(3*Dstar) - mode = 'deep mobilization (2/3)' - elif 0.40 <= ez_ratio <= 0.75: - aVH = 4.5 + L/(2*Dstar) - bVH = 3.5 - L/(4*Dstar) - mode = 'moderate mobilization (1/2 – 3/4)' - # else: - # aVH = 4.0 - # bVH = 4.0 - # mode = 'default exponents (fallback)' - print(f'Interaction exponents set to aVH = {aVH:.2f}, bVH = {bVH:.2f} [{mode}]') - - UC = (Ha/sum_Hmax)**aVH + (Va/Vmax_total)**bVH - - if plot: - deg = np.linspace(0, 90, 20) - x = np.cos(np.deg2rad(deg)) - y = (1 - x**bVH)**(1/aVH) - X = sum_Hmax*x - Y = Vmax_total*y - - plt.figure(figsize=(6, 5)) - plt.plot(X, Y, color='blue', label='VH Envelope') - plt.plot(Ha, Va, 'o', color='red', label='Load Point') - plt.xlabel('Horizontal Capacity (N)') - plt.ylabel('Vertical Capacity (N)') - plt.title('VH torpedo pile capacity envelope') - plt.grid(True) - plt.legend() - plt.tight_layout() - plt.show() - - resultsTorpedo = { - 'Horizontal max.': sum_Hmax, - 'Vertical max.': Vmax_total, - 'Unity check': UC, - 'Weight pile': Wp, - 'ez_global': ez_global, - 'layer_data': layer_data - } - - return layers, resultsTorpedo - -if __name__ == '__main__': - - profile_map = [ - { - 'name': 'CPT_1', - 'x': 498234, 'y': 5725141, - 'layers': [ - { - 'top': 0.0, 'bottom': 20.0, - 'soil_type': 'clay', - 'gamma_top': 8.0, 'gamma_bot': 8.5, - 'Su_top': 50, 'Su_bot': 70}, - { - 'top': 20.0, 'bottom': 25.0, - 'soil_type': 'clay', - 'gamma_top': 8.5, 'gamma_bot': 8.5, - 'Su_top': 80, 'Su_bot': 100}, - { - 'top': 25.0, 'bottom': 50.0, - 'soil_type': 'clay', - 'gamma_top': 8.5, 'gamma_bot': 9.0, - 'Su_top': 125, 'Su_bot': 150}] - } - ] - - D1 = 3.0 - D2 = 1.5 - L1 = 11.0 - L2 = 5.0 - zlug = 15.0 - ballast = 10000 - Ha = 6.0e6 - Va = 8.0e6 - - layers, results = getCapacityTorpedo(profile_map, 'CPT_1', D1, D2, L1, L2, zlug, ballast, Ha, Va) - - # print("\n--- Torpedo Pile Capacity Results ---") - # for key, val in results.items(): - # if key != 'layer_data': - # print(f"{key}: {val:.2f}") - - plot_torpedo(layers, D1, D2, L1, L2, z0 = layers[0]['top'], zlug=zlug, title='Torpedo Pile in Clay Profile') diff --git a/famodel/anchors/anchors_famodel_profile/capacity_dandg.py b/famodel/anchors/anchors_famodel_profile/capacity_dandg.py deleted file mode 100644 index 1970a91c..00000000 --- a/famodel/anchors/anchors_famodel_profile/capacity_dandg.py +++ /dev/null @@ -1,272 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from scipy.interpolate import interp1d -from scipy import linalg -from .capacity_soils import rock_profile -from .capacity_pycurves import py_Lovera -from .capacity_plots import plot_pile - -def getCapacityDandG(profile, soil_type, L, D, zlug, Ha, Va, plot=True): - '''Models a laterally loaded pile using the p-y method. The solution for - lateral displacements is obtained by solving the 4th order ODE, - EI*d4y/dz4 - V*d2y/dz2 + ky = 0 using the finite difference method. - EI*d4y/dz4 - V*d2y/dz2 + K*z*dy/dz + ky = 0 using the finite difference method. - - Assumes that EI remains constant with respect to curvature i.e. pile - material remains in the elastic region. - - Parameters - ---------- - profile : array - Rock profile as a 2D array: (z (m), UCS (MPa), Em (MPa)) - soil_type : string - Select soil condition, 'rock' - L : float - Pile length (m) - D : float - Pile diameter (m) - zlug : float - Load eccentricity above the mudline or depth to mudline relative to the pile head (m) - Ha : float - Horizontal load at pile lug elevation (N) - Va : float - Vertical load at pile lug elevation (N) - plot : bool - Plot the p-y curve and the deflection pile condition if True - - Returns - ------- - y : array - Lateral displacement at each node (n+1 real + 4 imaginary) - z : array - Node location along pile (m) - resultsDandG : dict - Dictionary with lateral, rotational, vertical and pile weight results - ''' - - n = 50; loc = 2 # Number of nodes (-) - tol = 1e-16; max_iter = 50 # Iteration parameters (-) - nhuc = 1; nhu = 0.3 # Resistance factor (-) - delta_r = 0.08 # Mean roughness height (m) - - t = (6.35 + D*20)/1e3 # Pile wall thickness (m), API RP2A-WSD - E = 200e9 # Elastic modulus of pile material (Pa) - rhows = 66.90e3 # Submerged steel specific weight (N/m3) - rhow = 10e3 # Water specific weight (N/m3) - - # Pile geometry - I = (np.pi/64.0)*(D**4 - (D - 2*t)**4) - EI = E*I - h = L/n # Element size - N = (n + 1) + 4 # (n+1) Real + 4 Imaginary nodes - - # Dry and wet mass of the pile - def PileWeight(Len, Dia, tw, rho): - Wp = ((np.pi/4)*(Dia**2 - (Dia - 2*tw)**2)*Len)*rho - return Wp - - # Array for displacements at nodes, including imaginary nodes. - y = np.ones(N)*(0.01*D) # An initial value of 0.01D was arbitrarily chosen - - # Initialize and assemble array/list of p-y curves at each real node - z = np.zeros(N) - k_secant = np.zeros(N) - py_funs = [] - DQ = [] - z0, f_UCS, f_Em = rock_profile(profile) - - - for i in [0, 1]: # Top two imaginary nodes - z[i] = (i - 2)*h - py_funs.append(0) - k_secant[i] = 0.0 - - for i in range(2, n+3): # Real nodes - z[i] = (i - 2)*h - if z[i] < z0: - # No p-y curve above mudline - py_funs.append(lambda y_val: np.zeros_like(y_val)) - k_secant[i] = 0.0 - DQ.append(0.0) - else: - py_funs.append(py_Lovera(z[i], D, f_UCS, f_Em, zlug, z0, plot=True)) - # print(f"z = {z[i]:.2f} m, UCS = {f_UCS(z[i]):.2e} Pa, Em = {f_Em(z[i]):.2e} Pa") - UCS = f_UCS(z[i]) - Em = f_Em(z[i]) - SCR = nhuc*Em/(UCS*(1 + nhu))*delta_r/D - alpha = 0.36*SCR - 0.0005 - fs = alpha*UCS - Dq = np.pi*D*fs*z[i] - DQ.append(Dq) - Vmax = PileWeight(L, D, t, rhows) + DQ[-1] - - k_secant[i] = py_funs[i](y[i])/y[i] - - for i in [n+3, n+4]: # Bottom two imaginary nodes - z[i] = (i - 2)*h - py_funs.append(0) - k_secant[i] = 0.0 - - for j in range(max_iter): - y_old = y.copy() - y = fd_solver(n, N, h, EI, Ha, Va, zlug, z0, k_secant) - - # Update stiffness - for i in range(2, n+3): - if callable(py_funs[i]): - k_secant[i] = py_funs[i](y[i])/y[i] if y[i] != 0 else 0.0 - - # Check convergence - if np.linalg.norm(y - y_old, ord=2) < tol: - print(f'[Converged in {j+1} iterations]') - break - else: - print('[Warning: Solver did not converge]') - - if plot: - y1 = np.linspace(-2.*D, 2.*D, 500) - plt.plot(y1, py_funs[loc](y1)) - plt.xlabel('y (m)'), plt.ylabel('p (N/m)') - plt.grid(True) - - fig, ax = plt.subplots(figsize=(3, 5)) - y0 = np.zeros_like(z[2:-2]) - # Plot original vertical pile - ax.plot(y0, z[2:-2], 'k', label='Original pile axis') - # Plot deflected shape - ax.plot(y[2:-2], z[2:-2], 'r', label='Deflected shape') - # Padeye marker - ax.plot(0, zlug, 'ko', label=f'Padeye (zlug = {zlug:.2f} m)') - # Mudline marker - ax.axhline(z0, color='blue', linestyle='--', label=f'Mudline (z0 = {z0:.2f} m)') - - ax.set_xlabel('Lateral displacement (m)') - ax.set_ylabel('Depth (m)') - ax.set_xlim([-0.1*D, 0.1*D]) - ax.set_ylim([L + 5, -2]) # Downward is positive z - ax.grid(ls='--') - ax.legend() - - # Relevant index of nodes - zlug_index = int(zlug/h); print(zlug_index) - ymax_index = int(np.max(y)); print(ymax_index) - - resultsDandG = { - 'Weight pile': PileWeight(L, D, t, rhows + rhow), - 'Vertical max.': Vmax, - 'Lateral displacement': y[ymax_index], - 'Rotational displacement': np.rad2deg(abs(y[ymax_index - 1] - y[ymax_index])/h), - 'Unity check (vertical)': Va/Vmax if Vmax != 0 else np.inf, - 'Unity check (horizontal)': 0.0, # Placeholder; no Mp or Mi in current model - 'Bending moment': None, - 'Plastic moment': None, - 'Plastic hinge': None, - 'Hinge location': None, - 'p-y model': 'Lovera (2023)', - } - - return y[2:-2], z[2:-2], resultsDandG - -def fd_solver(n, N, h, EI, Ha, Va, zlug, z0, k_secant): - '''Solves the finite difference equations from 'py_analysis_1'. This function should be run iteratively for - non-linear p-y curves by updating 'k_secant' using 'y'. A single iteration is sufficient if the p-y curves - are linear. - - Parameters - ---------- - n : int - Number of elements (-) - N : int - Total number of nodes (-) - h : float - Element size (m) - EI : float - Flexural rigidity of the pile (Nm²) - Ha : float - Horizontal load at padeye (N) - Va : float - Vertical load at padeye (N) - zlug : float - Padeye depth from pile head (m) - z0 : float - Mudline elevation from pile head (m) - k_secant : array - Secant stiffness at each node - - Returns - ------- - y : array - Lateral displacement at each node (n+1 real + 4 imaginary) - ''' - - # Initialize and assemble matrix - X = np.zeros((N, N)) - - # (n+1) finite difference equations for (n+1) real nodes - for i in range(0,n+1): - X[i, i] = 1.0 - X[i, i+1] = -4.0 + Va*h**2/EI - X[i, i+2] = 6.0 - 2*Va*h**2/EI + k_secant[i+2]*h**4/EI - X[i, i+3] = -4.0 + Va*h**2/EI - X[i, i+4] = 1.0 - - # Curvature at pile head - X[n+1, 1] = 1.0 - X[n+1, 2] = -2.0 - X[n+1, 3] = 1.0 - - # Shear at pile head - X[n+2, 0] = -1.0 - X[n+2, 1] = 2.0 - Va*h**2/EI - X[n+2, 2] = 0.0 - X[n+2, 3] = -2.0 + Va*h**2/EI - X[n+2, 4] = 1.0 - - # Curvature at pile tip - X[n+3, -2] = 1.0 - X[n+3, -3] = -2.0 - X[n+3, -4] = 1.0 - - # Shear at pile tip - X[n+4, -1] = 1.0 - X[n+4, -2] = -2.0 + Va*h**2/EI - X[n+4, -3] = 0.0 - X[n+4, -4] = 2.0 - Va*h**2/EI - X[n+4, -5] = -1.0 - - # Initialize vector q - q = np.zeros(N) - - # Index of the node where the horizontal load is applied (padeye) - zlug_index = int(zlug/h) - q[zlug_index] = 2*Ha*h**3 - - # Solve for displacement - y = linalg.solve(EI*X, q) - - return y - -if __name__ == '__main__': - - profile_rock = np.array([ - [ 2.0, 2, 200], - [ 5.0, 2, 200], - [ 9.0, 2, 200], - [30.0, 2, 200] - ]) - - D = 3.0 # Diameter (m) - L = 10.0 # Length (m) - zlug = 1 # Padeye elevation (m) - Ha = 8.0e6 # Horizontal load (N) - Va = 3.0e6 # Vertical load (N) - - y, z, resultsDandG = getCapacityDandG(profile_rock, 'rock', L, D, zlug, Ha, Va, plot=True) - for key, val in resultsDandG.items(): - if isinstance(val, float): - print(f"{key}: {val:.3f}") - else: - print(f"{key}: {val}") - - plot_pile(profile_rock, 'rock', y, z, D, L, profile_rock[0, 0], zlug) diff --git a/famodel/anchors/anchors_famodel_profile/capacity_driven.py b/famodel/anchors/anchors_famodel_profile/capacity_driven.py deleted file mode 100644 index 485f7e8c..00000000 --- a/famodel/anchors/anchors_famodel_profile/capacity_driven.py +++ /dev/null @@ -1,418 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from scipy.interpolate import interp1d -from scipy import linalg -from .capacity_soils import clay_profile, sand_profile, rock_profile -from .capacity_pycurves import py_Matlock, py_API, py_Reese -from .capacity_plots import plot_pile - -def getCapacityDriven(profile, soil_type, L, D, zlug, Ha, Va, plot=True): - '''Models a laterally loaded pile using the p-y method. The solution for - lateral displacements is obtained by solving the 4th order ODE, EI*d4y/dz4 - EI*d4y/dz4 - V*d2y/dz2 + ky = 0 using the finite difference method. - EI*d4y/dz4 - V*d2y/dz2 + K*z*dy/dz + ky = 0 using the finite difference method. - - Assumes that EI remains constant with respect to curvature i.e. pile - material remains in the elastic region. - - Parameters - ---------- - profile : array - Soil profile as a 2D array: (z, parameters) - Clay: (z (m), Su (kPa), gamma (kN/m³)) - Sand: (z (m), phi (deg), gamma (kN/m³), Dr (%)) - Rock: (z (m), UCS (MPa), Em (MPa)) - soil_type : string - Select soil condition: 'clay', 'sand', or '(weak) rock' - L : float - Pile length (m) - D : float - Pile diameter (m) - zlug : float - Depth of padeye from pile head (m) - Ha : float - Horizontal load applied at padeye (N) - Va : float - Vertical load applied at padeye (N) - plot : bool - Plot the p-y curve and the deflection pile condition if True - - Returns - ------- - y : array - Lateral displacement at each node (real nodes only) - z : array - Node depth positions corresponding to y (m) - resultsDriven : dict - Dictionary containing displacements, moment capacity, hinge state and vertical capacity - ''' - - n = 50; iterations = 10; loc = 2 - nhuc = 1; nhu = 0.3 # Resistance factor (-) - delta_r = 0.08 # Mean roughness height (m) - - t = (6.35 + D*20)/1e3 # Pile wall thickness (m), API RP2A-WSD - E = 200e9 # Elastic modulus of pile material (Pa) - fy = 350e6 # Yield strength of pile material (Pa) - rhows = 66.90e3 # Submerged steel specific weight (N/m3) - rhow = 10e3 # Water specific weight (N/m3) - - # Pile geometry - I = (np.pi/64.0)*(D**4 - (D - 2*t)**4) - EI = E*I - h = L/n # Element size - N = (n + 1) + 4 # (n+1) Real + 4 Imaginary nodes - - # Outer and inner surface of the pile skirt - def PileSurface(Len, Dia): - Sp = np.pi*Dia*Len - return Sp - # Dry and wet mass of the pile - def PileWeight(Len, Dia, tw, rho): - Wp = ((np.pi/4)*(Dia**2 - (Dia - 2*tw)**2)*Len)*rho - return Wp - # Mass of the soil plug - def SoilWeight(Len, Dia, tw, gamma_soil): - Wsoil =(np.pi/4)*(Dia - 2*tw)**2*Len*gamma_soil - return Wsoil - - # Array for displacements at nodes, including imaginary nodes. - y = np.ones(N)*(0.01*D) # An initial value of 0.01D was arbitrarily chosen - - # Initialize and assemble array/list of p-y curves at each real node - z = np.zeros(N) - py_funs = []; PileShaft =[] - k_secant = np.zeros(N) - DQ = [] - - for i in [0, 1]: # Top two imaginary nodes - z[i] = (i - 2)*h - py_funs.append(0) - k_secant[i] = 0.0 - - for i in range(2, n+3): # Real nodes - z[i] = (i - 2)*h - if soil_type == 'clay': - z0, f_Su, f_sigma_v_eff, f_gamma, f_alpha = clay_profile(profile) - if z[i] < z0: - # No p-y curve above mudline - py_funs.append(lambda y_val: np.zeros_like(y_val)) - k_secant[i] = 0.0 - PileShaft.append(0.0) - else: - Su = f_Su(z[i]) - sigma_v_eff = f_sigma_v_eff(z[i]) - gamma = f_gamma(z[i]) - alpha = f_alpha(z[i]) - py_funs.append(py_Matlock(z[i], D, zlug, f_Su, f_sigma_v_eff, f_gamma, z0=z0, plot=plot)) - Vo = np.pi*D*alpha*Su*z[i]**2 - PileShaft.append(Vo) - k_val = py_funs[i](y[i]) - k_secant[i] = k_val/y[i] if y[i] != 0 else 0.0 - - elif soil_type == 'sand': - z0, f_phi, f_sigma_v_eff, f_gamma, f_Dr, f_delta = sand_profile(profile) - if z[i] < z0: - # No p-y curve above mudline - py_funs.append(lambda y_val: np.zeros_like(y_val)) - k_secant[i] = 0.0 - PileShaft.append(0.0) - else: - phi = f_phi(z[i]) - sigma_v_eff = f_sigma_v_eff(z[i]) - gamma = f_gamma(z[i]) - delta = f_delta(z[i]) - py_funs.append(py_API(z[i], D, zlug, f_phi, f_sigma_v_eff, f_Dr, z0=z0, plot=plot)) - fs = delta * sigma_v_eff - Vo = np.pi*D*fs*z[i] - PileShaft.append(Vo) - k_val = py_funs[i](y[i]) - k_secant[i] = k_val/y[i] if y[i] != 0 else 0.0 - - elif soil_type in ['rock', 'weak_rock']: - z0, f_UCS, f_Em = rock_profile(profile) - if z[i] < z0: - # No p-y curve above mudline - py_funs.append(lambda y_val: np.zeros_like(y_val)) - k_secant[i] = 0.0 - DQ.append(0.0) - else: - UCS = f_UCS(z[i]) - Em = f_Em(z[i]) - py_funs.append(py_Reese(z[i], D, zlug, f_UCS, f_Em, z0=z0, plot=plot)) - SCR = nhuc*Em/(UCS*(1 + nhu))*delta_r/D - alpha = 0.36*SCR - 0.0005 - fs = alpha*UCS - Dq = np.pi*D*fs*z[i] - DQ.append(Dq) - k_val = py_funs[i](y[i]) - k_secant[i] = k_val/y[i] if y[i] != 0 else 0.0 - - for i in [n+3, n+4]: # Bottom two imaginary nodes - z[i] = (i - 2)*h - py_funs.append(0) - k_secant[i] = 0.0 - - # Compute individual contributions to total vertical load - Wp = PileWeight(L, D, t, rhows) # Pile self-weight (wet) - Wsoil = SoilWeight(L, D, t, gamma) if soil_type in ['clay', 'sand'] else 0.0 # Soil plug only in soil profiles - Wshaft = PileShaft[-1] if soil_type in ['clay', 'sand'] else 0.0 # Shaft resistance for soils - Wtip = DQ[-1] if soil_type in ['rock', 'weak_rock'] else 0.0 # Tip resistance for rock - - # Compute total vertical capacity - Vmax = Wp + Wsoil + Wshaft + Wtip - - for j in range(iterations): - y, Mi, Mp, hinge_formed, hinge_location = fd_solver(n, N, h, D, t, fy, EI, Ha, Va, zlug, z0, k_secant) - for i in range(2, n+3): - if callable(py_funs[i]): - k_secant[i] = py_funs[i](y[i])/y[i] - - if plot: - y1 = np.linspace(-2.*D, 2.*D, 500) - plt.plot(y1, py_funs[loc](y1)) - plt.xlabel('y (m)'), plt.ylabel('p (N/m)') - plt.grid(True) - - fig, ax = plt.subplots(figsize=(3, 5)) - y0 = np.zeros_like(z[2:-2]) - # Plot original vertical pile - ax.plot(y0, z[2:-2], 'k', label='Original pile axis') - # Plot deflected shape - ax.plot(y[2:-2], z[2:-2], 'r', label='Deflected shape') - # Padeye marker - ax.plot(0, zlug, 'ko', label=f'Padeye (zlug = {zlug:.2f} m)') - # Mudline marker - ax.axhline(z0, color='blue', linestyle='--', label=f'Mudline (z0 = {z0:.2f} m)') - - ax.set_xlabel('Lateral displacement (m)') - ax.set_ylabel('Depth (m)') - ax.set_xlim([-0.1*D, 0.1*D]) - ax.set_ylim([L + 5, -2]) # Downward is positive z - ax.grid(ls='--') - ax.legend() - - # Relevant index of nodes - zlug_index = int(zlug/h); print(zlug_index) - ymax_index = int(np.max(y)); print(ymax_index) - - resultsDriven = { - 'Weight pile': PileWeight(L, D, t, rhows + rhow), - 'Vertical max.': Vmax, - 'Horizontal max.': abs(Mi)/abs(zlug) if zlug != 0 else 1e-6, - 'Unity check (vertical)': Va/Vmax if Vmax != 0 else np.inf, - 'Unity check (horizontal)': Ha/(abs(Mi)/abs(zlug)) if zlug != 0 else np.inf, - 'Lateral displacement': y[ymax_index], - 'Rotational displacement': np.rad2deg(abs(y[ymax_index - 1] - y[ymax_index])/h), - 'Bending moment': abs(Mi), - 'Plastic moment': Mp, - 'Plastic hinge': hinge_formed, - 'Hinge location': hinge_location, - 'p-y model': 'Matlock (1970)' if soil_type == 'clay' else 'API RP2A (1993)' if soil_type == 'sand' else 'Reese (1997)', - } - - - return y[2:-2], z[2:-2], resultsDriven - -def fd_solver(n, N, h, D, t, fy, EI, Ha, Va, zlug, z0, k_secant): - '''Solves the finite difference equations from 'py_analysis_1'. This function should be run iteratively for - non-linear p-y curves by updating 'k_secant' using 'y'. A single iteration is sufficient if the p-y curves - are linear. - - Parameters - ---------- - n : int - Number of elements - N : int - Total number of nodes (real + imaginary) - h : float - Element size (m) - D : float - Pile diameter (m) - t : float - Pile wall thickness (m) - fy : float - Yield strength of pile material (Pa) - EI : float - Flexural rigidity of the pile (Nm²) - Ha : float - Horizontal load at pile lug elevation (N) - Va : float - Vertical load at pile lug elevation (N) - zlug : float - Depth of padeye from pile head (m) - z0 : float - Mudline depth from pile head (m) - k_secant : array - Secant stiffness from p-y curves at each node - - Returns - ------- - y : array - Lateral displacement at each node - Mi : float - Maximum internal bending moment (Nm) - Mp : float - Plastic moment capacity of the pile (Nm) - hinge_formed : bool - Whether plastic hinge is formed - hinge_location : int - Index of the node with hinge formation - ''' - - # Initialize and assemble matrix - X = np.zeros((N, N)) - - # (n+1) finite difference equations for (n+1) real nodes - for i in range(0, n+1): - X[i, i] = 1.0 - X[i, i+1] = -4.0 + Va*h**2/EI - X[i, i+2] = 6.0 - 2*Va*h**2/EI + k_secant[i+2]*h**4/EI - X[i, i+3] = -4.0 + Va*h**2/EI - X[i, i+4] = 1.0 - - # Curvature at pile head - X[n+1, 1] = 1.0 - X[n+1, 2] = -2.0 - X[n+1, 3] = 1.0 - - # Shear at pile head - X[n+2, 0] = -1.0 - X[n+2, 1] = 2.0 - Va*h**2/EI - X[n+2, 2] = 0.0 - X[n+2, 3] = -2.0 + Va*h**2/EI - X[n+2, 4] = 1.0 - - # Curvature at pile tip - X[n+3, -2] = 1.0 - X[n+3, -3] = -2.0 - X[n+3, -4] = 1.0 - - # Shear at pile tip - X[n+4, -1] = 1.0 - X[n+4, -2] = -2.0 + Va*h**2/EI - X[n+4, -3] = 0.0 - X[n+4, -4] = 2.0 - Va*h**2/EI - X[n+4, -5] = -1.0 - - # Initialize vector q - q = np.zeros(N) - - # Always apply shear - # Index of the node where the horizontal load is applied (padeye) - zlug_index = int(zlug/h) - q[zlug_index] = 2*Ha*h**3 - - y = linalg.solve(EI*X, q) - - # Compute the plastic moment capacity Mp - Zp = (1/6)*(D**3 - (D - 2*t)**3) # Plastic section modulus for hollow pile (m3) - Mp = Zp*fy # Plastic moment capacity (N/m) - - # Check for plastic hinge formation - Mi, Mp, hinge_formed, hinge_location = plastic_hinge(y, h, EI, Mp) - - return y, Mi, Mp, hinge_formed, hinge_location - -def plastic_hinge(y, h, EI, Mp): - '''Check for plastic hinge formation along the pile. - - Parameters - ---------- - y : array - Lateral displacements at each node - h : float - Element size (m) - EI : float - Flexural rigidity of the pile (Nm²) - Mp : float - Plastic moment capacity (Nm) - - Returns - ------- - Mi_max : float - Maximum internal moment along the pile (Nm) - Mp : float - Plastic moment capacity (Nm) - hinge_formed : bool - True if plastic hinge is formed - hinge_location : int - Node index where hinge forms (if any) - ''' - - hinge_formed = False - hinge_location = -1 - Mi_all = [] - - # Loop through each internal node and compute the bending moment - for i in range(1, len(y) - 1): - Mi = EI * (y[i+1] - 2*y[i] + y[i-1])/h**2 - Mi_all.append(Mi) - - if abs(Mi) >= Mp and not hinge_formed: - hinge_formed = True - hinge_location = i - - Mi_max = max(Mi_all, key=abs) if Mi_all else 0.0 - - return Mi_max, Mp, hinge_formed, hinge_location - -if __name__ == '__main__': - - profile_clay = np.array([ - [ 1.0, 600, 8], - [ 6.0, 200, 8], - [15.0, 400, 8], - [30.0, 600, 9] - ]) - - profile_sand = np.array([ - [ 2.0, 28, 8, 75], - [10.0, 34, 9, 75], - [15.0, 36, 10, 75], - [40.0, 45, 9, 85] - ]) - - profile_rock = np.array([ - [ 2.0, 0.5, 1e3], - [ 5.0, 2.0, 2e4], - [30.0, 1.0, 5e4] - ]) - - D = 2.5 # Diameter (m) - L = 25.0 # Length (m) - zlug = 1 # Padeye depth (m) - - # === CLAY === - y_clay, z_clay, resultsDriven_clay = getCapacityDriven(profile_clay, 'clay', L, D, zlug, Ha=5.0e6, Va=1.5e5, plot=True) - for key, val in resultsDriven_clay.items(): - if isinstance(val, float): - print(f"{key}: {val:.3f}") - else: - print(f"{key}: {val}") - - plot_pile(profile_clay, 'clay', y_clay, z_clay, D, L, profile_clay[0, 0], zlug, resultsDriven_clay.get('Hinge location')) - - # # === SAND === - # y_sand, z_sand, resultsDriven_sand = getCapacityDriven(profile_sand, 'sand', L, D, zlug, Ha=2.5e6, Va=2.0e6, plot=True) - # for key, val in resultsDriven_sand.items(): - # if isinstance(val, float): - # print(f"{key}: {val:.3f}") - # else: - # print(f"{key}: {val}") - - # plot_pile(profile_sand, 'sand', y_sand, z_sand, D, L, profile_sand[0, 0], zlug, resultsDriven_sand.get('Hinge location')) - - # # === ROCK === - # y_rock, z_rock, resultsDriven_rock = getCapacityDriven(profile_rock, 'rock', L, D, zlug, Ha=3.5e6, Va=3.0e6, plot=True) - # for key, val in resultsDriven_rock.items(): - # if isinstance(val, float): - # print(f"{key}: {val:.3f}") - # else: - # print(f"{key}: {val}") - - # plot_pile(profile_rock, 'rock', y_rock, z_rock, D, L, profile_rock[0, 0], zlug, resultsDriven_rock.get('Hinge location')) - - - diff --git a/famodel/anchors/anchors_famodel_profile/capacity_helical.py b/famodel/anchors/anchors_famodel_profile/capacity_helical.py deleted file mode 100644 index d425aea8..00000000 --- a/famodel/anchors/anchors_famodel_profile/capacity_helical.py +++ /dev/null @@ -1,152 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from .capacity_driven import getCapacityDriven, plot_pile -from .capacity_soils import clay_profile, sand_profile -from .capacity_plots import plot_helical - -def getCapacityHelical(profile, soil_type, D, L, d, zlug, Ha, Va, plot=True): - '''Calculate the vertical and horizontal capacity of a helical pile using a soil profile. - The calculation is based on the soil profile, anchor geometry and inclined load. - - Parameters - ---------- - profile : array - Soil profiles (z, parameters) - Clay: (z (m), Su (kPa), gamma (kN/m³)) - Sand: (z (m), phi (deg), gamma (kN/m³), Dr (%)) - soil_type : string - Select soil condition, 'clay' or 'sand' - D : float - Helix diameter (m) - L : float - Shaft length (m) - d : float - Shaft diameter (m) - zlug : float - Depth to padeye (m) - Ha : float - Horizontal load at pile lug elevation (N) - Va : float - Vertical load at pile lug elevation (N) - plot : bool - Plot the p-y curve and the deflection pile condition if True - - Returns - ------- - Dictionary with capacity, displacements, weight and UC. - ''' - - t = (6.35 + D*20)/1e3 # Helical pile wall thickness (m), API RP2A-WSD - rhows = 66.90e3 # Submerged steel specific weight (kN/m3) - rhow = 10e3 # Water specific weight (kN/m3) - - def PileWeight(Len, Dia1, Dia2, tw, rho): - return ((np.pi/4)*((Dia1**2 - (Dia1 - 2*tw)**2)*Len + (np.pi/4)*Dia2**2*tw))*rho - - if soil_type == 'clay': - z0, f_Su, f_sigma_v_eff, f_gamma, f_alpha = clay_profile(profile) - - z_helix = np.clip(zlug + (L - D), profile[0, 0], profile[-1, 0]) - Su = f_Su(z_helix) - sigma_v_eff = max(f_sigma_v_eff(z_helix), 1.0) - psi_val = Su/sigma_v_eff - alpha = min(0.5*psi_val**-0.50, 1) if psi_val <= 1.0 else min(0.5 * psi_val**-0.25, 1) - - Nc = min(6.0*(1 + 0.2*d/D), 9) - Qh = ((np.pi/4)*(D**2 - d**2)*Nc*Su + f_gamma(z_helix)*D)*0.75 - Qs = np.pi*d*L*alpha*Su - Qu = PileWeight(L, D, d, t, rhows) + Qh + Qs - - elif soil_type == 'sand': - z0, f_phi, f_sigma_v_eff, f_gamma, f_Dr, f_delta = sand_profile(profile) - - z_helix = np.clip(zlug + (L - D), profile[0, 0], profile[-1, 0]) - gamma = f_gamma(z_helix) - Dr = f_Dr(z_helix) - delta = f_delta(z_helix) - phi = f_phi(z_helix) - - Nq = 0.5*(12*phi)**(phi/54) - Qh = (np.pi/4)*(D**2 - d**2)*Nq*gamma*z_helix - Qs = np.pi*d*L*delta*gamma*z_helix - Qu = PileWeight(L, D, d, t, rhows) + Qh + Qs - - # Pile weight (inc. auxilary items) assessed as a factor - Wp = 1.10*PileWeight(L, D, d, t, (rhows + rhow)) - - # Unity Check based only on vertical capacity - UC_vertical = Va/Qu - - # Compute horizontal capacity using p-y method - y, z, results_lateral = getCapacityDriven(profile, soil_type, L, d, zlug, Ha, Va, plot=True) - if soil_type == 'clay': - plot_pile(profile_clay, 'clay', y, z, D, L, z0, zlug, hinge_location=None) - elif soil_type == 'sand': - plot_pile(profile_sand, 'sand', y, z, D, L, z0, zlug, hinge_location=None) - - Hcap = Ha if 'Plastic moment' not in results_lateral else results_lateral['Bending moment']/abs(zlug) if zlug != 0 else 1e-6 - UC_horizontal = Ha/Hcap if Hcap != 0 else np.inf - - resultsHelical = { - 'Weight pile': Wp, - 'Vertical max.': Qu, - 'Horizontal max.': Hcap, - 'Unity check (vertical)': UC_vertical, - 'Unity check (horizontal)': UC_horizontal, - 'Lateral displacement': results_lateral.get('Lateral displacement', None), - 'Rotational displacement': results_lateral.get('Rotational displacement', None), - 'Bending moment': results_lateral.get('Bending moment', None), - 'Plastic moment': results_lateral.get('Plastic moment', None), - 'Plastic hinge': results_lateral.get('Plastic hinge', None), - 'Hinge location': results_lateral.get('Hinge location', None), - 'p-y model': results_lateral.get('p-y model', None), - } - - return resultsHelical - -if __name__ == '__main__': - - profile_clay = np.array([ - [ 1.0, 10, 8.0], - [ 5.0, 15, 8.5], - [10.0, 25, 8.5], - [25.0, 50, 9.0] - ]) - - profile_sand = np.array([ - [ 1.0, 28, 9.5, 40, 60], - [ 5.0, 34, 10.0, 42, 70], - [ 8.0, 38, 10.0, 44, 75], - [15.0, 38, 11.5, 45, 85] - ]) - - D = 1.8 # Helix diameter (m) - L = 12.0 # Pile length (m) - d = 0.8 # Shaft diameter (m) - zlug = 2 # Padeye depth (m) - Va = 50e3 # Vertical load (N) - Ha = 30e3 # Horizontal load (N) - - # === CLAY === - # resultsHelical_clay = getCapacityHelical(profile_clay, 'clay', D, L, d, zlug, Ha, Va, plot=True) - # for key, val in resultsHelical_clay.items(): - # if isinstance(val, float): - # print(f"{key}: {val:.3f}") - # else: - # print(f"{key}: {val}") - - # plot_helical(profile_clay, 'clay', D, L, d, zlug, n_helix=1, spacing=1.0, title='Helical Pile in Clay Profile') - - # === SAND === - resultsHelical_sand = getCapacityHelical(profile_sand, 'sand', D, L, d, zlug, Ha, Va, plot=True) - for key, val in resultsHelical_sand.items(): - if isinstance(val, float): - print(f"{key}: {val:.3f}") - else: - print(f"{key}: {val}") - - plot_helical(profile_sand, 'sand', D, L, d, zlug, n_helix=1, spacing=1.0, title='Helical Pile in Sand Profile') - - - diff --git a/famodel/anchors/anchors_famodel_profile/capacity_load.py b/famodel/anchors/anchors_famodel_profile/capacity_load.py deleted file mode 100644 index 7c75ed1e..00000000 --- a/famodel/anchors/anchors_famodel_profile/capacity_load.py +++ /dev/null @@ -1,189 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from .capacity_soils import clay_profile, sand_profile -from .capacity_plots import plot_load - -def getTransferLoad(profile, soil_type, Tm, thetam, zlug, line_type, d, w=None, plot=True): - '''Calculate the transfer load from mudline to main padeye using a layered soil profile. - - Parameters - ---------- - profile : array - Soil profile as a 2D array: (z, parameters) - Clay soil profile (z (m), Su (kPa), gamma (kN/m³)) - Sand soil profile (z (m), phi (deg), gamma (kN/m³), Dr (%)) - soil_type : string - Select soil condition, 'clay' or 'sand' - Tm : float - Mooring line load at mudlevel (N) - thetam : float - Mooring line angle at mudlevel (deg) - zlug : float - Embedment depth of the lug (m) - line_type : string - Select mooring line type, 'chain' or 'wire' - d : float - Mooring line diameter (m) - w : float - Mooring line unit weight (N/m) - plot : bool - Plot the inverse catenary mooring line profile if True - - Returns - ------- - dict - Dictionary with transferred load components and depth. - ''' - - deltas = 0.2 # discretization step - - profile = np.array(profile) - - # Line mechanical properties - if line_type == 'chain': - Et, En = 10, 2.5 - elif line_type == 'wire': - Et, En = np.pi, 1 - W = w*deltas - - # Soil profile and interpolators - if soil_type == 'clay': - Nc = 8.5 - z0, f_Su, _, f_gamma, f_alpha = clay_profile(profile) - elif soil_type == 'sand': - nhu = 0.5 - z0, f_phi, _, f_gamma, _, f_delta = sand_profile(profile) - - # Initial values - T = Tm - theta = np.deg2rad(thetam) - drag = 0 - depth = z0 + 0.1 - - # Tracing lists - drag_values, depth_values = [], [] - - while (zlug - depth) >= 0: - if soil_type == 'clay': - Su = f_Su(depth) - alpha = f_alpha(depth) - dtheta = (En*d*Nc*Su - W*np.cos(theta))/T*deltas - dT = (Et*d*alpha*Su + W*np.sin(theta))*deltas - elif soil_type == 'sand': - gamma_z = f_gamma(depth) - delta_z = f_delta(depth) - phi = f_phi(depth) - Nq = np.exp(np.pi*np.tan(np.deg2rad(phi)))*(np.tan(np.deg2rad(45 + phi/2)))**2 - print(f'Nq = {Nq:.2f}, depth = {depth:.2f} m') - dtheta = (En*d*Nq*gamma_z*depth - W*np.cos(theta))/T*deltas - dT = (Et*d*gamma_z*depth*np.tan(np.deg2rad(delta_z)) + W*np.sin(theta))*deltas - - ddrag = deltas*np.cos(theta) - ddepth = deltas*np.sin(theta) - - theta += dtheta - T -= dT - drag += ddrag - depth += ddepth - - if abs(Tm - T) > 0.75*Tm: - raise Exception(f"Load transfer unrealistic: Tm = {Tm/1e6:.2f} MN vs T = {T/1e6:.2f} MN") - - if not (0 < np.rad2deg(theta) < 90): - raise Exception(f"Load angle unrealistic: {np.rad2deg(theta):.2f} deg") - - drag_values.append(-drag) - depth_values.append(-depth) - - Ta = T; thetaa = theta - # H = Ta*np.cos(thetaa) - # V = Ta*np.sin(thetaa) - - if plot: - plot_load( - profile, soil_type, - drag_values, depth_values, - Tm, thetam, - Ta, thetaa, - zlug - ) - - resultsLoads = { - 'Tm': Tm, - 'thetam': thetam, - 'Ta': Ta, - 'thetaa': thetaa, - 'length': deltas*len(drag_values), - 'drag_values': drag_values, - 'depth_values': depth_values - } - - return resultsLoads - -if __name__ == '__main__': - - # Define a clay profile: [depth (m), Su (kPa), gamma (kN/m3)] - # profile_clay = np.array([ - # [ 0.0, 0, 0.0], - # [ 2.0, 25, 8.0], - # [ 8.0, 50, 8.0], - # [16.0, 100, 8.0] - # ]) - - # Define a sand profile: [depth (m), phi (deg), gamma (kN/m3), Dr (%)] - profile_sand = np.array([ - [ 0.0, 30, 9.5, 70], - [ 5.0, 30, 9.5, 70], - [10.0, 30, 9.5, 70], - [15.0, 30, 9.5, 70] - ]) - - # # Input parameters - # Tm = 1.2e7 # Load at mudline (N) - # thetam = 10 # Angle at mudline (deg) - # zlug = 8.3 # Padeye depth (m) - # line_type = 'chain' - # d = 0.16 # Chain diameter (m) - # w = 4093 # Line weight (N/m) - - # # Run transfer load calculation - # results = getTransferLoad(profile_clay, soil_type, Tm, thetam, zlug, line_type, d, w, plot=True) - # print("\n--- Transfer Load Results (Clay) ---") - # for key, val in results.items(): - # if isinstance(val, float): - # print(f"{key}: {val:.3f}") - # elif isinstance(val, list): - # print(f"{key}:") - # for v in val: - # print(f" {v:.3f}") - # else: - # print(f"{key}: {val}") - - # plot_load(profile_clay, soil_type, results['drag_values'], results['depth_values'], results['Tm'], results['thetam'], results['Ta'], results['thetaa'], zlug) - - - # Input parameters - Tm = 8.2e6 - thetam = 10 - zlug = 8 - line_type = 'chain' - d = 0.25 - soil_type = 'sand' - w = 4093 - - results = getTransferLoad(profile_sand, soil_type, Tm, thetam, zlug, line_type, d, w, plot=True) - - # print("\n--- Transfer Load Results (Sand) ---") - # for key, val in results.items(): - # if isinstance(val, float): - # print(f"{key}: {val:.3f}") - # elif isinstance(val, list): - # print(f"{key}:") - # for v in val: - # print(f" {v:.3f}") - # else: - # print(f"{key}: {val}") - - plot_load(profile_sand, soil_type, results['drag_values'], results['depth_values'], results['Tm'], results['thetam'], results['Ta'], results['thetaa'], zlug) - diff --git a/famodel/anchors/anchors_famodel_profile/capacity_plate.py b/famodel/anchors/anchors_famodel_profile/capacity_plate.py deleted file mode 100644 index cb718fa2..00000000 --- a/famodel/anchors/anchors_famodel_profile/capacity_plate.py +++ /dev/null @@ -1,143 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from .capacity_soils import clay_profile -from .capacity_plots import plot_plate - -def getCapacityPlate(profile, soil_type, B, L, zlug, beta, Ha, Va, plot=True): - '''Calculate the plate anchor capacity using a full clay soil profile and return capacity + UC. - The calculation is based on the soil profile, anchor geometry and inclined load. - - Parameters - ---------- - profile : ndarray - Clay soil profile as a 2D array: [[depth, Su, gamma], ...] - soil_type : str - Currently only 'clay' is supported. - B : float - Plate width (m) - L : float - Plate length (m) - zlug : float - Embedment depth of the main padeye (m) - beta : float - Inclination angle of the plate (deg) - Ha : float - Applied horizontal load (kN) - Va : float - Applied vertical load (kN) - plot : bool - Placeholder for future use. - - Returns - ------- - Dictionary with capacity, weight and UC. - ''' - - Los = 0.05 - B_t = 40 - rhows = 66.90e3 # Submerged steel specific weight (kN/m3) - rhow = 10e3 # Water specific weight (kN/m3) - - # Extract soil parameters from profile - z0, f_Su, _, f_gamma, _ = clay_profile(profile) - - # Geometry - t = round(B/B_t, 2) - V_steel = round(B*L*t, 2) - zlug_B = zlug/B - - # Define 5 evaluation points along inclined width - N = 5 - z_offsets = np.linspace(-0.5, 0.5, N)*B*np.sin(np.deg2rad(beta)) - z_points = zlug + z_offsets; print(z_points) - - # Evaluate Su and gamma at these points - Su_vals = [f_Su(z) for z in z_points] - gamma_10 = f_gamma(z_points[2]); print(gamma_10) - gamma_vals = [f_gamma(z) for z in z_points]; print("gamma_vals:", [f"{val:.2f}" for val in gamma_vals], "N/m3") - Su = np.mean(Su_vals); print(f"Su: {Su:.2f} Pa") - gamma = np.mean(gamma_vals); print(f"gamma: {gamma:.2f} N/m3") - - print("Profile being sent to clay_profile():") - for row in profile: - print(f"z = {row[0]:.2f} m, Su = {row[1]:.2f} kPa, gamma = {row[2]:.2f} kN/m³") - - # Compute shear strength gradient k from linear fit - k = np.polyfit(z_points, Su_vals, 1)[0] - print(f"k: {k:.2f}") - - # Pile weight (inc. auxiliary elements) assessed as a factor - Wp = 1.35*V_steel*(rhows + rhow) - - # Capacity factors - Nco_0_0 = 2.483*np.log(zlug_B) + 1.974 - Nco_90_0 = 2.174*np.log(zlug_B) + 3.391 - kBSh = k*B/Su - print(f"kBSh: {kBSh:.2f}") - - f0 = np.where(zlug_B < 4, 1.77*(zlug_B**0.3) - 1.289, 0.192*zlug_B + 0.644) - f90 = np.where(zlug_B < 4, 0.68*(zlug_B**0.5) - 0.410, 0.153*zlug_B + 0.341) - - S_kB_0 = 1 - f0*kBSh - S_kB_90 = 1 - f90*kBSh - Nco_0 = S_kB_0*Nco_0_0 - Nco_90 = S_kB_90*Nco_90_0 - Nco = Nco_0 + (Nco_90 - Nco_0)*(beta/90)**2 - - Nco_s_0_0 = np.where(2.90*zlug_B + 6.02 <= 11.59, 2.90*zlug_B + 6.02, 11.596) - Nco_s_90_0 = np.where(2.72*zlug_B + 4.02 <= 11.59, 2.72*zlug_B + 4.02, 11.596) - - S_s_kB_0 = np.where(zlug_B <= 2, 1 + (0.8 - 0.3*zlug_B)*kBSh - (0.383*kBSh**1.36), 1) - f90s = np.where(zlug_B <= 3, 0.267*zlug_B, 0.6) - S_s_kB_90 = 1 - f90s*kBSh - Nco_s_0 = S_s_kB_0*Nco_s_0_0 - Nco_s_90 = S_s_kB_90*Nco_s_90_0 - Nco_s = Nco_s_90 + (Nco_s_0 - Nco_s_90)*((90 - beta)/90)**2 - - # Existing capacity factor and base pressure - Nc_final = max(Nco + (gamma*zlug)/Su, Nco_s) # anchor pullout capacity factor [kN] - print(f"Nc_star: {Nco + (gamma*zlug)/Su:.2f}") - print(f"Nc_star: {Nco_s:.2f}") - qu = Nc_final*Su # Bearing pressure capacity of the anchor plate - Tmax = round(qu*(1 - Los)*B*L, 2) # Bearing tension force capacity of the anchor plate - Hmax = Tmax*np.cos(np.deg2rad(90 - beta)) - Vmax = Tmax*np.sin(np.deg2rad(90 - beta)) - - Ta = np.sqrt(Ha**2 + Va**2) - UC = Ta/Tmax - - resultsPlate = { - 'Capacity': Tmax, - 'Horizontal max.': Hmax, - 'Vertical max.': Vmax, - 'Unity check': UC, - 'Weight plate': Wp - } - - return resultsPlate - -if __name__ == '__main__': - - profile_clay = np.array([ - [ 0.0, 10, 8.0], - [ 9.5, 25, 8.5], - [11.5, 45, 8.5], - [25.0, 50, 9.0] - ]) - - B = 2.0 # Plate width (m) - L = 2.0 # Plate length (m) - zlug = 10.0 # Padeye depth (m) - Ha = 350e3 # Horizontal load (N) - Va = 400e3 # Vertical load (N) - alpha = np.rad2deg(np.arctan2(Va, Ha)) # Load angle from horizontal (deg) - beta = 90 - alpha # Plate angle after keying (m) - - results = getCapacityPlate(profile_clay, 'clay', B, L, zlug, beta, Ha, Va) - print("\n--- Plate Anchor Capacity Results ---") - for key, val in results.items(): - print(f"{key}: {val:.2f}") - - # plot_plate(profile_clay, 'clay', B, L, zlug, beta, title='Inclined Plate Anchor in Clay') - diff --git a/famodel/anchors/anchors_famodel_profile/capacity_plots.py b/famodel/anchors/anchors_famodel_profile/capacity_plots.py deleted file mode 100644 index fb096f3e..00000000 --- a/famodel/anchors/anchors_famodel_profile/capacity_plots.py +++ /dev/null @@ -1,435 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt - -def plot_pile(profile, soil_type, y, z, D, L, z0=None, zlug=None, hinge_location=None): - '''Plots the deflected shape of the pile alongside the original vertical line. - - Parameters: - ---------- - profile : - - soil_type : str - - y : np.array - Lateral displacements (m) - z : np.array - Depths from pile head (m) - D : float - Pile diameter (m) - L : float - Pile length (m) - z0 : float, optional - Depth of the mudline from the pile head (m) - zlug : float, optional - Depth of the padeye from the pile head (m) - hinge_location : int, optional - Node index where a plastic hinge formed (if any) - label : str - Label for deflected shape line - color : str - Line color for deflected shape - ''' - fig, ax = plt.subplots(figsize=(3, 5)) - - lambdap = L / D - - # Adjust horizontal scale based on slenderness - if lambdap >= 4: - xmax = 5*D # Slender (e.g., driven pile) - elif lambdap <= 2: - xmax = 2*D # Stubby (e.g., drilled & grouted) - else: - xmax = 3*D # Intermediate case - - # Mudline marker - if z0 is not None: - ax.axhline(z0, color='blue', linestyle='--', label=f'Mudline (z0 = {z0:.2f} m)') - #ax.fill_betweenx(z, -0.05 * D, 0.05 * D, where=(z >= z0), color='lightgray', alpha=0.3, label='Soil zone') - - # Padeye marker (on right wall of pile) - if zlug is not None: - ax.plot(D/2, zlug, 'ko', label=f'Padeye (zlug = {zlug:.2f} m)') - - # Draw pile as rectangle (from head to tip) - pile = plt.Rectangle((-D/2, 0), D, L, edgecolor='k', facecolor='none', lw=2, label='Driven Pile') - ax.add_patch(pile) - - seen_labels = set() - # Plot soil layers as background fills - for i in range(len(profile) - 1): - z_top = profile[i][0] - z_bot = profile[i+1][0] - if soil_type == 'clay': - Su = profile[i][1] - color = plt.cm.Oranges(Su/np.max(profile[:, 1])) - label = f'Su = {Su:.0f} kPa' - elif soil_type == 'sand': - phi = profile[i][1] - gamma = profile[i][2] - color = plt.cm.YlOrBr(phi/np.max(profile[:, 1])) - label = f'ϕ = {phi:.0f}°, γ = {gamma:.1f} kN/m³' - elif soil_type == 'rock': - UCS = profile[i][1] - Em = profile[i][2] - color = plt.cm.Greys(UCS/np.max(profile[:, 1])) - label = f'UCS = {UCS:.2f} MPa, Em = {Em:.1f} MPa' - - # Only assign label if not already used - if label not in seen_labels: - ax.axhspan(z_bot, z_top, color=color, alpha=0.4, label=label) - seen_labels.add(label) - else: - ax.axhspan(z_bot, z_top, color=color, alpha=0.4) - - ax.set_xlabel('Lateral displacement (m)') - ax.set_ylabel('Depth (m)') - ax.set_xlim(-xmax, xmax) - ax.set_ylim([L + 5, -2]) # Downward is positive z - ax.grid(ls='--') - ax.legend() - ax.set_title('Pile Deflection Profile') - plt.tight_layout() - plt.show() - - -def plot_suction(profile, soil_type, L, D, zlug=None, title='Suction Pile and Soil Layers', ax=None): - '''Plot the soil profile and a suction pile geometry using array structure for profile. - - Parameters: - ---------- - profile : list or ndarray of lists (z, Su or phi or UCS, gamma) - soil_type : str - 'clay', 'sand', or 'rock' - L : float - Embedded length (m) - D : float - Pile diameter (m) - zlug : float - Padeye depth (m, referenced to pile head = 0) - title : string - Plot title - ''' - import numpy as np - import matplotlib.pyplot as plt - - profile = np.array(profile) - if ax is None: - fig, ax = plt.subplots(figsize=(5, 5)) - xmax = 2*D - - # Split numerical values from profile - z_vals = [float(row[0]) for row in profile] - values = [float(row[1]) for row in profile] - - seen_labels = set() - # Plot soil layers as background fills - for i in range(len(z_vals) - 1): - z_top = z_vals[i] - z_bot = z_vals[i+1] - val = values[i] - - if soil_type == 'clay': - color = plt.cm.Oranges(val / max(values)) - label = f'Su = {val:.0f} kPa' - elif soil_type == 'sand': - color = plt.cm.YlOrBr(val / max(values)) - label = f'ϕ = {val:.0f}°' - - if label not in seen_labels: - ax.axhspan(z_bot, z_top, color=color, alpha=0.4, label=label) - seen_labels.add(label) - else: - ax.axhspan(z_bot, z_top, color=color, alpha=0.4) - - # Draw pile geometry - x_left = -D/2; x_right = D/2 - z_top = 0; z_bot = L - ax.plot([x_left, x_left], [z_top, z_bot], color='k', lw=2.0, label='Suction Pile') - ax.plot([x_right, x_right], [z_top, z_bot], color='k', lw=2.0) - ax.plot([x_left, x_right], [z_top, z_top], color='k', lw=2.0) - - # Reference lines - ax.axhline(z_vals[0], color='k', linestyle='--', lw=1.5, label='Mudline') - ax.axhline(L, color='b', linestyle='--', lw=1.5, label='Pile Tip') - - # Padeye marker - if zlug is not None and 0 <= zlug <= L: - ax.plot(x_right, zlug, 'ko', label=f'Padeye (zlug = {zlug:.2f} m)') - - ax.set_xlabel('Horizontal extent (m)') - ax.set_ylabel('Depth (m)') - ax.set_xlim(-xmax, xmax) - ax.set_ylim(L + 2*D, -D) - ax.set_title(title) - ax.grid() - ax.legend() - plt.tight_layout() - plt.show() - - -def plot_torpedo(profile, soil_type, D1, D2, L1, L2, zlug, title='Torpedo Pile and Soil Layers'): - '''Plot the soil layers and geometry of a torpedo pile using absolute depth for soil and pile head at z=0. - - Parameters: - ---------- - profile : - list or array of (z, Su, 'clay') - soil_type : str - 'clay' - D1 : float - Wing diameter (at tip) (m) - D2 : float - Shaft diameter (at head) - L1 : float - Winged length (m) - L2 : float - Shaft length (m) - title : str - Plot title - ''' - fig, ax = plt.subplots(figsize=(7, 7)) - - xmax = 5*max(D1, D2) - z1 = zlug + L1 # interface between L1 and L2 - z_tip = z1 + L2 # pile tip - - # Split numerical values from profile - z_vals = [float(row[0]) for row in profile] - values = [float(row[1]) for row in profile] - - seen_labels = set() - # Plot soil layers as background fills - for i in range(len(z_vals) - 1): - z_top = z_vals[i] - z_bot = z_vals[i+1] - val = values[i] - - if soil_type == 'clay': - color = plt.cm.Oranges(val/max(values)) - label = f'Su = {val:.0f} kPa' - - # Only assign label if not already used - if label not in seen_labels: - ax.axhspan(z_bot, z_top, color=color, alpha=0.4, label=label) - seen_labels.add(label) - else: - ax.axhspan(z_bot, z_top, color=color, alpha=0.4) - - # Draw winged section (upper) - ax.add_patch(plt.Rectangle((-D1/2, zlug), D1, L1, edgecolor='k', facecolor='none', lw=2, label='Winged Section')) - - # Draw shaft section (lower) - ax.add_patch(plt.Rectangle((-D2/2, z1), D2, L2, edgecolor='k', facecolor='none', lw=2, label='Shaft Section')) - - # Reference lines - ax.axhline(z_vals[0], color='k', linestyle='--', lw=1.0, label='Mudline') - ax.axhline( z_tip, color='b', linestyle='--', lw=1.0, label='Pile Tip') - - # Padeye marker - if zlug is not None: - ax.plot(0, zlug, 'ko', label=f'Padeye (zlug = {zlug:.2f} m)') - - - ax.set_xlim(-xmax, xmax) - ax.set_ylim(max(z_vals) + 0.5*D1, min(zlug - 2*D1, z_vals[0] - 2)) - ax.set_xlabel('Horizontal extent (m)') - ax.set_ylabel('Depth (m)') - ax.set_title(title) - ax.grid() - ax.legend() - plt.tight_layout() - plt.show() - -def plot_helical(profile, soil_type, D, L, d, zlug, n_helix=1, spacing=1.0, title='Helical Pile and Soil Layers'): - '''Plot a helical pile in layered soil, with the pile starting at zlug and the helix near the pile tip. - - Parameters: - ---------- - profile : list or array of (z, Su or phi, ...) - soil_type : - 'clay' or 'sand' - D : float - Helix diameter (m) - L : float - Pile length (m) - d : float - Shaft diameter (m) - zlug : float - Embedment depth of pile head (m) - n_helix : int - Number of helices (-) - spacing : float - Vertical spacing between helices (m) - title : str - Plot title - ''' - fig, ax = plt.subplots(figsize=(5, 5)) - - xmax = 3*max(D, d) - - # Extract soil data - z_vals = [float(row[0]) for row in profile] - values = [float(row[1]) for row in profile] - - seen_labels = set() - # Plot soil layers as background fills - for i in range(len(z_vals) - 1): - z_top = z_vals[i] - z_bot = z_vals[i+1] - val = values[i] - - if soil_type == 'clay': - color = plt.cm.Oranges(val/max(values)) - label = f'Su = {val:.0f} kPa' - elif soil_type == 'sand': - color = plt.cm.YlOrBr(val / max(values)) - label = f'ϕ = {val:.0f}°' - - # Only assign label if not already used - if label not in seen_labels: - ax.axhspan(z_bot, z_top, color=color, alpha=0.4, label=label) - seen_labels.add(label) - else: - ax.axhspan(z_bot, z_top, color=color, alpha=0.4) - - # Draw shaft - ax.add_patch(plt.Rectangle((-d/2, 0), d, L, edgecolor='k', facecolor='none', lw=2, label='Shaft')) - - # Draw helices - z_helix_base = L - D # Base helix depth - for i in range(n_helix): - z_helix = z_helix_base - i*spacing - if z_helix < zlug: - break - ax.plot([-D/2, D/2], [z_helix - d/2, z_helix + d/2], color='k', lw=2, label='Helix' if i == 0 else None) - - # Reference lines - ax.axhline(z_vals[0], color='k', linestyle='--', lw=1.0, label='Mudline') - ax.axhline( L, color='b', linestyle='--', lw=1.0, label='Pile Tip') - - # Padeye marker - if zlug is not None: - ax.plot(d/2, zlug, 'ko', label=f'Padeye (zlug = {zlug:.2f} m)') - - ax.set_xlim(-xmax, xmax) - ax.set_ylim(max(z_vals), min(zlug - 0.5*d, z_vals[0] - 2)) - ax.set_xlabel('Horizontal extent (m)') - ax.set_ylabel('Depth (m)') - ax.set_title(title) - ax.grid() - ax.legend() - plt.tight_layout() - plt.show() - -def plot_plate(profile, B, L, zlug, beta, title='Plate Anchor in Clay Profile'): - '''Plot soil layers and an inclined plate anchor centered at zlug. - - Parameters: - ---------- - profile : ndarray of shape (n, 3), with (depth, Su, gamma) - B : float - Plate width (m) - L : float - Plate length (m) - zlug : float - Center embedment of the plate (m) - beta : float - Inclination angle of plate (deg) - title : str - Plot title - ''' - fig, ax = plt.subplots(figsize=(5, 5)) - - xmax = 3*B - - # Extract soil data - layer_depths = profile[:, 0] - layer_depths = np.append(layer_depths, [profile[0][-1]]) - - # Inclined plate geometry - dx = (B/2)*np.cos(np.deg2rad(beta)) - dz = (B/2)*np.sin(np.deg2rad(beta)) - plate_x = [-dx, dx] - plate_z = [zlug - dz, zlug + dz] - - seen_labels = set() - # Plot soil layers as background fills - for i in range(len(layer_depths) - 1): - z_top = layer_depths[i] - z_bot = layer_depths[i+1] - Su = profile[i][1] - color = plt.cm.Oranges(Su/np.max(profile[:, 1])) - label = f'Su = {Su:.0f} kPa' - - # Only assign label if not already used - if label not in seen_labels: - ax.axhspan(z_bot, z_top, color=color, alpha=0.4, label=label) - seen_labels.add(label) - else: - ax.axhspan(z_bot, z_top, color=color, alpha=0.4) - - # Plot inclined plate - ax.plot(plate_x, plate_z, color='k', lw=1.5, label='Plate') - - # Reference lines - ax.axhline(0, color='k', linestyle='--', lw=1.0, label='Mudline') - - # Padeye marker - if zlug is not None: - ax.plot(0, zlug, 'ko', label=f'Padeye (zlug = {zlug:.2f} m)') - - ax.set_xlim(-xmax, xmax) - ax.set_ylim(25, -1) - ax.set_xlabel("Horizontal extent (m)") - ax.set_ylabel("Depth (m)") - ax.set_title(title) - ax.legend(loc='lower right') - ax.grid(True) - plt.tight_layout() - plt.show() - -def plot_load(profile, soil_type, drag_values, depth_values, Tm, thetam, Ta, thetaa, zlug): - - fig, ax = plt.subplots(figsize=(12, 6)) - n = 2e6 - - # Plot the inverse catenary profile - ax.plot(drag_values, depth_values, color='b', label='Mooring line') - - # Add load vectors - ax.arrow(0, -profile[0][0], Tm*np.cos(np.deg2rad(thetam))/n, Tm*np.sin(np.deg2rad(thetam))/n, - head_width=0.25, head_length=0.5, color='r', label='Mudline Load') - ax.arrow(drag_values[-1], depth_values[-1], Ta*np.cos(thetaa)/n, Ta*np.sin(thetaa)/n, - head_width=0.25, head_length=0.5, color='g', label='Padeye Load') - - #ax.set_aspect('equal', adjustable='datalim') - - # Plot soil layers as background fills - for i in range(len(profile) - 1): - z_top = -profile[i][0] - z_bot = -profile[i+1][0] - if soil_type == 'clay': - Su = profile[i][1] - gamma = profile[i][2] - color = plt.cm.Oranges(Su/np.max(profile[:, 1])) - label = f'Su = {Su:.0f} kPa' - elif soil_type == 'sand': - phi = profile[i][1] - gamma = profile[i][2] - color = plt.cm.YlOrRd(phi/np.max(profile[:, 1])) - label = f'ϕ = {phi:.0f}°, γ = {gamma:.1f} kN/m³' - ax.axhspan(z_bot, z_top, color=color, alpha=0.4, label=label) - - # Deduplicate legend entries - handles, labels = ax.get_legend_handles_labels() - unique = dict(zip(labels, handles)) - ax.legend(unique.values(), unique.keys(), loc='lower left') - - ax.set_xlabel('Drag distance [m]') - ax.set_ylabel('Embedded depth [m]') - ax.set_title('Inverse Catenary in Layered Soil') - ax.grid(True) - - ax.annotate(f"{Tm/1e6:.2f} MN", (Tm*np.cos(np.deg2rad(thetam))/n, -profile[0][0] + Tm*np.sin(np.deg2rad(thetam))/n), color='r') - ax.annotate(f"{Ta/1e6:.2f} MN", (drag_values[-1] + Ta*np.cos(thetaa)/n, depth_values[-1] + Ta*np.sin(thetaa)/n), color='g') diff --git a/famodel/anchors/anchors_famodel_profile/capacity_pycurves.py b/famodel/anchors/anchors_famodel_profile/capacity_pycurves.py deleted file mode 100644 index 67eb67f8..00000000 --- a/famodel/anchors/anchors_famodel_profile/capacity_pycurves.py +++ /dev/null @@ -1,298 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from scipy.interpolate import interp1d - -def py_Matlock(z, D, zlug, f_Su, f_sigma_v_eff, f_gamma, z0=None, plot=True): - ''' Generate Matlock (1970) p–y curve at a given depth in clay. - - Parameters - ---------- - z : float - Depth relative to pile head (m) - D : float - Pile diameter (m) - zlug : float - Load eccentricity above or below mudline (m) - f_Su : function - Undrained shear strength (Pa) - f_sigma_v_eff : function - Effective vertical stress (Pa) - f_gamma : function - Effective unit weight (kN/m³) - z0 : float, optional - Mudline depth (m). If provided, disables resistance above this level - plot : bool - Plot the resulting p–y curve if True - - Returns - ------- - f : interp1d - Interpolation function for p–y relationship (N/m vs m) - ''' - - Su = f_Su(z) - sigma_v_eff = f_sigma_v_eff(z) - gamma = f_gamma(z) - - # Strain at half the strength as defined by Matlock (1970). - # Typically ranges from 0.005 (stiff clay) to 0.02 (soft clay). - epsilon_50 = 0.02 - J = 0.5 - - # No soil resistance above mudline - if z0 is not None and z < z0: - return lambda y_val: np.zeros_like(y_val) - - # Calculate ultimate resistance and shape parameters - Nc = 3.0 + sigma_v_eff/Su + J*z/D - Nc = min(Nc, 9.0) - z_cr = 6.0 *D/(gamma*D/Su + J) - - p_ult = Su * Nc * D - y_50 = 2.5 * epsilon_50 * D - - # Normalized lateral displacements - Y = np.concatenate((-np.logspace(3, -4, 100), [0], np.logspace(-4, 3, 100))) - P = 0.5 * np.sign(Y)*np.abs(Y)**(1.0/3.0) - P = np.clip(P, -1.0, 1.0) - - # Un-normallized p-y curves - y = Y*y_50 - p = P*p_ult - - f = interp1d(y, p, kind='linear', bounds_error=False, fill_value=0.0) # Interpolation function for p-y curve - - # Plot of p-y curve and check if 'k' is calculated correctly - if plot: - plt.plot(y, p,'-') - plt.xlabel('y (m)') - plt.ylabel('p (N/m)') - plt.title('PY Curves - Matlock (1970)') - plt.grid(True) - plt.xlim([-2*D, 2*D]) - - return f - -def py_API(z, D, zlug, f_phi, f_sigma_v_eff, f_Dr, z0=None, plot=True): - ''' Generate API RP2A (1993) p–y curve at a given depth in sand. - - Parameters - ---------- - z : float - Depth relative to pile head (m) - D : float - Pile diameter (m) - zlug : float - Load eccentricity above or below mudline (m) - f_phi : function - Friction angle (deg) - f_sigma_v_eff : function - Effective vertical stress (Pa) - f_Dr : function - Relative density (-) - z0 : float, optional - Mudline depth (m). If provided, disables resistance above this level - plot : bool - Plot the resulting p–y curve if True - - Returns - ------- - f : interp1d - Interpolation function for p–y relationship (N/m vs m) - ''' - - phi = f_phi(z) - sigma_v_eff = f_sigma_v_eff(z) - Dr = f_Dr(z) - - # Interpolate coefficients depending on the effective friction angle - phi_ref = [ 20, 25, 30, 35, 40] - C1_ref = [0.80, 1.25, 1.90, 3.00, 4.50] - C2_ref = [1.60, 2.10, 2.60, 3.40, 4.30] - C3_ref = [ 10, 15, 30, 55, 105] - - C1 = np.interp(phi, phi_ref, C1_ref) - C2 = np.interp(phi, phi_ref, C2_ref) - C3 = np.interp(phi, phi_ref, C3_ref) - - # Disable p–y curve above mudline - if z0 is not None and z < z0: - return lambda y_val: np.zeros_like(y_val) - - # Compute ultimate lateral resistance - p_ult = min(C1*z + C2*D, C3*D) * sigma_v_eff - - # Compute initial stiffness k (kN/m3 → N/m3) - k = (54.6*Dr**2 + 0.8*Dr + 1.8)*1e3 - - # Normalized displacement range - N = 20 - y = np.concatenate((-np.logspace(3, -4, N), [0], np.logspace(-4, 3, N))) - - # Shape coefficient A - A = max(3 - 0.8*z/D, 0.9) - - # Apply API p–y formulation - ε = 1e-6 # prevent division by zero - p = A * p_ult * np.tanh(k*z*y/(A*p_ult + ε)) - - f = interp1d(y, p, kind='linear', bounds_error=False, fill_value=0.0) - - if plot: - # Plot of p-y curve and check if 'k' is calculated correctly - plt.plot(y, p,'-') - plt.xlabel('y (m)') - plt.ylabel('p (N/m)') - plt.title('PY Curves - API (1993)') - plt.grid(True) - plt.xlim([-0.10*D, 0.10*D]) - - return f - -def py_Reese(z, D, zlug, f_UCS, f_Em, z0=None, plot=True): - ''' Generate Reese (1997) p–y curve at a given depth in weak rock. - - Parameters - ---------- - z : float - Depth relative to pile head (m) - D : float - Pile diameter (m) - zlug : float - Load eccentricity above or below mudline (m) - f_UCS : function - Unconfined compressive strength UCS(z) (Pa) - f_Em : function - Young's modulus Em(z) (Pa) - z0 : float, optional - Mudline depth (m). If provided, disables resistance above this level - plot : bool - Plot the resulting p–y curve if True - - Returns - ------- - f : interp1d - Interpolation function for p–y relationship (N/m vs m) - ''' - - UCS = f_UCS(z) - Em = f_Em(z) - - RQD = 52 # Assumed fair rock quality (moderately weathered rocks) - Dref = 0.305; nhu = 0.3; E = 200e9 - t = (6.35 + D*20)/1e3 # Pile wall thickness (m), API RP2A-WSD - I = np.pi*(D**4 - (D - 2*t)**4)/64.0 - EI = E*I - alpha = -0.00667*RQD + 1 - krm = 0.0005 - - if z < z0: - # Above mudline, no resistance - p_ur = 0 - else: - if z < 3*D: - p_ur = alpha*UCS*D*(1 + 1.4*z/D) - #kir = (100 +400*z/(3*D)) - else: - p_ur = 5.2*alpha*UCS*D - #kir = 500 - - kir = (D/Dref)*2**(-2*nhu)*(EI/(Em*D**4))**0.284 - Kir = kir*Em - y_rm = krm*D - y_a = (p_ur/(2*y_rm**0.25*Kir))**1.333 - - # Normalized lateral displacement - N = 20 - y = np.concatenate((-np.logspace(4,-3,N),[0],np.logspace(-3,4,N))) - - p = [] - for val in y: - if abs(val) < y_a: - p_val = np.sign(val) * Kir * val - else: - p_val = np.sign(val)*min((p_ur/2)*(abs(val)/y_rm)**0.25, p_ur) - p.append(p_val) - - f = interp1d(y, p, kind='linear', bounds_error=False, fill_value=0.0) - - if plot: - plt.plot(y, p) - plt.xlabel('y (m)') - plt.ylabel('p (N/m)'), - plt.title('PY Curves - Reese (1997)') - plt.grid(True) - plt.xlim([-0.03*D, 0.03*D]) - #plt.ylim([min(p), max(p)]) - - return f - -def py_Lovera(z, D, f_UCS, f_Em, zlug, z0, plot=True): - ''' Generate Lovera (2019) p–y curve at a given depth for layered rock interfaces. - - Parameters - ---------- - z : float - Depth relative to pile head (m) - D : float - Pile diameter (m) - f_UCS : function - Unconfined compressive strength UCS(z) (Pa) - f_Em : function - Young's modulus Em(z) (Pa) - zlug : float - Load eccentricity (m) - z0 : float - Mudline depth (m). If provided, disables resistance above this level - delta_grout : float, optional - Grout annulus thickness (m) (default value: delta_grout=0.075) - E_grout : float, optional - Grout elastic modulus (Pa) (default value: E_grout=20e9) - delta_crushed : float, optional - Crushed rock annulus thickness (m) (default value: delta_crushed=0.025) - plot : bool - Plot the resulting p–y curve if True - - Returns - ------- - f : interp1d - Interpolation function for p–y relationship (N/m vs m) - ''' - - # Default values - delta_grout = 0.075 - E_grout = 20e9 - delta_crushed = 0.025 - - if z < z0: - return lambda y: np.zeros_like(y) - - # Retrieve elastic modulus at depth - Em = f_Em(z) - nu = 0.3 # Typical Poisson's ratio for rock - G_rock = Em/(2*(1 + nu)) - k_rock = 4*G_rock - - # Set E_crushed as 25% of intact rock modulus if not given - E_crushed = 0.25*Em - - # Compute total stiffness from linear components - k_eq = 1.0/(0.4*delta_grout/E_grout + delta_crushed/E_crushed + 1.0/k_rock) - - y = np.linspace(-0.03*D, 0.03*D, 200) - p = k_eq*y - f = interp1d(y, p, fill_value="extrapolate") - - if plot: - plt.plot(y, p, '-') - plt.xlabel('y (m)') - plt.ylabel('p (N/m)') - plt.title('PY Curves - Lovera (2019)') - plt.grid(True) - plt.xlim([-0.1*D, 0.1*D]) - plt.ylim([min(p), max(p)]) - plt.show() - - return f - diff --git a/famodel/anchors/anchors_famodel_profile/capacity_soils.py b/famodel/anchors/anchors_famodel_profile/capacity_soils.py deleted file mode 100644 index 93d4ae19..00000000 --- a/famodel/anchors/anchors_famodel_profile/capacity_soils.py +++ /dev/null @@ -1,176 +0,0 @@ - -import numpy as np -from scipy.interpolate import interp1d - -def clay_profile(profile): - ''' Create interpolated functions for a clay soil profile. - Calculates Su, effective vertical stress, unit weight and adhesion factor. - - Parameters - ---------- - profile : array - Clay profile as 2D array: (z, Su, gamma) - Depth (m), undrained shear strength Su (kPa) and effective unit weight gamma (kN/m³) - - Returns - ------- - z0 : float - Depth of mudline relative to pile head (m) - f_Su : interp1d - Undrained shear strength, Su(z) (Pa) - f_sigma_v_eff : interp1d - Effective vertical stress, σ'v(z) (Pa) - f_gamma : interp1d - Effective unit weight of the soil, γ'(z) (N/m³) - f_alpha : function - Adhesion factor from API correlation, α (-) - ''' - - # Depth of mudline relative to pile head - z0 = float(profile[0][0]) - - # Extract data from profile array and zero strength virtual soil layer - # from the pile head down to the mudline - depth = np.concatenate([np.array([z0]),np.array([row[0] for row in profile],dtype=float)]) # m - Su = np.concatenate([np.array([0]), np.array([row[1] for row in profile],dtype=float)]) # kPa - gamma = np.concatenate([np.array([0]), np.array([row[2] for row in profile],dtype=float)]) # kN/m3 - - # Calculate sigma_v_eff at each depth - sigma_v_eff = np.zeros(len(depth)) - - for i in range(1, len(depth)): - sigma_v_eff[i] = sigma_v_eff[i-1] + gamma[i-1]*(depth[i] - depth[i-1]) - - # Define interpolation functions - f_Su = interp1d(depth, Su*1e3, kind='linear') # Pa - f_sigma_v_eff = interp1d(depth, sigma_v_eff*1e3, kind='linear') # Pa - f_gamma = interp1d(depth, gamma*1e3, kind='linear') # N/m3 - - # Calculate f_psi and f_alpha at each depth (not as a scalar) - f_psi = lambda z: f_Su(z)/np.maximum(f_sigma_v_eff(z), 1.0) - - def calc_alpha(psi): - # Avoid divide-by-zero or log(0) by setting a floor - psi = np.maximum(psi, 1e-6) - if np.ndim(psi) == 0: - psi = float(psi) - # API-style adhesion factor: two regimes - return min(0.5*psi**-0.50, 1) if psi <= 1.0 else min(0.5*psi**-0.25, 1) - else: - return np.where( - psi <= 1.0, - np.minimum(0.5*psi**-0.50, 1), - np.minimum(0.5*psi**-0.25, 1) - ) - - # Create an interpolated adhesion factor function - # Create an interpolated adhesion factor function - def f_alpha(z): - psi_val = f_psi(z) - alpha_val = calc_alpha(psi_val) - return np.atleast_1d(alpha_val)[0] if np.ndim(alpha_val) == 0 else alpha_val - - return z0, f_Su, f_sigma_v_eff, f_gamma, f_alpha - -def sand_profile(profile): - ''' Create interpolated functions for a sand soil profile. - Calculates phi, effective stress, unit weight, relative density, and skin friction factor. - - Parameters - ---------- - profile : array - Sand profile as 2D array: (z, phi, gamma, Dr) - Depth (m), friction angle, phi (deg), effective unit weight, gamma (kN/m³) and relative density, Dr (%) - - Returns - ------- - z0 : float - Depth of mudline relative to pile head (m) - f_phi : interp1d - Friction angle, φ(z) (deg) - f_sigma_v_eff : interp1d - Effective vertical stress, σ'v(z) (Pa) - f_gamma : interp1d - Effective unit weight of the soil, γ'(z) (N/m³) - f_Dr : interp1d - Relative density, Dr(z) (-) - f_delta : interp1d - Skin friction factor, δ(z) (-) - ''' - - # Depth of mudline relative to pile head - z0 = float(profile[0][0]) - - # Extract data from profile array and zero strength virtual soil layer - # from the pile head down to the mudline - depth = np.concatenate([np.array([z0]),np.array([row[0] for row in profile],dtype=float)]) # m - phi = np.concatenate([np.array([0]), np.array([row[1] for row in profile],dtype=float)]) # deg - gamma = np.concatenate([np.array([0]), np.array([row[2] for row in profile],dtype=float)]) # kN/m3 - Dr = np.concatenate([np.array([0]), np.array([row[3] for row in profile],dtype=float)]) # - - - # Calculate sigma_v_eff and static loading factor at each depth - sigma_v_eff = np.zeros(len(depth)) - - for i in range(1, len(depth)): - sigma_v_eff[i] = sigma_v_eff[i-1] + gamma[i-1]*(depth[i] - depth[i-1]) - - # Define interpolation functions - f_phi = interp1d(depth, phi, kind='linear') # deg - f_sigma_v_eff = interp1d(depth, sigma_v_eff*1e3, kind='linear') # Pa - f_gamma = interp1d(depth, gamma*1e3, kind='linear') # N/m3 - f_Dr = interp1d(depth, Dr, kind='linear') # - - - # Define delta as a function of Dr - def calc_delta(Dr_val): - if 35 <= Dr_val < 50: - return 0.29 - elif 50 <= Dr_val < 65: - return 0.37 - elif 65 <= Dr_val < 85: - return 0.46 - elif Dr_val >= 85: - return 0.56 - else: - return 0 # Default or error value for very low Dr values - - # Apply delta calculation to Dr profile - delta_values = np.array([calc_delta(Dr_val) for Dr_val in Dr]) - f_delta = interp1d(depth, delta_values, kind='linear') # Interpolated delta values - - return z0, f_phi, f_sigma_v_eff, f_gamma, f_Dr, f_delta - -def rock_profile(profile): - ''' Create interpolated functions for a weak rock profile. - Calculates unconfined compressive strength (UCS) and Young’s modulus (Em). - - Parameters - ---------- - profile : array - Rock profile as 2D array: (z, UCS, Em) - Depth (m), unconfined compressive strength, UCS (MPa), Young's modulus, Em (MPa) - - Returns - ------- - z0 : float - Depth of rockline relative to pile head (m) - f_UCS : interp1d - Unconfined compressive strength, UCS(z) (Pa) - f_Em : interp1d - Young's modulus, Em(z) (Pa) - ''' - - # Depth of rockline relative to pile head - z0 = float(profile[0][0]) - - # Extract data from soil_profile array and zero strength virtual soil layer - # from the pile head down to the mudline - depth = np.concatenate([np.array([z0]),np.array([row[0] for row in profile],dtype=float)]) # m - UCS = np.concatenate([np.array([0]), np.array([row[1] for row in profile],dtype=float)]) # MPa - Em = np.concatenate([np.array([0]), np.array([row[2] for row in profile],dtype=float)]) # MPa - - # Define interpolation functions - f_UCS = interp1d(depth, UCS*1e6, kind='linear') # Pa - f_Em = interp1d(depth, Em*1e6, kind='linear') # Pa - - return z0, f_UCS, f_Em - diff --git a/famodel/anchors/anchors_famodel_profile/capacity_suction.py b/famodel/anchors/anchors_famodel_profile/capacity_suction.py deleted file mode 100644 index e322048a..00000000 --- a/famodel/anchors/anchors_famodel_profile/capacity_suction.py +++ /dev/null @@ -1,293 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from scipy.optimize import fsolve -from scipy.optimize import root_scalar -from .capacity_soils import clay_profile, sand_profile -from .capacity_plots import plot_suction - -def getCapacitySuction(profile, soil_type, D, L, zlug, Ha, Va, plot=True): - '''Calculate the inclined load capacity of a suction pile in sand or clay following S. Kay methodology. - The calculation is based on the soil profile, anchor geometry and inclined load. - - Parameters - ---------- - profile : array - Soil profile as a 2D array: (z, parameters) - Clay soil profile (z (m), Su (kPa), gamma (kN/m³)) - Sand soil profile (z (m), phi (deg), gamma (kN/m³), Dr (%)) - soil_type : string - Select soil condition, 'clay' or 'sand' - D : float - Suction pile diameter (m) - L : float - Suction pile length from pile head (m) - zlug: float - Embedded depth of the main padeye (m) - thetalug: float - Angle of tilt misaligment (deg) (default value: 5.0) - psilug: float - Angle of twist misaligment (deg) (default value: 7.5) - Ha : float - Horizontal load at pile lug elevation (N) - Va : float - Vertical load at pile lug elevation (N) - plot : bool - Plot the capacity envelope if True - - Returns - ------- - Dictionary with capcity, weigths and UC. - ''' - - z0 = profile[0][0] - lambdap = (L - z0)/D; m = 2/3; # Suction pile slenderness ratio - t = (6.35 + D*20)/1e3 # Suction pile wall thickness (m), API RP2A-WSD - rlug = D/2 # Radial position of the lug - thetalug = 5 # Angle of tilt misaligment, default is 5. (deg) - psilug = 7.5 # Angle of twist misaligment, default is 7.5. (deg) - rhows = 66.90e3 # Submerged steel specific weight (N/m3) - rhow = 10e3 # Water specific weight (N/m3) - - # Outer and inner surface of the pile skirt - def PileSurface(Len, Dia): - Sp = np.pi*Dia*Len - return Sp - # Dry and wet mass of the pile - def PileWeight(Len, Dia, tw, rho): - Wp = ((np.pi/4)*((Dia**2 - (Dia - 2*tw)**2)*Len + (np.pi/4)*Dia**2*tw))*rho - return Wp - # Mass of the soil plug - def SoilWeight(Len, Dia, tw, gamma_soil): - Wsoil =(np.pi/4)*(Dia - 2*tw)**2*Len*gamma_soil - return Wsoil - # Tilt and twist effects due to installation misaligments - def rlugTilt(r, z, theta): - R = r*np.cos(np.deg2rad(theta)) - z*np.sin(np.deg2rad(theta)) - return R - def zlugTilt(r, z, theta): - Z = r*np.sin(np.deg2rad(theta)) + z*np.cos(np.deg2rad(theta)) - return Z - - if soil_type == 'clay': - z0, f_Su, f_sigma_v_eff, f_gamma, f_alpha = clay_profile(profile) - z_vals = np.linspace(z0, L, 10) - - Su_vals = f_Su(z_vals) - ez = np.trapz(z_vals*Su_vals, z_vals)/np.trapz(Su_vals, z_vals); - ez_soil = ez; print(f"ez_soil = {ez_soil:.2f} m") - gamma_vals = f_gamma(z_vals) - - Su_av_L = f_Su(ez_soil) - Su_tip = f_Su(L); # print(f"Su_tip = {Su_tip:.2f} Pa") - sigma_v_eff = f_sigma_v_eff(ez_soil) - gamma_av = np.trapz(gamma_vals, z_vals)/(L - z0); # print(f"gamma_av = {gamma_av:.2f} kN/m³") - alpha_av = float(f_alpha(ez_soil)) - - Nc = min(6.2*(1 + 0.34*np.arctan(lambdap)), 9) - Np_fixed = 10.25; Np_free = 4 - Hmax = Np_fixed*(L - z0)*D*Su_av_L; print(f'Su_av_L = {Su_av_L:.2f} Pa') - print(f'Hmax = {Hmax:.2f} N') - - M = -Va*rlugTilt(rlug, zlug, thetalug) - Ha*(zlugTilt(rlug, zlug, thetalug) - ez_soil) - # print(f"rlug_eff = {rlugTilt(rlug, zlug, thetalug):.2f} m") - # print(f"zlug_eff = {zlugTilt(rlug, zlug, thetalug):.2f} m") - print(f"M = {M:.2f} Nm") - - # --- MH Ellipse Parameters for Clay (Kay 2014) --- - # ΔφMH (piecewise based on L/D) - if 0.5 <= lambdap < 1.125: - delta_phi = 0.32 + 4.32*lambdap; # print(delta_phi) - elif 1.125 <= lambdap < 2.0: - delta_phi = 7.13 - 1.71*lambdap; # print(delta_phi) - elif 2.0 <= lambdap <= 8.0: - delta_phi = 4.55 - 0.425*lambdap; # print(delta_phi) - else: - raise ValueError('L/D ratio out of bounds for MH ellipse formulation.') - - phi_MH = -np.arctan(ez_soil/(L -z0)) - np.deg2rad(delta_phi) - a_MH = Np_fixed/np.cos(phi_MH) - delta_bMH = 0.45*(lambdap)**(-0.9) if lambdap <= 1.5 else 0 - b_MH = -Np_free*np.sin(phi_MH) + delta_bMH - print('M cos(phi)/a_MH =', (M*np.cos(phi_MH))/a_MH) - print('M sin(phi)/b_MH =', (M*np.sin(phi_MH))/b_MH) - - # Solve MH ellipse for Hmax - def f(Hmax): - term1 = ((M*np.cos(phi_MH) + Hmax*np.sin(phi_MH))/a_MH)**2 - term2 = ((M*np.sin(phi_MH) - Hmax*np.cos(phi_MH))/b_MH)**2 - return term1 + term2 - 1 - - try: - Hmax = max(fsolve(f, Hmax*0.8)[0], 0.0) - except: - Hmax = 0.0 - - print(f'Hmax (MH ellipse) = {Hmax:.2f} N') - - To = PileSurface((L - z0), D)*alpha_av*Su_av_L - Ti = PileSurface((L - z0), D - 2*t)*alpha_av*Su_av_L - Tbase = np.pi*D**3*Su_tip/12 - Tmax = min(To + Ti, To + Tbase) - - T = Ha*rlug*np.sin(np.deg2rad(psilug)) - nhuT = T/Tmax - nhuV = Ha/To - nhuVstar = np.sqrt(nhuV**2 - nhuT**2) - alphastar = alpha_av*(nhuVstar/nhuV); print(f"alphastar = {alphastar:.3f}") - - Vmax1 = PileWeight(L, D, t, rhows) + PileSurface((L - z0), D)*alphastar*Su_av_L + Nc*Su_tip*(np.pi/4)*D**2 - Vmax2 = PileWeight(L, D, t, rhows) + PileSurface((L - z0), D)*alphastar*Su_av_L + PileSurface((L - z0), D - 2*t)*alphastar*Su_av_L - Vmax3 = PileWeight(L, D, t, rhows) + PileSurface((L - z0), D)*alphastar*Su_av_L + SoilWeight((L - z0), D, t, gamma_av) - Vmax = min(Vmax1, Vmax2, Vmax3) - - print(f"Vmax1 = {Vmax1:.2f} N"); print(f"Vmax2 = {Vmax2:.2f} N"); print(f"Vmax3 = {Vmax3:.2f} N") - - - elif soil_type == 'sand': - z0, f_phi, f_sigma_v_eff, f_gamma, f_Dr, f_delta = sand_profile(profile) - z_vals = np.linspace(z0, L, 10) - - sigma_v_vals = f_sigma_v_eff(z_vals) - ez = np.trapz(z_vals*sigma_v_vals, z_vals) / np.trapz(sigma_v_vals, z_vals) - ez_soil = ez - z0 - - phi_vals = f_phi(z_vals) - gamma_vals = f_gamma(z_vals) - sigma_v_vals = f_sigma_v_eff(z_vals) - Dr_vals = f_Dr(z_vals) - delta_vals = f_delta(z_vals) - - phi_av = np.trapz(phi_vals, z_vals)/(L - z0) - gamma_av = np.trapz(gamma_vals, z_vals)/(L - z0) - delta_av = np.trapz(delta_vals, z_vals)/(L - z0) - sigma_av_L = np.trapz(sigma_v_vals, z_vals)/(L - z0) - sigma_tip = f_sigma_v_eff(L) - - Nq = np.e**(np.pi*np.tan(np.radians(phi_av)))*(np.tan(np.radians(45) + np.radians(phi_av)/2))**2 - Hmax = 0.5*D*Nq*gamma_av*(L - z0)**2 - Np_free = 3.0 - - M = -Va*rlugTilt(rlug, zlug, thetalug) - Ha*(zlugTilt(rlug, zlug, thetalug) - ez_soil) - - # --- MH Ellipse Parameters for Clay (Kay 2014) --- - # ΔφMH (piecewise based on L/D) - if 0.5 <= lambdap < 1.125: - delta_phi = 0.32 + 4.32*lambdap - elif 1.125 <= lambdap < 2.0: - delta_phi = 7.13 - 1.71*lambdap - elif 2.0 <= lambdap <= 6.0: - delta_phi = 4.55 - 0.425*lambdap - else: - raise ValueError('L/D ratio out of bounds for MH ellipse formulation.') - - phi_MH = -np.arctan(ez_soil/(L - z0)) - np.deg2rad(delta_phi) - a_MH = Nq/np.cos(phi_MH) - delta_bMH = 0.45*(lambdap)**(-0.9) if lambdap <= 1.5 else 0 - b_MH = -Nq*np.sin(phi_MH) + delta_bMH - - # Solve MH ellipse for Hmax - def f(Hmax): - term1 = ((M*np.cos(phi_MH) + Hmax*np.sin(phi_MH))/a_MH)**2 - term2 = ((M*np.sin(phi_MH) - Hmax*np.cos(phi_MH))/b_MH)**2 - return term1 + term2 - 1 - - Hmax = fsolve(f, 0.8*Hmax)[0] - print(f'Hmax (MH ellipse) = {Hmax:.2f} N') - - To = PileSurface((L - z0), D)*delta_av*sigma_av_L - Ti = PileSurface((L - z0), D - 2*t)*delta_av*sigma_av_L - Tbase = np.pi*D**3*sigma_tip/12 - Tmax = min(To + Ti, To + Tbase) - - T = Ha*rlug*np.sin(np.deg2rad(psilug)) - Fo = delta_av*sigma_av_L*L*np.pi*D - nhuT = T/Tmax - nhuV = Ha/Fo - nhuVstar = np.sqrt(nhuV**2 - nhuT**2) - deltastar = delta_av*(nhuVstar/nhuV) - - Vmax2 = PileWeight(L, D, t, rhows) + PileSurface((L - z0), D)*deltastar*sigma_av_L + PileSurface((L - z0), D - 2*t)*deltastar*sigma_av_L - Vmax3 = PileWeight(L, D, t, rhows) + PileSurface((L - z0), D)*deltastar*sigma_av_L + SoilWeight((L - z0), D, t, gamma_av) - Vmax = min(Vmax2, Vmax3) - - # Pile weight (inc. stiffening plus vent) assessed as a factor - Wp = 1.10*PileWeight(L, D, t, (rhows + rhow)) - # Submerged weight of the soil plug - Wsoil = SoilWeight((L - z0), D, t, gamma_av) - - # Capacity envelope - aVH = 0.5 + lambdap; bVH = 4.5 + lambdap/3 - # print('Env. exp = ' +str(aVH)+' '+str(bVH)) - UC = (Ha/Hmax)**aVH + (Va/Vmax)**bVH - x = np.cos(np.linspace (0, np.pi/2, 100)) - y = (1 - x**bVH)**(1/aVH) - X = Hmax*x; Y = Vmax*y - - if plot: - plt.figure(figsize=(6, 5)) - plt.plot(X, Y, color = 'b', label='VH Envelope') - plt.plot(Ha, Va, 'o', color = 'r', label='Load Point') - - # Set labels and title - plt.xlabel('Horizontal capacity (N)') - plt.ylabel('Vertical capacity (N)') - plt.suptitle('VH suction pile capacity envelope') - plt.axis([0, 1.3*max(X[0], Ha), 0, 1.3*max(Y[-1], Va)]) - plt.legend() - plt.grid(True) - plt.show() - - resultsSuction = { - 'Horizontal max.': Hmax, - 'Vertical max.': Vmax, - 'Unity check': UC, - 'Weight pile': Wp, - 'Weight soil': Wsoil, - 't': t - } - - return resultsSuction - -if __name__ == '__main__': - - # Clay profile: [depth (m), Su (kPa), gamma (kN/m³)] - profile_clay = np.array([ - [ 2.0, 25, 8.5], - [ 4.0, 25, 8.5], - [ 6.0, 25, 8.5], - [20.0, 25, 8.5] - ]) - - # Sand profile: [depth (m), phi (deg), gamma (kN/m³), Dr(%)] - profile_sand = np.array([ - [ 1.0, 28, 8.0, 75], - [ 5.0, 35, 8.5, 75], - [ 8.0, 38, 9.0, 75], - [20.0, 42, 9.5, 75] - ]) - - D = 3.0 # Diameter (m) - L = 10.0 # Length (m) - zlug = 8.0 # Padeye depth (m) - Ha = 2.0e6 # Horizontal load (N) - Va = 3.0e6 # Vertical load (N) - - # === CLAY === - resultsSuction_clay = getCapacitySuction(profile_clay, 'clay', D, L, zlug, Ha, Va, plot=True) - for key, val in resultsSuction_clay.items(): - print(f"{key}: {val:.2f}") - - # Plot suction pile with the clay profile - profile_clay_plot = [(float(z), float(Su), 'clay') for z, Su, _ in profile_clay] - plot_suction(profile_clay_plot, 'clay', L, D, zlug) - - # === SAND === - # resultsSuction_sand = getCapacitySuction(profile_sand, 'sand', D, L, zlug, Ha, Va, plot=True) - # for key, val in resultsSuction_sand.items(): - # print(f"{key}: {val:.2f}") - - # # Sand profile formatted for plotting - # profile_sand_plot = [(float(z), float(phi), 'sand') for z, phi, _, _ in profile_sand] - # plot_suction(profile_sand_plot, 'sand', L, D, zlug, title='Suction Pile in Sand Profile') - diff --git a/famodel/anchors/anchors_famodel_profile/capacity_torpedo.py b/famodel/anchors/anchors_famodel_profile/capacity_torpedo.py deleted file mode 100644 index 5495a956..00000000 --- a/famodel/anchors/anchors_famodel_profile/capacity_torpedo.py +++ /dev/null @@ -1,159 +0,0 @@ - -import numpy as np -import matplotlib.pyplot as plt -from .capacity_soils import clay_profile -from .capacity_plots import plot_torpedo - -def getCapacityTorpedo(profile, soil_type, D1, D2, L1, L2, zlug, ballast, Ha, Va, plot=True): - '''Calculate the inclined load capacity of a torpedo pile in clay following S. Kay methodology. - The calculation is based on the soil profile, anchor geometry and inclined load. - - Parameters - ---------- - profile : array - Clay soil profile (z, Su, gamma) - Clay soil profile (z (m), Su (kPa), gamma (kN/m³)) - soil_type : string - Select soil condition, 'clay' - D1 : float - Wing diameter (m) - D2 : float - Shaft diameter (m) - L1 : float - Winged section length (m) - L2 : float - Shaft section length (m) - zlug : float - Padeye embedment depth (m) - Ha : float - Horizontal load at pile lug elevation (N) - Va : float - Vertical load at pile lug elevation (N) - plot : bool - Plot the capacity envelope if True - - Returns - ------- - Dictionary with capcity, weigth and UC. - ''' - - t = (6.35 + D2*20)/1e3 # Torpedo pile wall thickness (m), API RP2A-WSD - rhows = 66.90e3 # Submerged steel specific weight (N/m3) - rhow = 10e3 # Water specific weight (N/m3) - - # Average effective width - L = L1 + L2 - A_wing_plane_1 = (D1 - D2)*L1 - A_wing_plane_2 = (D1 - D2)*np.cos(np.deg2rad(45))/2*L1 - A_shaft = D2*L - - # Choose based on direction: - plane = '1' # or '2' - - if plane == '1': - Dstar = (A_wing_plane_1 + A_shaft)/L - elif plane == '2': - Dstar = (A_wing_plane_2 + A_shaft)/L - - z0, f_Su, f_sigma_v_eff, f_gamma, f_alpha = clay_profile(profile) - - a = zlug - c = zlug + L1 + L2 - profile_depth = profile[-1, 0] - - if c > profile_depth: - raise ValueError( - f'Soil profile does not cover the full pile length.\n' - f' → Pile tip depth: {c:.2f} m\n' - f' → Soil profile depth: {profile_depth:.2f} m\n' - f'Extend the soil profile to at least the pile tip depth to run the capacity model.' - ) - - z_vals = np.linspace(a, c, 100) - Su_vals = f_Su(z_vals) - alpha_vals = np.array([f_alpha(z) for z in z_vals]) - - ez_soil = np.trapz(z_vals*Su_vals, z_vals)/np.trapz(Su_vals, z_vals) - Su_e = f_Su(ez_soil) - alpha_e = f_alpha(ez_soil) - print(f"Su_e = {Su_e:.2f} kPa, ez_soil = {ez_soil:.2f} m, alpha_e = {alpha_e:.2f}") - - def PileWeight(Len1, Len2, Dia1, Dia2, tw, rho): - return ((np.pi/4)*(Dia1**2 - (Dia1 - 2*tw)**2)*(Len1 + Len2) + 4*Len2*Dia2*tw)*rho - - def PileSurface(Len1, Len2, Dia1, Dia2): - return np.pi*Dia1*(Len1 + Len2) + 8*Len2*Dia2*0.9 - - Np_free = 3.45 - Hmax = Np_free*L*Dstar*Su_e - Vmax = PileSurface(L1, L2, D1, D2)*alpha_e*Su_e + PileWeight(L1, L2, D1, D2, t, rhows) + ballast - - # Pile weight (inc. auxiliary elements) assessed as a factor - Wp = 1.10*PileWeight(L1, L2, D1, D2, t, (rhows + rhow)) + ballast - - # Calculate actual ez_su to L ratio - ez_ratio = (ez_soil - zlug)/L; print(f"ez_ratio = {ez_ratio:.2f} m") - - # Assign aVH and bVH based on ez_su/L - if np.isclose(ez_ratio, 2/3, atol=0.05): - aVH = 0.5 + L/Dstar - bVH = 4.5 - L/(3*Dstar) - mode = 'deep mobilization (2/3)' - elif 0.45 <= ez_ratio <= 0.75: - aVH = 4.5 + L/(2*Dstar) - bVH = 3.5 - L/(4*Dstar) - mode = 'moderate mobilization (1/2 – 3/4)' - print(f'Interaction exponents set to aVH = {aVH:.2f}, bVH = {bVH:.2f} [{mode}]') - - UC = (Ha/Hmax)**aVH + (Va/Vmax)**bVH - - deg = np.linspace(0, 90, 20) - x = np.cos(np.deg2rad(deg)) - y = (1 - x**bVH)**(1/aVH) - X = Hmax*x; Y = Vmax*y - - if plot: - plt.plot(X, Y, color='blue', label='VH Envelope') - plt.plot(H, V, 'o', color='red', label='Load Point') - plt.xlabel('Horizontal Load (N)') - plt.ylabel('Vertical Load (N)') - plt.title('VH torpedo pile capacity envelope') - plt.grid(True) - plt.legend() - plt.axis([0, 1.3*max(X[0], H), 0, 1.3*max(Y[-1], V)]) - plt.show() - - resultsTorpedo = { - 'Horizontal max.': Hmax, - 'Vertical max.': Vmax, - 'Unity check': UC, - 'Weight pile': Wp - } - - return resultsTorpedo - -if __name__ == '__main__': - - profile_clay = np.array([ - [ 0.0, 50, 8.0], - [20.0, 50, 8.5], - [25.0, 50, 8.5], - [50.0, 50, 9.0] - ]) - - D1 = 3.0 # Wing diameter (m) - D2 = 1.5 # Shaft diamter (m) - L1 = 11.0 # Winged section length (m) - L2 = 10.0 # Shaft section length (m) - zlug = 15.0 # Padeye depth (m) - ballast = 10000 # Ballast load (N) - H = 6.0e6 # Horizontal load (N) - V = 8.0e6 # Vertical load (N) - - results = getCapacityTorpedo(profile_clay, 'clay', D1, D2, L1, L2, zlug, ballast, H, V, plot=True) - print("\n--- Torpedo Pile Capacity Results ---") - for key, val in results.items(): - print(f"{key}: {val:.2f}") - - plot_torpedo(profile_clay, 'clay', D1, D2, L1, L2, zlug, title='Torpedo Pile in Clay Profile') - diff --git a/famodel/anchors/getCapacityAnchor_profile.py b/famodel/anchors/getCapacityAnchor_profile.py deleted file mode 100644 index 4e7cf491..00000000 --- a/famodel/anchors/getCapacityAnchor_profile.py +++ /dev/null @@ -1,94 +0,0 @@ - -from famodel.anchors.anchor_profile import Anchor -from famodel.anchors.anchors_famodel_profile.capacity_plots import plot_load -import numpy as np - -# Define the soil profile -soil_profile = np.array([ - [ 1.0, 10, 8.0], - [ 2.0, 25, 8.5], - [ 8.0, 50, 9.0], - [16.0, 100, 9.5], - [25.0, 100, 9.5] -]) - -# Create Anchor object -anchor = Anchor( - dd={ - 'type': 'suction', - 'design': {'D': 2.5, 'L': 10.0, 'zlug': 6.0, 'soil_type': 'clay'}, - 'soil_properties': {'clay': soil_profile} - }, - ms=None, - r=[0.0, 0.0, 0.0], - aNum=0, - id='A1', - g=9.81, - rho=1025 -) - -# Assign loads manually -anchor.loads = { - 'Hm': 3e6, # Horizontal mudline load (N) - 'Vm': 1e6 # Vertical mudline load (N) -} - -# Also assign mooring line properties manually -anchor.line_type = 'chain' -anchor.d = 0.16 # Chain diameter (m) -anchor.w = 5000.0 # Nominal submerged weight (N/m) - -# --- Step 1: Compute Lug Forces --- -Ha, Va = anchor.getLugForces( - ground_conds=anchor.dd['soil_properties'], - Hm=anchor.loads['Hm'], - Vm=anchor.loads['Vm'], - thetam=np.degrees(np.arctan2(anchor.loads['Vm'], anchor.loads['Hm'])), - zlug=anchor.dd['design']['zlug'], - line_type=anchor.line_type, - d=anchor.d, - w=anchor.w, - plot=True -) - -# Print Lug Forces -print('\nLug Forces Computed:') -print(f'Ha = {Ha:.2f} N') -print(f'Va = {Va:.2f} N') - -# --- Step 2: Compute Anchor Capacity --- -anchor.getCapacityAnchor( - ground_conds=anchor.dd['soil_properties'], - Hm=anchor.loads['Hm'], - Vm=anchor.loads['Vm'], - thetam=np.degrees(np.arctan2(anchor.loads['Vm'], anchor.loads['Hm'])), - zlug=anchor.dd['design']['zlug'], - line_type=anchor.line_type, - d=anchor.d, - w=anchor.w, - plot=True -) - -# Print Capacity Results -print('\nCapacity Results:') -for key, value in anchor.capacity_results.items(): - print(f'{key}: {value:.2f}') - -# --- Step 3: Optimize Anchor Geometry --- -anchor.getSizeSuction( - geom=[anchor.dd['design']['L'], anchor.dd['design']['D']], - geomKeys=['L', 'D'], - geomBounds=[(5.0, 15.0), (2.0, 6.0)], - loads=None, - minfs={'Ha': 1.0, 'Va': 1.0}, - lambdap_con=[3, 6], - zlug_fix=False, - plot=True -) - -print('\nFinal Optimized Anchor:') -print('Design:', anchor.dd['design']) -print('Capacity Results:', anchor.capacity_results) - -# --- Step 4: Visualize Anchor Geometry --- -anchor.getCombinedPlot() \ No newline at end of file diff --git a/famodel/anchors/getCapacityHelical_map.py b/famodel/anchors/getCapacityHelical_map.py deleted file mode 100644 index 1710e413..00000000 --- a/famodel/anchors/getCapacityHelical_map.py +++ /dev/null @@ -1,70 +0,0 @@ - -from anchor_map import Anchor - -# --- Define soil profile --- -profile_map = [ - { - 'name': 'CPT_H1', - 'x': 0.0, 'y': 0.0, - 'layers': [ - {'top': 1.0, 'bottom': 10.0, 'soil_type': 'sand', 'gamma_top': 10.0, 'gamma_bot': 11.0, 'phi_top': 30, 'phi_bot': 32, 'Dr_top': 60, 'Dr_bot': 60}, - {'top': 10.0, 'bottom': 20.0, 'soil_type': 'sand', 'gamma_top': 11.0, 'gamma_bot': 11.5, 'phi_top': 36, 'phi_bot': 38, 'Dr_top': 60, 'Dr_bot': 80} - ] - } -] - -# --- Create helical anchor object --- -anchor = Anchor( - dd = { - 'type': 'helical', - 'design': { - 'D': 1.7, # Helix diameter (m) - 'L': 12.0, # Depth (m) - 'd': 0.3, # Shaft diameter (m) - 'zlug': 4.0 # Padeye depth (m) - } - }, - r = [0.0, 0.0, 0.0] -) - -# Assign loads and mooring info -anchor.loads = { - 'Hm': 8.8e6, - 'Vm': 1.2e6 -} -anchor.line_type = 'chain' -anchor.d = 0.16 -anchor.w = 5000.0 - -# Assign local soil -anchor.setSoilProfile(profile_map) - -# --- Step 1: Lug Forces --- -layers, Ha, Va = anchor.getLugForces( - Hm = anchor.loads['Hm'], - Vm = anchor.loads['Vm'], - zlug = anchor.dd['design']['zlug'], - line_type = anchor.line_type, - d = anchor.d, - w = anchor.w, - plot = True -) - -print('\nLug Forces Computed:') -print(f'Ha = {Ha:.2f} N') -print(f'Va = {Va:.2f} N') - -# --- Step 2: Capacity --- -anchor.getCapacityAnchor( - Hm = anchor.loads['Hm'], - Vm = anchor.loads['Vm'], - zlug = anchor.dd['design']['zlug'], - line_type = anchor.line_type, - d = anchor.d, - w = anchor.w, - plot = True -) - -print('\nCapacity Results:') -for key, val in anchor.capacity_results.items(): - print(f'{key}: {val:.2f}') diff --git a/famodel/anchors/getCapacityHelical_sand.py b/famodel/anchors/getCapacityHelical_sand.py deleted file mode 100644 index 1710e413..00000000 --- a/famodel/anchors/getCapacityHelical_sand.py +++ /dev/null @@ -1,70 +0,0 @@ - -from anchor_map import Anchor - -# --- Define soil profile --- -profile_map = [ - { - 'name': 'CPT_H1', - 'x': 0.0, 'y': 0.0, - 'layers': [ - {'top': 1.0, 'bottom': 10.0, 'soil_type': 'sand', 'gamma_top': 10.0, 'gamma_bot': 11.0, 'phi_top': 30, 'phi_bot': 32, 'Dr_top': 60, 'Dr_bot': 60}, - {'top': 10.0, 'bottom': 20.0, 'soil_type': 'sand', 'gamma_top': 11.0, 'gamma_bot': 11.5, 'phi_top': 36, 'phi_bot': 38, 'Dr_top': 60, 'Dr_bot': 80} - ] - } -] - -# --- Create helical anchor object --- -anchor = Anchor( - dd = { - 'type': 'helical', - 'design': { - 'D': 1.7, # Helix diameter (m) - 'L': 12.0, # Depth (m) - 'd': 0.3, # Shaft diameter (m) - 'zlug': 4.0 # Padeye depth (m) - } - }, - r = [0.0, 0.0, 0.0] -) - -# Assign loads and mooring info -anchor.loads = { - 'Hm': 8.8e6, - 'Vm': 1.2e6 -} -anchor.line_type = 'chain' -anchor.d = 0.16 -anchor.w = 5000.0 - -# Assign local soil -anchor.setSoilProfile(profile_map) - -# --- Step 1: Lug Forces --- -layers, Ha, Va = anchor.getLugForces( - Hm = anchor.loads['Hm'], - Vm = anchor.loads['Vm'], - zlug = anchor.dd['design']['zlug'], - line_type = anchor.line_type, - d = anchor.d, - w = anchor.w, - plot = True -) - -print('\nLug Forces Computed:') -print(f'Ha = {Ha:.2f} N') -print(f'Va = {Va:.2f} N') - -# --- Step 2: Capacity --- -anchor.getCapacityAnchor( - Hm = anchor.loads['Hm'], - Vm = anchor.loads['Vm'], - zlug = anchor.dd['design']['zlug'], - line_type = anchor.line_type, - d = anchor.d, - w = anchor.w, - plot = True -) - -print('\nCapacity Results:') -for key, val in anchor.capacity_results.items(): - print(f'{key}: {val:.2f}') diff --git a/famodel/anchors/images/Drilledandgroutedpiles/Drilled.png b/famodel/anchors/images/Drilledandgroutedpiles/Drilled.png new file mode 100644 index 00000000..38f4ae2b Binary files /dev/null and b/famodel/anchors/images/Drilledandgroutedpiles/Drilled.png differ diff --git a/famodel/anchors/images/Drilledandgroutedpiles/Rock - deformed dandg.png b/famodel/anchors/images/Drilledandgroutedpiles/Rock - deformed dandg.png new file mode 100644 index 00000000..260361c4 Binary files /dev/null and b/famodel/anchors/images/Drilledandgroutedpiles/Rock - deformed dandg.png differ diff --git a/famodel/anchors/images/Drivenpiles/Clay - deformed pile.png b/famodel/anchors/images/Drivenpiles/Clay - deformed pile.png new file mode 100644 index 00000000..66eefefc Binary files /dev/null and b/famodel/anchors/images/Drivenpiles/Clay - deformed pile.png differ diff --git a/famodel/anchors/images/Drivenpiles/Driven.png b/famodel/anchors/images/Drivenpiles/Driven.png new file mode 100644 index 00000000..07630a75 Binary files /dev/null and b/famodel/anchors/images/Drivenpiles/Driven.png differ diff --git a/famodel/anchors/images/Drivenpiles/Rock - deformed pile.png b/famodel/anchors/images/Drivenpiles/Rock - deformed pile.png new file mode 100644 index 00000000..44329257 Binary files /dev/null and b/famodel/anchors/images/Drivenpiles/Rock - deformed pile.png differ diff --git a/famodel/anchors/images/Drivenpiles/Rock - driven pile.png b/famodel/anchors/images/Drivenpiles/Rock - driven pile.png new file mode 100644 index 00000000..e6fee7fe Binary files /dev/null and b/famodel/anchors/images/Drivenpiles/Rock - driven pile.png differ diff --git a/famodel/anchors/images/Drivenpiles/Sand - deformed pile.png b/famodel/anchors/images/Drivenpiles/Sand - deformed pile.png new file mode 100644 index 00000000..bd3c4779 Binary files /dev/null and b/famodel/anchors/images/Drivenpiles/Sand - deformed pile.png differ diff --git a/famodel/anchors/images/Drivenpiles/Sand - driven pile.png b/famodel/anchors/images/Drivenpiles/Sand - driven pile.png new file mode 100644 index 00000000..5dfc06e8 Binary files /dev/null and b/famodel/anchors/images/Drivenpiles/Sand - driven pile.png differ diff --git a/famodel/anchors/images/Drivenpiles/pycurves - API.png b/famodel/anchors/images/Drivenpiles/pycurves - API.png new file mode 100644 index 00000000..953d7c1a Binary files /dev/null and b/famodel/anchors/images/Drivenpiles/pycurves - API.png differ diff --git a/famodel/anchors/images/Drivenpiles/pycurves - Lovera.png b/famodel/anchors/images/Drivenpiles/pycurves - Lovera.png new file mode 100644 index 00000000..88214936 Binary files /dev/null and b/famodel/anchors/images/Drivenpiles/pycurves - Lovera.png differ diff --git a/famodel/anchors/images/Drivenpiles/pycurves - Matlock.png b/famodel/anchors/images/Drivenpiles/pycurves - Matlock.png new file mode 100644 index 00000000..e5cf513a Binary files /dev/null and b/famodel/anchors/images/Drivenpiles/pycurves - Matlock.png differ diff --git a/famodel/anchors/images/Drivenpiles/pycurves - Reese.png b/famodel/anchors/images/Drivenpiles/pycurves - Reese.png new file mode 100644 index 00000000..647a1e57 Binary files /dev/null and b/famodel/anchors/images/Drivenpiles/pycurves - Reese.png differ diff --git a/famodel/anchors/images/Helicalpiles/Clay - deformed pile.png b/famodel/anchors/images/Helicalpiles/Clay - deformed pile.png new file mode 100644 index 00000000..20b7f0aa Binary files /dev/null and b/famodel/anchors/images/Helicalpiles/Clay - deformed pile.png differ diff --git a/famodel/anchors/images/Helicalpiles/Helical.png b/famodel/anchors/images/Helicalpiles/Helical.png new file mode 100644 index 00000000..050ac710 Binary files /dev/null and b/famodel/anchors/images/Helicalpiles/Helical.png differ diff --git a/famodel/anchors/images/Helicalpiles/Sand - deformed pile.png b/famodel/anchors/images/Helicalpiles/Sand - deformed pile.png new file mode 100644 index 00000000..4bc11e77 Binary files /dev/null and b/famodel/anchors/images/Helicalpiles/Sand - deformed pile.png differ diff --git a/famodel/anchors/images/Helicalpiles/Sand - helical pile.png b/famodel/anchors/images/Helicalpiles/Sand - helical pile.png new file mode 100644 index 00000000..cf6c639a Binary files /dev/null and b/famodel/anchors/images/Helicalpiles/Sand - helical pile.png differ diff --git a/famodel/anchors/images/Helicalpiles/pycurves - API.png b/famodel/anchors/images/Helicalpiles/pycurves - API.png new file mode 100644 index 00000000..d8172ec7 Binary files /dev/null and b/famodel/anchors/images/Helicalpiles/pycurves - API.png differ diff --git a/famodel/anchors/images/Helicalpiles/pycurves - Matlock.png b/famodel/anchors/images/Helicalpiles/pycurves - Matlock.png new file mode 100644 index 00000000..58c85213 Binary files /dev/null and b/famodel/anchors/images/Helicalpiles/pycurves - Matlock.png differ diff --git a/famodel/anchors/images/Plateanchors/Plate.png b/famodel/anchors/images/Plateanchors/Plate.png new file mode 100644 index 00000000..0698f449 Binary files /dev/null and b/famodel/anchors/images/Plateanchors/Plate.png differ diff --git a/famodel/anchors/images/Suctionpiles/Clay - suction envelope.png b/famodel/anchors/images/Suctionpiles/Clay - suction envelope.png new file mode 100644 index 00000000..81af02ee Binary files /dev/null and b/famodel/anchors/images/Suctionpiles/Clay - suction envelope.png differ diff --git a/famodel/anchors/images/Suctionpiles/Sand - suction envelope.png b/famodel/anchors/images/Suctionpiles/Sand - suction envelope.png new file mode 100644 index 00000000..78574484 Binary files /dev/null and b/famodel/anchors/images/Suctionpiles/Sand - suction envelope.png differ diff --git a/famodel/anchors/images/Suctionpiles/Sand - suction pile.png b/famodel/anchors/images/Suctionpiles/Sand - suction pile.png new file mode 100644 index 00000000..dd4af03e Binary files /dev/null and b/famodel/anchors/images/Suctionpiles/Sand - suction pile.png differ diff --git a/famodel/anchors/images/Suctionpiles/Suction.png b/famodel/anchors/images/Suctionpiles/Suction.png new file mode 100644 index 00000000..b96e863b Binary files /dev/null and b/famodel/anchors/images/Suctionpiles/Suction.png differ diff --git a/famodel/anchors/images/Torpedopiles/Clay - torpedo envelope.png b/famodel/anchors/images/Torpedopiles/Clay - torpedo envelope.png new file mode 100644 index 00000000..a633fdb1 Binary files /dev/null and b/famodel/anchors/images/Torpedopiles/Clay - torpedo envelope.png differ diff --git a/famodel/anchors/images/Torpedopiles/Torpedo.png b/famodel/anchors/images/Torpedopiles/Torpedo.png new file mode 100644 index 00000000..1ed223cf Binary files /dev/null and b/famodel/anchors/images/Torpedopiles/Torpedo.png differ diff --git a/famodel/geography.py b/famodel/geography.py index 5e92c5d6..0929f849 100644 --- a/famodel/geography.py +++ b/famodel/geography.py @@ -3,22 +3,17 @@ import os import numpy as np import matplotlib.pyplot as plt - import moorpy as mp from moorpy.helpers import set_axes_equal import yaml - import pandas as pd import geopandas as gpd from shapely.geometry import Point, Polygon, LineString - import famodel.seabed_tools as sbt - from pyproj import CRS from pyproj.aoi import AreaOfInterest from pyproj.database import query_utm_crs_info - # ============================================================================= # COORDINATE REFERENCE SYSTEMS & TRANSFORMATIONS # ============================================================================= @@ -89,7 +84,6 @@ def getTargetCRS(longitudes, latitudes): return target_crs - def getCustomCRS(long, lat): '''Seemingly way too simple of a method to create a pyproj CRS centered around a custom geographical point @@ -110,8 +104,6 @@ def getCustomCRS(long, lat): return custom_crs - - def getLeaseCoords(lease_name): # read in the BOEM shapefile that contains all Wind Energy Lease Areas (can use other shapefiles for aliquots) @@ -137,17 +129,17 @@ def getLeaseCoords(lease_name): raise ValueError(f"The lease area name '{lease_area}' is not supported yet") # extract the longitude and latitude coordinates of the lease area - area_longs, area_lats = lease_area.geometry.unary_union.exterior.coords.xy + #area_longs, area_lats = lease_area.geometry.unary_union.exterior.coords.xy + area_longs, area_lats = lease_area.geometry.union_all().exterior.coords.xy + # calculate the centroid of the lease area centroid = ( lease_area.geometry.centroid.values.x[0], lease_area.geometry.centroid.values.y[0] ) - return area_longs, area_lats, centroid - - - + return area_longs, area_lats, centroid + def convertLatLong2Meters(longs, lats, centroid, latlong_crs, target_crs, return_centroid=False): '''input longs/lats need to be in EPSG:4326 CRS Longs and Lats need to be in pairs, i.e., the first entry to longs and @@ -203,7 +195,6 @@ def convertLatLong2Meters(longs, lats, centroid, latlong_crs, target_crs, return else: return xs, ys - def convertMeters2LatLong(xs, ys, centroid, latlong_crs, target_crs, mesh=False): '''Input xs and ys need to be in the target CRS Xs and Ys need to be in pairs, i.e. the first entry to xs and the @@ -275,7 +266,6 @@ def getMapBathymetry(gebcofilename): return longs, lats, depths, ncols, nrows - def convertBathymetry2Meters(longs, lats, depths, centroid, centroid_utm, latlong_crs, target_crs, ncols, nrows, xs=[], ys=[]): @@ -329,8 +319,6 @@ def convertBathymetry2Meters(longs, lats, depths, centroid, centroid_utm, return bathXs, bathYs, bath_depths - - def writeBathymetryFile(moorpy_bathymetry_filename, bathXs, bathYs, bath_depths, soil=False): '''Write a MoorDyn/MoorPy-style bathymetry text file based on provided x and y grid line values and a 2D array of depth values.''' @@ -366,7 +354,6 @@ def writeBathymetryFile(moorpy_bathymetry_filename, bathXs, bathYs, bath_depths, f.close() - def getLeaseAndBathymetryInfo(lease_name, bathymetry_file, bath_ncols=100, bath_nrows=100, write_bathymetry=True): # initialize the conventional lat/long CRS @@ -379,7 +366,8 @@ def getLeaseAndBathymetryInfo(lease_name, bathymetry_file, bath_ncols=100, bath_ custom_crs = getCustomCRS(centroid[0], centroid[1]) # convert the lease boundary to meters - lease_xs, lease_ys, centroid_utm = convertLatLong2Meters(lease_longs, lease_lats, centroid, latlong_crs, custom_crs, return_centroid=True) + lease_xs, lease_ys, centroid_utm = convertLatLong2Meters(lease_longs, lease_lats, centroid, + latlong_crs, custom_crs, return_centroid=True) if write_bathymetry: # get bathymetry information from a GEBCO file (or other) @@ -545,8 +533,6 @@ def getSoilType(x, y, centroid, latlong_crs, custom_crs, soil_file): return soil_type - - def getSoilGrid(centroid, latlong_crs, custom_crs, soil_file, nrows=100, ncols=100, xbound=None, ybound=None): """Note: can make the outer shapely shape have 'holes' of the inner shapely shapes""" @@ -592,6 +578,7 @@ def getSoilGrid(centroid, latlong_crs, custom_crs, soil_file, nrows=100, ncols=1 ys = np.linspace(ybound[0], ybound[-1], nrows) else: ys = np.linspace( np.min([np.min(soil_ys[i]) for i in range(len(soil_shapes))]), np.max([np.max(soil_ys[i]) for i in range(len(soil_shapes))]), nrows) + soil_grid = np.zeros([len(ys), len(xs)]) # for each manmade grid point, loop through all the polygons and determine whether that grid point is within the shape or not @@ -613,13 +600,10 @@ def getSoilGrid(centroid, latlong_crs, custom_crs, soil_file, nrows=100, ncols=1 soil_grid = np.array(soil_grid_list) # saving to list and then changing to np.array because I couldn't figure out how else to do it with strings return xs, ys, soil_grid - - - if __name__ == '__main__': """ @@ -661,7 +645,7 @@ def getSoilGrid(centroid, latlong_crs, custom_crs, soil_file, nrows=100, ncols=1 # get bathymetry information from a GEBCO file (or other) bath_longs, bath_lats, bath_depths, ncols, nrows = getMapBathymetry('bathymetry/gebco_2023_n41.3196_s40.3857_w-125.2881_e-123.9642.asc') # convert bathymetry to meters - ncols = 500 + ncols = 500C:/Users/fmoreno/Downloads/GEBCO_25_Jun_2025_3c682d73375c/GEBCO_25_Jun_2025_3c682d73375c/gebco_2024_n44.2_s44.0_w12.5_e12.8.asc nrows = 500 bath_xs, bath_ys, bath_depths = convertBathymetry2Meters(bath_longs, bath_lats, bath_depths, centroid, centroid_utm, latlong_crs, custom_crs, ncols, nrows) # export to MoorPy-readable file @@ -677,12 +661,75 @@ def getSoilGrid(centroid, latlong_crs, custom_crs, soil_file, nrows=100, ncols=1 __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) lease_name = 'GulfofMaine_ResearchArray' gebco_file = __location__+'\\..\\geography\\gebco_2024_n44.1458_s41.4761_w-70.9497_e-66.2146.asc' - info = getLeaseAndBathymetryInfo(lease_name, bathymetry_file) + info = getLeaseAndBathymetryInfo(lease_name, gebco_file) + + x_center = np.mean(info['lease_xs']) + y_center = np.mean(info['lease_ys']) + + zoom = 8000 + + + xbounds = [x_center - zoom, x_center + zoom] + ybounds = [y_center - zoom, y_center + zoom] + + fig, ax = plot3d(info['lease_xs'], info['lease_ys'], 'bathymetry_100x100.txt', + area_on_bath=True, args_bath={'cmap': 'gist_earth', 'zlim': [-500, 50]}, + xbounds=xbounds, ybounds=ybounds) + + plt.show() + + # Load bathymetry data manually + with open('GulfOfMaine_bathymetry_100x100.txt', 'r') as f: + lines = f.readlines() + + nGridX = int(lines[1].split()[1]) + nGridY = int(lines[2].split()[1]) + x_vals = np.array([float(val) for val in lines[3].split()]) + y_vals = [] + z_matrix = [] + + for line in lines[4:4+nGridY]: + parts = line.split() + y_vals.append(float(parts[0])) + z_matrix.append([float(z) for z in parts[1:]]) + + + # Extract y and z + z_vals = np.array(z_matrix) + y_vals = np.array(y_vals) + + + # Now crop using xbounds and ybounds + xmask = (x_vals >= xbounds[0]) & (x_vals <= xbounds[1]) + ymask = (y_vals >= ybounds[0]) & (y_vals <= ybounds[1]) + + x_crop = x_vals[xmask] + y_crop = y_vals[ymask] + z_crop = z_vals[ymask][:, xmask] + + # Plot manually using Axes3D + X, Y = np.meshgrid(x_crop, y_crop) + fig = plt.figure() + ax = fig.add_subplot(111, projection='3d') + ax.plot_surface(X, Y, z_crop, cmap='gist_earth') + ax.set_title('Zoomed Bathymetry') + + lease_xs = info['lease_xs'] + lease_ys = info['lease_ys'] + ax.plot(lease_xs, lease_ys, zs=200, zdir='z', color='r', linewidth=2, label='Lease Area') + ax.legend() plt.show() - a = 2 + + + # plot3d(info['lease_xs'], info['lease_ys'], 'bathymetry_100x100.txt', area_on_bath=False, args_bath={'zlim':[-3000, 500], 'cmap': 'gist_earth'}) + # xbounds=(info['bath_xs'].min(), info['bath_xs'].min()), + # ybounds=(info['bath_ys'].min(), info['bath_ys'].min()), + # zbounds=(info['bath_depths'].min(), info['bath_depths'].min()) + + diff --git a/famodel/project.py b/famodel/project.py index d4f846cc..234c3880 100644 --- a/famodel/project.py +++ b/famodel/project.py @@ -1157,7 +1157,6 @@ def seabedIntersect(self, r, u): return r_i - def projectAlongSeabed(self, x, y): '''Project a set of x-y coordinates along a seabed surface (grid), returning the corresponding z coordinates.''' @@ -1177,206 +1176,207 @@ def projectAlongSeabed(self, x, y): return z - - # METHODS TO USE WITH ANCHOR TOOLS - - def loadSoil(self, filename=None, yaml=None): + def loadSoil(self, filename=None, yaml=None, soil_mode='uniform', profile_source=None): ''' - Load geoetechnical information from an input file (format TBD), convert to - a rectangular grid, and save the grid to the floating array object (TBD). - - The input file should provide rows with the following entries: - - x coordinate - - y coordinate - - class - soil classification name ('clay', 'sand', or 'rock' with optional modifiers) - - gamma* - soil effective unit weight [kPa] (all soils) - - Su0* - undrained shear strength at mudline [kPa] (clay - - K* - undrained shear strength gradient [kPa/m] (clay - - alpha* - soil skin friction coefficient [-] (clay soils) - - phi* - angle of internal friction [deg] (sand soils) - - Some (*) parameters are optional depending on the soil class and mode. + Load geotechnical information from input file or YAML. + Supports two soil modes: 'uniform' and 'layered'. - Irregular sampling points will be supported and interpolated to a - rectangular grid. - - Paramaters + Parameters ---------- - filename : path - path/name of file containing soil data + filename : str, optional + Path to .txt/.dat file with soil labels/profile IDs and coordinates + yaml : dict, optional + Dictionary containing soil data and properties (used when filename is None) + soil_mode : str + Either 'uniform' or 'layered' + profile_source : str, optional + Path to YAML file with layered profile definitions (only used if soil_mode='layered') ''' xs = None ys = None soil_names = None - if filename is not None: # if the filename option was selected, then that means there is at least a grid in the file, and maybe soil type information - if filename[-3:]=='shp': - raise ValueError("Geography-related operations not directly supported in Project class") - - elif filename[-3:]=='txt' or filename[-3:]=='dat': + soilProps = None - # load in the grid portion of the soil input file - xs, ys, soil_names = sbt.readBathymetryFile(filename, dtype=str) # read MoorDyn-style file + # Case 1: File input (grid + properties) + if filename is not None: + if filename.endswith('.shp'): + raise ValueError("Shapefiles not supported in Project class") - soilProps = sbt.getSoilTypes(filename) # load in the soil property information (if there is any) - - # regardless of whether there is soil type information in the file, if there is soil information in the yaml, read that in - if yaml: - soilProps = yaml['soil_types'] # if there is a yaml file as input, load in the soil props that way (overwrites the other one) + elif filename.endswith('.txt') or filename.endswith('.dat'): + # Load label/profile_id grid + xs, ys, soil_names = sbt.readBathymetryFile(filename, dtype=str) + + # Load soil properties + soilProps = sbt.getSoilTypes(filename, soil_mode=soil_mode, profile_source=profile_source) + if yaml: + soilProps = yaml.get('soil_types', soilProps) # allow overwriting via YAML - elif filename is None: # if the filename option was not selected - if yaml: # and if there was a yaml option selected, simply read in that yaml information + # Case 2: YAML only (no filename) + elif filename is None: + if yaml: xs = yaml['x'] ys = yaml['y'] soil_names = yaml['type_array'] - soilProps = yaml['soil_types'] - else: # but if there was no yaml option selected (and no file option selected) -> set default values - print('Warning: No soil grid nor soil properties were selected, but this function ran -> use preprogrammed default values') + raw_soil_types = yaml['soil_types'] + + # Ensure all soil types have a 'layers' field + soilProps = {} + for key, entry in raw_soil_types.items(): + if 'layers' in entry: + soilProps[key] = entry + else: + # Wrap old flat format into single-layer profile (optional fallback) + layer = dict(entry) + layer.setdefault('top', 0) + layer.setdefault('bottom', 50) + layer.setdefault('soil_type', key) + soilProps[key] = {'layers': [layer]} + else: + print('[Warning] No soil input provided — using default values') xs = [0] ys = [0] - soil_names = ['mud'] - soilProps = dict(mud={'Su0':[2.39], 'k':[1.41], 'gamma':[10], 'depth':[0]}, - rock={'UCS':[5], 'Em':[7], 'depth':[0]}) - + soil_names = [['mud']] # note: should be 2D to match grid structure + soilProps = { + 'mud': {'layers': [{ + 'soil_type': 'clay', + 'top': 0, 'bottom': 50, + 'gamma_top': 10, 'gamma_bot': 10, + 'Su_top': 2.39, 'Su_bot': 59.39 + }]}, + 'rock': {'layers': [{ + 'soil_type': 'rock', + 'top': 0, 'bottom': 50, + 'UCS_top': 5, 'UCS_bot': 5, + 'Em_top': 7, 'Em_bot': 7 + }]} + } + + else: - raise ValueError("Something is wrong") - - ''' - # check that correct soil properties are being provided for the different soil types - for soil in soilProps: - if 'rock' in soil or 'hard' in soil: - if not 'UCS' in soilProps[soil] or not 'Em' in soilProps[soil]: - raise ValueError('Rock soil type requires UCS and Em values') - elif 'sand' in soil: - if not 'phi' in soilProps[soil] or not 'gamma' in soilProps[soil]: - raise ValueError('Sand soil type requires phi and gamma values') - elif 'clay' in soil: - if not 'Su0' in soilProps[soil] or not 'k' in soilProps[soil]: - raise ValueError('Clay soil type requires Su0 and k values') - elif 'mud' in soil or 'mud_soft': - if not 'Su0' in soilProps[soil] or not 'k' in soilProps[soil]: - raise ValueError('Mud soil type requires Su0 and k values') - else: - raise ValueError(f'Soil type {soil} not recognized. Soil type key must contain one of the following keywords: rock, sand, clay, mud') - ''' - - # make sure the soilProps dictionary has all the required information (should be updated later with exact properties based on anchor capacity functions) - # setting each soil type dictionary with all the values, just in case they need them for whatever reason - here are the default values - # the default types (and values) are set if there is no other information provided - for key,props in soilProps.items(): - props['Su0'] = getFromDict(props, 'Su0' , shape=-1, dtype=list, default=[2.39], index=None) - props['k'] = getFromDict(props, 'k' , shape=-1, dtype=list, default=[1.41], index=None) - props['alpha'] = getFromDict(props, 'alpha', shape=-1, dtype=list, default=[0.7] , index=None) - props['gamma'] = getFromDict(props, 'gamma', shape=-1, dtype=list, default=[4.7] , index=None) - props['phi'] = getFromDict(props, 'phi' , shape=-1, dtype=list, default=[0.0] , index=None) - props['UCS'] = getFromDict(props, 'UCS' , shape=-1, dtype=list, default=[7.0] , index=None) - props['Em'] = getFromDict(props, 'Em' , shape=-1, dtype=list, default=[50.0], index=None) - - for k,prop in props.items(): - if 'array' in type(prop).__name__: - # clean up property type - props[k] = np.array(prop) - - + raise ValueError("Invalid combination of filename/yaml inputs") + + # --- Set defaults only for uniform mode --- + if soil_mode == 'uniform': + for key, props in soilProps.items(): + props['Su0'] = getFromDict(props, 'Su0', shape=-1, dtype=list, default=[2.39]) + props['k'] = getFromDict(props, 'k', shape=-1, dtype=list, default=[1.41]) + props['alpha'] = getFromDict(props, 'alpha', shape=-1, dtype=list, default=[0.7]) + props['gamma'] = getFromDict(props, 'gamma', shape=-1, dtype=list, default=[8.7]) + props['phi'] = getFromDict(props, 'phi', shape=-1, dtype=list, default=[0.0]) + props['UCS'] = getFromDict(props, 'UCS', shape=-1, dtype=list, default=[7.0]) + props['Em'] = getFromDict(props, 'Em', shape=-1, dtype=list, default=[50.0]) + + # ensure no array-like leftovers + for k, prop in props.items(): + if hasattr(prop, '__array__'): + props[k] = np.array(prop) + + # --- Store to project --- self.soilProps = soilProps - - - if xs is not None: self.soil_x = np.array(xs) self.soil_y = np.array(ys) self.soil_names = np.array(soil_names) - - - # update soil info for anchor if needed + + self.soil_mode = soil_mode + print(f"Loaded soilProps keys: {list(soilProps.keys())}") + + # --- Update anchor objects if available --- if self.anchorList: - for anch in self.anchorList.values(): - name, props = self.getSoilAtLocation(anch.r[0],anch.r[1]) - anch.soilProps = {name:props} - - # load data from file - - # interpolate onto grid defined by grid_x, grid_y - - # save - ''' - self.soil_class - self.soil_gamma - self.soil_Su0 - self.soil_K - self.soil_alpha - self.soil_phi - ''' - pass - + for anchor in self.anchorList.values(): + name, props = self.getSoilAtLocation(anchor.r[0], anchor.r[1]) + anchor.soilProps = {name: props} def getSoilAtLocation(self, x, y): ''' - Interpolate soil properties at specified location from the soil - properties grid and return a dictionary of soil properties that - can be used in anchor capacity calculations. - - Parameters - ---------- - x : float - x coordinate in array reference frame [m]. - y : float - y coordinate in array reference frame [m]. + Retrieve the soil information at a specific location, supporting both uniform and layered modes. Returns - ------- - soilProps : dictionary - Dictionary of standard MoorPy soil properties. + ------- + (str, dict or list): soil name or profile ID, and associated soil properties or layered profile ''' - - # NEW: finds the specific soil grid point that the xy point is closest to and assigns it that soil type if self.soil_x is not None: - ix = np.argmin([abs(x-soil_x) for soil_x in self.soil_x]) - iy = np.argmin([abs(y-soil_y) for soil_y in self.soil_y]) - - soil_name = self.soil_names[iy, ix] - - soil_info = self.soilProps[soil_name] - - return soil_name, soil_info + ix = np.argmin([abs(x - sx) for sx in self.soil_x]) + iy = np.argmin([abs(y - sy) for sy in self.soil_y]) + soil_id = self.soil_names[iy, ix] # could be label or profile_id + + if self.soil_mode == 'uniform': + soil_info = self.soilProps[soil_id] + return soil_id, soil_info + + elif self.soil_mode == 'layered': + profile_layers = self.soilProps[soil_id] # list of layer dicts + return soil_id, profile_layers + + else: + raise ValueError(f"Unknown soil_mode: {self.soil_mode}") + + print(f"[DEBUG] soil_id at location ({x}, {y}) is: {soil_id}") + print(f"[DEBUG] Available soilProps keys: {list(self.soilProps.keys())}") else: - pass - - ''' - # SIMPLE HACK FOR NOW - rocky, _,_,_,_ = sbt.interpFromGrid(x, y, self.soil_x, self.soil_y, self.soil_rocky) - - return rocky + raise ValueError("No soil grid defined") + + def convertUniformToLayered(self, default_layer=50.0): ''' + Converts self.soilProps (uniform format) into profile_map (layered format) + using a default thickness and assuming uniform clay profile. + Matches the structure of layered CPT-based soil profiles. ''' - soilProps = {} - - - if self.seabed_type == 'clay': + self.profile_map = {} + + for name, props in self.soilProps.items(): + name = str(name) + gamma = float(props['gamma'][0]) + Su0 = float(props['Su0'][0]) + k = float(props['k'][0]) + + layer = { + 'soil_type': 'clay', + 'top': 0.0, + 'bottom': default_layer, + 'gamma_top': gamma, + 'gamma_bot': gamma, + 'Su_top': Su0, + 'Su_bot': Su0 + k * default_layer} + + self.profile_map[name] = [layer] # just layers! - soilProps['class'] = 'clay' - soilProps['gamma'] = interp2d(x, y, self.seabed_x, self.seabed_y, self.soil_gamma) - soilProps['Su0' ] = interp2d(x, y, self.seabed_x, self.seabed_y, self.soil_Su0 ) - soilProps['k' ] = interp2d(x, y, self.seabed_x, self.seabed_y, self.soil_k ) - soilProps['alpha'] = interp2d(x, y, self.seabed_x, self.seabed_y, self.soil_alpha) - soilProps['phi' ] = None - - elif self.seabed_type == 'sand': - soilProps['class'] = 'sand' - soilProps['gamma'] = interp2d(x, y, self.seabed_x, self.seabed_y, self.soil_gamma) - soilProps['Su0' ] = None - soilProps['k' ] = None - soilProps['alpha'] = None - soilProps['phi' ] = interp2d(x, y, self.seabed_x, self.seabed_y, self.soil_phi ) - - # note: for sand, can assume homogeneous angle of internal fricton - else: - raise ValueError(f"Unsupported seabed type '{self.seabed_type}'.") - - return soilProps + def convertLayeredToUniform(self): ''' + Converts self.profile_map (layered format) into soilProps (uniform format) + assuming a single clay layer with linear Su(z) = Su0 + k*z. + Matches the structure expected by uniform soil models. + ''' + self.soilProps = {} + + for name, layers in self.profile_map.items(): + if not layers or len(layers) != 1: + raise ValueError('convertLayeredToUniform only supports a single-layer profile') + + layer = layers[0] + if str(layer.get('soil_type', '')).lower() != 'clay': + raise ValueError('convertLayeredToUniform only supports clay') + + top = float(layer['top']) + bot = float(layer['bottom']) + Su_top = float(layer['Su_top']) + Su_bot = float(layer['Su_bot']) + gamma = float(layer['gamma_top']) # gamma_top == gamma_bot in your format + + if bot <= top: + raise ValueError('Invalid layer thickness (bottom <= top)') + + thickness = bot - top + k = (Su_bot - Su_top)/thickness + Su0 = Su_top - k*top + + self.soilProps[name] = { + 'gamma': [gamma], + 'Su0': [Su0], + 'k': [k]} # # ----- Anchor def updateAnchor(self,anch='all',update_loc=True): @@ -1407,39 +1407,20 @@ def updateAnchor(self,anch='all',update_loc=True): name, props = self.getSoilAtLocation(x,y) # update soil anchor.soilProps = {name:props} - - - # def calcAnchorCapacity(self, anchor): - # '''Compute holding capacity of a given anchor based on the soil - # info at its position. The anchor object's anchor properties and - # location will be used to determine the holding capacity, which - # will be saved to the anchor object. - - # Parameters - # ---------- - # anchor : MoorPy Anchor object (derived from Point) - # The anchor object in question. - # ''' - - # # interpolate soil properties/class based on anchor position - # anchor.soilProps = self.getSoilAtLocation(anchor.r[0], anchor.r[1]) - - # # fill in generic anchor properties if anchor info not provided - # if not type(anchor.anchorProps) == dict: - # anchor.anchorProps = dict(type='suction', diameter=6, length=12) - - # # apply anchor capacity model - # capacity, info = anchorCapacity(anchorProps, soilProps) - - # # save all information to the anchor (attributes of the Point) - # anchor.soilProps = soilProps - # anchor.anchorCapacity = capacity - # anchor.anchorInfo = info - - # # also return it - # return capacity - + def setSoilAtLocation(self, anchor): + name, props = self.getSoilAtLocation(anchor.r[0], anchor.r[1]) + + # Add required metadata + layer = dict(props) # shallow copy of props + layer['soil_type'] = name # or force to 'clay'/'rock' if needed + layer['top'] = props.get('top', 0) + layer['bottom'] = props.get('bottom', 50) + # Wrap in expected profile_map format + profile_map = [{'name': name, 'layers': [layer]}] + anchor.setSoilProfile(profile_map) + + def setCableLayout(self): # 2-D diff --git a/famodel/seabed_tools.py b/famodel/seabed_tools.py index 6baeffb6..afeb868e 100644 --- a/famodel/seabed_tools.py +++ b/famodel/seabed_tools.py @@ -4,6 +4,7 @@ import os import matplotlib.pyplot as plt import numpy as np +import yaml @@ -43,31 +44,77 @@ def readBathymetryFile(filename, dtype=float): return bathGrid_Xs, bathGrid_Ys, bathGrid -def getSoilTypes(filename): - '''function to read in a preliminary input text file format of soil type information''' +def getSoilTypes(filename, soil_mode='layered', profile_source=None): + ''' + Load soil properties or layered profiles depending on soil_mode. + Parameters + ---------- + filename : str + Path to .txt file containing grid and profile/soil label definitions + soil_mode : str + 'uniform' or 'layered' + profile_source : str or None + Path to YAML file with layered soil profiles (used only for 'layered') + + Returns + ------- + soilProps : dict + Dictionary of soil type properties (uniform) or layered profiles (layered) + ''' soilProps = {} + used_labels = [] - f = open(filename, 'r') - - for line in f: - if line.count('---') > 0 and (line.upper().count('SOIL TYPES') > 0): - line = next(f) # skip this header line, plus channel names and units lines - var_names = line.split() - line = next(f) - line = next(f) - while line.count('---') == 0: - entries = line.split() - soilProps[entries[0]] = {} - for iv,var in enumerate(var_names[1:]): - # convert entries to strings unless there is - if entries[iv+1] == '-': - soilProps[entries[0]][var] = [0] - else: - soilProps[entries[0]][var] = [float(entries[iv+1])] - line = next(f) - - f.close() + with open(filename, 'r') as f: + lines = f.readlines() + + for i, line in enumerate(lines): + if line.strip().startswith('---') and 'SOIL TYPES' in line.upper(): + break + + # Extract used labels from the SOIL TYPES section + for line in lines[i+3:]: + if '---' in line: + break + entries = line.strip().split() + label = entries[0] + used_labels.append(label); print(label) + + if soil_mode == 'uniform': + var_names = lines[i+1].split() + for line in lines[i+3:]: + if '---' in line: + break + entries = line.strip().split() + label = entries[0] + soilProps[label] = {} + for iv, var in enumerate(var_names[1:]): + val = entries[iv+1] + soilProps[label][var] = [float(val)] if val != '-' else [0.0] + + elif soil_mode == 'layered': + if profile_source is None: + raise ValueError("profile_source (path to YAML) is required for layered mode.") + + # Load the full YAML file of profiles + with open(profile_source, 'r') as f: + all_profiles = yaml.safe_load(f) + + # Reassign each label to the actual layer list directly + for label in used_labels: + if label not in all_profiles: + raise KeyError(f'Profile ID {label} not found in YAML: {profile_source}') + soilProps[label] = all_profiles[label]['layers'] # now a list of layer dicts + + print(f"[DEBUG] Loaded profiles from YAML: {list(soilProps.keys())}") + if used_labels: + print(f"[DEBUG] Example layers for {used_labels[0]}: {soilProps[used_labels[0]]}") + else: + print("[WARNING] No profile labels were found in the soil grid.") + + + else: + raise ValueError(f"Unrecognized soil_mode '{soil_mode}'") return soilProps diff --git a/tests/mooring_ontology.yaml b/tests/mooring_ontology.yaml index aa06dd1d..f5da3059 100644 --- a/tests/mooring_ontology.yaml +++ b/tests/mooring_ontology.yaml @@ -152,7 +152,7 @@ mooring_connector_types: # Anchor type properties anchor_types: suction_pile1: - type : suction_pile + type : suction L : 16.4 # length of pile [m] D : 5.45 # diameter of pile [m] zlug : 9.32 # embedded depth of padeye [m] \ No newline at end of file diff --git a/tests/mooring_ontology_parallels.yaml b/tests/mooring_ontology_parallels.yaml index e98647ae..92794cd7 100644 --- a/tests/mooring_ontology_parallels.yaml +++ b/tests/mooring_ontology_parallels.yaml @@ -170,7 +170,7 @@ mooring_connector_types: # Anchor type properties anchor_types: suction_pile1: - type : suction_pile + type : suction L : 16.4 # length of pile [m] D : 5.45 # diameter of pile [m] zlug : 9.32 # embedded depth of padeye [m] \ No newline at end of file diff --git a/tests/platform_ontology.yaml b/tests/platform_ontology.yaml index f43a97a9..be7dd26b 100644 --- a/tests/platform_ontology.yaml +++ b/tests/platform_ontology.yaml @@ -1239,7 +1239,7 @@ mooring_line_types: # Anchor type properties anchor_types: suction_pile1: - type : suction_pile + type : suction L : 16.4 # length of pile [m] D : 5.45 # diameter of pile [m] zlug : 9.32 # embedded depth of padeye [m] \ No newline at end of file diff --git a/tests/simple_farm.yaml b/tests/simple_farm.yaml index c05945de..db5a46e4 100644 --- a/tests/simple_farm.yaml +++ b/tests/simple_farm.yaml @@ -1166,7 +1166,7 @@ platform: rB : [ 0, 0, 15] # [m] and B coordinates shape : circ # [-] circular or rectangular gamma : 0.0 # [deg] twist angle about the member's z-axis - potMod : True # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory # --- outer shell including hydro--- stations : [0, 1] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB d : 10.0 # [m] diameters if circular or side lengths if rectangular (can be pairs) @@ -1189,7 +1189,7 @@ platform: heading : [ 60, 180, 300] # [deg] heading rotation of column about z axis (for repeated members) shape : circ # [-] circular or rectangular gamma : 0.0 # [deg] twist angle about the member's z-axis - potMod : True # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory # --- outer shell including hydro--- stations : [0, 35] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB d : 12.5 # [m] diameters if circular or side lengths if rectangular (can be pairs) diff --git a/tests/testOntology.yaml b/tests/testOntology.yaml index 2c1eb1d0..5f645bb9 100644 --- a/tests/testOntology.yaml +++ b/tests/testOntology.yaml @@ -32,27 +32,53 @@ site: file: #'../bathymetry200m_sample.txt' seabed: - x : [-1901, 0, 1900] - y : [-1900, 2, 1900 ] + x : [-1901, 0, 1900 ] + y : [-1900, 2, 1900 ] type_array: - [mud_soft , mud_firm , mud_soft] - - [mud_soft , mud_soft , mud_soft] + - [mud_soft , mud_soft , mud_soft] - [mud_soft , mud_firm , mud_soft] - - soil_types: # dictionary-based approach - mud_soft: - Su0 : [2.39] # [kPa] - k : [1.41] # [kPa/m] - depth: [0] # [m] - mud_firm: - Su0 : [23.94] # [kPa] - k : [2.67] # [kPa/m] - depth: [0] # [m] - rock: - UCS : [7] # [MPa] - Em : [50] # [MPa] - depth: [0] # [m] + + soil_types: + mud_soft: + layers: + - soil_type: clay + top: 0 + bottom: 50 + gamma_top: 10.0 + gamma_bot: 10.0 + Su_top: 2.39 + Su_bot: 59.39 + mud_firm: + layers: + - soil_type: clay + top: 0 + bottom: 50 + gamma_top: 10.0 + gamma_bot: 50.0 + Su_top: 23.4 + Su_bot: 157.44 + sand: + layers: + - soil_type: sand + top: 1 + bottom: 50 + gamma_top: 8.5 + gamma_bot: 8.5 + phi_top: 28.0 + phi_bot: 32.00 + Dr_top: 50.0 + Dr_bot: 85.00 + weak_rock: + layers: + - soil_type: rock + top: 0 + bottom: 50 + UCS_top: 5.0 + UCS_bot: 5.0 + Em_top: 7.0 + Em_bot: 7.0 metocean: extremes: # extreme values for specified return periods (in years) @@ -82,7 +108,7 @@ site: - [ 10.5, 0, 0.01, operating, 0, JONSWAP, 12, 6, 0 ] RAFT_settings: - min_freq : 0.001 # [Hz] lowest frequency to consider, also the frequency bin width + min_freq : 0.001 # [Hz] lowest frequency to consider, also the frequency bin width max_freq : 0.10 # [Hz] highest frequency to consider XiStart : 0 # sets initial amplitude of each DOF for all frequencies nIter : 4 # sets how many iterations to perform in Model.solveDynamics() @@ -1220,7 +1246,7 @@ platforms: rB : [ 0, 0, 15] # [m] and B coordinates shape : circ # [-] circular or rectangular gamma : 0.0 # [deg] twist angle about the member's z-axis - potMod : True # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory # --- outer shell including hydro--- stations : [0, 1] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB d : 10.0 # [m] diameters if circular or side lengths if rectangular (can be pairs) @@ -1243,7 +1269,7 @@ platforms: heading : [ 60, 180, 300] # [deg] heading rotation of column about z axis (for repeated members) shape : circ # [-] circular or rectangular gamma : 0.0 # [deg] twist angle about the member's z-axis - potMod : True # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory + potMod : False # [bool] Whether to model the member with potential flow (BEM model) plus viscous drag or purely strip theory # --- outer shell including hydro--- stations : [0, 35] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB d : 12.5 # [m] diameters if circular or side lengths if rectangular (can be pairs) @@ -1492,17 +1518,17 @@ mooring_connector_types: # Anchor type properties anchor_types: suction_pile1: - type : suction_pile + type : suction L : 16.4 # length of pile [m] D : 5.45 # diameter of pile [m] zlug : 9.32 # embedded depth of padeye [m] d-g_pile1: - type : dandg_pile + type : dandg L : 50 # length of pile [m] D : 3 # diameter of pile [m] zlug : 0 # embedded depth [m] driven_pile1: - type : driven_pile + type : driven L : 20 # pile length [m] D : 1.5 # pile diameter [m] zlug : 3 # embedded depth [m @@ -1512,14 +1538,14 @@ anchor_types: zlug : 10 #beta: 30 torpedo_pile1: - type: torpedo_pile + type: torpedo D1 : 3 D2: 1.1 L1: 10 L2: 4 zlug: 16 helical_pile1: - type: helical_pile + type: helical L : 25.1 d : 1 D : 5.01 diff --git a/tests/test_anchors.py b/tests/test_anchors.py index ae177770..d97e57c2 100644 --- a/tests/test_anchors.py +++ b/tests/test_anchors.py @@ -5,6 +5,20 @@ import matplotlib.pyplot as plt import pytest +# --- Helper goes at module level --- +def assign_soil(anchor, soil_label, project): + soil_def = project.soilProps[soil_label] + layers = soil_def['layers'] + # print('[DEBUG] assign_soil: soil_label =', soil_label) + # print('[DEBUG] assign_soil: soil_def =', soil_def) + profile_map = [{ + 'name': 'CPT_Assigned', + 'x': 0, 'y': 0, + 'layers': layers}] + + anchor.setSoilProfile(profile_map) + anchor.profile_name = 'CPT_Assigned' + @pytest.fixture def project(): dir = os.path.dirname(os.path.realpath(__file__)) @@ -14,91 +28,135 @@ def test_anchor_loads(project): # load in famodel project project.getMoorPyArray(cables=1) anch = project.anchorList['FOWT1a'] + + assign_soil(anch, 'mud_soft', project) - # get lug loads on anchor - anch.getLugForces(plot=False) + # Force calculation + anch.getMudlineForces(max_force=False) - assert('Ha' in anch.loads) - assert('Hm' in anch.loads) - assert(anch.loads['Ha'] != anch.loads['Hm']) + # Extract mudline loads + Hm = anch.loads.get('Hm') + Vm = anch.loads.get('Vm') + zlug = anch.dd['design']['zlug'] + + # Compute lug loads + _, Ha, Va = anch.getLugForces(Hm, Vm, zlug, plot=False) + anch.loads['Ha'] = Ha + anch.loads['Va'] = Va + # Assertions + assert 'Ha' in anch.loads + assert 'Hm' in anch.loads + assert anch.loads['Ha'] != anch.loads['Hm'] + def test_anchor_capacities(project): # load in famodel project (suction pile anchor) project.getMoorPyArray(cables=1) anch = project.anchorList['FOWT1a'] + + assign_soil(anch, 'mud_firm', project) # fill in load dictionary to skip watch circle run - loads = {'Ha':4522222,'Va':3948278} + loads = {'Ha':4.5e6, 'Va':1.9e6} # get capacity and safety factor - anch.getAnchorCapacity(loads=loads, plot=False) - anch.getFS(loads=loads) - - # try suction pile with sand - soil = anch.soilProps - soil['sand'] = soil.pop(next(iter(soil.keys()))) - soil['sand']['phi'] = 33 - soil['sand']['Dr'] = 50 + Ha = loads['Ha'] + Va = loads['Va'] + zlug = anch.dd['design']['zlug'] + anch.getCapacityAnchor(Ha, Va, zlug=zlug, plot=False) + anch.getSafetyFactor() + + # try SUCTION PILE with sand + assign_soil(anch, 'sand', project) # get capacity and safety factor - anch.getAnchorCapacity(loads=loads, plot=False) - anch.getFS(loads=loads) - - # check plate anchor type - newdd = anch.dd - newdd['type'] = 'plate' - newdd['design'] = {'type':'plate','A':20,'zlug':10,'beta':10} - anch.soilProps['clay'] = anch.soilProps.pop('sand') - # new loads - loads['Ha'] = 1000000 + Ha = loads['Ha'] + Va = loads['Va'] + zlug = anch.dd['design']['zlug'] + anch.getCapacityAnchor(Ha, Va, zlug=zlug, plot=False) + anch.getSafetyFactor() + + # check PLATE ANCHOR type + anch.dd['type'] = 'plate' + anch.dd['design'] = {'B':5, 'L':2, 'zlug':10, 'beta':10} + assign_soil(anch, 'mud_soft', project) + # new horizontal load + loads['Ha'] = 2e6 loads['Va'] = 0 + Ha = loads['Ha'] + Va = loads['Va'] + zlug = anch.dd['design']['zlug'] # get capacity and safety factor - anch.getAnchorCapacity(loads=loads, plot=False) - anch.getFS(loads=loads) - - # check drilled and grouted anchor type (need to change material to rock) - loads = {'Ha':4522222,'Va':3948278} # go back to original loads - newdd['type'] = 'dandg_pile' - newdd['design'] = {'type':'dandg_pile','L':50,'D':3,'zlug':0} - soil['rock'] = soil.pop('clay') # soil_properties has default rock info in there already, just change name - anch.getAnchorCapacity(loads=loads, plot=False) - anch.getFS(loads=loads) - - # check driven pile anchor in rock and clay - newdd['type'] = 'driven' - soil['weak_rock'] = soil.pop('rock') - newdd['design'] = {'type':'driven','L':20,'D':1.5,'zlug':-3} - anch.getAnchorCapacity(loads=loads, plot=False) - anch.getFS(loads=loads) - - soil['clay'] = soil.pop('weak_rock') - newdd['design'] = {'type':'driven','L':30,'D':2,'zlug':3} - anch.getAnchorCapacity(loads=loads, plot=False) - anch.getFS(loads=loads) - - soil['sand'] = soil.pop('clay') - anch.getAnchorCapacity(loads=loads, plot=False) - anch.getFS(loads=loads) - soil['sand']['Dr'] = 50 - - # check helical pile anchor with sand - newdd['type'] = 'helical_pile' - newdd['design'] = {'type':'helical_pile','L':25.1,'d':1,'D':5.01,'zlug':5} - anch.getAnchorCapacity(loads=loads, plot=False) - anch.getFS(loads=loads) - - # check helical pile anchor with clay - soil['clay'] = soil.pop('sand') - newdd['type'] = 'helical_pile' - newdd['design'] = {'type':'helical_pile','L':25.1,'d':1,'D':5.01,'zlug':5} - anch.getAnchorCapacity(loads=loads, plot=False) - anch.getFS(loads=loads) - - # check torpedo anchor - newdd['type'] = 'torpedo_pile' - newdd['design'] = {'type':'torpedo_pile','D1':3,'D2':1.1,'L1':10,'L2':4,'zlug':16} - anch.getAnchorCapacity(loads=loads, plot=False) - anch.getFS(loads=loads) - + anch.getCapacityAnchor(Ha, Va, zlug=zlug, plot=False) + anch.getSafetyFactor() + + # check DRILLED & GROUTED PILE (need to change material to rock) + loads = {'Ha':4.5e5, 'Va':1.9e5} # again assign new loads + anch.dd['type'] = 'drilled' + anch.dd['design'] = {'L':10, 'D':3, 'zlug':0} + assign_soil(anch, 'weak_rock', project) + Ha = loads['Ha'] + Va = loads['Va'] + zlug = anch.dd['design']['zlug'] + anch.getCapacityAnchor(Ha, Va, zlug=zlug, plot=False) + anch.getSafetyFactor() + + # check DRIVEN PILES in soils and rock + anch.dd['type'] = 'driven' + anch.dd['design'] = {'L':20, 'D':1.5, 'zlug': 3} + assign_soil(anch, 'mud_firm', project) + Ha = loads['Ha'] + Va = loads['Va'] + zlug = anch.dd['design']['zlug'] + anch.getCapacityAnchor(Ha, Va, zlug=zlug, plot=False) + anch.getSafetyFactor() + + anch.dd['design'] = {'L':30, 'D':2, 'zlug':3} + assign_soil(anch, 'sand', project) + Ha = loads['Ha'] + Va = loads['Va'] + zlug = anch.dd['design']['zlug'] + anch.getCapacityAnchor(Ha, Va, zlug=zlug, plot=False) + anch.getSafetyFactor() + + assign_soil(anch, 'weak_rock', project) + Ha = loads['Ha'] + Va = loads['Va'] + # change the padeye back to mudline elevation in rock + anch.dd['design']['zlug'] = 0 + zlug = anch.dd['design']['zlug'] + anch.getCapacityAnchor(Ha, Va, zlug=zlug, plot=False) + anch.getSafetyFactor() + + # check HELICAL PILE with sand + anch.dd['type'] = 'helical' + anch.dd['design'] = {'L':15, 'd':1.25, 'D':2.00, 'zlug':3} + assign_soil(anch, 'sand', project) + Ha = loads['Ha'] + Va = loads['Va'] + zlug = anch.dd['design']['zlug'] + anch.getCapacityAnchor(Ha, Va, zlug=zlug, plot=False) + anch.getSafetyFactor() + + # check HELICAL PILE with clay + anch.dd['type'] = 'helical' + anch.dd['design'] = {'L':12, 'd':0.5, 'D':1.5, 'zlug':3} + assign_soil(anch, 'mud_firm', project) + Ha = loads['Ha'] + Va = loads['Va'] + zlug = anch.dd['design']['zlug'] + anch.getCapacityAnchor(Ha, Va, zlug=zlug, plot=False) + anch.getSafetyFactor() + + # check TORPEDO PILE + anch.dd['type'] = 'torpedo' + anch.dd['design'] = {'D1':3, 'D2':1.1, 'L1':10, 'L2':4, 'zlug':16} + assign_soil(anch, 'mud_soft', project) + Ha = loads['Ha'] + Va = loads['Va'] + zlug = anch.dd['design']['zlug'] + anch.getCapacityAnchor(Ha, Va, zlug=zlug, plot=False) + anch.getSafetyFactor() +