@@ -97,6 +97,7 @@ def __init__(self, lon=0, lat=0, file=None, depth=202,raft=1):
9797 self .rho_water = 1025 # density of water (default to saltwater) [kg/m^3]
9898 self .rho_air = 1.225 # density of air [kg/m^3]
9999 self .mu_air = 1.81e-5 # dynamic viscosity of air [Pa*s]
100+ self .marine_growth = None
100101
101102 # Project boundary (vertical stack of x,y coordinate pairs [m])
102103 self .boundary = np .zeros ([0 ,2 ])
@@ -110,10 +111,9 @@ def __init__(self, lon=0, lat=0, file=None, depth=202,raft=1):
110111 self .depth = depth
111112 self .grid_depth = np .array ([[self .depth ]]) # depth at each grid point [iy, ix]
112113
113- self .seabed_type = 'clay' # switch of which soil property set to use ('clay', 'sand', or 'rock')
114-
115114 # soil parameters at each grid point
116115 self .soilProps = {}
116+ self .soil_names = []
117117 self .soil_mode = 0 # soil/anchor model level to use (0: none; 1: simple categories; 2: quantitative)
118118 self .soil_class = [["none" ]] # soil classification name ('clay', 'sand', or 'rock' with optional modifiers)
119119 self .soil_gamma = np .zeros ((1 ,1 )) # soil effective unit weight [kPa] (all soils)
@@ -1858,18 +1858,19 @@ def addAnchor(self, id=None, dd=None, design=None, cost=0, atype=None, platform=
18581858 return (anchor )
18591859
18601860 def addTurbine (self ,id = None , typeID = None , platform = None , turbine_dd = {}):
1861+
18611862 if typeID == None :
18621863 typeID = len (self .turbineTypes )
18631864 if id == None :
18641865 id = 'T' + str (typeID )+ '_' + str (len (self .turbineList ))
18651866
18661867 if turbine_dd and 'blade' in turbine_dd :
1867- blade_diameter = turbine_dd ['blade' ]['Rtip' ]* 2
1868+ rotor_diameter = turbine_dd ['blade' ]['Rtip' ]* 2
18681869 self .turbineTypes .append (turbine_dd )
18691870 else :
18701871 blade_diameter = 0
18711872
1872- self .turbineList [id ] = Turbine (turbine_dd ,id ,D = blade_diameter )
1873+ self .turbineList [id ] = Turbine (turbine_dd ,id ,D = rotor_diameter )
18731874 self .turbineList [id ].dd ['type' ] = typeID
18741875 if platform != None :
18751876 platform .attach (self .turbineList [id ])
@@ -2184,7 +2185,7 @@ def plot2d(self, ax=None, plot_seabed=False, plot_soil=False,
21842185 depth_vmin = kwargs .get ('depth_vmin' , None )
21852186 depth_vmax = kwargs .get ('depth_vmax' , None )
21862187 bath_levels = kwargs .get ('bath_levels' , None )
2187- show_legend = kwargs .get ('show_legend ' , True )
2188+ plot_legend = kwargs .get ('plot_legend ' , True )
21882189 legend_x = kwargs .get ('legend_x' , 0.5 )
21892190 legend_y = kwargs .get ('legend_y' , - 0.1 )
21902191
@@ -2302,16 +2303,21 @@ def plot2d(self, ax=None, plot_seabed=False, plot_soil=False,
23022303 line .type ['material' ][1 :]+ ' Mooring' )
23032304
23042305 if mooring .ss :
2305- mooring .ss .drawLine2d (0 , ax , color = "self" , endpoints = False ,
2306- Xuvec = [1 ,0 ,0 ], Yuvec = [0 ,1 ,0 ], line_depth_settings = line_depth_settings , label = labs )
2306+ mooring .ss .drawLine2d (0 , ax , color = "self" ,
2307+ plot_endpoints = False ,
2308+ Xuvec = [1 ,0 ,0 ], Yuvec = [0 ,1 ,0 ],
2309+ line_depth_settings = line_depth_settings ,
2310+ label = labs )
23072311 elif mooring .parallels :
23082312 for i ,line in enumerate (lineList ):
23092313 line .drawLine2d (0 , ax , color = "self" ,
2310- Xuvec = [1 ,0 ,0 ], Yuvec = [0 ,1 ,0 ], label = labs [i ])
2314+ Xuvec = [1 ,0 ,0 ], Yuvec = [0 ,1 ,0 ],
2315+ label = labs [i ])
23112316
23122317 else : # simple line plot
23132318 ax .plot ([mooring .rA [0 ], mooring .rB [0 ]],
2314- [mooring .rA [1 ], mooring .rB [1 ]], 'k' , lw = 0.5 , label = 'Mooring Line' )
2319+ [mooring .rA [1 ], mooring .rB [1 ]], 'k' , lw = 0.5 ,
2320+ label = 'Mooring Line' )
23152321
23162322 # ---- Add colorbar for line depth ----
23172323 if line_depth_settings is not None and not bare :
@@ -2351,23 +2357,23 @@ def plot2d(self, ax=None, plot_seabed=False, plot_soil=False,
23512357 # has routing - first plot rA to sub.coordinate[0] connection
23522358 ax .plot ([sub .rA [0 ],sub .x [0 ]],
23532359 [sub .rA [1 ],sub .y [0 ]],':' ,color = Ccable ,
2354- lw = 1.2 ,label = 'Static Cable ' + str ( cableSize ) + ' mm$^{2}$' )
2360+ lw = 1.2 ,label = f 'Static Cable { cableSize } mm$^{ 2 } $' )
23552361 # now plot route
23562362 if len (sub .x ) > 1 :
23572363 for i in range (1 ,len (sub .x )):
23582364 ax .plot ([sub .x [i - 1 ],sub .x [i ]],
23592365 [sub .y [i - 1 ],sub .y [i ]],
23602366 ':' , color = Ccable , lw = 1.2 ,
2361- label = 'Static Cable ' + str ( cableSize ) + ' mm$^{2}$' )
2367+ label = f 'Static Cable { cableSize } mm$^{ 2 } $' )
23622368 # finally plot sub.coordinates[-1] to rB connection
23632369 ax .plot ([sub .x [- 1 ],sub .rB [0 ]],
23642370 [sub .y [- 1 ],sub .rB [1 ]],':' ,color = Ccable ,
2365- lw = 1.2 ,label = 'Static Cable ' + str ( cableSize ) + ' mm$^{2}$' )
2371+ lw = 1.2 ,label = f 'Static Cable { cableSize } mm$^{ 2 } $' )
23662372 else :
23672373 # if not routing just do simple line plot
23682374 ax .plot ([sub .rA [0 ],sub .rB [0 ]],
23692375 [sub .rA [1 ], sub .rB [1 ]],':' ,color = Ccable , lw = 1.2 ,
2370- label = 'Static Cable ' + str ( cableSize ) + ' mm$^{2}$' )
2376+ label = f 'Static Cable { cableSize } mm$^{ 2 } $' )
23712377
23722378 # if cable_labels:
23732379 # x = np.mean([sub.rA[0],sub.rB[0]])
@@ -2380,7 +2386,7 @@ def plot2d(self, ax=None, plot_seabed=False, plot_soil=False,
23802386 elif isinstance (sub ,DynamicCable ):
23812387 ax .plot ([sub .rA [0 ],sub .rB [0 ]],
23822388 [sub .rA [1 ], sub .rB [1 ]],color = Ccable , lw = 1.2 ,
2383- label = 'Dynamic Cable ' + str ( cableSize ) + ' mm$^{2}$' )
2389+ label = f 'Dynamic Cable { cableSize } mm$^{ 2 } $' )
23842390
23852391 if cable_labels :
23862392 x = np .mean ([sub .rA [0 ],sub .rB [0 ]])
@@ -2421,10 +2427,17 @@ def plot2d(self, ax=None, plot_seabed=False, plot_soil=False,
24212427 labels += [h .get_label () for h in soil_handles ]
24222428 by_label = dict (zip (labels , handles )) # Removing duplicate labels
24232429
2424- if show_legend :
2430+ if plot_legend :
24252431 ax .legend (by_label .values (), by_label .keys (),loc = 'upper center' ,bbox_to_anchor = (legend_x , legend_y ), fancybox = True , ncol = 4 )
24262432 if save :
2427- plt .savefig ('2dfarm.png' , dpi = 600 , bbox_inches = 'tight' ) # Adjust the dpi as needed
2433+ counter = 1
2434+ output_filename = f'2dfarm_{ counter } .png'
2435+ while os .path .exists (output_filename ):
2436+ counter += 1
2437+ output_filename = f'2dfarm_{ counter } .png'
2438+
2439+ # Increase the resolution when saving the plot
2440+ plt .savefig (output_filename , dpi = 600 , bbox_inches = 'tight' ) # Adjust the dpi as needed
24282441
24292442 # TODO - add ability to plot from RAFT FOWT
24302443 if return_contour :
@@ -2483,21 +2496,8 @@ def plot3d(self, ax=None, figsize=(10,8), plot_fowt=False, save=False,
24832496 args_bath = {'cmap' : cmap , 'vmin' :min ([min (x ) for x in - self .grid_depth ]),
24842497 'vmax' : vmax }
24852498
2486- # >>> below code sections seem to do unnecessary interpolation and regridding... >>>
24872499 if boundary_only : # if you only want to plot the bathymetry that's underneath the boundary, rather than the whole file
2488- boundary = np .vstack ([self .boundary , self .boundary [0 ,:]])
2489- xs = np .linspace (min (boundary [:,0 ]),max (boundary [:,0 ]),len (boundary [:,0 ]))
2490- ys = np .linspace (min (boundary [:,1 ]),max (boundary [:,1 ]),len (boundary [:,1 ]))
2491-
2492- self .setGrid (xs , ys )
2493-
2494- # plot the bathymetry in matplotlib using a plot_surface
2495- X , Y = np .meshgrid (xs , ys ) # 2D mesh of seabed grid
2496-
2497- plot_depths = np .zeros ([len (ys ), len (xs )])
2498- for i in range (len (ys )):
2499- for j in range (len (xs )):
2500- plot_depths [i ,j ], nvec = self .getDepthAtLocation (xs [j ], ys [i ])
2500+ self .trimGrids ()
25012501
25022502 else :
25032503 xs = np .linspace (min (self .grid_x ),max (self .grid_x ),len (self .grid_x ))
@@ -2775,9 +2775,12 @@ def getMoorPyArray(self, plt=0, pristineLines=True, cables=True):
27752775 # set location of subsystem for simpler coding
27762776 ssloc = mooring .ss
27772777 else :
2778- mooring . createSubsystem ( pristine = False , ms = self . ms )
2778+ # if modified , assume the ss_mod is already generated
27792779 # set location of subsystem for simpler coding
27802780 ssloc = mooring .ss_mod
2781+ # assign ss_mod in to ms
2782+ self .ms .lineList .append (ssloc )
2783+ ssloc .number = len (self .ms .lineList )
27812784
27822785 # (ms.lineList.append is now done in Mooring.createSubsystem)
27832786
@@ -2889,19 +2892,19 @@ def getMoorPyArray(self, plt=0, pristineLines=True, cables=True):
28892892 if check == 1 : # mooring object not in any anchor lists
28902893 # new shared line
28912894 # create subsystem for shared line
2892- if hasattr (mooring , 'shared' ): # <<<
2893- mooring .createSubsystem (case = mooring .shared ,
2894- pristine = pristineLines , ms = self .ms )
2895- else :
2896- mooring .createSubsystem (case = 1 ,pristine = pristineLines ,
2897- ms = self .ms ) # we doubled all symmetric lines so any shared lines should be case 1
2895+
28982896 # set location of subsystem for simpler coding
28992897 if pristineLines :
2898+ mooring .createSubsystem (case = mooring .shared ,
2899+ pristine = pristineLines , ms = self .ms )
29002900 ssloc = mooring .ss
29012901 else :
2902+ # modified line should already exist - just attach it
29022903 ssloc = mooring .ss_mod
2904+ self .ms .lineList .append (ssloc )
2905+ ssloc .number = len (self .ms .lineList )
29032906
2904- # (ms.lineList.append is now done in Mooring.createSubsystem)
2907+ # (ms.lineList.append is now done in Mooring.createSubsystem unless not pristine )
29052908
29062909 # find associated platforms/ buoys
29072910 att = mooring .attached_to
@@ -3432,7 +3435,7 @@ def getMarineGrowth(self,mgDict_start=None,lines='all',tol=2,display=False):
34323435 for j in range (0 ,len (cP )):
34333436 cEq .append (mgDict_start ['th' ][cD [j ][0 ]][cD [j ][1 ]] - self .cableList [i [0 ]].subcomponents [i [1 ]].ss_mod .pointList [cP [j ]].r [2 ])
34343437 else :
3435- cD ,cP = self .mooringList [i ].addMarineGrowth (mgDict , project = self , idx = i )
3438+ cD ,cP = self .mooringList [i ].addMarineGrowth (mgDict )
34363439 for j in range (0 ,len (cP )):
34373440 cEq .append (mgDict_start ['th' ][cD [j ][0 ]][cD [j ][1 ]] - self .mooringList [i ].ss_mod .pointList [cP [j ]].r [2 ])
34383441 # adjust depth to change based on difference between actual and desired change depth
@@ -4532,6 +4535,14 @@ def unload(self,file='project.yaml'):
45324535 site ['bathymetry' ] = {'x' :[float (x ) for x in self .grid_x ],'y' :[float (y ) for y in self .grid_y ],'depths' :[[float (y ) for y in x ] for x in self .grid_depth ]}
45334536 if len (self .boundary )> 0 :
45344537 site ['boundaries' ] = {'x_y' :[[float (y ) for y in x ] for x in self .boundary ]}
4538+
4539+ if self .marine_growth :
4540+ site ['marine_growth' ] = {
4541+ 'keys' :['thickness' , 'lowerRange' , 'upperRange' , 'density' ][:len (self .marine_growth ['th' ])],
4542+ 'data' :[v for v in self .marine_growth ['th' ]]
4543+ }
4544+ if 'buoy_th' in self .marine_growth :
4545+ site ['marine_growth' ]['buoys' ] = [x for x in self .marine_growth ['buoy_th' ]]
45354546 site ['general' ] = {'water_depth' :float (self .depth ),'rho_air' :float (self .rho_air ),
45364547 'rho_water' :float (self .rho_water ),'mu_air' :float (self .mu_air )}
45374548
@@ -4870,7 +4881,10 @@ def extractFarmInfo(self, cmax=5, fmax=10/6, Cmeander=1.9):
48704881 phi_deg = (phi_deg + 180 ) % 360 - 180 # Shift range to -180 to 180
48714882 for att in pf .attachments .values ():
48724883 if isinstance (att ['obj' ],Turbine ):
4873- D = 240 # att['obj'].D (assuming 15MW)
4884+ if hasattr (att ['obj' ], 'D' ):
4885+ D = att ['obj' ].D
4886+ else :
4887+ D = 242
48744888 zhub = att ['obj' ].dd ['hHub' ]
48754889
48764890 wts [i ] = {
0 commit comments