diff options
author | sotech117 <michael_foiani@brown.edu> | 2024-04-27 04:25:23 -0400 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2024-04-27 04:25:23 -0400 |
commit | e650ed1e1e908e51c78c1b047bec0da7c4fea366 (patch) | |
tree | 1fe238de7ca199b7fdee9bc29395080b3c4790e7 /hw7/8-12.jl | |
parent | 02756d17bca6f2b3bafa3f7b9fb6e5af438e94a0 (diff) |
testing
Diffstat (limited to 'hw7/8-12.jl')
-rw-r--r-- | hw7/8-12.jl | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/hw7/8-12.jl b/hw7/8-12.jl new file mode 100644 index 0000000..29e18ec --- /dev/null +++ b/hw7/8-12.jl @@ -0,0 +1,191 @@ +#!/Applications/Julia-1.7.app/Contents/Resources/julia/bin/julia + +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::Float64 + magnetization::Int + mc_steps::Int + accepted_moves::Int + energy_array::Vector{Float64} + magnetization_array::Vector{Int} + H::Float64 +end + +Ising2D(l::Int, temperature::Float64, H=1.0) = 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 = Float64(-2 * n + 2 * H * n) + magnetization = n + return Ising2D(l, n, temperature, w, state, energy, magnetization, 0, 0, + Int[], Int[], H) +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 + + changed_spins = 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)]) + de = 2 * changed_spins + 2 * ising.H * state[i, j] + + if de <= 0 || rand() < exp(-de / ising.temperature) + accepted_moves += 1 + new_spin = - state[i, j] # flip spin + state[i, j] = new_spin + + # add the effects of the 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 find_m(H::Float64, l::Int, num::Int, T::Float64) + m = Ising2D(l, T, H) + steps!(m, num) + print("T = $T\n") + print("H = $H\n") + print("Mean Energy: $(mean_energy(m))\n") + print("Mean Magnetization: $(mean_magnetization(m))\n\n") + return mean_magnetization(m) +end + +function map_h_to_m(H_range::Vector{Float64}, l::Int, num::Int, T::Float64) + m = [] + for H in H_range + push!(m, find_m(H, l, num, T)) + end + return m +end + +function do_linear_regression(x::Vector{Float64}, y::Vector{Float64}) + n = length(x) + x̄ = mean(x) + ȳ = mean(y) + Σxy = sum((x .- x̄) .* (y .- ȳ)) + Σx² = sum((x .- x̄) .^ 2) + b = Σxy / Σx² + a = ȳ - b * x̄ + return a, b +end + +function plot_log_of_m_and_h(H_range::Vector{Float64}, l::Int, num::Int, T=2.27) + m = map_h_to_m(H_range, l, num, T) + p = scatter(H_range, m, label="M vs H", xlabel="H", ylabel="M", title="Magnetization (M) vs Field (B) for Ising Model at T_c", scale=:ln) + + # get the linear regression of the log + log_h = log.(H_range) + log_m = log.(m) + a, b = do_linear_regression(log_h, log_m) + println("a: $a, b: $b") + # plot the linear regression + plot!(p, H_range, exp.(a) .* H_range .^ b, label="linear regression = $(round(a, digits=3)) + $(round(b, digits=3))x", line=:dash, color=:red) + + return p +end + +# textbook rec +h_range = .02:.02:.2 +h_range = collect(h_range) +T = 2.27 # T_c for this system +side = 64 +steps = 5000 +plot_log_of_m_and_h(h_range, side, steps)
\ No newline at end of file |