aboutsummaryrefslogtreecommitdiff
path: root/hw5/fpu-2.jl
blob: 3190f2b091d849e69692e51f8fb08563aac68ba4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
using Plots

N = 32 # number of masses
b =.3 # cubic string spring
A = 10 # amplitude
modes = 3 # number of modes to plot
final_time = 30 # seconds
dt = .05 # seconds


# get the intial positions
function calculate_x_i(mass_num, node_num, num_masses, amplitutude)
    return A *
        sqrt(2 / (num_masses + 1)) * 
        sin((mass_num * node_num * π) / (num_masses + 1))
end

# dynamics calculations
function dynamics!(
    mass_displacement, # 2d array
    params)
    (beta, delta_t, num_masses, num_steps) = params

    for step in 1:num_steps-1
        if step == 1
            continue
        end
        for mass_num in 2:num_masses-1

            if step == 1
                prev_mass_pos = 0
            else
                prev_mass_pos = mass_displacement[mass_num, step - 1]
            end

            right_mass_pos = mass_displacement[mass_num + 1, step]
            left_mass_pos = mass_displacement[mass_num - 1, step]

            mass_pos = mass_displacement[mass_num, step]

            xs[mass_num, step + 1] = caluclate_next_displacement(
                mass_pos, prev_mass_pos, 
                left_mass_pos, right_mass_pos, beta, delta_t)
        end

        # update the end points
        mass_displacement[1, step + 1] = caluclate_next_displacement(
            0, 0, 
            0, mass_displacement[2, step], beta, delta_t)
        mass_displacement[num_masses, step + 1] = caluclate_next_displacement(
            0, 0, 
            mass_displacement[num_masses - 1, step], 0, beta, delta_t)
    end

end

function caluclate_next_displacement(
    mass_pos, prev_mass_pos,
    left_mass_pos, right_mass_pos, 
    beta, delta_t
)
    # println(mass_pos, " " , prev_mass_pos, " ", left_mass_pos, " ", right_mass_pos, '\n')
    return 2 * mass_pos - prev_mass_pos
        + delta_t^(2) * (right_mass_pos + left_mass_pos - 2 * mass_pos)
        + beta * delta_t^(2) * ((right_mass_pos - mass_pos)^3 + (left_mass_pos - mass_pos)^3)
end


# energy calcuations, after the dynamics
function calculate_a_k(k, num_masses, delta_t, xs_n, beta)
    sum = 0
    for i in 1:num_masses
        sum += xs_n[i] * sin((k * i * π) / (num_masses + 1))
    end
    return sqrt(2 / (num_masses + 1)) * sum
end

function calculate_energy(a_k, a_k_plus1, delta_t, mode, num_masses)
    kinetic = .5 * ((a_k_plus1 - a_k) / delta_t)^2

    # sum over the three modes
    w_k = 2 * sin((mode * π) / (2 * (num_masses + 1)))
    potential = .5 * (w_k^2 * a_k^2)

    return kinetic + potential
end


# do the simulation
num_steps = Int(final_time / dt)
params = (b, dt, N, num_steps)
# build the 2d array of mass displacements to time
xs = zeros(N, num_steps)
# fill in the initial displacements
for mass_num in 2:N-1
    xs[mass_num, 1] = calculate_x_i(mass_num, 1, N, A)
end
dynamics!(xs, params)

# println(xs)


# plot these displacements over time as an animation
a = @animate for i in 1:num_steps
    plot(xs[:, i], legend=false, 
    marker = :circle, xlabel="Mass Number", ylabel="Displacement",
    yaxis = (-30, 30), title="Displacement Over Time"
    )
end

gif(a, "fpu.gif", fps=15)

# plot the first two timespets positions
# plot(xs[:, 1], label="t=0", marker=:circle, xlabel="Mass Number", ylabel="Displacement", title="First Two Time Steps")
# plot!(xs[:, 2], label="t=1", marker=:circle)
# plot!(xs[:, 3], label="t=2", marker=:circle)
# plot!(xs[:, 4], label="t=3", marker=:circle)
# plot!(xs[:, 5], label="t=4", marker=:circle)
# plot!(xs[:, 6], label="t=5", marker=:circle)
# plot!(xs[:, 7], label="t=6", marker=:circle)


# # calculate the energies for each mode from the displacements 
# energies = zeros(modes, num_steps)
# for mode in 1:modes
#     energies[mode, :] = calculate_energy_for_mode(mode, xs, N, dt, b)
# end

# make a range time steps
# time = range(0, final_time, length=num_steps)

# println("e:", length(energies[1, :]))
# println("t:", length(time))

# plot the energies for each mode
# scatter(time, energies[1, :], label="Mode 1", marker=:circle, xlabel="Time", ylabel="Energy", title="Energy for First Three Modes")
# scatter!(time, energies[2, :], label="Mode 2", marker=:circle)
# scatter!(time, energies[3, :], label="Mode 3", marker=:circle)