Neumann.jl

Neumann.jl exports a single method:

Neumann.neumannMethod
neumann(ops, N::Integer; kws...)  -->  Vector{String}

Return the symmetry-constraints among components of a tensor imposed by the set of point group symmetries in ops. The tensor order is provided via N. ops can be either a single symmetry operation (provided as an AbstractMatrix) or any iterable of symmetry operations.

The obtained relations are returned as a Vector{String}, with each element of this vector giving either:

  1. a free, nonzero component of the tensor (e.g., "xxx"),
  2. free, nonzero - but interrelated - components of the tensor (e.g., "xxx = yyy"),
  3. forbidden, zero components of the tensor (e.g., "xyz = xzy = 0").

Note that if the provided operators are not given in a Cartesian basis, the returned relations among tensor components will match the basis of the provided operators: we generally recommend supplying operators in a Cartesian basis for ease of interpretation.

Keyword arguments kws

  • kleinman (default, false): whether to incorporate Kleinman symmetry, i.e. whether to enforce that A[i,j,k,…] = A[i,perm(j,k,…)...] with perm(j,k,…) denoting all unique permutations of [j,k,…]. Relevant e.g., to low-frequency second-harmonic generation.
  • sparsify (default, true): whether to attempt to sparsify relations between allowed nonzero components of the response tensor. A "poor man's" approximation of matrix sparsification is carried out using the reduced row echelon form.
  • rref_tol (default, 1e-11): the absolute tolerance used during row echelon reduction in sparsification. As the row echelon form is numerically unstable for larger matrices, it may be necessary to increase this tolerance for larger tensor orders. Set to nothing to use the default tolerance of of RowEchelon.jl's rref.
  • atol (default, 1e-10): the absolute tolerance used in assessing whether a term in a relation is considered vanishing or not (and similarly used to assess whether a term has integer coefficient). Must be greater than rref_tol.
  • nullspace_kws (default, empty): keyword arguments passed to nullspace.

Examples

Second harmonic generation is forbidden in inversion symmetric materials

julia> using Neumann
julia> N = 3 # second-harmonic generation → third-rank tensor
julia> inversion = [-1 0 0; 0 -1 0; 0 0 -1]
julia> neumann(inversion, N)
1-element Vector{String}:
 "xxx = yxx = zxx = xyx = yyx = z" ⋯ 102 bytes ⋯ "yz = zyz = xzz = yzz = zzz = 0"

But several components of the second-harmonic response are allowed under e.g. the point group symmetry of D₃ (321):

julia> using Crystalline
julia> ops = generators("321", PointGroup{3}) # obtain generators of D₃ (321) from Crystalline
julia> ops .= cartesianize.(ops, Ref(crystal(1,1,1,π/2,π/2,2π/3))); # convert to a Cartesian basis
julia> neumann(ops, N)
5-element Vector{String}:
 "xxx = -yyx = -yxy = -xyy"
 "zyx = -zxy"
 "yzx = -xzy"
 "yxz = -xyz"
 "yxx = zxx = xyx = xzx = zzx = x" ⋯ 41 bytes ⋯ "yyz = zyz = xzz = yzz = zzz = 0"
source