@@ -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