Source code for hiphive.input_output.gpumd

from itertools import permutations, product
import ase
import numpy as np


[docs] def write_fcs_gpumd( fname_fc: str, fname_clusters: str, fcs, order: int, tol: float = 1e-10, ) -> None: """ Writes force constants of given order in GPUMD format. Parameters ---------- fname_fc Name of file which contains the lookup force constants. fname_clusters Name of file which contains the clusters and the force constant lookup index. fcs Force constants in :class:`ForceConstants` format. order Force constants for this order will be written to file. tol If the norm of a force constant term is less than this value it will be excluded from the output; if two force-constants differ by this value or less, they are considered equal. """ cluster_lookup, fc_lookup = _get_lookup_data_smart(fcs, order, tol) _write_clusters(fname_clusters, cluster_lookup, order) _write_fc_lookup(fname_fc, fc_lookup, order)
def _write_fc_lookup(fname, fc_lookup, order): """ Writes the lookup force constants to file """ fmt = '{}' + ' {}'*order with open(fname, 'w') as f: f.write(str(len(fc_lookup)) + '\n\n') for fc in fc_lookup: for xyz in product(range(3), repeat=order): f.write(fmt.format(*xyz, fc[xyz])+'\n') f.write('\n') def _write_clusters(fname, cluster_lookup, order): """ Writes the cluster lookup to file """ fmt = '{}' + ' {}'*order with open(fname, 'w') as f: f.write(str(len(cluster_lookup)) + '\n\n') for c, i in cluster_lookup.items(): line = fmt.format(*c, i) + '\n' f.write(line) def _get_clusters(fcs, order: int, tol: float): """ Collect all relevant clusters; for 2nd and 3rd-order force constants all permutations are included. """ if order in [2, 3]: clusters = [] for c in fcs._fc_dict.keys(): if len(c) == order and np.linalg.norm(fcs[c]) > tol: for ci in permutations(c): clusters.append(ci) clusters = list(sorted(set(clusters))) else: clusters = [c for c in fcs._fc_dict.keys() if len(c) == order and np.linalg.norm(fcs[c]) > tol] # noqa return clusters def _get_lookup_data_naive(fcs, order: int, tol: float): """ Groups force constants for a given order into groups for which the force constant is identical. """ fc_lookup = [] cluster_lookup = dict() clusters = _get_clusters(fcs, order, tol) for c in clusters: fc1 = fcs[c] if np.linalg.norm(fc1) < tol: continue for i, fc2 in enumerate(fc_lookup): if np.linalg.norm(fc1 - fc2) < tol: cluster_lookup[c] = i break else: cluster_lookup[c] = len(fc_lookup) fc_lookup.append(fc1) return cluster_lookup, fc_lookup def _get_lookup_data_smart(fcs, order: int, tol: float): """ Groups force constants for a given order into groups for which the force constant is identical. """ fc_lookup = [] cluster_lookup = dict() axis = tuple(range(1, order+1)) clusters = _get_clusters(fcs, order, tol) fc_all = np.array([fcs[c] for c in clusters]) indices = list(range(len(clusters))) while len(indices) > 0: i = indices[0] delta = fc_all[indices] - fc_all[i] delta_norm = np.sqrt(np.sum(delta**2, axis=axis)) inds_to_del = [indices[x] for x in np.where(delta_norm < tol)[0]] assert i in inds_to_del fc_lookup.append(fc_all[i]) for j in inds_to_del: indices.remove(j) cluster_lookup[clusters[j]] = len(fc_lookup)-1 return cluster_lookup, fc_lookup
[docs] def write_fcp_txt( fname: str, path: str, n_types: int, max_order: int, heat_current_order: int = 2, ) -> None: """ Write driver potential file for GPUMD. Parameters ---------- fname Output file name. path Path to directory with force constant file. n_types Number of atom types. max_order Maximum order of the force constant potential. heat_current_order Heat current order used in thermal conductivity. Format is a simple file containing the following:: fcp number_of_atom_types highest_force_order heat_current_order path_to_force_constant_files which in practice for a binary system with a sixth order model, consider third-order heat-currents, would mean:: fcp 2 6 3 /path/to/your/folder """ with open(fname, 'w') as f: f.write('fcp {}\n'.format(n_types)) f.write('{} {}\n'.format(max_order, heat_current_order)) f.write('{}'.format(path.rstrip('/'))) # without a trailing '/'
[docs] def write_r0(fname: str, atoms: ase.Atoms): """ Write the GPUMD r0 file with the reference atomic positions. Parameters ---------- fname Name of file to which to write the atomic positions. atoms Input structure. """ line = '{} {} {}\n' with open(fname, 'w') as f: for a in atoms: f.write(line.format(*a.position))