ACE Descriptors

This tutorial demonstrates a simple use of ACE descriptors.

using ACEpotentials, MultivariateStats, Plots

Load a tiny silicon dataset, which has the isolated atom, 25 diamond-like (dia) configurations, 25 beta-tin-like (bt) configurations, and 2 liquid (liq) configurations.

dataset, _, _ = ACEpotentials.example_dataset("Si_tiny");

An ACE basis specifies a vector of invariant features of atomic environments and can therefore be used as a general descriptor.

basis = ACE1x.ace_basis(elements = [:Si],
                        rcut = 5.5,
                        order = 3,        # body-order - 1
                        totaldegree = 8);

Compute an averaged structural descriptor for each configuration.

descriptors = []
config_types = []
for atoms in dataset
    struct_descriptor = sum(site_descriptors(basis, atoms)) / length(atoms)
    push!(descriptors, struct_descriptor)
    push!(config_types, atoms.data["config_type"].data)
end

Finally, extract the descriptor principal components and plot. Note the segregation by configuration type.

descriptors = hcat(descriptors...)
M = fit(PCA, descriptors; maxoutdim=3, pratio=1)
descriptors_trans = transform(M, descriptors)
p = scatter(
    descriptors_trans[1,:], descriptors_trans[2,:], descriptors_trans[3,:],
    marker=:circle, linewidth=0, group=config_types, legend=:right)
plot!(p, xlabel="PC1", ylabel="PC2", zlabel="PC3", camera=(20,10))
Example block output

The basis used above uses defaults that are suitable for regression of a potential energy surface, but other defaults might be better when using the ACE descriptor for other tasks such as classification. The following short script shows how to make some changes of this kind:

model = acemodel(elements = [:Si,], order = 3, totaldegree = 10,
       pair_transform = (:agnesi, 1, 4, 0.0),
       pair_envelope = (:x, 0, 2),
       transform = (:agnesi, 1, 4, 0.0),
       envelope = (:x, 0, 2),
       r0 = :bondlen, # default, could specify explicitly
       )
