└── src ├── classical_Lorentz.jl ├── tests2d.jl ├── efficient_3D.jl ├── efficient_2D.jl ├── ClassicalLorentz.jl └── eff-ata-latest-old.jl /src/classical_Lorentz.jl: -------------------------------------------------------------------------------- 1 | function ClassicLorentz(x, v, r) #This is a simpler and inefficient version of the Classic algorithm for ND. Just to 2 | #check if the 3D version works correctly. 3 | if norm(int(x) - x) < r #if a particle begin inside an obstacle, then the first collision 4 | #is considered with the same obstacle. 5 | xx,tt = collision(x, int(x), r, v) 6 | return xx 7 | end 8 | xr = false 9 | i = 0.0 10 | 11 | while xr == false 12 | while xr == false 13 | xr, tt = collision(x, int(x+v*(i)), r, v) 14 | i += 1 - 2*r 15 | end 16 | 17 | t = norm(xr - x) / normsq(v) 18 | if normsq(x + t*v - xr) > normsq(xr - x) 19 | xr = false 20 | end 21 | end 22 | 23 | xr 24 | end 25 | -------------------------------------------------------------------------------- /src/tests2d.jl: -------------------------------------------------------------------------------- 1 | #include("efficient-algorithm-revised.jl") 2 | include("eff-ata-latest-old.jl") 3 | push!(LOAD_PATH, "modules") 4 | 5 | using ClassicalLorentz 6 | using EfficientLorentz 7 | 8 | # Ata's E vs my E 9 | #= 10 | for j = 10:50 11 | for i = 1:100 12 | x = [0.8*rand() + 0.1, 0.8*rand() + 0.1] 13 | phi = 2pi*rand() 14 | v = [cos(phi), sin(phi)] 15 | r = 0.8^j 16 | 17 | effic = Lorentz(x, v, r) 18 | class = int(ClassicLorentz(x, v, r)) 19 | 20 | my_effic = collisions(x[1], x[2], v[1], v[2], r, 1, 64)[1][1] 21 | 22 | if effic == my_effic 23 | #println("Passed with x = $x; v = $v; r = $r") 24 | else 25 | t = norm(my_effic - x)/norm(v) 26 | my_class = collisions_classical(x, v, r, t + 0.1, 64)[2] 27 | println("Failed with x = $x; v = $v; r = $r : E = $effic, MyE = $my_effic, C = $class, MyC = $my_class") 28 | end 29 | end 30 | end 31 | =# 32 | 33 | # Ata's E vs Ata's C 34 | 35 | function compare() 36 | 37 | for j = 10:30 #50 38 | @show j 39 | for i = 1:100 40 | x = [0.8*rand() + 0.1, 0.8*rand() + 0.1] 41 | x = big(x) 42 | 43 | phi = big(2pi*rand()) 44 | v = [cos(phi), sin(phi)] 45 | 46 | r = big(0.8)^j 47 | x 48 | 49 | effic = Lorentz2(x, v, r) 50 | class = int(ClassicLorentz(x, v, r)) 51 | 52 | if effic == class 53 | #println("Passed with x = $x; v = $v; r = $r") 54 | else 55 | my_effic = collisions(x[1], x[2], v[1], v[2], r, 1, 64)[1][1] 56 | println("Failed with x = $x; v = $v; r = $r : E = $effic, C = $class, myE = $my_effic") 57 | end 58 | end 59 | end 60 | end 61 | 62 | @time compare() 63 | 64 | -------------------------------------------------------------------------------- /src/efficient_3D.jl: -------------------------------------------------------------------------------- 1 | function Lorentz3D2(x, v, r) 2 | if norm(int(x) - x) < r # if a particle begin inside an obstacle, then the first collision 3 | # is considered with the same obstacle. 4 | xx, t = collision(x, int(x), r, v) 5 | return xx 6 | end 7 | 8 | x1 = zeros(2) 9 | x2 = zeros(2) 10 | x3 = zeros(2) 11 | xr = false 12 | 13 | while (xr == false) 14 | v_xy = [v[1], v[2]] 15 | v_xz = [v[1], v[3]] 16 | v_yz = [v[2], v[3]] #Velocities in the planes xy, xz, and yz 17 | 18 | vn_xy = v_xy ./ norm(v_xy) 19 | vn_xz = v_xz ./ norm(v_xz) 20 | vn_yz = v_yz ./ norm(v_yz) #normalized velocities in the planes xy, xz, and yz 21 | 22 | tmax = 0 23 | tmin = -2 24 | x1[1] = 1 25 | x1[2] = 2 26 | x2[1] = 3 27 | x2[2] = 4 28 | x3[1] = 5 29 | x3[2] = 6 30 | # while (int(tmax)>int(tmin+BigFloat("0.5")) ) #it can be considerin time conincidence 31 | 32 | while x1[1] != x2[1] || x1[2] != x3[1] || x2[2] != x3[2] #or considering the obstacle coincidence. 33 | x_xy = [x[1], x[2]] 34 | x_xz = [x[1], x[3]] 35 | x_yz = [x[2], x[3]] #positions in the planes xy, xz, and yz 36 | 37 | x1 = Lorentz2(x_xy, vn_xy, r)#calculate the position of obstacle that collide with the particle 38 | if x1 == false 39 | return false 40 | end 41 | 42 | x2 = Lorentz2(x_xz, vn_xz, r)# in the 2D Lorentz gas for the 3 planes 43 | if x2 == false 44 | return false 45 | end 46 | 47 | x3 = Lorentz2(x_yz, vn_yz, r) 48 | if x3 == false 49 | return false 50 | end 51 | 52 | # calculate the time needed to reach the obstacle in each plane: 53 | t1 = (norm(x1 - x_xy) - r) / norm(v_xy) 54 | t2 = (norm(x2 - x_xz) - r) / norm(v_xz) 55 | t3 = (norm(x3 - x_yz) - r) / norm(v_yz) 56 | 57 | tmax = max(t1, t2, t3) # if the minumum and maximum valueds of time are almost the same, then 58 | tmin = min(t1, t2, t3) # there is very high probable a collision 59 | if tmax < 0 60 | tmax = 0.1 * r 61 | end 62 | x += v * (tmax - 0.1*r) 63 | end 64 | 65 | xr, tt = collision(x, int(x), r, v) #calculates the collision. In case that there is not, then, it advance the particle to the 66 | #next cell 67 | if tt<0 68 | xr=false 69 | end 70 | x += v * (1 - 2*r) 71 | end 72 | return xr 73 | end 74 | -------------------------------------------------------------------------------- /src/efficient_2D.jl: -------------------------------------------------------------------------------- 1 | normsq(x) = dot(x, x) 2 | 3 | 4 | 5 | doc"""Continued fraction algorithm: find a rational approximation $p/q$ 6 | to $x$ which is within a distance $\epsilon$ of $x$. 7 | """ 8 | function rational_approximation(x, ϵ) 9 | h1, h2 = 1, 0 10 | k1, k2 = 0, 1 11 | b = x 12 | 13 | while abs(k1*x - h1) > ϵ 14 | a = ifloor(b) 15 | h1, h2 = a*h1 + h2, h1 16 | k1, k2 = a*k1 + k2, k1 17 | b = inv(b - a) 18 | end 19 | return k1, h1 20 | end 21 | 22 | doc""" 23 | Find a collision of a particle with position `x` and velocity `v` with a local disc of radius $r$; if there is no such 24 | collision with a nearby disc, find the nearest position of the form $(n, b)$ with $n$ an integer. 25 | Supposes that v is in the first octant. 26 | """ 27 | function local_step(x, v, r) 28 | e1 = [1, 0] 29 | e2 = [0, 1] 30 | 31 | nn = ifloor(x) # bottom left of current cell 32 | xx = x-nn # position relative to current cell 33 | 34 | t = (1 - xx[1]) / v[1] # collision time with next vertical wall 35 | x1 = xx + v * t # collision position 36 | 37 | t2 = -xx[1] / v[1] # collision time with previous vertical wall 38 | x2 = xx + v * t2 39 | 40 | b1 = x1[2] # collision heights 41 | b2 = x2[2] 42 | 43 | ϵ = r / v[1] 44 | 45 | if (xx - e1)⋅v < 0 46 | if abs(b1) < ϵ 47 | return e1 + nn, 0 48 | end 49 | end 50 | 51 | if (xx - e2)⋅v < 0 52 | if abs(1 - b2) <ϵ 53 | return e2 + nn, 0 54 | end 55 | end 56 | 57 | if (xx - e1 - e2)⋅v < 0 58 | if abs(1-b1) < ϵ 59 | return e1 + e2 + nn, 0 60 | end 61 | end 62 | if (xx - e1 - 2*e2) ⋅ v < 0 63 | if abs(2-b1) < ϵ 64 | return e1 + 2*e2 +nn, 0 65 | end 66 | end 67 | 68 | return x1+nn, 1 69 | end 70 | 71 | doc""" 72 | Efficiently calculate with which disc of radius $r$ a trajectory will collide. 73 | The trajectory is a line through the point $(0, b)$ with slope $m$. 74 | """ 75 | function efficient_disc_collision(m, b, r) 76 | kn = 0 77 | b1 = b 78 | ϵ = r * √(m^2 + 1) 79 | 80 | if b < ϵ || 1 - b < ϵ 81 | if b < 0.5 82 | q, p = rational_approximation(m, 2b) 83 | else 84 | q, p = rational_approximation(m, 2*(1 - b)) 85 | end 86 | 87 | b = mod(m*q + b, 1) 88 | kn += q 89 | end 90 | 91 | while b > ϵ && 1 - b > ϵ 92 | if b < 0.5 93 | (q, p) = rational_approximation(m, 2b) 94 | else 95 | (q, p) = rational_approximation(m, 2*(1 - b)) 96 | end 97 | b = mod(m*q + b, 1) 98 | kn += q 99 | if abs(b - b1) < 1e-30 100 | throw(ArgumentError("Rational velocity along channel with slope $m; no collision")) 101 | end 102 | end 103 | q = kn 104 | p = round(m*q + b1) 105 | return [q, p] 106 | end 107 | 108 | """Find coordinates of the obstacle with which a particle 109 | at initial position `x`, with velocity `v`, collides 110 | if both components of the velocity are positive and the slope is less than 1, 111 | i.e. if the velocity vector lies within the first octant. 112 | """ 113 | function find_next_disc_first_octant(x, v, r) 114 | if normsq(round(x) - x) < r^2 # if inside obstacle 115 | return round(x) # then first collision is with that obstacle 116 | end # (used for the 3D algorithm) 117 | 118 | x1, collided = local_step(x, v, r) 119 | if collided == 0 # hit local disc 120 | return x1 121 | end 122 | 123 | v1, v2 = v 124 | m = v2 / v1 125 | b = x1[2] 126 | b -= floor(b) # move to form $(0, b)$ 127 | 128 | centre = efficient_disc_collision(m, b, r) 129 | 130 | d = [0, round(b)] 131 | x2 = round(x1) - d + centre 132 | return x2 133 | end 134 | 135 | 136 | doc"rotation matrix clockwise by angle π/2" 137 | const Rot = [ 0.0 1.0; 138 | -1.0 0.0 ] 139 | 140 | doc"reflection matrix; maps (x,y) ↦ (y,x)" 141 | const Refl = [ 0.0 1.0; 142 | 1.0 0.0 ] 143 | 144 | 145 | const T = Array(Matrix{Float64}, 8) 146 | const T_inverse = Array(Matrix{Float64}, 8) 147 | 148 | 149 | function initialise_transformations() 150 | for n in 1:8 # octant between 1 and 8 151 | 152 | quadrant = (n-1) ÷ 2 # integer division; quadrant between 0 and 3 153 | T[n] = Rot^quadrant 154 | 155 | if n%2 == 0 156 | T[n] = Refl * T[n] 157 | end 158 | 159 | T_inverse[n] = inv(T[n]) 160 | end 161 | end 162 | 163 | initialise_transformations() 164 | 165 | 166 | function octant(v) 167 | v1, v2 = v 168 | 169 | θ = atan2(v2, v1) 170 | if θ < 0 171 | θ += 2π 172 | end 173 | 174 | iceil(θ / (2π) * 8) # from 1 to 8 175 | end 176 | 177 | 178 | function find_next_disc(x, v, r) 179 | 180 | n = octant(v) 181 | 182 | M = T[n] 183 | 184 | x = M * x 185 | v = M * v 186 | 187 | x = find_next_disc_first_octant(x, v, r) 188 | 189 | x = T_inverse[n] * x 190 | end 191 | 192 | doc""" 193 | Find collision of particle with disc with centre `c` and radius `r`. 194 | `x` and `v` are the position and velocity of the particle. 195 | """ 196 | function collision(x, c, r, v) 197 | v2 = normsq(v) 198 | b = ((x - c) ⋅ v) / v2 199 | c = (normsq(x - c) - r^2) / v2 200 | if b^2 - c < 0 201 | return x, +Inf # no collision 202 | end 203 | 204 | t = -b - √(b^2 - c) # collision time 205 | x = v*t + x 206 | return x, t 207 | 208 | end 209 | 210 | doc""" 211 | Calculate the post-collision velocity at the point `x` on a disc of radius 212 | `c`. The pre-collision velocity is `v`. 213 | """ 214 | function post_collision_velocity(x, c, v) 215 | n = x - c 216 | n /= norm(n) 217 | 218 | v -= 2(v⋅n) * n 219 | v /= norm(v) 220 | v 221 | end 222 | 223 | function LorentzGas(x, v, r, steps) 224 | 225 | for i = 1:steps 226 | center = find_next_disc(x, v, r) 227 | x, t = collision(x, center, r, v) 228 | v = post_collision_velocity(x, center, v) 229 | end 230 | 231 | x, v 232 | end 233 | 234 | function LorentzGas2(x, v, r, time) 235 | t = 0 236 | v1 = copy(v) 237 | 238 | while t < time 239 | x1 = copy(x) 240 | v1 = copy(v) 241 | center = find_next_disc(x, v, r) 242 | x, tt = collision(x, center, r, v) 243 | v = post_collision_velocity(x, center, v) 244 | t += tt # norm(x-x1) 245 | end 246 | 247 | t -= time 248 | if t==0 249 | v1 = v 250 | end 251 | x -= t*v1 252 | 253 | x, v1 254 | end 255 | -------------------------------------------------------------------------------- /src/ClassicalLorentz.jl: -------------------------------------------------------------------------------- 1 | module ClassicalLorentz 2 | export crossz, crossing, crossing3d, collisions_classical, first_collision_classical, collisions3d_classical, first_collision3d_classical 3 | 4 | # Perpendicular (z-) component of cross product (scalar quantity) for 2-D vectors: (x cross y) dot e_z 5 | #set_bigfloat_precision(1024) 6 | crossz(x, y) = x[1]*y[2] - x[2]*y[1] 7 | 8 | function crossing(x, v, n, m) 9 | # Outputs new position in square [-0.5, 0.5)^2 and updates the numbers of new square 10 | 11 | # Minimum positive times to nearest crossing - concise formulas p. 48 - 49 12 | array_times = BigFloat[] 13 | k = v[2]/v[1] 14 | for i = 1:2 15 | for j = 1:2 16 | push!(array_times, ((-1)^j*0.5 - x[i])/v[i]) 17 | end 18 | end 19 | 20 | # Extract the minimum positive time value 21 | minpos = Inf 22 | number = 0 23 | for i = 1:length(array_times) 24 | if array_times[i] < minpos && array_times[i] > 0 25 | minpos = array_times[i] 26 | number = i 27 | end 28 | end 29 | 30 | t = array_times[number] 31 | x1 = x + v*t 32 | d = norm(v*t) 33 | 34 | # Possible outcomes depending on which wall will be hit 35 | if number == 2 36 | n += 1 37 | return [-0.5, x1[2]], d, n, m 38 | elseif number == 4 39 | m += 1 40 | return [x1[1], -0.5], d, n, m 41 | elseif number == 1 42 | n -= 1 43 | return [0.5, x1[2]], d, n, m 44 | elseif number == 3 45 | m -= 1 46 | return [x1[1], 0.5], d, n, m 47 | elseif error("Don't know which wall was hit") 48 | end 49 | 50 | end 51 | 52 | 53 | # Calculates the coordinates of places and of each hit obstacle of the collisions given the time 54 | function collisions_classical(x, v, r, tmax, prec::Integer=64) 55 | 56 | set_bigfloat_precision(prec) 57 | #x = big(x); v = big(v); r = big(r) 58 | x = [BigFloat("$(x[1])"), BigFloat("$(x[2])")]; v = [BigFloat("$(v[1])"), BigFloat("$(v[2])")]; r = BigFloat("$r") 59 | places = Array{BigFloat, 1}[] 60 | circles = Vector{BigInt}[] 61 | speeds = Array{BigFloat, 1}[] # Modification to collect speeds too; may be turned off 62 | times = BigFloat[] 63 | # Put the starting point into the places array 64 | push!(places, x) 65 | push!(speeds, v) 66 | push!(times, 0) 67 | 68 | # Initial square (n, m) 69 | n = ifloor(x[1] + 0.5) 70 | m = ifloor(x[2] + 0.5) 71 | 72 | # Place the first initial position into square [-0.5, 0.5)^2 73 | x -= [n, m] 74 | 75 | if norm(x) < r 76 | error("The initial position cannot be inside an obstacle") 77 | end 78 | 79 | t = 0 80 | while t <= tmax 81 | # Will hit or miss? Check the condition for hitting 82 | 83 | vcrossx = abs(crossz(v, x)) 84 | vr = norm(v)*r 85 | discr = vr^2 - vcrossx^2 86 | 87 | if vcrossx < vr && (-dot(v, x) - sqrt(discr)) >= 0 # To make sure it does not go backwards 88 | #println("hit") 89 | # Then reflect 90 | 91 | t1 = (-dot(v, x) - sqrt(discr))/norm(v)^2 92 | 93 | N0 = x + v*t1 94 | N = N0/norm(N0) 95 | 96 | # Velocity, place and time immediately after the collision 97 | v1 = v - 2dot(v, N)*N 98 | x1 = x + v*t1 99 | t += t1 100 | 101 | push!(places, x1 + [n, m]) 102 | push!(circles, [n, m]) 103 | push!(speeds, v1) 104 | push!(times, t) 105 | #print("{$(r1[1] + n), $(r1[2] + m)}, ") 106 | 107 | x, d, n, m = crossing(x1, v1, n, m) 108 | 109 | # The speed direction will stay the same 110 | v = v1 111 | 112 | # The time will increment once again from collision point to the wall 113 | t += d/norm(v) 114 | 115 | else # If it misses the ball 116 | #println("miss") 117 | v1 = v 118 | x1 = x 119 | 120 | # Now hit the wall 121 | x, d, n, m = crossing(x1, v1, n, m) 122 | 123 | # The speed direction will stay the same 124 | v = v1 125 | 126 | # The time will increment 127 | t += d/norm(v) 128 | end 129 | end 130 | return places, circles, speeds, times 131 | end 132 | 133 | 134 | # Calculates the coordinates of obstacles hit at the first collision 135 | function first_collision_classical(x::Vector, v::Vector, r::Real, precision::Integer=64) 136 | 137 | set_bigfloat_precision(precision) 138 | circles = Vector[] 139 | 140 | # Initial square (n, m) 141 | n = ifloor(x[1] + 0.5) 142 | m = ifloor(x[2] + 0.5) 143 | 144 | # Place the first initial position into square [-0.5, 0.5)^2 145 | x -= [n, m] 146 | 147 | if norm(x) < r 148 | error("The initial position cannot be inside an obstacle") 149 | end 150 | 151 | 152 | while abs(crossz(v, x)) > norm(v)*r # misses the ball 153 | 154 | v1 = v 155 | x1 = x 156 | 157 | # Now hit the wall 158 | x, d, n, m = crossing(x1, v1, n, m) 159 | 160 | # The speed direction will stay the same 161 | v = v1 162 | 163 | end 164 | 165 | (n, m) 166 | end 167 | 168 | 169 | ### 3D collisions 170 | 171 | function crossing3d(x, v, n, m, l) 172 | # Outputs new position in cube [-0.5, 0.5)^3 and updates the numbers of new square 173 | 174 | # Minimum positive times to nearest crossing - concise formulas p. 48 - 49 175 | array_times = BigFloat[] 176 | #k = v[2]/v[1] 177 | for i = 1:3 178 | for j = 1:2 179 | push!(array_times, ((-1)^j*0.5 - x[i])/v[i]) 180 | end 181 | end 182 | 183 | # Extract the minimum positive time value 184 | minpos = Inf 185 | number = 0 186 | for i = 1:length(array_times) 187 | if array_times[i] < minpos && array_times[i] > 0 188 | minpos = array_times[i] 189 | number = i 190 | end 191 | end 192 | 193 | t = array_times[number] 194 | x1 = x + v*t 195 | d = norm(v*t) 196 | 197 | # Possible outcomes depending on which wall will be hit 198 | if number == 2 199 | n += 1 200 | return [-0.5, x1[2], x1[3]], d, n, m, l 201 | elseif number == 4 202 | m += 1 203 | return [x1[1], -0.5, x1[3]], d, n, m, l 204 | elseif number == 1 205 | n -= 1 206 | return [0.5, x1[2], x1[3]], d, n, m, l 207 | elseif number == 3 208 | m -= 1 209 | return [x1[1], 0.5, x1[3]], d, n, m, l 210 | elseif number == 6 211 | l += 1 212 | return [x1[1], x1[2], -0.5], d, n, m, l 213 | elseif number == 5 214 | l -= 1 215 | return [x1[1], x1[2], 0.5], d, n, m, l 216 | elseif error("Don't know which wall was hit") 217 | end 218 | 219 | end 220 | 221 | 222 | function collisions3d_classical(x0, v0, r, tmax, precision::Integer=64) 223 | 224 | set_bigfloat_precision(precision) 225 | x0 = big(x0); v0 = big(v0); r = big(r) 226 | #x0 = [BigFloat("$(x0[1])"), BigFloat("$(x0[2])"), BigFloat("$(x0[3])")]; v0 = [BigFloat("$(v0[1])"), BigFloat("$(v0[2])"), BigFloat("$(v0[3])")]; r = BigFloat("$r") 227 | # Normalize speed 228 | v0 /= norm(v0) 229 | places = Vector{BigFloat}[] 230 | circles = Vector{BigInt}[] 231 | speeds = Vector{BigFloat}[] 232 | times = BigFloat[] 233 | # Put the starting point into the places array 234 | push!(places, x0) 235 | push!(speeds, v0) 236 | push!(times, 0) 237 | 238 | # Initial square (n, m) 239 | n = ifloor(x0[1] + 0.5) 240 | m = ifloor(x0[2] + 0.5) 241 | l = ifloor(x0[3] + 0.5) 242 | 243 | # Place the first initial position into cube [-0.5, 0.5)^3 244 | x0 -= [n, m, l] 245 | 246 | if norm(x0) < r 247 | error("The initial position cannot be inside an obstacle") 248 | end 249 | 250 | t = 0 251 | while t <= tmax 252 | # Will hit or miss? Check the condition for hitting - derivation pp. 83-84 253 | xcrossv = norm(cross(v0, x0)) 254 | vr = norm(v0)*r 255 | discr = vr^2 - xcrossv^2 256 | if xcrossv < vr && (-dot(v0, x0) - sqrt(discr)) > 0 257 | #println("hit") 258 | # Then reflect 259 | 260 | 261 | # Throw away complex time values if any, but there shouldn't be 262 | #if discr >= 0 263 | t1 = (-dot(v0, x0) - sqrt(discr))/norm(v0)^2 264 | #end 265 | 266 | N0 = x0 + v0*t1 267 | N = N0/norm(N0) 268 | 269 | # Velocity, place and time immediately after the collision 270 | v1 = v0 - 2*dot(v0, N)*N 271 | x1 = x0 + v0*t1 272 | t += t1 273 | 274 | push!(places, x1 + [n, m, l]) 275 | push!(circles, [n, m, l]) 276 | push!(speeds, v1) 277 | push!(times, t) 278 | norm(x1), norm(x1 + [n,m,l] - [n,m,l]) 279 | #print("{$(r1[1] + n), $(r1[2] + m)}, ") 280 | 281 | #x0 += v0*0.001 # Don't know why it was here. Commented out. 282 | 283 | x0, d, n, m, l = crossing3d(x1, v1, n, m, l) 284 | 285 | 286 | # The speed direction will stay the same 287 | v0 = v1 288 | 289 | # The time will increment once again from collision point to the wall 290 | t += d/norm(v0) 291 | 292 | 293 | else # If it misses the ball 294 | #println("miss") 295 | v1 = v0 296 | x1 = x0 297 | 298 | # Now hit the wall 299 | x0, d, n, m, l = crossing3d(x1, v1, n, m, l) 300 | 301 | # The speed direction will stay the same 302 | v0 = v1 303 | 304 | # The time will increment 305 | t += d/norm(v0) 306 | end 307 | end 308 | return places, circles, speeds, times 309 | end 310 | 311 | 312 | 313 | 314 | function first_collision3d_classical(x0, v0, r, precision::Integer=64) 315 | 316 | set_bigfloat_precision(precision) 317 | x0 = big(x0); v0 = big(v0); r = big(r) 318 | #x0 = [BigFloat("$(x0[1])"), BigFloat("$(x0[2])"), BigFloat("$(x0[3])")]; v0 = [BigFloat("$(v0[1])"), BigFloat("$(v0[2])"), BigFloat("$(v0[3])")]; r = BigFloat("$r") 319 | # Normalize speed 320 | v0 /= norm(v0) 321 | 322 | # Initial square (n, m) 323 | n = ifloor(x0[1] + 0.5) 324 | m = ifloor(x0[2] + 0.5) 325 | l = ifloor(x0[3] + 0.5) 326 | 327 | # Place the first initial position into cube [-0.5, 0.5)^3 328 | x0 -= [n, m, l] 329 | 330 | if norm(x0) < r 331 | error("The initial position cannot be inside an obstacle") 332 | end 333 | 334 | t = 0 335 | 336 | # Will hit or miss? Check the condition for hitting - derivation pp. 83-84 337 | #xcrossv = norm(cross(v0, x0)) 338 | #vr = norm(v0)*r 339 | #discr = vr^2 - xcrossv^2 340 | #if xcrossv < vr && (-dot(v0, x0) - sqrt(discr)) > 0 341 | while norm(cross(v0, x0)) > norm(v0)*r 342 | 343 | v1 = v0 344 | x1 = x0 345 | 346 | # Now hit the wall 347 | x0, d, n, m, l = crossing3d(x1, v1, n, m, l) 348 | 349 | # The speed direction will stay the same 350 | v0 = v1 351 | 352 | # The time will increment 353 | t += d/norm(v0) 354 | end 355 | 356 | return (n, m, l) 357 | end 358 | 359 | 360 | # End of module 361 | end 362 | -------------------------------------------------------------------------------- /src/eff-ata-latest-old.jl: -------------------------------------------------------------------------------- 1 | function collision(x1,x2,r,v) 2 | v2=dot(v,v) 3 | b=dot((x1-x2),v)/v2 4 | c=(dot((x1-x2),(x1-x2))-r^2)/v2 5 | if(BigFloat(b^2-c) epsilon 28 | a = ifloor(b) 29 | h1, h2 = a*h1 + h2, h1 30 | k1, k2 = a*k1 + k2, k1 31 | b = 1/(b - a) 32 | end 33 | return k1, h1 34 | end 35 | function nextt1(x,v,r) 36 | e1=[1,0] 37 | e2=[0,1] 38 | nn=ifloor(x) 39 | xx=x-nn 40 | t=(1-xx[1])/v[1] 41 | t2=-xx[1]/v[1] 42 | x1=xx+v*t 43 | x2=xx+v*t2 44 | b1=x1[2] 45 | b2=x2[2] 46 | epsilon=r/v[1] 47 | testt=0 48 | if( dot(xx-e1,v)<0) 49 | if(abs(b1) epsilon && 1 - b > epsilon 86 | if b < BigFloat("0.5") 87 | (q, p) = frac(m, 2.*b) 88 | else 89 | (q, p) = frac(m, 2.*(1. - b)) 90 | end 91 | b = mod(m*q + b, 1) 92 | kn += q 93 | if(abs(b-b1)x and x->y 129 | ROT2=ROT^2 130 | ROT3=ROT^3 131 | v1=v[1] 132 | v2=v[2] 133 | vv=copy(v) 134 | xx=copy(x) 135 | m1=v2/v1 136 | if(norm(int(x)-x)=0 && v2>=0) # if the velocity is in the quadrant I 141 | if(m1<=1) 142 | xx=Lor2(xx,vv,r) 143 | if(xx==false) 144 | return false 145 | end 146 | elseif(m1>1) 147 | xx=REF*xx 148 | vv=REF*vv 149 | xx=Lor2(xx,vv,r) 150 | if(xx==false) 151 | return false 152 | end 153 | xx=REF*xx 154 | vv=REF*vv 155 | end 156 | return xx 157 | elseif(m1>=0 && v2<0) #if the velocity is in the quadrant III 158 | xx=ROT2*xx 159 | vv=ROT2*vv 160 | if(m1<=1) 161 | xx=Lor2(xx,vv,r) 162 | if(xx==false) 163 | return false 164 | end 165 | elseif(m1>1) 166 | xx=REF*xx 167 | vv=REF*vv 168 | xx=Lor2(xx,vv,r) 169 | if(xx==false) 170 | return false 171 | end 172 | xx=REF*xx 173 | vv=REF*vv 174 | end 175 | xx=ROT2*xx 176 | vv=ROT2*vv 177 | return xx 178 | elseif(m1<0 && v2>=0) #if the velocity is in the quadrant II 179 | xx=ROT*xx 180 | vv=ROT*vv 181 | if(m1<-1) 182 | xx=Lor2(xx,vv,r) 183 | if(xx==false) 184 | return false 185 | end 186 | elseif(m1>=-1) 187 | xx=REF*xx 188 | vv=REF*vv 189 | xx=Lor2(xx,vv,r) 190 | if(xx==false) 191 | return false 192 | end 193 | xx=REF*xx 194 | vv=REF*vv 195 | end 196 | xx=ROT3*xx 197 | vv=ROT3*vv 198 | return xx 199 | elseif(m1<0 && v2<0) #if the velocity is in the quadrant IV 200 | xx=ROT3*xx 201 | vv=ROT3*vv 202 | if(m1<-1) 203 | xx=Lor2(xx,vv,r) 204 | if(xx==false) 205 | return false 206 | end 207 | elseif(m1>=-1) 208 | xx=REF*xx 209 | vv=REF*vv 210 | xx=Lor2(xx,vv,r) 211 | if(xx==false) 212 | return false 213 | end 214 | xx=REF*xx 215 | vv=REF*vv 216 | end 217 | xx=ROT*xx 218 | vv=ROT3*vv 219 | return xx 220 | end 221 | end 222 | function LorentzGas1(x,v,r,steps) 223 | for i=1:steps 224 | center=Lorentz2(x,v,r) 225 | x, t=collision(x,center,r,v) 226 | v=velo_col(x,center,v) 227 | end 228 | return x, v 229 | end 230 | 231 | function LorentzGas2(x,v,r,time) 232 | t=0 233 | v1=copy(v) 234 | while(tint(tmin+BigFloat("0.5")) ) #it can be considerin time conincidence 276 | while(x1[1]!=x2[1] || x1[2]!=x3[1] || x2[2]!=x3[2]) #or considering the obstacle coincidence. 277 | x_xy=[x[1], x[2]] 278 | x_xz=[x[1], x[3]] 279 | x_yz=[x[2], x[3]] #positions in the planes xy, xz, and yz 280 | 281 | x1=Lorentz2(x_xy,vn_xy,r)#calculate the position of obstacle that collide with the particle 282 | if(x1==false) 283 | return false 284 | end 285 | x2=Lorentz2(x_xz,vn_xz,r)# in the 2D Lorentz gas for the 3 planes 286 | if(x2==false) 287 | return false 288 | end 289 | x3=Lorentz2(x_yz,vn_yz,r) 290 | if(x3==false) 291 | return false 292 | end 293 | t1=(sqrt(dot(x1-x_xy,x1-x_xy))-r)/sqrt(dot(v_xy,v_xy)) 294 | t2=(sqrt(dot(x2-x_xz,x2-x_xz))-r)/sqrt(dot(v_xz,v_xz)) 295 | t3=(sqrt(dot(x3-x_yz,x3-x_yz))-r)/sqrt(dot(v_yz,v_yz)) #calculate the time used to reach the obstacle. 296 | tmax=maximum([t1 t2 t3]) # if the minumum and maximum valueds of time are almost the same, then 297 | tmin=minimum([t1 t2 t3]) # there is very high probable a collision 298 | if(tmax<0) 299 | tmax=0.1*r 300 | end 301 | x=x+v*(tmax-0.1*r) 302 | end 303 | xr, tt=collision(x,int(x),r,v) #calculates the collision. In case that there is not, then, it advance the particle to the 304 | #next cell 305 | if(tt<0) 306 | xr=false 307 | end 308 | x=x+v*(1-2*r) 309 | end 310 | return xr 311 | end 312 | 313 | function ClassicLorentz(x,v,r) #This is a simpler and inefficient version of the Classic algorithm for ND. Just to 314 | #check if the 3D version works correctly. 315 | if(norm(int(x)-x)dot(xr-x,xr-x)) 329 | xr=false 330 | end 331 | end 332 | return xr 333 | end 334 | 335 | function reordenar(A) 336 | B=zeros(0) 337 | N=length(A) 338 | for i=1:N 339 | ind=indmin(A) 340 | b=splice!(A,ind) 341 | push!(B,b) 342 | end 343 | return B 344 | end 345 | dist(x1,x2)=norm(x1-x2) 346 | --------------------------------------------------------------------------------