@@ -2765,7 +2765,9 @@ def getRAFT(self,RAFTDict,pristine=1):
27652765
27662766 if 'ID' in RAFTDict ['array' ]['keys' ]:
27672767 IDindex = np .where (np .array (RAFTDict ['array' ]['keys' ])== 'ID' )[0 ][0 ]
2768+ IDdata = [row [IDindex ] for row in RAFTDict ['array' ]['data' ]]
27682769 RAFTDict ['array' ]['keys' ].pop (IDindex ) # remove key for ID because this doesn't exist in RAFT array table
2770+ reinsert = True
27692771 if 'topsideID' in RAFTDict ['array' ]['keys' ]:
27702772 ts_loc = RAFTDict ['array' ]['keys' ].index ('topsideID' )
27712773 RAFTDict ['array' ]['keys' ][ts_loc ] = 'turbineID'
@@ -2789,7 +2791,8 @@ def getRAFT(self,RAFTDict,pristine=1):
27892791 if turb [tsIDindex ] > ti :
27902792 turb [tsIDindex ] -= 1
27912793
2792-
2794+
2795+
27932796 # create empty mooring dictionary
27942797 RAFTDict ['mooring' ] = {}
27952798 #RAFTDict['mooring']['currentMod']
@@ -2817,6 +2820,12 @@ def getRAFT(self,RAFTDict,pristine=1):
28172820 # connect RAFT fowt to the correct moorpy body
28182821 for i in range (0 ,len (self .platformList )): # do not include substations (these are made last)
28192822 self .array .fowtList [i ].body = self .ms .bodyList [i ]
2823+
2824+ # Reinsert 'ID' key and data back into RAFTDict
2825+ if reinsert :
2826+ RAFTDict ['array' ]['keys' ].insert (IDindex , 'ID' ) # Reinsert 'ID' key at its original position
2827+ for i , row in enumerate (RAFTDict ['array' ]['data' ]):
2828+ row .insert (IDindex , IDdata [i ]) # Reinsert 'ID' data into each row
28202829 else :
28212830 raise Exception ('Platform(s) must be specified in YAML file' )
28222831
@@ -4251,8 +4260,116 @@ def resetArrayCenter(self, FOWTOnly=True):
42514260
42524261 if 'platforms' in self .RAFTDict or 'platform' in self .RAFTDict :
42534262 self .getRAFT (self .RAFTDict ,pristine = 1 )
4263+ self .getMoorPyArray ()
4264+
4265+ def arrayReorientation (self , windHeading = None , degrees = False ):
4266+ '''
4267+ Reorients the array based on a given wind heading. The array will be reoriented such that wind faces East (the zero in FFarm).
4268+ Useful to allign the array with the wind direction.
4269+
4270+ Parameters
4271+ ----------
4272+ windHeading, float (optional)
4273+ The heading of the wind [deg or rad] depending on
4274+ degrees parameter. The heading is based on compass convention (North=0deg and +ve CW).
4275+ degrees : bool (optional)
4276+ Determines whether to use degree or radian for heading.
4277+ '''
4278+
4279+ from scipy .interpolate import griddata
4280+
4281+ # Check if windHeading is given
4282+ if windHeading is None :
4283+ raise ValueError ("windHeading is not given. Please provide a valid wind heading." )
4284+
4285+ if degrees :
4286+ windHeading = np .radians (windHeading )
4287+
4288+ # reference wind heading (aligned with x-axis)
4289+ windHeadingRef = np .radians (270 )
4290+ # Calculate the phi angle with which we will rotate the array
4291+ phi = ((np .pi / 2 - windHeading ) + np .pi ) % (2 * np .pi )
4292+
4293+ # Compute rotation matrix for faster computation
4294+ R = np .array ([[np .cos (phi ), np .sin (phi )],
4295+ [- np .sin (phi ), np .cos (phi )]])
4296+
4297+ # Rotate the boundary
4298+ self .boundary = np .dot (R , self .boundary .T ).T
4299+
4300+ # Rotate the bathymetry
4301+ X , Y = np .meshgrid (self .grid_x , self .grid_y )
4302+ coords_flat = np .stack ([X .flatten (), Y .flatten ()], axis = - 1 )
4303+ rotated_coords_flat = np .dot (R , coords_flat .T ).T
4304+ rotated_X_flat , rotated_Y_flat = rotated_coords_flat [:, 0 ], rotated_coords_flat [:, 1 ]
4305+ X_rot = rotated_X_flat .reshape (X .shape )
4306+ Y_rot = rotated_Y_flat .reshape (Y .shape )
4307+
4308+ min_X = np .min (X_rot )
4309+ max_X = np .max (X_rot )
4310+ min_Y = np .min (Y_rot )
4311+ max_Y = np .max (Y_rot )
4312+
4313+ self .grid_x = np .arange (min_X , max_X , np .min (np .diff (self .grid_x )))
4314+ self .grid_y = np .arange (min_Y , max_Y , np .min (np .diff (self .grid_y )))
4315+ X_rot , Y_rot = np .meshgrid (self .grid_x , self .grid_y )
4316+
4317+ # Interpolate self.grid_depth onto the rotated grid
4318+ depth_flat = self .grid_depth .flatten () # Flatten the depth values
4319+ rotated_depth = griddata (
4320+ points = rotated_coords_flat , # Original grid points
4321+ values = depth_flat , # Original depth values
4322+ xi = (X_rot , Y_rot ), # New rotated grid points
4323+ method = 'linear' # Interpolation method (can also use 'nearest' or 'cubic')
4324+ )
4325+
4326+ if np .isnan (rotated_depth ).any ():
4327+ nan_mask = np .isnan (rotated_depth )
4328+ nearest_depth = griddata (
4329+ points = rotated_coords_flat ,
4330+ values = depth_flat ,
4331+ xi = (X_rot , Y_rot ),
4332+ method = 'nearest'
4333+ )
4334+ rotated_depth [nan_mask ] = nearest_depth [nan_mask ]
4335+
4336+ self .grid_depth = rotated_depth
4337+
4338+ # Rotate the platforms
4339+ for pf in self .platformList .values ():
4340+ pf .r [:2 ] = np .dot (R , pf .r [:2 ].T ).T
4341+ pf .phi = pf .phi + windHeadingRef - windHeading
4342+
4343+
4344+ # Rotate moorings
4345+ for moor in self .mooringList .values ():
4346+ # if not moor.shared:
4347+ mooringHeading = np .radians (moor .heading ) + windHeadingRef - windHeading
4348+ moor .reposition (heading = mooringHeading , project = self )
4349+ # else:
4350+ # mooringHeading = np.radians(obj.heading)
4351+ # moor.reposition(heading=mooringHeading)
4352+
4353+
4354+
4355+ # if isinstance(obj, Cable):
4356+ # cableHeading = [obj.subcomponents[0].headingA + phi, obj.subcomponents[-1].headingB + phi]
4357+ # obj.reposiiton(headings=cableHeading, project=self)
42544358
4359+ # Change RAFTDict if available.
4360+ if self .RAFTDict :
4361+ x_idx = self .RAFTDict ['array' ]['keys' ].index ('x_location' )
4362+ y_idx = self .RAFTDict ['array' ]['keys' ].index ('y_location' )
4363+ p_idx = self .RAFTDict ['array' ]['keys' ].index ('heading_adjust' )
4364+ for i , pf in enumerate (self .platformList .values ()):
4365+ self .RAFTDict ['array' ]['data' ][i ][x_idx ] = pf .r [0 ]
4366+ self .RAFTDict ['array' ]['data' ][i ][y_idx ] = pf .r [1 ]
4367+ self .RAFTDict ['array' ]['data' ][i ][p_idx ] = np .degrees (pf .phi )
42554368
4369+ if 'platforms' in self .RAFTDict or 'platform' in self .RAFTDict :
4370+ self .getRAFT (self .RAFTDict ,pristine = 1 )
4371+
4372+ self .getMoorPyArray ()
42564373
42574374 def updateFailureProbability (self ):
42584375 '''
0 commit comments