diff options
Diffstat (limited to 'hw6/8-11.jl')
-rw-r--r-- | hw6/8-11.jl | 198 |
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 |