aboutsummaryrefslogtreecommitdiff
path: root/hw7/Laplacians.jl
diff options
context:
space:
mode:
Diffstat (limited to 'hw7/Laplacians.jl')
-rw-r--r--hw7/Laplacians.jl145
1 files changed, 145 insertions, 0 deletions
diff --git a/hw7/Laplacians.jl b/hw7/Laplacians.jl
new file mode 100644
index 0000000..10f0d48
--- /dev/null
+++ b/hw7/Laplacians.jl
@@ -0,0 +1,145 @@
+using Pkg
+Pkg.add("Plots")
+using Plots
+
+function del2_5(a::Matrix{Float64}, dx=1.0)
+ #=
+ Returns a finite-difference approximation of the laplacian of the array a,
+ with lattice spacing dx, using the five-point stencil:
+
+ 0 1 0
+ 1 -4 1
+ 0 1 0
+ =#
+
+ del2 = zeros(size(a))
+ del2[2:end-1, 2:end-1] .= (a[2:end-1, 3:end] + a[2:end-1, 1:end-2] +
+ a[3:end, 2:end-1] + a[1:end-2, 2:end-1] -
+ 4.0 * a[2:end-1, 2:end-1]) ./ (dx^2)
+ return del2
+end
+
+function del2_9(a::Matrix{Float64}, dx=1.0)
+ #=
+ Returns a finite-difference approximation of the laplacian of the array a,
+ with lattice spacing dx, using the nine-point stencil:
+
+ 1/6 2/3 1/6
+ 2/3 -10/3 2/3
+ 1/6 2/3 1/6
+ =#
+
+ del2 = zeros(size(a))
+ del2[2:end-1, 2:end-1] .= (4.0 * (a[2:end-1, 3:end] + a[2:end-1, 1:end-2] +
+ a[3:end, 2:end-1] + a[1:end-2, 2:end-1]) +
+ (a[1:end-2, 1:end-2] + a[1:end-2, 3:end] +
+ a[3:end, 1:end-2] + a[3:end, 3:end]) -
+ 20.0 * a[2:end-1, 2:end-1]) ./ (6.0 * dx^2)
+ return del2
+end
+
+function invDel2_5(b::Matrix{Float64}, dx=1.0, N=10000)
+ #=
+ Relaxes over N steps to a discrete approximation of the inverse laplacian
+ of the source term b, each step is a weighted average over the four neighboring
+ points and the source. This is the Jacobi algorithm.
+ =#
+
+ invDel2 = zeros(size(b))
+ newInvDel2 = zeros(size(b))
+
+ for m in 1:N
+ newInvDel2[2:end-1, 2:end-1] .= 0.25 * (invDel2[2:end-1, 3:end] +
+ invDel2[2:end-1, 1:end-2] +
+ invDel2[3:end, 2:end-1] +
+ invDel2[1:end-2, 2:end-1] -
+ (dx^2) * b[2:end-1, 2:end-1])
+ invDel2 .= newInvDel2
+ end
+
+ diff = del2_5(invDel2, dx) - b
+ diffSq = diff .* diff
+ error = sqrt(sum(diffSq))
+
+ println("\nerror = ", error)
+
+ return invDel2
+end
+
+
+# Define variables
+L = 10
+dx = 1.0
+
+# Parabola of revolution has constant Laplacian
+phi = zeros((L, L))
+for i = 1:L
+ x = (i + 0.5 - 0.5 * L) * dx
+ for j = 1:L
+ y = (j + 0.5 - 0.5 * L) * dx
+ phi[i, j] = x^2 + y^2
+ end
+end
+
+println(size(phi))
+
+println(del2_5(phi, dx))
+
+println("\n\n")
+
+println(del2_9(phi, dx))
+
+# Electrostatics example: uniformly charged cylinder (rho = 1) of radius R
+L = 100
+dx = 1.0
+R = 20.0
+R2 = R^2
+
+# Charge distribution
+rho = zeros((L, L))
+for i = 1:L
+ x = (i + 0.5 - 0.5 * L) * dx
+ for j = 1:L
+ y = (j + 0.5 - 0.5 * L) * dx
+ r2 = x^2 + y^2
+ if r2 < R2
+ rho[i, j] = 1.0
+ else
+ rho[i, j] = 0.0
+ end
+ end
+end
+
+rhoPlot = plot(rho[Int(L/2), :])
+
+# Exact (analytical) electric potential
+phi = zeros((L, L))
+for i = 1:L
+ x = (i + 0.5 - 0.5 * L) * dx
+ for j = 1:L
+ y = (j + 0.5 - 0.5 * L) * dx
+ r2 = x^2 + y^2
+ if r2 < R2
+ phi[i, j] = -π * r2
+ else
+ phi[i, j] = -π * (R2 + R2*log(r2/R2))
+ end
+ end
+end
+
+phiPlot = plot(phi[Int(L/2), :])
+
+# Charge density obtained from exact potential
+rho = -1.0/(4.0 * π) * del2_5(phi, dx)
+rhoPlotLattice = plot(rho[Int(L/2), :])
+
+phi = invDel2_5(-4.0 * π * rho, dx, 20000)
+#phi = invDelSOR(-4.0 * π * rho, dx, 500)
+phi .-= phi[Int(L/2), Int(L/2)]
+
+phiPlotInvDel = plot(phi[Int(L/2), :])
+
+contourf(phi)
+
+#plot(rhoPlot, rhoPlotLattice)
+#plot(phiPlot, phiPlotInvDel)