eOn 3.2.0
Long-timescale dynamics: aKMC, NEB, parallel replica
☾
Toggle main menu visibility
Loading...
Searching...
No Matches
LammpsLoader.cpp
Go to the documentation of this file.
1
/*
2
** This file is part of eOn.
3
**
4
** SPDX-License-Identifier: BSD-3-Clause
5
**
6
** Copyright (c) 2010--present, eOn Development Team
7
** All rights reserved.
8
**
9
** Repo:
10
** https://github.com/TheochemUI/eOn
11
*/
12
#include "
eon/potentials/LAMMPS/LammpsLoader.h
"
13
14
#include <cstdlib>
15
#include <filesystem>
16
#include <iostream>
17
#include <string>
18
#include <system_error>
19
20
namespace
eonc
{
21
22
namespace
{
23
24
const
char
*
const
*lammps_lib_names() noexcept {
25
#ifdef _WIN32
26
static
const
char
*names[] = {
"lammps.dll"
,
"liblammps.dll"
,
nullptr
};
27
#elif defined(__APPLE__)
28
static
const
char
*names[] = {
"liblammps.dylib"
,
"liblammps.0.dylib"
,
29
nullptr
};
30
#else
31
static
const
char
*names[] = {
"liblammps.so"
,
"liblammps.so.0"
,
nullptr
};
32
#endif
33
return
names;
34
}
35
36
bool
path_exists(
const
std::filesystem::path &p) {
37
std::error_code ec;
38
return
std::filesystem::exists(p, ec);
39
}
40
41
bool
lib_file_visible(
const
char
*
const
*names) {
42
for
(
const
char
*
const
*n = names; *n; ++n) {
43
if
(path_exists(*n))
44
return
true
;
45
}
46
#ifdef _WIN32
47
const
char
*path = std::getenv(
"PATH"
);
48
const
char
sep =
';'
;
49
#else
50
const
char
*path = std::getenv(
"LD_LIBRARY_PATH"
);
51
#ifdef __APPLE__
52
if
(!path || !*path)
53
path = std::getenv(
"DYLD_LIBRARY_PATH"
);
54
#endif
55
const
char
sep =
':'
;
56
#endif
57
if
(!path || !*path)
58
return
false
;
59
const
std::string paths(path);
60
std::string::size_type start = 0;
61
while
(start < paths.size()) {
62
auto
pos = paths.find(sep, start);
63
if
(pos == std::string::npos)
64
pos = paths.size();
65
if
(pos > start) {
66
const
std::filesystem::path dir(paths.substr(start, pos - start));
67
for
(
const
char
*
const
*n = names; *n; ++n) {
68
if
(path_exists(dir / *n))
69
return
true
;
70
}
71
}
72
start = pos + 1;
73
}
74
return
false
;
75
}
76
77
}
// namespace
78
79
LammpsLoader
&
LammpsLoader::instance
() {
80
static
LammpsLoader
loader;
81
return
loader;
82
}
83
84
void
LammpsLoader::ensure_loaded
() {
85
if
(
m_tried
)
86
return
;
87
m_tried
=
true
;
88
m_last_error
.clear();
89
90
// Always dlopen the soname. lib_file_visible only walks cwd and
91
// LD_LIBRARY_PATH; the dynamic linker also searches ld.so.cache and
92
// the default lib dirs. Gating on visibility skipped a distro so.
93
m_handle
=
dynlib::openFirst
(lammps_lib_names());
94
if
(!
m_handle
) {
95
const
std::string dle =
dynlib::error
();
96
if
(!lib_file_visible(lammps_lib_names())) {
97
m_last_error
=
"liblammps.so not visible on LD_LIBRARY_PATH / cwd "
98
"and dlopen of the soname failed "
99
"(liblammps_pot.so is the eOn plugin, not LAMMPS)"
;
100
}
else
{
101
m_last_error
=
"liblammps.so is visible but dlopen failed"
;
102
}
103
if
(!dle.empty()) {
104
m_last_error
+=
": "
+ dle;
105
}
106
return
;
107
}
108
109
open_no_mpi
=
dynlib::loadSym<open_no_mpi_fn>
(
m_handle
,
"lammps_open_no_mpi"
);
110
close
=
dynlib::loadSym<close_fn>
(
m_handle
,
"lammps_close"
);
111
command
=
dynlib::loadSym<command_fn>
(
m_handle
,
"lammps_command"
);
112
file
=
dynlib::loadSym<file_fn>
(
m_handle
,
"lammps_file"
);
113
scatter_atoms
=
114
dynlib::loadSym<scatter_atoms_fn>
(
m_handle
,
"lammps_scatter_atoms"
);
115
extract_variable
=
116
dynlib::loadSym<extract_var_fn>
(
m_handle
,
"lammps_extract_variable"
);
117
118
#ifdef EONMPI
119
open_mpi =
dynlib::loadSym<open_mpi_fn>
(
m_handle
,
"lammps_open"
);
120
#endif
121
122
if
(!
open_no_mpi
|| !
close
|| !
command
|| !
file
|| !
scatter_atoms
||
123
!
extract_variable
) {
124
std::cerr <<
"[LAMMPS] Library loaded but missing required symbols\n"
;
125
m_last_error
=
"opened a liblammps* but lammps_open_no_mpi is missing "
126
"(plugin or ABI mismatch, not the LAMMPS C library)"
;
127
dynlib::close
(
m_handle
);
128
m_handle
= {};
129
return
;
130
}
131
132
m_loaded
=
true
;
133
}
134
135
LammpsLoader::~LammpsLoader
() {
dynlib::close
(
m_handle
); }
136
137
bool
LammpsLoader::available
()
const
{
138
return
lib_file_visible(lammps_lib_names());
139
}
140
141
void
LammpsLoader::require_loaded
() {
142
ensure_loaded
();
143
if
(!
m_loaded
) {
144
std::string msg =
145
"LAMMPS potential requested but liblammps is not usable.\n"
;
146
if
(!
m_last_error
.empty()) {
147
msg +=
m_last_error
;
148
msg +=
"\n"
;
149
}
150
msg +=
"Need a real liblammps.so with lammps_open_no_mpi, built for "
151
"this glibc. conda-forge latest may need a newer libc than "
152
"the host. liblammps_pot.so is the eOn plugin, not LAMMPS."
;
153
throw
std::runtime_error(msg);
154
}
155
}
156
157
}
// namespace eonc
LammpsLoader.h
eonc::ILammpsLoader::close
close_fn close
Definition
LammpsLoader.h:48
eonc::ILammpsLoader::file
file_fn file
Definition
LammpsLoader.h:50
eonc::ILammpsLoader::open_no_mpi
open_no_mpi_fn open_no_mpi
Definition
LammpsLoader.h:47
eonc::ILammpsLoader::extract_variable
extract_var_fn extract_variable
Definition
LammpsLoader.h:52
eonc::ILammpsLoader::scatter_atoms
scatter_atoms_fn scatter_atoms
Definition
LammpsLoader.h:51
eonc::ILammpsLoader::command
command_fn command
Definition
LammpsLoader.h:49
eonc::LammpsLoader::LammpsLoader
LammpsLoader(const LammpsLoader &)=delete
eonc::LammpsLoader::~LammpsLoader
~LammpsLoader() override
Definition
LammpsLoader.cpp:135
eonc::LammpsLoader::require_loaded
void require_loaded() override
Load on first use, then throw if liblammps is not available.
Definition
LammpsLoader.cpp:141
eonc::LammpsLoader::m_loaded
bool m_loaded
Definition
LammpsLoader.h:102
eonc::LammpsLoader::m_last_error
std::string m_last_error
Definition
LammpsLoader.h:105
eonc::LammpsLoader::ensure_loaded
void ensure_loaded()
Definition
LammpsLoader.cpp:84
eonc::LammpsLoader::instance
static LammpsLoader & instance()
Thread-safe singleton accessor (Meyer's pattern). Does not dlopen.
Definition
LammpsLoader.cpp:79
eonc::LammpsLoader::m_handle
dynlib::Handle m_handle
Definition
LammpsLoader.h:104
eonc::LammpsLoader::m_tried
bool m_tried
Definition
LammpsLoader.h:103
eonc::LammpsLoader::available
bool available() const override
Filesystem probe: a candidate liblammps file is visible without dlopen, so LAMMPS static initializers...
Definition
LammpsLoader.cpp:137
eonc::dynlib::error
std::string error()
Definition
DynLib.h:82
eonc::dynlib::close
void close(Handle h) noexcept
Definition
DynLib.h:77
eonc::dynlib::loadSym
Fn loadSym(Handle h, const char *name) noexcept
Load a symbol and cast to a function pointer type.
Definition
DynLib.h:99
eonc::dynlib::openFirst
Handle openFirst(const char *const names[]) noexcept
Try a list of library names in order, return first successful handle.
Definition
DynLib.h:89
eonc
RAII resource manager for the ARTn C library with global synchronization.
Definition
ARTnSaddleSearch.cpp:23
client
potentials
LAMMPS
LammpsLoader.cpp
Generated by
1.17.0
Generated by
Doxygen 1.17.0
Analytics by
Antics
provided by
TurtleTech ehf