AtomsBase Interface
ACEpotentials has a new AtomsBase based interface in addition to JuLIP based interface.
AtomsBase allows easy communication between different Julia programs. In the future this interface will became the default one and JuLIP interface will be retired.
AtomsBase interface has not been rigorously tested yet. So, expect some issues here and there. But you are recommended to git it a try.
Loading Training Data
With AtomsBase you can use AtomsIO to load training data
using AtomsIO
data = load_trajectory("path to training data")
You can also use ExtXYZ directly (exported by ACEpotentials) to load training data
data = ExtXYZ.load("path to training data")
To use AtomsBase with the examples you can load the training data in AtomsBase format by giving a keyword argument atoms_base=true
data, _, meta = ACEpotentials.example_dataset("TiAl_tutorial"; atoms_base=true)
Training with AtomsBase
There are no changes to the training methods when using AtomsBase. You only need to have the training data in AtomsBase format for the training to work. Here is the acemodel
style training tutorial using AtomsBase
using ACEpotentials
data, _, meta = ACEpotentials.example_dataset("TiAl_tutorial"; atoms_base=true)
model = acemodel(
elements = [:Ti, :Al],
order = 3,
totaldegree = 6,
rcut = 5.5,
Eref = [:Ti => -1586.0195, :Al => -105.5954]
)
@show length(model.basis);
weights = Dict(
"FLD_TiAl" => Dict("E" => 60.0, "F" => 1.0 , "V" => 1.0 ),
"TiAl_T5000" => Dict("E" => 5.0, "F" => 1.0 , "V" => 1.0 )
);
solver = ACEfit.LSQR(damp = 1e-2, atol = 1e-6);
data_train = data[1:5:end]
P = smoothness_prior(model; p = 4)
acefit!(model, data_train; solver=solver, weights=weights, prior = P);
@info("Training Error Table")
ACEpotentials.linear_errors(data_train, model; weights=weights);
Weights with AtomsBase
With AtomsBase weights are stored in AtomsBase structures and there is no need to create AtomsData
structures. Weights can be given for either energy, forces or virial and for structure itself. Each of these have an associated keyword
:energy_weight
for energy:force_weight
for forcesvirial_weight
for virial:weight
a general weight for the structure that multiply other weights
To access the weights you can call
data_point[:energy_weight]
data_point[:force_weight]
data_point[:virial_weight]
data_point[:weight]
To set a weight by hand on an individual structure you can use
# Set general weight
data_point[:weight] = 60
# Set weight for energy
data_point[:energy_weight] = 60
# etc.
When you use acemodel interface (call acefit!
) the weights are applied by overwriting any existing weights.
You can look for what keys AtomsBase structures support by calling
# whole structure features
keys(data_point)
# features per atom
atomkeys(data_point)
You can give keyword group_key
to acefit!
to determine what group weights are used. Make sure that corresponding haskey
call returns true.
New Assemble Backend
AtomsBase interface uses new assemble backend that is faster than the old one. You can you the new backend with old JuLIP interface by giving keyword new_assembly=true
. E.g.
# acefit interface
acefit!(model, data_train; solver=solver, weights=weights, prior = P, new_assembly=true);
# acebasis interface
ACEfit.assemble(data_train, basis; new_assembly=true)
Calculations with AtomsBase
To use AtomsBase structures as an input for calculations you need to create ACEpotential
structure. If you use acemodel interface (like above) you can do this with
pot = ACEpotential(model)
If you use acebasis interface you can create potential with
pot_1 = ACEpotential(basis, results["C"])
After this you can use commands
E = ace_energy(system, pot)
F = ace_forces(system, pot)
V = ace_virial(system, pot)
where system
is an AtomsBase structure.
For more details on using AtomsBase look ACEmd.