2021-12-03 13:41:01 +00:00
|
|
|
using StaticArrays: SVector, SMatrix
|
2021-12-04 15:19:14 +00:00
|
|
|
using LinearAlgebra: eigvals, Hermitian
|
2021-12-03 13:16:35 +00:00
|
|
|
|
2021-12-08 20:53:15 +00:00
|
|
|
function project_to_unit_circle(x::Float64, l::Float64)
|
2021-12-03 13:16:35 +00:00
|
|
|
φ = (x + l) * π / l
|
2021-12-08 20:53:15 +00:00
|
|
|
si, co = sincos(φ)
|
|
|
|
return SVector(co, si)
|
2021-12-03 13:16:35 +00:00
|
|
|
end
|
|
|
|
|
2021-12-08 20:53:15 +00:00
|
|
|
function project_back_from_unit_circle(θ::T, l::Float64) where {T<:Real}
|
2021-12-03 13:16:35 +00:00
|
|
|
x = θ * l / π - l
|
2021-12-07 00:36:47 +00:00
|
|
|
return restrict_coordinate(x, l)
|
2021-12-03 13:16:35 +00:00
|
|
|
end
|
|
|
|
|
2021-12-08 20:53:15 +00:00
|
|
|
function center_of_mass(particles::Vector{Particle}, l::Float64)
|
2021-12-07 04:52:10 +00:00
|
|
|
x_proj_sum = SVector(0.0, 0.0)
|
|
|
|
y_proj_sum = SVector(0.0, 0.0)
|
2021-12-03 13:16:35 +00:00
|
|
|
|
2021-12-08 20:53:15 +00:00
|
|
|
for p in particles
|
|
|
|
x_proj_sum += project_to_unit_circle(p.c[1], l)
|
|
|
|
y_proj_sum += project_to_unit_circle(p.c[2], l)
|
2021-12-03 13:16:35 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Prevent for example atan(1e-16, 1e-15) != 0 with rounding
|
|
|
|
digits = 5
|
|
|
|
|
|
|
|
# No need for 1/N with atan
|
|
|
|
# If proj is (0, 0) then COM is 0 or L or -L. Here, 0 is choosen with θ = π
|
2021-12-04 15:19:14 +00:00
|
|
|
if round(x_proj_sum[1]; digits=digits) == round(x_proj_sum[2]; digits=digits) == 0
|
2021-12-03 13:16:35 +00:00
|
|
|
x_θ = π
|
|
|
|
else
|
|
|
|
x_θ = atan(x_proj_sum[2], x_proj_sum[1])
|
|
|
|
end
|
|
|
|
|
2021-12-04 15:19:14 +00:00
|
|
|
if round(y_proj_sum[1]; digits=digits) == round(y_proj_sum[2]; digits=digits) == 0
|
2021-12-03 13:16:35 +00:00
|
|
|
y_θ = π
|
|
|
|
else
|
|
|
|
y_θ = atan(y_proj_sum[2], y_proj_sum[1])
|
|
|
|
end
|
|
|
|
|
2021-12-08 20:53:15 +00:00
|
|
|
COM_x = project_back_from_unit_circle(x_θ, l)
|
|
|
|
COM_y = project_back_from_unit_circle(y_θ, l)
|
|
|
|
|
|
|
|
return SVector(COM_x, COM_y)
|
2021-12-03 13:41:01 +00:00
|
|
|
end
|
|
|
|
|
2021-12-08 20:53:15 +00:00
|
|
|
function gyration_tensor(particles::Vector{Particle}, l::Float64)
|
|
|
|
COM = center_of_mass(particles, l)
|
2021-12-03 13:41:01 +00:00
|
|
|
|
|
|
|
S11 = 0.0
|
|
|
|
S12 = 0.0
|
|
|
|
S22 = 0.0
|
|
|
|
|
2021-12-08 20:53:15 +00:00
|
|
|
for p in particles
|
|
|
|
shifted_c = restrict_coordinates!(p.c - COM, l)
|
2021-12-03 13:41:01 +00:00
|
|
|
|
2021-12-08 20:53:15 +00:00
|
|
|
S11 += shifted_c[1]^2
|
|
|
|
S12 += shifted_c[1] * shifted_c[2]
|
|
|
|
S22 += shifted_c[2]^2
|
2021-12-03 13:41:01 +00:00
|
|
|
end
|
|
|
|
|
2021-12-04 15:19:14 +00:00
|
|
|
return Hermitian(SMatrix{2,2}(S11, S12, S12, S22))
|
|
|
|
end
|
|
|
|
|
2021-12-08 20:53:15 +00:00
|
|
|
function gyration_tensor_eigvals_ratio(particles::Vector{Particle}, l::Float64)
|
|
|
|
ev = eigvals(gyration_tensor(particles, l)) # Eigenvalues are sorted
|
2021-12-04 15:19:14 +00:00
|
|
|
return ev[1] / ev[2]
|
2021-12-03 13:16:35 +00:00
|
|
|
end
|