WTP.OnGrid
β TypeThe orbitals are defined somewhat abstractly as functions on grids. The grid points are often times either real space points or wave numbers, but more generally they are sets of parameters of the a family of functions.
Centering Convention:
An OnGrid complies to the centering convention if it is defined on a grid centered at the origin. This means the domain is from -N to N-1 for an even grid, and -N to N for an odd grid.
Creating an Orbital
Base.map
β Methodmap(f, grid)
Map a pure function f
onto every grid vector on grid
. The map is threaded, so an unpure f
would probabbly be unsafe.
More likely than not, you would use the do
syntax
Example
julia> homecell = make_grid(HomeCell3D, CARTESIAN_BASIS, size_to_domain((4, 4, 4)));
julia> lattice = transform_grid(homecell);
julia> Ο = map(r->exp(1im * (lattice[1, 0, 0]' * r)), homecell);
julia> Ο[homecell[:, 0, 0]]
4-element Vector{ComplexF64}:
-1.0 - 1.2246467991473532e-16im
6.123233995736766e-17 - 1.0im
1.0 + 0.0im
6.123233995736766e-17 + 1.0im
This syntax is very simple and expressive, but keep in mind that this involves compiling an anonymous function for each map, which costs as much as the mapping it self.
Indexing
Indexing with a single grid vector
Base.getindex
β Methodgetindex(on_grid, grid_vector)
Indexing an OnGrid
object with a grid vector gives the element on the corresponding grid point. Can also write on_grid[grid_vector]
Example:
julia> Ο[homecell[0, 0, 0]]
0.0
Base.setindex!
β Methodsetindex!(on_grid, value, grid_vector)
Set an element of an OnGrid
object identified by a grid vector. Can also write on_grid[grid_vector] = value
.
Example:
julia> Ο[homecell[0, 0, 0]] = 24;
julia> Ο[homecell[0, 0, 0]]
24
julia> Ο[homecell[0, 0, 0]] = 0; # remember to set it back for later examples.
Indexing with an array of grid vectors
Base.getindex
β Methodgetindex(on_grid, grid_vector_array)
Indexing an OnGrid
object with an array of grid vectors gives an array of elements with the same dimension.
Example:
julia> Ο[homecell[:, 0, -1:1]]
4Γ3 Matrix{Float64}:
0.0 0.0 0.0
0.0 0.0 0.0
0.0 0.0 0.0
0.0 1.0 0.0
Base.setindex!
β Methodsetindex!(on_grid, value, grid_vector)
Set an array of elements of an OnGrid
object identified by an array of grid vectors with the same dimension. Can also write on_grid[grid_vector] = value
.
Example:
julia> Ο[homecell[:, 0, 0]] = [4, 3, 2, 1];
julia> Ο[homecell[:, 0, 0]]
24
julia> Ο[homecell[:, 0, 0]] = [0, 0, 0, 1]; # remember to set it back for later examples.
Normalization
LinearAlgebra.norm
β Methodnorm(on_grid)
The square norm of a function on a grid.
Example:
julia> norm(Ο)
8.0
WTP.square_normalize
β Functionsquare_normalize(on_grid)
Normalize on_grid to unit square norm.
Example:
julia> Ο_2 = square_normalize(Ο);
julia> norm(Ο_2)
1.0
WTP.square_normalize!
β Functionsquare_normalize!(on_grid)
Same as square_normalize
, but in place.
Example:
julia> square_normalize!(Ο);
julia> norm(Ο)
1.0
FFT
WTP.fft
β Methodfft(on_grid)
Fast Fourier Transform of an OnGrid
object.
Example:
julia> ΟΜ = fft(Ο);
julia> ΟΜ[lattice[:, 0, 0]]
4-element Vector{ComplexF64}:
-3.061616997868383e-17 - 3.061616997868383e-17im
0.0 + 3.061616997868383e-17im
3.061616997868383e-17 - 3.061616997868383e-17im
1.0 + 3.061616997868383e-17im
julia> typeof(Ο)
WTP.SimpleFunctionOnGrid{ReciprocalLattice3D}
WTP.ifft
β Methodifft(orbital)
Inverse Fast Fourier Transform of an OnGrid
object. The memory of the argument will be repurposed for its FFT.
Example:
julia> Ο = ifft(ΟΜ)
julia> Ο[homecell[:, 0, 0]]
4-element Vector{ComplexF64}:
-0.125 - 1.5308084989341915e-17im
7.654042494670958e-18 - 0.125im
0.125 + 0.0im
7.654042494670958e-18 + 0.125im
julia> typeof(Ο)
WTP.SimpleFunctionOnGrid{HomeCell3D}
WTP.@fft!
β Macro@fft!(real_orbital)
Perform a in-place Fourier Transform. real_orbital
will be set to nothing
.
WTP.@ifft!
β Macro@ifft!(reciprocal_orbital)
Perform a in-place inverse Fourier Transform. reciprocal_orbital
will be set to nothing
.
Arithmatics
WTP.add
β Methodadd(o_1, o_2)
Can also write o_1 + o_2
WTP.negate
β Methodnegate(o_1)
Can also write -o_1
.
WTP.minus
β Methodminus(o_1, o_2)
Can also write o_1 - o_2
.
WTP.mul
β Methodmul(o_1, o_2)
Elementwise product. Can also write o_1 * o_2
when both of them are bra
or ket
.
Base.abs2
β Methodabs2(o_1)
Elementwise abs2
. Handy for computing the density.
Example:
julia> sum(elements(abs2(Ο)))
1.0
WTP.braket
β Methodbraket(o_1, o_2)
β¨o1 | o2β©. It does not matter whether o_1
or o_2
is a ket. braket
will do the right thing. Can also write o_1' * o_2
, where o_1'
has to be a bra and o_2
must be a ket.
Example:
julia> braket(Ο, Ο)
1.0 + 0.0im
julia> Ο' * Ο
1.0 + 6.123233995736766e-17im
Density center
WTP.compute_r2
β Functionr2(homecell)
Compute $r^2$ on a homecell together with its Fourier transform.
Example:
julia> r2, rΜ2 = compute_r2(homecell);
julia> r2[homecell[2, 0, 0]]
4.0
julia> rΜ2[grid(rΜ2)[0, 0, 0]]
288.0 + 0.0im
WTP.center_spread
β Functioncenter_spread(oΜ, rΜ2)
Compute the center and the spread. Here, oΜ
should generally be fft of the density (instead of the orbital).
The algorithm can fail when the center is ill-defined
Example:
julia> center_spread(fft(abs2(Ο), false), rΜ2)
([NaN, NaN, NaN], NaN)
julia> center_spread(fft(abs2(square_normalize(map(r->r==homecell[0, 0, 0], homecell)))), rΜ2)
([0.0, -0.0, -0.0], 8.326672684688674e-17)
Misc
WTP.expand
β Methodexpand(on_grid, factors)
Expand (copy) an OnGrid
object by factors
along the respective directions.
Example:
julia> ΟΜ = expand(Ο);
julia> grid(ΟΜ)
type: ReciprocalLattice3D
domain: ((-4, 3), (-4, 3), (-4, 3))
basis:
ket: 1.571, 0.000, 0.000
ket: 0.000, 1.571, 0.000
ket: 0.000, 0.000, 1.571
julia> grid(Ο)
type: ReciprocalLattice3D
domain: ((-2, 1), (-2, 1), (-2, 1))
basis:
ket: 1.571, 0.000, 0.000
ket: 0.000, 1.571, 0.000
ket: 0.000, 0.000, 1.571
WTP.vectorize
β Methodvectorize(o)
Reshape the elements into a column vector.
WTP.sparsify
β Functionsparsify(on_grid, threshold=1e-16)
Store the elements of on_grid
as a sparse array.
PS: Quantum Espresso seems to have reinvented sparse arrays in trying to store their orbitals (with a spherical energy cutoff) efficeintly.
Example:
julia> ΟΜ_2 = sparsify(ΟΜ, threshold=1e-16);
julia> vectorize(ΟΜ_2)
64-element SparseVector{Number, Int64} with 1 stored entry:
[2 ] = 1.0+3.06162e-17im
Base.:>>
β Methodon_grid >> grid_vector
Translate on_grid
by grid_vector
.
Example:
julia> ΟΜ = ΟΜ >> lattice[1, 0, 0];
julia> ΟΜ[lattice[:, 0, 0]]
4-element Vector{ComplexF64}:
1.0 + 3.061616997868383e-17im
-3.061616997868383e-17 - 3.061616997868383e-17im
0.0 + 3.061616997868383e-17im
3.061616997868383e-17 - 3.061616997868383e-17im
julia> ΟΜ[lattice[:, 0, 0]]
4-element Vector{ComplexF64}:
-3.061616997868383e-17 - 3.061616997868383e-17im
0.0 + 3.061616997868383e-17im
3.061616997868383e-17 - 3.061616997868383e-17im
1.0 + 3.061616997868383e-17im