42#include "rgpot/LennardJones/LJClusterPot.hpp"
43#include "rgpot/LennardJones/LJPot.hpp"
44#include "rgpot/Morse/MorsePot.hpp"
45#include "rgpot/ZBL/ZBLPot.hpp"
47#include "rgpot/D3Pot/D3Pot.hpp"
50#include "rgpot/D4Pot/D4Pot.hpp"
53#include "rgpot/ExprPot/ExprPot.hpp"
55#include "rgpot/MOPACPot/MOPACPot.hpp"
56#include "rgpot/fortran/FortranPots.hpp"
119 const VectorXi &atmnrs,
121 double energy{std::numeric_limits<double>::infinity()};
122 long nAtoms =
static_cast<long>(pos.rows());
125 const auto n =
static_cast<size_t>(nAtoms);
126 this->
force(std::span<const double>(pos.data(), n * 3),
127 std::span<const int>(atmnrs.data(), n),
128 std::span<double>(forces.data(), n * 3), &energy, &var,
129 std::span<const double>(box.data(), 9));
132 if (!std::isfinite(energy) || !forces.allFinite()) {
133 throw std::runtime_error(
"Potential::get_ef: non-finite energy or forces");
136 return std::make_tuple(energy, forces);
142std::string lower_copy(std::string s) {
144 c =
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
150#ifdef RGPOT_HAS_DFTD3
151rgpot::D3Damping d3_damping_from_params(
const Parameters ¶ms) {
152 rgpot::D3Damping damp = rgpot::D3Damping::BJ;
153 if (lower_copy(params.dftd_options().d3_damping) ==
"zero") {
154 damp = rgpot::D3Damping::Zero;
160std::unique_ptr<rgpot::PotentialBase> make_expr_term(
const std::string &raw,
161 const Parameters ¶ms) {
162 const std::string name = lower_copy(raw);
164 return std::make_unique<rgpot::LJPot>(rgpot::LJConfig{});
166 if (name ==
"ljcluster") {
167 return std::make_unique<rgpot::LJClusterPot>(rgpot::LJClusterConfig{});
169 if (name ==
"morse" || name ==
"morse_pt") {
170 return std::make_unique<rgpot::MorsePot>(rgpot::MorseConfig{});
173 return std::make_unique<rgpot::ZBLPot>(rgpot::ZBLConfig{
174 .cut_inner = params.zbl_options().cut_inner,
175 .cut_global = params.zbl_options().cut_global,
178#ifdef RGPOT_HAS_DFTD3
179 if (name ==
"d3" || name ==
"dftd3") {
180 return std::make_unique<rgpot::D3Pot>(rgpot::D3Config{
181 .damping = d3_damping_from_params(params),
182 .functional = params.dftd_options().functional,
183 .atm = params.dftd_options().atm,
187#ifdef RGPOT_HAS_DFTD4
188 if (name ==
"d4" || name ==
"dftd4") {
189 return std::make_unique<rgpot::D4Pot>(rgpot::D4Config{
190 .functional = params.dftd_options().functional,
191 .charge = params.dftd_options().d4_charge,
192 .atm = params.dftd_options().atm,
196 if (name ==
"mopac") {
197 return std::make_unique<rgpot::MOPACPot>(rgpot::MOPACPot::Config{
198 .charge = params.mopac_options().charge,
199 .spin = params.mopac_options().spin,
200 .model = params.mopac_options().model,
201 .engine_path = params.mopac_options().engine_path,
204 throw std::runtime_error(
205 "ExprPot unknown term '" + raw +
206 "' (lj, ljcluster, morse, zbl, d3/dftd3, d4/dftd4, mopac)");
209std::vector<rgpot::ExprPot::Term> parse_expr_terms(
const Parameters ¶ms) {
210 std::vector<rgpot::ExprPot::Term> terms;
211 std::string buf = params.expr_options().terms;
214 while (!token.empty() &&
215 std::isspace(
static_cast<unsigned char>(token.front()))) {
216 token.erase(token.begin());
218 while (!token.empty() &&
219 std::isspace(
static_cast<unsigned char>(token.back()))) {
222 if (!token.empty()) {
223 terms.emplace_back(token, make_expr_term(token, params));
236 throw std::runtime_error(
237 "ExprPot needs [ExprPot] terms (comma-separated names used in "
249std::shared_ptr<Potential>
264 return (std::make_shared<EffectiveMediumTheory>(params));
268 return (std::make_shared<ExtPot>(params));
277 rgpot::LJClusterConfig{});
282 rgpot::MorseConfig{});
293 return (std::make_shared<Tip4p>(params));
297 return (std::make_shared<SpceCcl>(params));
302 return (std::make_shared<Tip4p_Pt>(params));
343 return (std::make_shared<VASP>(params));
349 return std::make_shared<LAMMPSPot>(params);
353 return (std::make_shared<MPIPot>(params));
360 return (std::make_shared<ASE>(params));
367 return (std::make_shared<AMS>(params));
371 return (std::make_shared<AMS_IO>(params));
377 return (std::make_shared<CatLearnPot>(params));
384 return (std::make_shared<XTBPot>(params));
390 return (std::make_shared<ASEOrcaPot>(params));
394#ifdef WITH_ASE_NWCHEM
396 return (std::make_shared<ASENwchemPot>(params));
402 return (std::make_shared<MetatomicPotential>(params));
406#ifdef RGPOT_HAS_DFTD3
408 rgpot::D3Damping damp = rgpot::D3Damping::BJ;
410 for (
char &c : dname) {
411 c =
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
413 if (dname ==
"zero") {
414 damp = rgpot::D3Damping::Zero;
418 rgpot::D3Config{.damping = damp,
424#ifdef RGPOT_HAS_DFTD4
445 return (std::make_shared<SocketNWChemPot>(params));
451 return (std::make_shared<RgpotPot>(params));
458 rgpot::MOPACPot::Config{
469 throw std::runtime_error(
470 "ExprPot needs [ExprPot] expression, e.g. 0.5*lj + d3");
473 parse_expr_terms(params));
474 return std::make_shared<RgpotAdapter<rgpot::ExprPot>>(
PotType::EXPR, params,
481 magic_enum::enum_name(ptype));
483 throw std::runtime_error(
"Terminating");
Eigen::Matrix< double, 3, 3, eOnStorageOrder > Matrix3d
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
#define EONC_LOG_ERROR(...)
std::shared_ptr< eonc::Potential > makeRgpotDefault(eonc::PotType ptype, const eonc::Parameters ¶ms)
Factory arm helper for kernels whose parameters are fixed tabulated data with no eOn-side configurati...
std::shared_ptr< eonc::Potential > makeRgpot(eonc::PotType ptype, const eonc::Parameters ¶ms, const Cfg &cfg)
Factory arm helper: construct the kernel from its config and wrap it.
const expr_options_t & expr_options() const
const potential_options_t & potential_options() const
const zbl_options_t & zbl_options() const
const mopac_options_t & mopac_options() const
const dftd_options_t & dftd_options() const
void add_config_paths(const std::string &colon_paths) override
Inject search paths from the eOn config file.
static PluginLoader & instance()
Thread-safe singleton accessor (Meyer's pattern).
RAII: Potential default construction records on this registry instead of PotRegistry::get().
std::atomic< size_t > forceCallCounter
virtual void force(long nAtoms, const double *positions, const int *atomicNrs, double *forces, double *energy, double *variance, const double *box)=0
std::tuple< double, AtomMatrix > get_ef(const AtomMatrix &pos, const VectorXi &atmnrs, const Matrix3d &box)
Move-only composition root for process resources (dlopen loaders and the potential registry).
PotRegistry & pots() noexcept
PluginLoader & plugins() noexcept
std::shared_ptr< Potential > makePotential(const Parameters ¶ms)
quill::Logger * get() noexcept
Get or create the default "combi" logger.
std::string potentialsPath