Merge branch 'master' into kk_gridcomm

This commit is contained in:
Axel Kohlmeyer
2021-09-09 19:17:55 -04:00
32 changed files with 310 additions and 274 deletions

View File

@ -36,7 +36,11 @@ find_package(Git)
# by default, install into $HOME/.local (not /usr/local), so that no root access (and sudo!!) is needed
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.local" CACHE PATH "Default install path" FORCE)
if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND (NOT CMAKE_CROSSCOMPILING))
set(CMAKE_INSTALL_PREFIX "$ENV{USERPROFILE}/LAMMPS" CACHE PATH "Default install path" FORCE)
else()
set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.local" CACHE PATH "Default install path" FORCE)
endif()
endif()
# If enabled, no need to use LD_LIBRARY_PATH / DYLD_LIBRARY_PATH when installed
@ -90,6 +94,10 @@ endif()
set(CMAKE_CXX_STANDARD 11)
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
if(MSVC)
add_compile_options(/Zc:__cplusplus)
endif()
# export all symbols when building a .dll file on windows
if((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND BUILD_SHARED_LIBS)

View File

@ -206,6 +206,9 @@ Convenience functions
Customized standard functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. doxygenfunction:: binary_search
:project: progguide
.. doxygenfunction:: merge_sort
:project: progguide

View File

@ -47,13 +47,18 @@ using namespace FixConst;
// socket interface
#ifndef _WIN32
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <netdb.h>
#else
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <io.h>
#include <windows.h>
#endif
#define MSGLEN 12

View File

@ -1029,12 +1029,12 @@ void Balance::tally(int dim, int n, double *split)
if (wtflag) {
weight = fixstore->vstore;
for (int i = 0; i < nlocal; i++) {
index = binary(x[i][dim],n,split);
index = utils::binary_search(x[i][dim],n,split);
onecost[index] += weight[i];
}
} else {
for (int i = 0; i < nlocal; i++) {
index = binary(x[i][dim],n,split);
index = utils::binary_search(x[i][dim],n,split);
onecost[index] += 1.0;
}
}
@ -1131,16 +1131,16 @@ double Balance::imbalance_splits()
if (wtflag) {
weight = fixstore->vstore;
for (int i = 0; i < nlocal; i++) {
ix = binary(x[i][0],nx,xsplit);
iy = binary(x[i][1],ny,ysplit);
iz = binary(x[i][2],nz,zsplit);
ix = utils::binary_search(x[i][0],nx,xsplit);
iy = utils::binary_search(x[i][1],ny,ysplit);
iz = utils::binary_search(x[i][2],nz,zsplit);
proccost[iz*nx*ny + iy*nx + ix] += weight[i];
}
} else {
for (int i = 0; i < nlocal; i++) {
ix = binary(x[i][0],nx,xsplit);
iy = binary(x[i][1],ny,ysplit);
iz = binary(x[i][2],nz,zsplit);
ix = utils::binary_search(x[i][0],nx,xsplit);
iy = utils::binary_search(x[i][1],ny,ysplit);
iz = utils::binary_search(x[i][2],nz,zsplit);
proccost[iz*nx*ny + iy*nx + ix] += 1.0;
}
}
@ -1161,40 +1161,6 @@ double Balance::imbalance_splits()
return imbalance;
}
/* ----------------------------------------------------------------------
binary search for where value falls in N-length vec
note that vec actually has N+1 values, but ignore last one
values in vec are monotonically increasing, but adjacent values can be ties
value may be outside range of vec limits
always return index from 0 to N-1 inclusive
return 0 if value < vec[0]
reutrn N-1 if value >= vec[N-1]
return index = 1 to N-2 inclusive if vec[index] <= value < vec[index+1]
note that for adjacent tie values, index of lower tie is not returned
since never satisfies 2nd condition that value < vec[index+1]
------------------------------------------------------------------------- */
int Balance::binary(double value, int n, double *vec)
{
int lo = 0;
int hi = n-1;
if (value < vec[lo]) return lo;
if (value >= vec[hi]) return hi;
// insure vec[lo] <= value < vec[hi] at every iteration
// done when lo,hi are adjacent
int index = (lo+hi)/2;
while (lo < hi-1) {
if (value < vec[index]) hi = index;
else if (value >= vec[index]) lo = index;
index = (lo+hi)/2;
}
return index;
}
/* ----------------------------------------------------------------------
write dump snapshot of line segments in Pizza.py mdump mesh format
write xy lines around each proc's sub-domain for 2d

View File

@ -84,7 +84,6 @@ class Balance : public Command {
void shift_setup_static(char *);
void tally(int, int, double *);
int adjust(int, double *);
int binary(double, int, double *);
#ifdef BALANCE_DEBUG
void debug_shift_output(int, int, int, double *);
#endif

View File

@ -782,13 +782,13 @@ int Comm::coord2proc(double *x, int &igx, int &igy, int &igz)
} else if (layout == Comm::LAYOUT_NONUNIFORM) {
if (triclinic == 0) {
igx = binary((x[0]-boxlo[0])/prd[0],procgrid[0],xsplit);
igy = binary((x[1]-boxlo[1])/prd[1],procgrid[1],ysplit);
igz = binary((x[2]-boxlo[2])/prd[2],procgrid[2],zsplit);
igx = utils::binary_search((x[0]-boxlo[0])/prd[0],procgrid[0],xsplit);
igy = utils::binary_search((x[1]-boxlo[1])/prd[1],procgrid[1],ysplit);
igz = utils::binary_search((x[2]-boxlo[2])/prd[2],procgrid[2],zsplit);
} else {
igx = binary(x[0],procgrid[0],xsplit);
igy = binary(x[1],procgrid[1],ysplit);
igz = binary(x[2],procgrid[2],zsplit);
igx = utils::binary_search(x[0],procgrid[0],xsplit);
igy = utils::binary_search(x[1],procgrid[1],ysplit);
igz = utils::binary_search(x[2],procgrid[2],zsplit);
}
}
@ -802,36 +802,6 @@ int Comm::coord2proc(double *x, int &igx, int &igy, int &igz)
return grid2proc[igx][igy][igz];
}
/* ----------------------------------------------------------------------
binary search for value in N-length ascending vec
value may be outside range of vec limits
always return index from 0 to N-1 inclusive
return 0 if value < vec[0]
reutrn N-1 if value >= vec[N-1]
return index = 1 to N-2 if vec[index] <= value < vec[index+1]
------------------------------------------------------------------------- */
int Comm::binary(double value, int n, double *vec)
{
int lo = 0;
int hi = n-1;
if (value < vec[lo]) return lo;
if (value >= vec[hi]) return hi;
// insure vec[lo] <= value < vec[hi] at every iteration
// done when lo,hi are adjacent
int index = (lo+hi)/2;
while (lo < hi-1) {
if (value < vec[index]) hi = index;
else if (value >= vec[index]) lo = index;
index = (lo+hi)/2;
}
return index;
}
/* ----------------------------------------------------------------------
partition a global regular grid into one brick-shaped sub-grid per proc
if grid point is inside my sub-domain I own it,

View File

@ -98,7 +98,6 @@ class Comm : protected Pointers {
virtual void forward_comm_array(int, double **) = 0;
virtual int exchange_variable(int, double *, double *&) = 0;
int binary(double, int, double *);
// map a point to a processor, based on current decomposition

View File

@ -64,7 +64,7 @@ vstore(nullptr), astore(nullptr), rbuf(nullptr)
if (flavor == PERATOM) {
restart_peratom = utils::inumeric(FLERR,arg[4],false,lmp);
nvalues = utils::inumeric(FLERR,arg[5],false,lmp);
if (restart_peratom < 0 or restart_peratom > 1 || nvalues <= 0)
if ((restart_peratom < 0) || (restart_peratom > 1) || (nvalues <= 0))
error->all(FLERR,"Illegal fix store command");
vecflag = 0;
if (nvalues == 1) vecflag = 1;

View File

@ -51,6 +51,9 @@
#include <map>
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#define PSAPI_VERSION 1
#include <windows.h>
#include <cstdint>

View File

@ -55,7 +55,9 @@
#include <cstring>
#include <map>
#if !defined(_WIN32)
#if defined(_WIN32)
#include <io.h>
#else
#include <unistd.h> // for isatty()
#endif

View File

@ -288,12 +288,6 @@ union ubuf {
#define _noopt
#endif
// settings to enable LAMMPS to build under Windows
#ifdef _WIN32
#include "lmpwindows.h"
#endif
// suppress unused parameter warning
#define LMP_UNUSED_PARAM(x) (void) (x)

View File

@ -11,17 +11,8 @@
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <ciso646>
#if !defined(__MINGW32__)
#include "erf.h"
#endif
#include <cmath>
#include <cstring>
#include <direct.h>
// LAMMPS uses usleep with 100 ms arguments, no microsecond precision needed
#if !defined(__MINGW32__)
#include "sleep.h"
#endif
// some symbols have different names in Windows

View File

@ -1,4 +1,3 @@
// clang-format off
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
@ -14,8 +13,6 @@
#include "my_page.h"
#include <cstdlib>
#if defined(LMP_INTEL) && !defined(LAMMPS_MEMALIGN) && !defined(_WIN32)
#define LAMMPS_MEMALIGN 64
#endif
@ -60,12 +57,12 @@ using namespace LAMMPS_NS;
* Need to call init() before use to define allocation settings */
template <class T>
MyPage<T>::MyPage() : ndatum(0), nchunk(0), pages(nullptr), page(nullptr),
npage(0), ipage(-1), index(-1), maxchunk(-1),
pagesize(-1), pagedelta(1), errorflag(0) {};
MyPage<T>::MyPage() :
ndatum(0), nchunk(0), pages(nullptr), page(nullptr), npage(0), ipage(-1), index(-1),
maxchunk(-1), pagesize(-1), pagedelta(1), errorflag(0){};
template <class T>
MyPage<T>::~MyPage() {
template <class T> MyPage<T>::~MyPage()
{
deallocate();
}
@ -79,27 +76,26 @@ MyPage<T>::~MyPage() {
* \param user_pagedelta Number of pages to allocate with one malloc
* \return 1 if there were invalid parameters, 2 if there was an allocation error or 0 if successful */
template<class T>
int MyPage<T>::init(int user_maxchunk, int user_pagesize,
int user_pagedelta) {
maxchunk = user_maxchunk;
pagesize = user_pagesize;
pagedelta = user_pagedelta;
template <class T> int MyPage<T>::init(int user_maxchunk, int user_pagesize, int user_pagedelta)
{
maxchunk = user_maxchunk;
pagesize = user_pagesize;
pagedelta = user_pagedelta;
if (maxchunk <= 0 || pagesize <= 0 || pagedelta <= 0) return 1;
if (maxchunk > pagesize) return 1;
if (maxchunk <= 0 || pagesize <= 0 || pagedelta <= 0) return 1;
if (maxchunk > pagesize) return 1;
// free storage if re-initialized
// free storage if re-initialized
deallocate();
deallocate();
// initial page allocation
// initial page allocation
allocate();
if (errorflag) return 2;
reset();
return 0;
}
allocate();
if (errorflag) return 2;
reset();
return 0;
}
/** Pointer to location that can store N items.
*
@ -110,8 +106,8 @@ int MyPage<T>::init(int user_maxchunk, int user_pagesize,
* \param n number of items for which storage is requested
* \return memory location or null pointer, if error or allocation failed */
template <class T>
T *MyPage<T>::get(int n) {
template <class T> T *MyPage<T>::get(int n)
{
if (n > maxchunk) {
errorflag = 1;
return nullptr;
@ -120,7 +116,7 @@ T *MyPage<T>::get(int n) {
nchunk++;
// return pointer from current page
if (index+n <= pagesize) {
if (index + n <= pagesize) {
int start = index;
index += n;
return &page[start];
@ -137,11 +133,10 @@ T *MyPage<T>::get(int n) {
return &page[0];
}
/** Reset state of memory pool without freeing any memory */
template <class T>
void MyPage<T>::reset() {
template <class T> void MyPage<T>::reset()
{
ndatum = nchunk = 0;
index = ipage = 0;
page = (pages != nullptr) ? pages[ipage] : nullptr;
@ -150,23 +145,22 @@ void MyPage<T>::reset() {
/* ---------------------------------------------------------------------- */
template <class T>
void MyPage<T>::allocate() {
template <class T> void MyPage<T>::allocate()
{
npage += pagedelta;
pages = (T **) realloc(pages,npage*sizeof(T *));
pages = (T **) realloc(pages, npage * sizeof(T *));
if (!pages) {
errorflag = 2;
return;
}
for (int i = npage-pagedelta; i < npage; i++) {
for (int i = npage - pagedelta; i < npage; i++) {
#if defined(LAMMPS_MEMALIGN)
void *ptr;
if (posix_memalign(&ptr, LAMMPS_MEMALIGN, pagesize*sizeof(T)))
errorflag = 2;
if (posix_memalign(&ptr, LAMMPS_MEMALIGN, pagesize * sizeof(T))) errorflag = 2;
pages[i] = (T *) ptr;
#else
pages[i] = (T *) malloc(pagesize*sizeof(T));
pages[i] = (T *) malloc(pagesize * sizeof(T));
if (!pages[i]) errorflag = 2;
#endif
}
@ -174,8 +168,8 @@ void MyPage<T>::allocate() {
/** Free all allocated pages of this class instance */
template <class T>
void MyPage<T>::deallocate() {
template <class T> void MyPage<T>::deallocate()
{
reset();
for (int i = 0; i < npage; i++) free(pages[i]);
free(pages);
@ -186,9 +180,9 @@ void MyPage<T>::deallocate() {
// explicit instantiations
namespace LAMMPS_NS {
template class MyPage<int>;
template class MyPage<long>;
template class MyPage<long long>;
template class MyPage<double>;
template class MyPage<HyperOneCoeff>;
}
template class MyPage<int>;
template class MyPage<long>;
template class MyPage<long long>;
template class MyPage<double>;
template class MyPage<HyperOneCoeff>;
} // namespace LAMMPS_NS

View File

@ -1,4 +1,3 @@
// clang-format off
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
@ -50,7 +49,8 @@ using namespace LAMMPS_NS;
template <class T>
MyPoolChunk<T>::MyPoolChunk(int user_minchunk, int user_maxchunk, int user_nbin,
int user_chunkperpage, int user_pagedelta) {
int user_chunkperpage, int user_pagedelta)
{
minchunk = user_minchunk;
maxchunk = user_maxchunk;
nbin = user_nbin;
@ -68,13 +68,13 @@ MyPoolChunk<T>::MyPoolChunk(int user_minchunk, int user_maxchunk, int user_nbin,
// insure nbin*binsize spans minchunk to maxchunk inclusive
binsize = (maxchunk-minchunk+1) / nbin;
if (minchunk + nbin*binsize <= maxchunk) binsize++;
binsize = (maxchunk - minchunk + 1) / nbin;
if (minchunk + nbin * binsize <= maxchunk) binsize++;
freelist = nullptr;
for (int ibin = 0; ibin < nbin; ibin++) {
freehead[ibin] = -1;
chunksize[ibin] = minchunk + (ibin+1)*binsize - 1;
chunksize[ibin] = minchunk + (ibin + 1) * binsize - 1;
if (chunksize[ibin] > maxchunk) chunksize[ibin] = maxchunk;
}
@ -85,10 +85,10 @@ MyPoolChunk<T>::MyPoolChunk(int user_minchunk, int user_maxchunk, int user_nbin,
}
/** Destroy class instance and free all allocated memory */
template <class T>
MyPoolChunk<T>::~MyPoolChunk() {
delete [] freehead;
delete [] chunksize;
template <class T> MyPoolChunk<T>::~MyPoolChunk()
{
delete[] freehead;
delete[] chunksize;
if (npage) {
free(freelist);
for (int i = 0; i < npage; i++) free(pages[i]);
@ -102,9 +102,9 @@ MyPoolChunk<T>::~MyPoolChunk() {
* \param index Index of chunk in memory pool
* \return Pointer to requested chunk of storage */
template <class T>
T *MyPoolChunk<T>::get(int &index) {
int ibin = nbin-1;
template <class T> T *MyPoolChunk<T>::get(int &index)
{
int ibin = nbin - 1;
if (freehead[ibin] < 0) {
allocate(ibin);
if (errorflag) {
@ -116,10 +116,10 @@ T *MyPoolChunk<T>::get(int &index) {
ndatum += maxchunk;
nchunk++;
index = freehead[ibin];
int ipage = index/chunkperpage;
int ipage = index / chunkperpage;
int ientry = index % chunkperpage;
freehead[ibin] = freelist[index];
return &pages[ipage][ientry*chunksize[ibin]];
return &pages[ipage][ientry * chunksize[ibin]];
}
/** Return pointer/index of unused chunk of size N
@ -128,15 +128,15 @@ T *MyPoolChunk<T>::get(int &index) {
* \param index Index of chunk in memory pool
* \return Pointer to requested chunk of storage */
template <class T>
T *MyPoolChunk<T>::get(int n, int &index) {
template <class T> T *MyPoolChunk<T>::get(int n, int &index)
{
if (n < minchunk || n > maxchunk) {
errorflag = 3;
index = -1;
return nullptr;
}
int ibin = (n-minchunk) / binsize;
int ibin = (n - minchunk) / binsize;
if (freehead[ibin] < 0) {
allocate(ibin);
if (errorflag) {
@ -148,35 +148,34 @@ T *MyPoolChunk<T>::get(int n, int &index) {
ndatum += n;
nchunk++;
index = freehead[ibin];
int ipage = index/chunkperpage;
int ipage = index / chunkperpage;
int ientry = index % chunkperpage;
freehead[ibin] = freelist[index];
return &pages[ipage][ientry*chunksize[ibin]];
return &pages[ipage][ientry * chunksize[ibin]];
}
/** Put indexed chunk back into memory pool via free list
*
* \param index Memory chunk index returned by call to get() */
template <class T>
void MyPoolChunk<T>::put(int index) {
if (index < 0) return;
int ipage = index/chunkperpage;
int ibin = whichbin[ipage];
nchunk--;
ndatum -= chunksize[ibin];
freelist[index] = freehead[ibin];
freehead[ibin] = index;
}
template <class T> void MyPoolChunk<T>::put(int index)
{
if (index < 0) return;
int ipage = index / chunkperpage;
int ibin = whichbin[ipage];
nchunk--;
ndatum -= chunksize[ibin];
freelist[index] = freehead[ibin];
freehead[ibin] = index;
}
template <class T>
void MyPoolChunk<T>::allocate(int ibin) {
template <class T> void MyPoolChunk<T>::allocate(int ibin)
{
int oldpage = npage;
npage += pagedelta;
freelist = (int *) realloc(freelist,sizeof(int)*npage*chunkperpage);
pages = (T **) realloc(pages,sizeof(T *)*npage);
whichbin = (int *) realloc(whichbin,sizeof(int)*npage);
freelist = (int *) realloc(freelist, sizeof(int) * npage * chunkperpage);
pages = (T **) realloc(pages, sizeof(T *) * npage);
whichbin = (int *) realloc(whichbin, sizeof(int) * npage);
if (!freelist || !pages) {
errorflag = 2;
return;
@ -188,34 +187,32 @@ void MyPoolChunk<T>::allocate(int ibin) {
whichbin[i] = ibin;
#if defined(LAMMPS_MEMALIGN)
void *ptr;
if (posix_memalign(&ptr, LAMMPS_MEMALIGN,
sizeof(T)*chunkperpage*chunksize[ibin]))
if (posix_memalign(&ptr, LAMMPS_MEMALIGN, sizeof(T) * chunkperpage * chunksize[ibin]))
errorflag = 2;
pages[i] = (T *) ptr;
#else
pages[i] = (T *) malloc(sizeof(T)*chunkperpage*chunksize[ibin]);
pages[i] = (T *) malloc(sizeof(T) * chunkperpage * chunksize[ibin]);
if (!pages[i]) errorflag = 2;
#endif
}
// reset free list for unused chunks on new pages
freehead[ibin] = oldpage*chunkperpage;
for (int i = freehead[ibin]; i < npage*chunkperpage; i++) freelist[i] = i+1;
freelist[npage*chunkperpage-1] = -1;
freehead[ibin] = oldpage * chunkperpage;
for (int i = freehead[ibin]; i < npage * chunkperpage; i++) freelist[i] = i + 1;
freelist[npage * chunkperpage - 1] = -1;
}
/** Return total size of allocated pages
*
* \return total storage used in bytes */
template <class T>
double MyPoolChunk<T>::size() const {
double bytes = (double)npage*chunkperpage*sizeof(int);
bytes += (double)npage*sizeof(T *);
bytes += (double)npage*sizeof(int);
for (int i=0; i < npage; ++i)
bytes += (double)chunkperpage*chunksize[i]*sizeof(T);
template <class T> double MyPoolChunk<T>::size() const
{
double bytes = (double) npage * chunkperpage * sizeof(int);
bytes += (double) npage * sizeof(T *);
bytes += (double) npage * sizeof(int);
for (int i = 0; i < npage; ++i) bytes += (double) chunkperpage * chunksize[i] * sizeof(T);
return bytes;
}
@ -223,6 +220,6 @@ double MyPoolChunk<T>::size() const {
// explicit instantiations
namespace LAMMPS_NS {
template class MyPoolChunk<int>;
template class MyPoolChunk<double>;
}
template class MyPoolChunk<int>;
template class MyPoolChunk<double>;
} // namespace LAMMPS_NS

View File

@ -365,10 +365,10 @@ void Neighbor::init()
int icollection, jcollection;
// If collections not yet defined, create default map using types
if (not custom_collection_flag) {
if (!custom_collection_flag) {
ncollections = n;
interval_collection_flag = 0;
if (not type2collection)
if (!type2collection)
memory->create(type2collection,n+1,"neigh:type2collection");
for (i = 1; i <= n; i++)
type2collection[i] = i-1;
@ -390,7 +390,7 @@ void Neighbor::init()
for (j = 0; j < ncollections; j++)
cutcollectionsq[i][j] = 0.0;
if (not interval_collection_flag) {
if (!interval_collection_flag) {
finite_cut_flag = 0;
for (i = 1; i <= n; i++){
icollection = type2collection[i];
@ -419,7 +419,7 @@ void Neighbor::init()
finite_cut_flag = 0;
// Map types to collections
if (not type2collection)
if (!type2collection)
memory->create(type2collection,n+1,"neigh:type2collection");
for (i = 1; i <= n; i++)
@ -2557,7 +2557,7 @@ void Neighbor::modify_params(int narg, char **arg)
comm->ncollections_cutoff = 0;
interval_collection_flag = 0;
custom_collection_flag = 1;
if (not type2collection)
if (!type2collection)
memory->create(type2collection,ntypes+1,"neigh:type2collection");
// Erase previous mapping

View File

@ -173,7 +173,7 @@ void TextFileReader::next_dvector(double *list, int n)
}
ValueTokenizer values(line);
while (values.has_next()) { list[i++] = values.next_double(); }
while (values.has_next() && i < n) { list[i++] = values.next_double(); }
}
}

View File

@ -415,14 +415,14 @@ bigint Thermo::lost_check()
error->all(FLERR,"Too many total atoms");
// print notification, if future warnings will be ignored
int maxwarn = error->get_maxwarn();
bigint maxwarn = error->get_maxwarn();
if ((maxwarn > 0) && (warnbefore == 0) && (ntotal[1] > maxwarn)) {
warnbefore = 1;
if (comm->me == 0)
error->message(FLERR,"WARNING: Too many warnings: {} vs {}. All "
"future warnings will be suppressed",ntotal[1],maxwarn);
}
error->set_allwarn(ntotal[1]);
error->set_allwarn(MIN(MAXSMALLINT,ntotal[1]));
// no lost atoms, nothing else to do.
if (ntotal[0] == atom->natoms) return ntotal[0];

View File

@ -21,6 +21,9 @@
#include <cstring>
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <cstdint>
#else

View File

@ -32,6 +32,21 @@
#include <unistd.h> // for readlink
#endif
#if defined(__APPLE__)
#include <fcntl.h> // for fcntl
#include <sys/syslimits.h>
#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 <io.h>
#include <windows.h>
#endif
/*! \file utils.cpp */
/*
@ -149,6 +164,9 @@ std::string utils::getsyserror()
/** 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.
@ -162,6 +180,20 @@ const char *utils::guesspath(char *buf, int len, FILE *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
@ -1284,6 +1316,30 @@ int utils::date2num(const std::string &date)
return num;
}
/* binary search in vector of ascending doubles */
int utils::binary_search(const double needle, const int n, const double *haystack)
{
int lo = 0;
int hi = n - 1;
if (needle < haystack[lo]) return lo;
if (needle >= haystack[hi]) return hi;
// insure haystack[lo] <= needle < haystack[hi] at every iteration
// done when lo,hi are adjacent
int index = (lo + hi) / 2;
while (lo < hi - 1) {
if (needle < haystack[index])
hi = index;
else if (needle >= haystack[index])
lo = index;
index = (lo + hi) / 2;
}
return index;
}
/* ----------------------------------------------------------------------
* Merge sort part 1: Loop over sublists doubling in size with each iteration.
* Pre-sort small sublists with insertion sort for better overall performance.
@ -1412,26 +1468,26 @@ static int re_matchp(const char *text, re_t pattern, int *matchlen);
#define MAX_CHAR_CLASS_LEN 40 /* Max length of character-class buffer in. */
enum {
UNUSED,
DOT,
BEGIN,
END,
QUESTIONMARK,
STAR,
PLUS,
CHAR,
CHAR_CLASS,
INV_CHAR_CLASS,
DIGIT,
NOT_DIGIT,
INTEGER,
NOT_INTEGER,
FLOAT,
NOT_FLOAT,
ALPHA,
NOT_ALPHA,
WHITESPACE,
NOT_WHITESPACE /*, BRANCH */
RX_UNUSED,
RX_DOT,
RX_BEGIN,
RX_END,
RX_QUESTIONMARK,
RX_STAR,
RX_PLUS,
RX_CHAR,
RX_CHAR_CLASS,
RX_INV_CHAR_CLASS,
RX_DIGIT,
RX_NOT_DIGIT,
RX_INTEGER,
RX_NOT_INTEGER,
RX_FLOAT,
RX_NOT_FLOAT,
RX_ALPHA,
RX_NOT_ALPHA,
RX_WHITESPACE,
RX_NOT_WHITESPACE /*, BRANCH */
};
typedef struct regex_t {
@ -1483,7 +1539,7 @@ int re_matchp(const char *text, re_t pattern, int *matchlen)
{
*matchlen = 0;
if (pattern != 0) {
if (pattern[0].type == BEGIN) {
if (pattern[0].type == RX_BEGIN) {
return ((matchpattern(&pattern[1], text, matchlen)) ? 0 : -1);
} else {
int idx = -1;
@ -1518,22 +1574,22 @@ re_t re_compile(re_ctx_t context, const char *pattern)
switch (c) {
/* Meta-characters: */
case '^': {
re_compiled[j].type = BEGIN;
re_compiled[j].type = RX_BEGIN;
} break;
case '$': {
re_compiled[j].type = END;
re_compiled[j].type = RX_END;
} break;
case '.': {
re_compiled[j].type = DOT;
re_compiled[j].type = RX_DOT;
} break;
case '*': {
re_compiled[j].type = STAR;
re_compiled[j].type = RX_STAR;
} break;
case '+': {
re_compiled[j].type = PLUS;
re_compiled[j].type = RX_PLUS;
} break;
case '?': {
re_compiled[j].type = QUESTIONMARK;
re_compiled[j].type = RX_QUESTIONMARK;
} break;
/* Escaped character-classes (\s \w ...): */
@ -1545,39 +1601,39 @@ re_t re_compile(re_ctx_t context, const char *pattern)
switch (pattern[i]) {
/* Meta-character: */
case 'd': {
re_compiled[j].type = DIGIT;
re_compiled[j].type = RX_DIGIT;
} break;
case 'D': {
re_compiled[j].type = NOT_DIGIT;
re_compiled[j].type = RX_NOT_DIGIT;
} break;
case 'i': {
re_compiled[j].type = INTEGER;
re_compiled[j].type = RX_INTEGER;
} break;
case 'I': {
re_compiled[j].type = NOT_INTEGER;
re_compiled[j].type = RX_NOT_INTEGER;
} break;
case 'f': {
re_compiled[j].type = FLOAT;
re_compiled[j].type = RX_FLOAT;
} break;
case 'F': {
re_compiled[j].type = NOT_FLOAT;
re_compiled[j].type = RX_NOT_FLOAT;
} break;
case 'w': {
re_compiled[j].type = ALPHA;
re_compiled[j].type = RX_ALPHA;
} break;
case 'W': {
re_compiled[j].type = NOT_ALPHA;
re_compiled[j].type = RX_NOT_ALPHA;
} break;
case 's': {
re_compiled[j].type = WHITESPACE;
re_compiled[j].type = RX_WHITESPACE;
} break;
case 'S': {
re_compiled[j].type = NOT_WHITESPACE;
re_compiled[j].type = RX_NOT_WHITESPACE;
} break;
/* Escaped character, e.g. '.' or '$' */
default: {
re_compiled[j].type = CHAR;
re_compiled[j].type = RX_CHAR;
re_compiled[j].u.ch = pattern[i];
} break;
}
@ -1592,14 +1648,14 @@ re_t re_compile(re_ctx_t context, const char *pattern)
/* Look-ahead to determine if negated */
if (pattern[i + 1] == '^') {
re_compiled[j].type = INV_CHAR_CLASS;
re_compiled[j].type = RX_INV_CHAR_CLASS;
i += 1; /* Increment i to avoid including '^' in the char-buffer */
if (pattern[i + 1] == 0) /* incomplete pattern, missing non-zero char after '^' */
{
return 0;
}
} else {
re_compiled[j].type = CHAR_CLASS;
re_compiled[j].type = RX_CHAR_CLASS;
}
/* Copy characters inside [..] to buffer */
@ -1628,7 +1684,7 @@ re_t re_compile(re_ctx_t context, const char *pattern)
/* Other characters: */
default: {
re_compiled[j].type = CHAR;
re_compiled[j].type = RX_CHAR;
re_compiled[j].u.ch = c;
} break;
}
@ -1639,8 +1695,8 @@ re_t re_compile(re_ctx_t context, const char *pattern)
i += 1;
j += 1;
}
/* 'UNUSED' is a sentinel used to indicate end-of-pattern */
re_compiled[j].type = UNUSED;
/* 'RX_UNUSED' is a sentinel used to indicate end-of-pattern */
re_compiled[j].type = RX_UNUSED;
return (re_t) re_compiled;
}
@ -1753,31 +1809,31 @@ static int matchcharclass(char c, const char *str)
static int matchone(regex_t p, char c)
{
switch (p.type) {
case DOT:
case RX_DOT:
return matchdot(c);
case CHAR_CLASS:
case RX_CHAR_CLASS:
return matchcharclass(c, (const char *) p.u.ccl);
case INV_CHAR_CLASS:
case RX_INV_CHAR_CLASS:
return !matchcharclass(c, (const char *) p.u.ccl);
case DIGIT:
case RX_DIGIT:
return matchdigit(c);
case NOT_DIGIT:
case RX_NOT_DIGIT:
return !matchdigit(c);
case INTEGER:
case RX_INTEGER:
return matchint(c);
case NOT_INTEGER:
case RX_NOT_INTEGER:
return !matchint(c);
case FLOAT:
case RX_FLOAT:
return matchfloat(c);
case NOT_FLOAT:
case RX_NOT_FLOAT:
return !matchfloat(c);
case ALPHA:
case RX_ALPHA:
return matchalphanum(c);
case NOT_ALPHA:
case RX_NOT_ALPHA:
return !matchalphanum(c);
case WHITESPACE:
case RX_WHITESPACE:
return matchwhitespace(c);
case NOT_WHITESPACE:
case RX_NOT_WHITESPACE:
return !matchwhitespace(c);
default:
return (p.u.ch == c);
@ -1817,7 +1873,7 @@ static int matchplus(regex_t p, regex_t *pattern, const char *text, int *matchle
static int matchquestion(regex_t p, regex_t *pattern, const char *text, int *matchlen)
{
if (p.type == UNUSED) return 1;
if (p.type == RX_UNUSED) return 1;
if (matchpattern(pattern, text, matchlen)) return 1;
if (*text && matchone(p, *text++)) {
if (matchpattern(pattern, text, matchlen)) {
@ -1833,13 +1889,13 @@ static int matchpattern(regex_t *pattern, const char *text, int *matchlen)
{
int pre = *matchlen;
do {
if ((pattern[0].type == UNUSED) || (pattern[1].type == QUESTIONMARK)) {
if ((pattern[0].type == RX_UNUSED) || (pattern[1].type == RX_QUESTIONMARK)) {
return matchquestion(pattern[0], &pattern[2], text, matchlen);
} else if (pattern[1].type == STAR) {
} else if (pattern[1].type == RX_STAR) {
return matchstar(pattern[0], &pattern[2], text, matchlen);
} else if (pattern[1].type == PLUS) {
} else if (pattern[1].type == RX_PLUS) {
return matchplus(pattern[0], &pattern[2], text, matchlen);
} else if ((pattern[0].type == END) && pattern[1].type == UNUSED) {
} else if ((pattern[0].type == RX_END) && pattern[1].type == RX_UNUSED) {
return (text[0] == '\0');
}
(*matchlen)++;

View File

@ -408,7 +408,7 @@ namespace utils {
/*! Try to detect pathname from FILE pointer.
*
* Currently only supported on Linux, otherwise will report "(unknown)".
* 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
@ -541,6 +541,23 @@ namespace utils {
int date2num(const std::string &date);
/*! Binary search in a vector of ascending doubles of length N
*
* If the value is smaller than the smallest value in the vector, 0 is returned.
* If the value is larger or equal than the largest value in the vector, N-1 is returned.
* Otherwise the index that satisfies the condition
*
* haystack[index] <= value < haystack[index+1]
*
* is returned, i.e. a value from 1 to N-2. Note that if there are tied values in the
* haystack, always the larger index is returned as only that satisfied the condition.
*
* \param needle search value for which are are looking for the closest index
* \param n size of the haystack array
* \param haystack array with data in ascending order.
* \return index of value in the haystack array smaller or equal to needle */
int binary_search(const double needle, const int n, const double *haystack);
/*! Custom merge sort implementation
*
* This function provides a custom upward hybrid merge sort

View File

@ -22,6 +22,7 @@
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <direct.h>
#include <io.h>
#include <windows.h>
#define chdir(x) _chdir(x)

View File

@ -65,7 +65,7 @@ TEST_F(LibraryProperties, memory_usage)
#if defined(__linux__) || defined(_WIN32)
EXPECT_GE(meminfo[1], 0.0);
#endif
#if !defined(__INTEL_LLVM_COMPILER)
#if (defined(__linux__) || defined(__APPLE__) || defined(_WIN32)) && !defined(__INTEL_LLVM_COMPILER)
EXPECT_GT(meminfo[2], 0.0);
#endif
};

View File

@ -117,6 +117,9 @@ endforeach()
# tester for timestepping fixes
add_executable(test_fix_timestep test_fix_timestep.cpp)
if(NOT BUILD_SHARED_LIBS)
target_compile_definitions(test_fix_timestep PRIVATE USING_STATIC_LIBS=1)
endif()
target_link_libraries(test_fix_timestep PRIVATE lammps style_tests)
# tests for timestep related fixes (time integration, thermostat, force manipulation, constraints/restraints)

View File

@ -255,6 +255,9 @@ TEST(FixTimestep, plain)
{
if (!LAMMPS::is_installed_pkg("MOLECULE")) GTEST_SKIP();
if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP();
#if defined(USING_STATIC_LIBS)
if (test_config.skip_tests.count("static")) GTEST_SKIP();
#endif
const char *args[] = {"FixTimestep", "-log", "none", "-echo", "screen", "-nocite"};
@ -703,6 +706,9 @@ TEST(FixTimestep, omp)
if (!LAMMPS::is_installed_pkg("OPENMP")) GTEST_SKIP();
if (!LAMMPS::is_installed_pkg("MOLECULE")) GTEST_SKIP();
if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP();
#if defined(USING_STATIC_LIBS)
if (test_config.skip_tests.count("static")) GTEST_SKIP();
#endif
const char *args[] = {"FixTimestep", "-log", "none", "-echo", "screen", "-nocite",
"-pk", "omp", "4", "-sf", "omp"};

View File

@ -1,7 +1,7 @@
---
lammps_version: 30 Jul 2021
date_generated: Mon Aug 23 20:32:03 2021
epsilon: 2e-11
epsilon: 2e-10
skip_tests:
prerequisites: ! |
pair reaxff

View File

@ -1,7 +1,7 @@
---
lammps_version: 30 Jul 2021
date_generated: Mon Aug 23 20:32:03 2021
epsilon: 3e-12
epsilon: 4e-12
skip_tests:
prerequisites: ! |
pair reaxff

View File

@ -1,6 +1,7 @@
---
lammps_version: 10 Mar 2021
date_generated: Wed Mar 24 18:57:26 202
date_generated: Wed Mar 24 18:57:26 2021
skip_tests: static
epsilon: 9e-12
prerequisites: ! |
atom full

View File

@ -1,7 +1,7 @@
---
lammps_version: 30 Jul 2021
date_generated: Tue Aug 24 15:36:39 2021
epsilon: 2e-13
epsilon: 7.5e-11
skip_tests: single
prerequisites: ! |
pair drip

View File

@ -1,7 +1,7 @@
---
lammps_version: 30 Jul 2021
date_generated: Tue Aug 24 15:36:41 2021
epsilon: 5e-13
epsilon: 2e-10
skip_tests: single
prerequisites: ! |
pair drip

View File

@ -1,7 +1,7 @@
---
lammps_version: 30 Jul 2021
date_generated: Wed Aug 25 07:37:07 2021
epsilon: 1e-13
epsilon: 2e-12
skip_tests: single
prerequisites: ! |
pair lebedeva/z

View File

@ -26,7 +26,7 @@ target_compile_definitions(test_python_package PRIVATE -DTEST_INPUT_FOLDER=${TES
# this requires CMake 3.12. don't care to add backward compatibility for this.
if(Python3_Development_FOUND)
target_compile_definitions(test_python_package PRIVATE -DTEST_HAVE_PYTHON_DEVELOPMENT=1)
target_link_libraries(test_python_package PRIVATE Python::Python)
target_link_libraries(test_python_package PRIVATE Python3::Python)
endif()
add_test(NAME PythonPackage COMMAND test_python_package WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set_tests_properties(PythonPackage PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR};PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${LAMMPS_PYTHON_DIR}:$ENV{PYTHONPATH};PYTHONUNBUFFERED=1")

View File

@ -722,7 +722,7 @@ TEST(Utils, guesspath)
{
char buf[256];
FILE *fp = fopen("test_guesspath.txt", "w");
#if defined(__linux__)
#if defined(__linux__) || defined(__APPLE__) || defined(_WIN32)
const char *path = utils::guesspath(buf, sizeof(buf), fp);
ASSERT_THAT(path, EndsWith("test_guesspath.txt"));
#else
@ -875,6 +875,24 @@ TEST(Utils, date2num)
ASSERT_EQ(utils::date2num("31December100"), 1001231);
}
TEST(Utils, binary_search)
{
double data[] = {-2.0, -1.8, -1.0, -1.0, -1.0, -0.5, -0.2, 0.0, 0.1, 0.1,
0.2, 0.3, 0.5, 0.5, 0.6, 0.7, 1.0, 1.2, 1.5, 2.0};
const int n = sizeof(data) / sizeof(double);
ASSERT_EQ(utils::binary_search(-5.0, n, data), 0);
ASSERT_EQ(utils::binary_search(-2.0, n, data), 0);
ASSERT_EQ(utils::binary_search(-1.9, n, data), 0);
ASSERT_EQ(utils::binary_search(-1.0, n, data), 4);
ASSERT_EQ(utils::binary_search(0.0, n, data), 7);
ASSERT_EQ(utils::binary_search(0.1, n, data), 9);
ASSERT_EQ(utils::binary_search(0.4, n, data), 11);
ASSERT_EQ(utils::binary_search(1.1, n, data), 16);
ASSERT_EQ(utils::binary_search(1.5, n, data), 18);
ASSERT_EQ(utils::binary_search(2.0, n, data), 19);
ASSERT_EQ(utils::binary_search(2.5, n, data), 19);
}
static int compare(int a, int b, void *)
{
if (a < b)