def load_lammps_eam_parameters( file: TextIO ) -> Tuple[Callable[[Array], Array], Callable[[Array], Array], Callable[ [Array], Array], float]: """Reads EAM parameters from a LAMMPS file and returns relevant spline fits. This function reads single-element EAM potential fit parameters from a file in DYNAMO funcl format. In summary, the file contains: Line 1-3: comments, Line 4: Number of elements and the element type, Line 5: The number of charge values that the embedding energy is evaluated on (num_drho), interval between the charge values (drho), the number of distances the pairwise energy and the charge density is evaluated on (num_dr), the interval between these distances (dr), and the cutoff distance (cutoff). The lines that come after are the embedding function evaluated on num_drho charge values, charge function evaluated at num_dr distance values, and pairwise energy evaluated at num_dr distance values. Note that the pairwise energy is multiplied by distance (in units of eV x Angstroms). For more details of the DYNAMO file format, see: https://sites.google.com/a/ncsu.edu/cjobrien/tutorials-and-guides/eam Args: f: File handle for the EAM parameters text file. Returns: charge_fn: A function that takes an ndarray of shape [n, m] of distances between particles and returns a matrix of charge contributions. embedding_fn: Function that takes an ndarray of shape [n] of charges and returns an ndarray of shape [n] of the energy cost of embedding an atom into the charge. pairwise_fn: A function that takes an ndarray of shape [n, m] of distances and returns an ndarray of shape [n, m] of pairwise energies. cutoff: Cutoff distance for the embedding_fn and pairwise_fn. """ raw_text = file.read().split('\n') if 'setfl' not in raw_text[0]: raise ValueError( 'File format is incorrect, expected LAMMPS setfl format.') temp_params = raw_text[4].split() num_drho, num_dr = int(temp_params[0]), int(temp_params[2]) drho, dr, cutoff = float(temp_params[1]), float(temp_params[3]), float( temp_params[4]) data = maybe_downcast([float(i) for i in raw_text[6:-1]]) embedding_fn = interpolate.spline(data[:num_drho], drho) charge_fn = interpolate.spline(data[num_drho:num_drho + num_dr], dr) # LAMMPS EAM parameters file lists pairwise energies after multiplying by # distance, in units of eV*Angstrom. We divide the energy by distance below, distances = np.arange(num_dr) * dr # Prevent dividing by zero at zero distance, which will not # affect the calculation distances = np.where(distances == 0, f32(0.001), distances) pairwise_fn = interpolate.spline( data[num_dr + num_drho:num_drho + 2 * num_dr] / distances, dr) return charge_fn, embedding_fn, pairwise_fn, cutoff
def make_eam_test_splines(): cutoff = 6.28721 num_spline_points = 21 dr = np.arange(0, num_spline_points) * (cutoff / num_spline_points) dr = np.array(dr, f32) drho = np.arange(0, 2, 2. / num_spline_points) drho = np.array(drho, f32) density_data = np.array([ 2.78589606e-01, 2.02694937e-01, 1.45334053e-01, 1.06069912e-01, 8.42517168e-02, 7.65140344e-02, 7.76263116e-02, 8.23214224e-02, 8.53322309e-02, 8.13915861e-02, 6.59095390e-02, 4.28915711e-02, 2.27910928e-02, 1.13713167e-02, 6.05020311e-03, 3.65836583e-03, 2.60587564e-03, 2.06750708e-03, 1.48749693e-03, 7.40019174e-04, 6.21225205e-05 ], np.float64) embedding_data = np.array([ 1.04222211e-10, -1.04142633e+00, -1.60359806e+00, -1.89287637e+00, -2.09490167e+00, -2.26456628e+00, -2.40590322e+00, -2.52245359e+00, -2.61385603e+00, -2.67744693e+00, -2.71053295e+00, -2.71110418e+00, -2.69287013e+00, -2.68464527e+00, -2.69204083e+00, -2.68976209e+00, -2.66001244e+00, -2.60122024e+00, -2.51338548e+00, -2.39650817e+00, -2.25058831e+00 ], np.float64) pairwise_data = np.array([ 6.27032242e+01, 3.49638589e+01, 1.79007014e+01, 8.69001383e+00, 4.51545250e+00, 2.83260884e+00, 1.93216616e+00, 1.06795515e+00, 3.37740836e-01, 1.61087890e-02, -6.20816372e-02, -6.51314297e-02, -5.35210341e-02, -5.20950200e-02, -5.51709524e-02, -4.89093894e-02, -3.28051688e-02, -1.13738785e-02, 2.33833655e-03, 4.19132033e-03, 1.68600692e-04 ], np.float64) charge_fn = spline(density_data, dr[1] - dr[0]) embedding_fn = spline(embedding_data, drho[1] - drho[0]) pairwise_fn = spline(pairwise_data, dr[1] - dr[0]) return charge_fn, embedding_fn, pairwise_fn
-2.61385603e+00, -2.67744693e+00, -2.71053295e+00, -2.71110418e+00, -2.69287013e+00, -2.68464527e+00, -2.69204083e+00, -2.68976209e+00, -2.66001244e+00, -2.60122024e+00, -2.51338548e+00, -2.39650817e+00, -2.25058831e+00 ], np.float32) PAIRWISE_DATA = np.array([ 6.27032242e+01, 3.49638589e+01, 1.79007014e+01, 8.69001383e+00, 4.51545250e+00, 2.83260884e+00, 1.93216616e+00, 1.06795515e+00, 3.37740836e-01, 1.61087890e-02, -6.20816372e-02, -6.51314297e-02, -5.35210341e-02, -5.20950200e-02, -5.51709524e-02, -4.89093894e-02, -3.28051688e-02, -1.13738785e-02, 2.33833655e-03, 4.19132033e-03, 1.68600692e-04 ], np.float32) charge_fn = spline(DENSITY_DATA, dr[1] - dr[0]) embedding_fn = spline(EMBEDDING_DATA, drho[1] - drho[0]) pairwise_fn = spline(PAIRWISE_DATA, dr[1] - dr[0]) class EnergyTest(jtu.JaxTestCase): # pylint: disable=g-complex-comprehension @parameterized.named_parameters( jtu.cases_from_list({ 'testcase_name': '_dim={}_alpha={}_dtype={}'.format(dim, alpha, dtype.__name__), 'spatial_dimension': dim, 'alpha': alpha,