aboutsummaryrefslogtreecommitdiff
path: root/hw6/8-11.jl
diff options
context:
space:
mode:
Diffstat (limited to 'hw6/8-11.jl')
-rw-r--r--hw6/8-11.jl198
1 files changed, 198 insertions, 0 deletions
diff --git a/hw6/8-11.jl b/hw6/8-11.jl
new file mode 100644
index 0000000..e8a0b2e
--- /dev/null
+++ b/hw6/8-11.jl
@@ -0,0 +1,198 @@
+# FOR PROBLEM 8.11
+# author: sotech117
+
+using Statistics
+using Plots
+
+function wrap_index(i::Int, l::Int)::Int
+ wrap = (i - 1) % l + 1
+ return (wrap <= 0) ? l + wrap : wrap
+end
+
+mutable struct Ising2D
+ l::Int
+ n::Int
+ temperature::Float64
+ w::Vector{Float64} # Boltzmann weights
+ state::Matrix
+ energy::Int
+ magnetization::Int
+ mc_steps::Int
+ accepted_moves::Int
+ energy_array::Vector{Int}
+ magnetization_array::Vector{Int}
+end
+
+Ising2D(l::Int, temperature::Float64) = begin
+ n = l^2
+ w = zeros(9)
+ w[9] = exp(-8.0 / temperature)
+ w[5] = exp(-4.0 / temperature)
+ state = ones(Int, l, l) # initially all spins up
+ energy = -2 * n
+ magnetization = n
+ return Ising2D(l, n, temperature, w, state, energy, magnetization, 0, 0,
+ Int[], Int[])
+end
+
+function reset!(ising::Ising2D)
+ ising.mc_steps = 0
+ ising.accepted_moves = 0
+ ising.energy_array = Int[]
+ ising.magnetization_array = Int[]
+end
+
+function mc_step!(ising::Ising2D)
+ l::Int = ising.l
+ n::Int = ising.n
+ w = ising.w
+
+ state = ising.state
+ accepted_moves = ising.accepted_moves
+ energy = ising.energy
+ magnetization = ising.magnetization
+
+ random_positions = l * rand(2 * n)
+ random_array = rand(n)
+
+ for k in 1:n
+ i = trunc(Int, random_positions[2 * k - 1]) + 1
+ j = trunc(Int, random_positions[2 * k]) + 1
+
+ de = 2 * state[i, j] * (state[i % l + 1, j] +
+ state[wrap_index(i - 1, l), j] + state[i, j % l + 1] +
+ state[i, wrap_index(j - 1, l)])
+
+ if de <= 0 || w[de + 1] > random_array[k]
+ accepted_moves += 1
+ new_spin = - state[i, j] # flip spin
+ state[i, j] = new_spin
+ energy += de
+ magnetization += 2 * new_spin
+ end
+
+ end
+
+ ising.state = state
+ ising.accepted_moves = accepted_moves
+ ising.energy = energy
+ ising.magnetization = magnetization
+
+ append!(ising.energy_array, ising.energy)
+ append!(ising.magnetization_array, ising.magnetization)
+ ising.mc_steps = ising.mc_steps + 1
+end
+
+function steps!(ising::Ising2D, num::Int=100)
+ for i in 1:num
+ mc_step!(ising)
+ end
+end
+
+function mean_energy(ising::Ising2D)
+ return mean(ising.energy_array) / ising.n
+end
+
+function specific_heat(ising::Ising2D)
+ return (std(ising.energy_array) / ising.temperature) ^ 2 / ising.n
+end
+
+function mean_magnetization(ising::Ising2D)
+ return mean(ising.magnetization_array) / ising.n
+end
+
+function susceptibility(ising::Ising2D)
+ return (std(ising.magnetization_array)) ^ 2 / (ising.temperature * ising.n)
+end
+
+function observables(ising::Ising2D)
+ printstyled("Temperature\t\t", bold=true)
+ print(ising.temperature); print("\n")
+
+ printstyled("Mean Energy\t\t", bold=true)
+ print(mean_energy(ising)); print("\n")
+
+ printstyled("Mean Magnetiz.\t\t", bold=true)
+ print(mean_magnetization(ising)); print("\n")
+
+ printstyled("Specific Heat\t\t", bold=true)
+ print(specific_heat(ising)); print("\n")
+
+ printstyled("Susceptibility\t\t", bold=true)
+ print(susceptibility(ising)); print("\n")
+
+ printstyled("MC Steps\t\t", bold=true)
+ print(ising.mc_steps); print("\n")
+ printstyled("Accepted Moves\t\t", bold=true)
+ print(ising.accepted_moves); print("\n")
+end
+
+
+function plot_ising(state::Matrix{Int})
+ pos = Tuple.(findall(>(0), state))
+ neg = Tuple.(findall(<(0), state))
+ scatter(pos, markersize=5)
+ scatter!(neg, markersize=5)
+end
+
+
+function get_magnetization(T, n=1000)
+ m = Ising2D(64, T)
+ steps!(m, n)
+
+ println("done with T = $T")
+ return mean_magnetization(m)
+end
+
+Ts = 0:.1:5
+ms = [abs(get_magnetization(T)) for T in Ts]
+
+println("done with calculating magnetizations")
+
+function linear_regression(x, y)
+ n = length(x)
+ x̄ = sum(x) / n
+ ȳ = sum(y) / n
+ a = sum((x .- x̄) .* (y .- ȳ)) / sum((x .- x̄).^2)
+ b = ȳ - a * x̄
+ return (a, b)
+end
+
+# plot M^(8) over T
+betas = .001:.001:1
+residuals = []
+for i in 1:length(betas)
+ b = betas[i]
+ m = ms .^ (1 / b)
+ # filter out the zero values
+
+
+ s = scatter(p,
+ Ts, m, xlabel="T (units of J / k_b)", ylabel="Magnetization", label="$b-beta", title="Magnetization vs Temp (Ising Monte Carlo)",
+ msw=0, ms=1.5, mc=:red, lc=:red, lw=1.5, legend=:bottomleft
+ )
+
+
+ # do a linear regression
+ a, b = linear_regression(Ts, m)
+
+ # plot a linear regression line
+ plot!(s, Ts, a*Ts .+ b, label="Linear Regression", lw=1.2, color=:red, linestyle=:dash)
+
+ # calculate the residuals
+ push!(residuals, sum((m .- (a*Ts .+ b)).^2))
+
+
+ savefig(s, "hw6/b/8-2-$i.png")
+end
+
+# plot the residuals over beta
+plot(betas, residuals, xlabel="beta", ylabel="Squared Distance", label="Residuals", title="Error from Linear Regression of M^(1/Beta)", lw=1.2, lc=:red, legend=:topright)
+# find the min on the first half of the residuals
+min_residuali = argmin(residuals[1:div(length(residuals), 2)])
+min_residual = betas[min_residuali]
+println("Minimum Residual: ", min_residual)
+vline!([min_residual], label="Minimum Point @ Beta = $min_residual", lc=:orange, lw=1.5, ls=:dash)
+# plot the analityical beta of .125
+vline!([.125], label="Analytical Minimum Beta = .125", lc=:green, lw=1.5, ls=:dot)
+savefig("hw6/8-2-residuals-100.png") \ No newline at end of file