Skip to content

Commit

Permalink
Merge branch 'ctopt' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
shousner committed Jan 6, 2024
2 parents 1bd3424 + 76d5d29 commit df5b201
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 53 deletions.
8 changes: 4 additions & 4 deletions designs/FOCTT_example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1064,14 +1064,14 @@ turbine:

name : tower # [-] an identifier (no longer has to be number)
type : 1 # [-]
rA : [ 0, 0, -2.5] # [m] end A coordinates
rB : [ 0, 0, -33.5] # [m] and B coordinates
rA : [ 0, 0, -33.5] # [m] end A coordinates
rB : [ 0, 0, -2.5] # [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 : [ -2.5, -31, -33.5 ] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB
d : [ 1.25, 1.25, .25 ] # [m] diameters if circular or side lengths if rectangular (can be pairs)
stations : [ -33.5, -31, -2.5 ] # [-] location of stations along axis. Will be normalized such that start value maps to rA and end value to rB
d : [ .25, 1.25, 1.25 ] # [m] diameters if circular or side lengths if rectangular (can be pairs)
t : [ 0.03, 0.03, 0.03 ] # [m] wall thicknesses (scalar or list of same length as stations)
Cd : 1.1 # [-] transverse drag coefficient (optional, scalar or list of same length as stations)
Ca : 1.0 # [-] transverse added mass coefficient (optional, scalar or list of same length as stations)
Expand Down
8 changes: 8 additions & 0 deletions designs/RM1_Floating.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,8 @@ platform:
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 : 0.4473325
rho_fill : 1025

- name : column-W # [-] an identifier (no longer has to be number)
type : 2 # [-]
Expand All @@ -737,6 +739,8 @@ platform:
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 : 0.4473325
rho_fill : 1025

- name : column-S # [-] an identifier (no longer has to be number)
type : 2 # [-]
Expand All @@ -753,6 +757,8 @@ platform:
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 : 0.4473325
rho_fill : 1025

- name : column-N # [-] an identifier (no longer has to be number)
type : 2 # [-]
Expand All @@ -769,6 +775,8 @@ platform:
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 : 0.4473325
rho_fill : 1025

