From 15b3e875d503ae5909097f10143bf8206a9f1594 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 29 Sep 2021 16:29:25 -0400 Subject: [PATCH 01/84] import files for platform namespace from standalone project w/o updating LAMMPS --- src/platform.cpp | 947 +++++++++++++++++++++++++++++++ src/platform.h | 350 ++++++++++++ unittest/utils/CMakeLists.txt | 16 + unittest/utils/test_platform.cpp | 395 +++++++++++++ unittest/utils/testshared.c | 20 + 5 files changed, 1728 insertions(+) create mode 100644 src/platform.cpp create mode 100644 src/platform.h create mode 100644 unittest/utils/test_platform.cpp create mode 100644 unittest/utils/testshared.c diff --git a/src/platform.cpp b/src/platform.cpp new file mode 100644 index 0000000000..d457f85c98 --- /dev/null +++ b/src/platform.cpp @@ -0,0 +1,947 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ +/** \file platform.cpp + * This file provides abstractions for a variety of platform specific + * functionality in a namespace "platform". This is a companion to + * the "utils" namespace with convenience and utility functions. */ + +#include "platform.h" +#include "utils.h" + +#if HAVE_MPI +#include +#endif + +//////////////////////////////////////////////////////////////////////// +// include system headers and tweak system settings +#if defined(_WIN32) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#if defined(_WIN32_WINNT) +#undef _WIN32_WINNT +#endif + +// target Windows version is windows 7 and later +#define _WIN32_WINNT _WIN32_WINNT_WIN7 +#define PSAPI_VERSION 2 + +#include +#include // for _get_osfhandle() +#include +#include + +#else // not Windows /////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if defined(__APPLE__) +#include +#include +#endif +//////////////////////////////////////////////////////////////////////// + +#include + +/* ------------------------------------------------------------------ */ + +/// Struct for listing on-the-fly compression/decompression commands +struct zip_info { + /// identifier for the different compression algorithms + enum styles { NONE, GZIP, BZIP2, ZSTD, XZ, LZMA, LZ4 }; + const std::string extension; ///< filename extension for the current algorithm + const std::string command; ///< command to perform compression or decompression + const std::string zipflags; ///< flags to append to compress from stdin to stdout + const std::string unzipflags; ///< flags to decompress file to stdout + const int style; ///< compression style flag +}; + +// clang-format off +static const std::vector zip_styles = { + {"", "", "", "", zip_info::NONE}, + {"gz", "gzip", " > ", " -cdf ", zip_info::GZIP}, + {"bz2", "bzip2", " > ", " -cdf ", zip_info::BZIP2}, + {"zstd", "zstd", " -q > ", " -cdf ", zip_info::ZSTD}, + {"xz", "xz", " > ", " -cdf ", zip_info::XZ}, + {"lzma", "xz", " --format=lzma > ", " --format=lzma -cdf ", zip_info::LZMA}, + {"lz4", "lz4", " > ", " -cdf ", zip_info::LZ4}, +}; +// clang-format on + +/* ------------------------------------------------------------------ */ + +static const zip_info &find_zip_type(const std::string &file) +{ + std::size_t dot = file.find_last_of('.'); + if (dot != std::string::npos) { + const std::string ext = file.substr(dot + 1); + for (const auto &i : zip_styles) { + if (i.extension == ext) return i; + } + } + return zip_styles[0]; +} + +/* ------------------------------------------------------------------ */ + +using namespace LAMMPS_NS; + +// get CPU time + +// clang-format off +// clang compilers are optimizing this function too aggressively returning always 0 +#if defined(__clang__) +[[clang::optnone]] +#endif +double platform::cputime() +// clang-format on +{ + double rv = 0.0; + +#ifdef _WIN32 + + // from MSD docs. + FILETIME ct, et, kt, ut; + union { + FILETIME ft; + uint64_t ui; + } cpu; + if (GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut)) { + cpu.ft = ut; + rv = cpu.ui * 0.0000001; + } + +#else /* ! _WIN32 */ + + struct rusage ru; + if (getrusage(RUSAGE_SELF, &ru) == 0) { + rv = (double) ru.ru_utime.tv_sec; + rv += (double) ru.ru_utime.tv_usec * 0.000001; + } + +#endif + + return rv; +} + +/* ---------------------------------------------------------------------- + get wall time +------------------------------------------------------------------------ */ +double platform::walltime() +{ + double wtime; + +#if defined(_WIN32) + + wtime = GetTickCount64() * 0.001; + +#else + + struct timeval tv; + + gettimeofday(&tv, nullptr); + wtime = 1.0 * tv.tv_sec + 1.0e-6 * tv.tv_usec; + +#endif + + return wtime; +} + +/* ---------------------------------------------------------------------- + get Operating system and version info +------------------------------------------------------------------------- */ + +std::string platform::os_info() +{ + std::string buf; + +#if defined(_WIN32) + + // Get Windows Edition name from registry + char value[1024]; + DWORD value_length = 1024; + const char *subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; + const char *entry = "ProductName"; + RegGetValue(HKEY_LOCAL_MACHINE, subkey, entry, RRF_RT_REG_SZ, nullptr, &value, + (LPDWORD) &value_length); + // enforce zero termination + value[1023] = '\0'; + buf = value; + + DWORD fullversion, majorv, minorv, buildv = 0; + fullversion = GetVersion(); + majorv = (DWORD) (LOBYTE(LOWORD(fullversion))); + minorv = (DWORD) (HIBYTE(LOWORD(fullversion))); + if (fullversion < 0x80000000) buildv = (DWORD) (HIWORD(fullversion)); + + buf += ", Windows ABI " + std::to_string(majorv) + "." + std::to_string(minorv) + " (" + + std::to_string(buildv) + ") on "; + + SYSTEM_INFO si; + GetSystemInfo(&si); + + switch (si.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_AMD64: + buf += "x86_64"; + break; + case PROCESSOR_ARCHITECTURE_ARM: + buf += "arm"; + break; + case PROCESSOR_ARCHITECTURE_IA64: + buf += "ia64"; + break; + case PROCESSOR_ARCHITECTURE_INTEL: + buf += "i386"; + break; + default: + buf += "(unknown)"; + } +#else + struct utsname ut; + uname(&ut); + + // try to get OS distribution name, if available + buf = ut.sysname; + +#if 0 // disable until this is integrated into LAMMPS and TextFileReader becomes available + if (utils::file_is_readable("/etc/os-release")) { + try { + TextFileReader reader("/etc/os-release",""); + while (1) { + auto words = reader.next_values(0,"="); + if ((words.count() > 1) && (words.next_string() == "PRETTY_NAME")) { + distro += " " + utils::trim(words.next_string()); + break; + } + } + } catch (std::exception &e) { + ; // EOF but keyword not found + } + } +#endif + + buf += std::string(" ") + ut.release + " " + ut.machine; +#endif + return buf; +} + +/* ---------------------------------------------------------------------- + identify C++ standard version +------------------------------------------------------------------------- */ + +std::string platform::cxx_standard() +{ +#if __cplusplus > 202002L + return "newer than C++20"; +#elif __cplusplus == 202002L + return "C++20"; +#elif __cplusplus == 201703L + return "C++17"; +#elif __cplusplus == 201402L + return "C++14"; +#elif __cplusplus == 201103L + return "C++11"; +#elif __cplusplus == 199711L + return "C++98"; +#else + return "unknown"; +#endif +} + +/* ---------------------------------------------------------------------- + identify compiler and its version +------------------------------------------------------------------------- */ + +std::string platform::compiler_info() +{ + std::string buf = "(Unknown)"; +#if 0 // disable for now untile merged into LAMMPS and fmt:: becomes available +#if defined(__INTEL_LLVM_COMPILER) + double version = static_cast(__INTEL_LLVM_COMPILER)*0.01; + buf = fmt::format("Intel LLVM C++ {:.1f} / {}", version, __VERSION__); +#elif defined(__ibmxl__) + buf = fmt::format("IBM XL C/C++ (Clang) {}.{}.{}", + __ibmxl_version__, __ibmxl_release__, __ibmxl_modification__); +#elif defined(__clang__) + buf = fmt::format("Clang C++ {}", __VERSION__); +#elif defined(__PGI) + buf = fmt::format("PGI C++ {}.{}",__PGIC__,__PGIC_MINOR__); +#elif defined(__INTEL_COMPILER) + double version = static_cast(__INTEL_COMPILER)*0.01; + buf = fmt::format("Intel Classic C++ {:.2f}.{} / {}", version, + __INTEL_COMPILER_UPDATE, __VERSION__); +#elif defined(__MINGW64__) + buf = fmt::format("MinGW-w64 64bit {}.{} / GNU C++ {}", __MINGW64_VERSION_MAJOR, + __MINGW64_VERSION_MINOR, __VERSION__); +#elif defined(__MINGW32__) + buf = fmt::format("MinGW-w64 32bit {}.{} / GNU C++ {}", __MINGW32_MAJOR_VERSION, + __MINGW32_MINOR_VERSION, __VERSION__); +#elif defined(__GNUC__) + buf = fmt::format("GNU C++ {}", __VERSION__); +#elif defined(_MSC_VER) && (_MSC_VER > 1920) && (_MSC_VER < 2000) + constexpr int major = _MSC_VER / 100; + constexpr int minor = _MSC_VER - major *100; + buf = "Microsoft Visual Studio 20" + std::to_string(major) + ", C/C++ " + std::to_string(major-5) + "." + std::to_string(minor); +#else + buf = "(Unknown)"; +#endif +#endif + return buf; +} + +/* ---------------------------------------------------------------------- + detect OpenMP standard +------------------------------------------------------------------------- */ + +std::string platform::openmp_standard() +{ + +#if !defined(_OPENMP) + return "OpenMP not enabled"; +#else + + // Supported OpenMP version corresponds to the release date of the + // specifications as posted at https://www.openmp.org/specifications/ + +#if _OPENMP > 202011 + return "OpenMP newer than version 5.1"; +#elif _OPENMP == 202011 + return "OpenMP 5.1"; +#elif _OPENMP == 201811 + return "OpenMP 5.0"; +#elif _OPENMP == 201611 + return "OpenMP 5.0 preview 1"; +#elif _OPENMP == 201511 + return "OpenMP 4.5"; +#elif _OPENMP == 201307 + return "OpenMP 4.0"; +#elif _OPENMP == 201107 + return "OpenMP 3.1"; +#elif _OPENMP == 200805 + return "OpenMP 3.0"; +#elif _OPENMP == 200505 + return "OpenMP 2.5"; +#elif _OPENMP == 200203 + return "OpenMP 2.0"; +#else + return "unknown OpenMP version"; +#endif + +#endif +} + +/* ---------------------------------------------------------------------- + identify MPI vendor from defines in the mpi.h file. +------------------------------------------------------------------------- */ + +std::string platform::mpi_vendor() +{ +#if defined(MPI_STUBS) + return "MPI STUBS"; +#elif defined(OPEN_MPI) + return "Open MPI"; +#elif defined(MPICH_NAME) + return "MPICH"; +#elif defined(I_MPI_VERSION) + return "Intel MPI"; +#elif defined(PLATFORM_MPI) + return "Platform MPI"; +#elif defined(HP_MPI) + return "HP MPI"; +#elif defined(MSMPI_VER) + // Get Microsoft MPI version from registry + char value[1024]; + DWORD value_length = 1024; + const char *subkey = "SOFTWARE\\Microsoft\\MPI"; + const char *entry = "Version"; + auto rv = RegGetValueA(HKEY_LOCAL_MACHINE, subkey, entry, RRF_RT_REG_SZ, nullptr, &value, + (LPDWORD) &value_length); + std::string buf = "Microsoft MPI"; + if (rv == ERROR_SUCCESS) buf += std::string(" v") + value; + return buf; +#else + return "Unknown MPI implementation"; +#endif +} + +/* ---------------------------------------------------------------------- + detect MPI version info +------------------------------------------------------------------------- */ + +std::string platform::mpi_info(int &major, int &minor) +{ + int len = 0; +#if (defined(MPI_VERSION) && (MPI_VERSION > 2)) || defined(MPI_STUBS) + static char version[MPI_MAX_LIBRARY_VERSION_STRING]; + MPI_Get_library_version(version, &len); +#else + constexpr int MAX_VERSION_STRING = 32; + static char version[MAX_VERSION_STRING]; + strncpy(version, mpi_vendor().c_str(), MAX_VERSION_STRING); +#endif + +#if defined(MPI_VERSION) + MPI_Get_version(&major, &minor); + if (len > 80) { + char *ptr = strchr(version + 80, '\n'); + if (ptr) *ptr = '\0'; + } +#else + major = 1; + minor = 0; +#endif + return std::string(version); +} + +/* ---------------------------------------------------------------------- + set environment variable +------------------------------------------------------------------------- */ + +int platform::putenv(const std::string &vardef) +{ + if (vardef.size() == 0) return -1; + + auto found = vardef.find_first_of('='); +#ifdef _WIN32 + // must assign a value to variable with _putenv() + if (found == std::string::npos) + return _putenv(utils::strdup(vardef + "=1")); + else + return _putenv(utils::strdup(vardef)); +#else + if (found == std::string::npos) + return setenv(vardef.c_str(), "", 1); + else + return setenv(vardef.substr(0, found).c_str(), vardef.substr(found + 1).c_str(), 1); +#endif + return -1; +} + +/* ---------------------------------------------------------------------- + split a "path" environment variable into a list +------------------------------------------------------------------------- */ + +std::vector platform::list_pathenv(const std::string &var) +{ + std::vector dirs; + const char *ptr = getenv(var.c_str()); + if (ptr == nullptr) return dirs; + + std::string pathvar = ptr; + std::size_t first = 0, next; + while (true) { + next = pathvar.find_first_of(pathvarsep, first); + if (next == std::string::npos) { + dirs.push_back(pathvar.substr(first)); + break; + } else { + dirs.push_back(pathvar.substr(first, next - first)); + first = next + 1; + } + } + return dirs; +} + +/* ---------------------------------------------------------------------- + find the full path name of an executable +------------------------------------------------------------------------- */ + +std::string platform::find_exe_path(const std::string &cmd) +{ + if (cmd.size() == 0) return ""; + auto pathdirs = list_pathenv("PATH"); +#ifdef _WIN32 + // windows always looks in "." and does it first + pathdirs.insert(pathdirs.begin(), "."); +#else + struct stat info; +#endif + for (const auto &dir : pathdirs) { + std::string exe = path_join(dir, cmd); +#ifdef _WIN32 + const char *extensions[] = {".exe", ".com", ".bat", nullptr}; + for (auto ext = extensions; *ext != nullptr; ++ext) { + auto exe_path = exe + *ext; + if (file_is_readable(exe_path)) return exe_path; + } +#else + memset(&info, 0, sizeof(info)); + if (stat(exe.c_str(), &info) != 0) continue; + if ((info.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) != 0) return exe; +#endif + } + return ""; +} + +/* ---------------------------------------------------------------------- + wrapper functions for loading shared objects and libraries +------------------------------------------------------------------------- */ + +#ifdef _WIN32 + +// open a shared object file +void *platform::dlopen(const std::string &fname) +{ + return (void *) LoadLibrary(fname.c_str()); +} + +// close a shared object +int platform::dlclose(void *handle) +{ + /* FreeLibrary returns nonzero on success unlike dlclose() */ + return (FreeLibrary((HINSTANCE) handle) == 0); +} + +// resolve a symbol in shared object +void *platform::dlsym(void *handle, const std::string &symbol) +{ + return (void *) GetProcAddress((HINSTANCE) handle, symbol.c_str()); +} + +#else + +// open a shared object file +void *platform::dlopen(const std::string &fname) +{ + return ::dlopen(fname.c_str(), RTLD_NOW); +} + +// close a shared object +int platform::dlclose(void *handle) +{ + return ::dlclose(handle); +} + +// resolve a symbol in shared object +void *platform::dlsym(void *handle, const std::string &symbol) +{ + return ::dlsym(handle, symbol.c_str()); +} +#endif + +/* ---------------------------------------------------------------------- */ + +/** On Linux the folder /proc/self/fd holds symbolic links to the actual + * pathnames associated with each open file descriptor of the current process. + * On macOS the same kind of information can be obtained using ``fcntl(fd,F_GETPATH,buf)``. + * On Windows we use ``GetFinalPathNameByHandleA()`` which is available with + * Windows Vista and later. If the buffer is to small (< 16 bytes) a null pointer is returned. + * + * This function is used to provide a filename with error messages in functions + * where the filename is not passed as an argument, but the FILE * pointer. */ + +const char *platform::guesspath(FILE *fp, char *buf, int len) +{ + // no point in guessing a path with a short buffer or NULL pointer as buffer + if ((buf == nullptr) || (len < 16)) return nullptr; + + // zero buffer and reserve last character in buffer for terminating '\0' + memset(buf, 0, len); + len--; + +#if defined(__linux__) + + int fd = fileno(fp); + // get pathname from /proc or copy (unknown) + if (readlink((std::string("/proc/self/fd/") + std::to_string(fd)).c_str(), buf, len) <= 0) + strncpy(buf, "(unknown)", len); + +#elif defined(__APPLE__) + + int fd = fileno(fp); + char filepath[PATH_MAX]; + if (fcntl(fd, F_GETPATH, filepath) != -1) + strncpy(buf, filepath, len); + else + strncpy(buf, "(unknown)", len); + +#elif defined(_WIN32) + + char filepath[MAX_PATH]; + HANDLE h = (HANDLE) _get_osfhandle(_fileno(fp)); + if (GetFinalPathNameByHandleA(h, filepath, MAX_PATH, FILE_NAME_NORMALIZED) > 0) + strncpy(buf, filepath, len); + else + strncpy(buf, "(unknown)", len); + +#else // unsupported OS + + strncpy(buf, "(unknown)", len); + +#endif + + return buf; +} + +/* ---------------------------------------------------------------------- + detect terminal, e.g. for using a pager automatically +------------------------------------------------------------------------- */ + +bool platform::is_console(FILE *fp) +{ + if (!fp) return false; +#if defined(_WIN32) + return (_isatty(fileno(fp)) == 1); +#else + return (isatty(fileno(fp)) == 1); +#endif +} + +/* ---------------------------------------------------------------------- + Get string with path to the current directory + PATH_MAX may not be a compile time constant, so we must allocate and delete a buffer. +------------------------------------------------------------------------- */ + +std::string platform::current_directory() +{ + std::string cwd = ""; + +#if defined(_WIN32) + char *buf = new char[MAX_PATH]; + if (_getcwd(buf, MAX_PATH)) { cwd = buf; } + delete[] buf; +#else + char *buf = new char[PATH_MAX]; + if (::getcwd(buf, PATH_MAX)) { cwd = buf; } + delete[] buf; +#endif + return cwd; +} + +/* ---------------------------------------------------------------------- + check if a path is a directory +------------------------------------------------------------------------- */ + +bool platform::path_is_directory(const std::string &path) +{ +#if defined(_WIN32) + struct _stat info; + memset(&info, 0, sizeof(info)); + if (_stat(path.c_str(), &info) != 0) return false; +#else + struct stat info; + memset(&info, 0, sizeof(info)); + if (stat(path.c_str(), &info) != 0) return false; +#endif + return ((info.st_mode & S_IFDIR) != 0); +} + +/* ---------------------------------------------------------------------- + get directory listing in string vector +------------------------------------------------------------------------- */ + +std::vector platform::list_directory(const std::string &dir) +{ + std::vector files; + if (!path_is_directory(dir)) return files; + +#if defined(_WIN32) + HANDLE handle; + WIN32_FIND_DATA fd; + std::string searchname = dir + filepathsep[0] + "*"; + handle = FindFirstFile(searchname.c_str(), &fd); + if (handle == ((HANDLE) -1)) return files; + while (FindNextFile(handle, &fd)) { + std::string entry(fd.cFileName); + if ((entry == "..") || (entry == ".")) continue; + files.push_back(entry); + } + FindClose(handle); +#else + std::string dirname = dir + filepathsep[0]; + DIR *handle = opendir(dirname.c_str()); + if (handle == nullptr) return files; + struct dirent *fd; + while ((fd = readdir(handle)) != nullptr) { + std::string entry(fd->d_name); + if ((entry == "..") || (entry == ".")) continue; + files.push_back(entry); + } + closedir(handle); +#endif + return files; +} + +/* ---------------------------------------------------------------------- + Change current directory +------------------------------------------------------------------------- */ + +int platform::chdir(const std::string &path) +{ +#if defined(_WIN32) + return ::_chdir(path.c_str()); +#else + return ::chdir(path.c_str()); +#endif +} + +/* ---------------------------------------------------------------------- + Create a directory +------------------------------------------------------------------------- */ + +int platform::mkdir(const std::string &path) +{ +#if defined(_WIN32) + return ::_mkdir(path.c_str()); +#else + return ::mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP); +#endif +} + +/* ---------------------------------------------------------------------- + Delete a directory and its contents recursively +------------------------------------------------------------------------- */ + +int platform::rmdir(const std::string &path) +{ + // recurse through directory tree deleting files and directories + auto entries = list_directory(path); + for (const auto &entry : entries) { + const auto newpath = path_join(path, entry); + if (path_is_directory(newpath)) + rmdir(newpath); + else + unlink(newpath); + } +#if defined(_WIN32) + return ::_rmdir(path.c_str()); +#else + return ::rmdir(path.c_str()); +#endif +} + +/* ---------------------------------------------------------------------- + Delete a file +------------------------------------------------------------------------- */ + +int platform::unlink(const std::string &path) +{ +#if defined(_WIN32) + return ::_unlink(path.c_str()); +#else + return ::unlink(path.c_str()); +#endif +} + +/* ---------------------------------------------------------------------- + Get current file stream position +------------------------------------------------------------------------- */ + +bigint platform::ftell(FILE *fp) +{ +#if defined(_WIN32) + return (bigint)::_ftelli64(fp); +#else + return (bigint)::ftell(fp); +#endif +} + +/* ---------------------------------------------------------------------- + Set current file stream position +------------------------------------------------------------------------- */ + +int platform::fseek(FILE *fp, bigint pos) +{ +#if defined(_WIN32) + return ::_fseeki64(fp, (__int64) pos, SEEK_SET); +#else + return ::fseek(fp, (long) pos, SEEK_SET); +#endif +} + +/* ---------------------------------------------------------------------- + Truncate opened file to given length +------------------------------------------------------------------------- */ + +int platform::ftruncate(FILE *fp, bigint length) +{ +#if defined(_WIN32) + HANDLE h = (HANDLE) _get_osfhandle(_fileno(fp)); + LARGE_INTEGER li_start, li_length; + li_start.QuadPart = (int64_t) 0; + li_length.QuadPart = (int64_t) length; + if (SetFilePointerEx(h, li_start, NULL, FILE_CURRENT) && + SetFilePointerEx(h, li_length, NULL, FILE_BEGIN) && SetEndOfFile(h)) { + return 0; + } else { + return 1; + } +#else + platform::fseek(fp, length); + return ::ftruncate(fileno(fp), (off_t) length); +#endif +} + +/* ---------------------------------------------------------------------- + open pipe +------------------------------------------------------------------------- */ + +FILE *platform::popen(const std::string &cmd, const std::string &mode) +{ + FILE *fp = nullptr; +#if defined(_WIN32) + if (mode == "r") + fp = ::_popen(cmd.c_str(), "rb"); + else if (mode == "w") + fp = ::_popen(cmd.c_str(), "wb"); +#else + if (mode == "r") + fp = ::popen(cmd.c_str(), "r"); + else if (mode == "w") + fp = ::popen(cmd.c_str(), "w"); +#endif + return fp; +} + +/* ---------------------------------------------------------------------- + close pipe +------------------------------------------------------------------------- */ + +int platform::pclose(FILE *fp) +{ +#if defined(_WIN32) + return ::_pclose(fp); +#else + return ::pclose(fp); +#endif +} + +/* ---------------------------------------------------------------------- + strip off leading part of path, return just the filename +------------------------------------------------------------------------- */ + +std::string platform::path_basename(const std::string &path) +{ + size_t start = path.find_last_of(platform::filepathsep); + + if (start == std::string::npos) { + start = 0; + } else { + start += 1; + } + + return path.substr(start); +} + +/* ---------------------------------------------------------------------- + Return only the leading part of a path, return just the directory +------------------------------------------------------------------------- */ + +std::string platform::path_dirname(const std::string &path) +{ + size_t start = path.find_last_of(platform::filepathsep); + + if (start == std::string::npos) return "."; + + return path.substr(0, start); +} + +/* ---------------------------------------------------------------------- + join two paths. + if one of the two is an empty string just return the other unmodified + if the first string ends in the separator or the second begins with one, trim them +------------------------------------------------------------------------- */ + +std::string platform::path_join(const std::string &a, const std::string &b) +{ + if (a.empty()) return b; + if (b.empty()) return a; + + // remove trailing separator(s) in first part + std::string joined = a; + while (joined.find_last_of(platform::filepathsep) == joined.size() - 1) { + for (const auto &s : platform::filepathsep) + if (joined.back() == s) joined.pop_back(); + } + + // skip over leading separator(s) in second part + std::size_t skip = 0; + while (b.find_first_of(platform::filepathsep, skip) == skip) ++skip; + + // combine and return + joined += platform::filepathsep[0] + b.substr(skip); + return joined; +} + +/* ---------------------------------------------------------------------- + try to open file for reading to prove if it exists and is accessible +------------------------------------------------------------------------- */ + +bool platform::file_is_readable(const std::string &path) +{ + FILE *fp = fopen(path.c_str(), "r"); + if (fp) { + fclose(fp); + return true; + } + return false; +} + +/* ---------------------------------------------------------------------- + check if filename has a known compression extension +------------------------------------------------------------------------- */ + +bool platform::has_zip_extension(const std::string &file) +{ + return find_zip_type(file).style != zip_info::NONE; +} + +/* ---------------------------------------------------------------------- + open pipe to read a compressed file +------------------------------------------------------------------------- */ + +FILE *platform::zip_read(const std::string &file) +{ + FILE *fp = nullptr; + +#if defined(LAMMPS_GZIP) + auto zip = find_zip_type(file); + if (zip.style == zip_info::NONE) return nullptr; + + if (find_exe_path(zip.command).size()) + // put quotes around file name so that they may contain blanks + fp = popen((zip.command + zip.unzipflags + "\"" + file + "\""), "r"); +#endif + return fp; +} + +/* ---------------------------------------------------------------------- + open pipe to write a compressed file +------------------------------------------------------------------------- */ + +FILE *platform::zip_write(const std::string &file) +{ + FILE *fp = nullptr; + +#if defined(LAMMPS_GZIP) + auto zip = find_zip_type(file); + if (zip.style == zip_info::NONE) return nullptr; + + if (find_exe_path(zip.command).size()) + // put quotes around file name so that they may contain blanks + fp = popen((zip.command + zip.zipflags + "\"" + file + "\""), "w"); +#endif + return fp; +} + +/* ---------------------------------------------------------------------- */ diff --git a/src/platform.h b/src/platform.h new file mode 100644 index 0000000000..5aeee1545e --- /dev/null +++ b/src/platform.h @@ -0,0 +1,350 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifndef LMP_PLATFORM_H +#define LMP_PLATFORM_H + +/*! \file platform.h */ + +#include "lmptype.h" + +#include +#include + +namespace LAMMPS_NS { +namespace platform { + + /*! Return the consumed CPU time for the current process in seconds + * + * This is a wrapper about the POSIX function getrusage() and the Windows equivalent. + * It is to be used in a similar fashion than MPI_Wtime(). + * + * \return used CPU time in second */ + + double cputime(); + + /*! Return the wall clock state for the current process in seconds + * + * This is a wrapper about XXX and its Windows equivalent. + * It is to be used in a similar fashion than MPI_Wtime(). + * + * \return wall clock time in second */ + + double walltime(); + + /*! Return string with the Operating system version and architecture info. + * + * \return string with info about the OS and the platform is is running on */ + + std::string os_info(); + + /*! Return string with C++ standard version used to compile LAMMPS. + * + * This function uses predefined compiler macros to identify + * the C++ standard version used to compile LAMMPS with. + * + * \return string with the C++ standard version or "unknown" */ + + std::string cxx_standard(); + + /*! Return string with compiler version info + * + * This function uses predefined compiler macros to identify + * Compilers and their version and configuration info. + * + * \return string with the compiler information text */ + + std::string compiler_info(); + + /*! Return string with OpenMP standard version info + * + * This function uses predefined compiler macros to identify + * OpenMP support and the supported version of the standard. + * + * \return string with the openmp information text */ + + std::string openmp_standard(); + + /*! Return string with MPI vendor info + * + * This function uses predefined macros to identify + * the vendor of the MPI library used. + * + * \return string with the MPI vendor information text */ + + std::string mpi_vendor(); + + /*! Return string with MPI version info + * + * This function uses predefined macros and MPI function + * calls to identify the version of the MPI library used. + * + * \param major major version of the MPI standard (set on exit) + * \param minor minor version of the MPI standard (set on exit) + * \return string with the MPI version information text */ + + std::string mpi_info(int &major, int &minor); + + /*! Add variable to the environment + * + * \param vardef variable name or variable definition (NAME=value) + * \return -1 if failure otherwise 0 */ + + int putenv(const std::string &vardef); + + /*! Get list of entries in a path environment variable + * + * This provides a list of strings of the entries in an environment + * variable that is containing a "path" like "PATH" or "LD_LIBRARY_PATH". + * + * \param var name of the environment variable + * \return vector with strings of all entries in that path variable */ + + std::vector list_pathenv(const std::string &var); + + /*! Open a shared object file or library + * + * \param fname name or path of the shared object + * \return handle to the shared object or null */ + + void *dlopen(const std::string &fname); + + /*! Close a shared object + * This releases the object corresponding to the provided handle. + * Resolved symbols associated with this handle may not be used + * after this call + * + * \param handle handle to an opened shared object + * \return 0 if succesful, non-zero of not */ + + int dlclose(void *handle); + + /*! Resolve a symbol in shared object + * + * \param handle handle to an opened shared object + * \param symbol name of the symbol to extract + * \return pointer to the resolved symbol or null */ + + void *dlsym(void *handle, const std::string &symbol); + + /*! File path component separators + * These are the characters that separate directories and filename in paths on + * a platform. If multiple are provided, the first is the preferred one. */ + +#if defined(_WIN32) + constexpr char filepathsep[] = "\\/"; +#else + constexpr char filepathsep[] = "/"; +#endif + + /*! Path environment variable component separator + * This is the character that separates entries in "PATH" environment variables. */ + +#if defined(_WIN32) + constexpr char pathvarsep = ';'; +#else + constexpr char pathvarsep = ':'; +#endif + + /*! Try to detect pathname from FILE pointer. + * + * Currently only supported on Linux and macOS, otherwise will report "(unknown)". + * + * \param fp FILE pointer struct from STDIO library for which we want to detect the name + * \param buf storage buffer for pathname. output will be truncated if not large enough + * \param len size of storage buffer. output will be truncated to this length - 1 + * \return pointer to the storage buffer with path or a NULL pointer if buf is invalid + * or the buffer size is too small */ + + const char *guesspath(FILE *fp, char *buf, int len); + + /*! Check if a file pointer may be connected to a console + * + * \param fp file pointer + * \return true if the file pointer is flagged as a TTY */ + + bool is_console(FILE *fp); + + /*! Get string with path to the current directory + * + * \return path to the current directory or empty string */ + + std::string current_directory(); + + /*! Check if a path is a directory + * + * \param path directory path + * \return true if the directory exists */ + + bool path_is_directory(const std::string &path); + + /*! Get list of entries in a directory + * + * This provides a list of strings of the entries in the directory + * without the leading path name while also skipping over ".." and ".". + * + * \param path path to directory + * \return vector with strings of all directory entries */ + + std::vector list_directory(const std::string &dir); + + /*! Find pathname of an executable in the standard search path + * + * This function will traverse the list of directories in the PATH + * environment variable and look for the executable *cmd*. If the + * file exists and is executable the full path is returned as string, + * otherwise and emptry string is returned. + * + * On Windows the *cmd* string must not include and extension as + * this function will automatically append the extensions ".exe", + * ".com" and ".bat" and look for those paths. On Windows also the + * current directory is checked (and first), while otherwise not unless + * "." exists in the PATH environment variable. + * + * Because of the nature of the check, this will not detect shell functions + * built-in command or aliases. + * + * \param cmd name of command + * \return vector with strings of all directory entries */ + + std::string find_exe_path(const std::string &cmd); + + /*! Change current directory + * + * \param path new current working directory path + * \return -1 if unsuccessful, otherwise >= 0 */ + + int chdir(const std::string &path); + + /*! Create a directory + * + * \param path directory path + * \return -1 if unsuccessful, otherwise >= 0 */ + + int mkdir(const std::string &path); + + /*! Delete a directory + * + * \param path directory path + * \return -1 if unsuccessful, otherwise >= 0 */ + + int rmdir(const std::string &path); + + /*! Delete a directory and its contents + * + * Unlike the the ``rmdir()`` or ``_rmdir()`` function of the + * C library, this function will check for the contents of the + * folder and recurse into any sub-folders, if necessary and + * delete all contained folders and their contents before + * deleting the folder *path*. + * + * \param path path to file to be deleted + * \return 0 on success, -1 on error */ + + int unlink(const std::string &path); + + /*! Get current file position + * + * \param fp FILE pointer of the given file + * \return current FILE pointer position cast to a bigint */ + + bigint ftell(FILE *fp); + + /*! Set absolute file position + * + * \param fp FILE pointer of the given file + * \param pos new position of the FILE pointer + * \return 0 if successful, otherwise -1 */ + + int fseek(FILE *fp, bigint pos); + + /*! Truncate file to a given length and reposition file pointer + * + * \param fp FILE pointer of the given file + * \param length length to which the file is being truncated to + * \return 0 if successful, otherwise -1 */ + + int ftruncate(FILE *fp, bigint length); + + /*! Open a pipe to a command for reading or writing + * + * \param cmd command for the pipe + * \param mode "r" for reading from *cmd* or "w" for writing to *cmd* + * \return file pointer to the pipe if successful or null */ + + FILE *popen(const std::string &cmd, const std::string &mode); + + /*! Close a previously opened pipe + * + * \param fp FILE pointer for the pipe + * \return exit status of the pipe command or -1 in case of errors */ + + int pclose(FILE *fp); + + /*! Strip off leading part of path, return just the filename + * + * \param path file path + * \return file name */ + + std::string path_basename(const std::string &path); + + /*! Return the directory part of a path. Return "." if empty + * + * \param path file path + * \return directory name */ + + std::string path_dirname(const std::string &path); + + /*! Join two pathname segments + * + * This uses the forward slash '/' character unless LAMMPS is compiled + * for Windows where it used the equivalent backward slash '\\'. + * + * \param a first path + * \param b second path + * \return combined path */ + + std::string path_join(const std::string &a, const std::string &b); + + /*! Check if file exists and is readable + * + * \param path file path + * \return true if file exists and is readable */ + + bool file_is_readable(const std::string &path); + + /*! Check if a file name ends in a known extension for a compressed file format + * Currently supported extensions are: .Z, .gz, .bz2, .zstd, .xz, .lzma + * + * \param file name of the file to check + * \return true if the file has a known extension, otherwise false */ + + bool has_zip_extension(const std::string &file); + + /*! Open pipe to compressed text file for reading. + * + * \param file name of the file to open + * \return FILE pointer to pipe using for reading the compressed file. */ + + FILE *zip_read(const std::string &file); + + /*! Open pipe to compressed text file for writing. + * + * \param file name of the file to open + * \return FILE pointer to pipe using for reading the compressed file. */ + + FILE *zip_write(const std::string &file); + +} // namespace platform +} // namespace LAMMPS_NS +#endif diff --git a/unittest/utils/CMakeLists.txt b/unittest/utils/CMakeLists.txt index c1ce7c136f..d58b1294be 100644 --- a/unittest/utils/CMakeLists.txt +++ b/unittest/utils/CMakeLists.txt @@ -15,6 +15,22 @@ target_link_libraries(test_utils PRIVATE lammps GTest::GMockMain GTest::GMock GT add_test(Utils test_utils) set_tests_properties(Utils PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") +add_executable(test_platform test_platform.cpp) +target_link_libraries(test_platform PRIVATE lammps GTest::GMockMain GTest::GMock GTest::GTest) +add_test(Platform test_platform) +set(PLATFORM_ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") +if(BUILD_SHARED_LIBS) + enable_language(C) + target_compile_definitions(test_platform PRIVATE -DTEST_SHARED_OBJECT=1) + add_library(testsharedobj MODULE testshared.c) + set_target_properties(testsharedobj PROPERTIES PREFIX "" WINDOWS_EXPORT_ALL_SYMBOLS TRUE) + add_library(testsharedlib SHARED testshared.c) + set_target_properties(testsharedlib PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) + add_dependencies(test_platform testsharedobj testsharedlib) + list(APPEND PLATFORM_ENVIRONMENT "TEST_SHARED_LIB=$" "TEST_SHARED_OBJ=$") +endif() +set_tests_properties(Platform PROPERTIES ENVIRONMENT ${PLATFORM_ENVIRONMENT} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + add_executable(test_fmtlib test_fmtlib.cpp) target_link_libraries(test_fmtlib PRIVATE lammps GTest::GMockMain GTest::GMock GTest::GTest) add_test(FmtLib test_fmtlib) diff --git a/unittest/utils/test_platform.cpp b/unittest/utils/test_platform.cpp new file mode 100644 index 0000000000..154fb2c222 --- /dev/null +++ b/unittest/utils/test_platform.cpp @@ -0,0 +1,395 @@ + +#include "platform.h" +#include "utils.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include + +using namespace LAMMPS_NS; +using testing::EndsWith; +using testing::Eq; +using testing::IsEmpty; +using testing::StartsWith; +using testing::StrEq; + +TEST(Platform, clock) +{ + const double wt_start = platform::walltime(); + const double ct_start = platform::cputime(); + + // spend some time computing pi + constexpr double known_pi = 3.141592653589793238462643; + constexpr int n = 10000000; + constexpr double h = 1.0 / (double) n; + double my_pi = 0.0, x; + for (int i = 0; i < n; ++i) { + x = h * ((double) i + 0.5); + my_pi += 4.0 / (1.0 + x * x); + } + my_pi *= h; + const double wt_used = platform::walltime() - wt_start; + const double ct_used = platform::cputime() - ct_start; + + ASSERT_NEAR(my_pi, known_pi, 1e-12); + ASSERT_GT(wt_used, 1e-4); + ASSERT_GT(ct_used, 1e-4); +} + +TEST(Platform, putenv) +{ + const char *var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(var, nullptr); + int rv = platform::putenv("UNITTEST_VAR1"); + var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(rv, 0); + ASSERT_NE(var, nullptr); + // we cannot set environment variables without a value on windows with _putenv() +#if defined(_WIN32) + ASSERT_THAT(var, StrEq("1")); +#else + ASSERT_THAT(var, StrEq("")); +#endif + + rv = platform::putenv("UNITTEST_VAR1=one"); + var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(rv, 0); + ASSERT_NE(var, nullptr); + ASSERT_THAT(var, StrEq("one")); + + rv = platform::putenv("UNITTEST_VAR1=one=two"); + var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(rv, 0); + ASSERT_NE(var, nullptr); + ASSERT_THAT(var, StrEq("one=two")); + + ASSERT_EQ(platform::putenv(""), -1); +} + +TEST(Platform, list_pathenv) +{ + auto dirs = platform::list_pathenv("PATH"); + ASSERT_GT(dirs.size(), 1); +} + +TEST(Platform, find_cmd_path) +{ +#if defined(_WIN32) + ASSERT_THAT(platform::find_exe_path("notepad"), EndsWith("\\notepad.exe")); + ASSERT_THAT(platform::find_exe_path("cmd"), EndsWith("\\cmd.exe")); + ASSERT_THAT(platform::find_exe_path("some_bogus_command"), IsEmpty()); +#else + ASSERT_THAT(platform::find_exe_path("ls"), EndsWith("bin/ls")); + ASSERT_THAT(platform::find_exe_path("sh"), EndsWith("bin/sh")); + ASSERT_THAT(platform::find_exe_path("some_bogus_command"), IsEmpty()); +#endif +} + +TEST(Platform, sharedload) +{ + const char *objs[] = {"TEST_SHARED_OBJ", "TEST_SHARED_LIB", nullptr}; + const char *envvar, **envptr; + const int *intvar; + const double *doublevar; + void *handle; + int (*intfunc)(int); + double (*doublefunc)(double, int); + + for (envptr = objs; *envptr != nullptr; ++envptr) { + envvar = getenv(*envptr); + EXPECT_NE(envvar, nullptr); + handle = platform::dlopen(envvar); + EXPECT_NE(handle, nullptr); + intvar = (int *) platform::dlsym(handle, "some_int_val"); + EXPECT_NE(intvar, nullptr); + EXPECT_EQ(*intvar, 12345); + doublevar = (double *) platform::dlsym(handle, "some_double_val"); + EXPECT_NE(doublevar, nullptr); + EXPECT_DOUBLE_EQ(*doublevar, 6.78e-9); + intfunc = (int (*)(int)) platform::dlsym(handle, "some_int_function"); + EXPECT_NE(intfunc, nullptr); + EXPECT_EQ((*intfunc)(12), 144); + doublefunc = (double (*)(double, int)) platform::dlsym(handle, "some_double_function"); + EXPECT_NE(doublefunc, nullptr); + EXPECT_DOUBLE_EQ((*doublefunc)(0.5, 6), 3.0); + EXPECT_EQ(platform::dlsym(handle, "some_nonexisting_symbol"), nullptr); + EXPECT_EQ(platform::dlclose(handle), 0); + } +} + +TEST(Platform, guesspath) +{ + char buf[256]; + FILE *fp = fopen("test_guesspath.txt", "w"); +#if defined(__linux__) || defined(__APPLE__) || defined(_WIN32) + const char *path = platform::guesspath(fp, buf, sizeof(buf)); + ASSERT_THAT(path, EndsWith("test_guesspath.txt")); +#else + const char *path = platform::guesspath(fp, buf, sizeof(buf)); + ASSERT_THAT(path, EndsWith("(unknown)")); +#endif + fclose(fp); + platform::unlink("test_guesspath.txt"); +} + +TEST(Platform, unlink) +{ + const char test[] = "12345678901234567890"; + platform::unlink("unlink.dat"); + ASSERT_EQ(platform::unlink("dummy.dat"), -1); + FILE *fp = fopen("unlink.dat", "w"); + fwrite(test, sizeof(test), 1, fp); + fclose(fp); + ASSERT_EQ(platform::unlink("unlink.dat"), 0); + ASSERT_EQ(platform::unlink("unlink.dat"), -1); + fp = fopen("unlink.dat", "r"); + ASSERT_EQ(fp, nullptr); + + platform::mkdir("unlink.dir"); + ASSERT_EQ(platform::unlink("unlink.dir"), -1); + platform::rmdir("unlink.dir"); +} + +TEST(Platform, fseek_ftell) +{ + const char test[] = "12345678901234567890"; + platform::unlink("seek_tell.dat"); + FILE *fp = fopen("seek_tell.dat", "w"); + fwrite(test, sizeof(test), 1, fp); + fflush(fp); + ASSERT_EQ(platform::ftell(fp), sizeof(test)); + fclose(fp); + fp = fopen("seek_tell.dat", "r+"); + ASSERT_EQ(fgetc(fp), '1'); + ASSERT_EQ(fgetc(fp), '2'); + ASSERT_EQ(platform::ftell(fp), 2); + ASSERT_EQ(platform::fseek(fp, 15), 0); + ASSERT_EQ(fgetc(fp), '6'); + fflush(fp); + fseek(fp, -1, SEEK_END); + ASSERT_EQ(fgetc(fp), 0); + ASSERT_EQ(platform::ftell(fp), 21); + fclose(fp); + platform::unlink("seek_tell.dat"); +} + +TEST(Platform, ftruncate) +{ + platform::unlink("truncate.dat"); + FILE *fp = fopen("truncate.dat", "w"); + fputs("header one\n", fp); + fputs("header two\n", fp); + fflush(fp); + bigint filepos = platform::ftell(fp); + fputs("line one\n", fp); + fputs("line two\n", fp); + fputs("line three\n", fp); + fflush(fp); + ASSERT_EQ(platform::ftruncate(fp, filepos), 0); + fputs("line four\n", fp); + ASSERT_GT(platform::ftell(fp), filepos); + fputs("line five\n", fp); + fflush(fp); + fclose(fp); + + // check file + fp = fopen("truncate.dat", "r"); + char buf[128]; + char *ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("header one")); + ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("header two")); + ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("line four")); + ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("line five")); + ptr = fgets(buf, 127, fp); + ASSERT_EQ(ptr, nullptr); + fclose(fp); + platform::unlink("truncate.dat"); +} + +TEST(Platform, path_basename) +{ +#if defined(_WIN32) + ASSERT_THAT(platform::path_basename("c:\\parent\\folder\\filename"), Eq("filename")); + ASSERT_THAT(platform::path_basename("folder\\"), Eq("")); + ASSERT_THAT(platform::path_basename("c:/parent/folder/filename"), Eq("filename")); +#else + ASSERT_THAT(platform::path_basename("/parent/folder/filename"), Eq("filename")); + ASSERT_THAT(platform::path_basename("/parent/folder/"), Eq("")); +#endif +} + +TEST(Platform, path_dirname) +{ +#if defined(_WIN32) + ASSERT_THAT(platform::path_dirname("c:/parent/folder/filename"), Eq("c:/parent/folder")); + ASSERT_THAT(platform::path_dirname("c:\\parent\\folder\\filename"), Eq("c:\\parent\\folder")); + ASSERT_THAT(platform::path_dirname("c:filename"), Eq(".")); +#else + ASSERT_THAT(platform::path_dirname("/parent/folder/filename"), Eq("/parent/folder")); +#endif + ASSERT_THAT(platform::path_dirname("filename"), Eq(".")); +} + +TEST(Platform, path_join) +{ +#if defined(_WIN32) + ASSERT_THAT(platform::path_join("c:\\folder", "filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\", "filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder", "\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\", "\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder", "/filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\\\", "\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\", "\\\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder/\\", "/\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\/", "\\/filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder", ""), Eq("c:\\folder")); + ASSERT_THAT(platform::path_join("", "\\/filename"), Eq("\\/filename")); +#else + ASSERT_THAT(platform::path_join("/parent/folder", "filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", "filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder", "/filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", "/filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder//", "filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder", "//filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder///", "/filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", "///filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", ""), Eq("/parent/folder/")); + ASSERT_THAT(platform::path_join("", "\\/filename"), Eq("\\/filename")); +#endif +} + +TEST(Platform, is_console) +{ + platform::unlink("file_is_no_console.txt"); + FILE *fp = fopen("file_is_no_console.txt", "w"); + fputs("some text\n", fp); + EXPECT_FALSE(platform::is_console(fp)); + fclose(fp); + platform::unlink("file_is_no_console.txt"); +} + +TEST(Platform, path_and_directory) +{ + platform::unlink("path_is_directory"); + platform::rmdir("path_is_directory"); + platform::unlink("path_is_file"); + platform::mkdir("path_is_directory"); + FILE *fp = fopen("path_is_file", "w"); + fputs("some text\n", fp); + fclose(fp); + + ASSERT_TRUE(platform::path_is_directory("path_is_directory")); + ASSERT_FALSE(platform::path_is_directory("path_is_file")); + ASSERT_FALSE(platform::path_is_directory("path_does_not_exist")); + platform::unlink("path_is_file"); + +#if defined(_WIN32) + fp = fopen("path_is_directory\\path_is_file", "w"); +#else + fp = fopen("path_is_directory/path_is_file", "w"); +#endif + fputs("some text\n", fp); + fclose(fp); +#if defined(_WIN32) + platform::mkdir("path_is_directory\\path_is_directory"); + fp = fopen("path_is_directory\\path_is_other_file", "w"); +#else + platform::mkdir("path_is_directory/path_is_directory"); + fp = fopen("path_is_directory/path_is_other_file", "w"); +#endif + fputs("some text\n", fp); + fclose(fp); + auto dirs = platform::list_directory("path_is_directory"); + ASSERT_EQ(dirs.size(), 3); + platform::rmdir("path_is_directory"); + ASSERT_FALSE(platform::path_is_directory("path_is_directory")); +} + +TEST(Platform, get_change_directory) +{ + platform::unlink("working_directory"); + platform::rmdir("working_directory"); + + auto cwd = platform::current_directory(); + ASSERT_GT(cwd.size(), 0); + + platform::mkdir("working_directory"); + ASSERT_EQ(platform::chdir("working_directory"), 0); + ASSERT_THAT(platform::current_directory(), EndsWith("working_directory")); + + ASSERT_EQ(platform::chdir(".."), 0); + ASSERT_THAT(platform::current_directory(), StrEq(cwd)); + platform::rmdir("working_directory"); +} + +TEST(Platform, file_is_readable) +{ + platform::unlink("file_is_readable.txt"); + FILE *fp = fopen("file_is_readable.txt", "w"); + fputs("some text\n", fp); + fclose(fp); + + ASSERT_TRUE(platform::file_is_readable("file_is_readable.txt")); + ASSERT_FALSE(platform::file_is_readable("file_does_not_exist.txt")); + platform::unlink("file_is_readable.txt"); + + // windows does not have permission flags +#if !defined(_WIN32) + platform::unlink("file_is_not_readable.txt"); + fp = fopen("file_is_not_readable.txt", "w"); + fputs("some text\n", fp); + fclose(fp); + chmod("file_is_not_readable.txt", 0); + ASSERT_FALSE(platform::file_is_readable("file_is_not_readable.txt")); + platform::unlink("file_is_not_readable.txt"); +#endif +} + +TEST(Platform, has_zip_extension) +{ + ASSERT_FALSE(platform::has_zip_extension("dummy")); + ASSERT_FALSE(platform::has_zip_extension("dum.my")); + ASSERT_TRUE(platform::has_zip_extension("dummy.gz")); + ASSERT_TRUE(platform::has_zip_extension("dummy.bz2")); + ASSERT_TRUE(platform::has_zip_extension("dummy.zstd")); + ASSERT_TRUE(platform::has_zip_extension("dummy.xz")); + ASSERT_TRUE(platform::has_zip_extension("dummy.lzma")); + ASSERT_TRUE(platform::has_zip_extension("dummy.lz4")); +} + +TEST(Platform, zip_read_write) +{ + const std::vector test_files = {"zip_test.zip", "zip_test.gz", "zip_test.bz2", + "zip_test.zstd", "zip_test.xz", "zip_test.lzma", + "zip_test.lz4", "zip_test.unk", "zip test.gz"}; + for (const auto &file : test_files) { + platform::unlink(file); + FILE *fp = platform::zip_write(file); + if (!fp) { + platform::unlink(file); + continue; + } + + clearerr(fp); + fputs("line one\n", fp); + fputs("line two\n", fp); + ASSERT_EQ(ferror(fp), 0); + fflush(fp); + platform::pclose(fp); + + fp = platform::zip_read(file); + ASSERT_NE(fp, nullptr); + char buf[128]; + char *ptr = fgets(buf, 128, fp); + EXPECT_THAT(ptr, StartsWith("line one")); + ptr = fgets(buf, 128, fp); + EXPECT_THAT(ptr, StartsWith("line two")); + ASSERT_EQ(ferror(fp), 0); + platform::pclose(fp); + platform::unlink(file); + } +} diff --git a/unittest/utils/testshared.c b/unittest/utils/testshared.c new file mode 100644 index 0000000000..869be91c2a --- /dev/null +++ b/unittest/utils/testshared.c @@ -0,0 +1,20 @@ +/* file for testing loading of shared objects and libraries */ + +int some_int_val = 12345; +double some_double_val = 6.78e-9; + +int some_int_function(int arg) +{ + return arg*arg; +} + +double some_double_function(double arg1, int arg2) +{ + double sum = 0; + for (int i = 0; i < arg2; ++i) + sum += arg1; + return sum; +} + + + From 195fe81c60bf8d8311ab2adb3104026de73d5e82 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 1 Oct 2021 23:52:02 -0400 Subject: [PATCH 02/84] correct test for loading shared objects and libraries --- unittest/utils/CMakeLists.txt | 12 +- unittest/utils/test_platform.cpp | 537 ++++++++++++++++--------------- 2 files changed, 278 insertions(+), 271 deletions(-) diff --git a/unittest/utils/CMakeLists.txt b/unittest/utils/CMakeLists.txt index d58b1294be..9f708861cc 100644 --- a/unittest/utils/CMakeLists.txt +++ b/unittest/utils/CMakeLists.txt @@ -13,23 +13,25 @@ add_test(ArgUtils test_argutils) add_executable(test_utils test_utils.cpp) target_link_libraries(test_utils PRIVATE lammps GTest::GMockMain GTest::GMock GTest::GTest) add_test(Utils test_utils) -set_tests_properties(Utils PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") add_executable(test_platform test_platform.cpp) target_link_libraries(test_platform PRIVATE lammps GTest::GMockMain GTest::GMock GTest::GTest) add_test(Platform test_platform) -set(PLATFORM_ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + +set_tests_properties(Utils Platform PROPERTIES + ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + if(BUILD_SHARED_LIBS) enable_language(C) - target_compile_definitions(test_platform PRIVATE -DTEST_SHARED_OBJECT=1) add_library(testsharedobj MODULE testshared.c) set_target_properties(testsharedobj PROPERTIES PREFIX "" WINDOWS_EXPORT_ALL_SYMBOLS TRUE) add_library(testsharedlib SHARED testshared.c) set_target_properties(testsharedlib PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) add_dependencies(test_platform testsharedobj testsharedlib) - list(APPEND PLATFORM_ENVIRONMENT "TEST_SHARED_LIB=$" "TEST_SHARED_OBJ=$") + target_compile_definitions(test_platform PRIVATE TEST_SHARED_LOAD=1 + TEST_SHARED_LIB=$ + TEST_SHARED_OBJ=$) endif() -set_tests_properties(Platform PROPERTIES ENVIRONMENT ${PLATFORM_ENVIRONMENT} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) add_executable(test_fmtlib test_fmtlib.cpp) target_link_libraries(test_fmtlib PRIVATE lammps GTest::GMockMain GTest::GMock GTest::GTest) diff --git a/unittest/utils/test_platform.cpp b/unittest/utils/test_platform.cpp index 154fb2c222..6c17b8876e 100644 --- a/unittest/utils/test_platform.cpp +++ b/unittest/utils/test_platform.cpp @@ -16,380 +16,385 @@ using testing::StrEq; TEST(Platform, clock) { - const double wt_start = platform::walltime(); - const double ct_start = platform::cputime(); + const double wt_start = platform::walltime(); + const double ct_start = platform::cputime(); - // spend some time computing pi - constexpr double known_pi = 3.141592653589793238462643; - constexpr int n = 10000000; - constexpr double h = 1.0 / (double) n; - double my_pi = 0.0, x; - for (int i = 0; i < n; ++i) { - x = h * ((double) i + 0.5); - my_pi += 4.0 / (1.0 + x * x); - } - my_pi *= h; - const double wt_used = platform::walltime() - wt_start; - const double ct_used = platform::cputime() - ct_start; + // spend some time computing pi + constexpr double known_pi = 3.141592653589793238462643; + constexpr int n = 10000000; + constexpr double h = 1.0 / (double)n; + double my_pi = 0.0, x; + for (int i = 0; i < n; ++i) { + x = h * ((double)i + 0.5); + my_pi += 4.0 / (1.0 + x * x); + } + my_pi *= h; + const double wt_used = platform::walltime() - wt_start; + const double ct_used = platform::cputime() - ct_start; - ASSERT_NEAR(my_pi, known_pi, 1e-12); - ASSERT_GT(wt_used, 1e-4); - ASSERT_GT(ct_used, 1e-4); + ASSERT_NEAR(my_pi, known_pi, 1e-12); + ASSERT_GT(wt_used, 1e-4); + ASSERT_GT(ct_used, 1e-4); } TEST(Platform, putenv) { - const char *var = getenv("UNITTEST_VAR1"); - ASSERT_EQ(var, nullptr); - int rv = platform::putenv("UNITTEST_VAR1"); - var = getenv("UNITTEST_VAR1"); - ASSERT_EQ(rv, 0); - ASSERT_NE(var, nullptr); - // we cannot set environment variables without a value on windows with _putenv() + const char *var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(var, nullptr); + int rv = platform::putenv("UNITTEST_VAR1"); + var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(rv, 0); + ASSERT_NE(var, nullptr); + // we cannot set environment variables without a value on windows with _putenv() #if defined(_WIN32) - ASSERT_THAT(var, StrEq("1")); + ASSERT_THAT(var, StrEq("1")); #else - ASSERT_THAT(var, StrEq("")); + ASSERT_THAT(var, StrEq("")); #endif - rv = platform::putenv("UNITTEST_VAR1=one"); - var = getenv("UNITTEST_VAR1"); - ASSERT_EQ(rv, 0); - ASSERT_NE(var, nullptr); - ASSERT_THAT(var, StrEq("one")); + rv = platform::putenv("UNITTEST_VAR1=one"); + var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(rv, 0); + ASSERT_NE(var, nullptr); + ASSERT_THAT(var, StrEq("one")); - rv = platform::putenv("UNITTEST_VAR1=one=two"); - var = getenv("UNITTEST_VAR1"); - ASSERT_EQ(rv, 0); - ASSERT_NE(var, nullptr); - ASSERT_THAT(var, StrEq("one=two")); + rv = platform::putenv("UNITTEST_VAR1=one=two"); + var = getenv("UNITTEST_VAR1"); + ASSERT_EQ(rv, 0); + ASSERT_NE(var, nullptr); + ASSERT_THAT(var, StrEq("one=two")); - ASSERT_EQ(platform::putenv(""), -1); + ASSERT_EQ(platform::putenv(""), -1); } TEST(Platform, list_pathenv) { - auto dirs = platform::list_pathenv("PATH"); - ASSERT_GT(dirs.size(), 1); + auto dirs = platform::list_pathenv("PATH"); + ASSERT_GT(dirs.size(), 1); } TEST(Platform, find_cmd_path) { #if defined(_WIN32) - ASSERT_THAT(platform::find_exe_path("notepad"), EndsWith("\\notepad.exe")); - ASSERT_THAT(platform::find_exe_path("cmd"), EndsWith("\\cmd.exe")); - ASSERT_THAT(platform::find_exe_path("some_bogus_command"), IsEmpty()); + ASSERT_THAT(platform::find_exe_path("notepad"), EndsWith("\\notepad.exe")); + ASSERT_THAT(platform::find_exe_path("cmd"), EndsWith("\\cmd.exe")); + ASSERT_THAT(platform::find_exe_path("some_bogus_command"), IsEmpty()); #else - ASSERT_THAT(platform::find_exe_path("ls"), EndsWith("bin/ls")); - ASSERT_THAT(platform::find_exe_path("sh"), EndsWith("bin/sh")); - ASSERT_THAT(platform::find_exe_path("some_bogus_command"), IsEmpty()); + ASSERT_THAT(platform::find_exe_path("ls"), EndsWith("bin/ls")); + ASSERT_THAT(platform::find_exe_path("sh"), EndsWith("bin/sh")); + ASSERT_THAT(platform::find_exe_path("some_bogus_command"), IsEmpty()); #endif } +#if defined(TEST_SHARED_LOAD) +#define stringify(s) mkstring(s) +#define mkstring(s) #s TEST(Platform, sharedload) { - const char *objs[] = {"TEST_SHARED_OBJ", "TEST_SHARED_LIB", nullptr}; - const char *envvar, **envptr; - const int *intvar; - const double *doublevar; - void *handle; - int (*intfunc)(int); - double (*doublefunc)(double, int); + const std::vector objs = {stringify(TEST_SHARED_OBJ), stringify(TEST_SHARED_LIB)}; + const int *intvar; + const double *doublevar; + void *handle; + int (*intfunc)(int); + double (*doublefunc)(double, int); - for (envptr = objs; *envptr != nullptr; ++envptr) { - envvar = getenv(*envptr); - EXPECT_NE(envvar, nullptr); - handle = platform::dlopen(envvar); - EXPECT_NE(handle, nullptr); - intvar = (int *) platform::dlsym(handle, "some_int_val"); - EXPECT_NE(intvar, nullptr); - EXPECT_EQ(*intvar, 12345); - doublevar = (double *) platform::dlsym(handle, "some_double_val"); - EXPECT_NE(doublevar, nullptr); - EXPECT_DOUBLE_EQ(*doublevar, 6.78e-9); - intfunc = (int (*)(int)) platform::dlsym(handle, "some_int_function"); - EXPECT_NE(intfunc, nullptr); - EXPECT_EQ((*intfunc)(12), 144); - doublefunc = (double (*)(double, int)) platform::dlsym(handle, "some_double_function"); - EXPECT_NE(doublefunc, nullptr); - EXPECT_DOUBLE_EQ((*doublefunc)(0.5, 6), 3.0); - EXPECT_EQ(platform::dlsym(handle, "some_nonexisting_symbol"), nullptr); - EXPECT_EQ(platform::dlclose(handle), 0); - } + for (const auto &obj : objs) { + handle = platform::dlopen(obj.c_str()); + EXPECT_NE(handle, nullptr); + intvar = (int *)platform::dlsym(handle, "some_int_val"); + EXPECT_NE(intvar, nullptr); + EXPECT_EQ(*intvar, 12345); + doublevar = (double *)platform::dlsym(handle, "some_double_val"); + EXPECT_NE(doublevar, nullptr); + EXPECT_DOUBLE_EQ(*doublevar, 6.78e-9); + intfunc = (int (*)(int))platform::dlsym(handle, "some_int_function"); + EXPECT_NE(intfunc, nullptr); + EXPECT_EQ((*intfunc)(12), 144); + doublefunc = (double (*)(double, int))platform::dlsym(handle, "some_double_function"); + EXPECT_NE(doublefunc, nullptr); + EXPECT_DOUBLE_EQ((*doublefunc)(0.5, 6), 3.0); + EXPECT_EQ(platform::dlsym(handle, "some_nonexisting_symbol"), nullptr); + EXPECT_EQ(platform::dlclose(handle), 0); + } } +#undef stringify +#undef mkstring +#endif TEST(Platform, guesspath) { - char buf[256]; - FILE *fp = fopen("test_guesspath.txt", "w"); + char buf[256]; + FILE *fp = fopen("test_guesspath.txt", "w"); #if defined(__linux__) || defined(__APPLE__) || defined(_WIN32) - const char *path = platform::guesspath(fp, buf, sizeof(buf)); - ASSERT_THAT(path, EndsWith("test_guesspath.txt")); + const char *path = platform::guesspath(fp, buf, sizeof(buf)); + ASSERT_THAT(path, EndsWith("test_guesspath.txt")); #else - const char *path = platform::guesspath(fp, buf, sizeof(buf)); - ASSERT_THAT(path, EndsWith("(unknown)")); + const char *path = platform::guesspath(fp, buf, sizeof(buf)); + ASSERT_THAT(path, EndsWith("(unknown)")); #endif - fclose(fp); - platform::unlink("test_guesspath.txt"); + fclose(fp); + platform::unlink("test_guesspath.txt"); } TEST(Platform, unlink) { - const char test[] = "12345678901234567890"; - platform::unlink("unlink.dat"); - ASSERT_EQ(platform::unlink("dummy.dat"), -1); - FILE *fp = fopen("unlink.dat", "w"); - fwrite(test, sizeof(test), 1, fp); - fclose(fp); - ASSERT_EQ(platform::unlink("unlink.dat"), 0); - ASSERT_EQ(platform::unlink("unlink.dat"), -1); - fp = fopen("unlink.dat", "r"); - ASSERT_EQ(fp, nullptr); + const char test[] = "12345678901234567890"; + platform::unlink("unlink.dat"); + ASSERT_EQ(platform::unlink("dummy.dat"), -1); + FILE *fp = fopen("unlink.dat", "w"); + fwrite(test, sizeof(test), 1, fp); + fclose(fp); + ASSERT_EQ(platform::unlink("unlink.dat"), 0); + ASSERT_EQ(platform::unlink("unlink.dat"), -1); + fp = fopen("unlink.dat", "r"); + ASSERT_EQ(fp, nullptr); - platform::mkdir("unlink.dir"); - ASSERT_EQ(platform::unlink("unlink.dir"), -1); - platform::rmdir("unlink.dir"); + platform::mkdir("unlink.dir"); + ASSERT_EQ(platform::unlink("unlink.dir"), -1); + platform::rmdir("unlink.dir"); } TEST(Platform, fseek_ftell) { - const char test[] = "12345678901234567890"; - platform::unlink("seek_tell.dat"); - FILE *fp = fopen("seek_tell.dat", "w"); - fwrite(test, sizeof(test), 1, fp); - fflush(fp); - ASSERT_EQ(platform::ftell(fp), sizeof(test)); - fclose(fp); - fp = fopen("seek_tell.dat", "r+"); - ASSERT_EQ(fgetc(fp), '1'); - ASSERT_EQ(fgetc(fp), '2'); - ASSERT_EQ(platform::ftell(fp), 2); - ASSERT_EQ(platform::fseek(fp, 15), 0); - ASSERT_EQ(fgetc(fp), '6'); - fflush(fp); - fseek(fp, -1, SEEK_END); - ASSERT_EQ(fgetc(fp), 0); - ASSERT_EQ(platform::ftell(fp), 21); - fclose(fp); - platform::unlink("seek_tell.dat"); + const char test[] = "12345678901234567890"; + platform::unlink("seek_tell.dat"); + FILE *fp = fopen("seek_tell.dat", "w"); + fwrite(test, sizeof(test), 1, fp); + fflush(fp); + ASSERT_EQ(platform::ftell(fp), sizeof(test)); + fclose(fp); + fp = fopen("seek_tell.dat", "r+"); + ASSERT_EQ(fgetc(fp), '1'); + ASSERT_EQ(fgetc(fp), '2'); + ASSERT_EQ(platform::ftell(fp), 2); + ASSERT_EQ(platform::fseek(fp, 15), 0); + ASSERT_EQ(fgetc(fp), '6'); + fflush(fp); + fseek(fp, -1, SEEK_END); + ASSERT_EQ(fgetc(fp), 0); + ASSERT_EQ(platform::ftell(fp), 21); + fclose(fp); + platform::unlink("seek_tell.dat"); } TEST(Platform, ftruncate) { - platform::unlink("truncate.dat"); - FILE *fp = fopen("truncate.dat", "w"); - fputs("header one\n", fp); - fputs("header two\n", fp); - fflush(fp); - bigint filepos = platform::ftell(fp); - fputs("line one\n", fp); - fputs("line two\n", fp); - fputs("line three\n", fp); - fflush(fp); - ASSERT_EQ(platform::ftruncate(fp, filepos), 0); - fputs("line four\n", fp); - ASSERT_GT(platform::ftell(fp), filepos); - fputs("line five\n", fp); - fflush(fp); - fclose(fp); + platform::unlink("truncate.dat"); + FILE *fp = fopen("truncate.dat", "w"); + fputs("header one\n", fp); + fputs("header two\n", fp); + fflush(fp); + bigint filepos = platform::ftell(fp); + fputs("line one\n", fp); + fputs("line two\n", fp); + fputs("line three\n", fp); + fflush(fp); + ASSERT_EQ(platform::ftruncate(fp, filepos), 0); + fputs("line four\n", fp); + ASSERT_GT(platform::ftell(fp), filepos); + fputs("line five\n", fp); + fflush(fp); + fclose(fp); - // check file - fp = fopen("truncate.dat", "r"); - char buf[128]; - char *ptr = fgets(buf, 127, fp); - ASSERT_THAT(ptr, StartsWith("header one")); - ptr = fgets(buf, 127, fp); - ASSERT_THAT(ptr, StartsWith("header two")); - ptr = fgets(buf, 127, fp); - ASSERT_THAT(ptr, StartsWith("line four")); - ptr = fgets(buf, 127, fp); - ASSERT_THAT(ptr, StartsWith("line five")); - ptr = fgets(buf, 127, fp); - ASSERT_EQ(ptr, nullptr); - fclose(fp); - platform::unlink("truncate.dat"); + // check file + fp = fopen("truncate.dat", "r"); + char buf[128]; + char *ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("header one")); + ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("header two")); + ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("line four")); + ptr = fgets(buf, 127, fp); + ASSERT_THAT(ptr, StartsWith("line five")); + ptr = fgets(buf, 127, fp); + ASSERT_EQ(ptr, nullptr); + fclose(fp); + platform::unlink("truncate.dat"); } TEST(Platform, path_basename) { #if defined(_WIN32) - ASSERT_THAT(platform::path_basename("c:\\parent\\folder\\filename"), Eq("filename")); - ASSERT_THAT(platform::path_basename("folder\\"), Eq("")); - ASSERT_THAT(platform::path_basename("c:/parent/folder/filename"), Eq("filename")); + ASSERT_THAT(platform::path_basename("c:\\parent\\folder\\filename"), Eq("filename")); + ASSERT_THAT(platform::path_basename("folder\\"), Eq("")); + ASSERT_THAT(platform::path_basename("c:/parent/folder/filename"), Eq("filename")); #else - ASSERT_THAT(platform::path_basename("/parent/folder/filename"), Eq("filename")); - ASSERT_THAT(platform::path_basename("/parent/folder/"), Eq("")); + ASSERT_THAT(platform::path_basename("/parent/folder/filename"), Eq("filename")); + ASSERT_THAT(platform::path_basename("/parent/folder/"), Eq("")); #endif } TEST(Platform, path_dirname) { #if defined(_WIN32) - ASSERT_THAT(platform::path_dirname("c:/parent/folder/filename"), Eq("c:/parent/folder")); - ASSERT_THAT(platform::path_dirname("c:\\parent\\folder\\filename"), Eq("c:\\parent\\folder")); - ASSERT_THAT(platform::path_dirname("c:filename"), Eq(".")); + ASSERT_THAT(platform::path_dirname("c:/parent/folder/filename"), Eq("c:/parent/folder")); + ASSERT_THAT(platform::path_dirname("c:\\parent\\folder\\filename"), Eq("c:\\parent\\folder")); + ASSERT_THAT(platform::path_dirname("c:filename"), Eq(".")); #else - ASSERT_THAT(platform::path_dirname("/parent/folder/filename"), Eq("/parent/folder")); + ASSERT_THAT(platform::path_dirname("/parent/folder/filename"), Eq("/parent/folder")); #endif - ASSERT_THAT(platform::path_dirname("filename"), Eq(".")); + ASSERT_THAT(platform::path_dirname("filename"), Eq(".")); } TEST(Platform, path_join) { #if defined(_WIN32) - ASSERT_THAT(platform::path_join("c:\\folder", "filename"), Eq("c:\\folder\\filename")); - ASSERT_THAT(platform::path_join("c:\\folder\\", "filename"), Eq("c:\\folder\\filename")); - ASSERT_THAT(platform::path_join("c:\\folder", "\\filename"), Eq("c:\\folder\\filename")); - ASSERT_THAT(platform::path_join("c:\\folder\\", "\\filename"), Eq("c:\\folder\\filename")); - ASSERT_THAT(platform::path_join("c:\\folder", "/filename"), Eq("c:\\folder\\filename")); - ASSERT_THAT(platform::path_join("c:\\folder\\\\", "\\filename"), Eq("c:\\folder\\filename")); - ASSERT_THAT(platform::path_join("c:\\folder\\", "\\\\filename"), Eq("c:\\folder\\filename")); - ASSERT_THAT(platform::path_join("c:\\folder/\\", "/\\filename"), Eq("c:\\folder\\filename")); - ASSERT_THAT(platform::path_join("c:\\folder\\/", "\\/filename"), Eq("c:\\folder\\filename")); - ASSERT_THAT(platform::path_join("c:\\folder", ""), Eq("c:\\folder")); - ASSERT_THAT(platform::path_join("", "\\/filename"), Eq("\\/filename")); + ASSERT_THAT(platform::path_join("c:\\folder", "filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\", "filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder", "\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\", "\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder", "/filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\\\", "\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\", "\\\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder/\\", "/\\filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder\\/", "\\/filename"), Eq("c:\\folder\\filename")); + ASSERT_THAT(platform::path_join("c:\\folder", ""), Eq("c:\\folder")); + ASSERT_THAT(platform::path_join("", "\\/filename"), Eq("\\/filename")); #else - ASSERT_THAT(platform::path_join("/parent/folder", "filename"), Eq("/parent/folder/filename")); - ASSERT_THAT(platform::path_join("/parent/folder/", "filename"), Eq("/parent/folder/filename")); - ASSERT_THAT(platform::path_join("/parent/folder", "/filename"), Eq("/parent/folder/filename")); - ASSERT_THAT(platform::path_join("/parent/folder/", "/filename"), Eq("/parent/folder/filename")); - ASSERT_THAT(platform::path_join("/parent/folder//", "filename"), Eq("/parent/folder/filename")); - ASSERT_THAT(platform::path_join("/parent/folder", "//filename"), Eq("/parent/folder/filename")); - ASSERT_THAT(platform::path_join("/parent/folder///", "/filename"), Eq("/parent/folder/filename")); - ASSERT_THAT(platform::path_join("/parent/folder/", "///filename"), Eq("/parent/folder/filename")); - ASSERT_THAT(platform::path_join("/parent/folder/", ""), Eq("/parent/folder/")); - ASSERT_THAT(platform::path_join("", "\\/filename"), Eq("\\/filename")); + ASSERT_THAT(platform::path_join("/parent/folder", "filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", "filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder", "/filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", "/filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder//", "filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder", "//filename"), Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder///", "/filename"), + Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", "///filename"), + Eq("/parent/folder/filename")); + ASSERT_THAT(platform::path_join("/parent/folder/", ""), Eq("/parent/folder/")); + ASSERT_THAT(platform::path_join("", "\\/filename"), Eq("\\/filename")); #endif } TEST(Platform, is_console) { - platform::unlink("file_is_no_console.txt"); - FILE *fp = fopen("file_is_no_console.txt", "w"); - fputs("some text\n", fp); - EXPECT_FALSE(platform::is_console(fp)); - fclose(fp); - platform::unlink("file_is_no_console.txt"); + platform::unlink("file_is_no_console.txt"); + FILE *fp = fopen("file_is_no_console.txt", "w"); + fputs("some text\n", fp); + EXPECT_FALSE(platform::is_console(fp)); + fclose(fp); + platform::unlink("file_is_no_console.txt"); } TEST(Platform, path_and_directory) { - platform::unlink("path_is_directory"); - platform::rmdir("path_is_directory"); - platform::unlink("path_is_file"); - platform::mkdir("path_is_directory"); - FILE *fp = fopen("path_is_file", "w"); - fputs("some text\n", fp); - fclose(fp); + platform::unlink("path_is_directory"); + platform::rmdir("path_is_directory"); + platform::unlink("path_is_file"); + platform::mkdir("path_is_directory"); + FILE *fp = fopen("path_is_file", "w"); + fputs("some text\n", fp); + fclose(fp); - ASSERT_TRUE(platform::path_is_directory("path_is_directory")); - ASSERT_FALSE(platform::path_is_directory("path_is_file")); - ASSERT_FALSE(platform::path_is_directory("path_does_not_exist")); - platform::unlink("path_is_file"); + ASSERT_TRUE(platform::path_is_directory("path_is_directory")); + ASSERT_FALSE(platform::path_is_directory("path_is_file")); + ASSERT_FALSE(platform::path_is_directory("path_does_not_exist")); + platform::unlink("path_is_file"); #if defined(_WIN32) - fp = fopen("path_is_directory\\path_is_file", "w"); + fp = fopen("path_is_directory\\path_is_file", "w"); #else - fp = fopen("path_is_directory/path_is_file", "w"); + fp = fopen("path_is_directory/path_is_file", "w"); #endif - fputs("some text\n", fp); - fclose(fp); + fputs("some text\n", fp); + fclose(fp); #if defined(_WIN32) - platform::mkdir("path_is_directory\\path_is_directory"); - fp = fopen("path_is_directory\\path_is_other_file", "w"); + platform::mkdir("path_is_directory\\path_is_directory"); + fp = fopen("path_is_directory\\path_is_other_file", "w"); #else - platform::mkdir("path_is_directory/path_is_directory"); - fp = fopen("path_is_directory/path_is_other_file", "w"); + platform::mkdir("path_is_directory/path_is_directory"); + fp = fopen("path_is_directory/path_is_other_file", "w"); #endif - fputs("some text\n", fp); - fclose(fp); - auto dirs = platform::list_directory("path_is_directory"); - ASSERT_EQ(dirs.size(), 3); - platform::rmdir("path_is_directory"); - ASSERT_FALSE(platform::path_is_directory("path_is_directory")); + fputs("some text\n", fp); + fclose(fp); + auto dirs = platform::list_directory("path_is_directory"); + ASSERT_EQ(dirs.size(), 3); + platform::rmdir("path_is_directory"); + ASSERT_FALSE(platform::path_is_directory("path_is_directory")); } TEST(Platform, get_change_directory) { - platform::unlink("working_directory"); - platform::rmdir("working_directory"); + platform::unlink("working_directory"); + platform::rmdir("working_directory"); - auto cwd = platform::current_directory(); - ASSERT_GT(cwd.size(), 0); + auto cwd = platform::current_directory(); + ASSERT_GT(cwd.size(), 0); - platform::mkdir("working_directory"); - ASSERT_EQ(platform::chdir("working_directory"), 0); - ASSERT_THAT(platform::current_directory(), EndsWith("working_directory")); + platform::mkdir("working_directory"); + ASSERT_EQ(platform::chdir("working_directory"), 0); + ASSERT_THAT(platform::current_directory(), EndsWith("working_directory")); - ASSERT_EQ(platform::chdir(".."), 0); - ASSERT_THAT(platform::current_directory(), StrEq(cwd)); - platform::rmdir("working_directory"); + ASSERT_EQ(platform::chdir(".."), 0); + ASSERT_THAT(platform::current_directory(), StrEq(cwd)); + platform::rmdir("working_directory"); } TEST(Platform, file_is_readable) { - platform::unlink("file_is_readable.txt"); - FILE *fp = fopen("file_is_readable.txt", "w"); - fputs("some text\n", fp); - fclose(fp); + platform::unlink("file_is_readable.txt"); + FILE *fp = fopen("file_is_readable.txt", "w"); + fputs("some text\n", fp); + fclose(fp); - ASSERT_TRUE(platform::file_is_readable("file_is_readable.txt")); - ASSERT_FALSE(platform::file_is_readable("file_does_not_exist.txt")); - platform::unlink("file_is_readable.txt"); + ASSERT_TRUE(platform::file_is_readable("file_is_readable.txt")); + ASSERT_FALSE(platform::file_is_readable("file_does_not_exist.txt")); + platform::unlink("file_is_readable.txt"); - // windows does not have permission flags + // windows does not have permission flags #if !defined(_WIN32) - platform::unlink("file_is_not_readable.txt"); - fp = fopen("file_is_not_readable.txt", "w"); - fputs("some text\n", fp); - fclose(fp); - chmod("file_is_not_readable.txt", 0); - ASSERT_FALSE(platform::file_is_readable("file_is_not_readable.txt")); - platform::unlink("file_is_not_readable.txt"); + platform::unlink("file_is_not_readable.txt"); + fp = fopen("file_is_not_readable.txt", "w"); + fputs("some text\n", fp); + fclose(fp); + chmod("file_is_not_readable.txt", 0); + ASSERT_FALSE(platform::file_is_readable("file_is_not_readable.txt")); + platform::unlink("file_is_not_readable.txt"); #endif } TEST(Platform, has_zip_extension) { - ASSERT_FALSE(platform::has_zip_extension("dummy")); - ASSERT_FALSE(platform::has_zip_extension("dum.my")); - ASSERT_TRUE(platform::has_zip_extension("dummy.gz")); - ASSERT_TRUE(platform::has_zip_extension("dummy.bz2")); - ASSERT_TRUE(platform::has_zip_extension("dummy.zstd")); - ASSERT_TRUE(platform::has_zip_extension("dummy.xz")); - ASSERT_TRUE(platform::has_zip_extension("dummy.lzma")); - ASSERT_TRUE(platform::has_zip_extension("dummy.lz4")); + ASSERT_FALSE(platform::has_zip_extension("dummy")); + ASSERT_FALSE(platform::has_zip_extension("dum.my")); + ASSERT_TRUE(platform::has_zip_extension("dummy.gz")); + ASSERT_TRUE(platform::has_zip_extension("dummy.bz2")); + ASSERT_TRUE(platform::has_zip_extension("dummy.zstd")); + ASSERT_TRUE(platform::has_zip_extension("dummy.xz")); + ASSERT_TRUE(platform::has_zip_extension("dummy.lzma")); + ASSERT_TRUE(platform::has_zip_extension("dummy.lz4")); } TEST(Platform, zip_read_write) { - const std::vector test_files = {"zip_test.zip", "zip_test.gz", "zip_test.bz2", - "zip_test.zstd", "zip_test.xz", "zip_test.lzma", - "zip_test.lz4", "zip_test.unk", "zip test.gz"}; - for (const auto &file : test_files) { - platform::unlink(file); - FILE *fp = platform::zip_write(file); - if (!fp) { - platform::unlink(file); - continue; + const std::vector test_files = {"zip_test.zip", "zip_test.gz", "zip_test.bz2", + "zip_test.zstd", "zip_test.xz", "zip_test.lzma", + "zip_test.lz4", "zip_test.unk", "zip test.gz"}; + for (const auto &file : test_files) { + platform::unlink(file); + FILE *fp = platform::zip_write(file); + if (!fp) { + platform::unlink(file); + continue; + } + + clearerr(fp); + fputs("line one\n", fp); + fputs("line two\n", fp); + ASSERT_EQ(ferror(fp), 0); + fflush(fp); + platform::pclose(fp); + + fp = platform::zip_read(file); + ASSERT_NE(fp, nullptr); + char buf[128]; + char *ptr = fgets(buf, 128, fp); + EXPECT_THAT(ptr, StartsWith("line one")); + ptr = fgets(buf, 128, fp); + EXPECT_THAT(ptr, StartsWith("line two")); + ASSERT_EQ(ferror(fp), 0); + platform::pclose(fp); + platform::unlink(file); } - - clearerr(fp); - fputs("line one\n", fp); - fputs("line two\n", fp); - ASSERT_EQ(ferror(fp), 0); - fflush(fp); - platform::pclose(fp); - - fp = platform::zip_read(file); - ASSERT_NE(fp, nullptr); - char buf[128]; - char *ptr = fgets(buf, 128, fp); - EXPECT_THAT(ptr, StartsWith("line one")); - ptr = fgets(buf, 128, fp); - EXPECT_THAT(ptr, StartsWith("line two")); - ASSERT_EQ(ferror(fp), 0); - platform::pclose(fp); - platform::unlink(file); - } } From 37bfe3d0cef97940023933b811334dda7ef6d454 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 2 Oct 2021 15:50:58 -0400 Subject: [PATCH 03/84] integrate platform sub-namespace into source code and documentation this updates function calls to functions that have been moved from the utils namepsace or the Info class to platform:: --- doc/doxygen/Doxyfile.in | 2 + doc/src/Developer.rst | 1 + doc/src/Developer_platform.rst | 140 ++++++++++++ doc/src/Developer_utils.rst | 19 +- doc/src/Howto_thermostat.rst | 2 +- doc/utils/sphinx-config/false_positives.txt | 3 + src/NETCDF/dump_netcdf.cpp | 2 +- src/NETCDF/dump_netcdf_mpiio.cpp | 2 +- src/bond.cpp | 2 +- src/info.cpp | 200 +----------------- src/info.h | 7 - src/lammps.cpp | 8 +- src/library.cpp | 6 +- src/pair.cpp | 2 +- src/platform.cpp | 8 +- src/platform.h | 10 +- src/pointers.h | 1 + src/read_data.cpp | 2 +- src/read_restart.cpp | 6 +- src/utils.cpp | 119 +---------- src/utils.h | 43 ---- tools/lammps-shell/lammps-shell.cpp | 5 +- unittest/commands/test_groups.cpp | 2 +- unittest/commands/test_kim_commands.cpp | 2 +- unittest/commands/test_lattice_region.cpp | 3 +- unittest/commands/test_reset_ids.cpp | 2 +- unittest/commands/test_simple_commands.cpp | 5 +- unittest/commands/test_variables.cpp | 2 +- unittest/cplusplus/test_error_class.cpp | 2 +- unittest/cplusplus/test_lammps_class.cpp | 2 +- unittest/formats/test_file_operations.cpp | 2 +- unittest/formats/test_molecule_file.cpp | 3 +- .../formats/test_potential_file_reader.cpp | 2 +- unittest/formats/test_text_file_reader.cpp | 2 +- unittest/testing/core.h | 3 +- unittest/utils/test_utils.cpp | 58 +---- 36 files changed, 207 insertions(+), 473 deletions(-) create mode 100644 doc/src/Developer_platform.rst diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in index 49a271355f..d454898f4e 100644 --- a/doc/doxygen/Doxyfile.in +++ b/doc/doxygen/Doxyfile.in @@ -435,6 +435,8 @@ INPUT = @LAMMPS_SOURCE_DIR@/utils.cpp \ @LAMMPS_SOURCE_DIR@/my_pool_chunk.cpp \ @LAMMPS_SOURCE_DIR@/my_pool_chunk.h \ @LAMMPS_SOURCE_DIR@/math_eigen.h \ + @LAMMPS_SOURCE_DIR@/platform.h \ + @LAMMPS_SOURCE_DIR@/platform.cpp \ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded diff --git a/doc/src/Developer.rst b/doc/src/Developer.rst index f68007486d..fd4a44a8a0 100644 --- a/doc/src/Developer.rst +++ b/doc/src/Developer.rst @@ -18,4 +18,5 @@ of time and requests from the LAMMPS user community. Developer_plugins Developer_unittest Classes + Developer_platform Developer_utils diff --git a/doc/src/Developer_platform.rst b/doc/src/Developer_platform.rst new file mode 100644 index 0000000000..dc482cb27a --- /dev/null +++ b/doc/src/Developer_platform.rst @@ -0,0 +1,140 @@ +Platform abstraction functions +------------------------------ + +The ``platform`` sub-namespace inside the ``LAMMPS_NS`` namespace +provides a collection of wrapper and convenience functions and utilities +that perform common tasks for which platform specific code would be +required or for which a more high-level abstraction would be convenient +and reduce duplicated code. This reduces redundant implementations and +encourages consistent behavior and thus has some overlap with the +:doc:`"utils" sub-namespace `. + +Time functions +^^^^^^^^^^^^^^ + +.. doxygenfunction:: cputime + :project: progguide + +.. doxygenfunction:: walltime + :project: progguide + +Platform information functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: os_info + :project: progguide + +.. doxygenfunction:: compiler_info + :project: progguide + +.. doxygenfunction:: cxx_standard + :project: progguide + +.. doxygenfunction:: openmp_standard + :project: progguide + +.. doxygenfunction:: mpi_vendor + :project: progguide + +.. doxygenfunction:: mpi_info + :project: progguide + + +File and path functions and global constants +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenvariable:: filepathsep + :project: progguide + +.. doxygenvariable:: pathvarsep + :project: progguide + +.. doxygenfunction:: guesspath + :project: progguide + +.. doxygenfunction:: path_basename + :project: progguide + +.. doxygenfunction:: path_join + :project: progguide + +.. doxygenfunction:: file_is_readable + :project: progguide + +.. doxygenfunction:: is_console + :project: progguide + +.. doxygenfunction:: path_is_directory + :project: progguide + +.. doxygenfunction:: current_directory + :project: progguide + +.. doxygenfunction:: list_directory + :project: progguide + +.. doxygenfunction:: chdir + :project: progguide + +.. doxygenfunction:: mkdir + :project: progguide + +.. doxygenfunction:: rmdir + :project: progguide + +.. doxygenfunction:: unlink + :project: progguide + +Standard I/O function wrappers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: ftell + :project: progguide + +.. doxygenfunction:: fseek + :project: progguide + +.. doxygenfunction:: ftruncate + :project: progguide + +.. doxygenfunction:: popen + :project: progguide + +.. doxygenfunction:: pclose + :project: progguide + +Environment variable functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: putenv + :project: progguide + +.. doxygenfunction:: list_pathenv + :project: progguide + +.. doxygenfunction:: find_exe_path + :project: progguide + +Dynamically loaded object or library functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: dlopen + :project: progguide + +.. doxygenfunction:: dlclose + :project: progguide + +.. doxygenfunction:: dlsym + :project: progguide + +Compressed file I/O functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. doxygenfunction:: has_zip_extension + :project: progguide + +.. doxygenfunction:: zip_read + :project: progguide + +.. doxygenfunction:: zip_write + :project: progguide diff --git a/doc/src/Developer_utils.rst b/doc/src/Developer_utils.rst index 041fce60b0..3cf059594b 100644 --- a/doc/src/Developer_utils.rst +++ b/doc/src/Developer_utils.rst @@ -7,7 +7,9 @@ a collection of convenience functions and utilities that perform common tasks that are required repeatedly throughout the LAMMPS code like reading or writing to files with error checking or translation of strings into specific types of numbers with checking for validity. This -reduces redundant implementations and encourages consistent behavior. +reduces redundant implementations and encourages consistent behavior and +thus has some overlap with the :doc:`"platform" sub-namespace +`. I/O with status check and similar functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,21 +145,6 @@ and parsing files or arguments. .. doxygenfunction:: is_double :project: progguide -File and path functions -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. doxygenfunction:: guesspath - :project: progguide - -.. doxygenfunction:: path_basename - :project: progguide - -.. doxygenfunction:: path_join - :project: progguide - -.. doxygenfunction:: file_is_readable - :project: progguide - Potential file functions ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/src/Howto_thermostat.rst b/doc/src/Howto_thermostat.rst index 249af54b6e..fe53fff540 100644 --- a/doc/src/Howto_thermostat.rst +++ b/doc/src/Howto_thermostat.rst @@ -57,7 +57,7 @@ velocities. See the doc pages for the individual fixes and for the assign a temperature compute to a thermostatting fix. For example, you can apply a thermostat only to atoms in a spatial -region by using it in conjuction with :doc:`compute temp/region +region by using it in conjunction with :doc:`compute temp/region `. Or you can apply a thermostat to only the x and z components of velocity by using it with :doc:`compute temp/partial `. Of you could thermostat only diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 5f64a4229c..76127104e0 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -1135,6 +1135,7 @@ Germann Germano gerolf Gerolf +getrusage Gershgorin getter gettimeofday @@ -1809,6 +1810,7 @@ lyon Lysogorskiy Lyulin lz +lzma Maaravi MACHDYN machdyn @@ -2762,6 +2764,7 @@ REAXFF ReaxFF reaxff rebo +recurse recursing Ree refactored diff --git a/src/NETCDF/dump_netcdf.cpp b/src/NETCDF/dump_netcdf.cpp index 5702c94499..b0bf57a41c 100644 --- a/src/NETCDF/dump_netcdf.cpp +++ b/src/NETCDF/dump_netcdf.cpp @@ -274,7 +274,7 @@ void DumpNetCDF::openfile() if (append_flag && !multifile) { // Fixme! Perform checks if dimensions and variables conform with // data structure standard. - if (not utils::file_is_readable(filecurrent)) + if (not platform::file_is_readable(filecurrent)) error->all(FLERR, "cannot append to non-existent file {}",filecurrent); if (singlefile_opened) return; diff --git a/src/NETCDF/dump_netcdf_mpiio.cpp b/src/NETCDF/dump_netcdf_mpiio.cpp index a6c3c535c9..b14cef4f68 100644 --- a/src/NETCDF/dump_netcdf_mpiio.cpp +++ b/src/NETCDF/dump_netcdf_mpiio.cpp @@ -272,7 +272,7 @@ void DumpNetCDFMPIIO::openfile() if (append_flag && !multifile) { // Fixme! Perform checks if dimensions and variables conform with // data structure standard. - if (not utils::file_is_readable(filecurrent)) + if (not platform::file_is_readable(filecurrent)) error->all(FLERR, "cannot append to non-existent file {}", filecurrent); MPI_Offset index[NC_MAX_VAR_DIMS], count[NC_MAX_VAR_DIMS]; diff --git a/src/bond.cpp b/src/bond.cpp index e636ae9bf8..fb313f0170 100644 --- a/src/bond.cpp +++ b/src/bond.cpp @@ -270,7 +270,7 @@ void Bond::write_file(int narg, char **arg) // write out a line with "DATE:" and "UNITS:" tags // - if the file already exists, print a message about appending // while printing the date and check that units are consistent. - if (utils::file_is_readable(table_file)) { + if (platform::file_is_readable(table_file)) { std::string units = utils::get_potential_units(table_file,"table"); if (!units.empty() && (units != update->unit_style)) { error->one(FLERR,"Trying to append to a table file with UNITS: {} while units are {}", diff --git a/src/info.cpp b/src/info.cpp index 137bf44b1a..340ba15b0f 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -282,7 +282,7 @@ void Info::command(int narg, char **arg) fmt::print(out,"Git info: {} / {} / {}\n", lmp->git_branch, lmp->git_descriptor,lmp->git_commit); - fmt::print(out,"\nOS information: {}\n\n",get_os_info()); + fmt::print(out,"\nOS information: {}\n\n",platform::os_info()); fmt::print(out,"sizeof(smallint): {}-bit\n" "sizeof(imageint): {}-bit\n" @@ -292,7 +292,7 @@ void Info::command(int narg, char **arg) sizeof(tagint)*8, sizeof(bigint)*8); fmt::print(out,"\nCompiler: {} with {}\nC++ standard: {}\n", - get_compiler_info(),get_openmp_info(),get_cxx_info()); + platform::compiler_info(),platform::openmp_standard(),platform::cxx_standard()); fputs("\nActive compile time flags:\n\n",out); if (has_gzip_support()) fputs("-DLAMMPS_GZIP\n",out); @@ -353,7 +353,7 @@ void Info::command(int narg, char **arg) if (flags & COMM) { int major,minor; - std::string version = get_mpi_info(major,minor); + std::string version = platform::mpi_info(major,minor); fmt::print(out,"\nCommunication information:\n" "MPI library level: MPI v{}.{}\n" @@ -1266,200 +1266,6 @@ bool Info::has_accelerator_feature(const std::string &package, return false; } -/* ---------------------------------------------------------------------- */ -#define _INFOBUF_SIZE 256 - -std::string Info::get_os_info() -{ - std::string buf; - -#if defined(_WIN32) - DWORD fullversion,majorv,minorv,buildv=0; - - fullversion = GetVersion(); - majorv = (DWORD) (LOBYTE(LOWORD(fullversion))); - minorv = (DWORD) (HIBYTE(LOWORD(fullversion))); - if (fullversion < 0x80000000) - buildv = (DWORD) (HIWORD(fullversion)); - - buf = fmt::format("Windows {}.{} ({}) on ",majorv,minorv,buildv); - - SYSTEM_INFO si; - GetSystemInfo(&si); - - switch (si.wProcessorArchitecture) { - case PROCESSOR_ARCHITECTURE_AMD64: - buf += "x86_64"; - break; - case PROCESSOR_ARCHITECTURE_ARM: - buf += "arm"; - break; - case PROCESSOR_ARCHITECTURE_IA64: - buf += "ia64"; - break; - case PROCESSOR_ARCHITECTURE_INTEL: - buf += "i386"; - break; - default: - buf += "(unknown)"; - } -#else - struct utsname ut; - uname(&ut); - - // try to get OS distribution name, if available - std::string distro = ut.sysname; - if (utils::file_is_readable("/etc/os-release")) { - try { - TextFileReader reader("/etc/os-release",""); - while (1) { - auto words = reader.next_values(0,"="); - if ((words.count() > 1) && (words.next_string() == "PRETTY_NAME")) { - distro += " " + utils::trim(words.next_string()); - break; - } - } - } catch (std::exception &e) { - ; // EOF but keyword not found - } - } - - buf = fmt::format("{} {} on {}", distro, ut.release, ut.machine); -#endif - return buf; -} - -std::string Info::get_compiler_info() -{ - std::string buf; -#if defined(__INTEL_LLVM_COMPILER) - constexpr double version = static_cast(__INTEL_LLVM_COMPILER)*0.01; - buf = fmt::format("Intel LLVM C++ {:.1f} / {}", version, __VERSION__); -#elif defined(__ibmxl__) - buf = fmt::format("IBM XL C/C++ (Clang) {}.{}.{}", - __ibmxl_version__, __ibmxl_release__, __ibmxl_modification__); -#elif defined(__clang__) - buf = fmt::format("Clang C++ {}", __VERSION__); -#elif defined(__PGI) - buf = fmt::format("PGI C++ {}.{}",__PGIC__, __PGIC_MINOR__); -#elif defined(__INTEL_COMPILER) - double version = static_cast(__INTEL_COMPILER)*0.01; - buf = fmt::format("Intel Classic C++ {:.2f}.{} / {}", version, - __INTEL_COMPILER_UPDATE, __VERSION__); -#elif defined(__MINGW64__) - buf = fmt::format("MinGW-w64 64bit {}.{} / GNU C++ {}", __MINGW64_VERSION_MAJOR, - __MINGW64_VERSION_MINOR, __VERSION__); -#elif defined(__MINGW32__) - buf = fmt::format("MinGW-w64 32bit {}.{} / GNU C++ {}", __MINGW32_MAJOR_VERSION, - __MINGW32_MINOR_VERSION, __VERSION__); -#elif defined(__GNUC__) - buf = fmt::format("GNU C++ {}", __VERSION__); -#elif defined(_MSC_VER) && (_MSC_VER > 1920) && (_MSC_VER < 2000) - constexpr int major = _MSC_VER / 100; - constexpr int minor = _MSC_VER - major *100; - buf = fmt::format("Microsoft Visual Studio 20{}, C/C++ {}.{}", major, major-5, minor); -#else - buf = "(Unknown)"; -#endif - return buf; -} - -std::string Info::get_openmp_info() -{ - -#if !defined(_OPENMP) - return "OpenMP not enabled"; -#else - -// Supported OpenMP version corresponds to the release date of the -// specifications as posted at https://www.openmp.org/specifications/ - -#if _OPENMP > 202011 - return "OpenMP newer than version 5.1"; -#elif _OPENMP == 202011 - return "OpenMP 5.1"; -#elif _OPENMP == 201811 - return "OpenMP 5.0"; -#elif _OPENMP == 201611 - return "OpenMP 5.0 preview 1"; -#elif _OPENMP == 201511 - return "OpenMP 4.5"; -#elif _OPENMP == 201307 - return "OpenMP 4.0"; -#elif _OPENMP == 201107 - return "OpenMP 3.1"; -#elif _OPENMP == 200805 - return "OpenMP 3.0"; -#elif _OPENMP == 200505 - return "OpenMP 2.5"; -#elif _OPENMP == 200203 - return "OpenMP 2.0"; -#else - return "unknown OpenMP version"; -#endif - -#endif -} - -std::string Info::get_mpi_vendor() { - #if defined(MPI_STUBS) - return "MPI STUBS"; - #elif defined(OPEN_MPI) - return "Open MPI"; - #elif defined(MPICH_NAME) - return "MPICH"; - #elif defined(I_MPI_VERSION) - return "Intel MPI"; - #elif defined(PLATFORM_MPI) - return "Platform MPI"; - #elif defined(HP_MPI) - return "HP MPI"; - #elif defined(MSMPI_VER) - return "Microsoft MPI"; - #else - return "Unknown MPI implementation"; - #endif -} - -std::string Info::get_mpi_info(int &major, int &minor) -{ - int len; -#if (defined(MPI_VERSION) && (MPI_VERSION > 2)) || defined(MPI_STUBS) - static char version[MPI_MAX_LIBRARY_VERSION_STRING]; - MPI_Get_library_version(version,&len); -#else - static char version[32]; - strcpy(version,get_mpi_vendor().c_str()); - len = strlen(version); -#endif - - MPI_Get_version(&major,&minor); - if (len > 80) { - char *ptr = strchr(version+80,'\n'); - if (ptr) *ptr = '\0'; - } - return std::string(version); -} - -std::string Info::get_cxx_info() -{ -#if __cplusplus > 202002L - return "newer than C++20"; -#elif __cplusplus == 202002L - return "C++20"; -#elif __cplusplus == 201703L - return "C++17"; -#elif __cplusplus == 201402L - return "C++14"; -#elif __cplusplus == 201103L - return "C++11"; -#elif __cplusplus == 199711L - return "C++98"; -#else - return "unknown"; -#endif -} - std::string Info::get_accelerator_info(const std::string &package) { std::string mesg(""); diff --git a/src/info.h b/src/info.h index d000b3c443..0e7bfb68f3 100644 --- a/src/info.h +++ b/src/info.h @@ -48,13 +48,6 @@ class Info : public Command { const std::string &); static bool has_gpu_device(); static std::string get_gpu_device_info(); - - static std::string get_os_info(); - static std::string get_compiler_info(); - static std::string get_openmp_info(); - static std::string get_mpi_vendor(); - static std::string get_mpi_info(int &, int &); - static std::string get_cxx_info(); static std::string get_accelerator_info(const std::string &pkg = ""); void get_memory_info(double *); diff --git a/src/lammps.cpp b/src/lammps.cpp index d9bb56d882..f6c4474cd5 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -1340,14 +1340,14 @@ void LAMMPS::print_config(FILE *fp) const char *pkg; int ncword, ncline = 0; - fmt::print(fp,"OS: {}\n\n",Info::get_os_info()); + fmt::print(fp,"OS: {}\n\n",platform::os_info()); fmt::print(fp,"Compiler: {} with {}\nC++ standard: {}\n", - Info::get_compiler_info(),Info::get_openmp_info(), - Info::get_cxx_info()); + platform::compiler_info(),platform::openmp_standard(), + platform::cxx_standard()); int major,minor; - std::string infobuf = Info::get_mpi_info(major,minor); + std::string infobuf = platform::mpi_info(major,minor); fmt::print(fp,"MPI v{}.{}: {}\n\n",major,minor,infobuf); fmt::print(fp,"Accelerator configuration:\n\n{}\n", diff --git a/src/library.cpp b/src/library.cpp index 13f480ed03..bf5ea50f58 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -4394,9 +4394,9 @@ void lammps_get_os_info(char *buffer, int buf_size) { if (buf_size <=0) return; buffer[0] = buffer[buf_size-1] = '\0'; - std::string txt = Info::get_os_info() + "\n"; - txt += Info::get_compiler_info(); - txt += " with " + Info::get_openmp_info() + "\n"; + std::string txt = platform::os_info() + "\n"; + txt += platform::compiler_info(); + txt += " with " + platform::openmp_standard() + "\n"; strncpy(buffer, txt.c_str(), buf_size-1); } diff --git a/src/pair.cpp b/src/pair.cpp index 6805166150..1039875718 100644 --- a/src/pair.cpp +++ b/src/pair.cpp @@ -1799,7 +1799,7 @@ void Pair::write_file(int narg, char **arg) // write out a line with "DATE:" and "UNITS:" tags // - if the file already exists, print a message about appending // while printing the date and check that units are consistent. - if (utils::file_is_readable(table_file)) { + if (platform::file_is_readable(table_file)) { std::string units = utils::get_potential_units(table_file,"table"); if (!units.empty() && (units != update->unit_style)) { error->one(FLERR,"Trying to append to a table file " diff --git a/src/platform.cpp b/src/platform.cpp index d457f85c98..3dd08d46ce 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -224,7 +224,7 @@ std::string platform::os_info() buf = ut.sysname; #if 0 // disable until this is integrated into LAMMPS and TextFileReader becomes available - if (utils::file_is_readable("/etc/os-release")) { + if (platform::file_is_readable("/etc/os-release")) { try { TextFileReader reader("/etc/os-release",""); while (1) { @@ -275,7 +275,6 @@ std::string platform::cxx_standard() std::string platform::compiler_info() { std::string buf = "(Unknown)"; -#if 0 // disable for now untile merged into LAMMPS and fmt:: becomes available #if defined(__INTEL_LLVM_COMPILER) double version = static_cast(__INTEL_LLVM_COMPILER)*0.01; buf = fmt::format("Intel LLVM C++ {:.1f} / {}", version, __VERSION__); @@ -304,7 +303,6 @@ std::string platform::compiler_info() buf = "Microsoft Visual Studio 20" + std::to_string(major) + ", C/C++ " + std::to_string(major-5) + "." + std::to_string(minor); #else buf = "(Unknown)"; -#endif #endif return buf; } @@ -543,9 +541,9 @@ void *platform::dlsym(void *handle, const std::string &symbol) /** On Linux the folder /proc/self/fd holds symbolic links to the actual * pathnames associated with each open file descriptor of the current process. - * On macOS the same kind of information can be obtained using ``fcntl(fd,F_GETPATH,buf)``. + * On MacOS the same kind of information can be obtained using ``fcntl(fd,F_GETPATH,buf)``. * On Windows we use ``GetFinalPathNameByHandleA()`` which is available with - * Windows Vista and later. If the buffer is to small (< 16 bytes) a null pointer is returned. + * Windows Vista and later. If the buffer is too small (< 16 bytes) a null pointer is returned. * * This function is used to provide a filename with error messages in functions * where the filename is not passed as an argument, but the FILE * pointer. */ diff --git a/src/platform.h b/src/platform.h index 5aeee1545e..1c4a659570 100644 --- a/src/platform.h +++ b/src/platform.h @@ -125,7 +125,7 @@ namespace platform { * after this call * * \param handle handle to an opened shared object - * \return 0 if succesful, non-zero of not */ + * \return 0 if successful, non-zero of not */ int dlclose(void *handle); @@ -158,7 +158,7 @@ namespace platform { /*! Try to detect pathname from FILE pointer. * - * Currently only supported on Linux and macOS, otherwise will report "(unknown)". + * Currently only supported on Linux and MacOS, otherwise will report "(unknown)". * * \param fp FILE pointer struct from STDIO library for which we want to detect the name * \param buf storage buffer for pathname. output will be truncated if not large enough @@ -193,7 +193,7 @@ namespace platform { * This provides a list of strings of the entries in the directory * without the leading path name while also skipping over ".." and ".". * - * \param path path to directory + * \param dir path to directory * \return vector with strings of all directory entries */ std::vector list_directory(const std::string &dir); @@ -203,7 +203,7 @@ namespace platform { * This function will traverse the list of directories in the PATH * environment variable and look for the executable *cmd*. If the * file exists and is executable the full path is returned as string, - * otherwise and emptry string is returned. + * otherwise and empty string is returned. * * On Windows the *cmd* string must not include and extension as * this function will automatically append the extensions ".exe", @@ -268,7 +268,7 @@ namespace platform { int fseek(FILE *fp, bigint pos); - /*! Truncate file to a given length and reposition file pointer + /*! Truncate file to a given length and re-position file pointer * * \param fp FILE pointer of the given file * \param length length to which the file is being truncated to diff --git a/src/pointers.h b/src/pointers.h index 4ae50715c1..55033aae3e 100644 --- a/src/pointers.h +++ b/src/pointers.h @@ -30,6 +30,7 @@ #include "lammps.h" // IWYU pragma: export #include "utils.h" // IWYU pragma: export #include "fmt/format.h" // IWYU pragma: export +#include "platform.h" // IWYU pragma: export namespace LAMMPS_NS { diff --git a/src/read_data.cpp b/src/read_data.cpp index 574117e93e..e9b222d6ef 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -308,7 +308,7 @@ void ReadData::command(int narg, char **arg) // check if data file is available and readable - if (!utils::file_is_readable(arg[0])) + if (!platform::file_is_readable(arg[0])) error->all(FLERR,fmt::format("Cannot open file {}: {}", arg[0], utils::getsyserror())); diff --git a/src/read_restart.cpp b/src/read_restart.cpp index bbd3bd3359..dd36175a90 100644 --- a/src/read_restart.cpp +++ b/src/read_restart.cpp @@ -540,8 +540,8 @@ std::string ReadRestart::file_search(const std::string &inpfile) { // separate inpfile into dir + filename - auto dirname = utils::path_dirname(inpfile); - auto filename = utils::path_basename(inpfile); + auto dirname = platform::path_dirname(inpfile); + auto filename = platform::path_basename(inpfile); // if filename contains "%" replace "%" with "base" @@ -574,7 +574,7 @@ std::string ReadRestart::file_search(const std::string &inpfile) if (maxnum < 0) error->one(FLERR,"Found no restart file matching pattern"); filename.replace(filename.find('*'),1,std::to_string(maxnum)); } - return utils::path_join(dirname,filename); + return platform::path_join(dirname,filename); } /* ---------------------------------------------------------------------- diff --git a/src/utils.cpp b/src/utils.cpp index 2feba5db97..55514fdd59 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -165,44 +165,6 @@ std::string utils::getsyserror() return std::string(strerror(errno)); } -/** On Linux the folder /proc/self/fd holds symbolic links to the actual - * pathnames associated with each open file descriptor of the current process. - * On MacOS the same kind of information can be obtained using ``fcntl(fd,F_GETPATH,buf)``. - * On Windows we use ``GetFinalPathNameByHandleA()`` which is available with - * Windows Vista and later. - * - * This function is used to provide a filename with error messages in functions - * where the filename is not passed as an argument, but the FILE * pointer. - */ -const char *utils::guesspath(char *buf, int len, FILE *fp) -{ - memset(buf, 0, len); - -#if defined(__linux__) - int fd = fileno(fp); - // get pathname from /proc or copy (unknown) - if (readlink(fmt::format("/proc/self/fd/{}", fd).c_str(), buf, len - 1) <= 0) - strncpy(buf, "(unknown)", len - 1); -#elif defined(__APPLE__) - int fd = fileno(fp); - char filepath[PATH_MAX]; - if (fcntl(fd, F_GETPATH, filepath) != -1) - strncpy(buf, filepath, len - 1); - else - strncpy(buf, "(unknown)", len - 1); -#elif defined(_WIN32) - char filepath[MAX_PATH]; - HANDLE h = (HANDLE) _get_osfhandle(_fileno(fp)); - if (GetFinalPathNameByHandleA(h, filepath, PATH_MAX, FILE_NAME_NORMALIZED) > 0) - strncpy(buf, filepath, len - 1); - else - strncpy(buf, "(unknown)", len - 1); -#else - strncpy(buf, "(unknown)", len - 1); -#endif - return buf; -} - // read line into buffer. if line is too long keep reading until EOL or EOF // but return only the first part with a newline at the end. @@ -256,7 +218,7 @@ void utils::sfgets(const char *srcname, int srcline, char *s, int size, FILE *fp std::string errmsg; // try to figure out the file name from the file pointer - if (!filename) filename = guesspath(buf, MAXPATHLENBUF, fp); + if (!filename) filename = platform::guesspath(fp, buf, MAXPATHLENBUF); if (feof(fp)) { errmsg = "Unexpected end of file while reading file '"; @@ -285,7 +247,7 @@ void utils::sfread(const char *srcname, int srcline, void *s, size_t size, size_ std::string errmsg; // try to figure out the file name from the file pointer - if (!filename) filename = guesspath(buf, MAXPATHLENBUF, fp); + if (!filename) filename = platform::guesspath(fp, buf, MAXPATHLENBUF); if (feof(fp)) { errmsg = "Unexpected end of file while reading file '"; @@ -920,7 +882,7 @@ size_t utils::count_words(const std::string &text, const std::string &separators size_t utils::trim_and_count_words(const std::string &text, const std::string &separators) { - return utils::count_words(utils::trim_comment(text), separators); + return utils::count_words(trim_comment(text), separators); } /* ---------------------------------------------------------------------- @@ -1065,71 +1027,6 @@ bool utils::is_id(const std::string &str) return true; } -/* ---------------------------------------------------------------------- - strip off leading part of path, return just the filename -------------------------------------------------------------------------- */ - -std::string utils::path_basename(const std::string &path) -{ -#if defined(_WIN32) - size_t start = path.find_last_of("/\\"); -#else - size_t start = path.find_last_of('/'); -#endif - - if (start == std::string::npos) { - start = 0; - } else { - start += 1; - } - - return path.substr(start); -} - -/* ---------------------------------------------------------------------- - Return only the leading part of a path, return just the directory -------------------------------------------------------------------------- */ - -std::string utils::path_dirname(const std::string &path) -{ -#if defined(_WIN32) - size_t start = path.find_last_of("/\\"); -#else - size_t start = path.find_last_of('/'); -#endif - - if (start == std::string::npos) return "."; - - return path.substr(0, start); -} - -/* ---------------------------------------------------------------------- - join two paths -------------------------------------------------------------------------- */ - -std::string utils::path_join(const std::string &a, const std::string &b) -{ -#if defined(_WIN32) - return fmt::format("{}\\{}", a, b); -#else - return fmt::format("{}/{}", a, b); -#endif -} - -/* ---------------------------------------------------------------------- - try to open file for reading -------------------------------------------------------------------------- */ - -bool utils::file_is_readable(const std::string &path) -{ - FILE *fp = fopen(path.c_str(), "r"); - if (fp) { - fclose(fp); - return true; - } - return false; -} - /* ---------------------------------------------------------------------- try to find potential file as specified by name search current directory and the LAMMPS_POTENTIALS directory if @@ -1139,9 +1036,9 @@ bool utils::file_is_readable(const std::string &path) std::string utils::get_potential_file_path(const std::string &path) { std::string filepath = path; - std::string filename = utils::path_basename(path); + std::string filename = platform::path_basename(path); - if (utils::file_is_readable(filepath)) { + if (platform::file_is_readable(filepath)) { return filepath; } else { // try the environment variable directory @@ -1154,11 +1051,11 @@ std::string utils::get_potential_file_path(const std::string &path) Tokenizer dirs(var, ":"); #endif while (dirs.has_next()) { - auto pot = utils::path_basename(filepath); + auto pot = platform::path_basename(filepath); auto dir = dirs.next(); - filepath = utils::path_join(dir, pot); + filepath = platform::path_join(dir, pot); - if (utils::file_is_readable(filepath)) { return filepath; } + if (platform::file_is_readable(filepath)) { return filepath; } } } } diff --git a/src/utils.h b/src/utils.h index 4dd4eea090..0437633ea6 100644 --- a/src/utils.h +++ b/src/utils.h @@ -417,49 +417,6 @@ namespace utils { bool is_id(const std::string &str); - /*! Try to detect pathname from FILE pointer. - * - * Currently supported on Linux, MacOS, and Windows, otherwise will report "(unknown)". - * - * \param buf storage buffer for pathname. output will be truncated if not large enough - * \param len size of storage buffer. output will be truncated to this length - 1 - * \param fp FILE pointer struct from STDIO library for which we want to detect the name - * \return pointer to the storage buffer, i.e. buf */ - - const char *guesspath(char *buf, int len, FILE *fp); - - /*! Strip off leading part of path, return just the filename - * - * \param path file path - * \return file name */ - - std::string path_basename(const std::string &path); - - /*! Return the directory part of a path. Return "." if empty - * - * \param path file path - * \return directory name */ - - std::string path_dirname(const std::string &path); - - /*! Join two pathname segments - * - * This uses the forward slash '/' character unless LAMMPS is compiled - * for Windows where it used the equivalent backward slash '\\'. - * - * \param a first path - * \param b second path - * \return combined path */ - - std::string path_join(const std::string &a, const std::string &b); - - /*! Check if file exists and is readable - * - * \param path file path - * \return true if file exists and is readable */ - - bool file_is_readable(const std::string &path); - /*! Determine full path of potential file. If file is not found in current directory, * search directories listed in LAMMPS_POTENTIALS environment variable * diff --git a/tools/lammps-shell/lammps-shell.cpp b/tools/lammps-shell/lammps-shell.cpp index 2ee62df920..76fa04d71a 100644 --- a/tools/lammps-shell/lammps-shell.cpp +++ b/tools/lammps-shell/lammps-shell.cpp @@ -6,6 +6,7 @@ // This software is distributed under the GNU General Public License. #include "library.h" +#include "platform.h" #include "utils.h" #include @@ -785,8 +786,8 @@ int main(int argc, char **argv) std::string input_file; if ((argc > 1) && (argv[1][0] != '-')) { --argc; - input_file = utils::path_basename(argv[1]); - chdir(utils::path_dirname(input_file).c_str()); + input_file = platform::path_basename(argv[1]); + chdir(platform::path_dirname(input_file).c_str()); for (int i = 1; i < argc; ++i) argv[i] = argv[i + 1]; } diff --git a/unittest/commands/test_groups.cpp b/unittest/commands/test_groups.cpp index e238e630d5..0c8a7cd83c 100644 --- a/unittest/commands/test_groups.cpp +++ b/unittest/commands/test_groups.cpp @@ -316,7 +316,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_kim_commands.cpp b/unittest/commands/test_kim_commands.cpp index a70176cc92..183d333ab4 100644 --- a/unittest/commands/test_kim_commands.cpp +++ b/unittest/commands/test_kim_commands.cpp @@ -684,7 +684,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_lattice_region.cpp b/unittest/commands/test_lattice_region.cpp index 5fbabcf173..47b69a15e0 100644 --- a/unittest/commands/test_lattice_region.cpp +++ b/unittest/commands/test_lattice_region.cpp @@ -20,7 +20,6 @@ #include "lammps.h" #include "lattice.h" #include "region.h" -#include "utils.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -631,7 +630,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_reset_ids.cpp b/unittest/commands/test_reset_ids.cpp index 221859e5c3..c67f90b341 100644 --- a/unittest/commands/test_reset_ids.cpp +++ b/unittest/commands/test_reset_ids.cpp @@ -686,7 +686,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_simple_commands.cpp b/unittest/commands/test_simple_commands.cpp index 31acf6d460..0ad47f4e96 100644 --- a/unittest/commands/test_simple_commands.cpp +++ b/unittest/commands/test_simple_commands.cpp @@ -20,7 +20,6 @@ #include "input.h" #include "output.h" #include "update.h" -#include "utils.h" #include "variable.h" #include "../testing/core.h" @@ -217,7 +216,7 @@ TEST_F(SimpleCommandsTest, Quit) TEST_FAILURE(".*ERROR: Expected integer .*", command("quit xxx");); // the following tests must be skipped with OpenMPI due to using threads - if (Info::get_mpi_vendor() == "Open MPI") GTEST_SKIP(); + if (platform::mpi_vendor() == "Open MPI") GTEST_SKIP(); ASSERT_EXIT(command("quit"), ExitedWithCode(0), ""); ASSERT_EXIT(command("quit 9"), ExitedWithCode(9), ""); } @@ -528,7 +527,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/commands/test_variables.cpp b/unittest/commands/test_variables.cpp index 9d8932d0f0..4f603df5ac 100644 --- a/unittest/commands/test_variables.cpp +++ b/unittest/commands/test_variables.cpp @@ -517,7 +517,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/cplusplus/test_error_class.cpp b/unittest/cplusplus/test_error_class.cpp index 489b085b1b..f4f0d3b28b 100644 --- a/unittest/cplusplus/test_error_class.cpp +++ b/unittest/cplusplus/test_error_class.cpp @@ -128,7 +128,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/cplusplus/test_lammps_class.cpp b/unittest/cplusplus/test_lammps_class.cpp index d25b232fa7..fa7f6b30a9 100644 --- a/unittest/cplusplus/test_lammps_class.cpp +++ b/unittest/cplusplus/test_lammps_class.cpp @@ -325,7 +325,7 @@ TEST_F(LAMMPS_kokkos, InitMembers) TEST(LAMMPS_init, OpenMP) { if (!LAMMPS::is_installed_pkg("OPENMP")) GTEST_SKIP(); - if (Info::get_openmp_info() == "OpenMP not enabled") GTEST_SKIP(); + if (platform::openmp_standard() == "OpenMP not enabled") GTEST_SKIP(); FILE *fp = fopen("in.lammps_empty", "w"); fputs("\n", fp); diff --git a/unittest/formats/test_file_operations.cpp b/unittest/formats/test_file_operations.cpp index 08baed2e54..bb26dff391 100644 --- a/unittest/formats/test_file_operations.cpp +++ b/unittest/formats/test_file_operations.cpp @@ -491,7 +491,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/formats/test_molecule_file.cpp b/unittest/formats/test_molecule_file.cpp index 5a3e3ca750..2cca7a6832 100644 --- a/unittest/formats/test_molecule_file.cpp +++ b/unittest/formats/test_molecule_file.cpp @@ -17,7 +17,6 @@ #include "input.h" #include "lammps.h" #include "molecule.h" -#include "utils.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -257,7 +256,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/formats/test_potential_file_reader.cpp b/unittest/formats/test_potential_file_reader.cpp index 5f7148b7e4..7cd61d25a4 100644 --- a/unittest/formats/test_potential_file_reader.cpp +++ b/unittest/formats/test_potential_file_reader.cpp @@ -326,7 +326,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/formats/test_text_file_reader.cpp b/unittest/formats/test_text_file_reader.cpp index 4e1f608d25..f0f695ae54 100644 --- a/unittest/formats/test_text_file_reader.cpp +++ b/unittest/formats/test_text_file_reader.cpp @@ -160,7 +160,7 @@ int main(int argc, char **argv) MPI_Init(&argc, &argv); ::testing::InitGoogleMock(&argc, argv); - if (Info::get_mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) + if (platform::mpi_vendor() == "Open MPI" && !LAMMPS_NS::Info::has_exceptions()) std::cout << "Warning: using OpenMPI without exceptions. " "Death tests will be skipped\n"; diff --git a/unittest/testing/core.h b/unittest/testing/core.h index 6867d88587..c922e96cc0 100644 --- a/unittest/testing/core.h +++ b/unittest/testing/core.h @@ -17,6 +17,7 @@ #include "info.h" #include "input.h" #include "lammps.h" +#include "platform.h" #include "variable.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -36,7 +37,7 @@ using ::testing::MatchesRegex; auto mesg = ::testing::internal::GetCapturedStdout(); \ ASSERT_THAT(mesg, MatchesRegex(errmsg)); \ } else { \ - if (Info::get_mpi_vendor() != "Open MPI") { \ + if (platform::mpi_vendor() != "Open MPI") { \ ::testing::internal::CaptureStdout(); \ ASSERT_DEATH({__VA_ARGS__}, ""); \ auto mesg = ::testing::internal::GetCapturedStdout(); \ diff --git a/unittest/utils/test_utils.cpp b/unittest/utils/test_utils.cpp index e0bc4984cc..b2c688cd59 100644 --- a/unittest/utils/test_utils.cpp +++ b/unittest/utils/test_utils.cpp @@ -13,14 +13,12 @@ #include "lmptype.h" #include "pointers.h" -#include "utils.h" #include "tokenizer.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include -#include #include #include @@ -721,54 +719,6 @@ TEST(Utils, boundsbig_case3) ASSERT_EQ(nhi, -1); } -TEST(Utils, guesspath) -{ - char buf[256]; - FILE *fp = fopen("test_guesspath.txt", "w"); -#if defined(__linux__) || defined(__APPLE__) || defined(_WIN32) - const char *path = utils::guesspath(buf, sizeof(buf), fp); - ASSERT_THAT(path, EndsWith("test_guesspath.txt")); -#else - const char *path = utils::guesspath(buf, sizeof(buf), fp); - ASSERT_THAT(path, EndsWith("(unknown)")); -#endif - fclose(fp); -} - -TEST(Utils, path_join) -{ -#if defined(_WIN32) - ASSERT_THAT(utils::path_join("c:\\parent\\folder", "filename"), - Eq("c:\\parent\\folder\\filename")); -#else - ASSERT_THAT(utils::path_join("/parent/folder", "filename"), Eq("/parent/folder/filename")); -#endif -} - -TEST(Utils, path_basename) -{ -#if defined(_WIN32) - ASSERT_THAT(utils::path_basename("c:\\parent\\folder\\filename"), Eq("filename")); - ASSERT_THAT(utils::path_basename("folder\\"), Eq("")); - ASSERT_THAT(utils::path_basename("c:/parent/folder/filename"), Eq("filename")); -#else - ASSERT_THAT(utils::path_basename("/parent/folder/filename"), Eq("filename")); - ASSERT_THAT(utils::path_basename("/parent/folder/"), Eq("")); -#endif -} - -TEST(Utils, path_dirname) -{ -#if defined(_WIN32) - ASSERT_THAT(utils::path_dirname("c:/parent/folder/filename"), Eq("c:/parent/folder")); - ASSERT_THAT(utils::path_dirname("c:\\parent\\folder\\filename"), Eq("c:\\parent\\folder")); - ASSERT_THAT(utils::path_dirname("c:filename"), Eq(".")); -#else - ASSERT_THAT(utils::path_dirname("/parent/folder/filename"), Eq("/parent/folder")); -#endif - ASSERT_THAT(utils::path_dirname("filename"), Eq(".")); -} - TEST(Utils, getsyserror) { #if defined(__linux__) @@ -792,16 +742,16 @@ TEST(Utils, potential_file) fputs("# CONTRIBUTOR: Pippo\n", fp); fclose(fp); - ASSERT_TRUE(utils::file_is_readable("ctest1.txt")); - ASSERT_TRUE(utils::file_is_readable("ctest2.txt")); - ASSERT_FALSE(utils::file_is_readable("no_such_file.txt")); + ASSERT_TRUE(platform::file_is_readable("ctest1.txt")); + ASSERT_TRUE(platform::file_is_readable("ctest2.txt")); + ASSERT_FALSE(platform::file_is_readable("no_such_file.txt")); ASSERT_THAT(utils::get_potential_file_path("ctest1.txt"), Eq("ctest1.txt")); ASSERT_THAT(utils::get_potential_file_path("no_such_file.txt"), Eq("")); const char *folder = getenv("LAMMPS_POTENTIALS"); if (folder != nullptr) { - std::string path = utils::path_join(folder, "Cu_u3.eam"); + std::string path = platform::path_join(folder, "Cu_u3.eam"); EXPECT_THAT(utils::get_potential_file_path("Cu_u3.eam"), Eq(path)); EXPECT_THAT(utils::get_potential_units(path, "EAM"), Eq("metal")); } From 2dcaa47b0ef1f12a947cbc3ed728e4c881d41139 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 2 Oct 2021 16:32:58 -0400 Subject: [PATCH 04/84] unfreeze versions of python packages used to build the documentation --- doc/utils/requirements.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/utils/requirements.txt b/doc/utils/requirements.txt index f367727d20..9b8e106875 100644 --- a/doc/utils/requirements.txt +++ b/doc/utils/requirements.txt @@ -1,7 +1,7 @@ -Sphinx==4.0.3 -sphinxcontrib-spelling==7.2.1 +Sphinx +sphinxcontrib-spelling git+git://github.com/akohlmey/sphinx-fortran@parallel-read -sphinx_tabs==3.2.0 -breathe==4.31.0 -Pygments==2.10.0 -six==1.16.0 +sphinx_tabs +breathe +Pygments +six From c6bdab8b4c480dcb4ed8a6c2d09df4ae6cb97643 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 2 Oct 2021 17:29:05 -0400 Subject: [PATCH 05/84] disable optimization of cputime function for MSVC++ to avoid bogus 0s reports --- src/platform.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/platform.cpp b/src/platform.cpp index 3dd08d46ce..530ec8fabf 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -112,6 +112,8 @@ using namespace LAMMPS_NS; // clang compilers are optimizing this function too aggressively returning always 0 #if defined(__clang__) [[clang::optnone]] +#elif defined(_MSC_VER) +#pragma optimize("",off) #endif double platform::cputime() // clang-format on @@ -143,6 +145,9 @@ double platform::cputime() return rv; } +#if defined(_MSC_VER) +#pragma optimize("",on) +#endif /* ---------------------------------------------------------------------- get wall time From dcaed72b6de2721a4b15a71015e8c48874c5acea Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 2 Oct 2021 17:29:12 -0400 Subject: [PATCH 06/84] update embedded docs --- src/platform.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform.h b/src/platform.h index 1c4a659570..461b8f75b0 100644 --- a/src/platform.h +++ b/src/platform.h @@ -26,7 +26,7 @@ namespace platform { /*! Return the consumed CPU time for the current process in seconds * - * This is a wrapper about the POSIX function getrusage() and the Windows equivalent. + * This is a wrapper around the POSIX function getrusage() and its Windows equivalent. * It is to be used in a similar fashion than MPI_Wtime(). * * \return used CPU time in second */ @@ -35,7 +35,7 @@ namespace platform { /*! Return the wall clock state for the current process in seconds * - * This is a wrapper about XXX and its Windows equivalent. + * This is a wrapper around the gettimeofday() function and its Windows equivalent. * It is to be used in a similar fashion than MPI_Wtime(). * * \return wall clock time in second */ From 69a8dfe4d97b60fbf429673ed4f99497139cbb5b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 2 Oct 2021 18:12:32 -0400 Subject: [PATCH 07/84] whitespace --- doc/src/Developer_platform.rst | 2 +- src/platform.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/Developer_platform.rst b/doc/src/Developer_platform.rst index dc482cb27a..a31e9d1c72 100644 --- a/doc/src/Developer_platform.rst +++ b/doc/src/Developer_platform.rst @@ -114,7 +114,7 @@ Environment variable functions .. doxygenfunction:: find_exe_path :project: progguide - + Dynamically loaded object or library functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/platform.h b/src/platform.h index 461b8f75b0..55131ec803 100644 --- a/src/platform.h +++ b/src/platform.h @@ -242,7 +242,7 @@ namespace platform { /*! Delete a directory and its contents * - * Unlike the the ``rmdir()`` or ``_rmdir()`` function of the + * Unlike the the ``rmdir()`` or ``_rmdir()`` function of the * C library, this function will check for the contents of the * folder and recurse into any sub-folders, if necessary and * delete all contained folders and their contents before From a6aa3fd3ee8399b00bef434f8ef56cd78bbaa5cf Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 2 Oct 2021 18:26:46 -0400 Subject: [PATCH 08/84] apply clang-format --- src/platform.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/platform.cpp b/src/platform.cpp index 530ec8fabf..ed007e089a 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -146,7 +146,7 @@ double platform::cputime() return rv; } #if defined(_MSC_VER) -#pragma optimize("",on) +#pragma optimize("", on) #endif /* ---------------------------------------------------------------------- @@ -281,19 +281,19 @@ std::string platform::compiler_info() { std::string buf = "(Unknown)"; #if defined(__INTEL_LLVM_COMPILER) - double version = static_cast(__INTEL_LLVM_COMPILER)*0.01; + double version = static_cast(__INTEL_LLVM_COMPILER) * 0.01; buf = fmt::format("Intel LLVM C++ {:.1f} / {}", version, __VERSION__); #elif defined(__ibmxl__) - buf = fmt::format("IBM XL C/C++ (Clang) {}.{}.{}", - __ibmxl_version__, __ibmxl_release__, __ibmxl_modification__); + buf = fmt::format("IBM XL C/C++ (Clang) {}.{}.{}", __ibmxl_version__, __ibmxl_release__, + __ibmxl_modification__); #elif defined(__clang__) buf = fmt::format("Clang C++ {}", __VERSION__); #elif defined(__PGI) - buf = fmt::format("PGI C++ {}.{}",__PGIC__,__PGIC_MINOR__); + buf = fmt::format("PGI C++ {}.{}", __PGIC__, __PGIC_MINOR__); #elif defined(__INTEL_COMPILER) - double version = static_cast(__INTEL_COMPILER)*0.01; - buf = fmt::format("Intel Classic C++ {:.2f}.{} / {}", version, - __INTEL_COMPILER_UPDATE, __VERSION__); + double version = static_cast(__INTEL_COMPILER) * 0.01; + buf = fmt::format("Intel Classic C++ {:.2f}.{} / {}", version, __INTEL_COMPILER_UPDATE, + __VERSION__); #elif defined(__MINGW64__) buf = fmt::format("MinGW-w64 64bit {}.{} / GNU C++ {}", __MINGW64_VERSION_MAJOR, __MINGW64_VERSION_MINOR, __VERSION__); @@ -301,11 +301,12 @@ std::string platform::compiler_info() buf = fmt::format("MinGW-w64 32bit {}.{} / GNU C++ {}", __MINGW32_MAJOR_VERSION, __MINGW32_MINOR_VERSION, __VERSION__); #elif defined(__GNUC__) - buf = fmt::format("GNU C++ {}", __VERSION__); + buf = fmt::format("GNU C++ {}", __VERSION__); #elif defined(_MSC_VER) && (_MSC_VER > 1920) && (_MSC_VER < 2000) constexpr int major = _MSC_VER / 100; - constexpr int minor = _MSC_VER - major *100; - buf = "Microsoft Visual Studio 20" + std::to_string(major) + ", C/C++ " + std::to_string(major-5) + "." + std::to_string(minor); + constexpr int minor = _MSC_VER - major * 100; + buf = "Microsoft Visual Studio 20" + std::to_string(major) + ", C/C++ " + + std::to_string(major - 5) + "." + std::to_string(minor); #else buf = "(Unknown)"; #endif From 7110e1c15e73fff6d38faa83faf1abf95d66cb3f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 2 Oct 2021 18:28:33 -0400 Subject: [PATCH 09/84] small format tweaks - brief description should not end in a dot as it becomes a title line - add empty line to separate title from body of description - revert order of file/path separator constants so that the Linux version shows up in doxygen --- src/platform.h | 56 +++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/platform.h b/src/platform.h index 55131ec803..b7c5d28561 100644 --- a/src/platform.h +++ b/src/platform.h @@ -42,7 +42,7 @@ namespace platform { double walltime(); - /*! Return string with the Operating system version and architecture info. + /*! Return string with the operating system version and architecture info * * \return string with info about the OS and the platform is is running on */ @@ -120,6 +120,7 @@ namespace platform { void *dlopen(const std::string &fname); /*! Close a shared object + * * This releases the object corresponding to the provided handle. * Resolved symbols associated with this handle may not be used * after this call @@ -137,28 +138,30 @@ namespace platform { void *dlsym(void *handle, const std::string &symbol); - /*! File path component separators - * These are the characters that separate directories and filename in paths on - * a platform. If multiple are provided, the first is the preferred one. */ - -#if defined(_WIN32) - constexpr char filepathsep[] = "\\/"; -#else - constexpr char filepathsep[] = "/"; -#endif - - /*! Path environment variable component separator - * This is the character that separates entries in "PATH" environment variables. */ - -#if defined(_WIN32) - constexpr char pathvarsep = ';'; -#else - constexpr char pathvarsep = ':'; -#endif - - /*! Try to detect pathname from FILE pointer. + /*! Platform specific file path component separator * - * Currently only supported on Linux and MacOS, otherwise will report "(unknown)". + * This is a string with the character that separates directories and filename in paths on + * a platform. If multiple are characters are provided, the first is the preferred one. */ + +#if !defined(_WIN32) + constexpr char filepathsep[] = "/"; +#else + constexpr char filepathsep[] = "\\/"; +#endif + + /*! Platform specific path environment variable component separator + * + * This is the character that separates entries in "PATH"-style environment variables. */ + +#if !defined(_WIN32) + constexpr char pathvarsep = ':'; +#else + constexpr char pathvarsep = ';'; +#endif + + /*! Try to detect pathname from FILE pointer + * + * Currently only supported on Linux, MacOS, and Windows. Otherwise will report "(unknown)". * * \param fp FILE pointer struct from STDIO library for which we want to detect the name * \param buf storage buffer for pathname. output will be truncated if not large enough @@ -308,7 +311,7 @@ namespace platform { /*! Join two pathname segments * * This uses the forward slash '/' character unless LAMMPS is compiled - * for Windows where it used the equivalent backward slash '\\'. + * for Windows where it uses the backward slash '\\' * * \param a first path * \param b second path @@ -324,21 +327,22 @@ namespace platform { bool file_is_readable(const std::string &path); /*! Check if a file name ends in a known extension for a compressed file format - * Currently supported extensions are: .Z, .gz, .bz2, .zstd, .xz, .lzma + * + * Currently supported file extensions are: .gz, .bz2, .zstd, .xz, .lzma, lz4 * * \param file name of the file to check * \return true if the file has a known extension, otherwise false */ bool has_zip_extension(const std::string &file); - /*! Open pipe to compressed text file for reading. + /*! Open pipe to compressed text file for reading * * \param file name of the file to open * \return FILE pointer to pipe using for reading the compressed file. */ FILE *zip_read(const std::string &file); - /*! Open pipe to compressed text file for writing. + /*! Open pipe to compressed text file for writing * * \param file name of the file to open * \return FILE pointer to pipe using for reading the compressed file. */ From c341c2c6a93507f94e1f714461c553b138f19f51 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 2 Oct 2021 20:00:53 -0400 Subject: [PATCH 10/84] correct platform call in kim query command --- src/KIM/kim_query.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KIM/kim_query.cpp b/src/KIM/kim_query.cpp index c1669650cc..3e891468a6 100644 --- a/src/KIM/kim_query.cpp +++ b/src/KIM/kim_query.cpp @@ -377,7 +377,7 @@ char *do_query(const std::string &qfunction, const std::string &mname, } auto user_agent = fmt::format("kim query--LAMMPS/{} ({})", - LAMMPS_VERSION, Info::get_os_info()); + LAMMPS_VERSION, platform::os_info()); curl_easy_setopt(handle, CURLOPT_USERAGENT, user_agent.c_str()); curl_easy_setopt(handle, CURLOPT_URL, url.c_str()); From 03f7bf66499538b764cb4cf79706093dc0d50517 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 2 Oct 2021 22:44:29 -0400 Subject: [PATCH 11/84] update eigen3 to the latest release and move download to our own server --- cmake/Modules/Packages/MACHDYN.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/Packages/MACHDYN.cmake b/cmake/Modules/Packages/MACHDYN.cmake index fab532541e..8729d80dbf 100644 --- a/cmake/Modules/Packages/MACHDYN.cmake +++ b/cmake/Modules/Packages/MACHDYN.cmake @@ -7,8 +7,9 @@ endif() option(DOWNLOAD_EIGEN3 "Download Eigen3 instead of using an already installed one)" ${DOWNLOAD_EIGEN3_DEFAULT}) if(DOWNLOAD_EIGEN3) message(STATUS "Eigen3 download requested - we will build our own") - set(EIGEN3_URL "https://gitlab.com/libeigen/eigen/-/archive/3.3.9/eigen-3.3.9.tar.gz" CACHE STRING "URL for Eigen3 tarball") - set(EIGEN3_MD5 "609286804b0f79be622ccf7f9ff2b660" CACHE STRING "MD5 checksum of Eigen3 tarball") + + set(EIGEN3_URL "https://download.lammps.org/thirdparty/eigen-3.4.0.tar.gz" CACHE STRING "URL for Eigen3 tarball") + set(EIGEN3_MD5 "4c527a9171d71a72a9d4186e65bea559" CACHE STRING "MD5 checksum of Eigen3 tarball") mark_as_advanced(EIGEN3_URL) mark_as_advanced(EIGEN3_MD5) include(ExternalProject) From dd2b5b22d4aa867314174bd4e806dcee1f454d40 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 4 Oct 2021 17:22:58 -0400 Subject: [PATCH 12/84] fix saed/vtk does not use the overwrite option anywhere --- doc/src/fix_saed_vtk.rst | 5 -- src/DIFFRACTION/fix_saed_vtk.cpp | 107 ++++++++++++++----------------- src/DIFFRACTION/fix_saed_vtk.h | 2 - 3 files changed, 49 insertions(+), 65 deletions(-) diff --git a/doc/src/fix_saed_vtk.rst b/doc/src/fix_saed_vtk.rst index a9e8f154e6..dd5db32966 100644 --- a/doc/src/fix_saed_vtk.rst +++ b/doc/src/fix_saed_vtk.rst @@ -28,7 +28,6 @@ Syntax Nstart = start averaging on this timestep *file* arg = filename filename = name of file to output time averages to - *overwrite* arg = none = overwrite output file with only latest output Examples """""""" @@ -161,10 +160,6 @@ the *file* keyword and this string is appended with _N.vtk where N is an index (0,1,2...) to account for situations with multiple diffraction intensity outputs. -The *overwrite* keyword will continuously overwrite the output file -with the latest output, so that it only contains one timestep worth of -output. This option can only be used with the *ave running* setting. - Restart, fix_modify, output, run start/stop, minimize info """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" diff --git a/src/DIFFRACTION/fix_saed_vtk.cpp b/src/DIFFRACTION/fix_saed_vtk.cpp index 2e7d0897a6..89627b64ef 100644 --- a/src/DIFFRACTION/fix_saed_vtk.cpp +++ b/src/DIFFRACTION/fix_saed_vtk.cpp @@ -31,6 +31,7 @@ #include #include + using namespace LAMMPS_NS; using namespace FixConst; @@ -100,8 +101,6 @@ FixSAEDVTK::FixSAEDVTK(LAMMPS *lmp, int narg, char **arg) : error->all(FLERR,"Illegal fix saed/vtk command"); if (nfreq % nevery || nrepeat*nevery > nfreq) error->all(FLERR,"Illegal fix saed/vtk command"); - if (ave != RUNNING && overwrite) - error->all(FLERR,"Illegal fix saed/vtk command"); // allocate memory for averaging @@ -315,7 +314,7 @@ void FixSAEDVTK::invoke_vector(bigint ntimestep) if (irepeat == 0) for (int i = 0; i < nrows; i++) - vector[i] = 0.0; + vector[i] = 0.0; // accumulate results of computes,fixes,variables to local copy // compute/fix/variable may invoke computes so wrap with clear/add @@ -369,7 +368,7 @@ void FixSAEDVTK::invoke_vector(bigint ntimestep) for (int i = 0; i < nrows; i++) { vector_total[i] += vector[i]; if (window_limit) vector_total[i] -= vector_list[iwindow][i]; - vector_list[iwindow][i] = vector[i]; + vector_list[iwindow][i] = vector[i]; } iwindow++; @@ -391,8 +390,7 @@ void FixSAEDVTK::invoke_vector(bigint ntimestep) fp = fopen(nName.c_str(),"w"); if (fp == nullptr) - error->one(FLERR,"Cannot open fix saed/vtk file {}: {}", - nName,utils::getsyserror()); + error->one(FLERR,"Cannot open fix saed/vtk file {}: {}", nName,utils::getsyserror()); } fprintf(fp,"# vtk DataFile Version 3.0 c_%s\n",ids); @@ -406,71 +404,68 @@ void FixSAEDVTK::invoke_vector(bigint ntimestep) fprintf(fp,"SCALARS intensity float\n"); fprintf(fp,"LOOKUP_TABLE default\n"); - filepos = ftell(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + // Finding the intersection of the reciprical space and Ewald sphere + int NROW1 = 0; + int NROW2 = 0; + double dinv2 = 0.0; + double r = 0.0; + double K[3]; - // Finding the intersection of the reciprical space and Ewald sphere - int NROW1 = 0; - int NROW2 = 0; - double dinv2 = 0.0; - double r = 0.0; - double K[3]; - - // Zone flag to capture entire recrocal space volume - if ((Zone[0] == 0) && (Zone[1] == 0) && (Zone[2] == 0)) { - for (int k = Knmin[2]; k <= Knmax[2]; k++) { - for (int j = Knmin[1]; j <= Knmax[1]; j++) { - for (int i = Knmin[0]; i <= Knmax[0]; i++) { - K[0] = i * dK[0]; - K[1] = j * dK[1]; - K[2] = k * dK[2]; - dinv2 = (K[0] * K[0] + K[1] * K[1] + K[2] * K[2]); - if (dinv2 < Kmax * Kmax) { - fprintf(fp,"%g\n",vector_total[NROW1]/norm); - fflush(fp); - NROW1++; - NROW2++; - } else { + // Zone flag to capture entire recrocal space volume + if ((Zone[0] == 0) && (Zone[1] == 0) && (Zone[2] == 0)) { + for (int k = Knmin[2]; k <= Knmax[2]; k++) { + for (int j = Knmin[1]; j <= Knmax[1]; j++) { + for (int i = Knmin[0]; i <= Knmax[0]; i++) { + K[0] = i * dK[0]; + K[1] = j * dK[1]; + K[2] = k * dK[2]; + dinv2 = (K[0] * K[0] + K[1] * K[1] + K[2] * K[2]); + if (dinv2 < Kmax * Kmax) { + fprintf(fp,"%g\n",vector_total[NROW1]/norm); + fflush(fp); + NROW1++; + NROW2++; + } else { fprintf(fp,"%d\n",-1); fflush(fp); NROW2++; - } } } } - } else { - for (int k = Knmin[2]; k <= Knmax[2]; k++) { - for (int j = Knmin[1]; j <= Knmax[1]; j++) { - for (int i = Knmin[0]; i <= Knmax[0]; i++) { - K[0] = i * dK[0]; - K[1] = j * dK[1]; - K[2] = k * dK[2]; - dinv2 = (K[0] * K[0] + K[1] * K[1] + K[2] * K[2]); - if (dinv2 < Kmax * Kmax) { - r=0.0; - for (int m=0; m<3; m++) r += pow(K[m] - Zone[m],2.0); - r = sqrt(r); - if ( (r > (R_Ewald - dR_Ewald) ) && (r < (R_Ewald + dR_Ewald) )) { - fprintf(fp,"%g\n",vector_total[NROW1]/norm); - fflush(fp); - NROW2++; - NROW1++; - } else { - fprintf(fp,"%d\n",-1); - fflush(fp); - NROW2++; - } + } + } else { + for (int k = Knmin[2]; k <= Knmax[2]; k++) { + for (int j = Knmin[1]; j <= Knmax[1]; j++) { + for (int i = Knmin[0]; i <= Knmax[0]; i++) { + K[0] = i * dK[0]; + K[1] = j * dK[1]; + K[2] = k * dK[2]; + dinv2 = (K[0] * K[0] + K[1] * K[1] + K[2] * K[2]); + if (dinv2 < Kmax * Kmax) { + r=0.0; + for (int m=0; m<3; m++) r += pow(K[m] - Zone[m],2.0); + r = sqrt(r); + if ( (r > (R_Ewald - dR_Ewald) ) && (r < (R_Ewald + dR_Ewald) )) { + fprintf(fp,"%g\n",vector_total[NROW1]/norm); + fflush(fp); + NROW2++; + NROW1++; } else { + fprintf(fp,"%d\n",-1); + fflush(fp); + NROW2++; + } + } else { fprintf(fp,"%d\n",-1); fflush(fp); NROW2++; - } } } } } } + } nOutput++; } @@ -497,7 +492,6 @@ void FixSAEDVTK::options(int narg, char **arg) fp = nullptr; ave = ONE; startstep = 0; - overwrite = 0; // optional args int iarg = 7; @@ -534,9 +528,6 @@ void FixSAEDVTK::options(int narg, char **arg) if (iarg+2 > narg) error->all(FLERR,"Illegal fix saed/vtk command"); startstep = utils::inumeric(FLERR,arg[iarg+1],false,lmp); iarg += 2; - } else if (strcmp(arg[iarg],"overwrite") == 0) { - overwrite = 1; - iarg += 1; } else error->all(FLERR,"Illegal fix saed/vtk command"); } } diff --git a/src/DIFFRACTION/fix_saed_vtk.h b/src/DIFFRACTION/fix_saed_vtk.h index 07aebce63d..a5691ea986 100644 --- a/src/DIFFRACTION/fix_saed_vtk.h +++ b/src/DIFFRACTION/fix_saed_vtk.h @@ -43,8 +43,6 @@ class FixSAEDVTK : public Fix { int nrows; int ave, nwindow, nsum, startstep; - int overwrite; - long filepos; int norm, iwindow, window_limit; double *vector; From 7cdd82dee29d7675819b9b9e65eb3231c3812895 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 4 Oct 2021 18:13:46 -0400 Subject: [PATCH 13/84] use platform functions for averaging fixes --- src/EXTRA-FIX/fix_ave_correlate_long.cpp | 25 +++++------ src/EXTRA-FIX/fix_ave_correlate_long.h | 2 +- src/fix_ave_chunk.cpp | 39 ++++++++-------- src/fix_ave_chunk.h | 2 +- src/fix_ave_correlate.cpp | 35 +++++++-------- src/fix_ave_correlate.h | 2 +- src/fix_ave_histo.cpp | 43 +++++++++--------- src/fix_ave_histo.h | 2 +- src/fix_ave_histo_weight.cpp | 10 ++--- src/fix_ave_time.cpp | 57 ++++++++++++------------ src/fix_ave_time.h | 2 +- 11 files changed, 106 insertions(+), 113 deletions(-) diff --git a/src/EXTRA-FIX/fix_ave_correlate_long.cpp b/src/EXTRA-FIX/fix_ave_correlate_long.cpp index 6e4e26754f..1746c7f6f5 100644 --- a/src/EXTRA-FIX/fix_ave_correlate_long.cpp +++ b/src/EXTRA-FIX/fix_ave_correlate_long.cpp @@ -36,7 +36,6 @@ #include #include -#include using namespace LAMMPS_NS; using namespace FixConst; @@ -260,11 +259,11 @@ FixAveCorrelateLong::FixAveCorrelateLong(LAMMPS * lmp, int narg, char **arg): fprintf(fp," %s*%s",arg[5+i],arg[5+j]); fprintf(fp,"\n"); } - filepos = ftell(fp); + filepos = platform::ftell(fp); } - delete [] title1; - delete [] title2; + delete[] title1; + delete[] title2; // allocate and initialize memory for calculated values and correlators @@ -319,11 +318,11 @@ FixAveCorrelateLong::FixAveCorrelateLong(LAMMPS * lmp, int narg, char **arg): FixAveCorrelateLong::~FixAveCorrelateLong() { - delete [] which; - delete [] argindex; - delete [] value2index; - for (int i = 0; i < nvalues; i++) delete [] ids[i]; - delete [] ids; + delete[] which; + delete[] argindex; + delete[] value2index; + for (int i = 0; i < nvalues; i++) delete[] ids[i]; + delete[] ids; memory->destroy(values); memory->destroy(shift); @@ -467,7 +466,7 @@ void FixAveCorrelateLong::end_of_step() evaluate(); if (fp && me == 0) { - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,"# Timestep: " BIGINT_FORMAT "\n", ntimestep); for (unsigned int i=0;idt*nevery); @@ -478,9 +477,9 @@ void FixAveCorrelateLong::end_of_step() } fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } diff --git a/src/EXTRA-FIX/fix_ave_correlate_long.h b/src/EXTRA-FIX/fix_ave_correlate_long.h index b62c6aefcb..a31ae78217 100644 --- a/src/EXTRA-FIX/fix_ave_correlate_long.h +++ b/src/EXTRA-FIX/fix_ave_correlate_long.h @@ -66,7 +66,7 @@ class FixAveCorrelateLong : public Fix { FILE *fp; int type, startstep, overwrite; - long filepos; + bigint filepos; int npair; // number of correlation pairs to calculate double *values; diff --git a/src/fix_ave_chunk.cpp b/src/fix_ave_chunk.cpp index 1328a27376..36c9eaf6fc 100644 --- a/src/fix_ave_chunk.cpp +++ b/src/fix_ave_chunk.cpp @@ -29,7 +29,6 @@ #include "variable.h" #include -#include using namespace LAMMPS_NS; using namespace FixConst; @@ -216,23 +215,23 @@ FixAveChunk::FixAveChunk(LAMMPS *lmp, int narg, char **arg) : iarg += 1; } else if (strcmp(arg[iarg],"format") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/chunk command"); - delete [] format_user; + delete[] format_user; format_user = utils::strdup(arg[iarg+1]); format = format_user; iarg += 2; } else if (strcmp(arg[iarg],"title1") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/chunk command"); - delete [] title1; + delete[] title1; title1 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title2") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/chunk command"); - delete [] title2; + delete[] title2; title2 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title3") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/chunk command"); - delete [] title3; + delete[] title3; title3 = utils::strdup(arg[iarg+1]); iarg += 2; } else error->all(FLERR,"Illegal fix ave/chunk command"); @@ -348,18 +347,18 @@ FixAveChunk::FixAveChunk(LAMMPS *lmp, int narg, char **arg) : if (ferror(fp)) error->one(FLERR,"Error writing file header"); - filepos = ftell(fp); + filepos = platform::ftell(fp); } - delete [] title1; - delete [] title2; - delete [] title3; + delete[] title1; + delete[] title2; + delete[] title3; // if wildcard expansion occurred, free earg memory from expand_args() // wait to do this until after file comment lines are printed if (expand) { - for (int i = 0; i < nargnew; i++) delete [] earg[i]; + for (int i = 0; i < nargnew; i++) delete[] earg[i]; memory->sfree(earg); } @@ -407,11 +406,11 @@ FixAveChunk::FixAveChunk(LAMMPS *lmp, int narg, char **arg) : FixAveChunk::~FixAveChunk() { - delete [] which; - delete [] argindex; - for (int i = 0; i < nvalues; i++) delete [] ids[i]; - delete [] ids; - delete [] value2index; + delete[] which; + delete[] argindex; + for (int i = 0; i < nvalues; i++) delete[] ids[i]; + delete[] ids; + delete[] value2index; if (fp && comm->me == 0) fclose(fp); @@ -438,7 +437,7 @@ FixAveChunk::~FixAveChunk() } } - delete [] idchunk; + delete[] idchunk; which = nullptr; argindex = nullptr; ids = nullptr; @@ -941,7 +940,7 @@ void FixAveChunk::end_of_step() if (fp && comm->me == 0) { clearerr(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); double count = 0.0; for (m = 0; m < nchunk; m++) count += count_total[m]; fprintf(fp,BIGINT_FORMAT " %d %g\n",ntimestep,nchunk,count); @@ -1027,9 +1026,9 @@ void FixAveChunk::end_of_step() fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } } diff --git a/src/fix_ave_chunk.h b/src/fix_ave_chunk.h index e7beed341f..69fdea0f06 100644 --- a/src/fix_ave_chunk.h +++ b/src/fix_ave_chunk.h @@ -61,7 +61,7 @@ class FixAveChunk : public Fix { class ComputeChunkAtom *cchunk; int lockforever; - long filepos; + bigint filepos; int maxvar; double *varatom; diff --git a/src/fix_ave_correlate.cpp b/src/fix_ave_correlate.cpp index 92b5ea3693..df6e33288e 100644 --- a/src/fix_ave_correlate.cpp +++ b/src/fix_ave_correlate.cpp @@ -30,7 +30,6 @@ #include "variable.h" #include -#include using namespace LAMMPS_NS; using namespace FixConst; @@ -139,17 +138,17 @@ FixAveCorrelate::FixAveCorrelate(LAMMPS * lmp, int narg, char **arg): iarg += 1; } else if (strcmp(arg[iarg],"title1") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command"); - delete [] title1; + delete[] title1; title1 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title2") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command"); - delete [] title2; + delete[] title2; title2 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title3") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command"); - delete [] title3; + delete[] title3; title3 = utils::strdup(arg[iarg+1]); iarg += 2; } else error->all(FLERR,"Illegal fix ave/correlate command"); @@ -256,18 +255,18 @@ FixAveCorrelate::FixAveCorrelate(LAMMPS * lmp, int narg, char **arg): if (ferror(fp)) error->one(FLERR,"Error writing file header"); - filepos = ftell(fp); + filepos = platform::ftell(fp); } - delete [] title1; - delete [] title2; - delete [] title3; + delete[] title1; + delete[] title2; + delete[] title3; // if wildcard expansion occurred, free earg memory from expand_args() // wait to do this until after file comment lines are printed if (expand) { - for (int i = 0; i < nargnew; i++) delete [] earg[i]; + for (int i = 0; i < nargnew; i++) delete[] earg[i]; memory->sfree(earg); } @@ -312,11 +311,11 @@ FixAveCorrelate::FixAveCorrelate(LAMMPS * lmp, int narg, char **arg): FixAveCorrelate::~FixAveCorrelate() { - delete [] which; - delete [] argindex; - delete [] value2index; - for (int i = 0; i < nvalues; i++) delete [] ids[i]; - delete [] ids; + delete[] which; + delete[] argindex; + delete[] value2index; + for (int i = 0; i < nvalues; i++) delete[] ids[i]; + delete[] ids; memory->destroy(values); memory->destroy(count); @@ -489,7 +488,7 @@ void FixAveCorrelate::end_of_step() if (fp && me == 0) { clearerr(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,BIGINT_FORMAT " %d\n",ntimestep,nrepeat); for (i = 0; i < nrepeat; i++) { fprintf(fp,"%d %d %d",i+1,i*nevery,count[i]); @@ -507,9 +506,9 @@ void FixAveCorrelate::end_of_step() fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } diff --git a/src/fix_ave_correlate.h b/src/fix_ave_correlate.h index d551ba7b92..6dde75c0d3 100644 --- a/src/fix_ave_correlate.h +++ b/src/fix_ave_correlate.h @@ -44,7 +44,7 @@ class FixAveCorrelate : public Fix { int type, ave, startstep, overwrite; double prefactor; - long filepos; + bigint filepos; int firstindex; // index in values ring of earliest time sample int lastindex; // index in values ring of latest time sample diff --git a/src/fix_ave_histo.cpp b/src/fix_ave_histo.cpp index 92b03035b3..8c55337074 100644 --- a/src/fix_ave_histo.cpp +++ b/src/fix_ave_histo.cpp @@ -25,7 +25,6 @@ #include "variable.h" #include -#include using namespace LAMMPS_NS; using namespace FixConst; @@ -168,7 +167,7 @@ FixAveHisto::FixAveHisto(LAMMPS *lmp, int narg, char **arg) : // if wildcard expansion occurred, free earg memory from expand_args() if (expand) { - for (int i = 0; i < nvalues; i++) delete [] earg[i]; + for (int i = 0; i < nvalues; i++) delete[] earg[i]; memory->sfree(earg); } @@ -434,12 +433,12 @@ FixAveHisto::FixAveHisto(LAMMPS *lmp, int narg, char **arg) : if (ferror(fp)) error->one(FLERR,"Error writing file header"); - filepos = ftell(fp); + filepos = platform::ftell(fp); } - delete [] title1; - delete [] title2; - delete [] title3; + delete[] title1; + delete[] title2; + delete[] title3; // allocate and initialize memory for averaging @@ -502,18 +501,18 @@ FixAveHisto::FixAveHisto(LAMMPS *lmp, int narg, char **arg) : FixAveHisto::~FixAveHisto() { - delete [] which; - delete [] argindex; - delete [] value2index; - for (int i = 0; i < nvalues; i++) delete [] ids[i]; - delete [] ids; + delete[] which; + delete[] argindex; + delete[] value2index; + for (int i = 0; i < nvalues; i++) delete[] ids[i]; + delete[] ids; if (fp && me == 0) fclose(fp); - delete [] bin; - delete [] bin_total; - delete [] bin_all; - delete [] coord; + delete[] bin; + delete[] bin_total; + delete[] bin_all; + delete[] coord; memory->destroy(stats_list); memory->destroy(bin_list); memory->destroy(vector); @@ -817,7 +816,7 @@ void FixAveHisto::end_of_step() if (fp && me == 0) { clearerr(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,BIGINT_FORMAT " %d %g %g %g %g\n",ntimestep,nbins, stats_total[0],stats_total[1],stats_total[2],stats_total[3]); if (stats_total[0] != 0.0) @@ -833,9 +832,9 @@ void FixAveHisto::end_of_step() fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}",utils::getsyserror()); } } } @@ -993,17 +992,17 @@ void FixAveHisto::options(int iarg, int narg, char **arg) iarg += 1; } else if (strcmp(arg[iarg],"title1") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command"); - delete [] title1; + delete[] title1; title1 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title2") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command"); - delete [] title2; + delete[] title2; title2 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title3") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command"); - delete [] title3; + delete[] title3; title3 = utils::strdup(arg[iarg+1]); iarg += 2; } else error->all(FLERR,"Illegal fix ave/histo command"); diff --git a/src/fix_ave_histo.h b/src/fix_ave_histo.h index 0158d04377..ef64ad74ff 100644 --- a/src/fix_ave_histo.h +++ b/src/fix_ave_histo.h @@ -44,7 +44,7 @@ class FixAveHisto : public Fix { FILE *fp; double lo, hi, binsize, bininv; int kind, beyond, overwrite; - long filepos; + bigint filepos; double stats[4], stats_total[4], stats_all[4]; double **stats_list; diff --git a/src/fix_ave_histo_weight.cpp b/src/fix_ave_histo_weight.cpp index 63321bf53e..7866490840 100644 --- a/src/fix_ave_histo_weight.cpp +++ b/src/fix_ave_histo_weight.cpp @@ -28,8 +28,6 @@ #include "update.h" #include "variable.h" -#include - using namespace LAMMPS_NS; using namespace FixConst; @@ -472,7 +470,7 @@ void FixAveHistoWeight::end_of_step() if (fp && me == 0) { clearerr(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,BIGINT_FORMAT " %d %g %g %g %g\n",ntimestep,nbins, stats_total[0],stats_total[1],stats_total[2],stats_total[3]); if (stats_total[0] != 0.0) @@ -488,9 +486,9 @@ void FixAveHistoWeight::end_of_step() fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } } diff --git a/src/fix_ave_time.cpp b/src/fix_ave_time.cpp index da9cd89e5e..a3da6e6a3d 100644 --- a/src/fix_ave_time.cpp +++ b/src/fix_ave_time.cpp @@ -28,7 +28,6 @@ #include "variable.h" #include -#include using namespace LAMMPS_NS; using namespace FixConst; @@ -274,18 +273,18 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) : if (ferror(fp)) error->one(FLERR,"Error writing file header"); - filepos = ftell(fp); + filepos = platform::ftell(fp); } - delete [] title1; - delete [] title2; - delete [] title3; + delete[] title1; + delete[] title2; + delete[] title3; // if wildcard expansion occurred, free earg memory from expand_args() // wait to do this until after file comment lines are printed if (expand) { - for (int i = 0; i < nvalues; i++) delete [] earg[i]; + for (int i = 0; i < nvalues; i++) delete[] earg[i]; memory->sfree(earg); } @@ -446,24 +445,24 @@ FixAveTime::~FixAveTime() } } - delete [] format_user; + delete[] format_user; - delete [] which; - delete [] argindex; - delete [] value2index; - delete [] offcol; - delete [] varlen; - for (int i = 0; i < nvalues; i++) delete [] ids[i]; - delete [] ids; + delete[] which; + delete[] argindex; + delete[] value2index; + delete[] offcol; + delete[] varlen; + for (int i = 0; i < nvalues; i++) delete[] ids[i]; + delete[] ids; - delete [] extlist; + delete[] extlist; if (fp && me == 0) fclose(fp); memory->destroy(column); - delete [] vector; - delete [] vector_total; + delete[] vector; + delete[] vector_total; memory->destroy(array); memory->destroy(array_total); memory->destroy(array_list); @@ -673,7 +672,7 @@ void FixAveTime::invoke_scalar(bigint ntimestep) if (fp && me == 0) { clearerr(fp); - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,BIGINT_FORMAT,ntimestep); for (i = 0; i < nvalues; i++) fprintf(fp,format,vector_total[i]/norm); fprintf(fp,"\n"); @@ -683,9 +682,9 @@ void FixAveTime::invoke_scalar(bigint ntimestep) fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } } @@ -885,7 +884,7 @@ void FixAveTime::invoke_vector(bigint ntimestep) // output result to file if (fp && me == 0) { - if (overwrite) fseek(fp,filepos,SEEK_SET); + if (overwrite) platform::fseek(fp,filepos); fprintf(fp,BIGINT_FORMAT " %d\n",ntimestep,nrows); for (i = 0; i < nrows; i++) { fprintf(fp,"%d",i+1); @@ -894,9 +893,9 @@ void FixAveTime::invoke_vector(bigint ntimestep) } fflush(fp); if (overwrite) { - long fileend = ftell(fp); - if ((fileend > 0) && (ftruncate(fileno(fp),fileend))) - perror("Error while tuncating output"); + bigint fileend = platform::ftell(fp); + if ((fileend > 0) && (platform::ftruncate(fp,fileend))) + error->warning(FLERR,"Error while tuncating output: {}", utils::getsyserror()); } } } @@ -1066,23 +1065,23 @@ void FixAveTime::options(int iarg, int narg, char **arg) iarg += 1; } else if (strcmp(arg[iarg],"format") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command"); - delete [] format_user; + delete[] format_user; format_user = utils::strdup(arg[iarg+1]); format = format_user; iarg += 2; } else if (strcmp(arg[iarg],"title1") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command"); - delete [] title1; + delete[] title1; title1 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title2") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command"); - delete [] title2; + delete[] title2; title2 = utils::strdup(arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"title3") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command"); - delete [] title3; + delete[] title3; title3 = utils::strdup(arg[iarg+1]); iarg += 2; } else error->all(FLERR,"Illegal fix ave/time command"); diff --git a/src/fix_ave_time.h b/src/fix_ave_time.h index 391a06f495..3a26dd6d70 100644 --- a/src/fix_ave_time.h +++ b/src/fix_ave_time.h @@ -54,7 +54,7 @@ class FixAveTime : public Fix { int *offlist; char *format, *format_user; char *title1, *title2, *title3; - long filepos; + bigint filepos; int norm, iwindow, window_limit; double *vector; From 40f683c1a76d931141c60158af299019cd712e40 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 4 Oct 2021 18:14:21 -0400 Subject: [PATCH 14/84] use platform functions to handle piping help output to a pager when on a console --- src/lammps.cpp | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/lammps.cpp b/src/lammps.cpp index f6c4474cd5..83a7115dcf 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -56,12 +56,6 @@ #include #include -#if defined(_WIN32) -#include -#else -#include // for isatty() -#endif - #include "lmpinstalledpkgs.h" #include "lmpgitversion.h" @@ -1118,11 +1112,7 @@ void _noopt LAMMPS::help() // user. scrollback buffers are often not large enough. this is most // beneficial to windows users, who are not used to command line. -#if defined(_WIN32) - int use_pager = _isatty(fileno(fp)); -#else - int use_pager = isatty(fileno(fp)); -#endif + int use_pager = platform::is_console(fp); // cannot use this with OpenMPI since its console is non-functional @@ -1133,11 +1123,7 @@ void _noopt LAMMPS::help() if (use_pager) { pager = getenv("PAGER"); if (pager == nullptr) pager = "more"; -#if defined(_WIN32) - fp = _popen(pager,"w"); -#else - fp = popen(pager,"w"); -#endif + fp = platform::popen(pager,"w"); // reset to original state, if pipe command failed if (fp == nullptr) { @@ -1299,7 +1285,7 @@ void _noopt LAMMPS::help() // close pipe to pager, if active - if (pager != nullptr) pclose(fp); + if (pager != nullptr) platform::pclose(fp); } /* ---------------------------------------------------------------------- From ee594a879b1dd27f428c8ee4e2fdaa612d911f45 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 4 Oct 2021 22:39:24 -0400 Subject: [PATCH 15/84] make use of platform::putenv() --- src/PLUMED/fix_plumed.cpp | 4 ++-- src/input.cpp | 15 +-------------- src/lammps.cpp | 7 ++++--- 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/PLUMED/fix_plumed.cpp b/src/PLUMED/fix_plumed.cpp index 7a142b57f8..137cd580a8 100644 --- a/src/PLUMED/fix_plumed.cpp +++ b/src/PLUMED/fix_plumed.cpp @@ -41,7 +41,7 @@ #if defined(__PLUMED_DEFAULT_KERNEL) #define PLUMED_QUOTE_DIRECT(name) #name #define PLUMED_QUOTE(macro) PLUMED_QUOTE_DIRECT(macro) -static char plumed_default_kernel[] = "PLUMED_KERNEL=" PLUMED_QUOTE(__PLUMED_DEFAULT_KERNEL); +static const char plumed_default_kernel[] = "PLUMED_KERNEL=" PLUMED_QUOTE(__PLUMED_DEFAULT_KERNEL); #endif /* -------------------------------------------------------------------- */ @@ -68,7 +68,7 @@ FixPlumed::FixPlumed(LAMMPS *lmp, int narg, char **arg) : #if defined(__PLUMED_DEFAULT_KERNEL) if (getenv("PLUMED_KERNEL") == nullptr) - putenv(plumed_default_kernel); + platform::putenv(plumed_default_kernel); #endif p=new PLMD::Plumed; diff --git a/src/input.cpp b/src/input.cpp index 833dbaa6df..c9b471f599 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -1241,20 +1241,7 @@ void Input::shell() if (narg < 2) error->all(FLERR,"Illegal shell putenv command"); for (int i = 1; i < narg; i++) { rv = 0; -#ifdef _WIN32 - if (arg[i]) rv = _putenv(utils::strdup(arg[i])); -#else - if (arg[i]) { - std::string vardef(arg[i]); - auto found = vardef.find_first_of('='); - if (found == std::string::npos) { - rv = setenv(vardef.c_str(),"",1); - } else { - rv = setenv(vardef.substr(0,found).c_str(), - vardef.substr(found+1).c_str(),1); - } - } -#endif + if (arg[i]) rv = platform::putenv(arg[i]); rv = (rv < 0) ? errno : 0; MPI_Reduce(&rv,&err,1,MPI_INT,MPI_MAX,0,world); if (me == 0 && err != 0) { diff --git a/src/lammps.cpp b/src/lammps.cpp index 83a7115dcf..e24c42689f 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -134,15 +134,16 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : init_pkg_lists(); #if defined(LMP_PYTHON) && defined(_WIN32) - // if the LAMMPSHOME environment variable is set, it should point + // If the LAMMPSHOME environment variable is set, it should point // to the location of the LAMMPS installation tree where we bundle // the matching Python installation for use with the PYTHON package. - // this is currently only used on Windows with the windows installer packages + // This is currently only used on Windows with the Windows installer packages const char *lmpenv = getenv("LAMMPSHOME"); if (lmpenv) { - _putenv(utils::strdup(fmt::format("PYTHONHOME={}",lmpenv))); + platform::putenv(fmt::format("PYTHONHOME={}",lmpenv)); } #endif + // check if -mpicolor is first arg // if so, then 2 apps were launched with one mpirun command // this means passed communicator (e.g. MPI_COMM_WORLD) is bigger than LAMMPS From 0bdc6d47e05651cf6e69b5baa2b068945f014358 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 4 Oct 2021 22:40:40 -0400 Subject: [PATCH 16/84] port molfile plugin reader to platform namespace --- src/MOLFILE/dump_molfile.cpp | 14 +- src/MOLFILE/molfile_interface.cpp | 260 ++++-------------------------- src/platform.cpp | 2 +- 3 files changed, 37 insertions(+), 239 deletions(-) diff --git a/src/MOLFILE/dump_molfile.cpp b/src/MOLFILE/dump_molfile.cpp index 052fb444a4..35e87f94af 100644 --- a/src/MOLFILE/dump_molfile.cpp +++ b/src/MOLFILE/dump_molfile.cpp @@ -26,8 +26,8 @@ #include "memory.h" #include "update.h" -#include #include +#include #include "molfile_interface.h" @@ -131,9 +131,9 @@ DumpMolfile::~DumpMolfile() if (typenames) { for (int i = 1; i <= ntypes; i++) - delete [] typenames[i]; + delete[] typenames[i]; - delete [] typenames; + delete[] typenames; typenames = nullptr; } } @@ -152,8 +152,7 @@ void DumpMolfile::init_style() typenames = new char*[ntypes+1]; for (int itype = 1; itype <= ntypes; itype++) { /* a 32-bit int can be maximally 10 digits plus sign */ - typenames[itype] = new char[12]; - sprintf(typenames[itype],"%d",itype); + typenames[itype] = utils::strdup(std::to_string(itype)); } } @@ -207,6 +206,7 @@ void DumpMolfile::write() } } ntotal = 0; + reorderflag = 0; // if file per timestep, open new file @@ -430,9 +430,9 @@ int DumpMolfile::modify_param(int narg, char **arg) if (typenames) { for (int i = 1; i <= ntypes; i++) - delete [] typenames[i]; + delete[] typenames[i]; - delete [] typenames; + delete[] typenames; typenames = nullptr; } diff --git a/src/MOLFILE/molfile_interface.cpp b/src/MOLFILE/molfile_interface.cpp index 8e1174d8f4..e18f62b337 100644 --- a/src/MOLFILE/molfile_interface.cpp +++ b/src/MOLFILE/molfile_interface.cpp @@ -17,6 +17,11 @@ ------------------------------------------------------------------------- */ #include "molfile_interface.h" + +#include "platform.h" +#include "tokenizer.h" +#include "utils.h" + #include "molfile_plugin.h" #include @@ -25,13 +30,6 @@ #include #include // for strcasecmp() -#if defined(_WIN32) -#include -#else -#include -#include -#endif - #if vmdplugin_ABIVERSION < 16 #error "unsupported VMD molfile plugin ABI version" #endif @@ -199,172 +197,17 @@ extern "C" { return 0; } - // directory traversal helper functions - -#if defined(_WIN32) - - // Win32 directory traversal handle - typedef struct { - HANDLE h; - WIN32_FIND_DATA fd; - char *name; - char *searchname; - int dlen; - } dirhandle_t; - - // open a directory handle - static dirhandle_t *my_opendir(const char *dirname) - { - dirhandle_t *d; - int len; - - if (dirname == nullptr) - return nullptr; - d = new dirhandle_t; - - len = 2 + strlen(dirname); - d->name = new char[len]; - strcpy(d->name, dirname); - strcat(d->name, "\\"); - d->dlen = len; - - len += 1; - d->searchname = new char[len]; - strcpy(d->searchname, dirname); - strcat(d->searchname, "\\*"); - - d->h = FindFirstFile(d->searchname, &(d->fd)); - if (d->h == ((HANDLE)(-1))) { - delete[] d->searchname; - delete[] d->name; - delete d; - return nullptr; - } - return d; - } - - // get next file name from directory handle - static char *my_readdir(dirhandle_t *d) - { - if (FindNextFile(d->h, &(d->fd))) { - return d->fd.cFileName; - } - return nullptr; - } - - // close directory handle - static void my_closedir(dirhandle_t *d) - { - if (d->h != nullptr) { - FindClose(d->h); - } - delete[] d->searchname; - delete[] d->name; - delete d; - } - - // open a shared object file - static void *my_dlopen(const char *fname) { - return (void *)LoadLibrary(fname); - } - - // resolve a symbol in shared object - static void *my_dlsym(void *h, const char *sym) { - return (void *)GetProcAddress((HINSTANCE)h, sym); - } - - // close a shared object - static int my_dlclose(void *h) { - /* FreeLibrary returns nonzero on success */ - return !FreeLibrary((HINSTANCE)h); - } - -#else - - // Unix directory traversal handle - typedef struct { - DIR *d; - char *name; - int dlen; - } dirhandle_t; - - // open a directory handle - static dirhandle_t *my_opendir(const char *dirname) - { - dirhandle_t *d; - int len; - - if (dirname == nullptr) return nullptr; - - d = new dirhandle_t; - len = 2 + strlen(dirname); - d->name = new char[len]; - strcpy(d->name,dirname); - strcat(d->name,"/"); - d->dlen = len; - - d->d = opendir(d->name); - if (d->d == nullptr) { - delete[] d->name; - delete d; - return nullptr; - } - return d; - } - - // get next file name from directory handle - static char *my_readdir(dirhandle_t *d) - { - struct dirent *p; - - if ((p = readdir(d->d)) != nullptr) { - return p->d_name; - } - - return nullptr; - } - - // close directory handle - static void my_closedir(dirhandle_t *d) - { - if (d->d != nullptr) { - closedir(d->d); - } - delete[] d->name; - delete d; - return; - } - - // open a shared object file - static void *my_dlopen(const char *fname) { - return dlopen(fname, RTLD_NOW); - } - - // resolve a symbol in shared object - static void *my_dlsym(void *h, const char *sym) { - return dlsym(h, sym); - } - - // close a shared object - static int my_dlclose(void *h) { - return dlclose(h); - } - -#endif - } // end of extern "C" region using namespace LAMMPS_NS; // constructor. MolfileInterface::MolfileInterface(const char *type, const int mode) - : _plugin(0), _dso(0), _ptr(0), _info(0), _natoms(0), - _mode(mode), _caps(M_NONE) + : _plugin(nullptr), _dso(nullptr), _ptr(nullptr), _info(nullptr), _natoms(0), + _mode(mode), _caps(M_NONE), _props(0) { - _name = new char[5]; - strcpy(_name,"none"); - _type = new char[1+strlen(type)]; - strcpy(_type,type); + _name = utils::strdup("none"); + _type = utils::strdup(type); } // destructor. @@ -384,62 +227,21 @@ MolfileInterface::~MolfileInterface() // register the best matching plugin in a given directory int MolfileInterface::find_plugin(const char *pluginpath) { - dirhandle_t *dir; - char *filename, *ext, *next, *path, *plugindir; int retval = E_NONE; -#if defined(_WIN32) -#define MY_PATHSEP ';' -#else -#define MY_PATHSEP ':' -#endif if (pluginpath == nullptr) return E_DIR; - plugindir = path = strdup(pluginpath); - while (plugindir) { - // check if this a single directory or path. - next = strchr(plugindir,MY_PATHSEP); - if (next) { - *next = '\0'; - ++next; + // search for suitable file names in provided path and try to inspect them + // only look at .so files, since this is what VMD uses on all platforms + + for (const auto &dir : Tokenizer(pluginpath,":").as_vector()) { + for (const auto &filename : platform::list_directory(dir)) { + if (utils::strmatch(filename,"\\.so$")) { + int rv = load_plugin(platform::path_join(dir,filename).c_str()); + if (rv > retval) retval = rv; + } } - - dir = my_opendir(plugindir); - if (!dir) - retval = (retval > E_DIR) ? retval : E_DIR; - - // search for suitable file names and try to inspect them - while (dir) { - char *fullname; - int len; - - filename = my_readdir(dir); - if (filename == nullptr) break; - - // only look at .so files - ext = strrchr(filename, '.'); - if (ext == nullptr) continue; - if (strcasecmp(ext,".so") != 0) continue; - - // construct full pathname of potential DSO - len = dir->dlen; - len += strlen(filename); - fullname = new char[len]; - strcpy(fullname,dir->name); - strcat(fullname,filename); - - // try to register plugin at file name. - int rv = load_plugin(fullname); - if (rv > retval) retval = rv; - - delete[] fullname; - } - if (dir) - my_closedir(dir); - - plugindir = next; } - free(path); return retval; } @@ -450,22 +252,22 @@ int MolfileInterface::load_plugin(const char *filename) int len, retval = E_NONE; // access shared object - dso = my_dlopen(filename); + dso = platform::dlopen(filename); if (dso == nullptr) return E_FILE; // check for required plugin symbols - void *ifunc = my_dlsym(dso,"vmdplugin_init"); - void *rfunc = my_dlsym(dso,"vmdplugin_register"); - void *ffunc = my_dlsym(dso,"vmdplugin_fini"); + void *ifunc = platform::dlsym(dso,"vmdplugin_init"); + void *rfunc = platform::dlsym(dso,"vmdplugin_register"); + void *ffunc = platform::dlsym(dso,"vmdplugin_fini"); if (ifunc == nullptr || rfunc == nullptr || ffunc == nullptr) { - my_dlclose(dso); + platform::dlclose(dso); return E_SYMBOL; } // initialize plugin. skip plugin if it fails. if (((initfunc)(ifunc))()) { - my_dlclose(dso); + platform::dlclose(dso); return E_SYMBOL; } @@ -528,12 +330,8 @@ int MolfileInterface::load_plugin(const char *filename) forget_plugin(); delete[] _name; - len = 16; - len += strlen(plugin->prettyname); - len += strlen(plugin->author); - _name = new char[len]; - sprintf(_name,"%s v%d.%d by %s",plugin->prettyname, - plugin->majorv, plugin->minorv, plugin->author); + _name = utils::strdup(fmt::format("{} v{}.{} by {}", plugin->prettyname, + plugin->majorv, plugin->minorv, plugin->author)); // determine plugin capabilities _caps = M_NONE; @@ -569,7 +367,7 @@ int MolfileInterface::load_plugin(const char *filename) } // better luck next time. clean up and return. - my_dlclose(dso); + platform::dlclose(dso); return retval; } @@ -583,10 +381,10 @@ void MolfileInterface::forget_plugin() _plugin = nullptr; if (_dso) { - void *ffunc = my_dlsym(_dso,"vmdplugin_fini"); + void *ffunc = platform::dlsym(_dso,"vmdplugin_fini"); if (ffunc) ((finifunc)ffunc)(); - my_dlclose(_dso); + platform::dlclose(_dso); } _dso = nullptr; diff --git a/src/platform.cpp b/src/platform.cpp index ed007e089a..2f04ee0068 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -527,7 +527,7 @@ void *platform::dlsym(void *handle, const std::string &symbol) // open a shared object file void *platform::dlopen(const std::string &fname) { - return ::dlopen(fname.c_str(), RTLD_NOW); + return ::dlopen(fname.c_str(), RTLD_NOW | RTLD_GLOBAL); } // close a shared object From 741cf9c7d59f876424bff642f117b6f2b148932e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 07:36:22 -0400 Subject: [PATCH 17/84] remove obsoleted include statements --- src/utils.cpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index 55514fdd59..3afd87ba7b 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -31,25 +31,6 @@ #include #include -#if defined(__linux__) -#include // for readlink -#endif - -#if defined(__APPLE__) -#include // for fcntl -#include -#endif - -#if defined(_WIN32) -// target Windows version is Windows 7 and later -#if defined(_WIN32_WINNT) -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT _WIN32_WINNT_WIN7 -#include -#include -#endif - /*! \file utils.cpp */ /* From af070aa351938f688ffef63be40f6712e1bcbbec Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 15:44:58 -0400 Subject: [PATCH 18/84] add support for seeking to the end of a file --- src/platform.cpp | 10 ++++++++-- src/platform.h | 5 +++++ unittest/utils/test_platform.cpp | 4 +++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/platform.cpp b/src/platform.cpp index 2f04ee0068..866e34b4cc 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -767,9 +767,15 @@ bigint platform::ftell(FILE *fp) int platform::fseek(FILE *fp, bigint pos) { #if defined(_WIN32) - return ::_fseeki64(fp, (__int64) pos, SEEK_SET); + if (pos == platform::END_OF_FILE) + return ::_fseeki64(fp, 0, SEEK_END); + else + return ::_fseeki64(fp, (__int64) pos, SEEK_SET); #else - return ::fseek(fp, (long) pos, SEEK_SET); + if (pos == platform::END_OF_FILE) + return ::fseek(fp, 0, SEEK_END); + else + return ::fseek(fp, (long) pos, SEEK_SET); #endif } diff --git a/src/platform.h b/src/platform.h index b7c5d28561..97057006ad 100644 --- a/src/platform.h +++ b/src/platform.h @@ -263,7 +263,12 @@ namespace platform { bigint ftell(FILE *fp); + /*! constant to seek to the end of the file */ + constexpr bigint END_OF_FILE = -1; + /*! Set absolute file position + * + * If the absolute position is END_OF_FILE, then position at the end of the file. * * \param fp FILE pointer of the given file * \param pos new position of the FILE pointer diff --git a/unittest/utils/test_platform.cpp b/unittest/utils/test_platform.cpp index 6c17b8876e..c5d04d3b94 100644 --- a/unittest/utils/test_platform.cpp +++ b/unittest/utils/test_platform.cpp @@ -170,7 +170,9 @@ TEST(Platform, fseek_ftell) ASSERT_EQ(platform::fseek(fp, 15), 0); ASSERT_EQ(fgetc(fp), '6'); fflush(fp); - fseek(fp, -1, SEEK_END); + ASSERT_EQ(platform::fseek(fp, platform::END_OF_FILE), 0); + ASSERT_EQ(platform::ftell(fp), 21); + ASSERT_EQ(platform::fseek(fp, 20), 0); ASSERT_EQ(fgetc(fp), 0); ASSERT_EQ(platform::ftell(fp), 21); fclose(fp); From 5128eb7b438ca96c1972336cf42f6560d8f31992 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 15:45:42 -0400 Subject: [PATCH 19/84] port read/write_restart to use the platform namespace --- src/read_restart.cpp | 26 ++++++++++++-------------- src/write_restart.cpp | 2 +- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/read_restart.cpp b/src/read_restart.cpp index dd36175a90..caa19d46fb 100644 --- a/src/read_restart.cpp +++ b/src/read_restart.cpp @@ -35,7 +35,6 @@ #include "update.h" #include -#include #include "lmprestart.h" @@ -117,6 +116,7 @@ void ReadRestart::command(int narg, char **arg) magic_string(); endian(); format_revision(); + check_eof_magic(); // read header info which creates simulation box @@ -557,20 +557,16 @@ std::string ReadRestart::file_search(const std::string &inpfile) if (loc != std::string::npos) { // convert pattern to equivalent regexp pattern.replace(loc,1,"\\d+"); - struct dirent *ep; - DIR *dp = opendir(dirname.c_str()); - if (dp == nullptr) - error->one(FLERR,"Cannot open directory {} to search for restart file: {}", - dirname, utils::getsyserror()); - while ((ep = readdir(dp))) { - std::string candidate(ep->d_name); + if (!platform::path_is_directory(dirname)) + error->one(FLERR,"Cannot open directory {} to search for restart file: {}",dirname); + + for (const auto &candidate : platform::list_directory(dirname)) { if (utils::strmatch(candidate,pattern)) { bigint num = ATOBIGINT(utils::strfind(candidate.substr(loc),"\\d+").c_str()); if (num > maxnum) maxnum = num; } } - closedir(dp); if (maxnum < 0) error->one(FLERR,"Found no restart file matching pattern"); filename.replace(filename.find('*'),1,std::to_string(maxnum)); } @@ -1084,11 +1080,11 @@ void ReadRestart::file_layout() flag = read_int(); } - // if MPI-IO file, broadcast the end of the header offste + // if MPI-IO file, broadcast the end of the header offset // this allows all ranks to compute offset to their data if (mpiioflag) { - if (me == 0) headerOffset = ftell(fp); + if (me == 0) headerOffset = platform::ftell(fp); MPI_Bcast(&headerOffset,1,MPI_LMP_BIGINT,0,world); } } @@ -1152,10 +1148,12 @@ void ReadRestart::check_eof_magic() // read magic string at end of file and restore file pointer if (me == 0) { - long curpos = ftell(fp); - fseek(fp,(long)-n,SEEK_END); + bigint curpos = platform::ftell(fp); + platform::fseek(fp,platform::END_OF_FILE); + bigint offset = platform::ftell(fp) - n; + platform::fseek(fp,offset); utils::sfread(FLERR,str,sizeof(char),n,fp,nullptr,error); - fseek(fp,curpos,SEEK_SET); + platform::fseek(fp,curpos); } MPI_Bcast(str,n,MPI_CHAR,0,world); diff --git a/src/write_restart.cpp b/src/write_restart.cpp index 7f73d868ff..4333fa5416 100644 --- a/src/write_restart.cpp +++ b/src/write_restart.cpp @@ -595,7 +595,7 @@ void WriteRestart::file_layout(int send_size) // this allows all ranks to compute offset to their data if (mpiioflag) { - if (me == 0) headerOffset = ftell(fp); + if (me == 0) headerOffset = platform::ftell(fp); MPI_Bcast(&headerOffset,1,MPI_LMP_BIGINT,0,world); } } From e3e82df9954edb71acf1d9023ce034edb4eedc64 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 16:36:06 -0400 Subject: [PATCH 20/84] port "embedded" shell commands to use platform functions --- src/input.cpp | 85 ++++++++++++++++----------------------------------- 1 file changed, 27 insertions(+), 58 deletions(-) diff --git a/src/input.cpp b/src/input.cpp index c9b471f599..21c092f356 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -49,11 +49,6 @@ #include #include #include -#include - -#ifdef _WIN32 -#include -#endif using namespace LAMMPS_NS; @@ -1164,15 +1159,6 @@ void Input::quit() /* ---------------------------------------------------------------------- */ -char *shell_failed_message(const char* cmd, int errnum) -{ - std::string errmsg = fmt::format("Shell command '{}' failed with error '{}'", - cmd, strerror(errnum)); - char *msg = new char[errmsg.size()+1]; - strcpy(msg, errmsg.c_str()); - return msg; -} - void Input::shell() { int rv,err; @@ -1181,62 +1167,47 @@ void Input::shell() if (strcmp(arg[0],"cd") == 0) { if (narg != 2) error->all(FLERR,"Illegal shell cd command"); - rv = (chdir(arg[1]) < 0) ? errno : 0; + rv = (platform::chdir(arg[1]) < 0) ? errno : 0; MPI_Reduce(&rv,&err,1,MPI_INT,MPI_MAX,0,world); + errno = err; if (me == 0 && err != 0) { - char *message = shell_failed_message("cd",err); - error->warning(FLERR,message); - delete[] message; + error->warning(FLERR, "Shell command 'cd {}' failed with error '{}'", arg[1], utils::getsyserror()); } - } else if (strcmp(arg[0],"mkdir") == 0) { if (narg < 2) error->all(FLERR,"Illegal shell mkdir command"); - if (me == 0) + if (me == 0) { for (int i = 1; i < narg; i++) { -#if defined(_WIN32) - rv = _mkdir(arg[i]); -#else - rv = mkdir(arg[i], S_IRWXU | S_IRGRP | S_IXGRP); -#endif - if (rv < 0) { - char *message = shell_failed_message("mkdir",errno); - error->warning(FLERR,message); - delete[] message; - } + if (platform::mkdir(arg[i]) < 0) + error->warning(FLERR, "Shell command 'mkdir {}' failed with error '{}'", + arg[i],utils::getsyserror()); } - + } } else if (strcmp(arg[0],"mv") == 0) { if (narg != 3) error->all(FLERR,"Illegal shell mv command"); - rv = (rename(arg[1],arg[2]) < 0) ? errno : 0; - MPI_Reduce(&rv,&err,1,MPI_INT,MPI_MAX,0,world); - if (me == 0 && err != 0) { - char *message = shell_failed_message("mv",err); - error->warning(FLERR,message); - delete[] message; + if (me == 0) { + if (rename(arg[1],arg[2]) < 0) { + error->warning(FLERR, "Shell command 'mv {} {}' failed with error '{}'", + arg[1],arg[2],utils::getsyserror()); + } } - } else if (strcmp(arg[0],"rm") == 0) { if (narg < 2) error->all(FLERR,"Illegal shell rm command"); - if (me == 0) + if (me == 0) { for (int i = 1; i < narg; i++) { - if (unlink(arg[i]) < 0) { - char *message = shell_failed_message("rm",errno); - error->warning(FLERR,message); - delete[] message; - } + if (platform::unlink(arg[i]) < 0) + error->warning(FLERR, "Shell command 'rm {}' failed with error '{}'", + arg[i], utils::getsyserror()); } - + } } else if (strcmp(arg[0],"rmdir") == 0) { if (narg < 2) error->all(FLERR,"Illegal shell rmdir command"); - if (me == 0) + if (me == 0) { for (int i = 1; i < narg; i++) { - if (rmdir(arg[i]) < 0) { - char *message = shell_failed_message("rmdir",errno); - error->warning(FLERR,message); - delete[] message; - } + if (platform::rmdir(arg[i]) < 0) + error->warning(FLERR, "Shell command 'rmdir {}' failed with error '{}'", + arg[i], utils::getsyserror()); } - + } } else if (strcmp(arg[0],"putenv") == 0) { if (narg < 2) error->all(FLERR,"Illegal shell putenv command"); for (int i = 1; i < narg; i++) { @@ -1244,13 +1215,11 @@ void Input::shell() if (arg[i]) rv = platform::putenv(arg[i]); rv = (rv < 0) ? errno : 0; MPI_Reduce(&rv,&err,1,MPI_INT,MPI_MAX,0,world); - if (me == 0 && err != 0) { - char *message = shell_failed_message("putenv",err); - error->warning(FLERR,message); - delete[] message; - } + errno = err; + if (me == 0 && err != 0) + error->warning(FLERR, "Shell command 'putenv {}' failed with error '{}'", + arg[i], utils::getsyserror()); } - // use work string to concat args back into one string separated by spaces // invoke string in shell via system() From 0c6707bf0c77b980507e3944de9844928e643303 Mon Sep 17 00:00:00 2001 From: Stan Moore Date: Tue, 5 Oct 2021 14:49:30 -0600 Subject: [PATCH 21/84] Fix compile issue with bond_class2_kokkos and UVM-enabled --- src/KOKKOS/bond_class2_kokkos.cpp | 20 ++++++++++---------- src/KOKKOS/bond_class2_kokkos.h | 9 +++++---- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/KOKKOS/bond_class2_kokkos.cpp b/src/KOKKOS/bond_class2_kokkos.cpp index e538c8e045..b4e87b4119 100644 --- a/src/KOKKOS/bond_class2_kokkos.cpp +++ b/src/KOKKOS/bond_class2_kokkos.cpp @@ -68,14 +68,14 @@ void BondClass2Kokkos::compute(int eflag_in, int vflag_in) //if(k_eatom.extent(0)destroy_kokkos(k_eatom,eatom); memoryKK->create_kokkos(k_eatom,eatom,maxeatom,"improper:eatom"); - d_eatom = k_eatom.template view(); + d_eatom = k_eatom.template view(); //} } if (vflag_atom) { //if(k_vatom.extent(0)destroy_kokkos(k_vatom,vatom); memoryKK->create_kokkos(k_vatom,vatom,maxvatom,"improper:vatom"); - d_vatom = k_vatom.template view(); + d_vatom = k_vatom.template view(); //} } @@ -210,10 +210,10 @@ void BondClass2Kokkos::coeff(int narg, char **arg) BondClass2::coeff(narg, arg); int n = atom->nbondtypes; - Kokkos::DualView k_k2("BondClass2::k2",n+1); - Kokkos::DualView k_k3("BondClass2::k3",n+1); - Kokkos::DualView k_k4("BondClass2::k4",n+1); - Kokkos::DualView k_r0("BondClass2::r0",n+1); + typename AT::tdual_ffloat_1d k_k2("BondClass2::k2",n+1); + typename AT::tdual_ffloat_1d k_k3("BondClass2::k3",n+1); + typename AT::tdual_ffloat_1d k_k4("BondClass2::k4",n+1); + typename AT::tdual_ffloat_1d k_r0("BondClass2::r0",n+1); d_k2 = k_k2.template view(); d_k3 = k_k3.template view(); @@ -247,10 +247,10 @@ void BondClass2Kokkos::read_restart(FILE *fp) BondClass2::read_restart(fp); int n = atom->nbondtypes; - Kokkos::DualView k_k2("BondClass2::k2",n+1); - Kokkos::DualView k_k3("BondClass2::k3",n+1); - Kokkos::DualView k_k4("BondClass2::k4",n+1); - Kokkos::DualView k_r0("BondClass2::r0",n+1); + typename AT::tdual_ffloat_1d k_k2("BondClass2::k2",n+1); + typename AT::tdual_ffloat_1d k_k3("BondClass2::k3",n+1); + typename AT::tdual_ffloat_1d k_k4("BondClass2::k4",n+1); + typename AT::tdual_ffloat_1d k_r0("BondClass2::r0",n+1); d_k2 = k_k2.template view(); d_k3 = k_k3.template view(); diff --git a/src/KOKKOS/bond_class2_kokkos.h b/src/KOKKOS/bond_class2_kokkos.h index 52136030aa..529046845f 100644 --- a/src/KOKKOS/bond_class2_kokkos.h +++ b/src/KOKKOS/bond_class2_kokkos.h @@ -67,10 +67,11 @@ class BondClass2Kokkos : public BondClass2 { typename Kokkos::View::value,Kokkos::MemoryTraits > f; typename AT::t_int_2d bondlist; - Kokkos::DualView k_eatom; - Kokkos::DualView k_vatom; - Kokkos::View::value,Kokkos::MemoryTraits > d_eatom; - Kokkos::View::value,Kokkos::MemoryTraits > d_vatom; + typedef typename KKDevice::value KKDeviceType; + Kokkos::DualView k_eatom; + Kokkos::DualView k_vatom; + Kokkos::View > d_eatom; + Kokkos::View > d_vatom; int nlocal,newton_bond; int eflag,vflag; From 528050aa087654c428dc72f3d80ef299af54ed1b Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 17:57:38 -0400 Subject: [PATCH 22/84] use platform namespace to delete file --- src/write_coeff.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/write_coeff.cpp b/src/write_coeff.cpp index e030148901..6f53a97e8f 100644 --- a/src/write_coeff.cpp +++ b/src/write_coeff.cpp @@ -26,7 +26,6 @@ #include #include -#include using namespace LAMMPS_NS; @@ -170,8 +169,8 @@ void WriteCoeff::command(int narg, char **arg) } fclose(one); fclose(two); - unlink(file); + platform::unlink(file); } - delete [] file; + delete[] file; } From fcdabe0002d7af458dc869a120233dfe52704229 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 17:58:27 -0400 Subject: [PATCH 23/84] implement a platform neutral usleep() using C++11 --- src/platform.cpp | 10 ++++++++++ src/platform.h | 9 +++++++++ src/variable.cpp | 7 +++---- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/platform.cpp b/src/platform.cpp index 866e34b4cc..9039816f12 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -61,7 +61,9 @@ #endif //////////////////////////////////////////////////////////////////////// +#include #include +#include /* ------------------------------------------------------------------ */ @@ -172,6 +174,14 @@ double platform::walltime() return wtime; } +/* ---------------------------------------------------------------------- + sleep with microsecond resolution +------------------------------------------------------------------------ */ +void platform::usleep(int usec) +{ + return std::this_thread::sleep_for(std::chrono::microseconds(usec)); +} + /* ---------------------------------------------------------------------- get Operating system and version info ------------------------------------------------------------------------- */ diff --git a/src/platform.h b/src/platform.h index 97057006ad..31710caf2e 100644 --- a/src/platform.h +++ b/src/platform.h @@ -42,6 +42,15 @@ namespace platform { double walltime(); + + /*! Suspend execution for a microsecond interval + * + * This emulates the usleep(3) BSD function call also mentioned in POSIX.1-2001. + * + * \param usec length of delay in microseconds */ + + void usleep(int usec); + /*! Return string with the operating system version and architecture info * * \return string with info about the OS and the platform is is running on */ diff --git a/src/variable.cpp b/src/variable.cpp index 1981d000c3..22f792b5ec 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -39,7 +39,6 @@ #include #include #include -#include #include using namespace LAMMPS_NS; @@ -692,11 +691,11 @@ int Variable::next(int narg, char **arg) int seed = 12345 + universe->me + which[find(arg[0])]; if (!random) random = new RanMars(lmp,seed); int delay = (int) (1000000*random->uniform()); - usleep(delay); + platform::usleep(delay); while (1) { if (!rename("tmp.lammps.variable","tmp.lammps.variable.lock")) break; delay = (int) (1000000*random->uniform()); - usleep(delay); + platform::usleep(delay); } // if the file cannot be found, we may have a race with some @@ -719,7 +718,7 @@ int Variable::next(int narg, char **arg) break; } delay = (int) (1000000*random->uniform()); - usleep(delay); + platform::usleep(delay); } delete random; random = nullptr; From b2c4f08bbcae26e68e5744ecaaeb1fc955ef1ea6 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 21:52:52 -0400 Subject: [PATCH 24/84] use C++11 functionality to determine wall time --- src/platform.cpp | 21 +++++---------------- src/platform.h | 17 +++++++++++------ 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/platform.cpp b/src/platform.cpp index 9039816f12..18d760b34b 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -106,6 +106,10 @@ static const zip_info &find_zip_type(const std::string &file) /* ------------------------------------------------------------------ */ +// set reference time stamp during executable/library init. +// should provide better resolution than using epoch, if the system clock supports it. +static auto initial_time = std::chrono::steady_clock::now(); + using namespace LAMMPS_NS; // get CPU time @@ -156,22 +160,7 @@ double platform::cputime() ------------------------------------------------------------------------ */ double platform::walltime() { - double wtime; - -#if defined(_WIN32) - - wtime = GetTickCount64() * 0.001; - -#else - - struct timeval tv; - - gettimeofday(&tv, nullptr); - wtime = 1.0 * tv.tv_sec + 1.0e-6 * tv.tv_usec; - -#endif - - return wtime; + return std::chrono::duration(std::chrono::steady_clock::now() - initial_time).count(); } /* ---------------------------------------------------------------------- diff --git a/src/platform.h b/src/platform.h index 31710caf2e..ef45ceff9b 100644 --- a/src/platform.h +++ b/src/platform.h @@ -27,25 +27,30 @@ namespace platform { /*! Return the consumed CPU time for the current process in seconds * * This is a wrapper around the POSIX function getrusage() and its Windows equivalent. - * It is to be used in a similar fashion than MPI_Wtime(). + * It is to be used in a similar fashion than MPI_Wtime(). Its resolution may + * be rather low so it can only be trusted when observing processes consuming at + * seconds or more of CPU time. * - * \return used CPU time in second */ + * \return used CPU time in seconds */ double cputime(); /*! Return the wall clock state for the current process in seconds * - * This is a wrapper around the gettimeofday() function and its Windows equivalent. - * It is to be used in a similar fashion than MPI_Wtime(). + * This this clock is counting continuous time is initialized during + * Load of the executable/library. Its absolute value must be considered + * arbitrary and thus elapsed wall times are measured in taking differences. + * It is therefore to be used in a similar fashion as MPI_Wtime() but + * has a different offset, usually leading to better resolution. * - * \return wall clock time in second */ + * \return wall clock time in seconds */ double walltime(); - /*! Suspend execution for a microsecond interval * * This emulates the usleep(3) BSD function call also mentioned in POSIX.1-2001. + * This is not a precise delay; it may be longer, but not shorter. * * \param usec length of delay in microseconds */ From 6f2076a9b8ab308963d1f0bd1040c8aefa12bf0c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 21:57:53 -0400 Subject: [PATCH 25/84] update docs --- doc/src/Developer_platform.rst | 6 ++++++ doc/utils/sphinx-config/false_positives.txt | 1 + src/tokenizer.cpp | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/src/Developer_platform.rst b/doc/src/Developer_platform.rst index a31e9d1c72..74ad4c1aac 100644 --- a/doc/src/Developer_platform.rst +++ b/doc/src/Developer_platform.rst @@ -18,6 +18,9 @@ Time functions .. doxygenfunction:: walltime :project: progguide +.. doxygenfunction:: usleep + :project: progguide + Platform information functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,6 +91,9 @@ File and path functions and global constants Standard I/O function wrappers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. doxygenvariable:: END_OF_FILE + :project: progguide + .. doxygenfunction:: ftell :project: progguide diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 76127104e0..107e252074 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -3444,6 +3444,7 @@ usec uSemiParallel userguide username +usleep usr util utils diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 43660d68ec..71b4ad610e 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -46,8 +46,8 @@ TokenizerException::TokenizerException(const std::string &msg, const std::string \endverbatim * - * \param str string to be processed - * \param separators string with separator characters (default: " \t\r\n\f") */ + * \param str string to be processed + * \param _separators string with separator characters (default: " \t\r\n\f") */ Tokenizer::Tokenizer(const std::string &str, const std::string &_separators) : text(str), separators(_separators), start(0), ntokens(std::string::npos) From 087c1b3a65ac45e70f2259540be861ba3cc8f169 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 22:30:45 -0400 Subject: [PATCH 26/84] revive skipped code to detect OS revisions --- src/platform.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/platform.cpp b/src/platform.cpp index 18d760b34b..1936baaf87 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -16,6 +16,7 @@ * the "utils" namespace with convenience and utility functions. */ #include "platform.h" +#include "text_file_reader.h" #include "utils.h" #if HAVE_MPI @@ -227,14 +228,13 @@ std::string platform::os_info() // try to get OS distribution name, if available buf = ut.sysname; -#if 0 // disable until this is integrated into LAMMPS and TextFileReader becomes available if (platform::file_is_readable("/etc/os-release")) { try { TextFileReader reader("/etc/os-release",""); while (1) { auto words = reader.next_values(0,"="); if ((words.count() > 1) && (words.next_string() == "PRETTY_NAME")) { - distro += " " + utils::trim(words.next_string()); + buf += " " + utils::trim(words.next_string()); break; } } @@ -242,7 +242,6 @@ std::string platform::os_info() ; // EOF but keyword not found } } -#endif buf += std::string(" ") + ut.release + " " + ut.machine; #endif From cc2d23de217624064f902127c0466387182455db Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 22:31:06 -0400 Subject: [PATCH 27/84] use platform::cputtime() --- src/info.cpp | 18 +----------------- src/timer.cpp | 52 +++++---------------------------------------------- 2 files changed, 6 insertions(+), 64 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index 340ba15b0f..01ac7a095c 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -636,23 +636,7 @@ void Info::command(int narg, char **arg) if (flags & TIME) { double wallclock = MPI_Wtime() - lmp->initclock; - double cpuclock = 0.0; - -#if defined(_WIN32) - // from MSD docs. - FILETIME ct,et,kt,ut; - union { FILETIME ft; uint64_t ui; } cpu; - if (GetProcessTimes(GetCurrentProcess(),&ct,&et,&kt,&ut)) { - cpu.ft = ut; - cpuclock = cpu.ui * 0.0000001; - } -#else /* POSIX */ - struct rusage ru; - if (getrusage(RUSAGE_SELF, &ru) == 0) { - cpuclock = (double) ru.ru_utime.tv_sec; - cpuclock += (double) ru.ru_utime.tv_usec * 0.000001; - } -#endif /* ! _WIN32 */ + double cpuclock = platform::cputime(); int cpuh,cpum,cpus,wallh,wallm,walls; cpus = fmod(cpuclock,60.0); diff --git a/src/timer.cpp b/src/timer.cpp index b01a7aa9d6..4efee8871c 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -20,50 +20,8 @@ #include -#ifdef _WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#else -#include -#include -#endif - using namespace LAMMPS_NS; - -// Return the CPU time for the current process in seconds very -// much in the same way as MPI_Wtime() returns the wall time. - -static double CPU_Time() -{ - double rv = 0.0; - -#ifdef _WIN32 - - // from MSD docs. - FILETIME ct,et,kt,ut; - union { FILETIME ft; uint64_t ui; } cpu; - if (GetProcessTimes(GetCurrentProcess(),&ct,&et,&kt,&ut)) { - cpu.ft = ut; - rv = cpu.ui * 0.0000001; - } - -#else /* ! _WIN32 */ - - struct rusage ru; - if (getrusage(RUSAGE_SELF, &ru) == 0) { - rv = (double) ru.ru_utime.tv_sec; - rv += (double) ru.ru_utime.tv_usec * 0.000001; - } - -#endif /* ! _WIN32 */ - - return rv; -} - /* ---------------------------------------------------------------------- */ Timer::Timer(LAMMPS *lmp) : Pointers(lmp) @@ -93,7 +51,7 @@ void Timer::_stamp(enum ttype which) { double current_cpu=0.0, current_wall=0.0; - if (_level > NORMAL) current_cpu = CPU_Time(); + if (_level > NORMAL) current_cpu = platform::cputime(); current_wall = MPI_Wtime(); if ((which > TOTAL) && (which < NUM_TIMER)) { @@ -117,7 +75,7 @@ void Timer::_stamp(enum ttype which) if (_sync) { MPI_Barrier(world); - if (_level > NORMAL) current_cpu = CPU_Time(); + if (_level > NORMAL) current_cpu = platform::cputime(); current_wall = MPI_Wtime(); cpu_array[SYNC] += current_cpu - previous_cpu; @@ -137,7 +95,7 @@ void Timer::barrier_start() if (_level < LOOP) return; - current_cpu = CPU_Time(); + current_cpu = platform::cputime(); current_wall = MPI_Wtime(); cpu_array[TOTAL] = current_cpu; @@ -156,7 +114,7 @@ void Timer::barrier_stop() if (_level < LOOP) return; - current_cpu = CPU_Time(); + current_cpu = platform::cputime(); current_wall = MPI_Wtime(); cpu_array[TOTAL] = current_cpu - cpu_array[TOTAL]; @@ -167,7 +125,7 @@ void Timer::barrier_stop() double Timer::cpu(enum ttype which) { - double current_cpu = CPU_Time(); + double current_cpu = platform::cputime(); return (current_cpu - cpu_array[which]); } From 46eaa4888e866fb616fef48a3e030a94102735c9 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 22:31:25 -0400 Subject: [PATCH 28/84] simplify using platform function --- src/utils.cpp | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index 3afd87ba7b..d67284822c 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1016,28 +1016,13 @@ bool utils::is_id(const std::string &str) std::string utils::get_potential_file_path(const std::string &path) { - std::string filepath = path; - std::string filename = platform::path_basename(path); - - if (platform::file_is_readable(filepath)) { - return filepath; + if (platform::file_is_readable(path)) { + return path; } else { - // try the environment variable directory - const char *var = getenv("LAMMPS_POTENTIALS"); - - if (var != nullptr) { -#if defined(_WIN32) - Tokenizer dirs(var, ";"); -#else - Tokenizer dirs(var, ":"); -#endif - while (dirs.has_next()) { - auto pot = platform::path_basename(filepath); - auto dir = dirs.next(); - filepath = platform::path_join(dir, pot); - - if (platform::file_is_readable(filepath)) { return filepath; } - } + for (const auto &dir : platform::list_pathenv("LAMMPS_POTENTIALS")) { + auto pot = platform::path_basename(path); + auto filepath = platform::path_join(dir, pot); + if (platform::file_is_readable(filepath)) return filepath; } } return ""; From f17aeebbcdea957e7c22458019e15ae354ce6a4e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 22:31:39 -0400 Subject: [PATCH 29/84] make compilable on windows --- src/KOKKOS/kokkos.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/KOKKOS/kokkos.cpp b/src/KOKKOS/kokkos.cpp index be32604f94..63a18ec387 100644 --- a/src/KOKKOS/kokkos.cpp +++ b/src/KOKKOS/kokkos.cpp @@ -23,7 +23,15 @@ #include #include #include -#include + +#if defined(_WIN32) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include // for _getpid() +#else +#include // for getpid() +#endif #ifdef LMP_KOKKOS_GPU @@ -591,6 +599,10 @@ int KokkosLMP::neigh_count(int m) void KokkosLMP::my_signal_handler(int sig) { if (sig == SIGSEGV) { +#if defined(_WIN32) + kill(_getpid(),SIGABRT); +#else kill(getpid(),SIGABRT); +#endif } } From 8b36061db408870be7ef5a7774741d92cd6adfd3 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 22:53:39 -0400 Subject: [PATCH 30/84] replace MPI_Wtime() with platform::walltime() --- src/DIFFRACTION/compute_saed.cpp | 4 ++-- src/DIFFRACTION/compute_xrd.cpp | 4 ++-- src/DPD-REACT/fix_rx.cpp | 2 +- src/GPU/pair_beck_gpu.cpp | 4 ++-- src/GPU/pair_born_coul_long_cs_gpu.cpp | 4 ++-- src/GPU/pair_born_coul_long_gpu.cpp | 4 ++-- src/GPU/pair_born_coul_wolf_cs_gpu.cpp | 4 ++-- src/GPU/pair_born_coul_wolf_gpu.cpp | 4 ++-- src/GPU/pair_born_gpu.cpp | 4 ++-- src/GPU/pair_buck_coul_cut_gpu.cpp | 4 ++-- src/GPU/pair_buck_coul_long_gpu.cpp | 4 ++-- src/GPU/pair_buck_gpu.cpp | 4 ++-- src/GPU/pair_colloid_gpu.cpp | 4 ++-- src/GPU/pair_coul_cut_gpu.cpp | 4 ++-- src/GPU/pair_coul_debye_gpu.cpp | 4 ++-- src/GPU/pair_coul_dsf_gpu.cpp | 4 ++-- src/GPU/pair_coul_long_cs_gpu.cpp | 4 ++-- src/GPU/pair_coul_long_gpu.cpp | 4 ++-- src/GPU/pair_dpd_gpu.cpp | 4 ++-- src/GPU/pair_dpd_tstat_gpu.cpp | 4 ++-- src/GPU/pair_gauss_gpu.cpp | 4 ++-- src/GPU/pair_gayberne_gpu.cpp | 4 ++-- src/GPU/pair_lj96_cut_gpu.cpp | 4 ++-- src/GPU/pair_lj_charmm_coul_charmm_gpu.cpp | 4 ++-- src/GPU/pair_lj_charmm_coul_long_gpu.cpp | 4 ++-- src/GPU/pair_lj_class2_coul_long_gpu.cpp | 4 ++-- src/GPU/pair_lj_class2_gpu.cpp | 4 ++-- src/GPU/pair_lj_cubic_gpu.cpp | 4 ++-- src/GPU/pair_lj_cut_coul_cut_gpu.cpp | 4 ++-- src/GPU/pair_lj_cut_coul_debye_gpu.cpp | 4 ++-- src/GPU/pair_lj_cut_coul_dsf_gpu.cpp | 4 ++-- src/GPU/pair_lj_cut_coul_long_gpu.cpp | 4 ++-- src/GPU/pair_lj_cut_coul_msm_gpu.cpp | 4 ++-- src/GPU/pair_lj_cut_dipole_cut_gpu.cpp | 4 ++-- src/GPU/pair_lj_cut_dipole_long_gpu.cpp | 4 ++-- src/GPU/pair_lj_cut_gpu.cpp | 4 ++-- src/GPU/pair_lj_cut_tip4p_long_gpu.cpp | 4 ++-- src/GPU/pair_lj_expand_coul_long_gpu.cpp | 4 ++-- src/GPU/pair_lj_expand_gpu.cpp | 4 ++-- src/GPU/pair_lj_gromacs_gpu.cpp | 4 ++-- src/GPU/pair_lj_sdk_coul_long_gpu.cpp | 4 ++-- src/GPU/pair_lj_sdk_gpu.cpp | 4 ++-- src/GPU/pair_lj_sf_dipole_sf_gpu.cpp | 4 ++-- src/GPU/pair_lj_smooth_gpu.cpp | 4 ++-- src/GPU/pair_mie_cut_gpu.cpp | 4 ++-- src/GPU/pair_morse_gpu.cpp | 4 ++-- src/GPU/pair_resquared_gpu.cpp | 4 ++-- src/GPU/pair_soft_gpu.cpp | 4 ++-- src/GPU/pair_table_gpu.cpp | 4 ++-- src/GPU/pair_ufm_gpu.cpp | 4 ++-- src/GPU/pair_yukawa_colloid_gpu.cpp | 4 ++-- src/GPU/pair_yukawa_gpu.cpp | 4 ++-- src/GPU/pair_zbl_gpu.cpp | 4 ++-- src/GPU/pppm_gpu.cpp | 4 ++-- src/INTEL/fix_intel.cpp | 2 +- src/KOKKOS/fix_rx_kokkos.cpp | 2 +- src/KOKKOS/pair_exp6_rx_kokkos.cpp | 2 +- src/KOKKOS/pppm_kokkos.cpp | 8 ++++---- src/KSPACE/pppm.cpp | 8 ++++---- src/KSPACE/pppm_dipole.cpp | 8 ++++---- src/KSPACE/pppm_disp.cpp | 16 ++++++++-------- src/REPLICA/fix_hyper_local.cpp | 18 +++++++++--------- src/REPLICA/tad.cpp | 4 ++-- src/RIGID/fix_rigid_small.cpp | 4 ++-- src/RIGID/fix_shake.cpp | 4 ++-- src/SMTBQ/pair_smtbq.cpp | 4 ++-- src/STUBS/mpi.cpp | 18 ++---------------- src/balance.cpp | 4 ++-- src/create_atoms.cpp | 4 ++-- src/info.cpp | 2 +- src/lammps.cpp | 4 ++-- src/read_data.cpp | 4 ++-- src/read_restart.cpp | 4 ++-- src/replicate.cpp | 4 ++-- src/reset_mol_ids.cpp | 4 ++-- src/special.cpp | 4 ++-- src/timer.cpp | 18 +++++++++--------- 77 files changed, 175 insertions(+), 189 deletions(-) diff --git a/src/DIFFRACTION/compute_saed.cpp b/src/DIFFRACTION/compute_saed.cpp index e5af83ca92..77f17d77d1 100644 --- a/src/DIFFRACTION/compute_saed.cpp +++ b/src/DIFFRACTION/compute_saed.cpp @@ -348,7 +348,7 @@ void ComputeSAED::compute_vector() if (me == 0 && echo) utils::logmesg(lmp,"-----\nComputing SAED intensities"); - double t0 = MPI_Wtime(); + double t0 = platform::walltime(); double *Fvec = new double[2*nRows]; // Strct factor (real & imaginary) // -- Note, vector entries correspond to different RELP @@ -491,7 +491,7 @@ void ComputeSAED::compute_vector() vector[i] = (scratch[2*i] * scratch[2*i] + scratch[2*i+1] * scratch[2*i+1]) / natoms; } - double t2 = MPI_Wtime(); + double t2 = platform::walltime(); // compute memory usage per processor double bytes = memory_usage(); diff --git a/src/DIFFRACTION/compute_xrd.cpp b/src/DIFFRACTION/compute_xrd.cpp index c6cf7be2ce..633c135e74 100644 --- a/src/DIFFRACTION/compute_xrd.cpp +++ b/src/DIFFRACTION/compute_xrd.cpp @@ -300,7 +300,7 @@ void ComputeXRD::compute_array() if (me == 0 && echo) utils::logmesg(lmp, "-----\nComputing XRD intensities"); - double t0 = MPI_Wtime(); + double t0 = platform::walltime(); double *Fvec = new double[2*size_array_rows]; // Strct factor (real & imaginary) // -- Note: array rows correspond to different RELP @@ -496,7 +496,7 @@ void ComputeXRD::compute_array() array[i][1] = (scratch[2*i] * scratch[2*i] + scratch[2*i+1] * scratch[2*i+1]) / natoms; } - double t2 = MPI_Wtime(); + double t2 = platform::walltime(); // compute memory usage per processor double bytes = memory_usage(); diff --git a/src/DPD-REACT/fix_rx.cpp b/src/DPD-REACT/fix_rx.cpp index 526c2d508f..8971f5ae48 100644 --- a/src/DPD-REACT/fix_rx.cpp +++ b/src/DPD-REACT/fix_rx.cpp @@ -58,7 +58,7 @@ namespace /* anonymous */ { typedef double TimerType; -TimerType getTimeStamp() { return MPI_Wtime(); } +TimerType getTimeStamp() { return platform::walltime(); } double getElapsedTime( const TimerType &t0, const TimerType &t1) { return t1-t0; } } // end namespace diff --git a/src/GPU/pair_beck_gpu.cpp b/src/GPU/pair_beck_gpu.cpp index a2a3133a24..e3dfda428f 100644 --- a/src/GPU/pair_beck_gpu.cpp +++ b/src/GPU/pair_beck_gpu.cpp @@ -120,9 +120,9 @@ void PairBeckGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_start < inum) { - cpu_time = MPI_Wtime(); + cpu_time = platform::walltime(); cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh); - cpu_time = MPI_Wtime() - cpu_time; + cpu_time = platform::walltime() - cpu_time; } } diff --git a/src/GPU/pair_lj96_cut_gpu.cpp b/src/GPU/pair_lj96_cut_gpu.cpp index f03fbc9d7f..546c31a94e 100644 --- a/src/GPU/pair_lj96_cut_gpu.cpp +++ b/src/GPU/pair_lj96_cut_gpu.cpp @@ -117,9 +117,9 @@ void PairLJ96CutGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); // if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_start(host_start, inum, ilist, numneigh, firstneigh); else cpu_compute<1,0>(host_start, inum, ilist, numneigh, firstneigh); } else cpu_compute<0,0>(host_start, inum, ilist, numneigh, firstneigh); - cpu_time = MPI_Wtime() - cpu_time; + cpu_time = platform::walltime() - cpu_time; } } diff --git a/src/GPU/pair_lj_sdk_gpu.cpp b/src/GPU/pair_lj_sdk_gpu.cpp index 9f925d0250..938ee83e4a 100644 --- a/src/GPU/pair_lj_sdk_gpu.cpp +++ b/src/GPU/pair_lj_sdk_gpu.cpp @@ -122,12 +122,12 @@ void PairLJSDKGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_start(host_start, inum, ilist, numneigh, firstneigh); else cpu_compute<1,0>(host_start, inum, ilist, numneigh, firstneigh); } else cpu_compute<0,0>(host_start, inum, ilist, numneigh, firstneigh); - cpu_time = MPI_Wtime() - cpu_time; + cpu_time = platform::walltime() - cpu_time; } } diff --git a/src/GPU/pair_lj_sf_dipole_sf_gpu.cpp b/src/GPU/pair_lj_sf_dipole_sf_gpu.cpp index bd40f855dc..0bb0e66d92 100644 --- a/src/GPU/pair_lj_sf_dipole_sf_gpu.cpp +++ b/src/GPU/pair_lj_sf_dipole_sf_gpu.cpp @@ -127,9 +127,9 @@ void PairLJSFDipoleSFGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR, "Insufficient memory on accelerator"); if (host_start < inum) { - cpu_time = MPI_Wtime(); + cpu_time = platform::walltime(); cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh); - cpu_time = MPI_Wtime() - cpu_time; + cpu_time = platform::walltime() - cpu_time; } //fprintf("LJ_SMOOTH_GPU"); } diff --git a/src/GPU/pair_mie_cut_gpu.cpp b/src/GPU/pair_mie_cut_gpu.cpp index 568b4dbc18..a059607880 100644 --- a/src/GPU/pair_mie_cut_gpu.cpp +++ b/src/GPU/pair_mie_cut_gpu.cpp @@ -118,9 +118,9 @@ void PairMIECutGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_start < inum) { - cpu_time = MPI_Wtime(); + cpu_time = platform::walltime(); cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh); - cpu_time = MPI_Wtime() - cpu_time; + cpu_time = platform::walltime() - cpu_time; } } diff --git a/src/GPU/pair_soft_gpu.cpp b/src/GPU/pair_soft_gpu.cpp index 9b6fc6a39a..654e2e603b 100644 --- a/src/GPU/pair_soft_gpu.cpp +++ b/src/GPU/pair_soft_gpu.cpp @@ -121,9 +121,9 @@ void PairSoftGPU::compute(int eflag, int vflag) error->one(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_startone(FLERR,"Insufficient memory on accelerator"); if (host_start void FixIntel::add_off_results(const ft * _noalias const f_in, const acc_t * _noalias const ev_global) { if (_offload_balance < 0.0) - _balance_other_time = MPI_Wtime() - _balance_other_time; + _balance_other_time = platform::walltime() - _balance_other_time; start_watch(TIME_OFFLOAD_WAIT); #ifdef _LMP_INTEL_OFFLOAD diff --git a/src/KOKKOS/fix_rx_kokkos.cpp b/src/KOKKOS/fix_rx_kokkos.cpp index 15b4a39849..f05fe88fd8 100644 --- a/src/KOKKOS/fix_rx_kokkos.cpp +++ b/src/KOKKOS/fix_rx_kokkos.cpp @@ -54,7 +54,7 @@ namespace /* anonymous */ { typedef double TimerType; -TimerType getTimeStamp(void) { return MPI_Wtime(); } +TimerType getTimeStamp(void) { return platform::walltime(); } double getElapsedTime( const TimerType &t0, const TimerType &t1) { return t1-t0; } } // end namespace diff --git a/src/KOKKOS/pair_exp6_rx_kokkos.cpp b/src/KOKKOS/pair_exp6_rx_kokkos.cpp index 4da3a43243..0988cb4910 100644 --- a/src/KOKKOS/pair_exp6_rx_kokkos.cpp +++ b/src/KOKKOS/pair_exp6_rx_kokkos.cpp @@ -61,7 +61,7 @@ namespace /* anonymous */ { //typedef double TimerType; -//TimerType getTimeStamp(void) { return MPI_Wtime(); } +//TimerType getTimeStamp(void) { return platform::walltime(); } //double getElapsedTime( const TimerType &t0, const TimerType &t1) { return t1-t0; } typedef struct timespec TimerType; diff --git a/src/KOKKOS/pppm_kokkos.cpp b/src/KOKKOS/pppm_kokkos.cpp index d71d7d1bad..da18bba001 100644 --- a/src/KOKKOS/pppm_kokkos.cpp +++ b/src/KOKKOS/pppm_kokkos.cpp @@ -2857,7 +2857,7 @@ int PPPMKokkos::timing_1d(int n, double &time1d) copymode = 0; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->timing1d(d_work1,nfft_both,FFT3dKokkos::FORWARD); @@ -2867,7 +2867,7 @@ int PPPMKokkos::timing_1d(int n, double &time1d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time1d = time2 - time1; return 4; @@ -2894,7 +2894,7 @@ int PPPMKokkos::timing_3d(int n, double &time3d) copymode = 0; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->compute(d_work1,d_work1,FFT3dKokkos::FORWARD); @@ -2904,7 +2904,7 @@ int PPPMKokkos::timing_3d(int n, double &time3d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time3d = time2 - time1; return 4; diff --git a/src/KSPACE/pppm.cpp b/src/KSPACE/pppm.cpp index b6739d43fd..9d3a06f18e 100644 --- a/src/KSPACE/pppm.cpp +++ b/src/KSPACE/pppm.cpp @@ -2981,7 +2981,7 @@ int PPPM::timing_1d(int n, double &time1d) for (int i = 0; i < 2*nfft_both; i++) work1[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->timing1d(work1,nfft_both,FFT3d::FORWARD); @@ -2993,7 +2993,7 @@ int PPPM::timing_1d(int n, double &time1d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time1d = time2 - time1; if (differentiation_flag) return 2; @@ -3011,7 +3011,7 @@ int PPPM::timing_3d(int n, double &time3d) for (int i = 0; i < 2*nfft_both; i++) work1[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->compute(work1,work1,FFT3d::FORWARD); @@ -3023,7 +3023,7 @@ int PPPM::timing_3d(int n, double &time3d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time3d = time2 - time1; if (differentiation_flag) return 2; diff --git a/src/KSPACE/pppm_dipole.cpp b/src/KSPACE/pppm_dipole.cpp index a39973c6ae..16e06ed13e 100644 --- a/src/KSPACE/pppm_dipole.cpp +++ b/src/KSPACE/pppm_dipole.cpp @@ -2443,7 +2443,7 @@ int PPPMDipole::timing_1d(int n, double &time1d) for (int i = 0; i < 2*nfft_both; i++) work1[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->timing1d(work1,nfft_both,FFT3d::FORWARD); @@ -2461,7 +2461,7 @@ int PPPMDipole::timing_1d(int n, double &time1d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time1d = time2 - time1; return 12; @@ -2478,7 +2478,7 @@ int PPPMDipole::timing_3d(int n, double &time3d) for (int i = 0; i < 2*nfft_both; i++) work1[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); for (int i = 0; i < n; i++) { fft1->compute(work1,work1,FFT3d::FFT3d::FORWARD); @@ -2496,7 +2496,7 @@ int PPPMDipole::timing_3d(int n, double &time3d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time3d = time2 - time1; return 12; diff --git a/src/KSPACE/pppm_disp.cpp b/src/KSPACE/pppm_disp.cpp index a523fcce9e..fa14cb23f0 100644 --- a/src/KSPACE/pppm_disp.cpp +++ b/src/KSPACE/pppm_disp.cpp @@ -8183,7 +8183,7 @@ int PPPMDisp::timing_1d(int n, double &time1d) for (int i = 0; i < 2*nfft_both_6; i++) work1_6[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); if (function[0]) { for (int i = 0; i < n; i++) { @@ -8197,11 +8197,11 @@ int PPPMDisp::timing_1d(int n, double &time1d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time1d = time2 - time1; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); if (function[1] + function[2] + function[3]) { for (int i = 0; i < n; i++) { @@ -8215,7 +8215,7 @@ int PPPMDisp::timing_1d(int n, double &time1d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time1d += (time2 - time1)*mixing; if (differentiation_flag) return 2; @@ -8238,7 +8238,7 @@ int PPPMDisp::timing_3d(int n, double &time3d) for (int i = 0; i < 2*nfft_both_6; i++) work1_6[i] = ZEROF; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); if (function[0]) { for (int i = 0; i < n; i++) { @@ -8252,11 +8252,11 @@ int PPPMDisp::timing_3d(int n, double &time3d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time3d = time2 - time1; MPI_Barrier(world); - time1 = MPI_Wtime(); + time1 = platform::walltime(); if (function[1] + function[2] + function[3]) { for (int i = 0; i < n; i++) { @@ -8270,7 +8270,7 @@ int PPPMDisp::timing_3d(int n, double &time3d) } MPI_Barrier(world); - time2 = MPI_Wtime(); + time2 = platform::walltime(); time3d += (time2 - time1) * mixing; if (differentiation_flag) return 2; diff --git a/src/REPLICA/fix_hyper_local.cpp b/src/REPLICA/fix_hyper_local.cpp index 4a477fad8d..ba91644c53 100644 --- a/src/REPLICA/fix_hyper_local.cpp +++ b/src/REPLICA/fix_hyper_local.cpp @@ -447,7 +447,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) int *ilist,*jlist,*numneigh,**firstneigh; //double time1,time2,time3,time4,time5,time6,time7,time8; - //time1 = MPI_Wtime(); + //time1 = platform::walltime(); nostrainyet = 0; @@ -520,7 +520,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) maxhalfstrain[iold] = halfstrain; } - //time2 = MPI_Wtime(); + //time2 = platform::walltime(); // reverse comm acquires maxstrain of all current owned atoms // needed b/c only saw half the bonds of each atom @@ -531,7 +531,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) comm->reverse_comm_fix(this); comm->forward_comm_fix(this); - //time3 = MPI_Wtime(); + //time3 = platform::walltime(); // ------------------------------------------------------------- // stage 2: @@ -636,7 +636,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) maxstrain_domain[i] = emax; } - //time4 = MPI_Wtime(); + //time4 = platform::walltime(); // reverse comm to acquire maxstrain_domain from ghost atoms // needed b/c neigh list may refer to old owned atoms that are now ghost @@ -646,7 +646,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) comm->reverse_comm_fix(this); comm->forward_comm_fix(this); - //time5 = MPI_Wtime(); + //time5 = platform::walltime(); // ------------------------------------------------------------- // stage 3: @@ -672,7 +672,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) bias[nbias++] = maxhalf[iold]; } - //time6 = MPI_Wtime(); + //time6 = platform::walltime(); // ------------------------------------------------------------- // stage 4: @@ -724,7 +724,7 @@ void FixHyperLocal::pre_reverse(int /* eflag */, int /* vflag */) // myboost += exp(beta * biascoeff[m]*vbias); } - //time7 = MPI_Wtime(); + //time7 = platform::walltime(); // ------------------------------------------------------------- // stage 5: @@ -887,7 +887,7 @@ void FixHyperLocal::build_bond_list(int natom) int *ilist,*jlist,*numneigh,**firstneigh; double time1,time2; - time1 = MPI_Wtime(); + time1 = platform::walltime(); if (natom) { nevent++; @@ -1185,7 +1185,7 @@ void FixHyperLocal::build_bond_list(int natom) // DEBUG //if (me == 0) printf("TOTAL BOND COUNT = %ld\n",allbonds); - time2 = MPI_Wtime(); + time2 = platform::walltime(); if (firstflag) nnewbond = 0; else { diff --git a/src/REPLICA/tad.cpp b/src/REPLICA/tad.cpp index 9b6ecf0b0c..881ec1604c 100644 --- a/src/REPLICA/tad.cpp +++ b/src/REPLICA/tad.cpp @@ -710,7 +710,7 @@ void TAD::perform_neb(int ievent) // time_neb += timer->get_wall(Timer::TOTAL); MPI_Barrier(world); - double time_tmp = MPI_Wtime(); + double time_tmp = platform::walltime(); double dt_hold = update->dt; update->dt = dt_neb; @@ -718,7 +718,7 @@ void TAD::perform_neb(int ievent) update->dt = dt_hold; MPI_Barrier(world); - time_neb += MPI_Wtime() - time_tmp; + time_neb += platform::walltime() - time_tmp; if (universe->me == 0) { universe->ulogfile = ulogfile_lammps; diff --git a/src/RIGID/fix_rigid_small.cpp b/src/RIGID/fix_rigid_small.cpp index 7216c56c83..7a30c8b1c9 100644 --- a/src/RIGID/fix_rigid_small.cpp +++ b/src/RIGID/fix_rigid_small.cpp @@ -391,14 +391,14 @@ FixRigidSmall::FixRigidSmall(LAMMPS *lmp, int narg, char **arg) : // sets bodytag for owned atoms // body attributes are computed later by setup_bodies() - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); create_bodies(bodyID); if (customflag) delete [] bodyID; if (comm->me == 0) utils::logmesg(lmp," create bodies CPU = {:.3f} seconds\n", - MPI_Wtime()-time1); + platform::walltime()-time1); // set nlocal_body and allocate bodies I own diff --git a/src/RIGID/fix_shake.cpp b/src/RIGID/fix_shake.cpp index f1c1d30fc5..9e45ec13d8 100644 --- a/src/RIGID/fix_shake.cpp +++ b/src/RIGID/fix_shake.cpp @@ -222,13 +222,13 @@ FixShake::FixShake(LAMMPS *lmp, int narg, char **arg) : // identify all SHAKE clusters - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); find_clusters(); if (comm->me == 0) utils::logmesg(lmp," find clusters CPU = {:.3f} seconds\n", - MPI_Wtime()-time1); + platform::walltime()-time1); // initialize list of SHAKE clusters to constrain diff --git a/src/SMTBQ/pair_smtbq.cpp b/src/SMTBQ/pair_smtbq.cpp index 4b7a1f2ac5..8922173433 100644 --- a/src/SMTBQ/pair_smtbq.cpp +++ b/src/SMTBQ/pair_smtbq.cpp @@ -2426,7 +2426,7 @@ void PairSMTBQ::Charge() ilist = list->ilist; - if (me == 0) t_init = MPI_Wtime(); + if (me == 0) t_init = platform::walltime(); if (step == 0) cluster = 0; // --------------------------- @@ -2729,7 +2729,7 @@ void PairSMTBQ::Charge() printf (" convergence : %f - %f\n",enegchk[gp],enegmax[gp]); } - t_end = MPI_Wtime(); + t_end = platform::walltime(); dt = t_end - t_init; printf (" temps dans charges : %f seconde. \n",dt); printf (" ======================================================== \n"); diff --git a/src/STUBS/mpi.cpp b/src/STUBS/mpi.cpp index e5cd50629e..e2098e0091 100644 --- a/src/STUBS/mpi.cpp +++ b/src/STUBS/mpi.cpp @@ -21,7 +21,6 @@ #include #include #include -#include /* data structure for double/int */ @@ -164,23 +163,10 @@ int MPI_Finalize() } /* ---------------------------------------------------------------------- */ - +static auto initial_time = std::chrono::steady_clock::now(); double MPI_Wtime() { -#if defined(_MSC_VER) - double t; - - t = GetTickCount(); - t /= 1000.0; - return t; -#else - double time; - struct timeval tv; - - gettimeofday(&tv, NULL); - time = 1.0 * tv.tv_sec + 1.0e-6 * tv.tv_usec; - return time; -#endif + return std::chrono::duration(std::chrono::steady_clock::now() - initial_time).count(); } /* ---------------------------------------------------------------------- */ diff --git a/src/balance.cpp b/src/balance.cpp index 06a3463db5..bd3ba007ef 100644 --- a/src/balance.cpp +++ b/src/balance.cpp @@ -259,7 +259,7 @@ void Balance::command(int narg, char **arg) // must reset atom map after exchange() since it clears it MPI_Barrier(world); - double start_time = MPI_Wtime(); + double start_time = platform::walltime(); lmp->init(); @@ -386,7 +386,7 @@ void Balance::command(int narg, char **arg) if (me == 0) { std::string mesg = fmt::format(" rebalancing time: {:.3f} seconds\n", - MPI_Wtime()-start_time); + platform::walltime()-start_time); mesg += fmt::format(" iteration count = {}\n",niter); for (int i = 0; i < nimbalance; ++i) mesg += imbalances[i]->info(); mesg += fmt::format(" initial/final maximal load/proc = {:.8} {:.8}\n" diff --git a/src/create_atoms.cpp b/src/create_atoms.cpp index 8baf6f88f7..e82be7d331 100644 --- a/src/create_atoms.cpp +++ b/src/create_atoms.cpp @@ -378,7 +378,7 @@ void CreateAtoms::command(int narg, char **arg) // Record wall time for atom creation MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); // clear ghost count and any ghost bonus data internal to AtomVec // same logic as beginning of Comm::exchange() @@ -591,7 +591,7 @@ void CreateAtoms::command(int narg, char **arg) if (scaleflag) domain->print_box(" using lattice units in "); else domain->print_box(" using box units in "); utils::logmesg(lmp," create_atoms CPU = {:.3f} seconds\n", - MPI_Wtime() - time1); + platform::walltime() - time1); } } diff --git a/src/info.cpp b/src/info.cpp index 01ac7a095c..3d24f9b56a 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -635,7 +635,7 @@ void Info::command(int narg, char **arg) } if (flags & TIME) { - double wallclock = MPI_Wtime() - lmp->initclock; + double wallclock = platform::walltime() - lmp->initclock; double cpuclock = platform::cputime(); int cpuh,cpum,cpus,wallh,wallm,walls; diff --git a/src/lammps.cpp b/src/lammps.cpp index e24c42689f..5e76e08112 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -129,7 +129,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : logfile = nullptr; infile = nullptr; - initclock = MPI_Wtime(); + initclock = platform::walltime(); init_pkg_lists(); @@ -719,7 +719,7 @@ LAMMPS::~LAMMPS() num_package = 0; packargs = nullptr; - double totalclock = MPI_Wtime() - initclock; + double totalclock = platform::walltime() - initclock; if ((me == 0) && (screen || logfile)) { int seconds = fmod(totalclock,60.0); totalclock = (totalclock - seconds) / 60.0; diff --git a/src/read_data.cpp b/src/read_data.cpp index e9b222d6ef..bb4fbe0315 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -114,7 +114,7 @@ void ReadData::command(int narg, char **arg) if (narg < 1) error->all(FLERR,"Illegal read_data command"); MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); // optional args @@ -914,7 +914,7 @@ void ReadData::command(int narg, char **arg) MPI_Barrier(world); if (comm->me == 0) - utils::logmesg(lmp," read_data CPU = {:.3f} seconds\n",MPI_Wtime()-time1); + utils::logmesg(lmp," read_data CPU = {:.3f} seconds\n",platform::walltime()-time1); } /* ---------------------------------------------------------------------- diff --git a/src/read_restart.cpp b/src/read_restart.cpp index caa19d46fb..0eab44baaa 100644 --- a/src/read_restart.cpp +++ b/src/read_restart.cpp @@ -54,7 +54,7 @@ void ReadRestart::command(int narg, char **arg) error->all(FLERR,"Cannot read_restart after simulation box is defined"); MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); MPI_Comm_rank(world,&me); MPI_Comm_size(world,&nprocs); @@ -522,7 +522,7 @@ void ReadRestart::command(int narg, char **arg) MPI_Barrier(world); if (comm->me == 0) - utils::logmesg(lmp," read_restart CPU = {:.3f} seconds\n",MPI_Wtime()-time1); + utils::logmesg(lmp," read_restart CPU = {:.3f} seconds\n",platform::walltime()-time1); delete mpiio; } diff --git a/src/replicate.cpp b/src/replicate.cpp index 2c2b512026..80edd7bcbc 100644 --- a/src/replicate.cpp +++ b/src/replicate.cpp @@ -79,7 +79,7 @@ void Replicate::command(int narg, char **arg) // record wall time for atom replication MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); // maxtag = largest atom tag across all existing atoms @@ -799,5 +799,5 @@ void Replicate::command(int narg, char **arg) MPI_Barrier(world); if (me == 0) - utils::logmesg(lmp," replicate CPU = {:.3f} seconds\n",MPI_Wtime()-time1); + utils::logmesg(lmp," replicate CPU = {:.3f} seconds\n",platform::walltime()-time1); } diff --git a/src/reset_mol_ids.cpp b/src/reset_mol_ids.cpp index 424b4bcb6c..4c973f543f 100644 --- a/src/reset_mol_ids.cpp +++ b/src/reset_mol_ids.cpp @@ -96,7 +96,7 @@ void ResetMolIDs::command(int narg, char **arg) // record wall time for resetting molecule IDs MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); // initialize system since comm->borders() will be invoked @@ -132,7 +132,7 @@ void ResetMolIDs::command(int narg, char **arg) else utils::logmesg(lmp," number of new molecule IDs = {}\n",nchunk); utils::logmesg(lmp," reset_mol_ids CPU = {:.3f} seconds\n", - MPI_Wtime()-time1); + platform::walltime()-time1); } } diff --git a/src/special.cpp b/src/special.cpp index dcc0d0c0ad..9f480da78f 100644 --- a/src/special.cpp +++ b/src/special.cpp @@ -56,7 +56,7 @@ Special::~Special() void Special::build() { MPI_Barrier(world); - double time1 = MPI_Wtime(); + double time1 = platform::walltime(); if (me == 0) { const double * const special_lj = force->special_lj; @@ -1303,5 +1303,5 @@ void Special::timer_output(double time1) { if (comm->me == 0) utils::logmesg(lmp," special bonds CPU = {:.3f} seconds\n", - MPI_Wtime()-time1); + platform::walltime()-time1); } diff --git a/src/timer.cpp b/src/timer.cpp index 4efee8871c..0cbf687137 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -52,7 +52,7 @@ void Timer::_stamp(enum ttype which) double current_cpu=0.0, current_wall=0.0; if (_level > NORMAL) current_cpu = platform::cputime(); - current_wall = MPI_Wtime(); + current_wall = platform::walltime(); if ((which > TOTAL) && (which < NUM_TIMER)) { const double delta_cpu = current_cpu - previous_cpu; @@ -76,7 +76,7 @@ void Timer::_stamp(enum ttype which) if (_sync) { MPI_Barrier(world); if (_level > NORMAL) current_cpu = platform::cputime(); - current_wall = MPI_Wtime(); + current_wall = platform::walltime(); cpu_array[SYNC] += current_cpu - previous_cpu; wall_array[SYNC] += current_wall - previous_wall; @@ -96,7 +96,7 @@ void Timer::barrier_start() if (_level < LOOP) return; current_cpu = platform::cputime(); - current_wall = MPI_Wtime(); + current_wall = platform::walltime(); cpu_array[TOTAL] = current_cpu; wall_array[TOTAL] = current_wall; @@ -115,7 +115,7 @@ void Timer::barrier_stop() if (_level < LOOP) return; current_cpu = platform::cputime(); - current_wall = MPI_Wtime(); + current_wall = platform::walltime(); cpu_array[TOTAL] = current_cpu - cpu_array[TOTAL]; wall_array[TOTAL] = current_wall - wall_array[TOTAL]; @@ -134,7 +134,7 @@ double Timer::cpu(enum ttype which) double Timer::elapsed(enum ttype which) { if (_level == OFF) return 0.0; - double current_wall = MPI_Wtime(); + double current_wall = platform::walltime(); return (current_wall - wall_array[which]); } @@ -165,7 +165,7 @@ void Timer::print_timeout(FILE *fp) // format timeout setting if (_timeout > 0) { // time since init_timeout() - const double d = MPI_Wtime() - timeout_start; + const double d = platform::walltime() - timeout_start; // remaining timeout in seconds int s = _timeout - d; // remaining 1/100ths of seconds @@ -184,7 +184,7 @@ void Timer::print_timeout(FILE *fp) bool Timer::_check_timeout() { - double walltime = MPI_Wtime() - timeout_start; + double walltime = platform::walltime() - timeout_start; // broadcast time to insure all ranks act the same. MPI_Bcast(&walltime,1,MPI_DOUBLE,0,world); @@ -202,7 +202,7 @@ bool Timer::_check_timeout() /* ---------------------------------------------------------------------- */ double Timer::get_timeout_remain() { - return (_timeout < 0.0) ? 0.0 : _timeout + timeout_start - MPI_Wtime(); + return (_timeout < 0.0) ? 0.0 : _timeout + timeout_start - platform::walltime(); } /* ---------------------------------------------------------------------- @@ -243,7 +243,7 @@ void Timer::modify_params(int narg, char **arg) ++iarg; } - timeout_start = MPI_Wtime(); + timeout_start = platform::walltime(); if (comm->me == 0) { // format timeout setting From 81492533e69abf164179526e2e4de317787cd922 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 5 Oct 2021 23:19:52 -0400 Subject: [PATCH 31/84] recover serial compilation --- src/STUBS/mpi.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/STUBS/mpi.cpp b/src/STUBS/mpi.cpp index e2098e0091..c178b06803 100644 --- a/src/STUBS/mpi.cpp +++ b/src/STUBS/mpi.cpp @@ -17,10 +17,11 @@ #include "../version.h" -#include -#include -#include -#include +#include +#include +#include +#include +#include /* data structure for double/int */ From e3cb5a5e2503f9fc77093206380e83c5a9cc7c9e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 07:09:36 -0400 Subject: [PATCH 32/84] restore old version of MPI_Wtime(). we're not using it anyway. --- src/STUBS/mpi.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/STUBS/mpi.cpp b/src/STUBS/mpi.cpp index c178b06803..e5cd50629e 100644 --- a/src/STUBS/mpi.cpp +++ b/src/STUBS/mpi.cpp @@ -17,11 +17,11 @@ #include "../version.h" -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* data structure for double/int */ @@ -164,10 +164,23 @@ int MPI_Finalize() } /* ---------------------------------------------------------------------- */ -static auto initial_time = std::chrono::steady_clock::now(); + double MPI_Wtime() { - return std::chrono::duration(std::chrono::steady_clock::now() - initial_time).count(); +#if defined(_MSC_VER) + double t; + + t = GetTickCount(); + t /= 1000.0; + return t; +#else + double time; + struct timeval tv; + + gettimeofday(&tv, NULL); + time = 1.0 * tv.tv_sec + 1.0e-6 * tv.tv_usec; + return time; +#endif } /* ---------------------------------------------------------------------- */ From 9fc23a2bda905535c761db3bb7b5308a833069ec Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 07:10:04 -0400 Subject: [PATCH 33/84] make use of platform namespace functions --- tools/lammps-shell/lammps-shell.cpp | 77 +++++++++++------------------ 1 file changed, 30 insertions(+), 47 deletions(-) diff --git a/tools/lammps-shell/lammps-shell.cpp b/tools/lammps-shell/lammps-shell.cpp index 76fa04d71a..936b539d43 100644 --- a/tools/lammps-shell/lammps-shell.cpp +++ b/tools/lammps-shell/lammps-shell.cpp @@ -1,7 +1,7 @@ // LAMMPS Shell. An improved interactive LAMMPS session with // command line editing, history, TAB expansion and shell escapes -// Copyright (c) 2020 Axel Kohlmeyer +// Copyright (c) 2020, 2021 Axel Kohlmeyer // This software is distributed under the GNU General Public License. @@ -15,21 +15,12 @@ #include #include -#if !defined(_WIN32) -#include -#else +#if defined(_WIN32) #if !defined(WIN32_LEAN_AND_MEAN) #define WIN32_LEAN_AND_MEAN #endif -#include -#include #include -#define chdir(x) _chdir(x) -#define getcwd(buf, len) _getcwd(buf, len) -#define isatty(x) _isatty(x) -#endif - -#if !defined(_WIN32) +#else #include #endif @@ -42,10 +33,10 @@ using namespace LAMMPS_NS; -char *omp_threads = nullptr; -const int buflen = 512; -char buf[buflen]; void *lmp = nullptr; +char *omp_threads = nullptr; +constexpr int BUFLEN = 512; +char buf[BUFLEN]; enum { ATOM_STYLE, @@ -214,7 +205,7 @@ template char *style_generator(const char *text, int state) } while (idx < num) { - lammps_style_name(lmp, lmp_style[STYLE], idx, buf, buflen); + lammps_style_name(lmp, lmp_style[STYLE], idx, buf, BUFLEN); ++idx; if ((len == 0) || (strncmp(text, buf, len) == 0)) return dupstring(buf); } @@ -231,7 +222,7 @@ template char *id_generator(const char *text, int state) } while (idx < num) { - lammps_id_name(lmp, lmp_id[ID], idx, buf, buflen); + lammps_id_name(lmp, lmp_id[ID], idx, buf, BUFLEN); ++idx; if ((len == 0) || (strncmp(text, buf, len) == 0)) return dupstring(buf); } @@ -389,8 +380,8 @@ static char *plugin_name_generator(const char *text, int state) nmax = lammps_plugin_count(); while (idx < nmax) { - char style[buflen], name[buflen]; - lammps_plugin_name(idx, style, name, buflen); + char style[BUFLEN], name[BUFLEN]; + lammps_plugin_name(idx, style, name, BUFLEN); ++idx; if (words[2] == style) { if (strncmp(name, words[3].c_str(), len) == 0) @@ -475,7 +466,7 @@ char *group_generator(const char *text, int state) } while (idx < num) { - lammps_id_name(lmp, "group", idx, buf, buflen); + lammps_id_name(lmp, "group", idx, buf, BUFLEN); ++idx; if ((len == 0) || (strncmp(text, buf, len) == 0)) return dupstring(buf); } @@ -577,7 +568,7 @@ static void init_commands() // store optional commands from command styles ncmds = lammps_style_count(lmp, "command"); for (int i = 0; i < ncmds; ++i) { - if (lammps_style_name(lmp, "command", i, buf, buflen)) commands.push_back(buf); + if (lammps_style_name(lmp, "command", i, buf, BUFLEN)) commands.push_back(buf); } // store LAMMPS shell specific command names @@ -599,7 +590,7 @@ static void init_commands() // otherwise any tabs in redirected input will cause havoc. const char *test_mode = getenv("LAMMPS_SHELL_TESTING"); if (test_mode) std::cout << "*TESTING* using LAMMPS Shell in test mode *TESTING*\n"; - if (isatty(fileno(stdin)) || test_mode) { + if (platform::is_console(stdin) || test_mode) { rl_attempted_completion_function = cmd_completion; } else { rl_bind_key('\t', rl_insert); @@ -608,10 +599,11 @@ static void init_commands() // read saved history, but not in test mode. if (!test_mode) read_history(".lammps_history"); -#if !defined(_WIN32) - signal(SIGINT, ctrl_c_handler); -#else + // intercept CTRL-C +#if defined(_WIN32) SetConsoleCtrlHandler(ctrl_c_handler, TRUE); +#else + signal(SIGINT, ctrl_c_handler); #endif } @@ -685,7 +677,7 @@ static int shell_cmd(const std::string &cmd) free(text); return 0; } else if ((words[0] == "pwd") || ((words[0] == "cd") && (words.size() == 1))) { - if (getcwd(buf, buflen)) std::cout << buf << "\n"; + std::cout << platform::current_directory() << "\n"; free(text); return 0; } else if (words[0] == "cd") { @@ -741,28 +733,19 @@ int main(int argc, char **argv) #if defined(_WIN32) // Special hack for Windows: if the current working directory is // the "system folder" (because that is where cmd.exe lives) - // switch to the user's documents directory. Avoid buffer overflow - // and skip this step if the path is too long for our buffer. - if (getcwd(buf, buflen)) { - if ((strstr(buf, "System32") || strstr(buf, "system32"))) { - char *drive = getenv("HOMEDRIVE"); - char *path = getenv("HOMEPATH"); - buf[0] = '\0'; - int len = strlen("\\Documents"); - if (drive) len += strlen(drive); - if (path) len += strlen(path); - if (len < buflen) { - if (drive) strcat(buf, drive); - if (path) strcat(buf, path); - strcat(buf, "\\Documents"); - chdir(buf); - } - } + // switch to the user's documents directory. + + auto curdir = platform::current_directory(); + if (utils::strmatch(curdir,"[Ss]ystem32")) { + std::string docdir = getenv("HOMEDRIVE"); + docdir += getenv("HOMEPATH"); + docdir += "\\Documents"; + platform::chdir(docdir); } #endif - lammps_get_os_info(buf, buflen); - std::cout << "LAMMPS Shell version 1.1 OS: " << buf; + lammps_get_os_info(buf, BUFLEN); + std::cout << "LAMMPS Shell version 1.2 OS: " << buf; if (!lammps_config_has_exceptions()) std::cout << "WARNING: LAMMPS was compiled without exceptions\n" @@ -777,7 +760,7 @@ int main(int argc, char **argv) // to use the maximum number of threads available since this is // not intended to be run with MPI. omp_threads = dupstring(std::string("OMP_NUM_THREADS=" + std::to_string(nthreads))); - putenv(omp_threads); + platform::putenv(omp_threads); // handle the special case where the first argument is not a flag but a file // this happens for example when using file type associations on Windows. @@ -787,7 +770,7 @@ int main(int argc, char **argv) if ((argc > 1) && (argv[1][0] != '-')) { --argc; input_file = platform::path_basename(argv[1]); - chdir(platform::path_dirname(input_file).c_str()); + platform::chdir(platform::path_dirname(input_file)); for (int i = 1; i < argc; ++i) argv[i] = argv[i + 1]; } From 7801d112b38e44e10604a226d8f2f2ad5fec9545 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 07:10:35 -0400 Subject: [PATCH 34/84] enable building plugins for windows --- examples/plugins/CMakeLists.txt | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/examples/plugins/CMakeLists.txt b/examples/plugins/CMakeLists.txt index 59c2802b45..e4c084fc1d 100644 --- a/examples/plugins/CMakeLists.txt +++ b/examples/plugins/CMakeLists.txt @@ -36,11 +36,6 @@ if((CMAKE_CXX_COMPILER_ID STREQUAL "Intel") OR (CMAKE_CXX_COMPILER_ID STREQUAL " set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -restrict") endif() -# bail out on windows -if(CMAKE_SYSTEM_NAME STREQUAL Windows) - message(FATAL_ERROR "LAMMPS plugins are currently not supported on Windows") -endif() - set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) include(CheckIncludeFileCXX) include(LAMMPSInterfaceCXX) @@ -62,12 +57,21 @@ add_library(zero2plugin MODULE zero2plugin.cpp pair_zero2.cpp bond_zero2.cpp angle_zero2.cpp dihedral_zero2.cpp improper_zero2.cpp) target_link_libraries(zero2plugin PRIVATE lammps) -set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin PROPERTIES - PREFIX "" - LINK_FLAGS "-rdynamic") +set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin PROPERTIES PREFIX "") # MacOS seems to need this if(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin + PROPERTIES LINK_FLAGS "-Wl,-undefined,dynamic_lookup") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") +# tell CMake to export all symbols to a .dll on Windows with special case for MinGW cross-compilers + set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin + PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) + if(CMAKE_CROSSCOMPILING) + set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin + PROPERTIES LINK_FLAGS "-Wl,--export-all-symbols") + endif() +else() set_target_properties(morse2plugin nve2plugin helloplugin zero2plugin PROPERTIES - LINK_FLAGS "-Wl,-undefined,dynamic_lookup") + LINK_FLAGS "-rdynamic") endif() From 10a8a1b325f6a87184049c8ef6cf3a452c2d7e3d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 08:45:56 -0400 Subject: [PATCH 35/84] add dlerror() call wrapper --- doc/src/Developer_platform.rst | 3 +++ src/platform.cpp | 16 ++++++++++++++++ src/platform.h | 10 ++++++++++ 3 files changed, 29 insertions(+) diff --git a/doc/src/Developer_platform.rst b/doc/src/Developer_platform.rst index 74ad4c1aac..19836b1ff2 100644 --- a/doc/src/Developer_platform.rst +++ b/doc/src/Developer_platform.rst @@ -133,6 +133,9 @@ Dynamically loaded object or library functions .. doxygenfunction:: dlsym :project: progguide +.. doxygenfunction:: dlerror + :project: progguide + Compressed file I/O functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/platform.cpp b/src/platform.cpp index 1936baaf87..427085a6be 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -507,6 +507,13 @@ void *platform::dlopen(const std::string &fname) return (void *) LoadLibrary(fname.c_str()); } +// return dynamic linker error string + +std::string platform::dlerror() +{ + return ""; +} + // close a shared object int platform::dlclose(void *handle) { @@ -528,6 +535,15 @@ void *platform::dlopen(const std::string &fname) return ::dlopen(fname.c_str(), RTLD_NOW | RTLD_GLOBAL); } +// return dynamic linker error string + +std::string platform::dlerror() +{ + const char *errmesg = ::dlerror(); + if (errmesg) return std::string(errmesg); + else return ""; +} + // close a shared object int platform::dlclose(void *handle) { diff --git a/src/platform.h b/src/platform.h index ef45ceff9b..794fd692b0 100644 --- a/src/platform.h +++ b/src/platform.h @@ -133,6 +133,16 @@ namespace platform { void *dlopen(const std::string &fname); + /*! Obtain error diagnostic info after dynamic linking function calls + * + * Return a human-readable string describing the most recent error that + * occurred when using one of the functions for dynamic loading objects + * the last call to this function. The string is empty, if there was no error. + * + * \return string with error message or empty */ + + std::string dlerror(); + /*! Close a shared object * * This releases the object corresponding to the provided handle. From 4aae11f8fb10a66219f23ffde1845fca51d035da Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 08:46:20 -0400 Subject: [PATCH 36/84] port plugin loader to platform namespace --- examples/plugins/LAMMPSInterfaceCXX.cmake | 4 +++- src/PLUGIN/plugin.cpp | 28 +++++++---------------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/examples/plugins/LAMMPSInterfaceCXX.cmake b/examples/plugins/LAMMPSInterfaceCXX.cmake index 02f9159319..d52cf8f4e5 100644 --- a/examples/plugins/LAMMPSInterfaceCXX.cmake +++ b/examples/plugins/LAMMPSInterfaceCXX.cmake @@ -23,7 +23,9 @@ endfunction(validate_option) # LAMMPS C++ interface. We only need the header related parts. add_library(lammps INTERFACE) target_include_directories(lammps INTERFACE ${LAMMPS_HEADER_DIR}) - +if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND CMAKE_CROSSCOMPILING) + target_link_libraries(lammps INTERFACE ${CMAKE_BINARY_DIR}/../liblammps.dll.a) +endif() ################################################################################ # MPI configuration if(NOT CMAKE_CROSSCOMPILING) diff --git a/src/PLUGIN/plugin.cpp b/src/PLUGIN/plugin.cpp index 270c9958f5..443fecc99f 100644 --- a/src/PLUGIN/plugin.cpp +++ b/src/PLUGIN/plugin.cpp @@ -25,12 +25,6 @@ #include #include -#ifdef _WIN32 -#include -#else -#include -#endif - namespace LAMMPS_NS { // list of plugin information data for loaded styles @@ -87,31 +81,28 @@ namespace LAMMPS_NS { #if defined(LMP_PLUGIN) int me = lmp->comm->me; -#if defined(WIN32) - lmp->error->all(FLERR,"Loading of plugins on Windows is not supported\n"); -#else // open DSO file from given path; load symbols globally - dlerror(); - void *dso = dlopen(file,RTLD_NOW|RTLD_GLOBAL); + platform::dlerror(); + void *dso = platform::dlopen(file); if (dso == nullptr) { if (me == 0) - utils::logmesg(lmp,"Open of file {} failed: {}\n",file,dlerror()); + utils::logmesg(lmp,"Open of file {} failed: {}\n",file,platform::dlerror()); return; } // look up lammpsplugin_init() function in DSO // function must have C bindings so there is no name mangling - dlerror(); - void *initfunc = dlsym(dso,"lammpsplugin_init"); + platform::dlerror(); + void *initfunc = platform::dlsym(dso,"lammpsplugin_init"); if (initfunc == nullptr) { - dlclose(dso); + platform::dlclose(dso); if (me == 0) utils::logmesg(lmp,"Plugin symbol lookup failure in file {}: {}\n", - file,dlerror()); + file,platform::dlerror()); return; } @@ -121,7 +112,6 @@ namespace LAMMPS_NS (*(lammpsplugin_initfunc)(initfunc))((void *)lmp, dso, (void *)&plugin_register); -#endif #endif } @@ -410,9 +400,7 @@ namespace LAMMPS_NS -- dso_refcounter[handle]; if (dso_refcounter[handle] == 0) { -#ifndef WIN32 - dlclose(handle); -#endif + platform::dlclose(handle); } #endif } From bbfb2d2712e66793438098174ce58f8e19084e9b Mon Sep 17 00:00:00 2001 From: Stan Moore Date: Wed, 6 Oct 2021 08:27:25 -0700 Subject: [PATCH 37/84] Add missing code to modify_kokkos --- src/KOKKOS/modify_kokkos.cpp | 102 ++++++++++++++++++++++++++++++++--- src/KOKKOS/modify_kokkos.h | 3 ++ 2 files changed, 97 insertions(+), 8 deletions(-) diff --git a/src/KOKKOS/modify_kokkos.cpp b/src/KOKKOS/modify_kokkos.cpp index 868de3e11e..08bbfa762f 100644 --- a/src/KOKKOS/modify_kokkos.cpp +++ b/src/KOKKOS/modify_kokkos.cpp @@ -38,7 +38,20 @@ ModifyKokkos::ModifyKokkos(LAMMPS *lmp) : Modify(lmp) void ModifyKokkos::setup(int vflag) { // compute setup needs to come before fix setup - // b/c NH fixes need use DOF of temperature computes + // b/c NH fixes need DOF of temperature computes + // fix group setup() is special case since populates a dynamic group + // needs to be done before temperature compute setup + + for (int i = 0; i < nfix; i++) { + if (strcmp(fix[i]->style,"GROUP") == 0) { + atomKK->sync(fix[i]->execution_space,fix[i]->datamask_read); + int prev_auto_sync = lmp->kokkos->auto_sync; + if (!fix[i]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[i]->setup(vflag); + lmp->kokkos->auto_sync = prev_auto_sync; + atomKK->modified(fix[i]->execution_space,fix[i]->datamask_modify); + } + } for (int i = 0; i < ncompute; i++) compute[i]->setup(); @@ -124,6 +137,37 @@ void ModifyKokkos::setup_pre_neighbor() } } +/* ---------------------------------------------------------------------- + setup post_neighbor call, only for fixes that define post_neighbor + called from Verlet, RESPA +------------------------------------------------------------------------- */ + +void ModifyKokkos::setup_post_neighbor() +{ + if (update->whichflag == 1) + for (int i = 0; i < n_post_neighbor; i++) { + atomKK->sync(fix[list_post_neighbor[i]]->execution_space, + fix[list_post_neighbor[i]]->datamask_read); + int prev_auto_sync = lmp->kokkos->auto_sync; + if (!fix[list_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_post_neighbor[i]]->setup_post_neighbor(); + lmp->kokkos->auto_sync = prev_auto_sync; + atomKK->modified(fix[list_post_neighbor[i]]->execution_space, + fix[list_post_neighbor[i]]->datamask_modify); + } + else if (update->whichflag == 2) + for (int i = 0; i < n_min_post_neighbor; i++) { + atomKK->sync(fix[list_min_post_neighbor[i]]->execution_space, + fix[list_min_post_neighbor[i]]->datamask_read); + int prev_auto_sync = lmp->kokkos->auto_sync; + if (!fix[list_min_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_min_post_neighbor[i]]->setup_post_neighbor(); + lmp->kokkos->auto_sync = prev_auto_sync; + atomKK->modified(fix[list_min_post_neighbor[i]]->execution_space, + fix[list_min_post_neighbor[i]]->datamask_modify); + } +} + /* ---------------------------------------------------------------------- setup pre_force call, only for fixes that define pre_force called from Verlet, RESPA, Min @@ -258,6 +302,24 @@ void ModifyKokkos::pre_neighbor() } } +/* ---------------------------------------------------------------------- + post_neighbor call, only for relevant fixes +------------------------------------------------------------------------- */ + +void ModifyKokkos::post_neighbor() +{ + for (int i = 0; i < n_post_neighbor; i++) { + atomKK->sync(fix[list_post_neighbor[i]]->execution_space, + fix[list_post_neighbor[i]]->datamask_read); + int prev_auto_sync = lmp->kokkos->auto_sync; + if (!fix[list_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_post_neighbor[i]]->post_neighbor(); + lmp->kokkos->auto_sync = prev_auto_sync; + atomKK->modified(fix[list_post_neighbor[i]]->execution_space, + fix[list_post_neighbor[i]]->datamask_modify); + } +} + /* ---------------------------------------------------------------------- pre_force call, only for relevant fixes ------------------------------------------------------------------------- */ @@ -420,6 +482,12 @@ void ModifyKokkos::post_run() atomKK->modified(fix[i]->execution_space, fix[i]->datamask_modify); } + + // must reset this to its default value, since computes may be added + // or removed between runs and with this change we will redirect any + // calls to addstep_compute() to addstep_compute_all() instead. + n_timeflag = -1; + } /* ---------------------------------------------------------------------- @@ -567,6 +635,24 @@ void ModifyKokkos::min_pre_neighbor() } } +/* ---------------------------------------------------------------------- + minimizer post-neighbor call, only for relevant fixes +------------------------------------------------------------------------- */ + +void ModifyKokkos::min_post_neighbor() +{ + for (int i = 0; i < n_min_post_neighbor; i++) { + atomKK->sync(fix[list_min_post_neighbor[i]]->execution_space, + fix[list_min_post_neighbor[i]]->datamask_read); + int prev_auto_sync = lmp->kokkos->auto_sync; + if (!fix[list_min_post_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_min_post_neighbor[i]]->min_post_neighbor(); + lmp->kokkos->auto_sync = prev_auto_sync; + atomKK->modified(fix[list_min_post_neighbor[i]]->execution_space, + fix[list_min_post_neighbor[i]]->datamask_modify); + } +} + /* ---------------------------------------------------------------------- minimizer pre-force call, only for relevant fixes ------------------------------------------------------------------------- */ @@ -646,7 +732,7 @@ double ModifyKokkos::min_energy(double *fextra) } /* ---------------------------------------------------------------------- - store current state of extra dof, only for relevant fixes + store current state of extra minimizer dof, only for relevant fixes ------------------------------------------------------------------------- */ void ModifyKokkos::min_store() @@ -664,7 +750,7 @@ void ModifyKokkos::min_store() } /* ---------------------------------------------------------------------- - mange state of extra dof on a stack, only for relevant fixes + manage state of extra minimizer dof on a stack, only for relevant fixes ------------------------------------------------------------------------- */ void ModifyKokkos::min_clearstore() @@ -710,7 +796,7 @@ void ModifyKokkos::min_popstore() } /* ---------------------------------------------------------------------- - displace extra dof along vector hextra, only for relevant fixes + displace extra minimizer dof along vector hextra, only for relevant fixes ------------------------------------------------------------------------- */ void ModifyKokkos::min_step(double alpha, double *hextra) @@ -755,7 +841,7 @@ double ModifyKokkos::max_alpha(double *hextra) } /* ---------------------------------------------------------------------- - extract extra dof for minimization, only for relevant fixes + extract extra minimizer dof, only for relevant fixes ------------------------------------------------------------------------- */ int ModifyKokkos::min_dof() @@ -775,7 +861,7 @@ int ModifyKokkos::min_dof() } /* ---------------------------------------------------------------------- - reset reference state of fix, only for relevant fixes + reset minimizer reference state of fix, only for relevant fixes ------------------------------------------------------------------------- */ int ModifyKokkos::min_reset_ref() @@ -788,10 +874,10 @@ int ModifyKokkos::min_reset_ref() int prev_auto_sync = lmp->kokkos->auto_sync; if (!fix[list_min_energy[i]]->kokkosable) lmp->kokkos->auto_sync = 1; itmp = fix[list_min_energy[i]]->min_reset_ref(); - lmp->kokkos->auto_sync = prev_auto_sync; if (itmp) itmpall = 1; + lmp->kokkos->auto_sync = prev_auto_sync; atomKK->modified(fix[list_min_energy[i]]->execution_space, fix[list_min_energy[i]]->datamask_modify); } - return itmpall; +return itmpall; } diff --git a/src/KOKKOS/modify_kokkos.h b/src/KOKKOS/modify_kokkos.h index 9b75b7c607..25911743b2 100644 --- a/src/KOKKOS/modify_kokkos.h +++ b/src/KOKKOS/modify_kokkos.h @@ -26,6 +26,7 @@ class ModifyKokkos : public Modify { void setup(int); void setup_pre_exchange(); void setup_pre_neighbor(); + void setup_post_neighbor(); void setup_pre_force(int); void setup_pre_reverse(int, int); void initial_integrate(int); @@ -33,6 +34,7 @@ class ModifyKokkos : public Modify { void pre_decide(); void pre_exchange(); void pre_neighbor(); + void post_neighbor(); void pre_force(int); void pre_reverse(int,int); void post_force(int); @@ -52,6 +54,7 @@ class ModifyKokkos : public Modify { void min_pre_exchange(); void min_pre_neighbor(); + void min_post_neighbor(); void min_pre_force(int); void min_pre_reverse(int,int); void min_post_force(int); From d9288ae7e9bf47da56d549ac228723cf8e2265b6 Mon Sep 17 00:00:00 2001 From: Stan Moore Date: Wed, 6 Oct 2021 08:33:02 -0700 Subject: [PATCH 38/84] whitespace --- src/KOKKOS/modify_kokkos.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KOKKOS/modify_kokkos.cpp b/src/KOKKOS/modify_kokkos.cpp index 08bbfa762f..5545351f53 100644 --- a/src/KOKKOS/modify_kokkos.cpp +++ b/src/KOKKOS/modify_kokkos.cpp @@ -879,5 +879,5 @@ int ModifyKokkos::min_reset_ref() atomKK->modified(fix[list_min_energy[i]]->execution_space, fix[list_min_energy[i]]->datamask_modify); } -return itmpall; + return itmpall; } From 891d4c278ff3303c79dc51a305b374f3402b11e2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 14:08:45 -0400 Subject: [PATCH 39/84] port dump movie to platform namespace --- src/dump_movie.cpp | 26 +++++++++++++------------- src/dump_movie.h | 1 + 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/dump_movie.cpp b/src/dump_movie.cpp index fb834b5fb0..52c0522289 100644 --- a/src/dump_movie.cpp +++ b/src/dump_movie.cpp @@ -41,28 +41,29 @@ DumpMovie::DumpMovie(LAMMPS *lmp, int narg, char **arg) : /* ---------------------------------------------------------------------- */ +DumpMovie::~DumpMovie() +{ + if (fp) platform::pclose(fp); + fp = nullptr; +} + +/* ---------------------------------------------------------------------- */ + void DumpMovie::openfile() { - char moviecmd[1024]; - if ((comm->me == 0) && (fp == nullptr)) { #ifdef LAMMPS_FFMPEG - sprintf(moviecmd,"ffmpeg -v error -y -r %.2f -f image2pipe -c:v ppm -i - " - "-r 24.0 -b:v %dk %s ", framerate, bitrate, filename); + auto moviecmd = fmt::format("ffmpeg -v error -y -r {:.2f} -f image2pipe -c:v ppm -i - " + "-r 24.0 -b:v {}k {}", framerate, bitrate, filename); + fp = platform::popen(moviecmd,"w"); #else + fp = nullptr; error->one(FLERR,"Support for writing movies not included"); #endif -#if defined(_WIN32) - fp = _popen(moviecmd,"wb"); -#else - fp = popen(moviecmd,"w"); -#endif - if (fp == nullptr) - error->one(FLERR,"Failed to open FFmpeg pipeline to " - "file {}",filename); + error->one(FLERR,"Failed to open FFmpeg pipeline to file {}",filename); } } /* ---------------------------------------------------------------------- */ @@ -100,4 +101,3 @@ int DumpMovie::modify_param(int narg, char **arg) return 0; } - diff --git a/src/dump_movie.h b/src/dump_movie.h index 1c41cb09b5..770193e039 100644 --- a/src/dump_movie.h +++ b/src/dump_movie.h @@ -27,6 +27,7 @@ namespace LAMMPS_NS { class DumpMovie : public DumpImage { public: DumpMovie(LAMMPS *, int, char **); + virtual ~DumpMovie(); virtual void openfile(); virtual void init_style(); From 3d86a0f5f661e1d1ac7c466c5232b088cebe64e4 Mon Sep 17 00:00:00 2001 From: Stan Moore Date: Wed, 6 Oct 2021 11:15:34 -0700 Subject: [PATCH 40/84] Fix two bugs in compute_orientorder_atom_kokkos --- src/KOKKOS/compute_orientorder_atom_kokkos.cpp | 14 ++++++++++---- src/MAKE/MACHINES/Makefile.summit_kokkos | 6 +++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/KOKKOS/compute_orientorder_atom_kokkos.cpp b/src/KOKKOS/compute_orientorder_atom_kokkos.cpp index 131e9933e8..f7ec879e3c 100644 --- a/src/KOKKOS/compute_orientorder_atom_kokkos.cpp +++ b/src/KOKKOS/compute_orientorder_atom_kokkos.cpp @@ -173,8 +173,6 @@ void ComputeOrientOrderAtomKokkos::compute_peratom() x = atomKK->k_x.view(); mask = atomKK->k_mask.view(); - Kokkos::deep_copy(d_qnm,{0.0,0.0}); - int vector_length_default = 1; int team_size_default = 1; if (!host_flag) @@ -185,6 +183,8 @@ void ComputeOrientOrderAtomKokkos::compute_peratom() if (chunk_size > inum - chunk_offset) chunk_size = inum - chunk_offset; + Kokkos::deep_copy(d_qnm,{0.0,0.0}); + //Neigh { int vector_length = vector_length_default; @@ -286,7 +286,7 @@ void ComputeOrientOrderAtomKokkos::operator() (TagComputeOrientOrder const int i = d_ilist[ii + chunk_offset]; const int ncount = d_ncount(ii); - // if not nnn neighbors, order parameter = 0; + // if not nnn neighbors, order parameter = 0 if ((ncount == 0) || (ncount < nnn)) { for (int jj = 0; jj < ncol; jj++) @@ -316,7 +316,7 @@ void ComputeOrientOrderAtomKokkos::operator() (TagComputeOrientOrder const int ncount = d_ncount(ii); if (jj >= ncount) return; - // if not nnn neighbors, order parameter = 0; + // if not nnn neighbors, order parameter = 0 if ((ncount == 0) || (ncount < nnn)) return; @@ -328,6 +328,12 @@ template KOKKOS_INLINE_FUNCTION void ComputeOrientOrderAtomKokkos::operator() (TagComputeOrientOrderAtomBOOP2,const int& ii) const { const int ncount = d_ncount(ii); + + // if not nnn neighbors, order parameter = 0 + + if ((ncount == 0) || (ncount < nnn)) + return; + calc_boop2(ncount, ii); } diff --git a/src/MAKE/MACHINES/Makefile.summit_kokkos b/src/MAKE/MACHINES/Makefile.summit_kokkos index 95ee7e39a8..4bd74a89c0 100644 --- a/src/MAKE/MACHINES/Makefile.summit_kokkos +++ b/src/MAKE/MACHINES/Makefile.summit_kokkos @@ -9,7 +9,7 @@ SHELL = /bin/sh KOKKOS_ABSOLUTE_PATH = $(shell cd $(KOKKOS_PATH); pwd) CC = $(KOKKOS_ABSOLUTE_PATH)/bin/nvcc_wrapper -CCFLAGS = -g -O3 +CCFLAGS = -g -O3 -DLAMMPS_BIGBIG SHFLAGS = -fPIC DEPFLAGS = -M @@ -68,9 +68,9 @@ FFT_LIB = -lcufft # PATH = path(s) for JPEG library and/or PNG library # LIB = name(s) of JPEG library and/or PNG library -JPG_INC = +JPG_INC = -DLAMMPS_PNG -I~/libpng-1.6.37/include JPG_PATH = -JPG_LIB = +JPG_LIB = -L~/libpng-1.6.37/lib -lpng # --------------------------------------------------------------------- # build rules and dependencies From a539c317b3297089c26c93917cf9c0af6a458252 Mon Sep 17 00:00:00 2001 From: Stan Moore Date: Wed, 6 Oct 2021 11:43:40 -0700 Subject: [PATCH 41/84] Revert changes to makefile --- src/MAKE/MACHINES/Makefile.summit_kokkos | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MAKE/MACHINES/Makefile.summit_kokkos b/src/MAKE/MACHINES/Makefile.summit_kokkos index 4bd74a89c0..95ee7e39a8 100644 --- a/src/MAKE/MACHINES/Makefile.summit_kokkos +++ b/src/MAKE/MACHINES/Makefile.summit_kokkos @@ -9,7 +9,7 @@ SHELL = /bin/sh KOKKOS_ABSOLUTE_PATH = $(shell cd $(KOKKOS_PATH); pwd) CC = $(KOKKOS_ABSOLUTE_PATH)/bin/nvcc_wrapper -CCFLAGS = -g -O3 -DLAMMPS_BIGBIG +CCFLAGS = -g -O3 SHFLAGS = -fPIC DEPFLAGS = -M @@ -68,9 +68,9 @@ FFT_LIB = -lcufft # PATH = path(s) for JPEG library and/or PNG library # LIB = name(s) of JPEG library and/or PNG library -JPG_INC = -DLAMMPS_PNG -I~/libpng-1.6.37/include +JPG_INC = JPG_PATH = -JPG_LIB = -L~/libpng-1.6.37/lib -lpng +JPG_LIB = # --------------------------------------------------------------------- # build rules and dependencies From ec1a55b35bf3c623f3a490d75b9c1e244a61c593 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 15:04:48 -0400 Subject: [PATCH 42/84] use platform code for reading/writing of compressed text file via a pipe --- src/EXTRA-FIX/fix_tmd.cpp | 29 +++++++++--------------- src/EXTRA-FIX/fix_tmd.h | 2 +- src/PHONON/dynamical_matrix.cpp | 37 +++++++++++++------------------ src/PHONON/third_order.cpp | 35 +++++++++++++---------------- src/REAXFF/fix_reaxff_bonds.cpp | 25 +++++++-------------- src/REAXFF/fix_reaxff_bonds.h | 2 +- src/REAXFF/fix_reaxff_species.cpp | 34 ++++++++++++---------------- src/REAXFF/fix_reaxff_species.h | 2 +- src/REPLICA/neb.cpp | 28 +++++++++-------------- src/SPIN/neb_spin.cpp | 25 +++++++-------------- src/dump.cpp | 19 ++++------------ src/read_data.cpp | 28 ++++++----------------- src/read_data.h | 2 +- src/reader.cpp | 27 ++++++---------------- src/reader.h | 2 +- 15 files changed, 104 insertions(+), 193 deletions(-) diff --git a/src/EXTRA-FIX/fix_tmd.cpp b/src/EXTRA-FIX/fix_tmd.cpp index a46eb89713..93d7ae6a56 100644 --- a/src/EXTRA-FIX/fix_tmd.cpp +++ b/src/EXTRA-FIX/fix_tmd.cpp @@ -123,7 +123,10 @@ nfileevery(0), fp(nullptr), xf(nullptr), xold(nullptr) FixTMD::~FixTMD() { - if (nfileevery && me == 0) fclose(fp); + if (nfileevery && me == 0) { + if (compressed) platform::pclose(fp); + else fclose(fp); + } // unregister callbacks to this fix from Atom class @@ -517,30 +520,18 @@ void FixTMD::readfile(char *file) test if gzipped ------------------------------------------------------------------------- */ -void FixTMD::open(char *file) +void FixTMD::open(const std::string &file) { - if (utils::strmatch(file,"\\.gz$")) { + if (platform::has_zip_extension(file)) { compressed = 1; - -#ifdef LAMMPS_GZIP - auto gunzip = fmt::format("gzip -c -d {}",file); - -#ifdef _WIN32 - fp = _popen(gunzip.c_str(),"rb"); -#else - fp = popen(gunzip.c_str(),"r"); -#endif - -#else - error->one(FLERR,"Cannot open gzipped file without gzip support"); -#endif + fp = platform::zip_read(file); + if (!fp) error->one(FLERR,"Cannot open compressed file for reading"); } else { compressed = 0; - fp = fopen(file,"r"); + fp = fopen(file.c_str(),"r"); } - if (fp == nullptr) - error->one(FLERR,"Cannot open file {}: {}",file, utils::getsyserror()); + if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror()); } /* ---------------------------------------------------------------------- */ diff --git a/src/EXTRA-FIX/fix_tmd.h b/src/EXTRA-FIX/fix_tmd.h index fd818eb583..b85869930a 100644 --- a/src/EXTRA-FIX/fix_tmd.h +++ b/src/EXTRA-FIX/fix_tmd.h @@ -52,7 +52,7 @@ class FixTMD : public Fix { double **xf, **xold; void readfile(char *); - void open(char *); + void open(const std::string &); }; } // namespace LAMMPS_NS diff --git a/src/PHONON/dynamical_matrix.cpp b/src/PHONON/dynamical_matrix.cpp index f7cb3f7f44..b2f473f9cc 100644 --- a/src/PHONON/dynamical_matrix.cpp +++ b/src/PHONON/dynamical_matrix.cpp @@ -55,9 +55,12 @@ DynamicalMatrix::DynamicalMatrix(LAMMPS *lmp) : Command(lmp), fp(nullptr) DynamicalMatrix::~DynamicalMatrix() { - if (fp && me == 0) fclose(fp); + if (fp && me == 0) { + if (compressed) platform::pclose(fp); + else fclose(fp); memory->destroy(groupmap); fp = nullptr; + } } /* ---------------------------------------------------------------------- @@ -212,32 +215,24 @@ void DynamicalMatrix::options(int narg, char **arg) some derived classes override this function ------------------------------------------------------------------------- */ -void DynamicalMatrix::openfile(const char* filename) +void DynamicalMatrix::openfile(const char *filename) { // if file already opened, return - //if (me!=0) return; if (file_opened) return; - - if (compressed) { -#ifdef LAMMPS_GZIP - char gzip[128]; - sprintf(gzip,"gzip -6 > %s",filename); -#ifdef _WIN32 - fp = _popen(gzip,"wb"); -#else - fp = popen(gzip,"w"); -#endif -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif - } else if (binaryflag) { + fp = nullptr; + + if (me == 0) { + if (compressed) { + fp = platform::zip_write(std::string(filename)+".gz"); + if (!fp) error->one(FLERR,"Cannot open gzipped file"); + } else if (binaryflag) { fp = fopen(filename,"wb"); - } else { + } else { fp = fopen(filename,"w"); + } + if (!fp) error->one(FLERR,"Cannot open dynmat file: {}", utils::getsyserror()); } - - if (fp == nullptr) error->one(FLERR,"Cannot open dump file"); - + file_opened = 1; } diff --git a/src/PHONON/third_order.cpp b/src/PHONON/third_order.cpp index 565e8b50e5..ca91a424af 100644 --- a/src/PHONON/third_order.cpp +++ b/src/PHONON/third_order.cpp @@ -55,7 +55,10 @@ ThirdOrder::ThirdOrder(LAMMPS *lmp) : Command(lmp), fp(nullptr) ThirdOrder::~ThirdOrder() { - if (fp && me == 0) fclose(fp); + if (fp && me == 0) { + if (compressed) platform::pclose(fp); + else fclose(fp); + } fp = nullptr; memory->destroy(groupmap); } @@ -215,27 +218,19 @@ void ThirdOrder::openfile(const char* filename) { // if file already opened, return if (file_opened) return; + fp = nullptr; - if (compressed) { -#ifdef LAMMPS_GZIP - char gzip[128]; - sprintf(gzip,"gzip -6 > %s",filename); -#ifdef _WIN32 - fp = _popen(gzip,"wb"); -#else - fp = popen(gzip,"w"); -#endif -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif - } else if (binaryflag) { - fp = fopen(filename,"wb"); - } else { - fp = fopen(filename,"w"); + if (me == 0) { + if (compressed) { + fp = platform::zip_write(std::string(filename)+".gz"); + if (!fp) error->one(FLERR,"Cannot open gzipped file"); + } else if (binaryflag) { + fp = fopen(filename,"wb"); + } else { + fp = fopen(filename,"w"); + } + if (!fp) error->one(FLERR,"Cannot open third_order file: {}", utils::getsyserror()); } - - if (fp == nullptr) error->one(FLERR,"Cannot open dump file"); - file_opened = 1; } diff --git a/src/REAXFF/fix_reaxff_bonds.cpp b/src/REAXFF/fix_reaxff_bonds.cpp index f13056c5b6..07d0c73f3d 100644 --- a/src/REAXFF/fix_reaxff_bonds.cpp +++ b/src/REAXFF/fix_reaxff_bonds.cpp @@ -45,30 +45,21 @@ FixReaxFFBonds::FixReaxFFBonds(LAMMPS *lmp, int narg, char **arg) : MPI_Comm_size(world,&nprocs); ntypes = atom->ntypes; nmax = atom->nmax; + compressed = 0; nevery = utils::inumeric(FLERR,arg[3],false,lmp); - if (nevery <= 0) - error->all(FLERR,"Illegal fix reaxff/bonds command"); + if (nevery <= 0) error->all(FLERR,"Illegal fix reaxff/bonds command"); if (me == 0) { - char *suffix = strrchr(arg[4],'.'); - if (suffix && strcmp(suffix,".gz") == 0) { -#ifdef LAMMPS_GZIP - auto gzip = fmt::format("gzip -6 > {}",arg[4]); -#ifdef _WIN32 - fp = _popen(gzip.c_str(),"wb"); -#else - fp = popen(gzip.c_str(),"w"); -#endif -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif + if (platform::has_zip_extension(arg[4])) { + compressed = 1; + fp = platform::zip_write(arg[4]); + if (!fp) error->one(FLERR,"Cannot open compressed file"); } else fp = fopen(arg[4],"w"); - if (!fp) - error->one(FLERR,fmt::format("Cannot open fix reaxff/bonds file {}: " - "{}",arg[4],utils::getsyserror())); + if (!fp) error->one(FLERR,fmt::format("Cannot open fix reaxff/bonds file {}: " + "{}",arg[4],utils::getsyserror())); } if (atom->tag_consecutive() == 0) diff --git a/src/REAXFF/fix_reaxff_bonds.h b/src/REAXFF/fix_reaxff_bonds.h index 4c2fd535ea..4c40017e43 100644 --- a/src/REAXFF/fix_reaxff_bonds.h +++ b/src/REAXFF/fix_reaxff_bonds.h @@ -36,7 +36,7 @@ class FixReaxFFBonds : public Fix { void end_of_step(); protected: - int me, nprocs, nmax, ntypes, maxsize; + int me, nprocs, nmax, ntypes, maxsize, compressed; int *numneigh; tagint **neighid; double **abo; diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index 4fc08975a8..856020227d 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -56,6 +56,7 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : size_peratom_cols = 0; peratom_freq = 1; + compressed = 0; nvalid = -1; MPI_Comm_rank(world,&me); @@ -106,23 +107,14 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : strcpy(tmparg[2],arg[5]); if (me == 0) { - char *suffix = strrchr(arg[6],'.'); - if (suffix && strcmp(suffix,".gz") == 0) { -#ifdef LAMMPS_GZIP - auto gzip = fmt::format("gzip -6 > {}",arg[6]); -#ifdef _WIN32 - fp = _popen(gzip.c_str(),"wb"); -#else - fp = popen(gzip.c_str(),"w"); -#endif -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif + if (platform::has_zip_extension(arg[6])) { + fp = platform::zip_write(arg[6]); + compressed = 1; + if (!fp) error->one(FLERR,"Cannot open compressed file"); } else fp = fopen(arg[6],"w"); - if (!fp) - error->one(FLERR,fmt::format("Cannot open fix reaxff/species file {}: " - "{}",arg[6],utils::getsyserror())); + if (!fp) error->one(FLERR,fmt::format("Cannot open fix reaxff/species file {}: " + "{}",arg[6],utils::getsyserror())); } x0 = nullptr; @@ -256,9 +248,12 @@ FixReaxFFSpecies::~FixReaxFFSpecies() if (filepos) delete [] filepos; - if (me == 0) fclose(fp); - if (me == 0 && posflag && multipos_opened) fclose(pos); - + if (me == 0) { + if (compressed) platform::pclose(fp); + else fclose(fp); + if (posflag && multipos_opened) fclose(pos); + } + modify->delete_compute("SPECATOM"); modify->delete_fix("SPECBOND"); } @@ -683,8 +678,7 @@ void FixReaxFFSpecies::OpenPos() char *ptr = strchr(filepos,'*'); *ptr = '\0'; if (padflag == 0) - sprintf(filecurrent,"%s" BIGINT_FORMAT "%s", - filepos,ntimestep,ptr+1); + sprintf(filecurrent,"%s" BIGINT_FORMAT "%s",filepos,ntimestep,ptr+1); else { char bif[8],pad[16]; strcpy(bif,BIGINT_FORMAT); diff --git a/src/REAXFF/fix_reaxff_species.h b/src/REAXFF/fix_reaxff_species.h index bcfcf2b6dd..91326273b6 100644 --- a/src/REAXFF/fix_reaxff_species.h +++ b/src/REAXFF/fix_reaxff_species.h @@ -45,7 +45,7 @@ class FixReaxFFSpecies : public Fix { protected: int me, nprocs, nmax, nlocal, ntypes, ntotal; - int nrepeat, nfreq, posfreq; + int nrepeat, nfreq, posfreq, compressed; int Nmoltype, vector_nmole, vector_nspec; int *Name, *MolName, *NMol, *nd, *MolType, *molmap; double *clusterID; diff --git a/src/REPLICA/neb.cpp b/src/REPLICA/neb.cpp index 9e6e32772d..281d0e830f 100644 --- a/src/REPLICA/neb.cpp +++ b/src/REPLICA/neb.cpp @@ -94,7 +94,10 @@ NEB::~NEB() MPI_Comm_free(&roots); memory->destroy(all); delete[] rdist; - if (fp) fclose(fp); + if (fp) { + if (compressed) platform::pclose(fp); + else fclose(fp); + } } /* ---------------------------------------------------------------------- @@ -539,28 +542,17 @@ void NEB::readfile(char *file, int flag) /* ---------------------------------------------------------------------- universe proc 0 opens NEB data file - test if gzipped + test if compressed ------------------------------------------------------------------------- */ void NEB::open(char *file) { compressed = 0; - char *suffix = file + strlen(file) - 3; - if (suffix > file && strcmp(suffix,".gz") == 0) compressed = 1; - if (!compressed) fp = fopen(file,"r"); - else { -#ifdef LAMMPS_GZIP - auto gunzip = std::string("gzip -c -d ") + file; -#ifdef _WIN32 - fp = _popen(gunzip.c_str(),"rb"); -#else - fp = popen(gunzip.c_str(),"r"); -#endif - -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif - } + if (platform::has_zip_extension(file)) { + compressed = 1; + fp = platform::zip_read(file); + if (!fp) error->one(FLERR,"Cannot open compressed file"); + } else fp = fopen(file,"r"); if (fp == nullptr) error->one(FLERR,"Cannot open file {}: {}",file,utils::getsyserror()); diff --git a/src/SPIN/neb_spin.cpp b/src/SPIN/neb_spin.cpp index fe24235a98..c2cefdcc97 100644 --- a/src/SPIN/neb_spin.cpp +++ b/src/SPIN/neb_spin.cpp @@ -79,7 +79,10 @@ NEBSpin::~NEBSpin() MPI_Comm_free(&roots); memory->destroy(all); delete[] rdist; - if (fp) fclose(fp); + if (fp) { + if (compressed) platform::pclose(fp); + else fclose(fp); + } } /* ---------------------------------------------------------------------- @@ -690,22 +693,10 @@ int NEBSpin::initial_rotation(double *spi, double *sploc, double fraction) void NEBSpin::open(char *file) { compressed = 0; - char *suffix = file + strlen(file) - 3; - if (suffix > file && strcmp(suffix,".gz") == 0) compressed = 1; - if (!compressed) fp = fopen(file,"r"); - else { -#ifdef LAMMPS_GZIP - auto gunzip = std::string("gzip -c -d ") + file; -#ifdef _WIN32 - fp = _popen(gunzip.c_str(),"rb"); -#else - fp = popen(gunzip.c_str(),"r"); -#endif - -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif - } + if (platform::has_zip_extension(file)) { + fp = platform::zip_read(file); + if (!fp) error->one(FLERR,"Cannot open compressed file"); + } else fp = fopen(file,"r"); if (fp == nullptr) error->one(FLERR,"Cannot open file {}: {}",file,utils::getsyserror()); diff --git a/src/dump.cpp b/src/dump.cpp index 647fd3d38d..637ded53d0 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -108,9 +108,8 @@ Dump::Dump(LAMMPS *lmp, int /*narg*/, char **arg) : Pointers(lmp) // if contains '%', write one file per proc and replace % with proc-ID // if contains '*', write one file per timestep and replace * with timestep // check file suffixes - // if ends in .bin = binary file - // else if ends in .gz = gzipped text file - // else if ends in .zst = Zstd compressed text file + // if ends in .bin -> binary file + // else if ends in .gz or other known extensions -> compressed text file // else ASCII text file fp = nullptr; @@ -144,8 +143,7 @@ Dump::Dump(LAMMPS *lmp, int /*narg*/, char **arg) : Pointers(lmp) if (strchr(filename,'*')) multifile = 1; if (utils::strmatch(filename, "\\.bin$")) binary = 1; - if (utils::strmatch(filename, "\\.gz$") - || utils::strmatch(filename, "\\.zst$")) compressed = 1; + if (platform::has_zip_extension(filename)) compressed = 1; } /* ---------------------------------------------------------------------- */ @@ -580,16 +578,7 @@ void Dump::openfile() if (filewriter) { if (compressed) { -#ifdef LAMMPS_GZIP - auto gzip = fmt::format("gzip -6 > {}",filecurrent); -#ifdef _WIN32 - fp = _popen(gzip.c_str(),"wb"); -#else - fp = popen(gzip.c_str(),"w"); -#endif -#else - error->one(FLERR,"Cannot open gzipped file"); -#endif + fp = platform::zip_write(filecurrent); } else if (binary) { fp = fopen(filecurrent,"wb"); } else if (append_flag) { diff --git a/src/read_data.cpp b/src/read_data.cpp index bb4fbe0315..bbc3e20d44 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -741,7 +741,7 @@ void ReadData::command(int narg, char **arg) // close file if (me == 0) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); fp = nullptr; } @@ -1954,31 +1954,17 @@ int ReadData::reallocate(int **pcount, int cmax, int amax) test if gzipped ------------------------------------------------------------------------- */ -void ReadData::open(char *file) +void ReadData::open(const std::string &file) { - if (utils::strmatch(file,"\\.gz$")) { + if (platform::has_zip_extension(file)) { compressed = 1; - -#ifdef LAMMPS_GZIP - auto gunzip = fmt::format("gzip -c -d {}",file); - -#ifdef _WIN32 - fp = _popen(gunzip.c_str(),"rb"); -#else - fp = popen(gunzip.c_str(),"r"); -#endif - -#else - error->one(FLERR,"Cannot open gzipped file without gzip support"); -#endif + fp = platform::zip_read(file); + if (!fp) error->one(FLERR,"Cannot open compressed file {}", file); } else { compressed = 0; - fp = fopen(file,"r"); + fp = fopen(file.c_str(),"r"); + if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror()); } - - if (fp == nullptr) - error->one(FLERR,"Cannot open file {}: {}", - file, utils::getsyserror()); } /* ---------------------------------------------------------------------- diff --git a/src/read_data.h b/src/read_data.h index 482c45e6e6..3374f48be0 100644 --- a/src/read_data.h +++ b/src/read_data.h @@ -78,7 +78,7 @@ class ReadData : public Command { // methods - void open(char *); + void open(const std::string &); void scan(int &, int &, int &, int &); int reallocate(int **, int, int); void header(int); diff --git a/src/reader.cpp b/src/reader.cpp index 71036e7444..3a07417912 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -32,33 +32,20 @@ Reader::Reader(LAMMPS *lmp) : Pointers(lmp) generic version for ASCII files that may be compressed ------------------------------------------------------------------------- */ -void Reader::open_file(const char *file) +void Reader::open_file(const std::string &file) { if (fp != nullptr) close_file(); - if (utils::strmatch(file,"\\.gz$")) { + if (platform::has_zip_extension(file)) { compressed = 1; - -#ifdef LAMMPS_GZIP - auto gunzip = fmt::format("gzip -c -d {}",file); - -#ifdef _WIN32 - fp = _popen(gunzip.c_str(),"rb"); -#else - fp = popen(gunzip.c_str(),"r"); -#endif - -#else - error->one(FLERR,"Cannot open gzipped file without gzip support"); -#endif + fp = platform::zip_read(file); + if (!fp) error->one(FLERR,"Cannot open compressed file for reading"); } else { compressed = 0; - fp = fopen(file,"r"); + fp = fopen(file.c_str(),"r"); } - if (fp == nullptr) - error->one(FLERR,"Cannot open file {}: {}", - file, utils::getsyserror()); + if (!fp) error->one(FLERR,"Cannot open file {}: {}", file, utils::getsyserror()); } /* ---------------------------------------------------------------------- @@ -69,7 +56,7 @@ void Reader::open_file(const char *file) void Reader::close_file() { if (fp == nullptr) return; - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); fp = nullptr; } diff --git a/src/reader.h b/src/reader.h index 2d71750f98..18977790cd 100644 --- a/src/reader.h +++ b/src/reader.h @@ -33,7 +33,7 @@ class Reader : protected Pointers { int &, int &, int &) = 0; virtual void read_atoms(int, int, double **) = 0; - virtual void open_file(const char *); + virtual void open_file(const std::string &); virtual void close_file(); protected: From 6c7b42a190ee3242f0c11b75bff6bfab6f401ffc Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 15:24:59 -0400 Subject: [PATCH 43/84] small tweaks and fixes for compiling with MSVC++ --- cmake/CMakeLists.txt | 4 +++- src/dump.cpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 3af67bf8e0..4ca978338f 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -97,9 +97,11 @@ if(PKG_KOKKOS AND (CMAKE_CXX_STANDARD LESS 14)) endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "Use compiler extensions") -# ugly hack for MSVC which by default always reports an old C++ standard in the __cplusplus macro +# ugly hacks for MSVC which by default always reports an old C++ standard in the __cplusplus macro +# and prints lots of pointless warnings about "unsafe" functions if(MSVC) add_compile_options(/Zc:__cplusplus) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() # export all symbols when building a .dll file on windows diff --git a/src/dump.cpp b/src/dump.cpp index 637ded53d0..7dbe95c1d3 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -196,7 +196,7 @@ Dump::~Dump() if (multifile == 0 && fp != nullptr) { if (compressed) { - if (filewriter) pclose(fp); + if (filewriter) platform::pclose(fp); } else { if (filewriter) fclose(fp); } @@ -518,7 +518,7 @@ void Dump::write() if (multifile) { if (compressed) { - if (filewriter && fp != nullptr) pclose(fp); + if (filewriter && fp != nullptr) platform::pclose(fp); } else { if (filewriter && fp != nullptr) fclose(fp); } From 7a1cf322e5cfd8cf46bedd923cb5a2f5c5c6d69f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 15:57:26 -0400 Subject: [PATCH 44/84] more tweaks for Visual C++ compilation and portability --- cmake/CMakeLists.txt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 4ca978338f..2e1504f1f0 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -101,6 +101,8 @@ set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "Use compiler extensions") # and prints lots of pointless warnings about "unsafe" functions if(MSVC) add_compile_options(/Zc:__cplusplus) + add_compile_options(/wd4244) + add_compile_options(/wd4267) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() @@ -473,9 +475,12 @@ foreach(HEADER cmath) endif(NOT FOUND_${HEADER}) endforeach(HEADER) -set(MATH_LIBRARIES "m" CACHE STRING "math library") -mark_as_advanced( MATH_LIBRARIES ) -target_link_libraries(lammps PRIVATE ${MATH_LIBRARIES}) +# make the standard math library overrideable and autodetected (for systems that don't have it) +find_library(STANDARD_MATH_LIB m DOC "Standard Math library") +mark_as_advanced(STANDARD_MATH_LIB) +if(STANDARD_MATH_LIB) + target_link_libraries(lammps PRIVATE ${STANDARD_MATH_LIB}) +endif() ###################################### # Generate Basic Style files @@ -613,7 +618,7 @@ endif() # and after everything else that is compiled locally ###################################################################### if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - target_link_libraries(lammps PRIVATE -lwsock32 -lpsapi) + target_link_libraries(lammps PRIVATE "wsock32;psapi") endif() ###################################################### From 4260d31b85f715c2fe649a4e8b8d4e4c3bd25c03 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 15:57:33 -0400 Subject: [PATCH 45/84] whitespace --- src/PHONON/dynamical_matrix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PHONON/dynamical_matrix.cpp b/src/PHONON/dynamical_matrix.cpp index b2f473f9cc..8861a87491 100644 --- a/src/PHONON/dynamical_matrix.cpp +++ b/src/PHONON/dynamical_matrix.cpp @@ -220,7 +220,7 @@ void DynamicalMatrix::openfile(const char *filename) // if file already opened, return if (file_opened) return; fp = nullptr; - + if (me == 0) { if (compressed) { fp = platform::zip_write(std::string(filename)+".gz"); @@ -232,7 +232,7 @@ void DynamicalMatrix::openfile(const char *filename) } if (!fp) error->one(FLERR,"Cannot open dynmat file: {}", utils::getsyserror()); } - + file_opened = 1; } From 50d997526cbe33ada1af0af206a8656048a54215 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 16:13:12 -0400 Subject: [PATCH 46/84] a few more MSVC++ tweaks for improved compatibility and fewer warnings --- cmake/Modules/Tools.cmake | 4 +++- src/lammps.cpp | 4 ++-- src/platform.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cmake/Modules/Tools.cmake b/cmake/Modules/Tools.cmake index 146764dbd5..c3b0a0771d 100644 --- a/cmake/Modules/Tools.cmake +++ b/cmake/Modules/Tools.cmake @@ -25,7 +25,9 @@ if(BUILD_TOOLS) get_filename_component(MSI2LMP_SOURCE_DIR ${LAMMPS_TOOLS_DIR}/msi2lmp/src ABSOLUTE) file(GLOB MSI2LMP_SOURCES ${MSI2LMP_SOURCE_DIR}/[^.]*.c) add_executable(msi2lmp ${MSI2LMP_SOURCES}) - target_link_libraries(msi2lmp PRIVATE ${MATH_LIBRARIES}) + if(STANDARD_MATH_LIB) + target_link_libraries(msi2lmp PRIVATE ${STANDARD_MATH_LIB}) + endif() install(TARGETS msi2lmp DESTINATION ${CMAKE_INSTALL_BINDIR}) install(FILES ${LAMMPS_DOC_DIR}/msi2lmp.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) endif() diff --git a/src/lammps.cpp b/src/lammps.cpp index 5e76e08112..f4dd4e5708 100644 --- a/src/lammps.cpp +++ b/src/lammps.cpp @@ -657,7 +657,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) : int n = plast[i] - pfirst[i]; packargs[i] = new char*[n+1]; for (int j=0; j < n; ++j) - packargs[i][j] = strdup(arg[pfirst[i]+j]); + packargs[i][j] = utils::strdup(arg[pfirst[i]+j]); packargs[i][n] = nullptr; } memory->destroy(pfirst); @@ -711,7 +711,7 @@ LAMMPS::~LAMMPS() if (num_package) { for (int i = 0; i < num_package; i++) { for (char **ptr = packargs[i]; *ptr != nullptr; ++ptr) - free(*ptr); + delete[] *ptr; delete[] packargs[i]; } delete[] packargs; diff --git a/src/platform.cpp b/src/platform.cpp index 427085a6be..ddd9d8ba8e 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -619,7 +619,7 @@ bool platform::is_console(FILE *fp) { if (!fp) return false; #if defined(_WIN32) - return (_isatty(fileno(fp)) == 1); + return (_isatty(_fileno(fp)) == 1); #else return (isatty(fileno(fp)) == 1); #endif From f643c2b98f676e68d5cc472b1364d34d98abd288 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 16:32:43 -0400 Subject: [PATCH 47/84] portability changes --- src/MANYBODY/pair_atm.cpp | 8 ++++---- src/OPENMP/npair_half_size_multi_newton_omp.cpp | 2 +- src/REAXFF/fix_reaxff_species.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/MANYBODY/pair_atm.cpp b/src/MANYBODY/pair_atm.cpp index 81adef5871..f7eda909e6 100644 --- a/src/MANYBODY/pair_atm.cpp +++ b/src/MANYBODY/pair_atm.cpp @@ -128,9 +128,9 @@ void PairATM::compute(int eflag, int vflag) rij[0] = x[j][0] - xi; if (rij[0] < 0.0) continue; rij[1] = x[j][1] - yi; - if (rij[0] == 0.0 and rij[1] < 0.0) continue; + if (rij[0] == 0.0 && rij[1] < 0.0) continue; rij[2] = x[j][2] - zi; - if (rij[0] == 0.0 and rij[1] == 0.0 and rij[2] < 0.0) continue; + if (rij[0] == 0.0 && rij[1] == 0.0 && rij[2] < 0.0) continue; rij2 = rij[0]*rij[0] + rij[1]*rij[1] + rij[2]*rij[2]; if (rij2 > cutoff_squared) continue; @@ -141,9 +141,9 @@ void PairATM::compute(int eflag, int vflag) rik[0] = x[k][0] - xi; if (rik[0] < 0.0) continue; rik[1] = x[k][1] - yi; - if (rik[0] == 0.0 and rik[1] < 0.0) continue; + if (rik[0] == 0.0 && rik[1] < 0.0) continue; rik[2] = x[k][2] - zi; - if (rik[0] == 0.0 and rik[1] == 0.0 and rik[2] < 0.0) continue; + if (rik[0] == 0.0 && rik[1] == 0.0 && rik[2] < 0.0) continue; rik2 = rik[0]*rik[0] + rik[1]*rik[1] + rik[2]*rik[2]; if (rik2 > cutoff_squared) continue; diff --git a/src/OPENMP/npair_half_size_multi_newton_omp.cpp b/src/OPENMP/npair_half_size_multi_newton_omp.cpp index cdc68e1b42..bcf87d385c 100644 --- a/src/OPENMP/npair_half_size_multi_newton_omp.cpp +++ b/src/OPENMP/npair_half_size_multi_newton_omp.cpp @@ -108,7 +108,7 @@ void NPairHalfSizeMultiNewtonOmp::build(NeighList *list) // if j is ghost, only store if j coords are "above and to the right" of i for (j = js; j >= 0; j = bins[j]) { - if(icollection != jcollection and j < i) continue; + if(icollection != jcollection && j < i) continue; if (j >= nlocal) { if (x[j][2] < ztmp) continue; diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index 856020227d..897f36d988 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -253,7 +253,7 @@ FixReaxFFSpecies::~FixReaxFFSpecies() else fclose(fp); if (posflag && multipos_opened) fclose(pos); } - + modify->delete_compute("SPECATOM"); modify->delete_fix("SPECBOND"); } From aab3e085a265e898faecca85cc45cf6a2d206165 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 16:41:29 -0400 Subject: [PATCH 48/84] silence compiler warning on windows --- src/MANYBODY/pair_polymorphic.cpp | 2 +- src/MOLECULE/angle_table.cpp | 2 +- src/MOLECULE/bond_table.cpp | 2 +- src/error.cpp | 9 +++++---- src/pair_table.cpp | 2 +- src/utils.cpp | 2 +- tools/msi2lmp/src/SearchAndFill.c | 4 ++++ 7 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/MANYBODY/pair_polymorphic.cpp b/src/MANYBODY/pair_polymorphic.cpp index f12d369e0d..ce476e1204 100644 --- a/src/MANYBODY/pair_polymorphic.cpp +++ b/src/MANYBODY/pair_polymorphic.cpp @@ -593,7 +593,7 @@ void PairPolymorphic::read_file(char *file) if ((ng == 0) || (nr == 0) || (nx == 0)) error->one(FLERR,"Error reading potential file header"); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { error->one(FLERR,"Potential file incompatible with this pair style version"); } diff --git a/src/MOLECULE/angle_table.cpp b/src/MOLECULE/angle_table.cpp index 4299e375f1..a5ba07b779 100644 --- a/src/MOLECULE/angle_table.cpp +++ b/src/MOLECULE/angle_table.cpp @@ -412,7 +412,7 @@ void AngleTable::read_table(Table *tb, char *file, char *keyword) tb->afile[i] = values.next_double(); tb->efile[i] = values.next_double(); tb->ffile[i] = values.next_double(); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { ++cerror; } } diff --git a/src/MOLECULE/bond_table.cpp b/src/MOLECULE/bond_table.cpp index 5637dfa699..db1314c76f 100644 --- a/src/MOLECULE/bond_table.cpp +++ b/src/MOLECULE/bond_table.cpp @@ -340,7 +340,7 @@ void BondTable::read_table(Table *tb, char *file, char *keyword) tb->rfile[i] = values.next_double(); tb->efile[i] = values.next_double(); tb->ffile[i] = values.next_double(); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { ++cerror; } diff --git a/src/error.cpp b/src/error.cpp index 9811a1d3eb..5338f41cca 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -58,7 +58,8 @@ void Error::universe_all(const std::string &file, int line, const std::string &s std::string mesg = "ERROR: " + str; try { mesg += fmt::format(" ({}:{})\n",truncpath(file),line); - } catch (fmt::format_error &e) { + } catch (fmt::format_error &) { + ; // do nothing } if (universe->me == 0) { if (universe->uscreen) fputs(mesg.c_str(),universe->uscreen); @@ -147,9 +148,9 @@ void Error::all(const std::string &file, int line, const std::string &str) std::string mesg = "ERROR: " + str; if (input && input->line) lastcmd = input->line; try { - mesg += fmt::format(" ({}:{})\nLast command: {}\n", - truncpath(file),line,lastcmd); - } catch (fmt::format_error &e) { + mesg += fmt::format(" ({}:{})\nLast command: {}\n", truncpath(file),line,lastcmd); + } catch (fmt::format_error &) { + ; // do nothing } utils::logmesg(lmp,mesg); } diff --git a/src/pair_table.cpp b/src/pair_table.cpp index 60272b5276..7b77a847f1 100644 --- a/src/pair_table.cpp +++ b/src/pair_table.cpp @@ -407,7 +407,7 @@ void PairTable::read_table(Table *tb, char *file, char *keyword) rfile = values.next_double(); tb->efile[i] = conversion_factor * values.next_double(); tb->ffile[i] = conversion_factor * values.next_double(); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { ++cerror; } diff --git a/src/utils.cpp b/src/utils.cpp index d67284822c..d87eb3784b 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1172,7 +1172,7 @@ double utils::timespec2seconds(const std::string ×pec) if (!values.has_next()) break; vals[i] = values.next_int(); } - } catch (TokenizerException &e) { + } catch (TokenizerException &) { return -1.0; } diff --git a/tools/msi2lmp/src/SearchAndFill.c b/tools/msi2lmp/src/SearchAndFill.c index 1a85ee111f..ff05ff13d0 100644 --- a/tools/msi2lmp/src/SearchAndFill.c +++ b/tools/msi2lmp/src/SearchAndFill.c @@ -13,6 +13,10 @@ #include #include +#if defined(_WIN32) +#define strdup(x) _strdup(x) +#endif + static int blank_line(char *line) { while (*line != '\0') { From a9bccee7b2cfe36e7a3e76304f69408d2836765f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 17:43:41 -0400 Subject: [PATCH 49/84] add utility to convert a string to lowercase --- doc/src/Developer_utils.rst | 3 +++ src/utils.cpp | 11 +++++++++++ src/utils.h | 7 +++++++ unittest/utils/test_utils.cpp | 6 ++++++ 4 files changed, 27 insertions(+) diff --git a/doc/src/Developer_utils.rst b/doc/src/Developer_utils.rst index 3cf059594b..72d7a80fa4 100644 --- a/doc/src/Developer_utils.rst +++ b/doc/src/Developer_utils.rst @@ -103,6 +103,9 @@ and parsing files or arguments. .. doxygenfunction:: strdup :project: progguide +.. doxygenfunction:: lowercase + :project: progguide + .. doxygenfunction:: trim :project: progguide diff --git a/src/utils.cpp b/src/utils.cpp index d87eb3784b..14241316de 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -694,6 +694,17 @@ char *utils::strdup(const std::string &text) return tmp; } +/* ---------------------------------------------------------------------- + Return string converted to lowercase +------------------------------------------------------------------------- */ + +std::string utils::lowercase(const std::string &text) +{ + std::string converted; + for (auto c : text) converted += ::tolower(c); + return converted; +} + /* ---------------------------------------------------------------------- Return string without leading or trailing whitespace ------------------------------------------------------------------------- */ diff --git a/src/utils.h b/src/utils.h index 0437633ea6..af8bec2aeb 100644 --- a/src/utils.h +++ b/src/utils.h @@ -282,6 +282,13 @@ namespace utils { char *strdup(const std::string &text); + /*! Convert string to lowercase + * + * \param line string that should be converted + * \return new string with all lowercase characters */ + + std::string lowercase(const std::string &line); + /*! Trim leading and trailing whitespace. Like TRIM() in Fortran. * * \param line string that should be trimmed diff --git a/unittest/utils/test_utils.cpp b/unittest/utils/test_utils.cpp index b2c688cd59..9e050f18e4 100644 --- a/unittest/utils/test_utils.cpp +++ b/unittest/utils/test_utils.cpp @@ -64,6 +64,12 @@ TEST(Utils, trim) ASSERT_THAT(trimmed, StrEq("")); } +TEST(Utils, lowercase) +{ + ASSERT_THAT(utils::lowercase("Gba35%*zAKgRvr"), StrEq("gba35%*zakgrvr")); + ASSERT_THAT(utils::lowercase("A BC DEFG"), StrEq("a bc defg")); +} + TEST(Utils, trim_comment) { auto trimmed = utils::trim_comment("some text # comment"); From ef84435b7c7256ad3390e1649f73cf05aecf25b6 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 17:44:45 -0400 Subject: [PATCH 50/84] replace non-portable strcasecmp() with comparing two strings converted to lowercase --- src/REAXFF/pair_reaxff.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/REAXFF/pair_reaxff.cpp b/src/REAXFF/pair_reaxff.cpp index a8cc249e58..000209a606 100644 --- a/src/REAXFF/pair_reaxff.cpp +++ b/src/REAXFF/pair_reaxff.cpp @@ -39,7 +39,6 @@ #include #include -#include // for strcasecmp() #include "reaxff_api.h" @@ -299,7 +298,7 @@ void PairReaxFF::coeff(int nargs, char **args) // pair_coeff element map for (int i = 3; i < nargs; i++) for (int j = 0; j < nreax_types; j++) - if (strcasecmp(args[i],api->system->reax_param.sbp[j].name) == 0) { + if (utils::lowercase(args[i]) == utils::lowercase(api->system->reax_param.sbp[j].name)) { map[i-2] = j; itmp ++; } From b3ca238a61f4ad8c6b127588bdc3115d7d33d519 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 17:44:57 -0400 Subject: [PATCH 51/84] silence warning --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 568da132e2..095e1752da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -79,7 +79,7 @@ int main(int argc, char **argv) KokkosLMP::finalize(); Python::finalize(); MPI_Abort(ae.universe, 1); - } catch (LAMMPSException &e) { + } catch (LAMMPSException &) { KokkosLMP::finalize(); Python::finalize(); MPI_Barrier(lammps_comm); From 5c34fe4d5d171e01c52a83ba889bdcc8b604f0a4 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 20:43:56 -0500 Subject: [PATCH 52/84] Replace strcasecmp() --- src/DIFFRACTION/compute_saed.cpp | 11 +++++------ src/DIFFRACTION/compute_xrd.cpp | 3 +-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/DIFFRACTION/compute_saed.cpp b/src/DIFFRACTION/compute_saed.cpp index 77f17d77d1..e2df7fe3b8 100644 --- a/src/DIFFRACTION/compute_saed.cpp +++ b/src/DIFFRACTION/compute_saed.cpp @@ -31,7 +31,6 @@ #include #include -#include // for strcasecmp() #include "omp_compat.h" using namespace LAMMPS_NS; @@ -85,13 +84,13 @@ ComputeSAED::ComputeSAED(LAMMPS *lmp, int narg, char **arg) : ztype[i] = SAEDmaxType + 1; } for (int i=0; iall(FLERR,"Compute SAED: Invalid ASF atom type"); + } + if (ztype[i] == SAEDmaxType + 1) + error->all(FLERR,"Compute SAED: Invalid ASF atom type"); iarg++; } diff --git a/src/DIFFRACTION/compute_xrd.cpp b/src/DIFFRACTION/compute_xrd.cpp index 633c135e74..d798c2f4db 100644 --- a/src/DIFFRACTION/compute_xrd.cpp +++ b/src/DIFFRACTION/compute_xrd.cpp @@ -32,7 +32,6 @@ #include #include -#include // for strcasecmp() #include "omp_compat.h" using namespace LAMMPS_NS; @@ -87,7 +86,7 @@ ComputeXRD::ComputeXRD(LAMMPS *lmp, int narg, char **arg) : } for (int i = 0; i < ntypes; i++) { for (int j = 0; j < XRDmaxType; j++) { - if (strcasecmp(arg[iarg],XRDtypeList[j]) == 0) { + if (utils::lowercase(arg[iarg]) == utils::lowercase(XRDtypeList[j])) { ztype[i] = j; } } From 98d9b675f94f47d8f3256953980b8dc5dc4c89e3 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 20:44:27 -0500 Subject: [PATCH 53/84] Use portable logical operators --- src/DRUDE/fix_tgnh_drude.cpp | 2 +- src/ORIENT/fix_orient_eco.cpp | 2 +- src/PHONON/third_order.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DRUDE/fix_tgnh_drude.cpp b/src/DRUDE/fix_tgnh_drude.cpp index eb8922d4cc..700f9669d8 100644 --- a/src/DRUDE/fix_tgnh_drude.cpp +++ b/src/DRUDE/fix_tgnh_drude.cpp @@ -761,7 +761,7 @@ void FixTGNHDrude::setup_mol_mass_dof() { dof_mol, dof_int, dof_drude); } } - if (dof_mol <=0 or dof_int <=0 or dof_drude <=0) + if (dof_mol <=0 || dof_int <=0 || dof_drude <=0) error->all(FLERR, "TGNHC thermostat requires DOFs of molecules, atoms and dipoles larger than 0"); } diff --git a/src/ORIENT/fix_orient_eco.cpp b/src/ORIENT/fix_orient_eco.cpp index 6ec4e278ec..55486adc37 100644 --- a/src/ORIENT/fix_orient_eco.cpp +++ b/src/ORIENT/fix_orient_eco.cpp @@ -550,7 +550,7 @@ int FixOrientECO::get_norm() { squared_distance = delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]; // check if atom is within cutoff region - if ((squared_distance != 0.0) and (squared_distance < squared_cutoff)) { + if ((squared_distance != 0.0) && (squared_distance < squared_cutoff)) { ++neigh; squared_distance *= inv_squared_cutoff; diff --git a/src/PHONON/third_order.cpp b/src/PHONON/third_order.cpp index ca91a424af..04a2417f13 100644 --- a/src/PHONON/third_order.cpp +++ b/src/PHONON/third_order.cpp @@ -203,7 +203,7 @@ void ThirdOrder::options(int narg, char **arg) iarg += 2; } else error->all(FLERR,"Illegal third_order command"); } - if (file_flag == 1 and me == 0) { + if (file_flag == 1 && me == 0) { openfile(filename); } } From b8d6df6461df6d42a52ea064494a3f7970fb68a4 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 6 Oct 2021 20:44:42 -0500 Subject: [PATCH 54/84] add missing platform scope --- src/SPIN/neb_spin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SPIN/neb_spin.cpp b/src/SPIN/neb_spin.cpp index c2cefdcc97..80f5f56324 100644 --- a/src/SPIN/neb_spin.cpp +++ b/src/SPIN/neb_spin.cpp @@ -555,12 +555,12 @@ void NEBSpin::readfile(char *file, int flag) if (flag == 0) { if (me_universe == 0) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); } } else { if (me == 0 && ireplica) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); } } From 059f450f1b369c5acea8ed840a88fbca30ffea11 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 00:00:33 -0400 Subject: [PATCH 55/84] add uppercase string utility function (for symmetry) --- doc/src/Developer_utils.rst | 3 +++ src/utils.cpp | 13 ++++++++++++- src/utils.h | 7 +++++++ unittest/utils/test_utils.cpp | 4 +++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/doc/src/Developer_utils.rst b/doc/src/Developer_utils.rst index 72d7a80fa4..db47a9e3c3 100644 --- a/doc/src/Developer_utils.rst +++ b/doc/src/Developer_utils.rst @@ -106,6 +106,9 @@ and parsing files or arguments. .. doxygenfunction:: lowercase :project: progguide +.. doxygenfunction:: uppercase + :project: progguide + .. doxygenfunction:: trim :project: progguide diff --git a/src/utils.cpp b/src/utils.cpp index 14241316de..db909078a9 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -312,7 +312,7 @@ int utils::logical(const char *file, int line, const char *str, bool do_abort, L lmp->error->all(file, line, msg); } - // convert to ascii and lowercase + // convert to ascii std::string buf(str); if (has_utf8(buf)) buf = utf8_subst(buf); @@ -705,6 +705,17 @@ std::string utils::lowercase(const std::string &text) return converted; } +/* ---------------------------------------------------------------------- + Return string converted to uppercase +------------------------------------------------------------------------- */ + +std::string utils::uppercase(const std::string &text) +{ + std::string converted; + for (auto c : text) converted += ::toupper(c); + return converted; +} + /* ---------------------------------------------------------------------- Return string without leading or trailing whitespace ------------------------------------------------------------------------- */ diff --git a/src/utils.h b/src/utils.h index af8bec2aeb..1feee26f27 100644 --- a/src/utils.h +++ b/src/utils.h @@ -289,6 +289,13 @@ namespace utils { std::string lowercase(const std::string &line); + /*! Convert string to uppercase + * + * \param line string that should be converted + * \return new string with all uppercase characters */ + + std::string uppercase(const std::string &line); + /*! Trim leading and trailing whitespace. Like TRIM() in Fortran. * * \param line string that should be trimmed diff --git a/unittest/utils/test_utils.cpp b/unittest/utils/test_utils.cpp index 9e050f18e4..72a90a95a0 100644 --- a/unittest/utils/test_utils.cpp +++ b/unittest/utils/test_utils.cpp @@ -64,10 +64,12 @@ TEST(Utils, trim) ASSERT_THAT(trimmed, StrEq("")); } -TEST(Utils, lowercase) +TEST(Utils, casemod) { ASSERT_THAT(utils::lowercase("Gba35%*zAKgRvr"), StrEq("gba35%*zakgrvr")); ASSERT_THAT(utils::lowercase("A BC DEFG"), StrEq("a bc defg")); + ASSERT_THAT(utils::uppercase("Gba35%*zAKgRvr"), StrEq("GBA35%*ZAKGRVR")); + ASSERT_THAT(utils::uppercase("a bc defg"), StrEq("A BC DEFG")); } TEST(Utils, trim_comment) From c8ff66e07fe0af5ffa9d47141252f01a31b41768 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 06:48:49 -0400 Subject: [PATCH 56/84] correct file extension for Zstd compressed files --- src/platform.cpp | 2 +- unittest/utils/test_platform.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/platform.cpp b/src/platform.cpp index ddd9d8ba8e..2d56adcc11 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -84,7 +84,7 @@ static const std::vector zip_styles = { {"", "", "", "", zip_info::NONE}, {"gz", "gzip", " > ", " -cdf ", zip_info::GZIP}, {"bz2", "bzip2", " > ", " -cdf ", zip_info::BZIP2}, - {"zstd", "zstd", " -q > ", " -cdf ", zip_info::ZSTD}, + {"zst", "zstd", " -q > ", " -cdf ", zip_info::ZSTD}, {"xz", "xz", " > ", " -cdf ", zip_info::XZ}, {"lzma", "xz", " --format=lzma > ", " --format=lzma -cdf ", zip_info::LZMA}, {"lz4", "lz4", " > ", " -cdf ", zip_info::LZ4}, diff --git a/unittest/utils/test_platform.cpp b/unittest/utils/test_platform.cpp index c5d04d3b94..eddb6e1b20 100644 --- a/unittest/utils/test_platform.cpp +++ b/unittest/utils/test_platform.cpp @@ -362,7 +362,7 @@ TEST(Platform, has_zip_extension) ASSERT_FALSE(platform::has_zip_extension("dum.my")); ASSERT_TRUE(platform::has_zip_extension("dummy.gz")); ASSERT_TRUE(platform::has_zip_extension("dummy.bz2")); - ASSERT_TRUE(platform::has_zip_extension("dummy.zstd")); + ASSERT_TRUE(platform::has_zip_extension("dummy.zst")); ASSERT_TRUE(platform::has_zip_extension("dummy.xz")); ASSERT_TRUE(platform::has_zip_extension("dummy.lzma")); ASSERT_TRUE(platform::has_zip_extension("dummy.lz4")); @@ -370,9 +370,9 @@ TEST(Platform, has_zip_extension) TEST(Platform, zip_read_write) { - const std::vector test_files = {"zip_test.zip", "zip_test.gz", "zip_test.bz2", - "zip_test.zstd", "zip_test.xz", "zip_test.lzma", - "zip_test.lz4", "zip_test.unk", "zip test.gz"}; + const std::vector test_files = {"zip_test.zip", "zip_test.gz", "zip_test.bz2", + "zip_test.zst", "zip_test.xz", "zip_test.lzma", + "zip_test.lz4", "zip_test.unk", "zip test.gz"}; for (const auto &file : test_files) { platform::unlink(file); FILE *fp = platform::zip_write(file); From a818be585d71c6e85dd265a0d4890c03f6f69c9d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 12:22:16 -0400 Subject: [PATCH 57/84] use portable functions from platform and utils namespaces --- src/COLVARS/fix_colvars.cpp | 29 +++++++++++++---------------- src/DPD-MESO/pair_mdpd.cpp | 30 ++++++++++++++---------------- src/DPD-MESO/pair_tdpd.cpp | 32 +++++++++++++++----------------- src/EXTRA-FIX/fix_tmd.cpp | 2 +- src/REAXFF/reaxff_ffield.cpp | 10 ++++------ src/REPLICA/neb.cpp | 4 ++-- 6 files changed, 49 insertions(+), 58 deletions(-) diff --git a/src/COLVARS/fix_colvars.cpp b/src/COLVARS/fix_colvars.cpp index 32211f7689..6d6799b43e 100644 --- a/src/COLVARS/fix_colvars.cpp +++ b/src/COLVARS/fix_colvars.cpp @@ -303,7 +303,7 @@ FixColvars::FixColvars(LAMMPS *lmp, int narg, char **arg) : me = comm->me; root2root = MPI_COMM_NULL; - conf_file = strdup(arg[3]); + conf_file = utils::strdup(arg[3]); rng_seed = 1966; unwrap_flag = 1; @@ -319,22 +319,22 @@ FixColvars::FixColvars(LAMMPS *lmp, int narg, char **arg) : error->all(FLERR,"Missing argument to keyword"); if (0 == strcmp(arg[iarg], "input")) { - inp_name = strdup(arg[iarg+1]); + inp_name = utils::strdup(arg[iarg+1]); } else if (0 == strcmp(arg[iarg], "output")) { - out_name = strdup(arg[iarg+1]); + out_name = utils::strdup(arg[iarg+1]); } else if (0 == strcmp(arg[iarg], "seed")) { rng_seed = utils::inumeric(FLERR,arg[iarg+1],false,lmp); } else if (0 == strcmp(arg[iarg], "unwrap")) { unwrap_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); } else if (0 == strcmp(arg[iarg], "tstat")) { - tmp_name = strdup(arg[iarg+1]); + tmp_name = utils::strdup(arg[iarg+1]); } else { error->all(FLERR,"Unknown fix colvars parameter"); } ++iarg; ++iarg; } - if (!out_name) out_name = strdup("out"); + if (!out_name) out_name = utils::strdup("out"); /* initialize various state variables. */ tstat_id = -1; @@ -359,10 +359,10 @@ FixColvars::FixColvars(LAMMPS *lmp, int narg, char **arg) : FixColvars::~FixColvars() { - memory->sfree(conf_file); - memory->sfree(inp_name); - memory->sfree(out_name); - memory->sfree(tmp_name); + delete[] conf_file; + delete[] inp_name; + delete[] out_name; + delete[] tmp_name; memory->sfree(comm_buf); if (proxy) { @@ -430,17 +430,15 @@ void FixColvars::one_time_init() // create and initialize the colvars proxy if (me == 0) { - if (screen) fputs("colvars: Creating proxy instance\n",screen); - if (logfile) fputs("colvars: Creating proxy instance\n",logfile); + utils::logmesg(lmp,"colvars: Creating proxy instance\n"); #ifdef LAMMPS_BIGBIG - if (screen) fputs("colvars: cannot handle atom ids > 2147483647\n",screen); - if (logfile) fputs("colvars: cannot handle atom ids > 2147483647\n",logfile); + utils::logmesg(lmp,"colvars: cannot handle atom ids > 2147483647\n"); #endif if (inp_name) { if (strcmp(inp_name,"NULL") == 0) { - memory->sfree(inp_name); + delete[] inp_name; inp_name = nullptr; } } @@ -458,8 +456,7 @@ void FixColvars::one_time_init() } } - proxy = new colvarproxy_lammps(lmp,inp_name,out_name, - rng_seed,t_target,root2root); + proxy = new colvarproxy_lammps(lmp,inp_name,out_name,rng_seed,t_target,root2root); proxy->init(conf_file); num_coords = (proxy->modify_atom_positions()->size()); diff --git a/src/DPD-MESO/pair_mdpd.cpp b/src/DPD-MESO/pair_mdpd.cpp index 9e704de2a7..bdadb8fb23 100644 --- a/src/DPD-MESO/pair_mdpd.cpp +++ b/src/DPD-MESO/pair_mdpd.cpp @@ -19,19 +19,19 @@ #include "pair_mdpd.h" +#include "atom.h" +#include "citeme.h" +#include "comm.h" +#include "error.h" +#include "force.h" +#include "memory.h" +#include "neigh_list.h" +#include "neighbor.h" +#include "random_mars.h" +#include "update.h" + #include #include -#include "atom.h" -#include "comm.h" -#include "update.h" -#include "force.h" -#include "neighbor.h" -#include "neigh_list.h" -#include "random_mars.h" -#include "citeme.h" -#include "memory.h" -#include "error.h" - using namespace LAMMPS_NS; @@ -218,11 +218,9 @@ void PairMDPD::settings(int narg, char **arg) // initialize Marsaglia RNG with processor-unique seed - if (seed <= 0) { - struct timespec time; - clock_gettime( CLOCK_REALTIME, &time ); - seed = time.tv_nsec; // if seed is non-positive, get the current time as the seed - } + if (seed <= 0) + seed = (int) (platform::walltime() * 1073741824.0); + delete random; random = new RanMars(lmp,(seed + comm->me) % 900000000); diff --git a/src/DPD-MESO/pair_tdpd.cpp b/src/DPD-MESO/pair_tdpd.cpp index e99edfa5ff..1f48e12f55 100644 --- a/src/DPD-MESO/pair_tdpd.cpp +++ b/src/DPD-MESO/pair_tdpd.cpp @@ -18,19 +18,19 @@ ------------------------------------------------------------------------- */ #include "pair_tdpd.h" -#include -#include -#include "atom.h" -#include "comm.h" -#include "update.h" -#include "force.h" -#include "neighbor.h" -#include "neigh_list.h" -#include "random_mars.h" -#include "citeme.h" -#include "memory.h" -#include "error.h" +#include "atom.h" +#include "citeme.h" +#include "comm.h" +#include "error.h" +#include "force.h" +#include "memory.h" +#include "neigh_list.h" +#include "neighbor.h" +#include "random_mars.h" +#include "update.h" + +#include using namespace LAMMPS_NS; @@ -240,11 +240,9 @@ void PairTDPD::settings(int narg, char **arg) // initialize Marsaglia RNG with processor-unique seed - if (seed <= 0) { - struct timespec time; - clock_gettime( CLOCK_REALTIME, &time ); - seed = time.tv_nsec; // if seed is non-positive, get the current time as the seed - } + if (seed <= 0) + seed = (int) (platform::walltime() * 1073741824.0); + delete random; random = new RanMars(lmp,(seed + comm->me) % 900000000); diff --git a/src/EXTRA-FIX/fix_tmd.cpp b/src/EXTRA-FIX/fix_tmd.cpp index 93d7ae6a56..123814b22a 100644 --- a/src/EXTRA-FIX/fix_tmd.cpp +++ b/src/EXTRA-FIX/fix_tmd.cpp @@ -495,7 +495,7 @@ void FixTMD::readfile(char *file) delete [] buffer; if (me == 0) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); } diff --git a/src/REAXFF/reaxff_ffield.cpp b/src/REAXFF/reaxff_ffield.cpp index 6297f4cf94..a07d37e0f4 100644 --- a/src/REAXFF/reaxff_ffield.cpp +++ b/src/REAXFF/reaxff_ffield.cpp @@ -32,7 +32,6 @@ #include "text_file_reader.h" #include "utils.h" -#include #include #include #include @@ -161,11 +160,10 @@ namespace ReaxFF { if (values.count() < 9) THROW_ERROR("Invalid force field file format"); - auto element = values.next_string(); - int len = MIN(element.size(),3); // truncate stored element symbol if necessary - for (j = 0; j < len; ++j) - sbp[i].name[j] = toupper(element[j]); - sbp[i].name[len] = '\0'; + // copy element symbol in uppercase and truncate stored element symbol if necessary + auto element = utils::uppercase(values.next_string()); + strncpy(sbp[i].name,element.c_str(),4); + sbp[i].name[4] = '\0'; sbp[i].r_s = values.next_double(); sbp[i].valency = values.next_double(); diff --git a/src/REPLICA/neb.cpp b/src/REPLICA/neb.cpp index 281d0e830f..318ee0a3c7 100644 --- a/src/REPLICA/neb.cpp +++ b/src/REPLICA/neb.cpp @@ -528,12 +528,12 @@ void NEB::readfile(char *file, int flag) if (flag == 0) { if (me_universe == 0) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); } } else { if (me == 0 && ireplica) { - if (compressed) pclose(fp); + if (compressed) platform::pclose(fp); else fclose(fp); } } From 3661b8cd5030897d738ce0a7062ddb55983ce0f1 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 12:22:26 -0400 Subject: [PATCH 58/84] optimize --- src/utils.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index db909078a9..035b68d660 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -700,8 +700,8 @@ char *utils::strdup(const std::string &text) std::string utils::lowercase(const std::string &text) { - std::string converted; - for (auto c : text) converted += ::tolower(c); + std::string converted(text); + for (auto &c : converted) c = ::tolower(c); return converted; } @@ -711,8 +711,8 @@ std::string utils::lowercase(const std::string &text) std::string utils::uppercase(const std::string &text) { - std::string converted; - for (auto c : text) converted += ::toupper(c); + std::string converted(text); + for (auto &c : converted) c = ::toupper(c); return converted; } From 4f17082d74de96364f61192909a6151ae9c52f91 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 12:23:17 -0400 Subject: [PATCH 59/84] use portable logic operators --- src/EXTRA-PAIR/pair_e3b.cpp | 2 +- src/KOKKOS/fix_rx_kokkos.cpp | 2 +- src/MDI/fix_mdi_engine.cpp | 2 +- src/ML-IAP/mliap_model_python.cpp | 2 +- src/NETCDF/dump_netcdf.cpp | 2 +- src/NETCDF/dump_netcdf_mpiio.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/EXTRA-PAIR/pair_e3b.cpp b/src/EXTRA-PAIR/pair_e3b.cpp index a904939e42..7e865ac6f8 100644 --- a/src/EXTRA-PAIR/pair_e3b.cpp +++ b/src/EXTRA-PAIR/pair_e3b.cpp @@ -643,7 +643,7 @@ void PairE3B::checkInputs(const double &bondL) if (k2 == NOT_SET) error->all(FLERR, "K2 keyword missing"); //now test that values are within acceptable ranges - if (k2 < 0.0 or k3 < 0.0) error->all(FLERR, "exponential decay is negative"); + if (k2 < 0.0 || k3 < 0.0) error->all(FLERR, "exponential decay is negative"); if (bondL < 0.0) error->all(FLERR, "OH bond length is negative"); if (rc2 < 0.0 || rc3 < 0.0 || rs < 0.0) error->all(FLERR, "potential cutoff is negative"); if (rs > rc3) error->all(FLERR, "potential switching distance is larger than cutoff"); diff --git a/src/KOKKOS/fix_rx_kokkos.cpp b/src/KOKKOS/fix_rx_kokkos.cpp index f05fe88fd8..caa79c77b1 100644 --- a/src/KOKKOS/fix_rx_kokkos.cpp +++ b/src/KOKKOS/fix_rx_kokkos.cpp @@ -2075,7 +2075,7 @@ void FixRxKokkos::computeLocalTemperature() // Local list views. (This isn't working!) NeighListKokkos* k_list = static_cast*>(list); - if (not(list->kokkos)) + if (!list->kokkos) error->one(FLERR,"list is not a Kokkos list\n"); //typename ArrayTypes::t_neighbors_2d d_neighbors = k_list->d_neighbors; diff --git a/src/MDI/fix_mdi_engine.cpp b/src/MDI/fix_mdi_engine.cpp index 8024623e43..b08209080a 100644 --- a/src/MDI/fix_mdi_engine.cpp +++ b/src/MDI/fix_mdi_engine.cpp @@ -388,7 +388,7 @@ char *FixMDIEngine::engine_mode(const char *node) // respond to commands from the driver - while (not exit_flag and not local_exit_flag) { + while (!exit_flag && !local_exit_flag) { // read the next command from the driver // all procs call this, but only proc 0 receives the command diff --git a/src/ML-IAP/mliap_model_python.cpp b/src/ML-IAP/mliap_model_python.cpp index 3d91107449..b89d17f289 100644 --- a/src/ML-IAP/mliap_model_python.cpp +++ b/src/ML-IAP/mliap_model_python.cpp @@ -132,7 +132,7 @@ void MLIAPModelPython::connect_param_counts() void MLIAPModelPython::compute_gradients(MLIAPData *data) { - if (not model_loaded) { error->all(FLERR, "Model not loaded."); } + if (!model_loaded) { error->all(FLERR, "Model not loaded."); } PyGILState_STATE gstate = PyGILState_Ensure(); MLIAPPY_compute_gradients(this, data); diff --git a/src/NETCDF/dump_netcdf.cpp b/src/NETCDF/dump_netcdf.cpp index b0bf57a41c..5f30c941ca 100644 --- a/src/NETCDF/dump_netcdf.cpp +++ b/src/NETCDF/dump_netcdf.cpp @@ -274,7 +274,7 @@ void DumpNetCDF::openfile() if (append_flag && !multifile) { // Fixme! Perform checks if dimensions and variables conform with // data structure standard. - if (not platform::file_is_readable(filecurrent)) + if (!platform::file_is_readable(filecurrent)) error->all(FLERR, "cannot append to non-existent file {}",filecurrent); if (singlefile_opened) return; diff --git a/src/NETCDF/dump_netcdf_mpiio.cpp b/src/NETCDF/dump_netcdf_mpiio.cpp index b14cef4f68..0a76203f96 100644 --- a/src/NETCDF/dump_netcdf_mpiio.cpp +++ b/src/NETCDF/dump_netcdf_mpiio.cpp @@ -272,7 +272,7 @@ void DumpNetCDFMPIIO::openfile() if (append_flag && !multifile) { // Fixme! Perform checks if dimensions and variables conform with // data structure standard. - if (not platform::file_is_readable(filecurrent)) + if (!platform::file_is_readable(filecurrent)) error->all(FLERR, "cannot append to non-existent file {}", filecurrent); MPI_Offset index[NC_MAX_VAR_DIMS], count[NC_MAX_VAR_DIMS]; From 6a9bb577cf480e64c67bfd267ce5b82fe971db3f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 12:38:11 -0400 Subject: [PATCH 60/84] rename "zip" functions to "compress" functions. update related docs --- doc/src/Build_settings.rst | 20 ++++---- doc/src/Developer_platform.rst | 6 +-- doc/utils/sphinx-config/false_positives.txt | 1 + src/COMPRESS/dump_atom_gz.cpp | 2 +- src/COMPRESS/dump_cfg_gz.cpp | 2 +- src/COMPRESS/dump_custom_gz.cpp | 2 +- src/COMPRESS/dump_custom_zstd.cpp | 2 +- src/COMPRESS/dump_local_gz.cpp | 2 +- src/COMPRESS/dump_local_zstd.cpp | 2 +- src/COMPRESS/dump_xyz_gz.cpp | 2 +- src/COMPRESS/dump_xyz_zstd.cpp | 2 +- src/EXTRA-FIX/fix_tmd.cpp | 6 +-- src/PHONON/dynamical_matrix.cpp | 6 +-- src/PHONON/third_order.cpp | 6 +-- src/REAXFF/fix_reaxff_bonds.cpp | 4 +- src/REAXFF/fix_reaxff_species.cpp | 4 +- src/REPLICA/neb.cpp | 4 +- src/SPIN/neb_spin.cpp | 6 +-- src/dump.cpp | 6 +-- src/library.cpp | 7 +-- src/platform.cpp | 52 ++++++++++----------- src/platform.h | 8 ++-- src/read_data.cpp | 6 +-- src/reader.cpp | 4 +- 24 files changed, 83 insertions(+), 79 deletions(-) diff --git a/doc/src/Build_settings.rst b/doc/src/Build_settings.rst index c7397935d8..01bd8e2c80 100644 --- a/doc/src/Build_settings.rst +++ b/doc/src/Build_settings.rst @@ -354,8 +354,10 @@ Read or write compressed files ----------------------------------------- If this option is enabled, large files can be read or written with -gzip compression by several LAMMPS commands, including -:doc:`read_data `, :doc:`rerun `, and :doc:`dump `. +compression by ``gzip`` or similar tools by several LAMMPS commands, +including :doc:`read_data `, :doc:`rerun `, and +:doc:`dump `. Currently supported compression tools are: +``gzip``, ``bzip2``, ``zstd``, and ``lzma``. .. tabs:: @@ -364,8 +366,7 @@ gzip compression by several LAMMPS commands, including .. code-block:: bash -D WITH_GZIP=value # yes or no - # default is yes if CMake can find gzip, else no - -D GZIP_EXECUTABLE=path # path to gzip executable if CMake cannot find it + # default is yes if CMake can find the gzip program, else no .. tab:: Traditional make @@ -373,14 +374,15 @@ gzip compression by several LAMMPS commands, including LMP_INC = -DLAMMPS_GZIP -This option requires that your operating system fully supports the "popen()" -function in the standard runtime library and that a ``gzip`` executable can be -found by LAMMPS during a run. +This option requires that your operating system fully supports the +"popen()" function in the standard runtime library and that a ``gzip`` +or other executable can be found by LAMMPS in the standard search path +during a run. .. note:: - On some clusters with high-speed networks, using the "fork()" library - call (required by "popen()") can interfere with the fast communication + On clusters with high-speed networks, using the "fork()" library call + (required by "popen()") can interfere with the fast communication library and lead to simulations using compressed output or input to hang or crash. For selected operations, compressed file I/O is also available using a compression library instead, which is what the diff --git a/doc/src/Developer_platform.rst b/doc/src/Developer_platform.rst index 19836b1ff2..4cea36f94c 100644 --- a/doc/src/Developer_platform.rst +++ b/doc/src/Developer_platform.rst @@ -139,11 +139,11 @@ Dynamically loaded object or library functions Compressed file I/O functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. doxygenfunction:: has_zip_extension +.. doxygenfunction:: has_compress_extension :project: progguide -.. doxygenfunction:: zip_read +.. doxygenfunction:: compressed_read :project: progguide -.. doxygenfunction:: zip_write +.. doxygenfunction:: compressed_write :project: progguide diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 107e252074..ccc321c7e0 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -1223,6 +1223,7 @@ Guo gw gyromagnetic gz +gzip gzipped Haak Hafskjold diff --git a/src/COMPRESS/dump_atom_gz.cpp b/src/COMPRESS/dump_atom_gz.cpp index 38229a71bb..5f799054bb 100644 --- a/src/COMPRESS/dump_atom_gz.cpp +++ b/src/COMPRESS/dump_atom_gz.cpp @@ -33,7 +33,7 @@ DumpAtomGZ::~DumpAtomGZ() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_cfg_gz.cpp b/src/COMPRESS/dump_cfg_gz.cpp index ea51ce87c3..8d6347d978 100644 --- a/src/COMPRESS/dump_cfg_gz.cpp +++ b/src/COMPRESS/dump_cfg_gz.cpp @@ -35,7 +35,7 @@ DumpCFGGZ::~DumpCFGGZ() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_custom_gz.cpp b/src/COMPRESS/dump_custom_gz.cpp index 7cbab10cb4..f40cf8d3d1 100644 --- a/src/COMPRESS/dump_custom_gz.cpp +++ b/src/COMPRESS/dump_custom_gz.cpp @@ -33,7 +33,7 @@ DumpCustomGZ::~DumpCustomGZ() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_custom_zstd.cpp b/src/COMPRESS/dump_custom_zstd.cpp index 8b7d153fc4..347c9c08e2 100644 --- a/src/COMPRESS/dump_custom_zstd.cpp +++ b/src/COMPRESS/dump_custom_zstd.cpp @@ -45,7 +45,7 @@ DumpCustomZstd::~DumpCustomZstd() /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_local_gz.cpp b/src/COMPRESS/dump_local_gz.cpp index 206e2aeb09..a23fa1a1ac 100644 --- a/src/COMPRESS/dump_local_gz.cpp +++ b/src/COMPRESS/dump_local_gz.cpp @@ -33,7 +33,7 @@ DumpLocalGZ::~DumpLocalGZ() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_local_zstd.cpp b/src/COMPRESS/dump_local_zstd.cpp index 91fb36bb6e..1d3fc4756e 100644 --- a/src/COMPRESS/dump_local_zstd.cpp +++ b/src/COMPRESS/dump_local_zstd.cpp @@ -39,7 +39,7 @@ DumpLocalZstd::~DumpLocalZstd() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_xyz_gz.cpp b/src/COMPRESS/dump_xyz_gz.cpp index a1acad7fc2..2d9548bf14 100644 --- a/src/COMPRESS/dump_xyz_gz.cpp +++ b/src/COMPRESS/dump_xyz_gz.cpp @@ -32,7 +32,7 @@ DumpXYZGZ::~DumpXYZGZ() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_xyz_zstd.cpp b/src/COMPRESS/dump_xyz_zstd.cpp index 534bc0ee56..b56488ec09 100644 --- a/src/COMPRESS/dump_xyz_zstd.cpp +++ b/src/COMPRESS/dump_xyz_zstd.cpp @@ -38,7 +38,7 @@ DumpXYZZstd::~DumpXYZZstd() {} /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ diff --git a/src/EXTRA-FIX/fix_tmd.cpp b/src/EXTRA-FIX/fix_tmd.cpp index 123814b22a..4d85687e4d 100644 --- a/src/EXTRA-FIX/fix_tmd.cpp +++ b/src/EXTRA-FIX/fix_tmd.cpp @@ -517,14 +517,14 @@ void FixTMD::readfile(char *file) /* ---------------------------------------------------------------------- proc 0 opens TMD data file - test if gzipped + test if compressed ------------------------------------------------------------------------- */ void FixTMD::open(const std::string &file) { - if (platform::has_zip_extension(file)) { + if (platform::has_compress_extension(file)) { compressed = 1; - fp = platform::zip_read(file); + fp = platform::compressed_read(file); if (!fp) error->one(FLERR,"Cannot open compressed file for reading"); } else { compressed = 0; diff --git a/src/PHONON/dynamical_matrix.cpp b/src/PHONON/dynamical_matrix.cpp index 8861a87491..e236e24a15 100644 --- a/src/PHONON/dynamical_matrix.cpp +++ b/src/PHONON/dynamical_matrix.cpp @@ -211,7 +211,7 @@ void DynamicalMatrix::options(int narg, char **arg) /* ---------------------------------------------------------------------- generic opening of a file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ @@ -223,8 +223,8 @@ void DynamicalMatrix::openfile(const char *filename) if (me == 0) { if (compressed) { - fp = platform::zip_write(std::string(filename)+".gz"); - if (!fp) error->one(FLERR,"Cannot open gzipped file"); + fp = platform::compressed_write(std::string(filename)+".gz"); + if (!fp) error->one(FLERR,"Cannot open compressed file"); } else if (binaryflag) { fp = fopen(filename,"wb"); } else { diff --git a/src/PHONON/third_order.cpp b/src/PHONON/third_order.cpp index 04a2417f13..3206882a4a 100644 --- a/src/PHONON/third_order.cpp +++ b/src/PHONON/third_order.cpp @@ -210,7 +210,7 @@ void ThirdOrder::options(int narg, char **arg) /* ---------------------------------------------------------------------- generic opening of a file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ @@ -222,8 +222,8 @@ void ThirdOrder::openfile(const char* filename) if (me == 0) { if (compressed) { - fp = platform::zip_write(std::string(filename)+".gz"); - if (!fp) error->one(FLERR,"Cannot open gzipped file"); + fp = platform::compressed_write(std::string(filename)+".gz"); + if (!fp) error->one(FLERR,"Cannot open compressed file"); } else if (binaryflag) { fp = fopen(filename,"wb"); } else { diff --git a/src/REAXFF/fix_reaxff_bonds.cpp b/src/REAXFF/fix_reaxff_bonds.cpp index 07d0c73f3d..740a32a0a6 100644 --- a/src/REAXFF/fix_reaxff_bonds.cpp +++ b/src/REAXFF/fix_reaxff_bonds.cpp @@ -52,9 +52,9 @@ FixReaxFFBonds::FixReaxFFBonds(LAMMPS *lmp, int narg, char **arg) : if (nevery <= 0) error->all(FLERR,"Illegal fix reaxff/bonds command"); if (me == 0) { - if (platform::has_zip_extension(arg[4])) { + if (platform::has_compress_extension(arg[4])) { compressed = 1; - fp = platform::zip_write(arg[4]); + fp = platform::compressed_write(arg[4]); if (!fp) error->one(FLERR,"Cannot open compressed file"); } else fp = fopen(arg[4],"w"); diff --git a/src/REAXFF/fix_reaxff_species.cpp b/src/REAXFF/fix_reaxff_species.cpp index 897f36d988..7bf6f34aa7 100644 --- a/src/REAXFF/fix_reaxff_species.cpp +++ b/src/REAXFF/fix_reaxff_species.cpp @@ -107,8 +107,8 @@ FixReaxFFSpecies::FixReaxFFSpecies(LAMMPS *lmp, int narg, char **arg) : strcpy(tmparg[2],arg[5]); if (me == 0) { - if (platform::has_zip_extension(arg[6])) { - fp = platform::zip_write(arg[6]); + if (platform::has_compress_extension(arg[6])) { + fp = platform::compressed_write(arg[6]); compressed = 1; if (!fp) error->one(FLERR,"Cannot open compressed file"); } else fp = fopen(arg[6],"w"); diff --git a/src/REPLICA/neb.cpp b/src/REPLICA/neb.cpp index 318ee0a3c7..8cfc4b5c24 100644 --- a/src/REPLICA/neb.cpp +++ b/src/REPLICA/neb.cpp @@ -548,9 +548,9 @@ void NEB::readfile(char *file, int flag) void NEB::open(char *file) { compressed = 0; - if (platform::has_zip_extension(file)) { + if (platform::has_compress_extension(file)) { compressed = 1; - fp = platform::zip_read(file); + fp = platform::compressed_read(file); if (!fp) error->one(FLERR,"Cannot open compressed file"); } else fp = fopen(file,"r"); diff --git a/src/SPIN/neb_spin.cpp b/src/SPIN/neb_spin.cpp index 80f5f56324..1c987f8e7e 100644 --- a/src/SPIN/neb_spin.cpp +++ b/src/SPIN/neb_spin.cpp @@ -687,14 +687,14 @@ int NEBSpin::initial_rotation(double *spi, double *sploc, double fraction) /* ---------------------------------------------------------------------- universe proc 0 opens NEBSpin data file - test if gzipped + test if compressed ------------------------------------------------------------------------- */ void NEBSpin::open(char *file) { compressed = 0; - if (platform::has_zip_extension(file)) { - fp = platform::zip_read(file); + if (platform::has_compress_extension(file)) { + fp = platform::compressed_read(file); if (!fp) error->one(FLERR,"Cannot open compressed file"); } else fp = fopen(file,"r"); diff --git a/src/dump.cpp b/src/dump.cpp index 7dbe95c1d3..d00c42086d 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -143,7 +143,7 @@ Dump::Dump(LAMMPS *lmp, int /*narg*/, char **arg) : Pointers(lmp) if (strchr(filename,'*')) multifile = 1; if (utils::strmatch(filename, "\\.bin$")) binary = 1; - if (platform::has_zip_extension(filename)) compressed = 1; + if (platform::has_compress_extension(filename)) compressed = 1; } /* ---------------------------------------------------------------------- */ @@ -528,7 +528,7 @@ void Dump::write() /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or gzipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ @@ -578,7 +578,7 @@ void Dump::openfile() if (filewriter) { if (compressed) { - fp = platform::zip_write(filecurrent); + fp = platform::compressed_write(filecurrent); } else if (binary) { fp = fopen(filecurrent,"wb"); } else if (append_flag) { diff --git a/src/library.cpp b/src/library.cpp index bf5ea50f58..ed208413e6 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -4420,15 +4420,16 @@ int lammps_config_has_mpi_support() /* ---------------------------------------------------------------------- */ -/** Check if the LAMMPS library supports compressed files via a pipe to gzip +/** Check if the LAMMPS library supports reading or writing compressed + * files via a pipe to gzip or similar compression programs \verbatim embed:rst Several LAMMPS commands (e.g. :doc:`read_data`, :doc:`write_data`, :doc:`dump styles atom, custom, and xyz `) support reading and writing compressed files via creating a pipe to the ``gzip`` program. This function checks whether this feature was :ref:`enabled at compile -time `. It does **not** check whether the ``gzip`` itself is -installed and usable. +time `. It does **not** check whether``gzip`` or any other +supported compression programs themselves are installed and usable. \endverbatim * * \return 1 if yes, otherwise 0 diff --git a/src/platform.cpp b/src/platform.cpp index 2d56adcc11..00636ec703 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -69,40 +69,40 @@ /* ------------------------------------------------------------------ */ /// Struct for listing on-the-fly compression/decompression commands -struct zip_info { +struct compress_info { /// identifier for the different compression algorithms enum styles { NONE, GZIP, BZIP2, ZSTD, XZ, LZMA, LZ4 }; const std::string extension; ///< filename extension for the current algorithm const std::string command; ///< command to perform compression or decompression - const std::string zipflags; ///< flags to append to compress from stdin to stdout - const std::string unzipflags; ///< flags to decompress file to stdout + const std::string compressflags; ///< flags to append to compress from stdin to stdout + const std::string uncompressflags; ///< flags to decompress file to stdout const int style; ///< compression style flag }; // clang-format off -static const std::vector zip_styles = { - {"", "", "", "", zip_info::NONE}, - {"gz", "gzip", " > ", " -cdf ", zip_info::GZIP}, - {"bz2", "bzip2", " > ", " -cdf ", zip_info::BZIP2}, - {"zst", "zstd", " -q > ", " -cdf ", zip_info::ZSTD}, - {"xz", "xz", " > ", " -cdf ", zip_info::XZ}, - {"lzma", "xz", " --format=lzma > ", " --format=lzma -cdf ", zip_info::LZMA}, - {"lz4", "lz4", " > ", " -cdf ", zip_info::LZ4}, +static const std::vector compress_styles = { + {"", "", "", "", compress_info::NONE}, + {"gz", "gzip", " > ", " -cdf ", compress_info::GZIP}, + {"bz2", "bzip2", " > ", " -cdf ", compress_info::BZIP2}, + {"zst", "zstd", " -q > ", " -cdf ", compress_info::ZSTD}, + {"xz", "xz", " > ", " -cdf ", compress_info::XZ}, + {"lzma", "xz", " --format=lzma > ", " --format=lzma -cdf ", compress_info::LZMA}, + {"lz4", "lz4", " > ", " -cdf ", compress_info::LZ4}, }; // clang-format on /* ------------------------------------------------------------------ */ -static const zip_info &find_zip_type(const std::string &file) +static const compress_info &find_compress_type(const std::string &file) { std::size_t dot = file.find_last_of('.'); if (dot != std::string::npos) { const std::string ext = file.substr(dot + 1); - for (const auto &i : zip_styles) { + for (const auto &i : compress_styles) { if (i.extension == ext) return i; } } - return zip_styles[0]; + return compress_styles[0]; } /* ------------------------------------------------------------------ */ @@ -925,26 +925,26 @@ bool platform::file_is_readable(const std::string &path) check if filename has a known compression extension ------------------------------------------------------------------------- */ -bool platform::has_zip_extension(const std::string &file) +bool platform::has_compress_extension(const std::string &file) { - return find_zip_type(file).style != zip_info::NONE; + return find_compress_type(file).style != compress_info::NONE; } /* ---------------------------------------------------------------------- open pipe to read a compressed file ------------------------------------------------------------------------- */ -FILE *platform::zip_read(const std::string &file) +FILE *platform::compressed_read(const std::string &file) { FILE *fp = nullptr; #if defined(LAMMPS_GZIP) - auto zip = find_zip_type(file); - if (zip.style == zip_info::NONE) return nullptr; + auto compress = find_compress_type(file); + if (compress.style == compress_info::NONE) return nullptr; - if (find_exe_path(zip.command).size()) + if (find_exe_path(compress.command).size()) // put quotes around file name so that they may contain blanks - fp = popen((zip.command + zip.unzipflags + "\"" + file + "\""), "r"); + fp = popen((compress.command + compress.uncompressflags + "\"" + file + "\""), "r"); #endif return fp; } @@ -953,17 +953,17 @@ FILE *platform::zip_read(const std::string &file) open pipe to write a compressed file ------------------------------------------------------------------------- */ -FILE *platform::zip_write(const std::string &file) +FILE *platform::compressed_write(const std::string &file) { FILE *fp = nullptr; #if defined(LAMMPS_GZIP) - auto zip = find_zip_type(file); - if (zip.style == zip_info::NONE) return nullptr; + auto compress = find_compress_type(file); + if (compress.style == compress_info::NONE) return nullptr; - if (find_exe_path(zip.command).size()) + if (find_exe_path(compress.command).size()) // put quotes around file name so that they may contain blanks - fp = popen((zip.command + zip.zipflags + "\"" + file + "\""), "w"); + fp = popen((compress.command + compress.compressflags + "\"" + file + "\""), "w"); #endif return fp; } diff --git a/src/platform.h b/src/platform.h index 794fd692b0..de8ecce016 100644 --- a/src/platform.h +++ b/src/platform.h @@ -357,26 +357,26 @@ namespace platform { /*! Check if a file name ends in a known extension for a compressed file format * - * Currently supported file extensions are: .gz, .bz2, .zstd, .xz, .lzma, lz4 + * Currently supported file extensions are: .gz, .bz2, .zst, .xz, .lzma, lz4 * * \param file name of the file to check * \return true if the file has a known extension, otherwise false */ - bool has_zip_extension(const std::string &file); + bool has_compress_extension(const std::string &file); /*! Open pipe to compressed text file for reading * * \param file name of the file to open * \return FILE pointer to pipe using for reading the compressed file. */ - FILE *zip_read(const std::string &file); + FILE *compressed_read(const std::string &file); /*! Open pipe to compressed text file for writing * * \param file name of the file to open * \return FILE pointer to pipe using for reading the compressed file. */ - FILE *zip_write(const std::string &file); + FILE *compressed_write(const std::string &file); } // namespace platform } // namespace LAMMPS_NS diff --git a/src/read_data.cpp b/src/read_data.cpp index bbc3e20d44..c17ab97229 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -1951,14 +1951,14 @@ int ReadData::reallocate(int **pcount, int cmax, int amax) /* ---------------------------------------------------------------------- proc 0 opens data file - test if gzipped + test if compressed ------------------------------------------------------------------------- */ void ReadData::open(const std::string &file) { - if (platform::has_zip_extension(file)) { + if (platform::has_compress_extension(file)) { compressed = 1; - fp = platform::zip_read(file); + fp = platform::compressed_read(file); if (!fp) error->one(FLERR,"Cannot open compressed file {}", file); } else { compressed = 0; diff --git a/src/reader.cpp b/src/reader.cpp index 3a07417912..f2652d868d 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -36,9 +36,9 @@ void Reader::open_file(const std::string &file) { if (fp != nullptr) close_file(); - if (platform::has_zip_extension(file)) { + if (platform::has_compress_extension(file)) { compressed = 1; - fp = platform::zip_read(file); + fp = platform::compressed_read(file); if (!fp) error->one(FLERR,"Cannot open compressed file for reading"); } else { compressed = 0; From 0f442fddd98007a0655330bca2ae40ce6760b0eb Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 12:39:58 -0400 Subject: [PATCH 61/84] correct use of utils function --- src/REAXFF/reaxff_ffield.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/REAXFF/reaxff_ffield.cpp b/src/REAXFF/reaxff_ffield.cpp index a07d37e0f4..f3f9bf6a00 100644 --- a/src/REAXFF/reaxff_ffield.cpp +++ b/src/REAXFF/reaxff_ffield.cpp @@ -39,6 +39,7 @@ using LAMMPS_NS::utils::open_potential; using LAMMPS_NS::utils::getsyserror; +using LAMMPS_NS::utils::uppercase; namespace ReaxFF { @@ -161,9 +162,9 @@ namespace ReaxFF { THROW_ERROR("Invalid force field file format"); // copy element symbol in uppercase and truncate stored element symbol if necessary - auto element = utils::uppercase(values.next_string()); + auto element = uppercase(values.next_string()); strncpy(sbp[i].name,element.c_str(),4); - sbp[i].name[4] = '\0'; + sbp[i].name[3] = '\0'; sbp[i].r_s = values.next_double(); sbp[i].valency = values.next_double(); From 2c7b67203ab38ae172d7516d069798497a5c6716 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 13:44:18 -0400 Subject: [PATCH 62/84] recover unit test compile --- unittest/utils/test_platform.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/unittest/utils/test_platform.cpp b/unittest/utils/test_platform.cpp index eddb6e1b20..0f39534c31 100644 --- a/unittest/utils/test_platform.cpp +++ b/unittest/utils/test_platform.cpp @@ -356,26 +356,26 @@ TEST(Platform, file_is_readable) #endif } -TEST(Platform, has_zip_extension) +TEST(Platform, has_compress_extension) { - ASSERT_FALSE(platform::has_zip_extension("dummy")); - ASSERT_FALSE(platform::has_zip_extension("dum.my")); - ASSERT_TRUE(platform::has_zip_extension("dummy.gz")); - ASSERT_TRUE(platform::has_zip_extension("dummy.bz2")); - ASSERT_TRUE(platform::has_zip_extension("dummy.zst")); - ASSERT_TRUE(platform::has_zip_extension("dummy.xz")); - ASSERT_TRUE(platform::has_zip_extension("dummy.lzma")); - ASSERT_TRUE(platform::has_zip_extension("dummy.lz4")); + ASSERT_FALSE(platform::has_compress_extension("dummy")); + ASSERT_FALSE(platform::has_compress_extension("dum.my")); + ASSERT_TRUE(platform::has_compress_extension("dummy.gz")); + ASSERT_TRUE(platform::has_compress_extension("dummy.bz2")); + ASSERT_TRUE(platform::has_compress_extension("dummy.zst")); + ASSERT_TRUE(platform::has_compress_extension("dummy.xz")); + ASSERT_TRUE(platform::has_compress_extension("dummy.lzma")); + ASSERT_TRUE(platform::has_compress_extension("dummy.lz4")); } -TEST(Platform, zip_read_write) +TEST(Platform, compress_read_write) { const std::vector test_files = {"zip_test.zip", "zip_test.gz", "zip_test.bz2", "zip_test.zst", "zip_test.xz", "zip_test.lzma", "zip_test.lz4", "zip_test.unk", "zip test.gz"}; for (const auto &file : test_files) { platform::unlink(file); - FILE *fp = platform::zip_write(file); + FILE *fp = platform::compressed_write(file); if (!fp) { platform::unlink(file); continue; @@ -388,7 +388,7 @@ TEST(Platform, zip_read_write) fflush(fp); platform::pclose(fp); - fp = platform::zip_read(file); + fp = platform::compressed_read(file); ASSERT_NE(fp, nullptr); char buf[128]; char *ptr = fgets(buf, 128, fp); From 2b27af1572c55713f71ff15e5891cbcba6dfdc40 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 14:37:37 -0400 Subject: [PATCH 63/84] fix a few more MSVC issues and reduce warnings --- .gitignore | 7 ++++++- src/EXTRA-DUMP/xdr_compat.h | 4 ++-- src/ML-SNAP/pair_snap.cpp | 13 +++++-------- src/MOLFILE/molfile_interface.cpp | 4 +--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index ae708ff184..3fb3af0d13 100644 --- a/.gitignore +++ b/.gitignore @@ -37,8 +37,8 @@ vgcore.* .Trashes ehthumbs.db Thumbs.db -.clang-format .lammps_history +.vs #cmake /build* @@ -49,3 +49,8 @@ Thumbs.db /Testing /cmake_install.cmake /lmp +out/Debug +out/RelWithDebInfo +out/Release +out/x86 +out/x64 diff --git a/src/EXTRA-DUMP/xdr_compat.h b/src/EXTRA-DUMP/xdr_compat.h index 30aecbcb62..6557a60a53 100644 --- a/src/EXTRA-DUMP/xdr_compat.h +++ b/src/EXTRA-DUMP/xdr_compat.h @@ -59,8 +59,8 @@ extern "C" { typedef int bool_t; -#if defined(__MINGW32__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__DragonFly__) || defined(__OpenBSD__) || defined(__NetBSD__) +#if defined(_WIN32) || defined(__APPLE__) || defined(__FreeBSD__) || \ + defined(__DragonFly__) || defined(__OpenBSD__) || defined(__NetBSD__) typedef char *caddr_t; typedef unsigned int u_int; #endif diff --git a/src/ML-SNAP/pair_snap.cpp b/src/ML-SNAP/pair_snap.cpp index d7cd953615..d6da639734 100644 --- a/src/ML-SNAP/pair_snap.cpp +++ b/src/ML-SNAP/pair_snap.cpp @@ -500,8 +500,7 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) nelemtmp = words.next_int(); ncoeffall = words.next_int(); } catch (TokenizerException &e) { - error->all(FLERR,"Incorrect format in SNAP coefficient " - "file: {}", e.what()); + error->all(FLERR,"Incorrect format in SNAP coefficient file: {}", e.what()); } // clean out old arrays and set up element lists @@ -538,7 +537,7 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) std::vector words; try { words = Tokenizer(utils::trim_comment(line),"\"' \t\n\r\f").as_vector(); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { // ignore } if (words.size() != 3) @@ -599,8 +598,7 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) coeffelem[jelem][icoeff] = coeff.next_double(); } catch (TokenizerException &e) { - error->all(FLERR,"Incorrect format in SNAP coefficient " - "file: {}", e.what()); + error->all(FLERR,"Incorrect format in SNAP coefficient file: {}", e.what()); } } } @@ -609,8 +607,7 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) for (int jelem = 0; jelem < nelements; jelem++) { if (elementflags[jelem] == 0) - error->all(FLERR,"Element {} not found in SNAP coefficient " - "file", elements[jelem]); + error->all(FLERR,"Element {} not found in SNAP coefficient file", elements[jelem]); } delete[] elementflags; @@ -660,7 +657,7 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) std::vector words; try { words = Tokenizer(utils::trim_comment(line),"\"' \t\n\r\f").as_vector(); - } catch (TokenizerException &e) { + } catch (TokenizerException &) { // ignore } diff --git a/src/MOLFILE/molfile_interface.cpp b/src/MOLFILE/molfile_interface.cpp index e18f62b337..808bc16ab4 100644 --- a/src/MOLFILE/molfile_interface.cpp +++ b/src/MOLFILE/molfile_interface.cpp @@ -27,8 +27,6 @@ #include #include #include -#include -#include // for strcasecmp() #if vmdplugin_ABIVERSION < 16 #error "unsupported VMD molfile plugin ABI version" @@ -249,7 +247,7 @@ int MolfileInterface::find_plugin(const char *pluginpath) int MolfileInterface::load_plugin(const char *filename) { void *dso; - int len, retval = E_NONE; + int retval = E_NONE; // access shared object dso = platform::dlopen(filename); From 3a3f07d91a4abba951404fb7523d6bb4be024244 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 15:05:32 -0400 Subject: [PATCH 64/84] use portable logic operators --- src/DPD-REACT/fix_rx.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/DPD-REACT/fix_rx.cpp b/src/DPD-REACT/fix_rx.cpp index 8971f5ae48..b14831ee8d 100644 --- a/src/DPD-REACT/fix_rx.cpp +++ b/src/DPD-REACT/fix_rx.cpp @@ -126,7 +126,7 @@ FixRX::FixRX(LAMMPS *lmp, int narg, char **arg) : error->all(FLERR, errmsg); } - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { std::string msg = "FixRX: matrix format is "; if (useSparseKinetics) msg += std::string("sparse"); @@ -172,7 +172,7 @@ FixRX::FixRX(LAMMPS *lmp, int narg, char **arg) : char *word = arg[iarg++]; minSteps = atoi( word ); - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { char msg[128]; sprintf(msg, "FixRX: RK4 numSteps= %d", minSteps); error->message(FLERR, msg); @@ -197,7 +197,7 @@ FixRX::FixRX(LAMMPS *lmp, int narg, char **arg) : // maxIters must be at least minSteps. maxIters = std::max( minSteps, maxIters ); - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { //printf("FixRX: RKF45 minSteps= %d maxIters= %d absTol= %e relTol= %e\n", minSteps, maxIters, absTol, relTol); char msg[128]; sprintf(msg, "FixRX: RKF45 minSteps= %d maxIters= %d relTol= %.1e absTol= %.1e diagnosticFrequency= %d", minSteps, maxIters, relTol, absTol, diagnosticFrequency); @@ -371,7 +371,7 @@ void FixRX::initSparse() { const int Verbosity = 1; - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { for (int k = 0; k < nspecies; ++k) printf("atom->dvname[%d]= %s\n", k, atom->dvname[k]); @@ -421,7 +421,7 @@ void FixRX::initSparse() std::string pstr, rstr; bool allAreIntegral = true; for (int k = 0; k < nspecies; ++k) { - if (stoichReactants[i][k] == 0 and stoichProducts[i][k] == 0) + if (stoichReactants[i][k] == 0 && stoichProducts[i][k] == 0) nzeros++; if (stoichReactants[i][k] > 0.0) { @@ -448,7 +448,7 @@ void FixRX::initSparse() pstr += atom->dvname[k]; } } - if (comm->me == 0 and Verbosity > 1) + if (comm->me == 0 && Verbosity > 1) printf("rx%3d: %d %d %d ... %s %s %s\n", i, nreac_i, nprod_i, allAreIntegral, rstr.c_str(), /*reversible[i]*/ (false) ? "<=>" : "=", pstr.c_str()); mxreac = std::max( mxreac, nreac_i ); @@ -457,7 +457,7 @@ void FixRX::initSparse() if (allAreIntegral) nIntegral++; } - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { char msg[256]; sprintf(msg, "FixRX: Sparsity of Stoichiometric Matrix= %.1f%% non-zeros= %d nspecies= %d nreactions= %d maxReactants= %d maxProducts= %d maxSpecies= %d integralReactions= %d", 100*(double(nzeros) / (nspecies * nreactions)), nzeros, nspecies, nreactions, mxreac, mxprod, (mxreac + mxprod), SparseKinetics_enableIntegralReactions); error->message(FLERR, msg); @@ -539,7 +539,7 @@ void FixRX::initSparse() sparseKinetics_isIntegralReaction[i] = isIntegral_i; } - if (comm->me == 0 and Verbosity > 1) { + if (comm->me == 0 && Verbosity > 1) { for (int i = 1; i < nu_bin.size(); ++i) if (nu_bin[i] > 0) printf("nu_bin[%d] = %d\n", i, nu_bin[i]); @@ -554,7 +554,7 @@ void FixRX::initSparse() rstr += " + "; char digit[6]; - if (SparseKinetics_enableIntegralReactions and sparseKinetics_isIntegralReaction[i]) + if (SparseKinetics_enableIntegralReactions && sparseKinetics_isIntegralReaction[i]) sprintf(digit,"%d ", sparseKinetics_inu[i][kk]); else sprintf(digit,"%4.1f ", sparseKinetics_nu[i][kk]); @@ -570,7 +570,7 @@ void FixRX::initSparse() pstr += " + "; char digit[6]; - if (SparseKinetics_enableIntegralReactions and sparseKinetics_isIntegralReaction[i]) + if (SparseKinetics_enableIntegralReactions && sparseKinetics_isIntegralReaction[i]) sprintf(digit,"%d ", sparseKinetics_inu[i][kk]); else sprintf(digit,"%4.1f ", sparseKinetics_nu[i][kk]); @@ -578,7 +578,7 @@ void FixRX::initSparse() pstr += atom->dvname[k]; } } - if (comm->me == 0 and Verbosity > 1) + if (comm->me == 0 && Verbosity > 1) printf("rx%3d: %s %s %s\n", i, rstr.c_str(), /*reversible[i]*/ (false) ? "<=>" : "=", pstr.c_str()); } // end for nreactions From ef8aa4de9014e6e2d5e88e1cdcc553f4050cc89c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 15:29:46 -0400 Subject: [PATCH 65/84] silence warning --- src/QEQ/fix_qeq.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/QEQ/fix_qeq.cpp b/src/QEQ/fix_qeq.cpp index a0d012bb5b..e2cae80dd4 100644 --- a/src/QEQ/fix_qeq.cpp +++ b/src/QEQ/fix_qeq.cpp @@ -767,7 +767,7 @@ void FixQEq::read_file(char *file) for (int n=nlo; n <= nhi; ++n) zcore[n] = val; for (int n=nlo; n <= nhi; ++n) setflag[n] = 1; } - } catch (EOFException &e) { + } catch (EOFException &) { ; // catch and ignore to exit loop } catch (std::exception &e) { error->one(FLERR,e.what()); From 5d5cc0ac55ac3885d3a37b6704f0a7f24dc60d8e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 15:31:26 -0400 Subject: [PATCH 66/84] preset with packages that build natively on windows with visual c++ --- cmake/presets/windows.cmake | 66 +++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 cmake/presets/windows.cmake diff --git a/cmake/presets/windows.cmake b/cmake/presets/windows.cmake new file mode 100644 index 0000000000..267d1b6154 --- /dev/null +++ b/cmake/presets/windows.cmake @@ -0,0 +1,66 @@ +set(WIN_PACKAGES + ASPHERE + AWPMD + BOCS + BODY + BROWNIAN + CG-DNA + CG-SDK + CLASS2 + COLLOID + COLVARS + CORESHELL + DIELECTRIC + DIFFRACTION + DIPOLE + DPD-BASIC + DPD-MESO + DPD-REACT + DPD-SMOOTH + DRUDE + EFF + EXTRA-COMPUTE + EXTRA-DUMP + EXTRA-FIX + EXTRA-MOLECULE + EXTRA-PAIR + FEP + GRANULAR + INTERLAYER + KSPACE + MANIFOLD + MANYBODY + MC + MEAM + MGPT + MISC + ML-IAP + ML-SNAP + MOFFF + MOLECULE + MOLFILE + OPENMP + ORIENT + PERI + PHONON + POEMS + PTM + QEQ + QTB + REACTION + REAXFF + REPLICA + RIGID + SHOCK + SMTBQ + SPH + SPIN + SRD + TALLY + UEF + YAFF) + +foreach(PKG ${WIN_PACKAGES}) + set(PKG_${PKG} ON CACHE BOOL "" FORCE) +endforeach() + From d5b3ea263b1dc810485b740a0715a7ff106ed81e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 15:42:33 -0400 Subject: [PATCH 67/84] awpmd requires blas, mgpt is not portable --- cmake/presets/windows.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmake/presets/windows.cmake b/cmake/presets/windows.cmake index 267d1b6154..d4e69c5fca 100644 --- a/cmake/presets/windows.cmake +++ b/cmake/presets/windows.cmake @@ -1,6 +1,5 @@ set(WIN_PACKAGES ASPHERE - AWPMD BOCS BODY BROWNIAN @@ -32,7 +31,6 @@ set(WIN_PACKAGES MANYBODY MC MEAM - MGPT MISC ML-IAP ML-SNAP From 4fca127ea41ac1259e873b796459952bac1249cd Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 15:59:12 -0400 Subject: [PATCH 68/84] copy MSVC++ compiler hacks to plugin CMakeLists.txt file --- examples/plugins/CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/examples/plugins/CMakeLists.txt b/examples/plugins/CMakeLists.txt index e4c084fc1d..c61454870a 100644 --- a/examples/plugins/CMakeLists.txt +++ b/examples/plugins/CMakeLists.txt @@ -14,6 +14,15 @@ endif() project(plugins VERSION 1.0 LANGUAGES CXX) +# ugly hacks for MSVC which by default always reports an old C++ standard in the __cplusplus macro +# and prints lots of pointless warnings about "unsafe" functions +if(MSVC) + add_compile_options(/Zc:__cplusplus) + add_compile_options(/wd4244) + add_compile_options(/wd4267) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) +endif() + # NOTE: the next line should be commented out when used outside of the LAMMPS package get_filename_component(LAMMPS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src ABSOLUTE) set(LAMMPS_HEADER_DIR ${LAMMPS_SOURCE_DIR} CACHE PATH "Location of LAMMPS headers") From e12fa5779497d824a297e6991a2e5f4bba345bbb Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 17:11:04 -0400 Subject: [PATCH 69/84] A few more tweaks --- src/MISC/fix_pair_tracker.cpp | 7 +++---- src/MOLFILE/reader_molfile.cpp | 28 +++++++--------------------- src/MOLFILE/reader_molfile.h | 2 +- 3 files changed, 11 insertions(+), 26 deletions(-) diff --git a/src/MISC/fix_pair_tracker.cpp b/src/MISC/fix_pair_tracker.cpp index 95151375c4..d4b640434e 100644 --- a/src/MISC/fix_pair_tracker.cpp +++ b/src/MISC/fix_pair_tracker.cpp @@ -79,15 +79,14 @@ FixPairTracker::FixPairTracker(LAMMPS *lmp, int narg, char **arg) : } else if (strcmp(arg[iarg], "type/include") == 0) { if (iarg + 1 >= narg) error->all(FLERR, "Invalid keyword in fix pair/tracker command"); int ntypes = atom->ntypes; - - int i, j, itype, jtype, in, jn, infield, jnfield; + int i, j, itype, jtype; int inlo, inhi, jnlo, jnhi; - char *istr, *jstr; + if (!type_filter) { memory->create(type_filter, ntypes + 1, ntypes + 1, "fix/pair/tracker:type_filter"); for (i = 0; i <= ntypes; i++) { - for (j = 0; j <= ntypes; j++) { type_filter[i][j] = 0; } + for (j = 0; j <= ntypes; j++) type_filter[i][j] = 0; } } diff --git a/src/MOLFILE/reader_molfile.cpp b/src/MOLFILE/reader_molfile.cpp index e04b615018..57c8ad3a6e 100644 --- a/src/MOLFILE/reader_molfile.cpp +++ b/src/MOLFILE/reader_molfile.cpp @@ -85,13 +85,7 @@ void ReaderMolfile::settings(int narg, char **arg) if (mf->find_plugin(path)!= MFI::E_MATCH) error->one(FLERR,"No suitable molfile plugin found"); - if (screen) - fprintf(screen,"Dump reader uses molfile plugin: %s\n", - mf->get_plugin_name()); - - if (logfile) - fprintf(logfile,"Dump reader uses molfile plugin: %s\n", - mf->get_plugin_name()); + utils::logmesg(lmp,"Dump reader uses molfile plugin: {}\n", mf->get_plugin_name()); } } @@ -100,30 +94,22 @@ void ReaderMolfile::settings(int narg, char **arg) only called by proc 0 ------------------------------------------------------------------------- */ -void ReaderMolfile::open_file(const char *file) +void ReaderMolfile::open_file(const std::string &file) { int rv; - char str[1024]; - + // close open file, if needed. if (mf->is_open()) mf->close(); - rv = mf->open(file,&natoms); + rv = mf->open(file.c_str(),&natoms); - if (rv != MFI::E_NONE) { - snprintf(str,1024,"Cannot open file %s",file); - error->one(FLERR,str); - } + if (rv != MFI::E_NONE) error->one(FLERR,"Cannot open file {}", file); - if (natoms < 1) { - snprintf(str,1024,"No atoms in file %s",file); - error->one(FLERR,str); - } + if (natoms < 1) error->one(FLERR,"No atoms in file {}", file); memory->create(types,natoms,"reader:types"); memory->create(coords,3*natoms,"reader:coords"); - if (mf->has_vels()) - memory->create(vels,3*natoms,"reader:vels"); + if (mf->has_vels()) memory->create(vels,3*natoms,"reader:vels"); // initialize system properties, if available if (mf->has_props()) { diff --git a/src/MOLFILE/reader_molfile.h b/src/MOLFILE/reader_molfile.h index 1f7fead9c0..4330eaf4eb 100644 --- a/src/MOLFILE/reader_molfile.h +++ b/src/MOLFILE/reader_molfile.h @@ -39,7 +39,7 @@ class ReaderMolfile : public Reader { int &, int &, int &); virtual void read_atoms(int, int, double **); - virtual void open_file(const char *); + virtual void open_file(const std::string &); virtual void close_file(); private: From 4b86dbd200e08fb8351c9fda7aa2ddce3384d2be Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 7 Oct 2021 17:11:33 -0400 Subject: [PATCH 70/84] add cmake configuration file for visual studio --- cmake/CMakeSettings.json | 55 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 cmake/CMakeSettings.json diff --git a/cmake/CMakeSettings.json b/cmake/CMakeSettings.json new file mode 100644 index 0000000000..dada2f6752 --- /dev/null +++ b/cmake/CMakeSettings.json @@ -0,0 +1,55 @@ +{ + "configurations": [ + { + "name": "x64-Debug-MSVC", + "generator": "Ninja", + "configurationType": "Debug", + "buildRoot": "${workspaceRoot}\\build\\${name}", + "installRoot": "${workspaceRoot}\\install\\${name}", + "cmakeCommandArgs": "-S ${workspaceRoot}\\cmake -C ${workspaceRoot}\\cmake\\presets\\windows.cmake", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [ + { + "name": "BUILD_SHARED_LIBS", + "value": "True", + "type": "BOOL" + }, + { + "name": "BUILD_TOOLS", + "value": "True", + "type": "BOOL" + }, + { + "name": "LAMMPS_EXCEPTIONS", + "value": "True", + "type": "BOOL" + } + ] + }, + { + "name": "x64-Debug-Clang", + "generator": "Ninja", + "configurationType": "Debug", + "buildRoot": "${workspaceRoot}\\build\\${name}", + "installRoot": "${workspaceRoot}\\install\\${name}", + "cmakeCommandArgs": "-S ${workspaceRoot}\\cmake -C ${workspaceRoot}\\cmake\\presets\\windows.cmake", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64" ], + "variables": [ + { + "name": "BUILD_TOOLS", + "value": "True", + "type": "BOOL" + }, + { + "name": "LAMMPS_EXCEPTIONS", + "value": "True", + "type": "BOOL" + } + ] + } + ] +} \ No newline at end of file From 392ebf7db765ca008754570609b089689a17f1db Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 8 Oct 2021 11:34:21 -0400 Subject: [PATCH 71/84] revise automatic seed generation --- src/DPD-MESO/pair_mdpd.cpp | 7 +++++-- src/DPD-MESO/pair_tdpd.cpp | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/DPD-MESO/pair_mdpd.cpp b/src/DPD-MESO/pair_mdpd.cpp index bdadb8fb23..53994800d0 100644 --- a/src/DPD-MESO/pair_mdpd.cpp +++ b/src/DPD-MESO/pair_mdpd.cpp @@ -217,9 +217,12 @@ void PairMDPD::settings(int narg, char **arg) seed = utils::inumeric(FLERR,arg[2],false,lmp); // initialize Marsaglia RNG with processor-unique seed + // create a positive seed based on the system clock, if requested. - if (seed <= 0) - seed = (int) (platform::walltime() * 1073741824.0); + if (seed <= 0) { + constexpr double LARGE_NUM = 2<<30; + seed = int(fmod(platform::walltime() * LARGE_NUM, LARGE_NUM)) + 1; + } delete random; random = new RanMars(lmp,(seed + comm->me) % 900000000); diff --git a/src/DPD-MESO/pair_tdpd.cpp b/src/DPD-MESO/pair_tdpd.cpp index 1f48e12f55..70168c0e2a 100644 --- a/src/DPD-MESO/pair_tdpd.cpp +++ b/src/DPD-MESO/pair_tdpd.cpp @@ -239,9 +239,12 @@ void PairTDPD::settings(int narg, char **arg) seed = utils::inumeric(FLERR,arg[2],false,lmp); // initialize Marsaglia RNG with processor-unique seed + // create a positive seed based on the system clock, if requested. - if (seed <= 0) - seed = (int) (platform::walltime() * 1073741824.0); + if (seed <= 0) { + constexpr double LARGE_NUM = 2<<30; + seed = int(fmod(platform::walltime() * LARGE_NUM, LARGE_NUM)) + 1; + } delete random; random = new RanMars(lmp,(seed + comm->me) % 900000000); From cc11fa37b2b3fda3d544c4e0f9422b652ce182ba Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 8 Oct 2021 11:44:09 -0400 Subject: [PATCH 72/84] whitespace --- src/MISC/fix_pair_tracker.cpp | 2 +- src/MOLFILE/reader_molfile.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MISC/fix_pair_tracker.cpp b/src/MISC/fix_pair_tracker.cpp index d4b640434e..3616855869 100644 --- a/src/MISC/fix_pair_tracker.cpp +++ b/src/MISC/fix_pair_tracker.cpp @@ -81,7 +81,7 @@ FixPairTracker::FixPairTracker(LAMMPS *lmp, int narg, char **arg) : int ntypes = atom->ntypes; int i, j, itype, jtype; int inlo, inhi, jnlo, jnhi; - + if (!type_filter) { memory->create(type_filter, ntypes + 1, ntypes + 1, "fix/pair/tracker:type_filter"); diff --git a/src/MOLFILE/reader_molfile.cpp b/src/MOLFILE/reader_molfile.cpp index 57c8ad3a6e..5f75ae50f5 100644 --- a/src/MOLFILE/reader_molfile.cpp +++ b/src/MOLFILE/reader_molfile.cpp @@ -97,7 +97,7 @@ void ReaderMolfile::settings(int narg, char **arg) void ReaderMolfile::open_file(const std::string &file) { int rv; - + // close open file, if needed. if (mf->is_open()) mf->close(); From 6e8da80148039e6ba1dfc8fbefebb93ccb38a01c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 8 Oct 2021 13:57:09 -0400 Subject: [PATCH 73/84] adjustments for intel compilers on windows --- cmake/CMakeLists.txt | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 2e1504f1f0..37975084c8 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -82,11 +82,22 @@ include(CheckIncludeFileCXX) # set required compiler flags and compiler/CPU arch specific optimizations if((CMAKE_CXX_COMPILER_ID STREQUAL "Intel") OR (CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -restrict") - if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4) - set(CMAKE_TUNE_DEFAULT "-xCOMMON-AVX512") + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + if (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Qrestrict") + endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4) + set(CMAKE_TUNE_DEFAULT "/QxCOMMON-AVX512") + else() + set(CMAKE_TUNE_DEFAULT "/QxHost") + endif() else() - set(CMAKE_TUNE_DEFAULT "-xHost") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -restrict") + if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.3 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 17.4) + set(CMAKE_TUNE_DEFAULT "-xCOMMON-AVX512") + else() + set(CMAKE_TUNE_DEFAULT "-xHost") + endif() endif() endif() From 46efae5998e0737e54afc4ff135989c76161fdce Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 8 Oct 2021 13:58:08 -0400 Subject: [PATCH 74/84] needed for compilation on windows. not really used because of platform::walltime() --- src/STUBS/mpi.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/STUBS/mpi.cpp b/src/STUBS/mpi.cpp index e5cd50629e..d3823a0297 100644 --- a/src/STUBS/mpi.cpp +++ b/src/STUBS/mpi.cpp @@ -21,7 +21,13 @@ #include #include #include + +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +#else #include +#endif /* data structure for double/int */ From fb137b26bf6a7544cb7b706b447e8561667a115c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 8 Oct 2021 13:59:17 -0400 Subject: [PATCH 75/84] silence compiler warnings --- src/platform.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/platform.cpp b/src/platform.cpp index 00636ec703..4db5042e78 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -396,6 +396,10 @@ std::string platform::mpi_info(int &major, int &minor) #if (defined(MPI_VERSION) && (MPI_VERSION > 2)) || defined(MPI_STUBS) static char version[MPI_MAX_LIBRARY_VERSION_STRING]; MPI_Get_library_version(version, &len); + if (len > 80) { + char *ptr = strchr(version + 80, '\n'); + if (ptr) *ptr = '\0'; + } #else constexpr int MAX_VERSION_STRING = 32; static char version[MAX_VERSION_STRING]; @@ -404,10 +408,6 @@ std::string platform::mpi_info(int &major, int &minor) #if defined(MPI_VERSION) MPI_Get_version(&major, &minor); - if (len > 80) { - char *ptr = strchr(version + 80, '\n'); - if (ptr) *ptr = '\0'; - } #else major = 1; minor = 0; From 83bc70bf05b7e0c37f2583904d6617b359b0d838 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 8 Oct 2021 15:11:16 -0400 Subject: [PATCH 76/84] workaround for classic intel compiler on windows --- src/platform.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/platform.cpp b/src/platform.cpp index 4db5042e78..b057c6415b 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -289,6 +289,9 @@ std::string platform::compiler_info() #elif defined(__PGI) buf = fmt::format("PGI C++ {}.{}", __PGIC__, __PGIC_MINOR__); #elif defined(__INTEL_COMPILER) +#if !defined(__VERSION__) +#define __VERSION__ __INTEL_COMPILER_BUILD_DATE +#endif double version = static_cast(__INTEL_COMPILER) * 0.01; buf = fmt::format("Intel Classic C++ {:.2f}.{} / {}", version, __INTEL_COMPILER_UPDATE, __VERSION__); From ae0fa17132a821c57a5314efe3aa8619dd546c5a Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 8 Oct 2021 15:33:26 -0400 Subject: [PATCH 77/84] make consistent with include files --- src/STUBS/mpi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/STUBS/mpi.cpp b/src/STUBS/mpi.cpp index d3823a0297..3f4cc5964f 100644 --- a/src/STUBS/mpi.cpp +++ b/src/STUBS/mpi.cpp @@ -173,7 +173,7 @@ int MPI_Finalize() double MPI_Wtime() { -#if defined(_MSC_VER) +#if defined(_WIN32) double t; t = GetTickCount(); From 09bcfc2116c84a31f8a5cf436e455d83b4b08647 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 8 Oct 2021 15:33:49 -0400 Subject: [PATCH 78/84] document visual studio support --- doc/src/Build_windows.rst | 44 ++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/doc/src/Build_windows.rst b/doc/src/Build_windows.rst index 3a56f29d09..fa2296d302 100644 --- a/doc/src/Build_windows.rst +++ b/doc/src/Build_windows.rst @@ -4,6 +4,7 @@ Notes for building LAMMPS on Windows * :ref:`General remarks ` * :ref:`Running Linux on Windows ` * :ref:`Using GNU GCC ported to Windows ` +* :ref:`Using Visual Studio ` * :ref:`Using a cross-compiler ` ---------- @@ -31,13 +32,13 @@ pre-compiled Windows binary packages are sufficient for your needs. If it is necessary for you to compile LAMMPS on a Windows machine (e.g. because it is your main desktop), please also consider using a virtual machine software and compile and run LAMMPS in a Linux virtual -machine, or - if you have a sufficiently up-to-date Windows 10 -installation - consider using the Windows subsystem for Linux. This -optional Windows feature allows you to run the bash shell from Ubuntu -from within Windows and from there on, you can pretty much use that -shell like you are running on an Ubuntu Linux machine (e.g. installing -software via apt-get and more). For more details on that, please see -:doc:`this tutorial `. +machine, or - if you have a sufficiently up-to-date Windows 10 or +Windows 11 installation - consider using the Windows subsystem for +Linux. This optional Windows feature allows you to run the bash shell +from Ubuntu from within Windows and from there on, you can pretty much +use that shell like you are running on an Ubuntu Linux machine +(e.g. installing software via apt-get and more). For more details on +that, please see :doc:`this tutorial `. .. _gnu: @@ -67,6 +68,35 @@ requiring changes to the LAMMPS source code, or figure out corrections yourself, please report them on the lammps-users mailing list, or file them as an issue or pull request on the LAMMPS GitHub project. +.. _msvc: + +Using Microsoft Visual Studio +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Following the integration of the :doc:`platform namespace +` into the LAMMPS code base, portability of LAMMPS +to be compiled on Windows using Visual Studio has been significantly +improved. This has been tested with Visual Studio 2019 (aka version +16). Not all features and packages in LAMMPS are currently supported +out of the box, but a preset ``cmake/presets/windows.cmake`` is provided +that contains the packages that have been compiled successfully. You +must use the CMake based build procedure, and either use the integrated +CMake support of Visual Studio or use an external CMake installation to +create build files for the Visual Studio build system. Please note that +on launching Visual Studio it will scan the directory tree and likely +miss the correct master ``CMakeLists.txt``. Try to open the +``cmake/CMakeSettings.json`` and use those CMake configurations as a +starting point. It is also possible to configure and compile LAMMPS +from the command line with a CMake binary from `cmake.org `_. + +To support running in parallel you can compile with OpenMP enabled using +the OPENMP package or install Microsoft MPI (including the SDK) and compile +LAMMPS with MPI enabled. + +This is work in progress and you should contact the LAMMPS developers +via GitHub, the forum, or the mailing list, if you have questions or +LAMMPS specific problems. + .. _cross: Using a cross-compiler From dd6e3c1acc734a1879bb09f865e0fa844a00ccf7 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 8 Oct 2021 20:07:20 -0400 Subject: [PATCH 79/84] avoid variable length array and signed vs. unsigned warnings --- lib/gpu/geryon/ocl_device.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/gpu/geryon/ocl_device.h b/lib/gpu/geryon/ocl_device.h index 003b4b3ba7..df53aff5b8 100644 --- a/lib/gpu/geryon/ocl_device.h +++ b/lib/gpu/geryon/ocl_device.h @@ -481,7 +481,7 @@ int UCL_Device::set_platform(int pid) { cl_device_id *subdevice_list = new cl_device_id[num_subdevices]; CL_SAFE_CALL(clCreateSubDevices(device_list[i], props, num_subdevices, subdevice_list, &num_subdevices)); - for (int j=0; j= 3.0) op.has_shuffle_support=true; } + delete[] buffer2; #endif _properties.push_back(op); @@ -836,7 +837,7 @@ int UCL_Device::auto_set_platform(const enum UCL_DEVICE_TYPE type, bool vendor_match=false; bool type_match=false; - int max_cus=0; + unsigned int max_cus=0; int best_platform=0; std::string vendor_upper=vendor; From 2e122ff62b3b243b7519f617cfde77445d5eaa18 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 9 Oct 2021 19:46:52 -0400 Subject: [PATCH 80/84] Add GitHub action compiling LAMMPS with Visual C++ --- .github/workflows/compile-msvc.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/compile-msvc.yml diff --git a/.github/workflows/compile-msvc.yml b/.github/workflows/compile-msvc.yml new file mode 100644 index 0000000000..68ddafb887 --- /dev/null +++ b/.github/workflows/compile-msvc.yml @@ -0,0 +1,27 @@ +# GitHub action to build LAMMPS on Windows with Visual C++ +name: "Native Windows Compilation" + +on: + push: + branches: [platform-namespace] + +jobs: + build: + name: Windows Compilation Test + if: ${{ github.repository == 'akohlmey/lammps' }} + runs-on: windows-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 2 + + - name: Building LAMMPS via CMake + shell: bash + run: | + cmake -C ../cmake/presets/windowws.cmake \ + -S cmake -B build \ + -D BUILD_SHARED_LIBS=on \ + -D LAMMPS_EXCEPTIONS=on + cmake --build build --config Release From 5ad7e5a81586dbfb38ece0a376d36bef6aa0c83f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 9 Oct 2021 19:55:30 -0400 Subject: [PATCH 81/84] correct path to preset file and do two quick runs for checking the binary --- .github/workflows/compile-msvc.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-msvc.yml b/.github/workflows/compile-msvc.yml index 68ddafb887..8e2e644690 100644 --- a/.github/workflows/compile-msvc.yml +++ b/.github/workflows/compile-msvc.yml @@ -20,8 +20,14 @@ jobs: - name: Building LAMMPS via CMake shell: bash run: | - cmake -C ../cmake/presets/windowws.cmake \ + cmake -C cmake/presets/windows.cmake \ -S cmake -B build \ -D BUILD_SHARED_LIBS=on \ -D LAMMPS_EXCEPTIONS=on cmake --build build --config Release + + - name: Run LAMMPS executable + shell: bash + run: | + ./build/Release/lmp.exe -h + ./build/Release/lmp.exe -in bench/in.lj From c3629b5f0147046004f74e898baf14cd531c8c22 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 9 Oct 2021 20:27:47 -0400 Subject: [PATCH 82/84] MS VC++ needs to have STUBS with PUBLIC linkage --- cmake/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 37975084c8..95d454a25f 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -298,7 +298,11 @@ else() set_target_properties(mpi_stubs PROPERTIES OUTPUT_NAME lammps_mpi_stubs${LAMMPS_MACHINE}) target_include_directories(mpi_stubs PUBLIC $) if(BUILD_SHARED_LIBS) - target_link_libraries(lammps PRIVATE mpi_stubs) + if(MSVC) + target_link_libraries(lammps PUBLIC mpi_stubs) + else() + target_link_libraries(lammps PRIVATE mpi_stubs) + endif() target_include_directories(lammps INTERFACE $) target_compile_definitions(lammps INTERFACE $) else() From 1bbed2579b904c06ea0be611b3faf18b16abe031 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 9 Oct 2021 20:32:39 -0400 Subject: [PATCH 83/84] try alternate approach to make MSVC++ happy linking STUBS --- cmake/CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 95d454a25f..fc427acdc9 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -298,11 +298,12 @@ else() set_target_properties(mpi_stubs PROPERTIES OUTPUT_NAME lammps_mpi_stubs${LAMMPS_MACHINE}) target_include_directories(mpi_stubs PUBLIC $) if(BUILD_SHARED_LIBS) + target_link_libraries(lammps PRIVATE mpi_stubs) if(MSVC) - target_link_libraries(lammps PUBLIC mpi_stubs) - else() - target_link_libraries(lammps PRIVATE mpi_stubs) - endif() + target_link_libraries(lmp PRIVATE mpi_stubs) + target_include_directories(lmp INTERFACE $) + target_compile_definitions(lmp INTERFACE $) + endif(MSVC) target_include_directories(lammps INTERFACE $) target_compile_definitions(lammps INTERFACE $) else() From 64b27fa28e9a369cfbccefb443602d3fdb028b65 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 9 Oct 2021 20:54:18 -0400 Subject: [PATCH 84/84] only run windows compilation action on master branch in lammps repo --- .github/workflows/compile-msvc.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile-msvc.yml b/.github/workflows/compile-msvc.yml index 8e2e644690..307dc81fe6 100644 --- a/.github/workflows/compile-msvc.yml +++ b/.github/workflows/compile-msvc.yml @@ -3,12 +3,12 @@ name: "Native Windows Compilation" on: push: - branches: [platform-namespace] + branches: [master] jobs: build: name: Windows Compilation Test - if: ${{ github.repository == 'akohlmey/lammps' }} + if: ${{ github.repository == 'lammps/lammps' }} runs-on: windows-latest steps: