44 return [
pot = std::move(
pot)](
long nAtoms,
const double *positions,
45 const int *atomicNrs,
double *forces,
46 double *energy,
const double *box) {
47 double variance = 0.0;
48 pot->force(nAtoms, positions, atomicNrs, forces, energy, &variance, box);
62 std::string(magic_enum::enum_name(pot_type)));
67 std::string(magic_enum::enum_name(pot_type)));
71 auto callback = makeForceCallback(std::move(eon_pot));
83 if (endpoints.empty()) {
89 if (endpoints.size() == 1) {
90 auto params = base_params;
92 endpoints[0].potential;
93 serveMode(params, endpoints[0].host, endpoints[0].port);
98 EONC_LOG_INFO(
"Starting {} concurrent RPC servers", endpoints.size());
100 std::vector<std::thread> threads;
101 threads.reserve(endpoints.size());
103 for (
const auto &ep : endpoints) {
104 threads.emplace_back([&base_params, ep]() {
105 auto params = base_params;
107 auto pot_name = std::string(magic_enum::enum_name(ep.potential));
109 EONC_LOG_INFO(
"[{}:{}] Creating potential: {}", ep.host, ep.port,
119 auto callback = makeForceCallback(std::move(eon_pot));
125 for (
auto &t : threads) {
137 uint16_t base_port,
size_t replicas) {
147 EONC_LOG_INFO(
"Starting {} replicated servers on ports {}-{}", replicas,
148 base_port, base_port + replicas - 1);
150 std::vector<std::thread> threads;
151 threads.reserve(replicas);
153 for (
size_t i = 0; i < replicas; ++i) {
154 uint16_t port =
static_cast<uint16_t
>(base_port + i);
155 threads.emplace_back(
156 [¶ms, &host, port]() {
serveMode(params, host, port); });
159 for (
auto &t : threads) {
171 uint16_t port,
size_t pool_size) {
172 if (pool_size == 0) {
178 EONC_LOG_INFO(
"Creating pool of {} {} instances for gateway on {}:{}",
179 pool_size, std::string(magic_enum::enum_name(pot_type)), host,
182 std::vector<ForceCallback> pool;
183 pool.reserve(pool_size);
185 for (
size_t i = 0; i < pool_size; ++i) {
188 EONC_LOG_ERROR(
"Failed to create potential instance {}/{}", i + 1,
192 pool.push_back(makeForceCallback(std::move(eon_pot)));
207 if (!opts.endpoints.empty()) {
209 if (endpoints.empty()) {
218 if (opts.gateway_port > 0) {
219 size_t pool = (opts.replicas > 0) ? opts.replicas : 1;
220 serveGateway(params, opts.host, opts.gateway_port, pool);
233 std::vector<ServeEndpoint> endpoints;
234 std::istringstream stream(spec);
237 while (std::getline(stream, token,
',')) {
239 token.erase(0, token.find_first_not_of(
" \t"));
240 token.erase(token.find_last_not_of(
" \t") + 1);
245 size_t first_colon = token.find(
':');
246 if (first_colon == std::string::npos) {
247 EONC_LOG_ERROR(
"Invalid serve spec '{}': expected 'potential:port'",
252 std::string pot_str = token.substr(0, first_colon);
253 std::string rest = token.substr(first_colon + 1);
256 pot_str.erase(0, pot_str.find_first_not_of(
" \t"));
257 pot_str.erase(pot_str.find_last_not_of(
" \t") + 1);
258 rest.erase(0, rest.find_first_not_of(
" \t"));
259 rest.erase(rest.find_last_not_of(
" \t") + 1);
262 std::ranges::transform(pot_str, pot_str.begin(), [](
unsigned char c) {
263 return static_cast<char>(std::tolower(c));
268 magic_enum::enum_cast<PotType>(pot_str, magic_enum::case_insensitive)
276 size_t second_colon = rest.find(
':');
277 if (second_colon != std::string::npos) {
279 ep.
host = rest.substr(0, second_colon);
280 ep.
host.erase(0, ep.
host.find_first_not_of(
" \t"));
281 ep.
host.erase(ep.
host.find_last_not_of(
" \t") + 1);
282 std::string port_str = rest.substr(second_colon + 1);
283 port_str.erase(0, port_str.find_first_not_of(
" \t"));
284 port_str.erase(port_str.find_last_not_of(
" \t") + 1);
285 ep.
port =
static_cast<uint16_t
>(std::stoi(port_str));
288 ep.
host =
"localhost";
289 ep.
port =
static_cast<uint16_t
>(std::stoi(rest));
295 endpoints.push_back(ep);
#define EONC_LOG_ERROR(...)
#define EONC_LOG_INFO(...)
const potential_options_t & potential_options() const
const serve_options_t & serve_options() const
std::shared_ptr< Potential > makePotential(const Parameters ¶ms)
quill::Logger * get() noexcept
Get or create the default "combi" logger.
RAII resource manager for the ARTn C library with global synchronization.
std::vector< ServeEndpoint > parseServeSpec(const std::string &spec)
Parse a serve configuration string into endpoints.
void serveGateway(const Parameters ¶ms, const std::string &host, uint16_t port, size_t pool_size)
Start a gateway server backed by a pool of potential instances.
void serveMode(const Parameters ¶ms, const std::string &host, uint16_t port)
Start a single rgpot-compatible Cap'n Proto RPC server.
void serveFromConfig(const Parameters ¶ms)
Start serve mode from config-file parameters.
std::function< void(long nAtoms, const double *positions, const int *atomicNrs, double *forces, double *energy, const double *box)> ForceCallback
Callback type for potential energy/force evaluation.
void startPooledRpcServer(std::vector< ForceCallback > pool, const std::string &host, uint16_t port)
Start a blocking Cap'n Proto RPC server backed by a pool of force callbacks dispatched round-robin.
void serveMultiple(const std::vector< ServeEndpoint > &endpoints, const Parameters &base_params)
Serve multiple potentials concurrently on different ports.
void serveReplicated(const Parameters ¶ms, const std::string &host, uint16_t base_port, size_t replicas)
Serve N replicas of the same potential across sequential ports.
void startRpcServer(ForceCallback callback, const std::string &host, uint16_t port)
Start a blocking Cap'n Proto RPC server using a force callback.
static potential_options_t & potential_options(Parameters &p)
Configuration for a single serve endpoint.