Skip to content

Commit 85bee3f

Browse files
author
Rudy Alkarem
committed
updating extractFarmInfo function to apply a force and get the initial conditions of the platform displacement to be fed to ElastoDyn
1 parent a1e7308 commit 85bee3f

File tree

1 file changed

+60
-25
lines changed

1 file changed

+60
-25
lines changed

famodel/project.py

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2857,7 +2857,7 @@ def getMoorPyArray(self, plt=0, cables=True):
28572857
mooring = att['obj']
28582858

28592859
# create subsystem
2860-
2860+
28612861
mooring.createSubsystem(ms=self.ms)
28622862

28632863
# set location of subsystem for simpler coding
@@ -4891,17 +4891,24 @@ def unload(self,file='project.yaml'):
48914891
with open(file,'w') as f:
48924892
yaml.dump(output,f)
48934893

4894-
def extractFarmInfo(self, cmax=5, fmax=10/6, Cmeander=1.9):
4894+
def extractFarmInfo(self, cmax=5, fmax=10/6, Cmeander=1.9, force=1e9, direction=0.0, retainForce=False):
48954895
'''
48964896
Function to extract farm-level information required to create FAST.Farm case simulations. [Under developement]:
48974897
48984898
Parameters
48994899
----------
49004900
cmax : float, optional
4901-
maximum blade chord (m)
4902-
fmax: maximum excitation frequency (Hz)
4903-
Cmeander: Meandering constant (-)
4904-
4901+
Maximum rotor induction factor to be used in FAST.Farm simulations
4902+
fmax: float, optional
4903+
Maximum rotor frequency to be used in FAST.Farm simulations (Hz)
4904+
Cmeander: float, optional
4905+
Meandering coefficient to be used in FAST.Farm simulations
4906+
force: float, optional
4907+
Magnitude of the external force applied to each platform (N)
4908+
direction: float, optional
4909+
Direction of the applied force in degrees (0deg = +x +ve CCW)
4910+
retainForce: bool, optional
4911+
A flag to retain the applied force after extracting the platform offsets. If False, the force is removed and the equilibrium is re-solved.
49054912
Returns
49064913
-------
49074914
wts : dict
@@ -4914,26 +4921,54 @@ def extractFarmInfo(self, cmax=5, fmax=10/6, Cmeander=1.9):
49144921
# ----------- Extract Wind Farm Data
49154922
wts = {}
49164923
i = 0
4917-
yaw_init = np.zeros((1, len(self.platformList.items())))
4924+
yaw_init = np.zeros((1, len(self.platformList.items())))
49184925
for _, pf in self.platformList.items():
4919-
if pf.entity=='FOWT':
4920-
x, y, z = pf.r[0], pf.r[1], pf.r[2]
4921-
phi_deg = np.degrees(pf.phi) # float((90 - np.degrees(pf.phi)) % 360) # Converting FAD's rotational convention (0deg N, +ve CW) into FF's rotational convention (0deg E, +ve CCW)
4922-
phi_deg = (phi_deg + 180) % 360 - 180 # Shift range to -180 to 180
4923-
for att in pf.attachments.values():
4924-
if isinstance(att['obj'],Turbine):
4925-
if hasattr(att['obj'], 'D'):
4926-
D = int(att['obj'].D)
4927-
else:
4928-
D = 242
4929-
zhub = att['obj'].dd['hHub']
4930-
4931-
wts[i] = {
4932-
'x': x, 'y': y, 'z': z, 'phi_deg': phi_deg, 'D': D, 'zhub': zhub,
4933-
'cmax': cmax, 'fmax': fmax, 'Cmeander': Cmeander
4934-
}
4935-
yaw_init[0, i] = -phi_deg
4936-
i += 1
4926+
x, y, z = pf.r[0], pf.r[1], pf.r[2]
4927+
phi_deg = np.degrees(pf.phi) # float((90 - np.degrees(pf.phi)) % 360) # Converting FAD's rotational convention (0deg N, +ve CW) into FF's rotational convention (0deg E, +ve CCW)
4928+
phi_deg = (phi_deg + 180) % 360 - 180 # Shift range to -180 to 180
4929+
for att in pf.attachments.values():
4930+
if isinstance(att['obj'],Turbine):
4931+
if hasattr(att['obj'], 'D'):
4932+
D = int(att['obj'].D)
4933+
else:
4934+
D = 242
4935+
zhub = att['obj'].dd['hHub']
4936+
4937+
wts[i] = {
4938+
'x': x, 'y': y, 'z': z, 'phi_deg': phi_deg, 'D': D, 'zhub': zhub,
4939+
'cmax': cmax, 'fmax': fmax, 'Cmeander': Cmeander
4940+
}
4941+
yaw_init[0, i] = -phi_deg
4942+
i += 1
4943+
4944+
# Apply force and compute initial platform offsets
4945+
fx = force*np.cos(np.radians(direction))
4946+
fy = force*np.sin(np.radians(direction))
4947+
for _, pf in self.platformList.items():
4948+
# if pf.entity=='FOWT': #TODO: Rudy - maybe this should be replaced with an attribute: operatingPlatform: True or False (or a percentage of curtailment) [because we do want all platforms available in project class to be transformed to FFarm and if platform is not operating, we still want its information]
4949+
pf.body.f6Ext = np.array([fx, fy, 0, 0, 0, 0])
4950+
4951+
4952+
self.ms.solveEquilibrium3(DOFtype='both')
4953+
4954+
i = 0
4955+
for _, pf in self.platformList.items():
4956+
x, y, z = wts[i]['x'], wts[i]['y'], wts[i]['z']
4957+
xi = pf.body.r6[0] - x
4958+
yi = pf.body.r6[1] - y
4959+
zi = pf.body.r6[2] - z
4960+
wts[i]['xi'] = xi
4961+
wts[i]['yi'] = yi
4962+
wts[i]['zi'] = zi
4963+
i += 1
4964+
4965+
# Return to original status if requested
4966+
if retainForce:
4967+
for _, pf in self.platformList.items():
4968+
pf.body.f6Ext = np.array([0, 0, 0, 0, 0, 0])
4969+
4970+
4971+
self.ms.solveEquilibrium3(DOFtype='both')
49374972

49384973
# store farm-level wind turbine information
49394974
self.wts = wts

0 commit comments

Comments
 (0)