- implementation of ZBL-core repulsion with smooth transition from ACE to ZBL + Kokkos implementation

- automatic BBasis(.yaml) to CTildeBasis(.yace) conversion for pair_pace
This commit is contained in:
Yury Lysogorskiy
2023-11-22 10:19:18 +01:00
parent 33dcfb5390
commit 77549414ae
7 changed files with 228 additions and 38 deletions

View File

@ -1,33 +1,40 @@
set(PACELIB_URL "https://github.com/ICAMS/lammps-user-pace/archive/refs/tags/v.2023.10.04.tar.gz" CACHE STRING "URL for PACE evaluator library sources")
set(PACELIB_URL "https://github.com/ICAMS/lammps-user-pace/archive/refs/tags/v.2023.11.22.tar.gz" CACHE STRING "URL for PACE evaluator library sources")
set(PACELIB_MD5 "70ff79f4e59af175e55d24f3243ad1ff" CACHE STRING "MD5 checksum of PACE evaluator library tarball")
set(PACELIB_MD5 "c8e811f96d761ef8863f5b88a3fd36f4" CACHE STRING "MD5 checksum of PACE evaluator library tarball")
mark_as_advanced(PACELIB_URL)
mark_as_advanced(PACELIB_MD5)
GetFallbackURL(PACELIB_URL PACELIB_FALLBACK)
# download library sources to build folder
if(EXISTS ${CMAKE_BINARY_DIR}/libpace.tar.gz)
file(MD5 ${CMAKE_BINARY_DIR}/libpace.tar.gz DL_MD5)
endif()
if(NOT "${DL_MD5}" STREQUAL "${PACELIB_MD5}")
message(STATUS "Downloading ${PACELIB_URL}")
file(DOWNLOAD ${PACELIB_URL} ${CMAKE_BINARY_DIR}/libpace.tar.gz STATUS DL_STATUS SHOW_PROGRESS)
file(MD5 ${CMAKE_BINARY_DIR}/libpace.tar.gz DL_MD5)
if((NOT DL_STATUS EQUAL 0) OR (NOT "${DL_MD5}" STREQUAL "${PACELIB_MD5}"))
message(WARNING "Download from primary URL ${PACELIB_URL} failed\nTrying fallback URL ${PACELIB_FALLBACK}")
file(DOWNLOAD ${PACELIB_FALLBACK} ${CMAKE_BINARY_DIR}/libpace.tar.gz EXPECTED_HASH MD5=${PACELIB_MD5} SHOW_PROGRESS)
endif()
# LOCAL_ML-PACE points to top-level dir with local lammps-user-pace repo,
# to make it easier to check local build without going through the public github releases
if(LOCAL_ML-PACE)
set(lib-pace "${LOCAL_ML-PACE}")
else()
message(STATUS "Using already downloaded archive ${CMAKE_BINARY_DIR}/libpace.tar.gz")
endif()
# download library sources to build folder
if(EXISTS ${CMAKE_BINARY_DIR}/libpace.tar.gz)
file(MD5 ${CMAKE_BINARY_DIR}/libpace.tar.gz DL_MD5)
endif()
if(NOT "${DL_MD5}" STREQUAL "${PACELIB_MD5}")
message(STATUS "Downloading ${PACELIB_URL}")
#file(DOWNLOAD ${PACELIB_URL} ${CMAKE_BINARY_DIR}/libpace.tar.gz STATUS DL_STATUS SHOW_PROGRESS)
#file(MD5 ${CMAKE_BINARY_DIR}/libpace.tar.gz DL_MD5)
if((NOT DL_STATUS EQUAL 0) OR (NOT "${DL_MD5}" STREQUAL "${PACELIB_MD5}"))
message(WARNING "Download from primary URL ${PACELIB_URL} failed\nTrying fallback URL ${PACELIB_FALLBACK}")
file(DOWNLOAD ${PACELIB_FALLBACK} ${CMAKE_BINARY_DIR}/libpace.tar.gz EXPECTED_HASH MD5=${PACELIB_MD5} SHOW_PROGRESS)
endif()
else()
message(STATUS "Using already downloaded archive ${CMAKE_BINARY_DIR}/libpace.tar.gz")
endif()
# uncompress downloaded sources
execute_process(
COMMAND ${CMAKE_COMMAND} -E remove_directory lammps-user-pace*
COMMAND ${CMAKE_COMMAND} -E tar xzf libpace.tar.gz
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
get_newest_file(${CMAKE_BINARY_DIR}/lammps-user-pace-* lib-pace)
# uncompress downloaded sources
execute_process(
COMMAND ${CMAKE_COMMAND} -E remove_directory lammps-user-pace*
COMMAND ${CMAKE_COMMAND} -E tar xzf libpace.tar.gz
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
get_newest_file(${CMAKE_BINARY_DIR}/lammps-user-pace-* lib-pace)
endif()
add_subdirectory(${lib-pace} build-pace)
set_target_properties(pace PROPERTIES CXX_EXTENSIONS ON OUTPUT_NAME lammps_pace${LAMMPS_MACHINE})

View File

@ -18,11 +18,11 @@ from install_helpers import fullpath, geturl, checkmd5sum, getfallback
# settings
thisdir = fullpath('.')
version ='v.2023.10.04'
version ='v.2023.11.22'
# known checksums for different PACE versions. used to validate the download.
checksums = { \
'v.2023.10.04': '70ff79f4e59af175e55d24f3243ad1ff'
'v.2023.11.22': 'c8e811f96d761ef8863f5b88a3fd36f4'
}
parser = ArgumentParser(prog='Install.py', description="LAMMPS library build wrapper script")

View File

@ -123,6 +123,9 @@ void PairPACEExtrapolationKokkos<DeviceType>::grow(int natom, int maxneigh)
// hard-core repulsion
MemKK::realloc_kokkos(rho_core, "pace:rho_core", natom);
MemKK::realloc_kokkos(dF_drho_core, "pace:dF_drho_core", natom);
MemKK::realloc_kokkos(dF_dfcut, "pace:dF_dfcut", natom);
MemKK::realloc_kokkos(d_d_min, "pace:r_min_pair", natom);
MemKK::realloc_kokkos(d_jj_min, "pace:j_min_pair", natom);
MemKK::realloc_kokkos(dB_flatten, "pace:dB_flatten", natom, idx_ms_combs_max, basis_set->rankmax);
@ -219,6 +222,24 @@ void PairPACEExtrapolationKokkos<DeviceType>::copy_pertype()
Kokkos::deep_copy(d_wpre, h_wpre);
Kokkos::deep_copy(d_mexp, h_mexp);
// ZBL core-rep
MemKK::realloc_kokkos(d_cut_in, "pace:d_cut_in", nelements, nelements);
MemKK::realloc_kokkos(d_dcut_in, "pace:d_dcut_in", nelements, nelements);
auto h_cut_in = Kokkos::create_mirror_view(d_cut_in);
auto h_dcut_in = Kokkos::create_mirror_view(d_dcut_in);
for (int mu_i = 0; mu_i < nelements; ++mu_i) {
for (int mu_j = 0; mu_j < nelements; ++mu_j) {
h_cut_in(mu_i,mu_j) = basis_set->map_bond_specifications.at({mu_i,mu_j}).rcut_in;
h_dcut_in(mu_i,mu_j) = basis_set->map_bond_specifications.at({mu_i,mu_j}).dcut_in;
}
}
Kokkos::deep_copy(d_cut_in, h_cut_in);
Kokkos::deep_copy(d_dcut_in, h_dcut_in);
is_zbl = basis_set->radial_functions->inner_cutoff_type == "zbl";
}
/* ---------------------------------------------------------------------- */
@ -631,6 +652,10 @@ void PairPACEExtrapolationKokkos<DeviceType>::compute(int eflag_in, int vflag_in
Kokkos::deep_copy(A_rank1, 0.0);
Kokkos::deep_copy(rhos, 0.0);
Kokkos::deep_copy(rho_core, 0.0);
Kokkos::deep_copy(d_d_min, PairPACEExtrapolation::aceimpl->basis_set->cutoffmax);
Kokkos::deep_copy(d_jj_min, -1);
Kokkos::deep_copy(projections, 0.0);
Kokkos::deep_copy(d_gamma, 0.0);
@ -799,6 +824,7 @@ void PairPACEExtrapolationKokkos<DeviceType>::operator() (TagPairPACEComputeNeig
const X_FLOAT ytmp = x(i,1);
const X_FLOAT ztmp = x(i,2);
const int jnum = d_numneigh[i];
const int mu_i = d_map(type(i));
// get a pointer to scratch memory
// This is used to cache whether or not an atom is within the cutoff
@ -858,6 +884,32 @@ void PairPACEExtrapolationKokkos<DeviceType>::operator() (TagPairPACEComputeNeig
}
offset++;
});
if(is_zbl) {
//adapted from https://www.osti.gov/servlets/purl/1429450
using minloc_value_type=Kokkos::MinLoc<F_FLOAT,int>::value_type;
minloc_value_type djjmin;
djjmin.val=1e20;
djjmin.loc=-1;
Kokkos::MinLoc<F_FLOAT,int> reducer_scalar(djjmin);
// loop over ncount (actual neighbours withing cutoff) rather than jnum (total number of neigh in cutoff+skin)
Kokkos::parallel_reduce(Kokkos::TeamThreadRange(team, ncount),
[&](const int offset, minloc_value_type &min_d_dist) {
int j = d_nearest(ii,offset);
j &= NEIGHMASK;
const int jtype = type(j);
auto r = d_rnorms(ii,offset);
const int mu_j = d_map(type(j));
const F_FLOAT d = r - (d_cut_in(mu_i, mu_j) - d_dcut_in(mu_i, mu_j));
if (d < min_d_dist.val) {
min_d_dist.val = d;
min_d_dist.loc = offset;
}
}, reducer_scalar);
d_d_min(ii) = djjmin.val;
d_jj_min(ii) = djjmin.loc;// d_jj_min should be NOT in 0..jnum range, but in 0..d_ncount(<=jnum)
}
}
/* ---------------------------------------------------------------------- */
@ -1056,19 +1108,38 @@ void PairPACEExtrapolationKokkos<DeviceType>::operator() (TagPairPACEComputeFS,
const int ndensity = d_ndensity(mu_i);
double evdwl, fcut, dfcut;
double evdwl_cut;
evdwl = fcut = dfcut = 0.0;
inner_cutoff(rho_core(ii), rho_cut, drho_cut, fcut, dfcut);
FS_values_and_derivatives(ii, evdwl, mu_i);
dF_drho_core(ii) = evdwl * dfcut + 1;
if(is_zbl) {
if (d_jj_min(ii) != -1) {
const int mu_jmin = d_mu(ii,d_jj_min(ii));
F_FLOAT dcutin = d_dcut_in(mu_i, mu_jmin);
F_FLOAT transition_coordinate = dcutin - d_d_min(ii); // == cutin - r_min
cutoff_func_poly(transition_coordinate, dcutin, dcutin, fcut, dfcut);
dfcut = -dfcut; // invert, because rho_core = cutin - r_min
} else {
// no neighbours
fcut = 1;
dfcut = 0;
}
evdwl_cut = evdwl * fcut + rho_core(ii) * (1 - fcut); // evdwl * fcut + rho_core_uncut - rho_core_uncut* fcut
dF_drho_core(ii) = 1 - fcut;
dF_dfcut(ii) = evdwl * dfcut - rho_core(ii) * dfcut;
} else {
inner_cutoff(rho_core(ii), rho_cut, drho_cut, fcut, dfcut);
dF_drho_core(ii) = evdwl * dfcut + 1;
evdwl_cut = evdwl * fcut + rho_core(ii);
}
for (int p = 0; p < ndensity; ++p)
dF_drho(ii, p) *= fcut;
// tally energy contribution
if (eflag) {
double evdwl_cut = evdwl * fcut + rho_core(ii);
// E0 shift
evdwl_cut += d_E0vals(mu_i);
e_atom(ii) = evdwl_cut;
@ -1240,6 +1311,15 @@ void PairPACEExtrapolationKokkos<DeviceType>::operator() (TagPairPACEComputeDeri
f_ij(ii, jj, 0) = scale * f_ji[0] + fpair * r_hat[0];
f_ij(ii, jj, 1) = scale * f_ji[1] + fpair * r_hat[1];
f_ij(ii, jj, 2) = scale * f_ji[2] + fpair * r_hat[2];
if(is_zbl) {
if(jj==d_jj_min(ii)) {
// DCRU = 1.0
f_ij(ii, jj, 0) += dF_dfcut(ii) * r_hat[0];
f_ij(ii, jj, 1) += dF_dfcut(ii) * r_hat[1];
f_ij(ii, jj, 2) += dF_dfcut(ii) * r_hat[2];
}
}
}
/* ---------------------------------------------------------------------- */
@ -1777,6 +1857,7 @@ double PairPACEExtrapolationKokkos<DeviceType>::memory_usage()
bytes += MemKK::memory_usage(weights_rank1);
bytes += MemKK::memory_usage(rho_core);
bytes += MemKK::memory_usage(dF_drho_core);
bytes += MemKK::memory_usage(dF_dfcut);
bytes += MemKK::memory_usage(dB_flatten);
bytes += MemKK::memory_usage(fr);
bytes += MemKK::memory_usage(dfr);
@ -1794,6 +1875,8 @@ double PairPACEExtrapolationKokkos<DeviceType>::memory_usage()
bytes += MemKK::memory_usage(d_mu);
bytes += MemKK::memory_usage(d_rhats);
bytes += MemKK::memory_usage(d_rnorms);
bytes += MemKK::memory_usage(d_d_min);
bytes += MemKK::memory_usage(d_jj_min);
bytes += MemKK::memory_usage(d_nearest);
bytes += MemKK::memory_usage(f_ij);
bytes += MemKK::memory_usage(d_rho_core_cutoff);

View File

@ -130,6 +130,7 @@ class PairPACEExtrapolationKokkos : public PairPACEExtrapolation {
tdual_fparams k_cutsq, k_scale;
typedef Kokkos::View<F_FLOAT**, DeviceType> t_fparams;
t_fparams d_cutsq, d_scale;
t_fparams d_cut_in, d_dcut_in; // inner cutoff
typename AT::t_int_1d d_map;
@ -240,6 +241,7 @@ class PairPACEExtrapolationKokkos : public PairPACEExtrapolation {
t_ace_2d cr;
t_ace_2d dcr;
t_ace_1d dF_drho_core;
t_ace_1d dF_dfcut;
// radial functions
t_ace_4d fr;
@ -282,6 +284,11 @@ class PairPACEExtrapolationKokkos : public PairPACEExtrapolation {
t_ace_3d3 d_rhats;
t_ace_2i d_nearest;
// for ZBL core-rep implementation
t_ace_1d d_d_min; // [i] -> min-d for atom ii, d=d = r - (cut_in(mu_i, mu_j) - dcut_in(mu_i, mu_j))
t_ace_1i d_jj_min; // [i] -> jj-index of nearest neigh (by r-(cut_in-dcut_in) criterion)
bool is_zbl;
// per-type
t_ace_1i d_ndensity;
t_ace_1i d_npoti;

View File

@ -121,6 +121,9 @@ void PairPACEKokkos<DeviceType>::grow(int natom, int maxneigh)
// hard-core repulsion
MemKK::realloc_kokkos(rho_core, "pace:rho_core", natom);
MemKK::realloc_kokkos(dF_drho_core, "pace:dF_drho_core", natom);
MemKK::realloc_kokkos(dF_dfcut, "pace:dF_dfcut", natom);
MemKK::realloc_kokkos(d_d_min, "pace:r_min_pair", natom);
MemKK::realloc_kokkos(d_jj_min, "pace:j_min_pair", natom);
MemKK::realloc_kokkos(dB_flatten, "pace:dB_flatten", natom, idx_rho_max, basis_set->rankmax);
}
@ -212,6 +215,23 @@ void PairPACEKokkos<DeviceType>::copy_pertype()
Kokkos::deep_copy(d_wpre, h_wpre);
Kokkos::deep_copy(d_mexp, h_mexp);
// ZBL core-rep
MemKK::realloc_kokkos(d_cut_in, "pace:d_cut_in", nelements, nelements);
MemKK::realloc_kokkos(d_dcut_in, "pace:d_dcut_in", nelements, nelements);
auto h_cut_in = Kokkos::create_mirror_view(d_cut_in);
auto h_dcut_in = Kokkos::create_mirror_view(d_dcut_in);
for (int mu_i = 0; mu_i < nelements; ++mu_i) {
for (int mu_j = 0; mu_j < nelements; ++mu_j) {
h_cut_in(mu_i,mu_j) = basis_set->map_bond_specifications.at({mu_i,mu_j}).rcut_in;
h_dcut_in(mu_i,mu_j) = basis_set->map_bond_specifications.at({mu_i,mu_j}).dcut_in;
}
}
Kokkos::deep_copy(d_cut_in, h_cut_in);
Kokkos::deep_copy(d_dcut_in, h_dcut_in);
is_zbl = basis_set->radial_functions->inner_cutoff_type == "zbl";
}
/* ---------------------------------------------------------------------- */
@ -588,6 +608,8 @@ void PairPACEKokkos<DeviceType>::compute(int eflag_in, int vflag_in)
Kokkos::deep_copy(A_rank1, 0.0);
Kokkos::deep_copy(rhos, 0.0);
Kokkos::deep_copy(rho_core, 0.0);
Kokkos::deep_copy(d_d_min, PairPACE::aceimpl->basis_set->cutoffmax);
Kokkos::deep_copy(d_jj_min, -1);
EV_FLOAT ev_tmp;
@ -665,6 +687,7 @@ void PairPACEKokkos<DeviceType>::compute(int eflag_in, int vflag_in)
Kokkos::parallel_for("ComputeDerivative",policy_derivative,*this);
}
//ComputeForce
{
if (evflag) {
@ -741,6 +764,7 @@ void PairPACEKokkos<DeviceType>::operator() (TagPairPACEComputeNeigh,const typen
const X_FLOAT ytmp = x(i,1);
const X_FLOAT ztmp = x(i,2);
const int jnum = d_numneigh[i];
const int mu_i = d_map(type(i));
// get a pointer to scratch memory
// This is used to cache whether or not an atom is within the cutoff
@ -800,6 +824,32 @@ void PairPACEKokkos<DeviceType>::operator() (TagPairPACEComputeNeigh,const typen
}
offset++;
});
if(is_zbl) {
//adapted from https://www.osti.gov/servlets/purl/1429450
using minloc_value_type=Kokkos::MinLoc<F_FLOAT,int>::value_type;
minloc_value_type djjmin;
djjmin.val=1e20;
djjmin.loc=-1;
Kokkos::MinLoc<F_FLOAT,int> reducer_scalar(djjmin);
// loop over ncount (actual neighbours withing cutoff) rather than jnum (total number of neigh in cutoff+skin)
Kokkos::parallel_reduce(Kokkos::TeamThreadRange(team, ncount),
[&](const int offset, minloc_value_type &min_d_dist) {
int j = d_nearest(ii,offset);
j &= NEIGHMASK;
const int jtype = type(j);
auto r = d_rnorms(ii,offset);
const int mu_j = d_map(type(j));
const F_FLOAT d = r - (d_cut_in(mu_i, mu_j) - d_dcut_in(mu_i, mu_j));
if (d < min_d_dist.val) {
min_d_dist.val = d;
min_d_dist.loc = offset;
}
}, reducer_scalar);
d_d_min(ii) = djjmin.val;
d_jj_min(ii) = djjmin.loc;// d_jj_min should be NOT in 0..jnum range, but in 0..d_ncount(<=jnum)
}
}
/* ---------------------------------------------------------------------- */
@ -990,22 +1040,38 @@ void PairPACEKokkos<DeviceType>::operator() (TagPairPACEComputeFS, const int& ii
const int ndensity = d_ndensity(mu_i);
double evdwl, fcut, dfcut;
double evdwl_cut;
evdwl = fcut = dfcut = 0.0;
inner_cutoff(rho_core(ii), rho_cut, drho_cut, fcut, dfcut);
FS_values_and_derivatives(ii, evdwl, mu_i);
dF_drho_core(ii) = evdwl * dfcut + 1;
if(is_zbl) {
if (d_jj_min(ii) != -1) {
const int mu_jmin = d_mu(ii,d_jj_min(ii));
F_FLOAT dcutin = d_dcut_in(mu_i, mu_jmin);
F_FLOAT transition_coordinate = dcutin - d_d_min(ii); // == cutin - r_min
cutoff_func_poly(transition_coordinate, dcutin, dcutin, fcut, dfcut);
dfcut = -dfcut; // invert, because rho_core = cutin - r_min
} else {
// no neighbours
fcut = 1;
dfcut = 0;
}
evdwl_cut = evdwl * fcut + rho_core(ii) * (1 - fcut); // evdwl * fcut + rho_core_uncut - rho_core_uncut* fcut
dF_drho_core(ii) = 1 - fcut;
dF_dfcut(ii) = evdwl * dfcut - rho_core(ii) * dfcut;
} else {
inner_cutoff(rho_core(ii), rho_cut, drho_cut, fcut, dfcut);
dF_drho_core(ii) = evdwl * dfcut + 1;
evdwl_cut = evdwl * fcut + rho_core(ii);
}
for (int p = 0; p < ndensity; ++p)
dF_drho(ii, p) *= fcut;
dF_drho(ii, p) *= fcut;
// tally energy contribution
if (eflag) {
double evdwl_cut = evdwl * fcut + rho_core(ii);
// E0 shift
evdwl_cut += d_E0vals(mu_i);
e_atom(ii) = evdwl_cut;
// E0 shift
evdwl_cut += d_E0vals(mu_i);
e_atom(ii) = evdwl_cut;
}
}
@ -1146,6 +1212,15 @@ void PairPACEKokkos<DeviceType>::operator() (TagPairPACEComputeDerivative, const
f_ij(ii, jj, 0) = scale * f_ji[0] + fpair * r_hat[0];
f_ij(ii, jj, 1) = scale * f_ji[1] + fpair * r_hat[1];
f_ij(ii, jj, 2) = scale * f_ji[2] + fpair * r_hat[2];
if(is_zbl) {
if(jj==d_jj_min(ii)) {
// DCRU = 1.0
f_ij(ii, jj, 0) += dF_dfcut(ii) * r_hat[0];
f_ij(ii, jj, 1) += dF_dfcut(ii) * r_hat[1];
f_ij(ii, jj, 2) += dF_dfcut(ii) * r_hat[2];
}
}
}
/* ---------------------------------------------------------------------- */
@ -1683,6 +1758,7 @@ double PairPACEKokkos<DeviceType>::memory_usage()
bytes += MemKK::memory_usage(weights_rank1);
bytes += MemKK::memory_usage(rho_core);
bytes += MemKK::memory_usage(dF_drho_core);
bytes += MemKK::memory_usage(dF_dfcut);
bytes += MemKK::memory_usage(dB_flatten);
bytes += MemKK::memory_usage(fr);
bytes += MemKK::memory_usage(dfr);
@ -1700,6 +1776,8 @@ double PairPACEKokkos<DeviceType>::memory_usage()
bytes += MemKK::memory_usage(d_mu);
bytes += MemKK::memory_usage(d_rhats);
bytes += MemKK::memory_usage(d_rnorms);
bytes += MemKK::memory_usage(d_d_min);
bytes += MemKK::memory_usage(d_jj_min);
bytes += MemKK::memory_usage(d_nearest);
bytes += MemKK::memory_usage(f_ij);
bytes += MemKK::memory_usage(d_rho_core_cutoff);

View File

@ -121,6 +121,7 @@ class PairPACEKokkos : public PairPACE {
tdual_fparams k_cutsq, k_scale;
typedef Kokkos::View<F_FLOAT**, DeviceType> t_fparams;
t_fparams d_cutsq, d_scale;
t_fparams d_cut_in, d_dcut_in; // inner cutoff
typename AT::t_int_1d d_map;
@ -228,6 +229,7 @@ class PairPACEKokkos : public PairPACE {
t_ace_2d cr;
t_ace_2d dcr;
t_ace_1d dF_drho_core;
t_ace_1d dF_dfcut;
// radial functions
t_ace_4d fr;
@ -265,6 +267,11 @@ class PairPACEKokkos : public PairPACE {
t_ace_3d3 d_rhats;
t_ace_2i d_nearest;
// for ZBL core-rep implementation
t_ace_1d d_d_min; // [i] -> min-d for atom ii, d=d = r - (cut_in(mu_i, mu_j) - dcut_in(mu_i, mu_j))
t_ace_1i d_jj_min; // [i] -> jj-index of nearest neigh (by r-(cut_in-dcut_in) criterion)
bool is_zbl;
// per-type
t_ace_1i d_ndensity;
t_ace_1i d_npoti;

View File

@ -45,7 +45,8 @@ Copyright 2021 Yury Lysogorskiy^1, Cas van der Oord^2, Anton Bochkarev^1,
#include "ace-evaluator/ace_evaluator.h"
#include "ace-evaluator/ace_recursive.h"
#include "ace-evaluator/ace_version.h"
#include "ace/ace_b_basis.h"
#include <unistd.h>
namespace LAMMPS_NS {
struct ACEImpl {
ACEImpl() : basis_set(nullptr), ace(nullptr) {}
@ -287,7 +288,14 @@ void PairPACE::coeff(int narg, char **arg)
//load potential file
delete aceimpl->basis_set;
if (comm->me == 0) utils::logmesg(lmp, "Loading {}\n", potential_file_name);
aceimpl->basis_set = new ACECTildeBasisSet(potential_file_name);
// if potential is in ACEBBasisSet (YAML) format, then convert to ACECTildeBasisSet automatically
if (utils::strmatch(potential_file_name,".*\\.yaml$")) {
ACEBBasisSet bBasisSet = ACEBBasisSet(potential_file_name);
ACECTildeBasisSet cTildeBasisSet = bBasisSet.to_ACECTildeBasisSet();
aceimpl->basis_set = new ACECTildeBasisSet(cTildeBasisSet);
} else {
aceimpl->basis_set = new ACECTildeBasisSet(potential_file_name);
}
if (comm->me == 0) {
utils::logmesg(lmp, "Total number of basis functions\n");