Skip to content

Commit 1b4eea5

Browse files
authored
Merge pull request #78 from byuflowlab/typestability
Typestability
2 parents 16626ea + cb50a23 commit 1b4eea5

File tree

11 files changed

+824
-445
lines changed

11 files changed

+824
-445
lines changed

src/fatigue_model.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -645,9 +645,9 @@ function get_single_damage_surr(turbine_x,turbine_y,turbine_z,rotor_diameter,hub
645645

646646
temp_resource = DiscretizedWindResource([3*pi/2], [ws], [1.0], measurementheight, air_density, ambient_tis, wind_shear_model)
647647

648-
turbine_velocities, turbine_ct, turbine_local_ti = turbine_velocities_one_direction(turbine_x, turbine_y, turbine_z, rotor_diameter, hub_height, turbine_yaw,
649-
turbine_ai, sorted_turbine_index, ct_model, rotor_sample_points_y, rotor_sample_points_z, wind_resource,
650-
model_set; wind_farm_state_id=state_ID)
648+
turbine_velocities, turbine_ct, _, turbine_local_ti = turbine_velocities_one_direction_full(turbine_x, turbine_y, turbine_z, rotor_diameter, hub_height, turbine_yaw,
649+
sorted_turbine_index, ct_model, rotor_sample_points_y, rotor_sample_points_z, wind_resource,
650+
model_set; wind_farm_state_id=state_ID, turbine_ai=turbine_ai)
651651

652652

653653
for i = 1:nCycles*naz

src/general_models.jl

Lines changed: 204 additions & 144 deletions
Large diffs are not rendered by default.

src/power_models.jl

Lines changed: 228 additions & 160 deletions
Large diffs are not rendered by default.

src/sparsity_functions.jl

Lines changed: 147 additions & 81 deletions
Large diffs are not rendered by default.

src/user_functions.jl

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ author: Benjamin Varela
1010
build_wind_farm_struct(x,turbine_x,turbine_y,turbine_z,hub_height,turbine_yaw,rotor_diameter,
1111
ct_models,generator_efficiency,cut_in_speed,cut_out_speed,rated_speed,rated_power,wind_resource,
1212
power_models,model_set,update_function;rotor_sample_points_y=[0.0],rotor_sample_points_z=[0.0],
13-
AEP_scale=0.0,input_type=nothing,opt_x=false,opt_y=false,opt_hub=false,opt_yaw=false,opt_diam=false,
14-
force_single_thread=false)
13+
AEP_scale=0.0,input_type=nothing,opt_x=false,opt_y=false,opt_hub=false,opt_yaw=false,opt_diam=false)
1514
1615
function to build a wind_farm_struct
1716
@@ -42,17 +41,13 @@ function to build a wind_farm_struct
4241
- `opt_hub`: Boolean to optimize hub heights of turbines
4342
- `opt_yaw`: Boolean to optimize yaw angles of turbines
4443
- `opt_diam`: Boolean to optimize rotor diameters of turbines
45-
- `force_single_thread`: Boolean to force single thread calculation
4644
"""
4745
function build_wind_farm_struct(x,turbine_x,turbine_y,turbine_z,hub_height,turbine_yaw,rotor_diameter,
4846
ct_models,generator_efficiency,cut_in_speed,cut_out_speed,rated_speed,rated_power,wind_resource,
4947
power_models,model_set,update_function;rotor_sample_points_y=[0.0],rotor_sample_points_z=[0.0],
50-
AEP_scale=0.0,input_type=nothing,opt_x=false,opt_y=false,opt_hub=false,opt_yaw=false,opt_diam=false,
51-
force_single_thread=false)
48+
AEP_scale=0.0,input_type=nothing,opt_x=false,opt_y=false,opt_hub=false,opt_yaw=false,opt_diam=false)
5249

5350
n_turbines = length(turbine_x)
54-
n_threads = Threads.nthreads()
55-
force_single_thread && (n_threads = 1)
5651
results = DiffResults.GradientResult(x)
5752
AEP_gradient = zeros(eltype(x),length(x))
5853
AEP = Array{eltype(x),0}(undef)
@@ -65,6 +60,7 @@ function build_wind_farm_struct(x,turbine_x,turbine_y,turbine_z,hub_height,turbi
6560
cut_out_speed, rated_speed, rated_power, wind_resource, power_models, model_set;
6661
rotor_sample_points_y=rotor_sample_points_y, rotor_sample_points_z=rotor_sample_points_z)
6762

63+
ideal_AEP == 0.0 && (ideal_AEP = 1.0)
6864
(AEP_scale == 0.0) && (AEP_scale = 1.0/ideal_AEP)
6965

7066
cfg = nothing
@@ -86,13 +82,40 @@ function build_wind_farm_struct(x,turbine_x,turbine_y,turbine_z,hub_height,turbi
8682
opt_yaw && (turbine_yaw = Vector{input_type}(turbine_yaw))
8783
opt_diam && (rotor_diameter = Vector{input_type}(rotor_diameter))
8884

89-
preallocations = preallocations_struct(zeros(input_type,n_turbines,n_threads),zeros(input_type,n_turbines,n_threads),
90-
zeros(input_type,n_turbines,n_threads),zeros(input_type,n_turbines,n_threads),zeros(input_type,n_turbines,
91-
n_turbines,n_threads),zeros(input_type,n_turbines,n_turbines,n_threads),
92-
zeros(input_type,n_turbines,n_turbines,n_threads),zeros(input_type,n_turbines,n_turbines,n_threads))
85+
preallocations = create_preallocations(turbine_x, turbine_y, turbine_yaw, rotor_diameter, hub_height, wind_farm_constants.wind_resource, wind_farm_constants.model_set)
9386

9487
return wind_farm_struct(turbine_x, turbine_y, hub_height, turbine_yaw, rotor_diameter, results,
95-
wind_farm_constants, AEP_scale, ideal_AEP, preallocations, update_function, AEP_gradient, AEP, cfg, force_single_thread)
88+
wind_farm_constants, AEP_scale, ideal_AEP, preallocations, update_function, AEP_gradient, AEP, cfg)
89+
end
90+
91+
function create_preallocations(turbine_x, turbine_y, turbine_yaw, rotor_diameter, hub_height, wind_resource, model_set)
92+
n_turbines = length(turbine_x)
93+
n_threads = Threads.nthreads()
94+
n_states = determine_number_of_states(wind_resource, model_set)
95+
T = promote_type(eltype(turbine_x),eltype(turbine_y),eltype(turbine_yaw),eltype(rotor_diameter),eltype(hub_height))
96+
return preallocations_struct(zeros(T,n_turbines,n_threads),zeros(T,n_turbines,n_threads),
97+
zeros(T,n_turbines,n_threads),zeros(T,n_turbines,n_threads),zeros(T,n_turbines,
98+
n_turbines,n_threads),zeros(T,n_turbines,n_turbines,n_threads),
99+
zeros(T,n_turbines,n_turbines,n_threads),zeros(T,n_turbines,n_turbines,n_threads),
100+
zeros(T,n_turbines,n_threads),zeros(T,n_turbines,n_threads),
101+
zeros(T,n_turbines,n_threads),
102+
zeros(Int,n_turbines,n_threads),
103+
zeros(T,n_turbines,n_threads),
104+
zeros(T,n_turbines,n_threads),
105+
zeros(T,n_turbines,n_threads),
106+
zeros(T,n_states))
107+
end
108+
109+
function determine_number_of_states(wind_resource, model_set)
110+
if typeof(model_set.wake_combination_model) == SumOfSquaresFreestreamSuperposition
111+
# find unique directions
112+
unique_directions = unique(wind_resource.wind_directions)
113+
114+
# find how many unique directions there are
115+
return length(unique_directions)
116+
else
117+
return length(wind_resource.wind_directions)
118+
end
96119
end
97120

98121
"""
@@ -171,6 +194,21 @@ function calculate_aep!(farm,x)
171194
- `farm`: The wind_farm_struct
172195
- `x`: Vector containing the design variables
173196
"""
197+
function calculate_aep!(farm,x::Array{ForwardDiff.Dual{T,V,N}}) where {T,V,N}
198+
farm.update_function(farm,x)
199+
200+
AEP = calculate_aep(farm.turbine_x, farm.turbine_y, farm.constants.turbine_z, farm.rotor_diameter,
201+
farm.hub_height, farm.turbine_yaw, farm.constants.ct_models, farm.constants.generator_efficiency,
202+
farm.constants.cut_in_speed, farm.constants.cut_out_speed, farm.constants.rated_speed,
203+
farm.constants.rated_power, farm.constants.wind_resource, farm.constants.power_models,
204+
farm.constants.model_set,rotor_sample_points_y=farm.constants.rotor_sample_points_y,
205+
rotor_sample_points_z=farm.constants.rotor_sample_points_z,
206+
preallocations = farm.preallocations
207+
) .* farm.AEP_scale
208+
209+
return AEP
210+
end
211+
174212
function calculate_aep!(farm,x)
175213
farm.update_function(farm,x)
176214

@@ -180,17 +218,11 @@ function calculate_aep!(farm,x)
180218
farm.constants.rated_power, farm.constants.wind_resource, farm.constants.power_models,
181219
farm.constants.model_set,rotor_sample_points_y=farm.constants.rotor_sample_points_y,
182220
rotor_sample_points_z=farm.constants.rotor_sample_points_z,
183-
prealloc_turbine_velocities=farm.preallocations.prealloc_turbine_velocities,
184-
prealloc_turbine_ct=farm.preallocations.prealloc_turbine_ct,
185-
prealloc_turbine_ai=farm.preallocations.prealloc_turbine_ai,
186-
prealloc_turbine_local_ti=farm.preallocations.prealloc_turbine_local_ti,
187-
prealloc_wake_deficits=farm.preallocations.prealloc_wake_deficits,
188-
prealloc_contribution_matrix=farm.preallocations.prealloc_contribution_matrix,
189-
prealloc_deflections=farm.preallocations.prealloc_deflections,
190-
prealloc_sigma_squared=farm.preallocations.prealloc_sigma_squared,
191-
force_single_thread=farm.force_single_thread
221+
preallocations = farm.preallocations
192222
) .* farm.AEP_scale
193223

224+
farm.AEP[1] = AEP
225+
194226
return AEP
195227
end
196228

@@ -211,20 +243,6 @@ function calculate_aep_gradient!(farm,x)
211243
return farm.AEP[1], farm.AEP_gradient
212244
end
213245

214-
"""
215-
calculate_aep_gradient!(farm,x,sparse_struct::T)
216-
217-
function to calculate the AEP and its gradient for the wind farm using sparse methods
218-
219-
# Arguments
220-
- `farm`: The wind_farm_struct
221-
- `x`: Vector containing the design variables
222-
"""
223-
function calculate_aep_gradient!(farm,x,sparse_struct::T) where T <: AbstractSparseMethod
224-
calculate_aep_gradient!(farm,x,sparse_struct)
225-
return farm.AEP[1], farm.AEP_gradient
226-
end
227-
228246
"""
229247
calculate_spacing!(spacing_vec,x,spacing_struct)
230248

