Skip to content

Commit e573218

Browse files
committed
Add docstring for KPS4()
1 parent 8ba6f5d commit e573218

1 file changed

Lines changed: 52 additions & 40 deletions

File tree

src/KPS4.jl

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
#= Model of a kite-power system in implicit form: residual = f(y, yd)
55
66
This model implements a 3D mass-spring system with reel-out. It uses six tether segments (the number can be
7-
configured in the file data/settings.yaml). The kite is modelled using 4 point masses and 3 aerodynamic
7+
configured in the file data/settings.yaml). The kite is modelled using 4 point masses and 3 aerodynamic
88
surfaces. The spring constant and the axial_damping decrease with the segment length. The aerodynamic kite forces
9-
are acting on three of the four kite point masses.
9+
are acting on three of the four kite point masses.
1010
1111
Four point kite model, included from KiteModels.jl.
1212
@@ -16,7 +16,7 @@ Scientific background: http://arxiv.org/abs/1406.6218 =#
1616
# First point, second point, unstressed length.
1717
const SPRINGS_INPUT = [0. 1. 150.
1818
1. 2. -1. # s1, p7, p8
19-
4. 2. -1. # s2, p10, p8
19+
4. 2. -1. # s2, p10, p8
2020
4. 5. -1. # s3, p10, p11
2121
3. 4. -1. # s4, p9, p10
2222
5. 1. -1. # s5, p11, p7
@@ -76,9 +76,9 @@ $(TYPEDFIELDS)
7676
calc_cl::Spline1D
7777
"Function for calculation the drag coefficient, using a spline based on the provided value pairs."
7878
calc_cd::Spline1D
79-
"wind vector at the height of the kite"
79+
"wind vector at the height of the kite"
8080
v_wind::T = zeros(S, 3)
81-
"wind vector at reference height"
81+
"wind vector at reference height"
8282
v_wind_gnd::T = zeros(S, 3)
8383
"wind vector used for the calculation of the tether drag"
8484
v_wind_tether::T = zeros(S, 3)
@@ -97,12 +97,12 @@ $(TYPEDFIELDS)
9797
"max_steering angle in radian"
9898
ks::S = 0.0
9999
"lift force of the kite; output of calc_aero_forces!"
100-
lift_force::T = zeros(S, 3)
100+
lift_force::T = zeros(S, 3)
101101
"spring force of the current tether segment, output of calc_particle_forces!"
102102
spring_force::T = zeros(S, 3)
103103
"last winch force"
104104
last_force::T = zeros(S, 3)
105-
"a copy of the residual one (pos,vel) for debugging and unit tests"
105+
"a copy of the residual one (pos,vel) for debugging and unit tests"
106106
res1::SVector{P, KVec3} = zeros(SVector{P, KVec3})
107107
"a copy of the residual two (vel,acc) for debugging and unit tests"
108108
res2::SVector{P, KVec3} = zeros(SVector{P, KVec3})
@@ -206,7 +206,7 @@ function clear!(s::KPS4)
206206
s.segment_length = s.l_tether / s.set.segments
207207
init_masses!(s)
208208
init_springs!(s)
209-
for i in 1:s.set.segments + KiteModels.KITE_PARTICLES + 1
209+
for i in 1:s.set.segments + KiteModels.KITE_PARTICLES + 1
210210
s.forces[i] .= zeros(3)
211211
end
212212
s.drag_force .= [0.0, 0, 0]
@@ -236,7 +236,7 @@ function clear!(s::KPS4)
236236
s.psi = 0.0
237237
s.rho = s.set.rho_0
238238
s.bridle_factor = s.set.l_bridle / bridle_length(s.set)
239-
s.ks = deg2rad(Float64(s.set.max_steering))
239+
s.ks = deg2rad(Float64(s.set.max_steering))
240240
s.kcu.depower = s.set.depower::Float64/100.0
241241
s.kcu.set_depower = s.kcu.depower
242242
s.kcu.steering = 0.0
@@ -254,16 +254,28 @@ function clear!(s::KPS4)
254254
KiteModels.set_depower_steering!(s, get_depower(s.kcu), get_steering(s.kcu))
255255
end
256256

257+
"""
258+
KPS4(kcu::KCU)
259+
260+
Create and initialize a four-point kite power system model from an existing
261+
KCU (kite control unit) instance.
262+
263+
This constructor selects the winch model based on `kcu.set.winch_model`,
264+
creates interpolation splines for lift/drag coefficients, and calls `clear!`
265+
to initialize all state variables.
266+
267+
Returns a `KPS4` instance ready for `init!`/`find_steady_state!` and simulation.
268+
"""
257269
function KPS4(kcu::KCU)
258270
wm = if kcu.set.winch_model == "AsyncMachine"
259271
AsyncMachine(kcu.set)
260272
elseif kcu.set.winch_model == "TorqueControlledMachine"
261273
TorqueControlledMachine(kcu.set)
262274
end
263275
# wm.last_set_speed = kcu.set.v_reel_out
264-
s = KPS4{SimFloat, KVec3, kcu.set.segments+KITE_PARTICLES+1, kcu.set.segments+KITE_SPRINGS, SP}(set=kcu.set,
265-
kcu=kcu, wm=wm, calc_cl = Spline1D(kcu.set.alpha_cl, kcu.set.cl_list),
266-
calc_cd=Spline1D(kcu.set.alpha_cd, kcu.set.cd_list) )
276+
s = KPS4{SimFloat, KVec3, kcu.set.segments+KITE_PARTICLES+1, kcu.set.segments+KITE_SPRINGS, SP}(set=kcu.set,
277+
kcu=kcu, wm=wm, calc_cl = Spline1D(kcu.set.alpha_cl, kcu.set.cl_list),
278+
calc_cd=Spline1D(kcu.set.alpha_cd, kcu.set.cd_list) )
267279
clear!(s)
268280
return s
269281
end
@@ -272,17 +284,17 @@ function KPS4(set::Settings)
272284
KPS4(kcu)
273285
end
274286

275-
"""
287+
"""
276288
calc_particle_forces!(s::KPS4, pos1, pos2, vel1, vel2, spring, segments, d_tether, rho, i)
277289
278290
Calculate the drag force of the tether segment, defined by the parameters pos1, pos2, vel1 and vel2
279291
and distribute it equally on the two particles, that are attached to the segment.
280-
The result is stored in the array s.forces.
292+
The result is stored in the array s.forces.
281293
"""
282294
@inline function calc_particle_forces!(s::KPS4, pos1, pos2, vel1, vel2, spring, segments, d_tether, rho, i)
283295
l_0 = spring.length # Unstressed length
284296
k = spring.axial_stiffness * s.stiffness_factor # Spring constant
285-
c = spring.axial_damping # Damping coefficient
297+
c = spring.axial_damping # Damping coefficient
286298
segment = pos1 - pos2
287299
rel_vel = vel1 - vel2
288300
av_vel = 0.5 * (vel1 + vel2)
@@ -295,7 +307,7 @@ The result is stored in the array s.forces.
295307
spring_vel = unit_vector rel_vel
296308
if (norm1 - l_0) > 0.0
297309
if i > segments # kite springs
298-
s.spring_force .= (k * (norm1 - l_0) + (c1 * spring_vel)) * unit_vector
310+
s.spring_force .= (k * (norm1 - l_0) + (c1 * spring_vel)) * unit_vector
299311
else
300312
s.spring_force .= (k * (norm1 - l_0) + (c * spring_vel)) * unit_vector
301313
end
@@ -318,7 +330,7 @@ The result is stored in the array s.forces.
318330
end
319331

320332
v_app_perp = s.v_apparent - s.v_apparent unit_vector * unit_vector
321-
half_drag_force = (-0.25 * rho * s.set.cd_tether * norm(v_app_perp) * area) * v_app_perp
333+
half_drag_force = (-0.25 * rho * s.set.cd_tether * norm(v_app_perp) * area) * v_app_perp
322334
if i == segments
323335
v_app_perp_kcu = v_app_kcu - v_app_kcu unit_vector * unit_vector
324336
kcu_area = π * (s.set.kcu_diameter/2)^2
@@ -355,7 +367,7 @@ Updates the vector s.forces of the first parameter.
355367
pos_B, pos_C, pos_D = pos[s.set.segments+3], pos[s.set.segments+4], pos[s.set.segments+5]
356368
v_A, v_B, v_C, v_D = vel[s.set.segments+2], vel[s.set.segments+3], vel[s.set.segments+4], vel[s.set.segments+5]
357369
va_1, va_2, va_3, va_4 = s.v_wind - v_A, s.v_wind - v_B, s.v_wind - v_C, s.v_wind - v_D
358-
370+
359371
pos_centre = 0.5 * (pos_C + pos_D)
360372
delta = pos_B - pos_centre
361373
z = -normalize(delta)
@@ -448,7 +460,7 @@ end
448460
loop!(s::KPS4, pos, vel, posd, veld)
449461
450462
Calculate the vectors s.res1 and calculate s.res2 using loops
451-
that iterate over all tether segments.
463+
that iterate over all tether segments.
452464
"""
453465
function loop!(s::KPS4, pos, vel, posd, veld)
454466
L_0 = s.l_tether / s.set.segments
@@ -462,14 +474,14 @@ function loop!(s::KPS4, pos, vel, posd, veld)
462474
s.res2[1] .= vel[1]
463475
particles = s.set.segments + KITE_PARTICLES + 1
464476
for i in 2:particles
465-
s.res1[i] .= vel[i] - posd[i]
477+
s.res1[i] .= vel[i] - posd[i]
466478
end
467479
# Compute the masses and forces
468480
m_tether_particle = mass_per_meter * s.segment_length
469481
s.masses[s.set.segments+1] = s.set.kcu_mass + 0.5 * m_tether_particle
470482
# TODO: check if the next two lines are correct
471483
axial_damping = s.set.axial_damping / L_0
472-
axial_stiffness = s.set.axial_stiffness/L_0
484+
axial_stiffness = s.set.axial_stiffness/L_0
473485
for i in 1:s.set.segments
474486
@inbounds s.masses[i] = m_tether_particle
475487
@inbounds s.springs[i] = SP(s.springs[i].p1, s.springs[i].p2, s.segment_length, axial_stiffness, axial_damping)
@@ -488,12 +500,12 @@ end
488500
State vector y = pos1, pos2, ... , posn, vel1, vel2, . .., veln, length, v_reel_out
489501
Derivative yd = posd1, posd2, ..., posdn, veld1, veld2, ..., veldn, lengthd, v_reel_outd
490502
Output:
491-
Residual res = res1, res2 = vel1-posd1, ..., veld1-acc1, ...,
503+
Residual res = res1, res2 = vel1-posd1, ..., veld1-acc1, ...,
492504
493505
Additional parameters:
494506
s: Struct with work variables, type KPS4
495507
S: The dimension of the state vector
496-
The number of the point masses of the model N = S/6, the state of each point
508+
The number of the point masses of the model N = S/6, the state of each point
497509
is represented by two 3 element vectors.
498510
"""
499511
function residual!(res, yd, y::Vector{SimFloat}, s::KPS4, time)
@@ -505,7 +517,7 @@ end
505517
function residual!(res, yd, y::MVector{S, SimFloat}, s::KPS4, _) where S
506518
T = S-2 # T: three times the number of particles excluding the origin
507519
segments = div(T,6) - KITE_PARTICLES
508-
520+
509521
# Reset the force vector to zero.
510522
for i in 1:segments+KITE_PARTICLES+1
511523
s.forces[i] .= SVector(0.0, 0, 0)
@@ -540,9 +552,9 @@ function residual!(res, yd, y::MVector{S, SimFloat}, s::KPS4, _) where S
540552
use_brake = true
541553
end
542554
if s.wm isa AsyncMachine
543-
res[end] = v_reel_outd - calc_acceleration(s.wm::AsyncMachine, s.sync_speed, v_reel_out, norm(s.forces[1]), true)
555+
res[end] = v_reel_outd - calc_acceleration(s.wm::AsyncMachine, s.sync_speed, v_reel_out, norm(s.forces[1]), true)
544556
elseif !isnothing(s.wm)
545-
res[end] = v_reel_outd - calc_acceleration(s.wm, v_reel_out, norm(s.forces[1]); set_speed=s.sync_speed,
557+
res[end] = v_reel_outd - calc_acceleration(s.wm, v_reel_out, norm(s.forces[1]; set_speed=s.sync_speed,
546558
set_torque=s.set_torque, use_brake)
547559
else
548560
res[end] = v_reel_outd
@@ -607,7 +619,7 @@ end
607619
"""
608620
winch_force(s::KPS4)
609621
610-
Return the absolute value of the force at the winch as calculated during the last timestep.
622+
Return the absolute value of the force at the winch as calculated during the last timestep.
611623
"""
612624
function winch_force(s::KPS4) norm(s.last_force) end
613625

@@ -654,13 +666,13 @@ function spring_forces(s::KPS4; prn=true)
654666
pos1, pos2 = s.pos[p1], s.pos[p2]
655667
spring = s.springs[i+s.set.segments]
656668
l_0 = spring.length # Unstressed length
657-
k = spring.axial_stiffness * s.stiffness_factor # Spring constant
669+
k = spring.axial_stiffness * s.stiffness_factor # Spring constant
658670
segment = pos1 - pos2
659671
norm1 = norm(segment)
660672
k1 = 0.25 * k # compression stiffness kite segments
661673
if (norm1 - l_0) > 0.0
662-
spring_force = k * (norm1 - l_0)
663-
else
674+
spring_force = k * (norm1 - l_0)
675+
else
664676
spring_force = k1 * (norm1 - l_0)
665677
end
666678
forces[i+s.set.segments] = spring_force
@@ -720,12 +732,12 @@ function find_steady_state!(s::KPS4; prn=false, delta = 0.001, stiffness_factor=
720732
end
721733
# copy the acceleration of point KCU in x direction
722734
i = s.set.segments+1
723-
F[end-1] = res[1 + 3*(i-1) + 3*(s.set.segments+KITE_PARTICLES)]
735+
F[end-1] = res[1 + 3*(i-1) + 3*(s.set.segments+KITE_PARTICLES)]
724736
# copy the acceleration of point C in y direction
725-
i = s.set.segments+3
737+
i = s.set.segments+3
726738
x = res[1 + 3*(i-1) + 3*(s.set.segments+KITE_PARTICLES)]
727-
F[end] = res[2 + 3*(i-1) + 3*(s.set.segments+KITE_PARTICLES)]
728-
return nothing
739+
F[end] = res[2 + 3*(i-1) + 3*(s.set.segments+KITE_PARTICLES)]
740+
return nothing
729741
end
730742
if prn println("\nStarted function test_nlsolve...") end
731743
X00 = zeros(SimFloat, 2*(s.set.segments+KITE_PARTICLES-1)+2)
@@ -747,7 +759,7 @@ const PRE_STRESS = 0.9998 # Multiplier for the initial spring lengths.
747759
# Functions to calculate the initial state vector, the initial masses and initial springs
748760

749761
function init_springs!(s::KPS4)
750-
l_0 = s.set.l_tethers[1] / s.set.segments
762+
l_0 = s.set.l_tethers[1] / s.set.segments
751763
particles = KiteUtils.get_particles(s.set.height_k, s.set.h_bridle, s.set.width, s.set.m_k)
752764
for j in 1:size(SPRINGS_INPUT)[1]
753765
# build the tether segments
@@ -776,7 +788,7 @@ end
776788
function init_masses!(s::KPS4)
777789
MASS_FACTOR = 1.0
778790
s.masses = zeros(s.set.segments+KITE_PARTICLES+1)
779-
l_0 = s.set.l_tethers[1] / s.set.segments
791+
l_0 = s.set.l_tethers[1] / s.set.segments
780792
for i in 1:s.set.segments
781793
s.masses[i] += 0.5 * l_0 * s.set.rho_tether * (s.set.d_tether/2000.0)^2 * pi
782794
s.masses[i+1] += 0.5 * l_0 * s.set.rho_tether * (s.set.d_tether/2000.0)^2 * pi
@@ -789,7 +801,7 @@ function init_masses!(s::KPS4)
789801
s.masses[s.set.segments+3] += k2 * s.set.mass * MASS_FACTOR
790802
s.masses[s.set.segments+4] += k3 * s.set.mass * MASS_FACTOR
791803
s.masses[s.set.segments+5] += k4 * s.set.mass * MASS_FACTOR
792-
s.masses
804+
s.masses
793805
end
794806

795807
function init_pos_vel_acc(s::KPS4, X=zeros(2 * (s.set.segments+KITE_PARTICLES)+1); old=false, delta = 0.0)
@@ -810,7 +822,7 @@ function init_pos_vel_acc(s::KPS4, X=zeros(2 * (s.set.segments+KITE_PARTICLES)+1
810822
if old
811823
particles = KiteUtils.get_particles(s.set.height_k, s.set.h_bridle, s.set.width, s.set.m_k)
812824
else
813-
particles = KiteUtils.get_particles(s.set.height_k, s.set.h_bridle, s.set.width, s.set.m_k,
825+
particles = KiteUtils.get_particles(s.set.height_k, s.set.h_bridle, s.set.width, s.set.m_k,
814826
pos[s.set.segments+1], rotate_around_y(vec_c, deg2rad(KITE_ANGLE)), s.v_apparent)
815827
end
816828
j = 1
@@ -836,7 +848,7 @@ function init_pos_vel_acc(s::KPS4, X=zeros(2 * (s.set.segments+KITE_PARTICLES)+1
836848
end
837849
# the velocity vector of the kite particles is the same as the velocity of the last tether point
838850
for i in s.set.segments+2:s.set.segments+KITE_PARTICLES+1
839-
vel[i] .+= vel[s.set.segments+1]
851+
vel[i] .+= vel[s.set.segments+1]
840852
end
841853
pos, vel, acc
842854
end
@@ -847,7 +859,7 @@ function set_initial_velocity!(s::KPS4)
847859
end
848860
# the velocity vector of the kite particles is the same as the velocity of the last tether point
849861
for i in s.set.segments+2:s.set.segments+KITE_PARTICLES+1
850-
s.vel[i] .= s.vel[s.set.segments+1]
862+
s.vel[i] .= s.vel[s.set.segments+1]
851863
end
852864
end
853865

0 commit comments

Comments
 (0)