diff --git a/CMakeLists.txt b/CMakeLists.txt index abc5740a2..cd3faa39d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,15 @@ option(SYSTEM_EIGEN3 "Use system's eigen3 library" OFF) option(SYSTEM_BOOST "Use system's boost library" OFF) #option(SYSTEM_PYBIND11 "Use system's pybind11 library" OFF) option(SYSTEM_XDRFILE "Use system's xdrfile" OFF) +option(BUILD_MMAP "Build command line interface and lammps binary interface. If OFF removes dependency over unix's mmap" ON) + +if (NOT PYTHON_INTERFACE AND NOT BUILD_MMAP) +message(FATAL_ERROR "Cannot set both PYTHON_INTERFACE and BUILD_MMAP to OFF: in this way I'm building nothing but thin air") +endif() + +if (NOT BUILD_MMAP AND BUILD_TESTS) +message(FATAL_ERROR "tests are implemented only if BUILD_MMAP is ON") +endif() include(CheckCXXCompilerFlag) include(CheckCCompilerFlag) @@ -117,30 +126,32 @@ set (XDR_FILE xdrfile) message(STATUS "using packaged xdrfile library") set (HAVE_XDRFILE 1) endif() +set (MMAP_LIB + lib/src/readlog.cpp + lib/src/testtraiettoria.cpp + lib/src/traiettoria.cpp + lib/src/greenkubo2componentionicfluid.cpp + lib/src/posizioniequilibrio.cpp + lib/src/chargefluxts.cpp + ) set (ANALISI_LIB + lib/src/mp.cpp lib/src/calcoliblocchi.cpp - lib/src/chargefluxts.cpp lib/src/convertibinario.cpp lib/src/convolution.cpp lib/src/correlatorespaziale.cpp lib/src/cronometro.C lib/src/doubleround.cpp lib/src/gofrt.cpp - lib/src/greenkubo2componentionicfluid.cpp lib/src/greenkuboNcomponentionicfluid.cpp lib/src/heatfluxts.cpp lib/src/interpolator.cpp lib/src/istogrammaatomiraggio.cpp lib/src/istogrammavelocita.cpp lib/src/modivibrazionali.cpp - lib/src/mp.cpp lib/src/msd.cpp - lib/src/posizioniequilibrio.cpp - lib/src/readlog.cpp lib/src/rnd.c lib/src/spettrovibrazionale.cpp - lib/src/testtraiettoria.cpp - lib/src/traiettoria.cpp lib/src/heatc.cpp lib/src/calcolamultithread.cpp lib/src/centerdiff.cpp @@ -150,6 +161,9 @@ set (ANALISI_LIB lib/src/atomicdensity.cpp ) +if (BUILD_MMAP) +set (ANALISI_LIB ${ANALISI_LIB} ${MMAP_LIB} ) +endif() if(PYTHON_INTERFACE) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/pybind11/tools") @@ -179,11 +193,12 @@ set_property(TARGET ${PROJECT_NAME}_lib PROPERTY POSITION_INDEPENDENT_CODE ON) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) target_link_libraries(${PROJECT_NAME}_lib PUBLIC Threads::Threads) +if (BUILD_MMAP) add_executable(${PROJECT_NAME} analisi/main.cpp ) target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib) - +endif() ## test suite if (BUILD_TESTS) @@ -243,8 +258,9 @@ else() set (FFTW_MT "" ) endif() - +if (BUILD_MMAP) target_link_libraries(${PROJECT_NAME} boost_program_options "${FFTW}" "${FFTW_MT}" "${XDR_FILE}") +endif() target_link_libraries(${PROJECT_NAME}_lib "${FFTW}" "${FFTW_MT}" "${XDR_FILE}") add_definitions(-DANALISI -DDEBUG) #add_definitions(-DANALISI) diff --git a/README_.md b/README_.md index 5d22e09d7..8f8cc3139 100644 --- a/README_.md +++ b/README_.md @@ -54,6 +54,9 @@ import numpy as np pos = np.load( 'tests/data/positions.npy') vel = np.load( 'tests/data/velocities.npy') box = np.load( 'tests/data/cells.npy') +#atomic types: load an array with length equal to the number of atoms +#in this example I set all the atoms to type 0 but the last 16, +#wich are 8 of type 1 and 8 of type 2 types = np.zeros(pos.shape[1], dtype = np.int32) types[-16:-8]=1 types[-8:]=2 @@ -62,13 +65,23 @@ print('first cell matrix is {}'.format(box[0])) #create trajectory object import pyanalisi -analisi_traj = pyanalisi.Trajectory(pos, vel, types, box,True, False) +analisi_traj = pyanalisi.Trajectory( + pos, #shape (ntimesteps, natoms, 3) + vel, #same shape as pos + types, #shape (natoms) + box, #shape (ntimesteps, 3,3) or (ntimesteps, 6) + True, # if True, box for a single frame is 3,3, + # if False is 6 + False # don't apply pbc + ) #do the calculation that you want +#see MSD section msd=pyanalisi.MeanSquareDisplacement(analisi_traj,10,4000,4,True,False,False) msd.reset(3000) msd.calculate(0) +#the calculation object can be used as an array result=np.array(msd,copy=False) @@ -81,17 +94,22 @@ result=np.array(msd,copy=False) Heat transport coefficient calculation: correlation functions and gk integral for a multicomponent fluid example ``` import numpy as np +#read first line, that is an header, and the column formatted data file with open(filepath_tests + '/data/gk_integral.dat', 'r') as flog: headers = flog.readline().split() log = np.loadtxt(filepath_tests + '/data/gk_integral.dat', skiprows=1) import pyanalisi +#wrapper for the pyanalisi interface traj = pyanalisi.ReadLog(log, headers) +#see Green Kubo section gk = pyanalisi.GreenKubo(analisi_log,'', 1,['c_flux[1]','c_vcm[1][1]'], False, 2000, 2,False,0,4,False,1,100) gk.reset(analisi_log.getNtimesteps()-2000) gk.calculate(0) + +#the calculation object can be used as a python array result = np.array(gk,copy=False) ``` @@ -105,19 +123,21 @@ If you use this program and you like it, spread the word around and give it cred This is a framework for computing averages on molecular dynamics trajectories and block averages. An mpi parallelization over the blocks is implemented in a very abstract and general way, so it is easy to implement a new calculation that can be parallelized with no effort using MPI. The code has two interfaces: a command line interface that is parallelized with MPI and threads, and a python interface that is parallelized on threads only. With such many parallelization levels more accurate averages can be performed, as described in details in the next sections. +Every MPI processes uses the same amount of memory by loading the part of the trajectory that it is used to do the calculation in every block. For this reason it is suggested to use one MPI process per machine, and parallelize by using threads only inside the single machine. + Features: - python interface (reads numpy array) - command line interface (reads binary lammps-like files or time series in column format) - multithreaded ( defaults to number of threads specifies by the shell variable OMP_NUM_THREADS ) - - command line interface has MPI too (for super-heavy calculations) + - command line interface has MPI too (for super-heavy multi-machine calculations) - command line calculates variance of every quantity and every function (in python you can do it by yourselves with numpy.var ) - jupyter notebook example of the python interface Calculations: - g of r ( and time too!) -- vibrational spectrum (this is nothing special) +- vibrational spectrum with FFTW3 - histogram of number of neighbours - mean square displacement - green kubo integral of currents @@ -132,7 +152,7 @@ Dependencies: - C++17 compatible compiler (GCC 7+, clang 6+, intel 19.0.1+, [source](https://en.cppreference.com/w/cpp/compiler_support) ) - cmake -- linux or macOS (mmap - maybe this dependency can be removed with some additional work) +- linux or macOS (mmap - maybe this dependency can be removed with some additional work, and it is not used in the python interface) - FFTW3 (included in the package) - Eigen3 (included in the package) - Boost (included in the package) diff --git a/config.h.in b/config.h.in index 38b2cdd24..cb66801ab 100644 --- a/config.h.in +++ b/config.h.in @@ -14,6 +14,7 @@ #define CONFIG_H #cmakedefine PYTHON_SUPPORT "${PYTHON_SUPPORT}" +#cmakedefine BUILD_MMAP "${BUILD_MMAP}" #cmakedefine HAVEfftw3 ${HAVEfftw3} #cmakedefine HAVEfftw ${HAVEfftw} #cmakedefine HAVEeigen3EigenDense ${HAVEeigen3EigenDense} @@ -52,7 +53,7 @@ const static char * _info_msg= #ifdef XDR_FILE "\nWith gromacs XDR file conversion support" #endif -"\nv0.3.1" +"\nv0.3.2" ; diff --git a/lib/include/lammps_struct.h b/lib/include/lammps_struct.h index 5c3aff186..43a90253b 100644 --- a/lib/include/lammps_struct.h +++ b/lib/include/lammps_struct.h @@ -12,6 +12,7 @@ #include #include #include +#include #ifndef LAMMPS_STRUCT_H #define LAMMPS_STRUCT_H @@ -45,6 +46,15 @@ struct Intestazione_timestep { file=read_and_advance(file,&nchunk); return file; } + void write(std::ofstream & out) { + out.write((char*) ×tep, sizeof (bigint)); + out.write((char*) &natoms, sizeof(bigint)); + out.write((char*) &triclinic, sizeof(int)); + out.write((char*) condizioni_al_contorno, sizeof(int)*6); + out.write((char*) scatola, sizeof(double)*6); + out.write((char*)&dimensioni_riga_output, sizeof(int)); + out.write((char*)&nchunk, sizeof(int)); + } static int get_triclinic(char * file) { int triclinic; read_and_advance(file+sizeof (timestep)+sizeof (natoms),&triclinic); @@ -197,7 +207,7 @@ class TimestepManager { throw std::runtime_error("Error: end of file reached"); } if (dimensioni_riga_output() != NDOUBLE_ATOMO) { - throw std::runtime_error("ERROR: the binary format does not have "+std::to_string(NDOUBLE_ATOMO)+" numbers per atom"); + throw std::runtime_error("ERROR: the binary format does not have "+std::to_string(NDOUBLE_ATOMO)+" numbers per atom but it has "+ std::to_string(dimensioni_riga_output())); } return current_ptr-begin; } diff --git a/lib/src/atomicdensity.cpp b/lib/src/atomicdensity.cpp index 0326ca953..c60212aa6 100644 --- a/lib/src/atomicdensity.cpp +++ b/lib/src/atomicdensity.cpp @@ -66,8 +66,10 @@ std::vector AtomicDensity::get_stride() const { return {static_cast(sizeof (Hist))*static_cast(nbin[0]*nbin[1]*nbin[2]),static_cast(nbin[1]*nbin[2]*sizeof (Hist)),static_cast(nbin[2]*sizeof (Hist)),static_cast(sizeof (Hist))}; } +#ifdef BUILD_MMAP #include "traiettoria.h" template class AtomicDensity; +#endif #ifdef PYTHON_SUPPORT #include "traiettoria_numpy.h" diff --git a/lib/src/convertibinario.cpp b/lib/src/convertibinario.cpp index ecefafdc6..2052cd7e2 100644 --- a/lib/src/convertibinario.cpp +++ b/lib/src/convertibinario.cpp @@ -153,7 +153,7 @@ ConvertiBinario::ConvertiBinario(const std::string filein, const std::string fil head.nchunk=1; int n_data=head.natoms*NDOUBLE_ATOMO; //qui ho impostato l'intestazione, la scrivo - out.write((char*) &head,sizeof(Intestazione_timestep)); + head.write(out); out.write((char*) &n_data,sizeof(int)); //adesso devo scrivere tutte le righe, una dopo l'altra diff --git a/lib/src/gofrt.cpp b/lib/src/gofrt.cpp index dfcf3101d..48c279dda 100644 --- a/lib/src/gofrt.cpp +++ b/lib/src/gofrt.cpp @@ -165,7 +165,9 @@ template Gofrt & Gofrt::operator =(c return *this; } +#ifdef BUILD_MMAP template class Gofrt; +#endif #ifdef PYTHON_SUPPORT #include "traiettoria_numpy.h" template class Gofrt; diff --git a/lib/src/greenkuboNcomponentionicfluid.cpp b/lib/src/greenkuboNcomponentionicfluid.cpp index eb78ae386..4048c220d 100644 --- a/lib/src/greenkuboNcomponentionicfluid.cpp +++ b/lib/src/greenkuboNcomponentionicfluid.cpp @@ -420,10 +420,12 @@ template std::string GreenKuboNC +#ifdef BUILD_MMAP #include "readlog.h" template class GreenKuboNComponentIonicFluid, double,double>; template class GreenKuboNComponentIonicFluid, long double,double>; template class GreenKuboNComponentIonicFluid, long double,long double>; +#endif #ifdef PYTHON_SUPPORT #include "readlog_numpy.h" diff --git a/lib/src/msd.cpp b/lib/src/msd.cpp index 21f314c3e..60915d1ed 100644 --- a/lib/src/msd.cpp +++ b/lib/src/msd.cpp @@ -152,8 +152,10 @@ MSD & MSD::operator=(const MSD &destra) { return *this; } +#ifdef BUILD_MMAP template class MSD; template class MSD; +#endif #ifdef PYTHON_SUPPORT #include "traiettoria_numpy.h" template class MSD; diff --git a/lib/src/spettrovibrazionale.cpp b/lib/src/spettrovibrazionale.cpp index c289953cc..184e1c192 100644 --- a/lib/src/spettrovibrazionale.cpp +++ b/lib/src/spettrovibrazionale.cpp @@ -195,7 +195,10 @@ SpettroVibrazionale & SpettroVibrazionale::operator = (const SpettroVibraz return *this; } +#ifdef BUILD_MMAP template class SpettroVibrazionale; +#endif + #ifdef PYTHON_SUPPORT #include "traiettoria_numpy.h" template class SpettroVibrazionale; diff --git a/lib/src/sphericalcorrelations.cpp b/lib/src/sphericalcorrelations.cpp index bc5b24157..22c0c7eb0 100644 --- a/lib/src/sphericalcorrelations.cpp +++ b/lib/src/sphericalcorrelations.cpp @@ -305,7 +305,9 @@ void SphericalCorrelations::corr_sh_calc(const TFLOAT * sh1, cons } } +#ifdef BUILD_MMAP template class SphericalCorrelations<10,double,Traiettoria>; +#endif #ifdef PYTHON_SUPPORT #include "traiettoria_numpy.h" diff --git a/lib/src/traiettoria_numpy.cpp b/lib/src/traiettoria_numpy.cpp index d966968e9..03697f07e 100644 --- a/lib/src/traiettoria_numpy.cpp +++ b/lib/src/traiettoria_numpy.cpp @@ -172,7 +172,7 @@ Traiettoria_numpy::dump_lammps_bin_traj(const std::string &fname, int start_ts, head.nchunk=1; int n_data=head.natoms*head.dimensioni_riga_output; //write timestep header - out.write((char*) &head,sizeof(Intestazione_timestep)); + head.write(out); out.write((char*) &n_data,sizeof(int)); for (unsigned int iatom=0;iatom