Loading...
Searching...
No Matches
LAMMPSPot.h
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// serves as an interface between LAMMPS potentials maintained by SANDIA
13
14#pragma once
15
16#include "eon/Parameters.h"
17#include "eon/Potential.h"
18
19#include <cerrno>
20#include <cstdint>
21#include <mutex>
22#include <string>
23#include <vector>
24
25#ifdef EONMPI
26#include <mpi.h>
27#endif
28
29namespace eonc {
31inline bool lammpsWorkerReaped(long got, long child, int err) {
32 if (got == child) {
33 return true;
34 }
35 return got < 0 && err != EINTR;
36}
37
41inline std::int64_t lammpsScreenCursor(std::int64_t pos, std::int64_t fileSize,
42 bool restarted) {
43 if (restarted || pos < 0 || fileSize < pos) {
44 return 0;
45 }
46 return pos;
47}
48
51inline std::vector<std::string> lammpsOpenArgs(bool logging, bool with_omp,
52 const std::string &screen) {
53 std::vector<std::string> args{"liblammps", "-echo", "screen", "-log", "none"};
54 if (logging) {
55 args.insert(args.end(), {"-screen", screen});
56 } else {
57 args.insert(args.end(), {"-screen", "none"});
58 }
59 if (with_omp) {
60 args.insert(args.end(), {"-suffix", "omp"});
61 }
62 return args;
63}
64} // namespace eonc
65
66namespace eonc {
67class ILammpsLoader;
68}
69
70class LAMMPSPot : public eonc::Potential {
71
72public:
73 [[nodiscard]] bool needsPerImageInstance() const noexcept override {
74 return true;
75 }
76
77 explicit LAMMPSPot(const eonc::Parameters &p);
80 ~LAMMPSPot();
81 void cleanMemory();
82 void force(long N, const double *R, const int *atomicNrs, double *F,
83 double *U, double *variance, const double *box) override;
84 void setFixedMask(long nAtoms, const double *isFixed) override;
85
86 [[nodiscard]] bool computesStress() const noexcept override {
87 return haveStress_;
88 }
89
90 [[nodiscard]] Matrix3d cauchyStress() const override { return stress_; }
91
92private:
94 bool isolate_worker);
96 int lammpsThr{0};
97 bool lammpsLogging_{false};
99 std::mutex maskMutex_;
100 // client_lammps-N.log. The worker child writes it. The parent, after the
101 // child has finished a force call, copies new lines into the process log.
102 // The child does not touch that logger: quill does not survive fork.
103 std::string lammpsScreenPath_;
104 std::int64_t lammpsScreenPos_{0};
105 // Consumed by drainLammpsScreen. A new LAMMPS open truncates the screen
106 // file, so the next copy starts at the beginning.
108 bool workerChild_{false};
109#ifdef EONMPI
110 MPI_Comm mpiComm;
111#endif
113 double oldBox[9]{};
114 void *LAMMPSObj{nullptr};
115 void makeNewLAMMPS(long N, const double *R, const int *atomicNrs,
116 const double *box);
117 void applySetforce(long N);
118 bool realunits{false};
119 Matrix3d stress_{Matrix3d::Zero()};
120 bool haveStress_{false};
121 std::vector<double> fixedMask_;
122 long maskN_{0};
123 // Covers fixedMask_ and, on the in-process paths, LAMMPSObj. The worker
124 // pipe uses the same mutex: a shared instance must not update the mask
125 // while another thread copies it or evaluates a force.
126 std::mutex workerMutex;
127
128#if !defined(EONMPI) && !defined(IS_WINDOWS)
129 // Process-per-image evaluation. NEB drives intermediate images on separate
130 // std::threads; if each thread opened LAMMPS in this process they would all
131 // share one MPI_COMM_WORLD and their concurrent reduction collectives would
132 // collide (heap corruption / MPI_ERR_OP). Instead each LAMMPSPot forks a
133 // dedicated worker process that owns its LAMMPS instance, so every image runs
134 // in its own process with its own MPI_COMM_WORLD and true parallelism.
135 // Not available on Windows (no fork/pipe).
136 // Respawns allowed after a worker times out, dies, or reports an error.
137 // A single transient failure must not poison the job: every later
138 // evaluation would return the impassable wall, no minimisation could ever
139 // meet its force criterion, and the search would be discarded as a minimum
140 // that failed to converge. Respawning is safe now that the teardown is
141 // bounded rather than waiting on a wedged child forever. The budget is
142 // finite so a worker that cannot be revived still ends the search instead
143 // of looping.
145 // Serialises the request/response exchange with the worker. eOn minimises
146 // the two endpoints of a saddle concurrently, and when both share this
147 // instance the two threads interleave writes and reads on the same pipe.
148 // The protocol is a bare byte stream with no framing, so an interleaved
149 // exchange is read as corrupt: the worker reports an evaluation error, the
150 // next send finds a closed pipe, and the worker dies, all within the first
151 // three force calls of the minimisation. Uncontended when instances really
152 // are per-image.
153 int workerPid{-1};
154 int reqFd{-1}; // parent writes requests here (child stdin side)
155 int resFd{-1}; // parent reads results here (child stdout side)
156 bool workerSpawned{false};
157 // Geometry of the last request. The child rebuilds LAMMPS, and truncates
158 // the screen file, when the atom count or the cell changes.
159 bool screenHaveGeom_{false};
161 double screenBox_[9]{};
162
163 // Fork the worker child on first use; child enters runWorkerLoop().
164 void ensureWorker();
165 bool noteScreenGeometry(long N, const double *box);
166 // Child main loop: read requests, evaluate, write results; never returns.
167 [[noreturn]] void runWorkerLoop();
168 void stopWorker();
169#endif
170 // In-process LAMMPS force evaluation (used directly on Windows/MPI, and
171 // inside the worker child on POSIX).
172 void forceLocal(long N, const double *R, const int *atomicNrs, double *F,
173 double *U, const double *box);
174 void lammpsCommand(const char *cmd);
175 void drainLammpsScreen();
176};
Eigen::Matrix< double, 3, 3, eOnStorageOrder > Matrix3d
Definition Eigen.h:35
double oldBox[9]
Definition LAMMPSPot.h:113
int workerPid
Definition LAMMPSPot.h:153
bool screenHaveGeom_
Definition LAMMPSPot.h:159
bool lammpsScreenRestart_
Definition LAMMPSPot.h:107
std::string lammpsScreenPath_
Definition LAMMPSPot.h:103
bool computesStress() const noexcept override
True when force() leaves a Cauchy stress that cauchyStress() can read until the next force() on this ...
Definition LAMMPSPot.h:86
void setFixedMask(long nAtoms, const double *isFixed) override
Optional frozen-atom mask (nAtoms*3, 1.0 = fixed).
Definition LAMMPSPot.cpp:87
std::mutex maskMutex_
Definition LAMMPSPot.h:99
Matrix3d cauchyStress() const override
Cauchy stress in eV/Angstrom^3.
Definition LAMMPSPot.h:90
std::vector< double > fixedMask_
Definition LAMMPSPot.h:121
void makeNewLAMMPS(long N, const double *R, const int *atomicNrs, const double *box)
void drainLammpsScreen()
int lammpsThr
Definition LAMMPSPot.h:96
LAMMPSPot(const eonc::Parameters &p)
Production: process-default LammpsLoader and POSIX worker isolation.
Definition LAMMPSPot.cpp:44
Matrix3d stress_
Definition LAMMPSPot.h:119
bool lammpsLogging_
Definition LAMMPSPot.h:97
bool workerSpawned
Definition LAMMPSPot.h:156
void cleanMemory()
void lammpsCommand(const char *cmd)
int lammpsLogIndex_
Definition LAMMPSPot.h:98
int workerRespawnsLeft
Definition LAMMPSPot.h:144
long maskN_
Definition LAMMPSPot.h:122
bool realunits
Definition LAMMPSPot.h:118
void stopWorker()
bool haveStress_
Definition LAMMPSPot.h:120
long screenAtoms_
Definition LAMMPSPot.h:160
void * LAMMPSObj
Definition LAMMPSPot.h:114
bool needsPerImageInstance() const noexcept override
Whether NEB should create separate Potential instances per image for true parallel force evaluation.
Definition LAMMPSPot.h:73
std::int64_t lammpsScreenPos_
Definition LAMMPSPot.h:104
void ensureWorker()
void runWorkerLoop()
long numberOfAtoms
Definition LAMMPSPot.h:112
double screenBox_[9]
Definition LAMMPSPot.h:161
void force(long N, const double *R, const int *atomicNrs, double *F, double *U, double *variance, const double *box) override
bool noteScreenGeometry(long N, const double *box)
void forceLocal(long N, const double *R, const int *atomicNrs, double *F, double *U, const double *box)
bool workerChild_
Definition LAMMPSPot.h:108
std::mutex workerMutex
Definition LAMMPSPot.h:126
void applySetforce(long N)
eonc::ILammpsLoader & loader_
Definition LAMMPSPot.h:95
RAII resource manager for the ARTn C library with global synchronization.
std::int64_t lammpsScreenCursor(std::int64_t pos, std::int64_t fileSize, bool restarted)
Byte offset at which to keep copying a LAMMPS screen file.
Definition LAMMPSPot.h:41
bool lammpsWorkerReaped(long got, long child, int err)
True when waitpid has collected the child. EINTR is not a collection.
Definition LAMMPSPot.h:31
std::vector< std::string > lammpsOpenArgs(bool logging, bool with_omp, const std::string &screen)
LAMMPS argv.
Definition LAMMPSPot.h:51