I am trying to generate a numerical initial condition for a PDE that looks like this: it is a Bravais lattice, with a gaussian at each site (in 2D). This is not difficult to do by hand for a square lattice with two atoms per unit cell, for example:
using Plots
const N = 256
dx = 1/143
dy = dx
x = collect(-N/2*dx:dx:(N/2-1)*dx)
y = collect(-N/2*dy:dy:(N/2-1)*dy)
Nₚ = 4 # Has to be power of two, number of partitions. You get Nₚ^2 sites
xₗ = collect(-N/Nₚ/2*dx:dx:(N/Nₚ/2-1)*dx) # Local coordinate
yₗ = collect(-N/Nₚ/2*dy:dy:(N/Nₚ/2-1)*dy) # Local Coordinate
# hack fix for rect lattices
if length(yₗ) < length(xₗ)
append!(yₗ,yₗ[end]+dy)
end
α = 500.0
u01 = kron(ones(Nₚ, Nₚ), (1 .- exp.(-α*((xₗ).^2 .+ (yₗ').^2)) .- exp.(-α*((xₗ.-xₗ[end]).^2 .+ (yₗ'.-yₗ[end]).^2)) .- exp.(-α*((xₗ.-xₗ[1]).^2 .+ (yₗ'.-yₗ[end]).^2)) .- exp.(-α*((xₗ.-xₗ[end]).^2 .+ (yₗ'.-yₗ[1]).^2)) .- exp.(-α*((xₗ.-xₗ[1]).^2 .+ (yₗ'.-yₗ[1]).^2))))
heatmap(u01)
Or even a triangular (hexagonal) lattice if we expand our PDE model to handle rectangular grids:
using Plots
const N = 256
dx = 1/143
dy = dx*2/sqrt(3)
x = collect(-N/2*dx:dx:(N/2-1)*dx)
y = collect(-N/2*dy:dy:(N/2-1)*dy)
Nₚ = 4 # Has to be power of two, number of partitions. You get Nₚ^2 sites
xₗ = collect(-N/Nₚ/2*dx:dx:(N/Nₚ/2-1)*dx) # Local coordinate
yₗ = collect(-N/Nₚ/2*dy:dy:(N/Nₚ/2-1)*dy) # Local Coordinate
# hack fix for rect lattices
if length(yₗ) < length(xₗ)
append!(yₗ,yₗ[end]+dy)
end
α = 500.0
u01_piece = (1 .- exp.(-α*((xₗ).^2 .+ (yₗ'.- yₗ[end]).^2)) .- exp.(-α*((xₗ).^2 .+ (yₗ'.- yₗ[1]).^2)) .-
exp.(-α*((xₗ.+sqrt(3)/2*yₗ[1]).^2 .+ (yₗ'.+yₗ[1]/2).^2)) .-
exp.(-α*((xₗ.+sqrt(3)/2*yₗ[1]).^2 .+ (yₗ'.-yₗ[1]/2).^2)) .-
exp.(-α*((xₗ.-sqrt(3)/2*yₗ[1]).^2 .+ (yₗ'.-yₗ[1]/2).^2)) .-
exp.(-α*((xₗ.-sqrt(3)/2*yₗ[1]).^2 .+ (yₗ'.+yₗ[1]/2).^2)) .-
exp.(-α*((xₗ).^2 .+ (yₗ').^2)))
u01 = kron(ones(Nₚ, Nₚ), u01_piece)
heatmap(u01)
However:
- This code is very clunky and ugly
- This code is not generalizable to more complex patterns, such as the one I’m actually after shown below:
I tried using this Bravais.jl package but it is a WIP and doesn’t exactly work with rectangular grids.
using Bravais
using Plots
N = 5
M = 5
c = 6
Lattice = TriangularLattice([N,M])
x = zeros(1, N*M)
y = zeros(1, N*M)
for i in 1:N*M
x[i], y[i] = realspace(lattice, lattice[i])
end
x = [-x -x x x] # Need to remove duplicates but no big deal for now
y = [-y y -y y]
xₘ = maximum(x)
yₘ = maximum(y)
Ng = 256
dx = 1/143
dy = dx*yₘ/xₘ
xg = collect(-Ng/2*dx:dx:(Ng/2-1)*dx)
yg = collect(-Ng/2*dy:dy:(Ng/2-1)*dy)
x = x./xₘ*maximum(xg)
y = y./xₘ*maximum(xg)
α = 500.0
u01_piece = ones(Ng,Ng)
for i in 1:length(x)
u01_piece .-= exp.(-α*((xg .- x[i]).^2 .+ (yg'.- y[i]).^2))
end
#u01 = kron(ones(Nₚ, Nₚ), u01_piece)
heatmap(xg, yg, u01_piece', aspect_ratio=yₘ/xₘ)
Any thoughts on this problem? Is there a package that makes writing code like this more elegant? Or a different approach than what I’m doing?