After Training¶
After the on-the-fly training is complete, we can play with the force field we obtained. We are going to do the following things:
- Parse the on-the-fly training trajectory to collect training data
- Reconstruct the GP model from the training trajectory
- Build up Mapped GP (MGP) for accelerated force field, and save coefficient file for LAMMPS
- Use LAMMPS to run fast simulation using MGP pair style
Parse OTF log file¶
After the on-the-fly training is complete, we have a log file and can use the otf_parser
module to parse the trajectory.
[3]:
import numpy as np
from flare import otf_parser
logdir = '../../../tests/test_files'
file_name = f'{logdir}/AgI_snippet.out'
hyp_no = 2 # use the hyperparameters from the 2nd training step
otf_object = otf_parser.OtfAnalysis(file_name)
Construct GP model from log file¶
We can reconstruct GP model from the parsed log file (the on-the-fly training trajectory). Here we build up the GP model with 2+3 body kernel from the on-the-fly log file.
[4]:
gp_model = otf_object.make_gp(hyp_no=hyp_no)
gp_model.parallel = True
gp_model.hyp_labels = ['sig2', 'ls2', 'sig3', 'ls3', 'noise']
# write model to a binary file
gp_model.write_model('AgI.gp', format='pickle')
Final name of the gp instance is default_gp_2
The last step write_model
is to write this GP model into a binary file, so next time we can directly load the model from the pickle file as
[5]:
from flare.gp import GaussianProcess
gp_model = GaussianProcess.from_file('AgI.gp.pickle')
Final name of the gp instance is default_gp_2_2
Map the GP force field & Dump LAMMPS coefficient file¶
To use the trained force field with accelerated version MGP, or in LAMMPS, we need to build MGP from GP model. Since 2-body and 3-body are both included, we need to set up the number of grid points for 2-body and 3-body in grid_params
. We build up energy mapping, thus set map_force=False
. See MGP tutorial for more explanation of the MGP settings.
[6]:
from flare.mgp import MappedGaussianProcess
grid_params = {'twobody': {'grid_num': [64]},
'threebody': {'grid_num': [20, 20, 20]}}
data = gp_model.training_statistics
lammps_location = 'AgI_Molten_15.txt'
mgp_model = MappedGaussianProcess(grid_params, data['species'],
map_force=False, lmp_file_name='AgI_Molten_15.txt', n_cpus=1)
mgp_model.build_map(gp_model)
The coefficient file for LAMMPS mgp pair_style is automatically saved once the mapping is done. Saved as lmp_file_name
.
Run LAMMPS with MGP pair style¶
With the above coefficient file, we can run LAMMPS simulation with the mgp pair style. First download our mgp pair style files, compile your lammps executable with mgp pair style following our instruction.
- One way to use it is running
lmp_executable < in.lammps > log.lammps
with the executable provided in our repository. When creating the input file, please note to set
newton off
pair_style mgp
pair_coeff * * <lmp_file_name> <chemical_symbols> yes/no yes/no
An example is using coefficient file AgI_Molten_15.txt
for AgI system, with two-body (the 1st yes
) together with three-body (the 2nd yes
).
pair_coeff * * AgI_Molten_15.txt Ag I yes yes
Note: if you build force mapping (map_force=True
) instead of energy mapping, please use
pair_style mgpf
- The third way is to use the ASE LAMMPS interface
[ ]:
from flare.ase.calculator import FLARE_Calculator
# get chemical symbols, masses etc.
species = gp_model.training_statistics['species']
specie_symbol_list = " ".join(species)
masses=[f"{i} {_Z_to_mass[_element_to_Z[species[i]]]}" for i in range(len(species))]
# set up input params
parameters = {'command': os.environ.get('lmp'), # set up executable for ASE
'newton': 'off',
'pair_style': 'mgp',
'pair_coeff': [f'* * {lammps_location} {specie_symbol_list} yes yes'],
'mass': masses}
files = [lammps_location]
# create ASE calc
lmp_calc = LAMMPS(label=f'tmp_AgI', keep_tmp_files=True, tmp_dir='./tmp/',
parameters=parameters, files=files, specorder=species)
- The second way to run LAMMPS is using our LAMMPS interface, please set the environment variable
$lmp
to the executable.
[ ]:
from flare import struc
from flare.lammps import lammps_calculator
# lmp coef file is automatically written now every time MGP is constructed
# create test structure
species = otf_object.gp_species_list[-1]
positions = otf_object.position_list[-1]
forces = otf_object.force_list[-1]
otf_cell = otf_object.header['cell']
structure = struc.Structure(otf_cell, species, positions)
atom_types = [1, 2]
atom_masses = [108, 127]
atom_species = [1, 2] * 27
# create data file
data_file_name = 'tmp.data'
data_text = lammps_calculator.lammps_dat(structure, atom_types,
atom_masses, atom_species)
lammps_calculator.write_text(data_file_name, data_text)
# create lammps input
style_string = 'mgp'
coeff_string = '* * {} Ag I yes yes'.format(lammps_location)
lammps_executable = '$lmp'
dump_file_name = 'tmp.dump'
input_file_name = 'tmp.in'
output_file_name = 'tmp.out'
input_text = \
lammps_calculator.generic_lammps_input(data_file_name, style_string,
coeff_string, dump_file_name)
lammps_calculator.write_text(input_file_name, input_text)
lammps_calculator.run_lammps(lammps_executable, input_file_name,
output_file_name)
lammps_forces = lammps_calculator.lammps_parser(dump_file_name)