- name : upper_brace-NE # [-] an identifier (no longer has to be number)
type : 2 # [-]
Expand Down
40 changes: 21 additions & 19 deletions raft/raft_fowt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2024,36 +2024,38 @@ def saveTurbineOutputs(self, results, case):
self.add_output('tower_maxMy_Mz', val=np.zeros(n_full_tow-1), units='kN*m', desc='distributed moment around tower-aligned x-axis corresponding to maximum fore-aft moment at tower base')
'''

def plot(self, ax, color=None, nodes=0, plot_rotor=True, station_plot=[], airfoils=False, zorder=2):
def plot(self, ax, color=None, nodes=0, plot_rotor=True, station_plot=[], airfoils=False, zorder=2,
plot_fowt=True, plot_ms=True, shadow=True):
'''plots the FOWT...'''

R = rotationMatrix(self.r6[3], self.r6[4], self.r6[5]) # note: eventually Rotor could handle orientation internally <<<

if self.ms:
self.ms.plot(ax=ax, color=color)
if plot_ms:
if self.ms:
self.ms.plot(ax=ax, color=color, shadow=shadow)

if color==None:
color='k'

if plot_rotor:
for rotor in self.rotorList:
coords = np.array([rotor.coords[0], rotor.coords[1], 0]) + self.r6[:3]
rotor.plot(ax, r_ptfm=coords, R_ptfm=R, color=color, airfoils=airfoils, zorder=zorder)
#rotor.plot(ax, r_ptfm=self.body.r6[:3], R_ptfm=self.body.R, color=color)
'''
for afmem in rotor.bladeMemberList:
afmem.calcOrientation()
afmem.plot(ax, r_ptfm=self.body.r6[:3], R_ptfm=self.body.R, color=color, nodes=nodes, station_plot=station_plot)
'''

if plot_fowt:
if plot_rotor:
for rotor in self.rotorList:
coords = np.array([rotor.coords[0], rotor.coords[1], 0]) + self.r6[:3]
rotor.plot(ax, r_ptfm=coords, R_ptfm=R, color=color, airfoils=airfoils, zorder=zorder)
#rotor.plot(ax, r_ptfm=self.body.r6[:3], R_ptfm=self.body.R, color=color)
'''
for afmem in rotor.bladeMemberList:
afmem.calcOrientation()
afmem.plot(ax, r_ptfm=self.body.r6[:3], R_ptfm=self.body.R, color=color, nodes=nodes, station_plot=station_plot)
'''

# loop through each member and plot it
for mem in self.memberList:
# loop through each member and plot it
for mem in self.memberList:

mem.setPosition() # offsets/rotations could be done in this function rather than in mem.plot <<<
mem.setPosition() # offsets/rotations could be done in this function rather than in mem.plot <<<

mem.plot(ax, r_ptfm=self.r6[:3], R_ptfm=R, color=color,
nodes=nodes, station_plot=station_plot, zorder=zorder)
mem.plot(ax, r_ptfm=self.r6[:3], R_ptfm=R, color=color,
nodes=nodes, station_plot=station_plot, zorder=zorder)

# in future should consider ability to animate mode shapes and also to animate response at each frequency
# including hydro excitation vectors stored in each member
Expand Down
5 changes: 3 additions & 2 deletions raft/raft_member.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def RectangularFrustumMOI(La, Wa, Lb, Wb, H, p):
y2 = (1/12)*p* ( (Wb-Wa)**3*H*(Lb/5 + La/20) + (Wb-Wa)**2*Wa*H(3*Lb/4 + La/4) + \
(Wb-Wa)*Wa**2*H*(Lb + La/2) + Wa**3*H*(Lb/2 + La/2) )

z2 = p*( Wb*Lb/5 + Wa*Lb/20 + La*Wb/20 + Wa*La*(8/15) )
z2 = p*( Wb*Lb/5 + Wa*Lb/20 + La*Wb/20 + Wa*La*(1/30) ) * H**3

Ixx = y2+z2 # MoI around the local x-axis about the end node [kg-m^2]
Iyy = x2+z2 # MoI around the local y-axis about the end node [kg-m^2]
Expand Down Expand Up @@ -1002,7 +1002,8 @@ def getSectionProperties(self, station):
'''Get member cross sectional area and moments of inertia at a user-
specified location along the member.'''


A = 0
I = 0

return A, I

Expand Down
14 changes: 6 additions & 8 deletions raft/raft_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1434,8 +1434,8 @@ def preprocess_HAMS(self, dw=0, wMax=0, dz=0, da=0):

def plot(self, ax=None, hideGrid=False, draw_body=True, color=None, nodes=0,
xbounds=None, ybounds=None, zbounds=None, plot_rotor=True, airfoils=False,
station_plot=[], zorder=2, figsize=(6,4), plot_water=False, plot_soil=False):

station_plot=[], zorder=2, figsize=(6,4), plot_fowt=True, plot_ms=True,
shadow=True, plot_water=False, plot_soil=False):
'''plots the whole model, including FOWTs and mooring system...'''

# for now, start the plot via the mooring system, since MoorPy doesn't yet know how to draw on other codes' plots
Expand All @@ -1462,8 +1462,8 @@ def plot(self, ax=None, hideGrid=False, draw_body=True, color=None, nodes=0,
# plot each FOWT
for fowt in self.fowtList:
fowt.plot(ax, color=color, zorder=zorder, nodes=nodes,
plot_rotor=plot_rotor, station_plot=station_plot,
airfoils=airfoils)
plot_rotor=plot_rotor, station_plot=station_plot,
airfoils=airfoils, plot_ms=plot_ms, plot_fowt=plot_fowt, shadow=shadow)

set_axes_equal(ax)

Expand Down Expand Up @@ -2182,13 +2182,11 @@ def runRAFTFarm(input_file, plot=0):
### Run a Reference FOWT Model ###
#model = runRAFT(os.path.join(raft_dir,'designs/OC3spar.yaml'), plot=1)
#model = runRAFT(os.path.join(raft_dir,'designs/OC4semi.yaml'), plot=1)
model = runRAFT(os.path.join(raft_dir,'designs/VolturnUS-S.yaml'), plot=1)
#model = runRAFT(os.path.join(raft_dir,'designs/VolturnUS-S.yaml'), plot=1)

### Run a MHK Model ###
#model = runRAFT(os.path.join(raft_dir,'designs/FOCTT_example.yaml'), plot=1)
#model = runRAFT(os.path.join(raft_dir,'designs/RM1_Floating.yaml'), plot=1)
#model = runRAFT(os.path.join(raft_dir,'designs/test2.yaml'), plot=1)
#model = runRAFT(os.path.join(raft_dir,'designs/test2.yaml'), plot=1)
model = runRAFT(os.path.join(raft_dir,'designs/RM1_Floating.yaml'), plot=1)

### Run a RAFT Farm Model ###
#model = runRAFTFarm(os.path.join(raft_dir,'designs/VolturnUS-S_farm.yaml'), plot=1)
Expand Down
42 changes: 22 additions & 20 deletions raft/raft_rotor.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,28 +555,30 @@ def calcHydroConstants(self, dgamma=0, rho=1025, g=9.81):

# --- whole-rotor members approach ---
for i,mem in enumerate(self.bladeMemberList):
# the input memberList is the rotor.bladeMemberList multiplied by nBlades (e.g. if len(rotor.bladeMemberList)=10, then this len(memberList)=30 for 3 blade rotor)
# adjust the heading/orientation of the each section of blade members by the corresponding heading in rotor.headings based on where in the list you are
j = i // int(len(self.bladeMemberList)/self.nBlades) # i (from 0 to 30) // 10, which results in either j = 1, 2, or 3, for each blade heading

rOG = np.array([mem.rA0, mem.rB0])

# find the end nodes of the blade member about the global coordinates (e.g,, if rA_OG = [0,0,0] and rB_OG=[0,1,0], and heading=90, then rA=[0,0,0] and rB=[0,0,1])
rUpdated = self.getBladeMemberPositions(self.headings[j], rOG) # blade node coords relative to hub
mem.rA0 = rUpdated[0]
mem.rB0 = rUpdated[-1]

# apply a blade pitch angle to every blade member if applicable
mem.gamma = mem.gamma + dgamma

# run calcOrientation to ensure the p1 and p2 axes of the members are oriented the way they should be
mem.setPosition()

# compute hydro added mass and inertial excitation terms relative to hub
A_hydro_i, I_hydro_i = mem.calcHydroConstants(sum_inertia=True, rho=rho, g=g)
rOG = np.array([mem.rA0, mem.rB0]) # save the original position of the blade members

for theta in self.headings: # for each blade member, repeat the process for each heading

# find the end nodes of the blade member about the global coordinates (e.g,, if rA_OG = [0,0,0] and rB_OG=[0,1,0], and heading=90, then rA=[0,0,0] and rB=[0,0,1])
rUpdated = self.getBladeMemberPositions(theta, rOG) # blade node coords relative to hub
mem.rA0 = rUpdated[0]
mem.rB0 = rUpdated[-1]

# apply a blade pitch angle to every blade member if applicable
mem.gamma = mem.gamma + dgamma

# run calcOrientation to ensure the p1 and p2 axes of the members are oriented the way they should be
mem.setPosition()

# compute hydro added mass and inertial excitation terms relative to hub
A_hydro_i, I_hydro_i = mem.calcHydroConstants(sum_inertia=True, rho=rho, g=g)

A_hydro += A_hydro_i
I_hydro += I_hydro_i

A_hydro += A_hydro_i
I_hydro += I_hydro_i
mem.rA0 = rOG[0] # reset end positions of each blade member after rotating
mem.rB0 = rOG[1]

# --- save hydro matrices (these are in global orientations) ---
self.A_hydro = A_hydro
Expand Down

0 comments on commit df5b201

Please sign in to comment.