[docs]classWakeFrame(Model):""" Abstract base class for wake frames. Wake frames translate global coordinates into wake frame coordinates, which are then evaluated by wake models. They are also responsible for the calculation of the turbine evaluation order. Attributes ---------- max_length_km: float The maximal wake length in km :group: core """
[docs]def__init__(self,max_length_km=3e4):""" Constructor. Parameters ---------- max_length_km: float The maximal wake length in km """super().__init__()self.max_length_km=max_length_km
[docs]@abstractmethoddefcalc_order(self,algo,mdata,fdata):""" Calculates the order of turbine evaluation. This function is executed on a single chunk of data, all computations should be based on numpy arrays. Parameters ---------- algo: foxes.core.Algorithm The calculation algorithm mdata: foxes.core.MData The model data fdata: foxes.core.FData The farm data Returns ------- order: numpy.ndarray The turbine order, shape: (n_states, n_turbines) """pass
[docs]@abstractmethoddefget_wake_coos(self,algo,mdata,fdata,tdata,downwind_index,):""" Calculate wake coordinates of rotor points. Parameters ---------- algo: foxes.core.Algorithm The calculation algorithm mdata: foxes.core.MData The model data fdata: foxes.core.FData The farm data tdata: foxes.core.TData The target point data downwind_index: int The index of the wake causing turbine in the downwind order Returns ------- wake_coos: numpy.ndarray The wake frame coordinates of the evaluation points, shape: (n_states, n_targets, n_tpoints, 3) """pass
[docs]defget_wake_modelling_data(self,algo,variable,downwind_index,fdata,tdata,target,states0=None,):""" Return data that is required for computing the wake from source turbines to evaluation points. Parameters ---------- algo: foxes.core.Algorithm, optional The algorithm, needed for data from previous iteration variable: str The variable, serves as data key downwind_index: int, optional The index in the downwind order fdata: foxes.core.FData The farm data tdata: foxes.core.TData The target point data target: str, optional The dimensions identifier for the output, FC.STATE_TURBINE, FC.STATE_TARGET, FC.STATE_TARGET_TPOINT states0: numpy.ndarray, optional The states of wake creation Returns ------- data: numpy.ndarray Data for wake modelling, shape: (n_states, n_turbines) or (n_states, n_target) """s=np.s_[:]ifstates0isNoneelsestates0iftarget==FC.STATE_TARGET_TPOINT:out=fdata[variable][s,downwind_index,None,None]eliftargetin[FC.STATE_TURBINE,FC.STATE_TARGET]:out=fdata[variable][s,downwind_index,None]else:raiseValueError(f"Unkown target '{target}', choices are {FC.STATE_TURBINE}, {FC.STATE_TARGET}, {FC.STATE_TARGET_TPOINT}")returnout
[docs]defget_centreline_points(self,algo,mdata,fdata,downwind_index,x):""" Gets the points along the centreline for given values of x. Parameters ---------- algo: foxes.core.Algorithm The calculation algorithm mdata: foxes.core.MData The model data fdata: foxes.core.FData The farm data downwind_index: int The index in the downwind order x: numpy.ndarray The wake frame x coordinates, shape: (n_states, n_points) Returns ------- points: numpy.ndarray The centreline points, shape: (n_states, n_points, 3) """raiseNotImplementedError(f"Wake frame '{self.name}': Centreline points requested but not implemented.")
[docs]defcalc_centreline_integral(self,algo,mdata,fdata,downwind_index,variables,x,dx,wake_models=None,self_wake=True,**ipars,):""" Integrates variables along the centreline. Parameters ---------- algo: foxes.core.Algorithm The calculation algorithm mdata: foxes.core.MData The model data fdata: foxes.core.FData The farm data downwind_index: int The index in the downwind order variables: list of str The variables to be integrated x: numpy.ndarray The wake frame x coordinates of the upper integral bounds, shape: (n_states, n_points) dx: float The step size of the integral wake_models: list of foxes.core.WakeModels The wake models to consider, default: from algo self_wake: bool Flag for considering only wake from states_source_turbine ipars: dict, optional Additional interpolation parameters Returns ------- results: numpy.ndarray The integration results, shape: (n_states, n_points, n_vars) """# prepare:n_states,n_points=x.shapevrs=[FV.amb2var.get(v,v)forvinvariables]n_vars=len(vrs)# calc evaluation points:xmin=0.0xmax=min(np.nanmax(x),self.max_length_km*1e3)n_steps=int((xmax-xmin)/dx)ifxmin+n_steps*dx<xmax:n_steps+=1n_ix=n_steps+1xs=np.arange(xmin,xmin+n_ix*dx,dx)xpts=np.zeros((n_states,n_steps),dtype=config.dtype_double)xpts[:]=xs[None,1:]pts=self.get_centreline_points(algo,mdata,fdata,downwind_index,xpts)# run ambient calculation:tdata=TData.from_points(pts,data={v:np.full((n_states,n_steps,1),np.nan,dtype=config.dtype_double)forvinvrs},dims={v:(FC.STATE,FC.TARGET,FC.TPOINT)forvinvrs},)res=algo.states.calculate(algo,mdata,fdata,tdata)tdata.update(res)amb2var=algo.get_model("SetAmbPointResults")()amb2var.initialize(algo,verbosity=0,force=True)res=amb2var.calculate(algo,mdata,fdata,tdata)tdata.update(res)delres,amb2var# find out if all vars ambient:ambient=Trueforvinvariables:ifvnotinFV.amb2var:ambient=Falsebreak# calc wakes:ifnotambient:wcalc=algo.get_model("PointWakesCalculation")(wake_models=wake_models)wcalc.initialize(algo,verbosity=0,force=True)wsrc=downwind_indexifself_wakeelseNoneres=wcalc.calculate(algo,mdata,fdata,tdata,downwind_index=wsrc)tdata.update(res)delwcalc,res# collect integration results:iresults=np.zeros((n_states,n_ix,n_vars),dtype=config.dtype_double)forvi,vinenumerate(variables):foriinrange(n_steps):iresults[:,i+1,vi]=iresults[:,i,vi]+tdata[v][:,i,0]*dx# interpolate to x of interest:qts=np.zeros((n_states,n_points,2),dtype=config.dtype_double)qts[:,:,0]=np.arange(n_states)[:,None]qts[:,:,1]=xqts=qts.reshape(n_states*n_points,2)results=interpn((np.arange(n_states),xs),iresults,qts,bounds_error=False,fill_value=0.0,**ipars,)returnresults.reshape(n_states,n_points,n_vars)
[docs]@classmethoddefnew(cls,wframe_type,*args,**kwargs):""" Run-time wake frame factory. Parameters ---------- wframe_type: str The selected derived class name args: tuple, optional Additional parameters for constructor kwargs: dict, optional Additional parameters for constructor """returnnew_instance(cls,wframe_type,*args,**kwargs)