307 rgsaddle_version_t stamp{};
308 checkStatus(rgsaddle_abi_stamp(&stamp), "rgsaddle_abi_stamp");
309 if (stamp.major != RGSADDLE_ABI_MAJOR) {
310 throw std::runtime_error("incompatible rgsaddle ABI");
311 }
313 const auto nImages =
static_cast<int64_t
>(neb.
numImages + 2);
314 const auto nAtoms =
static_cast<int64_t
>(neb.
atoms);
315 if (nImages < 3 || nAtoms < 1) {
316 throw std::runtime_error("rgsaddle band needs at least 3 images");
317 }
318 if (springKind(nebOpt) == RGSADDLE_SPRING_WEIGHTED) {
319 m_springKs.assign(
static_cast<size_t>(nImages - 1), nebOpt.spring.constant);
320 }
321 rgsaddle_band_config_t config{};
322 config.version = RGSADDLE_VERSION_INIT;
323
324
325
326 config.flags = 0;
327 if (!neb.
path.empty() &&
328 neb.
path[0]->numberOfFreeAtoms() < neb.
path[0]->numberOfAtoms()) {
329 config.flags |= RGSADDLE_BAND_KEEP_TRANSLATION;
330 }
331 config.tangent = tangentKind(nebOpt);
332 config.spring = springKind(nebOpt);
333 config.projection = projectionKind(nebOpt);
334 config.method = methodKind(params);
335 config.spring_k = nebOpt.spring.om.enabled
336 ? nebOpt.spring.constant * nebOpt.spring.om.k_scale
337 : nebOpt.spring.constant;
339 if (nebOpt.climbing_image.enabled) {
340#if RGSADDLE_ABI_MINOR >= 17
341
342 config.flags |= RGSADDLE_BAND_CI_AFTER;
343 config.ci_trigger_factor = nebOpt.climbing_image.trigger_factor;
344#else
345 config.ci_trigger_factor = nebOpt.climbing_image.trigger_factor > 0.0
346 ? nebOpt.climbing_image.trigger_factor
347 : 1.0e-300;
348#endif
349 config.ci_trigger_force = nebOpt.climbing_image.trigger_force;
350 } else {
351 config.ci_trigger_factor = 0.0;
352 config.ci_trigger_force = 0.0;
353 }
357 m_cell.assign(cell.data(), cell.data() + 9);
358 config.cell =
m_cell.data();
359 }
360 config.force_tol = nebOpt.force_tolerance;
363
364 std::vector<double> positions(static_cast<size_t>(nImages * 3 * nAtoms), 0.0);
365 for (int64_t i = 0; i < nImages; ++i) {
367 std::copy(pos.data(), pos.data() + pos.size(),
368 positions.begin() + static_cast<std::ptrdiff_t>(i * pos.size()));
369 }
371#if RGSADDLE_ABI_MINOR >= 17
372
373
374 std::vector<double> cells(static_cast<size_t>(nImages * 9), 0.0);
375 for (int64_t i = 0; i < nImages; ++i) {
376 cellToRowMajor(neb.
path[i]->getCell(), cells.data() + 9 * i);
377 }
378 const auto &solid = nebOpt.solid_state;
380 rgsaddle_band_create_solid(&config, nImages, nAtoms, positions.data(),
381 cells.data(), solid.pressure, solid.weight);
383 throw std::runtime_error("rgsaddle_band_create_solid failed");
384 }
385 return;
386#else
387 throw std::runtime_error(
388 "solid_state NEB on the rgsaddle band needs rgsaddle ABI minor 17 "
389 "or newer (built against minor " +
390 std::to_string(RGSADDLE_ABI_MINOR) +
391 "); the older band keeps every cell fixed. Use a newer rgsaddle or "
392 "an eOn optimizer for opt_method");
393#endif
394 }
395 m_band = rgsaddle_band_create(&config, nImages, nAtoms, positions.data());
397 throw std::runtime_error("rgsaddle_band_create failed");
398 }
399}
Eigen::Matrix< double, 3, 3, eOnStorageOrder > Matrix3d
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
std::vector< std::shared_ptr< Matter > > path
bool solidState() const noexcept
const neb_options_t & neb_options() const
const main_options_t & main_options() const
const optimizer_options_t & optimizer_options() const
NudgedElasticBand * m_neb
std::vector< double > m_cell
std::vector< double > m_springKs
struct eonc::optimizer_options_t::lbfgs_t lbfgs