61 auto capnpPos = fip.getPos();
62 for (
size_t i = 0; i < numAtoms * 3; ++i) {
63 positions[i] = capnpPos[i];
66 std::vector<int> atomicNrs(numAtoms);
67 auto capnpAtmnrs = fip.getAtmnrs();
68 for (
size_t i = 0; i < numAtoms; ++i) {
69 atomicNrs[i] = capnpAtmnrs[i];
73 auto capnpBox = fip.getBox();
74 for (
size_t i = 0; i < 9 && i < capnpBox.size(); ++i) {
79 std::vector<double> forces(numAtoms * 3, 0.0);
81 m_callback(
static_cast<long>(numAtoms), positions.data(), atomicNrs.data(),
82 forces.data(), &energy, box);
85 auto result = context.getResults();
86 auto pres = result.initResult();
87 pres.setEnergy(energy);
89 auto forcesList = pres.initForces(numAtoms * 3);
90 for (
size_t i = 0; i < numAtoms * 3; ++i) {
91 forcesList.set(i, forces[i]);
105 EONC_LOG_INFO(
"Starting Cap'n Proto RPC server on {}:{}", host, port);
107 capnp::EzRpcServer server(kj::heap<CallbackPotImpl>(std::move(callback)),
110 auto &waitScope = server.getWaitScope();
111 EONC_LOG_INFO(
"Server ready on port {}. Ctrl+C to stop.", port);
112 kj::NEVER_DONE.wait(waitScope);
125class PooledCallbackPotImpl final :
public Potential::Server {
127 explicit PooledCallbackPotImpl(std::vector<ForceCallback> pool)
128 : m_pool(std::move(pool)),
129 m_mutexes(m_pool.size()),
132 kj::Promise<void> calculate(CalculateContext context)
override {
133 size_t idx = m_next.fetch_add(1, std::memory_order_relaxed) % m_pool.size();
135 auto fip = context.getParams().getFip();
136 const size_t numAtoms = fip.getPos().size() / 3;
138 KJ_REQUIRE(fip.getAtmnrs().size() == numAtoms,
"AtomNumbers size mismatch");
140 std::vector<double> positions(numAtoms * 3);
141 auto capnpPos = fip.getPos();
142 for (
size_t i = 0; i < numAtoms * 3; ++i) {
143 positions[i] = capnpPos[i];
146 std::vector<int> atomicNrs(numAtoms);
147 auto capnpAtmnrs = fip.getAtmnrs();
148 for (
size_t i = 0; i < numAtoms; ++i) {
149 atomicNrs[i] = capnpAtmnrs[i];
153 auto capnpBox = fip.getBox();
154 for (
size_t i = 0; i < 9 && i < capnpBox.size(); ++i) {
155 box[i] = capnpBox[i];
158 std::vector<double> forces(numAtoms * 3, 0.0);
161 std::lock_guard<std::mutex> lock(m_mutexes[idx]);
162 m_pool[idx](
static_cast<long>(numAtoms), positions.data(), atomicNrs.data(),
163 forces.data(), &energy, box);
165 auto result = context.getResults();
166 auto pres = result.initResult();
167 pres.setEnergy(energy);
169 auto forcesList = pres.initForces(numAtoms * 3);
170 for (
size_t i = 0; i < numAtoms * 3; ++i) {
171 forcesList.set(i, forces[i]);
174 return kj::READY_NOW;
178 std::vector<ForceCallback> m_pool;
179 std::vector<std::mutex> m_mutexes;
180 std::atomic<size_t> m_next;
186 const std::string &host, uint16_t port) {
187 EONC_LOG_INFO(
"Starting pooled RPC gateway on {}:{} with {} instances", host,
190 capnp::EzRpcServer server(kj::heap<PooledCallbackPotImpl>(std::move(pool)),
193 auto &waitScope = server.getWaitScope();
194 EONC_LOG_INFO(
"Gateway ready on port {}. Ctrl+C to stop.", port);
195 kj::NEVER_DONE.wait(waitScope);