The following is a list of pull requests relevant to LAMMPS in the Colvars repository since 2024-08-06: - 752 New tool poisson_integrator_conv https://github.com/Colvars/colvars/pull/752 (@jhenin) - 733 Custom grids for all biases https://github.com/Colvars/colvars/pull/733 (@giacomofiorin, @jhenin) - 776 Avoid error in acos and asin with fast-math https://github.com/Colvars/colvars/pull/776 (@jhenin) - 773 fix: fix the clang build test failure of OPES https://github.com/Colvars/colvars/pull/773 (@HanatoK) - 768 fix: clamp the input values of asin and acos in case of fast math on aarch64 https://github.com/Colvars/colvars/pull/768 (@HanatoK) - 761 Add debug code for the Jacobi failure https://github.com/Colvars/colvars/pull/761 (@HanatoK) - 759 min_image fix; Saves long runs from crashes; https://github.com/Colvars/colvars/pull/759 (@PolyachenkoYA) - 757 Fix MSVC OpenMP issue https://github.com/Colvars/colvars/pull/757 (@HanatoK) - 755 Fix indentation of 'Init CVC' message in standard output https://github.com/Colvars/colvars/pull/755 (@jhenin) - 750 Optimize and simplify the calculation of dihedral gradients https://github.com/Colvars/colvars/pull/750 (@HanatoK) - 749 Add references to new Colvars paper https://github.com/Colvars/colvars/pull/749 (@jhenin, @giacomofiorin) - 740 Report the specific C++ standard at init time, stop warning about C++97/03 https://github.com/Colvars/colvars/pull/740 (@giacomofiorin) - 731 Improve detection of hard/mathematical boundaries https://github.com/Colvars/colvars/pull/731 (@giacomofiorin) - 729 Optimize the fit gradients https://github.com/Colvars/colvars/pull/729 (@HanatoK, @jhenin) - 728 Fix undefined behavior when getting the current working directory from std::filesystem https://github.com/Colvars/colvars/pull/728 (@giacomofiorin) - 727 Add patchversion scripting command https://github.com/Colvars/colvars/pull/727 (@giacomofiorin) - 724 Fix gradients and metric functions of distanceDir https://github.com/Colvars/colvars/pull/724 (@giacomofiorin) - 715 Add missing rotation in orientation component https://github.com/Colvars/colvars/pull/715 (@giacomofiorin) - 713 fix: try to solve #87 for non-scala components https://github.com/Colvars/colvars/pull/713 (@HanatoK) - 709 Implementation of OPES in Colvars https://github.com/Colvars/colvars/pull/709 (@HanatoK, @giacomofiorin, @jhenin) - 706 BUGFIX for Segmentation fault in colvarbias_meta::calc_energy() with useGrids off https://github.com/Colvars/colvars/pull/706 (@alphataubio) - 570 enable use of CVs defined by PyTorch neural network models https://github.com/Colvars/colvars/pull/570 (@zwpku, @giacomofiorin, @HanatoK, @jhenin) Authors: @alphataubio, @EzryStIago, @giacomofiorin, @HanatoK, @jhenin, @PolyachenkoYA, @zwpku
293 lines
9.5 KiB
C++
293 lines
9.5 KiB
C++
// -*- c++ -*-
|
|
|
|
// This file is part of the Collective Variables module (Colvars).
|
|
// The original version of Colvars and its updates are located at:
|
|
// https://github.com/Colvars/colvars
|
|
// Please update all Colvars source files before making any changes.
|
|
// If you wish to distribute your changes, please submit them to the
|
|
// Colvars repository at GitHub.
|
|
|
|
#ifndef MEMORY_STREAM_H
|
|
#define MEMORY_STREAM_H
|
|
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <typeinfo>
|
|
#include <vector>
|
|
#include <iomanip>
|
|
|
|
|
|
// Work around missing std::is_trivially_copyable in old GCC and Clang versions
|
|
// TODO remove this after CentOS 7 has been beyond EOL for a while
|
|
#if (defined(__GNUC__) && (__GNUC__ < 5) && !defined(__clang__)) || (defined(__clang__) && (__clang_major__ < 7))
|
|
// Clang needs an exception, because it defines __GNUC__ as well
|
|
#define IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
|
|
#else
|
|
#define IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
|
|
#endif
|
|
|
|
|
|
class cvm::memory_stream {
|
|
|
|
public:
|
|
|
|
/// Set up an empty stream with an internal buffer, suitable for writing to
|
|
/// \param max_length Maximum allowed capacity (default is 64 GiB)
|
|
memory_stream(size_t max_length = (static_cast<size_t>(1L) << 36)) : max_length_(max_length) {}
|
|
|
|
/// Set up a stream based on an external input buffer
|
|
memory_stream(size_t n, unsigned char const *buf)
|
|
: external_input_buffer_(buf), internal_buffer_(), data_length_(n), max_length_(data_length_)
|
|
{
|
|
}
|
|
|
|
/// Set up a stream based on an external output buffer
|
|
memory_stream(std::vector<unsigned char> &buf) : memory_stream()
|
|
{
|
|
external_output_buffer_ = &buf;
|
|
}
|
|
|
|
/// Length of the buffer
|
|
inline size_t length() const { return data_length_; }
|
|
|
|
/// Output buffer
|
|
inline unsigned char *output_buffer()
|
|
{
|
|
return (external_output_buffer_ ? external_output_buffer_->data() : internal_buffer_.data());
|
|
}
|
|
|
|
/// Next location to write to
|
|
inline unsigned char *output_location() { return output_buffer() + data_length_; }
|
|
|
|
/// Input buffer
|
|
inline unsigned char const *input_buffer() const
|
|
{
|
|
return (external_input_buffer_ ? external_input_buffer_ : internal_buffer_.data());
|
|
}
|
|
|
|
/// Next location to read from
|
|
inline unsigned char const *input_location() const { return input_buffer() + read_pos_; }
|
|
|
|
/// Cast operator to be used to test for errors
|
|
inline explicit operator bool() const { return state_ == std::ios::goodbit; }
|
|
|
|
/// Write a simple object to the output buffer
|
|
template <typename T> void write_object(T const &t);
|
|
|
|
/// Wrapper to write_object()
|
|
template <typename T> friend memory_stream &operator<<(memory_stream &os, T const &t);
|
|
|
|
/// Write a vector of simple objects to the output buffer
|
|
template <typename T> void write_vector(std::vector<T> const &t);
|
|
|
|
/// Wrapper to write_vector()
|
|
template <typename T>
|
|
friend memory_stream &operator<<(memory_stream &os, std::vector<T> const &t);
|
|
|
|
/// Read a simple object from the buffer
|
|
template <typename T> void read_object(T &t);
|
|
|
|
/// Wrapper to read_object()
|
|
template <typename T> friend memory_stream &operator>>(memory_stream &is, T &t);
|
|
|
|
/// Read a vector of simple objects from the buffer
|
|
template <typename T> void read_vector(std::vector<T> &t);
|
|
|
|
/// Wrapper to read_vector()
|
|
template <typename T> friend memory_stream &operator>>(memory_stream &is, std::vector<T> &t);
|
|
|
|
|
|
// Compatibility with STL stream functions
|
|
|
|
/// Report the current position in the buffer
|
|
inline size_t tellg() const { return read_pos_; }
|
|
|
|
/// Report the current position in the buffer
|
|
inline memory_stream & seekg(size_t pos) { read_pos_ = pos; return *this; }
|
|
|
|
/// Ignore formatting operators
|
|
inline void setf(decltype(std::ios::fmtflags(0)), decltype(std::ios::floatfield)) {}
|
|
|
|
/// Ignore formatting operators
|
|
inline void setf(decltype(std::ios::fmtflags(0))) {}
|
|
|
|
/// Ignore formatting operators
|
|
inline void flags(decltype(std::ios::fmtflags(0))) {}
|
|
|
|
/// Get the current formatting flags (i.e. none because this stream is unformatted)
|
|
inline decltype(std::ios::fmtflags(0)) flags() const { return std::ios::fmtflags(0); }
|
|
|
|
/// Get the error code
|
|
inline std::ios::iostate rdstate() const { return state_; }
|
|
|
|
/// Set the error code
|
|
inline void setstate(std::ios::iostate new_state) { state_ |= new_state; }
|
|
|
|
/// Clear the error code
|
|
inline void clear() { state_ = std::ios::goodbit; }
|
|
|
|
protected:
|
|
|
|
/// External output buffer
|
|
std::vector<unsigned char> *external_output_buffer_ = nullptr;
|
|
|
|
/// External input buffer
|
|
unsigned char const *external_input_buffer_ = nullptr;
|
|
|
|
/// Internal buffer (may server for both input and output)
|
|
std::vector<unsigned char> internal_buffer_;
|
|
|
|
/// Length of the data buffer (either internal or external)
|
|
size_t data_length_ = 0L;
|
|
|
|
/// Largest allowed capacity of the data buffer
|
|
size_t const max_length_;
|
|
|
|
/// Error status
|
|
std::ios::iostate state_ = std::ios::goodbit;
|
|
|
|
/// Add the requester number of bytes to the array capacity; return false if buffer is external
|
|
bool expand_output_buffer(size_t add_bytes);
|
|
|
|
/// Move the buffer position past the data just written
|
|
inline void incr_write_pos(size_t c) { data_length_ += c; }
|
|
|
|
/// Current position when reading from the buffer
|
|
size_t read_pos_ = 0L;
|
|
|
|
/// Begin an attempt to read an object; assume EOF unless there is space remaining
|
|
inline void begin_reading() { setstate(std::ios::eofbit); }
|
|
|
|
/// Mark the reading attempt succesful
|
|
inline void done_reading() { clear(); }
|
|
|
|
/// Move the buffer position past the data just read
|
|
inline void incr_read_pos(size_t c) { read_pos_ += c; }
|
|
|
|
/// Check that the buffer contains enough bytes to read as the argument says, set error
|
|
/// otherwise
|
|
inline bool has_remaining(size_t c) { return c <= (data_length_ - read_pos_); }
|
|
};
|
|
|
|
template <typename T> void cvm::memory_stream::write_object(T const &t)
|
|
{
|
|
static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use write_object() on complex type");
|
|
size_t const new_data_size = sizeof(T);
|
|
if (expand_output_buffer(new_data_size)) {
|
|
std::memcpy(output_location(), &t, sizeof(T));
|
|
incr_write_pos(new_data_size);
|
|
}
|
|
}
|
|
|
|
template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os, T const &t)
|
|
{
|
|
os.write_object<T>(t);
|
|
return os;
|
|
}
|
|
|
|
template <typename T> void cvm::memory_stream::write_vector(std::vector<T> const &t)
|
|
{
|
|
static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use write_vector() on complex type");
|
|
size_t const vector_length = t.size();
|
|
size_t const new_data_size = sizeof(size_t) + sizeof(T) * vector_length;
|
|
if (expand_output_buffer(new_data_size)) {
|
|
std::memcpy(output_location(), &vector_length, sizeof(size_t));
|
|
incr_write_pos(sizeof(T));
|
|
std::memcpy(output_location(), t.data(), t.size() * sizeof(T));
|
|
incr_write_pos(t.size() * sizeof(T));
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
cvm::memory_stream &operator<<(cvm::memory_stream &os, std::vector<T> const &t)
|
|
{
|
|
os.write_vector<T>(t);
|
|
return os;
|
|
}
|
|
|
|
template <typename T> void cvm::memory_stream::read_object(T &t)
|
|
{
|
|
static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use read_object() on complex type");
|
|
begin_reading();
|
|
if (has_remaining(sizeof(T))) {
|
|
std::memcpy(&t, input_location(), sizeof(T));
|
|
incr_read_pos(sizeof(T));
|
|
done_reading();
|
|
}
|
|
}
|
|
|
|
template <typename T> cvm::memory_stream &operator>>(cvm::memory_stream &is, T &t)
|
|
{
|
|
is.read_object<T>(t);
|
|
return is;
|
|
}
|
|
|
|
template <typename T> void cvm::memory_stream::read_vector(std::vector<T> &t)
|
|
{
|
|
static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use read_vector() on complex type");
|
|
begin_reading();
|
|
size_t vector_length = 0;
|
|
if (has_remaining(sizeof(size_t))) {
|
|
std::memcpy(&vector_length, input_location(), sizeof(size_t));
|
|
incr_read_pos(sizeof(size_t));
|
|
if (has_remaining(vector_length * sizeof(T))) {
|
|
t.resize(vector_length);
|
|
std::memcpy(t.data(), input_location(), vector_length * sizeof(T));
|
|
incr_read_pos(vector_length * sizeof(T));
|
|
done_reading();
|
|
} else {
|
|
setstate(std::ios::failbit);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename T> cvm::memory_stream &operator>>(cvm::memory_stream &is, std::vector<T> &t)
|
|
{
|
|
is.read_vector<T>(t);
|
|
return is;
|
|
}
|
|
|
|
template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os,
|
|
decltype(std::setprecision(10)) const &)
|
|
{
|
|
return os;
|
|
}
|
|
|
|
#if !defined(_MSC_VER) && !defined(__SUNPRO_CC)
|
|
// Visual Studio and MSVC use the same return type for both modifiers
|
|
template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os,
|
|
decltype(std::setw(10)) const &)
|
|
{
|
|
return os;
|
|
}
|
|
#endif
|
|
|
|
// Declare specializations
|
|
|
|
template <> void cvm::memory_stream::write_object(std::string const &t);
|
|
|
|
template <> cvm::memory_stream &operator<<(cvm::memory_stream &os, std::string const &t);
|
|
|
|
template <> void cvm::memory_stream::write_object(colvarvalue const &t);
|
|
|
|
template <> cvm::memory_stream &operator<<(cvm::memory_stream &os, colvarvalue const &x);
|
|
|
|
template <> void cvm::memory_stream::write_object(cvm::vector1d<cvm::real> const &t);
|
|
|
|
template <>
|
|
cvm::memory_stream &operator<<(cvm::memory_stream &os, cvm::vector1d<cvm::real> const &t);
|
|
|
|
template <> void cvm::memory_stream::read_object(std::string &t);
|
|
|
|
template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, std::string &t);
|
|
|
|
template <> void cvm::memory_stream::read_object(colvarvalue &t);
|
|
|
|
template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, colvarvalue &t);
|
|
|
|
template <> void cvm::memory_stream::read_object(cvm::vector1d<cvm::real> &t);
|
|
|
|
template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, cvm::vector1d<cvm::real> &t);
|
|
|
|
#endif
|