Source code for calphy.lattice

calphy: a Python library and command line interface for automated free
energy calculations.

Copyright 2021  (c) Sarath Menon^1, Yury Lysogorskiy^2, Ralf Drautz^2
^1: Max Planck Institut für Eisenforschung, Dusseldorf, Germany 
^2: Ruhr-University Bochum, Bochum, Germany

calphy is published and distributed under the Academic Software License v1.0 (ASL). 
calphy is distributed in the hope that it will be useful for non-commercial academic research, 
calphy API is published and distributed under the BSD 3-Clause "New" or "Revised" License
See the LICENSE FILE for more details. 

More information about the program can be found in:
Menon, Sarath, Yury Lysogorskiy, Jutta Rogal, and Ralf Drautz.
“Automated Free Energy Calculation from Atomistic Simulations.” Physical Review Materials 5(10), 2021
DOI: 10.1103/PhysRevMaterials.5.103801

For more information contact:

from mendeleev import element
import os
from pylammpsmpi import LammpsLibrary
import numpy as np
import pyscal.core as pc

Conversion factors for creating initial lattices
latticedict = {
    "BCC" :{"LQD": 1.00000, "BCC":1.00000, "FCC":0.79370, "HCP":1.12246, "DIA":0.62996, "SC":1.25992, "N":2},
    "FCC" :{"LQD": 1.00000, "BCC":1.25992, "FCC":1.00000, "HCP":1.78179, "DIA":0.79370, "SC":1.58740, "N":4},
    "HCP" :{"LQD": 1.00000, "BCC":0.89090, "FCC":0.79370, "HCP":1.00000, "DIA":0.62996, "SC":0.89089, "N":4},
    "DIA" :{"LQD": 1.00000, "BCC":1.58740, "FCC":0.79370, "HCP":1.25992, "DIA":1.00000, "SC":2.00000, "N":8},
    "SC"  :{"LQD": 1.00000, "BCC":0.79370, "FCC":0.62996, "HCP":1.12247, "DIA":0.50000, "SC":1.00000, "N":1},

[docs]def get_lattice(symbol, lat): """ Find lattice constants of an element Parameters ---------- symbol : string symbol of chemical element lattice_list : list of strings list of lattices Returns ------- lattice_constants : list of floats list of lattice constant values atoms_per_cell : list of ints number of atoms per cell lammps_lattice : list of strings the main lattice to be used in lammps """ chem = element(symbol) mainlat = chem.lattice_structure if mainlat == "HEX": mainlat = "HCP" mainalat = chem.lattice_constant #print(mainlat, lat) newlat = latticedict[mainlat][lat]*mainalat lattice_constant = newlat if lat == "LQD": atoms_per_cell = latticedict[mainlat]["N"] lammps_lattice = mainlat.lower() else: atoms_per_cell = latticedict[lat]["N"] lammps_lattice = lat.lower() return lattice_constant, atoms_per_cell, lammps_lattice
[docs]def check_dump_file(infile): try: #now use pyscal to read it in, sys = pc.System() sys.read_inputfile(infile) atoms = sys.atoms natoms = len(atoms) types = [atom.type for atom in atoms] xx, xxcounts = np.unique(types, return_counts=True) conc = xxcounts/np.sum(xxcounts) return (natoms, conc) except: return None
[docs]def check_data_file(infile): try: lmp = LammpsLibrary(mode="local", cores=1, working_directory=os.getcwd()) lmp.units("metal") lmp.boundary("p p p") lmp.atom_style("atomic") lmp.timestep(0.001) lmp.read_data(infile) natoms = lmp.natoms #now we convert to a dump file and read the concentration trajfile = ".".join([infile, "dump"]) lmp.command("mass * 1.0") lmp.dump("2 all custom", 1, trajfile,"id type x y z") lmp.undump(2) #now use pyscal to read it in, sys = pc.System() sys.read_inputfile(trajfile) atoms = sys.atoms types = [atom.type for atom in atoms] xx, xxcounts = np.unique(types, return_counts=True) conc = xxcounts/np.sum(xxcounts) lmp.close() return (natoms, conc) except: return None
[docs]def prepare_lattice(calc): #process lattice lattice = calc.lattice.upper() dumpfile = False if lattice in ["BCC", "FCC", "HCP", "DIA", "SC", "LQD"]: #process lattice #throw error for multicomponent if calc.n_elements > 1: raise ValueError("Only files supported for multicomponent") alat, apc, l = get_lattice(calc.element[0], calc.lattice) #replace lattice constant if calc.lattice_constant != 0: alat = calc.lattice_constant conc = [1,] elif os.path.exists(calc.lattice): calc.lattice = os.path.abspath(calc.lattice) res = check_dump_file(calc.lattice) dumpfile = True if res is None: res = check_data_file(calc.lattice) dumpfile = False if res is not None: natoms = res[0] conc = res[1] l = "file" alat = 1.00 apc = natoms else: raise ValueError("An input file was provided but it was neither data or dump file") else: raise ValueError("Unknown lattice found. Allowed options are BCC, FCC, HCP, DIA, SC or LQD; or an input file.") if l == "dia": l = "diamond" return l, alat, apc, conc, dumpfile