basis = model.basis
JuLIP.MLIPs.IPSuperBasis{JuLIP.MLIPs.IPBasis}(JuLIP.MLIPs.IPBasis[PolyPairBasis{ACE1.OrthPolys.TransformedPolys{Float64, ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}, ACE1.OrthPolys.OrthPolyBasis{Float64}, ACE1.OrthPolys.OneEnvelope}, 1}(JuLIP.Potentials.SZList{1}(AtomicNumber[<14>]), ACE1.OrthPolys.TransformedPolys{Float64, ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}, ACE1.OrthPolys.OrthPolyBasis{Float64}, ACE1.OrthPolys.OneEnvelope}[ACE1.OrthPolys.TransformedPolys{Float64, ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}, ACE1.OrthPolys.OrthPolyBasis{Float64}, ACE1.OrthPolys.OneEnvelope}(ACE1.OrthPolys.OrthPolyBasis{Float64}(0, 0.0, 2, 1.0, [2.2360689091951995, 7.099309346735727, 5.291522024409, 4.738063448424564, 4.484386643542148, 4.344482007955068, 4.258391894831597, 4.201377361610357, 4.1615577274183035, 4.132600058800379], [0.0, -1.1832206894942505, -1.7638467747583702, -1.8952356846820837, -1.943249621114157, -1.965382380919459, -1.9771390388551457, -1.9840203025885013, -1.9883453766477837, -1.9912174403384049], [0.0, 0.0, -0.7453572968815695, -0.8954065440091865, -0.9464598126125228, -0.9688018347417563, -0.9801840327648208, -0.9866112526443501, -0.9905222428825616, -0.9930416275551956], [0.0005, 0.0015, 0.0025, 0.0035, 0.0045, 0.0055, 0.0065, 0.0075, 0.0085, 0.0095  …  0.9905, 0.9915, 0.9925, 0.9935, 0.9945, 0.9955, 0.9965, 0.9975, 0.9985, 0.9995], [0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001  …  0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001]), ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}(ACE1.Transforms.Agnesi2Transform{Float64, Int64}(2.4, 1, 4, 0.2727272727272727, 0.0), 1.0, 0.6094563632576547, 6.0), 0.0, 6.0, ACE1.OrthPolys.OneEnvelope());;], [0;;]), RPIBasis{Float64, BasicPSH1pBasis{Float64, 1, ACE1.OrthPolys.TransformedPolys{Float64, ACE1.Transforms.MultiTransform{1, ACE1.Transforms.AffineT{Float64, ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}}}, ACE1.OrthPolys.OrthPolyBasis{Float64}, ACE1.OrthPolys.OneEnvelope}}, 1, ACE1.DAGEvaluator}(PIBasis{BasicPSH1pBasis{Float64, 1, ACE1.OrthPolys.TransformedPolys{Float64, ACE1.Transforms.MultiTransform{1, ACE1.Transforms.AffineT{Float64, ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}}}, ACE1.OrthPolys.OrthPolyBasis{Float64}, ACE1.OrthPolys.OneEnvelope}}, 1, ACE1.DAGEvaluator}(BasicPSH1pBasis{Float64, 1, ACE1.OrthPolys.TransformedPolys{Float64, ACE1.Transforms.MultiTransform{1, ACE1.Transforms.AffineT{Float64, ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}}}, ACE1.OrthPolys.OrthPolyBasis{Float64}, ACE1.OrthPolys.OneEnvelope}}(ACE1.OrthPolys.TransformedPolys{Float64, ACE1.Transforms.MultiTransform{1, ACE1.Transforms.AffineT{Float64, ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}}}, ACE1.OrthPolys.OrthPolyBasis{Float64}, ACE1.OrthPolys.OneEnvelope}(ACE1.OrthPolys.OrthPolyBasis{Float64}(0, -1.0, 2, 1.0, [0.5590172272987999, 3.5496546733678636, 2.6457610122045, 2.3690317242122805, 2.2421933217710746, 2.1722410039775335, 2.129195947415799, 2.1006886808051783, 2.0807788637091518, 2.066300029400189, 2.055429679150542, 2.047054944278475, 2.040463473582576], [0.0, 2.3664339838736135, 0.881914237446129, 0.4737960395301985, 0.29894370065691694, 0.20685862305807545, 0.15205690856065218, 0.1166683782166776, 0.09243348706136743, 0.07508258906178471, 0.0622191370400381, 0.05240996282372767, 0.044753712522501335, 0.03865970882897952], [0.0, 0.0, -0.7453572968815678, -0.8954065440091885, -0.9464598126125205, -0.9688018347417586, -0.9801840327648191, -0.9866112526443519, -0.9905222428825597, -0.9930416275551971, -0.9947392198156224, -0.9959255551493605, -0.9967800225810635, -0.997411318554425], [-0.999, -0.997, -0.995, -0.993, -0.991, -0.989, -0.987, -0.985, -0.983, -0.981  …  0.981, 0.983, 0.985, 0.987, 0.989, 0.991, 0.993, 0.995, 0.997, 0.999], [0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001  …  0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001]), ACE1.Transforms.MultiTransform{1, ACE1.Transforms.AffineT{Float64, ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}}}(JuLIP.Potentials.SZList{1}(AtomicNumber[<14>]), ACE1.Transforms.AffineT{Float64, ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}}[ACE1.Transforms.AffineT{Float64, ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}}(ACE1.Transforms.Normalized{Float64, ACE1.Transforms.Agnesi2Transform{Float64, Int64}}(ACE1.Transforms.Agnesi2Transform{Float64, Int64}(2.4, 1, 4, 0.2727272727272727, 0.0), 1.0, 0.6094563632576547, 6.0), 0.0, 1.0, -1.0, 1.0);;]), 0.0, 6.0, ACE1.OrthPolys.OneEnvelope()), ACE1.SphericalHarmonics.SHBasis{Float64}(2, ACE1.SphericalHarmonics.ALPCoefficients{Float64}([6.9096938596553e-310, 0.0, 6.9096938596561e-310, 1.9364916731037085, 6.90969385965213e-310, 0.0], [6.90975067562514e-310, 6.90970740417723e-310, 6.90975874806966e-310, -0.5773502691896257, 6.90974765051415e-310, 6.9097587480839e-310])), JuLIP.Potentials.SZList{1}(AtomicNumber[<14>]), ACE1.RPI.PSH1pBasisFcn[znlm[0|1,0,0], znlm[0|1,1,-1], znlm[0|1,1,0], znlm[0|1,1,1], znlm[0|1,2,-2], znlm[0|1,2,-1], znlm[0|1,2,0], znlm[0|1,2,1], znlm[0|1,2,2], znlm[0|2,0,0]  …  znlm[0|6,0,0], znlm[0|6,1,-1], znlm[0|6,1,0], znlm[0|6,1,1], znlm[0|7,0,0], znlm[0|8,0,0], znlm[0|9,0,0], znlm[0|10,0,0], znlm[0|11,0,0], znlm[0|12,0,0]], UnitRange{Int64}[1:45;;]), JuLIP.Potentials.SZList{1}(AtomicNumber[<14>]), (ACE1.InnerPIBasis([1, 1, 1, 1, 1, 1, 1, 1, 1, 1  …  3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [1 0 0; 10 0 0; … ; 19 19 19; 19 19 28], Dict{ACE1.PIBasisFcn, Int64}(ACE1.PIBasisFcn{2, ACE1.RPI.PSH1pBasisFcn}(<14>, (znlm[14|2,1,1], znlm[14|4,1,-1]), ACE1.RPI.PSH1pBasisFcn) => 68, ACE1.PIBasisFcn{3, ACE1.RPI.PSH1pBasisFcn}(<14>, (znlm[14|1,0,0], znlm[14|3,0,0], znlm[14|6,0,0]), ACE1.RPI.PSH1pBasisFcn) => 134, ACE1.PIBasisFcn{3, ACE1.RPI.PSH1pBasisFcn}(<14>, (znlm[14|1,1,0], znlm[14|2,1,0], znlm[14|3,0,0]), ACE1.RPI.PSH1pBasisFcn) => 172, ACE1.PIBasisFcn{3, ACE1.RPI.PSH1pBasisFcn}(<14>, (znlm[14|1,1,-1], znlm[14|1,1,1], znlm[14|5,0,0]), ACE1.RPI.PSH1pBasisFcn) => 148, ACE1.PIBasisFcn{3, ACE1.RPI.PSH1pBasisFcn}(<14>, (znlm[14|1,1,-1], znlm[14|1,2,1], znlm[14|2,1,0]), ACE1.RPI.PSH1pBasisFcn) => 150, ACE1.PIBasisFcn{3, ACE1.RPI.PSH1pBasisFcn}(<14>, (znlm[14|2,0,0], znlm[14|2,0,0], znlm[14|6,0,0]), ACE1.RPI.PSH1pBasisFcn) => 193, ACE1.PIBasisFcn{3, ACE1.RPI.PSH1pBasisFcn}(<14>, (znlm[14|1,0,0], znlm[14|1,1,-1], znlm[14|2,1,1]), ACE1.RPI.PSH1pBasisFcn) => 96, ACE1.PIBasisFcn{2, ACE1.RPI.PSH1pBasisFcn}(<14>, (znlm[14|3,0,0], znlm[14|4,0,0]), ACE1.RPI.PSH1pBasisFcn) => 74, ACE1.PIBasisFcn{2, ACE1.RPI.PSH1pBasisFcn}(<14>, (znlm[14|1,2,-2], znlm[14|1,2,2]), ACE1.RPI.PSH1pBasisFcn) => 39, ACE1.PIBasisFcn{3, ACE1.RPI.PSH1pBasisFcn}(<14>, (znlm[14|1,0,0], znlm[14|1,2,1], znlm[14|2,2,-1]), ACE1.RPI.PSH1pBasisFcn) => 115…), Dict{Any, Int64}(), 1:206, <14>, ACE1.DAG.CorrEvalGraph{Int64, Int64}([(1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0), (8, 0), (9, 0), (10, 0)  …  (10, 79), (10, 81), (73, 19), (73, 28), (73, 32), (74, 28), (75, 19), (78, 19), (83, 19), (83, 28)], [1, 0, 0, 0, 0, 0, 0, 0, 0, 2  …  197, 198, 199, 200, 201, 202, 203, 204, 205, 206], 45, 95)),), ACE1.DAGEvaluator()), (sparse([1, 2, 3, 10, 11, 12, 16, 17, 18, 19  …  93, 93, 94, 95, 96, 97, 98, 98, 99, 100], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1  …  197, 198, 199, 200, 201, 202, 203, 204, 205, 206], [-0.6371868657466297, 0.13327692844605582, -0.016791269897828018, -1.103640025388731, 0.23084241154529034, -0.029083332586639976, 1.424793146179495, -0.2980162718377559, 0.03754642092008935, -0.4460295422673056  …  0.5773502691896257, -0.5773502691896257, 1.4142135623730951, 1.0, 1.0, 1.4142135623730951, -1.6329931618554518, 0.8164965809277259, 2.449489742783178, 1.4142135623730951], 100, 206),), (1:100,))])
  • [pair_]transfor = (:agnesi, 1, 4, 0.0) : this generates a transform that behaves as t' ~ r^3 near zero and t' ~ r^-2 near the cutoff, but then actually enforces t' = 0 at the cutoff.
  • [pair_]envelope = (:x, 0, 2) : this generates an envelope that is ~ (x - xcut)^2 at the cutoff and just ~ 1 for r -> 0.

This page was generated using Literate.jl.