src/utilities.jl

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,31 @@ function rotate_to_wind_direction(xlocs::AbstractArray, ylocs::AbstractArray, wi
4848
return x_cart, y_cart
4949
end
5050

51+
function rotate_to_wind_direction!(x_cart, y_cart, xlocs::AbstractArray, ylocs::AbstractArray, wind_direction_met::Number; center=0.0)
52+
# use radians
53+
54+
# convert from meteorological polar system (CW, 0 rad.=N) to standard polar system (CCW, 0 rad.=E)
55+
wind_direction_cart = met2cart(wind_direction_met)
56+
57+
cos_wdr = cos(-wind_direction_cart)
58+
sin_wdr = sin(-wind_direction_cart)
59+
60+
if center != 0.0
61+
center_x = center[1]
62+
center_y = center[2]
63+
else
64+
center_x = 0.0
65+
center_y = 0.0
66+
end
67+
# convert to cartesian coordinates with wind to positive x
68+
for i in eachindex(xlocs)
69+
x_cart[i] = ((xlocs[i] - center_x) * cos_wdr - (ylocs[i] - center_y) * sin_wdr) + center_x
70+
y_cart[i] = ((xlocs[i] - center_x) * sin_wdr + (ylocs[i] - center_y) * cos_wdr) + center_y
71+
end
72+
73+
return x_cart, y_cart
74+
end
75+
5176
function rotate_to_wind_direction(xlocs::Number, ylocs::Number, wind_direction_met::Number; center=[0.0,0.0])
5277
# use radians
5378

@@ -1683,3 +1708,33 @@ function star_boundary(n, ri, ro, rotation=0.0)
16831708
# return
16841709
return round.(vertices, digits=6)
16851710
end
1711+
1712+
# Nonallocating sortperm function
1713+
function quicksort!(idx, x, lo::Int, hi::Int)
1714+
if lo < hi
1715+
p = partition!(idx, x, lo, hi)
1716+
quicksort!(idx, x, lo, p - 1)
1717+
quicksort!(idx, x, p + 1, hi)
1718+
end
1719+
end
1720+
1721+
function partition!(idx, x, lo::Int, hi::Int)
1722+
pivot = x[idx[hi]]
1723+
i = lo - 1
1724+
@inbounds for j in lo:hi-1
1725+
if x[idx[j]] pivot
1726+
i += 1
1727+
idx[i], idx[j] = idx[j], idx[i]
1728+
end
1729+
end
1730+
idx[i+1], idx[hi] = idx[hi], idx[i+1]
1731+
return i + 1
1732+
end
1733+
1734+
function sortperm!(idx::AbstractVector{Int}, x::AbstractVector)
1735+
@inbounds for i in eachindex(idx)
1736+
idx[i] = i
1737+
end
1738+
quicksort!(idx, x, 1, length(idx))
1739+
return nothing
1740+
end

src/wake_deficit_models.jl

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -571,12 +571,14 @@ end
571571

572572
function _gauss_yaw_discontinuity(dt, x0, ky, kz, yaw, ct)
573573
# for clarity, break out the terms in the equation
574-
a = ky + kz*cos(yaw)
575-
b = 4.0 * ky * kz * cos(yaw)*(ct - 1.0)
576-
c = 2.0 * sqrt(8.0) * ky * kz
574+
cy = cos(yaw)
575+
a = ky + kz*cy
576+
kykz4 = 4.0 * ky * kz
577+
b = kykz4 * cy*(ct - 1.0)
578+
c = kykz4 * sqrt(2)
577579

578580
# distance from rotor to the last point where the wake model is undefined
579-
discontinuity_point = x0 + dt * (a - sqrt(a^2 - b))/c
581+
discontinuity_point = x0 + dt * (a - sqrt(a*a - b))/c
580582

581583
return discontinuity_point
582584
end
@@ -599,10 +601,20 @@ function _gauss_yaw_model_deficit(dx, dy, dz, dt, yaw, ct, ti, as, bs, ky, kz, w
599601
sigma_z = _gauss_yaw_spread_interpolated(dt, kz, dx, x0, 0.0, xd)
600602

601603
# calculate velocity deficit #check - infty when large input ~= 500
602-
ey = exp(-0.5*(dy/(wf*sigma_y))^2)
603-
ez = exp(-0.5*(dz/(wf*sigma_z))^2)
604+
c1 = -0.5*(dy/(wf*sigma_y))^2
605+
c2 = -0.5*(dz/(wf*sigma_z))^2
604606

605-
sqrtterm = 1.0-ct*cos(yaw)/(8.0*(sigma_y*sigma_z/dt^2))
607+
if c1 <= -750.0
608+
loss = 0.0
609+
end
610+
if c2 <= -750.0
611+
loss = 0.0
612+
end
613+
ey = exp(c1)
614+
ez = exp(c2)
615+
616+
dt2 = dt*dt
617+
sqrtterm = 1.0-ct*cos(yaw)/(8.0*(sigma_y*sigma_z/dt2))
606618
if sqrtterm >= 1e-8 #check - could try increasing tolerance
607619
loss = (1.0-sqrt(sqrtterm))*ey*ez
608620
else

src/wake_deflection_models.jl

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,21 @@ function _bpa_theta_0(yaw, ct)
182182
end
183183

184184
function _bpa_deflection(diam, ct, yaw, ky, kz, sigmay, sigmaz, theta0, x0)
185-
a = theta0*x0/diam
186-
b = (theta0/14.7)*sqrt(cos(yaw)/(ky*kz*ct))*(2.9-1.3*sqrt(1.0-ct)-ct)
187-
c = (1.6+sqrt(ct))*(1.6*sqrt(8.0*sigmay*sigmaz/(cos(yaw)*diam^2))-ct)
188-
d = (1.6-sqrt(ct))*(1.6*sqrt(8.0*sigmay*sigmaz/(cos(yaw)*diam^2))+ct)
185+
diam_inv = 1.0/diam
186+
a = theta0*x0*diam_inv
187+
b1 = cos(yaw)
188+
b = (theta0/14.7)*sqrt(b1/(ky*kz*ct))*(2.9-1.3*sqrt(1.0-ct)-ct)
189+
190+
c1 = 1.6*sqrt(8.0*sigmay*sigmaz * diam_inv * diam_inv / b1)
191+
c2 = sqrt(ct)
192+
193+
# c = (1.6+c2)*(c1-ct)
194+
# d = (1.6-c2)*(c1+ct)
195+
g1 = 1.6*c1-c2*ct
196+
g2 = -1.6*ct+c1*c2
197+
c = g1+g2
198+
d = g1-g2
199+
189200
y_deflection = diam*(a+b*log(c/d))
190201
return y_deflection
191202
end

src/windfarms.jl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ Unifying struct defining a wind farm and all necessary variables to calculate th
2121
- `AEP_gradient`: The gradient of the AEP
2222
- `AEP`: The AEP of the farm
2323
- `config`: The ForwardDiff config object if using ForwardDiff for AEP gradient calculation, otherwise nothing
24-
- `force_single_thread`: Boolean that forces the code to run in a single thread
2524
"""
26-
struct wind_farm_struct{T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15} <: AbstractWindFarmModel
25+
struct wind_farm_struct{T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14} <: AbstractWindFarmModel
2726
turbine_x::T1
2827
turbine_y::T2
2928
hub_height::T3
@@ -38,7 +37,6 @@ struct wind_farm_struct{T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15} <: A
3837
AEP_gradient::T12
3938
AEP::T13
4039
config::T14
41-
force_single_thread::T15
4240
end
4341

4442
"""
@@ -56,7 +54,7 @@ struct that holds all the preallocated space for AEP calculation with one per th
5654
- `prealloc_deflections`: Matrix containing preallocated space for deflections
5755
- `prealloc_sigma_squared`: Matrix containing preallocated space for sigma squared
5856
"""
59-
struct preallocations_struct{V,M}
57+
struct preallocations_struct{V,M,VI,Ve}
6058
prealloc_turbine_velocities::V
6159
prealloc_turbine_ct::V
6260
prealloc_turbine_ai::V
@@ -65,6 +63,14 @@ struct preallocations_struct{V,M}
6563
prealloc_contribution_matrix::M
6664
prealloc_deflections::M
6765
prealloc_sigma_squared::M
66+
prealloc_rot_x::V
67+
prealloc_rot_y::V
68+
prealloc_power::V
69+
prealloc_sort_index::VI
70+
prealloc_diam::V
71+
prealloc_hub::V
72+
prealloc_yaw::V
73+
prealloc_state_aep::Ve
6874
end
6975

7076
"""

test/plottest.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function plot_velocity_row_deficit()
2222
include("./model_sets/model_set_2.jl")
2323

2424
# calculate wind turbine velocities and corresponding aerodynamic operational states
25-
turbine_inflow_velcities, turbine_ct, turbine_ai, turbine_local_ti = ff.turbine_velocities_one_direction(turbine_x, turbine_y, turbine_z, rotor_diameter, hub_height, turbine_yaw,
25+
turbine_inflow_velcities, turbine_ct, turbine_ai, turbine_local_ti = ff.turbine_velocities_one_direction_full(turbine_x, turbine_y, turbine_z, rotor_diameter, hub_height, turbine_yaw,
2626
sorted_turbine_index, ct_model, rotor_sample_points_y, rotor_sample_points_z, windresource,
2727
model_set, wind_farm_state_id=1)
2828

0 commit comments

Comments
 (0)