├── .coveragerc ├── .gitignore ├── .travis.yml ├── CMakeLists.txt.in ├── COPYING ├── LICENSE ├── README.rst ├── cpp_tests ├── README ├── get_gtest.sh └── source │ ├── CMakeLists.txt │ ├── CMakeModules │ └── CodeCoverage.cmake │ ├── test_accept_tests.cpp │ ├── test_conf_tests.cpp │ ├── test_histogram.cpp │ ├── test_mc.cpp │ ├── test_pair_dist_histogram.cpp │ ├── test_takestep.cpp │ └── test_time_series.cpp ├── cythonize.py ├── dark_example_code.png ├── dark_example_run.png ├── diagram_fluid.png ├── doc ├── AcceptTest.rst ├── Action.rst ├── BaseMCRunner.rst ├── Base_MPI_Parallel_Tempering.rst ├── ConfTest.rst ├── MPI_Parallel_Tempering.rst ├── Makefile ├── TakeStep.rst ├── _static │ └── scipy.css ├── _templates │ └── autosummary │ │ ├── class.rst │ │ └── module.rst ├── conf.py ├── diagram_fluid.png ├── getting_started.rst ├── index.rst ├── monte_carlo.rst ├── parallel_tempering.rst └── sphinxext │ └── viewcode-new.py ├── examples ├── compute_pi │ └── compute_pi.py └── sfHS_WCA_fluid │ └── radial_distribution_function.py ├── mcpele ├── __init__.py ├── monte_carlo │ ├── __init__.py │ ├── _accept_test_cpp.pxd │ ├── _accept_test_cpp.pyx │ ├── _action_cpp.pxd │ ├── _action_cpp.pyx │ ├── _conf_test_cpp.pxd │ ├── _conf_test_cpp.pyx │ ├── _monte_carlo_cpp.pxd │ ├── _monte_carlo_cpp.pyx │ ├── _nullpotential_cpp.pyx │ ├── _pele_mc.pxd │ ├── _pele_mc.pyx │ ├── _takestep_cpp.pxd │ ├── _takestep_cpp.pyx │ ├── mcrunner.py │ └── tests │ │ ├── __init__.py │ │ ├── test_metropolis_mcrunner.py │ │ └── test_take_step_probability.py ├── parallel_tempering │ ├── __init__.py │ ├── _base_mpi_ptmc.py │ ├── mpi_ptmc.py │ └── tests │ │ ├── __init__.py │ │ ├── _test_run_mpi_ptmc.py │ │ └── test_run_mpi_ptmc.py └── utils │ ├── __init__.py │ └── _utils.py ├── setup.py ├── setup_with_cmake.py └── source ├── CODING_STYLE.rst ├── adaptive_takestep.cpp ├── check_spherical_container.cpp ├── conf_test_OR.cpp ├── energy_window_test.cpp ├── gaussian_coords_displacement.cpp ├── histogram.cpp ├── lowest_eigenvalue.cpp ├── mc.cpp ├── mcpele ├── adaptive_takestep.h ├── check_spherical_container.h ├── check_spherical_container_config.h ├── conf_test_OR.h ├── energy_window_test.h ├── gaussian_coords_displacement.h ├── histogram.h ├── lowest_eigenvalue.h ├── mc.h ├── metropolis_test.h ├── moving_average.h ├── nullpotential.h ├── pair_dist_histogram.h ├── particle_pair_swap.h ├── pattern_manager.h ├── progress.h ├── random_coords_displacement.h ├── record_coords_timeseries.h ├── record_displacement_per_particle_timeseries.h ├── record_energy_histogram.h ├── record_energy_timeseries.h ├── record_lowest_evalue_timeseries.h ├── record_pair_dist_histogram.h ├── record_scalar_timeseries.h ├── record_vector_timeseries.h ├── rsm_displacement.h ├── take_step_pattern.h ├── take_step_probabilities.h ├── uniform_rectangular_sampling.h └── uniform_spherical_sampling.h ├── metropolis_test.cpp ├── particle_pair_swap.cpp ├── random_coords_displacement.cpp ├── record_coords_timeseries.cpp ├── record_energy_histogram.cpp ├── record_scalar_timeseries.cpp ├── record_vector_timeseries.cpp ├── rsm_displacement.cpp ├── take_step_pattern.cpp └── take_step_probabilities.cpp /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | source = mcpele 4 | include = */mcpele/* 5 | [report] 6 | exclude_lines = 7 | pragma: no cover 8 | raise AssertionError 9 | raise NotImplementedError 10 | if __name__ == .__main__.: 11 | if False 12 | def draw.self 13 | def load_coords_pymol.self 14 | def show_histogram.self -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.cxx 3 | *.so 4 | *.pyc 5 | *.out 6 | *.log 7 | gtest*.zip 8 | build/ 9 | cpp_tests/build/ 10 | cpp_tests/gtest/ 11 | cythonize.dat 12 | CMakeLists.txt 13 | mcpele/version.py 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - 2.7 4 | 5 | env: 6 | - MPI=openmpi 7 | 8 | virtualenv: 9 | system_site_packages: true 10 | 11 | branches: 12 | only: 13 | - master 14 | 15 | before_install: 16 | # Use miniconda and conda packages to speed up dependency setup (principally 17 | # borrowed from https://gist.github.com/dan-blanchard/7045057 18 | # and https://github.com/Jorge-C/ordination/blob/master/.travis.yml 19 | - export LD_PRELOAD=$LD_PRELOAD:/usr/lib/x86_64-linux-gnu/libgfortran.so.3 20 | # The preceding line was added to solve an issue with travis where we 21 | # got errors like the following: 22 | # $ nosetests -v --with-coverage pele 23 | # Failure: ImportError (/home/travis/miniconda/envs/pelenv/bin/../lib/libgfortran.so.3: 24 | # version `GFORTRAN_1.4' not found (required by 25 | # /home/travis/miniconda/envs/pelenv/lib/python2.7/site-packages/ 26 | # pele/transition_states/_orthogoptf.so)) ... ERROR 27 | # It seems that the solution proposed in the link below fixes this: 28 | # http://code-saturne.org/forum/viewtopic.php?f=3&t=1687&sid=9912a7abac3b92c1b067fc495521ed7a&start=10 29 | - pwd 30 | - sudo apt-get update -qq 31 | - sudo apt-get install -qq libatlas-dev libatlas-base-dev liblapack-dev gfortran lcov 32 | - gem install coveralls-lcov 33 | - test $MPI == openmpi && MPIPACKAGES='openmpi-bin openmpi-dev' || true 34 | - sudo apt-get install -qq $MPIPACKAGES 35 | - wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh 36 | - chmod +x miniconda.sh 37 | - ./miniconda.sh -b -p $HOME/miniconda 38 | - export PATH="$HOME/miniconda/bin:$PATH" 39 | # Update conda itself 40 | - hash -r 41 | - conda config --set always_yes yes --set changeps1 no 42 | - conda update conda 43 | # Useful for debugging any issues with conda 44 | - conda info -a 45 | # matplotlib needs a DISPLAY 46 | - "export DISPLAY=:99.0" 47 | - "sh -e /etc/init.d/xvfb start" 48 | 49 | 50 | install: 51 | - conda create --yes -n pelenv python=$TRAVIS_PYTHON_VERSION nose pip cython numpy scipy matplotlib sqlalchemy networkx 52 | - source activate pelenv 53 | - pip install munkres hungarian pyro4 brewer2mpl coverage coveralls coveralls-merge mpi4py 54 | # download and install pele 55 | - pwd 56 | - cd $HOME/build/pele-python 57 | - git clone https://github.com/pele-python/pele.git 58 | - cd pele 59 | - python setup_with_cmake.py build_ext -i --fcompiler=gfortran 60 | - export PYTHONPATH="$PWD:$PYTHONPATH" 61 | # build and install mcpele 62 | - cd ../mcpele 63 | - python setup.py build --fcompiler=gfortran 64 | - python setup.py install 65 | - cp .coveragerc $HOME 66 | - pwd 67 | - sourcedir=$PWD 68 | # build the c++ tests 69 | - cd cpp_tests 70 | - cpp_test_dir=$PWD 71 | - ./get_gtest.sh 72 | - cppbuild=$PWD/build 73 | - mkdir $cppbuild && cd $cppbuild 74 | - cmake ../source -DCMAKE_BUILD_TYPE=Coverage 75 | - make 76 | 77 | script: 78 | # avoid running in the checkout directory so nose finds built modules.. 79 | - rundir=$HOME 80 | - cd $rundir 81 | - nosetests -v --with-coverage mcpele 82 | # do the c++ tests 83 | - cd $cppbuild 84 | - ./test_main 85 | 86 | after_success: 87 | # generate the cpp coverage report 88 | - cd $cppbuild 89 | - lcov --capture --directory . -b . --output-file coverage.info 90 | # Artificially change the directory of the c++ source files to the python 91 | # site-packages directory. This is purely so that it has the same root 92 | # directory as the python files so that the coveralls website can find the 93 | # source on github. This is an ugly hack, there must be a better way. 94 | - site_packages_dir=$(dirname `python -c "import mcpele; print mcpele.__file__"`) 95 | - site_packages_dir=$(readlink -f $site_packages_dir/..) # go one dir higher and clean up the dir name 96 | - sed -i "s=$sourcedir=$site_packages_dir=g" coverage.info 97 | # coverall-lcov requires the source files to exist, so copy them over 98 | - cp -r $sourcedir/source $site_packages_dir 99 | # remove unwanted directories from the coverage report 100 | - lcov --remove coverage.info 'tests/*' '/usr/*' '/pele/*' --output-file coverage.info.cleaned 101 | - coveralls-lcov -v -n coverage.info.cleaned > coverage.c.json 102 | # need to be in source directory to call coverage 103 | - cd $sourcedir # not sure if this is necessary 104 | - cp $rundir/.coverage . 105 | - coveralls-merge $cppbuild/coverage.c.json 106 | -------------------------------------------------------------------------------- /CMakeLists.txt.in: -------------------------------------------------------------------------------- 1 | # this file is mean to be parsed by python before being a proper CMakeLists.txt file 2 | # in particular, the following strings will be set by python 3 | set(numpy_include __NUMPY_INCLUDE__) 4 | set(PYTHON_INCLUDE_DIRS __PYTHON_INCLUDE__) 5 | set(PYTHON_LDFLAGS "__PYTHON_LDFLAGS__") 6 | set(pele_include __PELE_INCLUDE__) 7 | 8 | # osx makes the suffix for shared object libraries .dylib 9 | IF(APPLE) 10 | SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so") 11 | ENDIF(APPLE) 12 | 13 | message("python include dirs: ${PYTHON_INCLUDE_DIRS}") 14 | message("python ldflags: ${PYTHON_LDFLAGS}") 15 | message("numpy include dirs: ${numpy_include}") 16 | message("pele include dirs: ${pele_include}") 17 | include_directories(${numpy_include}) 18 | include_directories(${PYTHON_INCLUDE_DIRS}) 19 | include_directories(${pele_include}) 20 | # note: We set CMAKE_SHARED_LINKER_FLAGS because I couldn't get it to work using 21 | # target_link_librarires(). CMake kept interpreting the flag CoreFoundation 22 | # as a library and appending -l to it and the compiler would complain 23 | unset(CMAKE_SHARED_LINKER_FLAGS CACHE) 24 | set(CMAKE_SHARED_LINKER_FLAGS ${PYTHON_LDFLAGS} CACHE type string) 25 | 26 | cmake_minimum_required(VERSION 2.8) 27 | 28 | enable_language(CXX) 29 | SET(CMAKE_CXX_FLAGS __COMPILER_EXTRA_ARGS__) 30 | 31 | #cmake_policy(SET CMP0015 NEW) 32 | 33 | # set the mcpele include directory 34 | set(mcpele_include ${CMAKE_SOURCE_DIR}/source) 35 | include_directories(${mcpele_include}) 36 | message("mcpele include directory: ${mcpele_include}") 37 | 38 | # build the mcpele library 39 | FILE(GLOB pele_sources ${pele_include}/*.cpp) 40 | FILE(GLOB mcpele_sources ${mcpele_include}/*.cpp) 41 | add_library(mcpele_lib SHARED ${mcpele_sources} ${pele_sources}) 42 | 43 | function(make_cython_lib cython_cxx_source) 44 | get_filename_component(library_name ${cython_cxx_source} NAME) 45 | string(REGEX REPLACE ".cxx$" "" library_name ${library_name}) 46 | add_library(${library_name} SHARED ${cython_cxx_source}) 47 | target_link_libraries(${library_name} mcpele_lib) 48 | set_target_properties(${library_name} PROPERTIES PREFIX "") 49 | message("making library ${library_name} from source ${cython_cxx_source}") 50 | endfunction(make_cython_lib) 51 | 52 | 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | pele is free software: you can redistribute it and/or modify 2 | it under the terms of the GNU General Public License as published by 3 | the Free Software Foundation, either version 3 of the License, or 4 | (at your option) any later version. 5 | 6 | pele is distributed in the hope that it will be useful, 7 | but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | GNU General Public License for more details. 10 | 11 | You should have received a copy of the GNU General Public License 12 | along with pele. If not, see . 13 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. image:: https://travis-ci.org/pele-python/mcpele.svg?branch=master 2 | :target: https://travis-ci.org/pele-python/mcpele 3 | 4 | .. image:: https://coveralls.io/repos/pele-python/mcpele/badge.png?branch=master 5 | :target: https://coveralls.io/r/pele-python/mcpele?branch=master 6 | 7 | mcpele : Monte Carlo Python Energy Landscape Explorer 8 | +++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 | 10 | Flexible and efficient Monte Carlo general purpose framework 11 | and MPI/mpi4py based Replica Exchange Method, built on the `pele `_ 12 | foundations. mcpele provides a seamless integration of the 13 | tools for energy landscape exploration built in pele. 14 | The package also acts as a plugin for the `Nested Sampling `_ project. 15 | 16 | Through its c++ interface, mcpele makes Monte Carlo simulations available to 17 | researchers with little programming experience, without having to compromise 18 | on efficiency. Furthermore mcpele abstracts each element of a Monte Carlo 19 | simulation eliminating the need for frequent code rewriting that experienced 20 | Monte Carlo developers typically go through, thus reducing the time required for 21 | the implementation of an idea and reducing the occurrence of bugs. 22 | 23 | Source code: https://github.com/pele-python/mcpele 24 | 25 | Documentation: http://pele-python.github.io/mcpele/ 26 | 27 | .. figure:: diagram_fluid.png 28 | 29 | Figure 1: Diagramatic representation of the mcpele framework. On the right 30 | is a hard spheres fluid equilibrated by uniform sampling in a cubic box with 31 | periodic boundary conditions. 32 | 33 | mcpele is authored by Stefano Martiniani, Ken J Schrenk and Jacob Stevenson at the University of Cambridge. 34 | The project is publicly available under the GNU general public licence. 35 | 36 | Description 37 | =========== 38 | mcpele is a general purpose framework for Monte Carlo simulations that integrates 39 | the c/c++ backend of the `pele`_ project through a python interface, including a number 40 | of potential energy functions, cell lists for n-dimensional spaces with and without 41 | periodic boundary conditions, tools for energy minimization and structure alignment. 42 | 43 | Because mcpele is designed for large distributed parallel equilibrium simulations, it 44 | provides a MPI/mpi4py implementation of the Replica Exchange Method known as Parallel 45 | Tempering. 46 | 47 | Furthermore the library can act as a plug-in for the `Nested Sampling`_ project, 48 | since Monte Carlo walks need to be run at each iteration. 49 | 50 | All of mcpele runs in its c++ backend but the Monte Carlo routines are assembled 51 | through its Python interface. The basic abstract structure of mcpele is summarised 52 | by the diagram in figure 1 (refer to `Get started`_ for details). 53 | The following methods are already implemented in mcpele: 54 | 55 | - **TakeStep**: 56 | - *RandomCoordsDisplacement*: Uniform random coordinates displacement (single particle and global) 57 | - *GaussianCoordsDisplacement*: Gaussian random coordinates displacement (single particle and global) 58 | - *ParticlePairSwap*: swap pairs of particles 59 | - *TakeStepPattern*: combines multiple moves and executes them deterministically with some frequency 60 | - *TakeStepProbabilities*: combines multiple moves and executes them probabilistically with some frequency 61 | - **ConfTest**: 62 | - *CheckSphericalContainer*: checks that each particle is within some radius from the origin 63 | - **AcceptTest**: 64 | - *MetropolisTest*: metropolis acceptance criterion 65 | - *EnergyWindowTest*: accept if energy is within some window 66 | - **Action**: 67 | - *RecordEnergyHistogram*: stores entries in a resizable histogram and computes the moments of the distribution on the fly 68 | - *RecordPairDistHistogram*: records radial distribution function (accumulates each configuration into the same `g(r)` histogram) 69 | - *RecordEnergyTimeSeries*: records a time series of the energy 70 | - *RecordLowestEValueTimeSeries*: records a time series of the lowest eigenvalue from inherent structure 71 | - *RecordDisplacementPerParticleTimeSeries*: records mean square displacement for each particle 72 | 73 | Get started 74 | =========== 75 | 76 | Build your first MC runner class 77 | -------------------------------- 78 | 79 | .. figure:: dark_example_code.png 80 | 81 | The diagramatic representation in figure 1 summarises the abstract structure of mcpele. 82 | In mcpele we call a MCrunner those classes that can perform a Monte Carlo random walk. 83 | Each MCrunner derives from the abstract class _baseMCrunner that implements the basic 84 | abstract structure needed by every MCrunner, this takes by default a potential, initial coordinates, 85 | temperature (or equivalent control parameter) and the target number of iterations. Once the parent class is constructed all 86 | we need to do is to add to our new MCrunner class all the other components in the diagram 87 | of figure 1 that are missing. 88 | 89 | Let us assume that we would like to build a MCrunner to simulate 90 | particles with only translational degrees of freedom, such as Lennard-Jones atoms. 91 | First we would like to add a TakeStep method to our MCrunner to displace the coordinates 92 | of the system at each step, as required. The most simple type of displacement would be a 93 | random one, hence we choose the *RandomCoordsDisplacement* method that can perform both 94 | single particle and global moves. 95 | 96 | Then we would like our system to be within a spherical 97 | container, for instance to stop it from evaporating, and we add a configuration test, 98 | *CheckSphericalContainer*. Note that we distinguish between *early* and *late* configuration 99 | tests. Tipically configurations tests are cheaper than a potential energy call, hence we would 100 | like to run them before the *compute energy* step; sometimes, however, configuration 101 | tests can be more expensive than a potential call, hence we would rather run the test 102 | after the *accept tests*. 103 | 104 | The *accept tests* verify that the energy of the system after each step satisfies certain 105 | constraints. In this case we choose the *MetropolisTest* acceptance criterion. Finally 106 | we might want to record somme information during the run to compute some properties of 107 | the system. One common choice is to record a energy histogram and its associated moments 108 | (mean energy and variance). To do so we construct a *RecordEnergyHistogram* method. 109 | 110 | Finally we need to plug each of the constructed methods into the MCrunner and we do so 111 | by *adding* them. Note that after each iteration the loop *reports* back to the TakeStep 112 | routines to, for instance, adapt the stepsize. Since adaptive steps break the 113 | detailed balanance of the random walk we might want to reach some target acceptance within 114 | the first *adjustf_niter* steps and then keep the stepsize fixed and start recording 115 | the histogram. Hence we *set_report_steps* to indicate the number of steps for which 116 | the stepsize should be adapted. 117 | 118 | In the present example we only used one method for each element of a generic MCrunner, however 119 | one can combine multiple ones. *AcceptTests*, *ConfTests* and *Actions* can be added at will, simply 120 | *adding* them to the MCrunner in the desired order of execution (*order matters!*). 121 | *TakeSteps* can be combined through a *TakeStepPattern* class in a deterministic or 122 | a probabilistic sequence: at each iteration only one type of step is taken and *report* 123 | acts only on that particular step. For instance one might want to combine particles 124 | swaps with random translation but would like the swaps to occur only once every *1000* steps. 125 | Finally potentials can be combined through the `CombinedPotential `_ class. 126 | 127 | Run a Monte Carlo random walk 128 | ----------------------------- 129 | 130 | .. figure:: dark_example_run.png 131 | 132 | We have built our first MCrunner, so let us try running it. All it takes is loading some 133 | initial coordinates, constructing the potential we want to use, in this case the pele::Lennard-Jones 134 | potential, and then set parameters such as temperature, number of iterations, initial stepsize and a 135 | few more keyword arguments. Then we call the *run()* function and we get c++ performance 136 | from a few lines of a pure Python interface. Finally we might want to *show* or *dump* the histogram. 137 | 138 | INSTALLATION 139 | ============ 140 | 141 | Required packages 142 | ----------------- 143 | 144 | for compilation: 145 | 146 | 1. c++ compiler (must support c++11, GCC > 4.6 or similar) 147 | 148 | python packages: 149 | 150 | 1. numpy: 151 | We use numpy everywhere for doing numerical work. 152 | 153 | #. `pele`_: 154 | python energy landscape explorer for potential, minimizers etc. 155 | 156 | #. matplotlib: 157 | For making plots (e.g. histogram, time series, rdf etc.) 158 | 159 | #. mpi4py: 160 | for replica exchange Monte Carlo 161 | 162 | non-python packages: 163 | 164 | 1. cmake: optional 165 | to compile using cmake (much faster) 166 | 167 | All the above packages can be installed via the python package manager pip (or 168 | easy_install), with the exception of pele. However, some of the packages (numpy, scipy) 169 | have additional dependencies and it can be more convenient to use the linux package manager 170 | (apt, yum, ...). 171 | 172 | Tests 173 | ===== 174 | mcpele has a suite of unit tests. They can be run using the nose testing 175 | framework (which can be installed using pip). The tests are run from the top 176 | directory with this command:: 177 | 178 | nosetests mcpele 179 | -------------------------------------------------------------------------------- /cpp_tests/README: -------------------------------------------------------------------------------- 1 | get gtest 2 | --------- 3 | get gtest from googlecode.com 4 | 5 | wget https://googletest.googlecode.com/files/gtest-1.7.0.zip 6 | 7 | unzip it and put it in source/gtest 8 | 9 | unzip gtest-1.7.0.zip 10 | mv gtest-1.7.0 gtest 11 | 12 | build the tests 13 | 14 | mkdir build && cd build 15 | cmake ../source 16 | make -j8 17 | -------------------------------------------------------------------------------- /cpp_tests/get_gtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # this script downloads the gtest source code and puts it into the folder 3 | # source/gtest/ 4 | # The script is called by the travis build script .travis.yml 5 | gtest=gtest-1.7.0 6 | if [ ! -f $gtest.zip ]; then 7 | wget https://googletest.googlecode.com/files/$gtest.zip 8 | fi 9 | unzip $gtest.zip 10 | mv $gtest gtest 11 | -------------------------------------------------------------------------------- /cpp_tests/source/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | # if not specified by user, the standard build type is release 4 | if(NOT CMAKE_BUILD_TYPE) 5 | set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release Coverage." FORCE) 6 | endif(NOT CMAKE_BUILD_TYPE) 7 | 8 | enable_language(CXX) 9 | SET(CMAKE_CXX_FLAGS "-Wall -ansi -pedantic -std=c++0x -O3") 10 | 11 | #cmake_policy(SET CMP0015 NEW) 12 | 13 | # Add and compile the gtest library 14 | set(gtest_src ../gtest) 15 | set(gtest_binary_dir googletest) 16 | set(gtest_include ${gtest_src}/include/) 17 | include_directories(${gtest_include}) 18 | message("gtest include directory ${gtest_include}") 19 | add_subdirectory(../gtest ${gtest_binary_dir}) 20 | set(gtest_libs gtest gtest_main) 21 | message("gtest_libs ${gtest_libs}") 22 | 23 | # set the mcpele include directory 24 | set(mcpele_include ../../source) 25 | include_directories(${mcpele_include}) 26 | message("mcpele include directory ${mcpele_include}") 27 | 28 | # build the mcpele library 29 | FILE(GLOB mcpele_sources ${mcpele_include}/*.cpp) 30 | add_library(mcpele_lib ${mcpele_sources}) 31 | 32 | # set the pele include directory 33 | set(pele_include ../../../pele/source CACHE STRING "the pele c++ source directory") 34 | if (EXISTS ${pele_include}/pele/array.h) 35 | message("pele include directory: ${pele_include}") 36 | else() 37 | message(FATAL_ERROR "pele include directory is not correct: ${pele_include} : use ccmake to set it") 38 | endif() 39 | include_directories(${pele_include}) 40 | 41 | # build the pele library 42 | FILE(GLOB pele_sources ${pele_include}/*.cpp) 43 | add_library(pele_lib ${pele_sources}) 44 | 45 | # get all the source files 46 | FILE(GLOB sources *.cpp) 47 | 48 | add_executable(test_main ${sources}) 49 | target_link_libraries(test_main pele_lib mcpele_lib gtest gtest_main pthread) 50 | 51 | 52 | 53 | # Custom version of this function which came from CodeCoverage.cmake 54 | # It removes coverage information for the pele library. 55 | FUNCTION(SETUP_TARGET_FOR_COVERAGE_CUSTOM _targetname _testrunner _outputname) 56 | 57 | IF(NOT LCOV_PATH) 58 | MESSAGE(FATAL_ERROR "lcov not found! Aborting...") 59 | ENDIF() # NOT LCOV_PATH 60 | 61 | IF(NOT GENHTML_PATH) 62 | MESSAGE(FATAL_ERROR "genhtml not found! Aborting...") 63 | ENDIF() # NOT GENHTML_PATH 64 | 65 | # Setup target 66 | ADD_CUSTOM_TARGET(${_targetname} 67 | 68 | # Cleanup lcov 69 | ${LCOV_PATH} --directory . --zerocounters 70 | 71 | # Run tests 72 | COMMAND ${_testrunner} ${ARGV3} 73 | 74 | # Capturing lcov counters and generating report 75 | COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info 76 | COMMAND ${LCOV_PATH} --remove ${_outputname}.info 'tests/*' '/usr/*' '/pele/*' --output-file ${_outputname}.info.cleaned 77 | COMMAND ${GENHTML_PATH} -o ${_outputname} ${_outputname}.info.cleaned 78 | COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info ${_outputname}.info.cleaned 79 | 80 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 81 | COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." 82 | ) 83 | 84 | # Show info where to find the report 85 | ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD 86 | COMMAND ; 87 | COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report." 88 | ) 89 | 90 | ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_CUSTOM 91 | 92 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules) 93 | if(CMAKE_BUILD_TYPE STREQUAL "Coverage") 94 | include(CodeCoverage) 95 | setup_target_for_coverage_custom(mcpele_coverage test_main coverage) 96 | endif() 97 | -------------------------------------------------------------------------------- /cpp_tests/source/CMakeModules/CodeCoverage.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # 2012-01-31, Lars Bilke 3 | # - Enable Code Coverage 4 | # 5 | # 2013-09-17, Joakim Söderberg 6 | # - Added support for Clang. 7 | # - Some additional usage instructions. 8 | # 9 | # USAGE: 10 | 11 | # 0. (Mac only) If you use Xcode 5.1 make sure to patch geninfo as described here: 12 | # http://stackoverflow.com/a/22404544/80480 13 | # 14 | # 1. Copy this file into your cmake modules path. 15 | # 16 | # 2. Add the following line to your CMakeLists.txt: 17 | # INCLUDE(CodeCoverage) 18 | # 19 | # 3. Set compiler flags to turn off optimization and enable coverage: 20 | # SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") 21 | # SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") 22 | # 23 | # 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target 24 | # which runs your test executable and produces a lcov code coverage report: 25 | # Example: 26 | # SETUP_TARGET_FOR_COVERAGE( 27 | # my_coverage_target # Name for custom target. 28 | # test_driver # Name of the test driver executable that runs the tests. 29 | # # NOTE! This should always have a ZERO as exit code 30 | # # otherwise the coverage generation will not complete. 31 | # coverage # Name of output directory. 32 | # ) 33 | # 34 | # 4. Build a Debug build: 35 | # cmake -DCMAKE_BUILD_TYPE=Debug .. 36 | # make 37 | # make my_coverage_target 38 | # 39 | # 40 | 41 | # Check prereqs 42 | FIND_PROGRAM( GCOV_PATH gcov ) 43 | FIND_PROGRAM( LCOV_PATH lcov ) 44 | FIND_PROGRAM( GENHTML_PATH genhtml ) 45 | FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests) 46 | 47 | IF(NOT GCOV_PATH) 48 | MESSAGE(FATAL_ERROR "gcov not found! Aborting...") 49 | ENDIF() # NOT GCOV_PATH 50 | 51 | IF(NOT CMAKE_COMPILER_IS_GNUCXX) 52 | # Clang version 3.0.0 and greater now supports gcov as well. 53 | MESSAGE(WARNING "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.") 54 | 55 | IF(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") 56 | MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") 57 | ENDIF() 58 | ENDIF() # NOT CMAKE_COMPILER_IS_GNUCXX 59 | 60 | SET(CMAKE_CXX_FLAGS_COVERAGE 61 | "-g -O0 --coverage -fprofile-arcs -ftest-coverage" 62 | CACHE STRING "Flags used by the C++ compiler during coverage builds." 63 | FORCE ) 64 | SET(CMAKE_C_FLAGS_COVERAGE 65 | "-g -O0 --coverage -fprofile-arcs -ftest-coverage" 66 | CACHE STRING "Flags used by the C compiler during coverage builds." 67 | FORCE ) 68 | SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE 69 | "" 70 | CACHE STRING "Flags used for linking binaries during coverage builds." 71 | FORCE ) 72 | SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE 73 | "" 74 | CACHE STRING "Flags used by the shared libraries linker during coverage builds." 75 | FORCE ) 76 | MARK_AS_ADVANCED( 77 | CMAKE_CXX_FLAGS_COVERAGE 78 | CMAKE_C_FLAGS_COVERAGE 79 | CMAKE_EXE_LINKER_FLAGS_COVERAGE 80 | CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) 81 | 82 | IF ( NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "Coverage")) 83 | MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" ) 84 | ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" 85 | 86 | 87 | # Param _targetname The name of new the custom make target 88 | # Param _testrunner The name of the target which runs the tests. 89 | # MUST return ZERO always, even on errors. 90 | # If not, no coverage report will be created! 91 | # Param _outputname lcov output is generated as _outputname.info 92 | # HTML report is generated in _outputname/index.html 93 | # Optional fourth parameter is passed as arguments to _testrunner 94 | # Pass them in list form, e.g.: "-j;2" for -j 2 95 | FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname) 96 | 97 | IF(NOT LCOV_PATH) 98 | MESSAGE(FATAL_ERROR "lcov not found! Aborting...") 99 | ENDIF() # NOT LCOV_PATH 100 | 101 | IF(NOT GENHTML_PATH) 102 | MESSAGE(FATAL_ERROR "genhtml not found! Aborting...") 103 | ENDIF() # NOT GENHTML_PATH 104 | 105 | # Setup target 106 | ADD_CUSTOM_TARGET(${_targetname} 107 | 108 | # Cleanup lcov 109 | ${LCOV_PATH} --directory . --zerocounters 110 | 111 | # Run tests 112 | COMMAND ${_testrunner} ${ARGV3} 113 | 114 | # Capturing lcov counters and generating report 115 | COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info 116 | COMMAND ${LCOV_PATH} --remove ${_outputname}.info 'tests/*' '/usr/*' --output-file ${_outputname}.info.cleaned 117 | COMMAND ${GENHTML_PATH} -o ${_outputname} ${_outputname}.info.cleaned 118 | COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info ${_outputname}.info.cleaned 119 | 120 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 121 | COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." 122 | ) 123 | 124 | # Show info where to find the report 125 | ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD 126 | COMMAND ; 127 | COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report." 128 | ) 129 | 130 | ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE 131 | 132 | # Param _targetname The name of new the custom make target 133 | # Param _testrunner The name of the target which runs the tests 134 | # Param _outputname cobertura output is generated as _outputname.xml 135 | # Optional fourth parameter is passed as arguments to _testrunner 136 | # Pass them in list form, e.g.: "-j;2" for -j 2 137 | FUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname) 138 | 139 | IF(NOT PYTHON_EXECUTABLE) 140 | MESSAGE(FATAL_ERROR "Python not found! Aborting...") 141 | ENDIF() # NOT PYTHON_EXECUTABLE 142 | 143 | IF(NOT GCOVR_PATH) 144 | MESSAGE(FATAL_ERROR "gcovr not found! Aborting...") 145 | ENDIF() # NOT GCOVR_PATH 146 | 147 | ADD_CUSTOM_TARGET(${_targetname} 148 | 149 | # Run tests 150 | ${_testrunner} ${ARGV3} 151 | 152 | # Running gcovr 153 | COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml 154 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 155 | COMMENT "Running gcovr to produce Cobertura code coverage report." 156 | ) 157 | 158 | # Show info where to find the report 159 | ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD 160 | COMMAND ; 161 | COMMENT "Cobertura code coverage report saved in ${_outputname}.xml." 162 | ) 163 | 164 | ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA 165 | -------------------------------------------------------------------------------- /cpp_tests/source/test_accept_tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "pele/array.h" 8 | 9 | #include "mcpele/energy_window_test.h" 10 | 11 | TEST(EnergyWindow, Works){ 12 | double emin = 1.; 13 | double emax = 2.; 14 | pele::Array xnew, xold; 15 | mcpele::MC * mc = NULL; 16 | double T = 0., eold = 0.; 17 | double eps = 1e-10; 18 | mcpele::EnergyWindowTest test(emin, emax); 19 | EXPECT_TRUE(test.test(xnew, emin+eps, xold, eold, T, mc)); 20 | EXPECT_TRUE(test.test(xnew, emax-eps, xold, eold, T, mc)); 21 | EXPECT_FALSE(test.test(xnew, emin-eps, xold, eold, T, mc)); 22 | EXPECT_FALSE(test.test(xnew, emax+eps, xold, eold, T, mc)); 23 | } 24 | -------------------------------------------------------------------------------- /cpp_tests/source/test_conf_tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "mcpele/check_spherical_container.h" 8 | #include "mcpele/check_spherical_container_config.h" 9 | 10 | #define EXPECT_NEAR_RELATIVE(A, B, T) EXPECT_NEAR(fabs(A)/(fabs(A)+fabs(B)+1), fabs(B)/(fabs(A)+fabs(B)+1), T) 11 | 12 | TEST(CheckSphericalContainer, Works){ 13 | size_t ndim = 4; 14 | pele::Array x(2*ndim,0); 15 | double r = 2.; 16 | double eps = 1e-10; 17 | mcpele::MC * mcvoid = NULL; 18 | 19 | mcpele::CheckSphericalContainer check(r, ndim); 20 | x[0] = r - eps; 21 | EXPECT_TRUE(check.conf_test(x, mcvoid)); 22 | x[0] = r + eps; 23 | EXPECT_FALSE(check.conf_test(x, mcvoid)); 24 | } 25 | 26 | TEST(CheckSphericalContainerConfig, Works){ 27 | size_t ndim = 4; 28 | pele::Array x(2 * ndim, 0); 29 | double r = 2.; 30 | double eps = 1e-10; 31 | mcpele::MC * mcvoid = NULL; 32 | 33 | mcpele::CheckSphericalContainerConfig check(r); 34 | x[0] = r - eps; 35 | EXPECT_TRUE(check.conf_test(x, mcvoid)); 36 | x[0] = r + eps; 37 | EXPECT_FALSE(check.conf_test(x, mcvoid)); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /cpp_tests/source/test_histogram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "pele/array.h" 9 | 10 | #include "mcpele/random_coords_displacement.h" 11 | #include "mcpele/gaussian_coords_displacement.h" 12 | #include "mcpele/histogram.h" 13 | 14 | using pele::Array; 15 | 16 | #define EXPECT_NEAR_RELATIVE(A, B, T) EXPECT_NEAR(fabs(A)/(fabs(A)+fabs(B)+1), fabs(B)/(fabs(A)+fabs(B)+1), T) 17 | 18 | class TestHistogram: public ::testing::Test{ 19 | public: 20 | typedef pele::Array arr_t; 21 | size_t ndof; 22 | size_t nsteps; 23 | size_t ntot; 24 | arr_t displ_uniform_all, displ_uniform_single; 25 | arr_t displ_gaussian; 26 | arr_t baseline; 27 | double ss; 28 | mcpele::MC* mc; 29 | virtual void SetUp(){ 30 | ndof = 1000; 31 | nsteps = 100; 32 | ntot = nsteps*ndof; 33 | displ_uniform_all = Array(ndof); 34 | displ_uniform_single = Array(ndof); 35 | displ_gaussian = Array(ndof); 36 | baseline = Array(ndof); 37 | for (size_t i = 0; i < ndof; ++i){ 38 | displ_uniform_all[i] = 0; 39 | displ_uniform_single[i] = 0; 40 | displ_gaussian[i] = 0; 41 | baseline[i] = 0; 42 | } 43 | ss = 4.2; 44 | mc = NULL; 45 | } 46 | }; 47 | 48 | TEST_F(TestHistogram, TestMomentsGlobalMoves){ 49 | std::fill(displ_gaussian.data(), displ_gaussian.data() + ndof, 0); 50 | mcpele::SampleGaussian sampler_gaussian(42, ss, displ_gaussian); 51 | mcpele::RandomCoordsDisplacementAll sampler_uniform_all(42, ss); 52 | mcpele::Histogram hist_uniform_all(-0.5 * ss, 0.5 * ss, 0.01); 53 | mcpele::Histogram hist_gaussian(-5, 5, 0.1); 54 | for (size_t step = 0; step < nsteps; ++step) { 55 | std::fill(displ_uniform_all.data(), displ_uniform_all.data() + ndof, 0); 56 | std::fill(displ_gaussian.data(), displ_gaussian.data() + ndof, 0); 57 | sampler_uniform_all.displace(displ_uniform_all, mc); 58 | sampler_gaussian.displace(displ_gaussian, mc); 59 | for (size_t dof = 0; dof < ndof; ++dof) { 60 | hist_uniform_all.add_entry(displ_uniform_all[dof]); 61 | hist_gaussian.add_entry(displ_gaussian[dof]); 62 | } 63 | } 64 | EXPECT_EQ(static_cast(hist_uniform_all.get_count()), ntot); 65 | EXPECT_EQ(static_cast(hist_gaussian.get_count()), ntot); 66 | EXPECT_NEAR_RELATIVE(hist_uniform_all.get_mean(), sampler_uniform_all.expected_mean(), 2 * ss / sqrt(ntot)); 67 | EXPECT_NEAR_RELATIVE(hist_gaussian.get_mean(), sampler_gaussian.expected_mean(), 2 * ss / sqrt(ntot)); 68 | EXPECT_NEAR_RELATIVE(hist_uniform_all.get_variance(), sampler_uniform_all.expected_variance(ss), 2 * ss / sqrt(ntot)); 69 | EXPECT_NEAR_RELATIVE(hist_gaussian.get_variance(), sampler_gaussian.expected_variance(ss), 2 * ss / sqrt(ntot)); 70 | } 71 | 72 | TEST_F(TestHistogram, TestMomentsSingleMoves){ 73 | mcpele::RandomCoordsDisplacementSingle sampler_uniform_single(42, 500, 2, ss); 74 | mcpele::Histogram hist_uniform_single(-0.5 * ss, 0.5 * ss, 0.01); 75 | for (size_t step = 0; step < nsteps*500; ++step) { 76 | std::fill(displ_uniform_single.data(), displ_uniform_single.data() + ndof, 0); 77 | sampler_uniform_single.displace(displ_uniform_single, mc); 78 | for (size_t dof = 0; dof < ndof; ++dof) { 79 | if (displ_uniform_single[dof]!= 0){ 80 | hist_uniform_single.add_entry(displ_uniform_single[dof]); 81 | } 82 | } 83 | } 84 | 85 | EXPECT_EQ(static_cast(hist_uniform_single.get_count()), ntot); 86 | EXPECT_NEAR_RELATIVE(hist_uniform_single.get_mean(), sampler_uniform_single.expected_mean(), 2 * ss / sqrt(ntot)); 87 | EXPECT_NEAR_RELATIVE(hist_uniform_single.get_variance(), sampler_uniform_single.expected_variance(ss), 2 * ss / sqrt(ntot)); 88 | } 89 | 90 | TEST_F(TestHistogram, TestBinning){ 91 | std::fill(displ_gaussian.data(), displ_gaussian.data() + ndof, 0); 92 | mcpele::SampleGaussian sampler(42, ss, displ_gaussian); 93 | const double min = -42; 94 | const double max = 42; 95 | const double bin = 2; 96 | mcpele::Histogram hist(min, max, bin); 97 | for (size_t step = 0; step < nsteps; ++step) { 98 | sampler.displace(displ_gaussian, mc); 99 | for (size_t dof = 0; dof < ndof; ++dof) { 100 | hist.add_entry(displ_gaussian[dof]); 101 | } 102 | } 103 | EXPECT_EQ(static_cast(hist.get_count()), ntot); 104 | EXPECT_LE(min, hist.min()); 105 | EXPECT_LE(max, hist.max()); 106 | EXPECT_DOUBLE_EQ(hist.bin(), bin); 107 | EXPECT_DOUBLE_EQ(hist.get_count(), nsteps * ndof); 108 | EXPECT_DOUBLE_EQ(std::accumulate(hist.begin(), hist.end(), double(0)), hist.get_count()); 109 | const std::vector vecdata = hist.get_vecdata(); 110 | EXPECT_EQ(vecdata.size(), hist.size()); 111 | EXPECT_DOUBLE_EQ(std::accumulate(vecdata.begin(), vecdata.end(), double(0)), hist.get_count()); 112 | const std::vector vecdata_normalized = hist.get_vecdata_normalized(); 113 | EXPECT_EQ(vecdata_normalized.size(), hist.size()); 114 | EXPECT_DOUBLE_EQ(std::accumulate(vecdata_normalized.begin(), vecdata_normalized.end(), double(0)) * bin, 1); 115 | const std::vector error = hist.get_vecdata_error(); 116 | for (size_t ii = 0; ii < hist.size(); ++ii) { 117 | const double xi = hist.get_position(ii); 118 | const double true_i = exp(-pow((xi - sampler.expected_mean()), 2) / (2 * sampler.expected_variance(ss))) / sqrt(M_PI * 2 * sampler.expected_variance(ss)); 119 | const double EPS = 1e-12; 120 | if (vecdata_normalized.at(ii) > EPS) { 121 | EXPECT_NEAR(vecdata_normalized.at(ii), true_i, 2 * error.at(ii)); 122 | } 123 | } 124 | // Test ticks function returns bin centers 125 | const std::vector vectics = hist.get_vectics(); 126 | size_t i = 0; 127 | for (const double x : vectics) { 128 | EXPECT_DOUBLE_EQ(-42 + (0.5 + i++) * 2, x); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /cpp_tests/source/test_pair_dist_histogram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "pele/lbfgs.h" 10 | 11 | #include "mcpele/record_pair_dist_histogram.h" 12 | 13 | using pele::Array; 14 | 15 | #define EXPECT_NEAR_RELATIVE(A, B, T) EXPECT_NEAR(fabs(A)/(fabs(A)+fabs(B)+1), fabs(B)/(fabs(A)+fabs(B)+1), T) 16 | 17 | using std::shared_ptr; 18 | using mcpele::ConfTest; 19 | using mcpele::MC; 20 | 21 | #define boxdim 3 22 | 23 | struct TrivialPotential : public pele::BasePotential{ 24 | size_t call_count; 25 | virtual double get_energy(Array coords) 26 | { 27 | call_count++; 28 | return 0.; 29 | } 30 | }; 31 | 32 | struct TrivialTakestep : public mcpele::TakeStep{ 33 | size_t call_count; 34 | TrivialTakestep() 35 | : call_count(0) 36 | {} 37 | virtual void displace(Array &coords, MC * mc) 38 | { 39 | call_count++; 40 | } 41 | }; 42 | 43 | class TestPairDistHist: public ::testing::Test{ 44 | public: 45 | 46 | typedef pele::Array arr_t; 47 | size_t nparticles; 48 | size_t ndof; 49 | arr_t origin; 50 | arr_t x; 51 | double stepsize; 52 | std::shared_ptr potential; 53 | std::shared_ptr step; 54 | size_t max_iter; 55 | size_t nr_bins; 56 | arr_t boxvector; 57 | double boxlength; 58 | virtual void SetUp(){ 59 | nparticles = 1e1; 60 | ndof = boxdim * nparticles; 61 | origin = Array(ndof); 62 | std::fill(origin.data(), origin.data() + ndof, 0); 63 | x = Array(ndof); 64 | std::fill(x.data(), x.data() + ndof, 0); 65 | stepsize = 1e-2; 66 | potential = std::make_shared(); 67 | step = std::make_shared(); 68 | max_iter = 1e5; 69 | nr_bins = 100; 70 | boxvector = arr_t(boxdim); 71 | boxlength = 42; 72 | std::fill(boxvector.data(), boxvector.data() + boxdim, boxlength); 73 | } 74 | }; 75 | 76 | TEST_F(TestPairDistHist, BasicFunctionality){ 77 | std::shared_ptr mc = std::make_shared(potential, x, 1); 78 | mc->set_takestep(step); 79 | const size_t eqsteps(max_iter/1e1); 80 | std::shared_ptr > record_gr = std::make_shared >(boxvector, nr_bins, eqsteps, 1); 81 | std::shared_ptr opt = std::make_shared(potential, x); 82 | std::shared_ptr > record_gr_quench = std::make_shared >(boxvector, nr_bins, eqsteps, 1, opt); 83 | mc->add_action(record_gr); 84 | mc->add_action(record_gr_quench); 85 | mc->run(max_iter); 86 | EXPECT_EQ(mc->get_iterations_count(), max_iter); 87 | EXPECT_TRUE(record_gr->get_eqsteps() == eqsteps); 88 | EXPECT_TRUE(record_gr_quench->get_eqsteps() == eqsteps); 89 | const double number_density = nparticles / pow(boxlength, boxdim); 90 | pele::Array r = record_gr->get_hist_r(); 91 | pele::Array gr = record_gr->get_hist_gr(number_density, nparticles); 92 | EXPECT_EQ(r[0], (boxlength * 0.5 / nr_bins) * 0.5); // bin size OK 93 | // normalization OK 94 | if (boxdim == 2) { 95 | EXPECT_DOUBLE_EQ(gr[0], nparticles * (nparticles - 1) / (nparticles * number_density * 2 * M_PI * r[0] * (boxlength * 0.5 / nr_bins))); 96 | } 97 | if (boxdim == 3) { 98 | const double dr = (boxlength * 0.5 / nr_bins); 99 | EXPECT_DOUBLE_EQ(gr[0], nparticles * (nparticles - 1) / (nparticles * number_density * 4 * M_PI / 3 * (pow(r[0] + 0.5 * dr, 3) - pow(r[0] - 0.5 * dr, 3)))); 100 | } 101 | for (size_t i = 1; i < gr.size(); ++i) { 102 | EXPECT_EQ(gr[i], 0); 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /cpp_tests/source/test_time_series.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "pele/array.h" 9 | #include "pele/harmonic.h" 10 | #include "pele/hs_wca.h" 11 | #include "pele/lj.h" 12 | 13 | #include "mcpele/moving_average.h" 14 | #include "mcpele/record_energy_timeseries.h" 15 | #include "mcpele/record_displacement_per_particle_timeseries.h" 16 | #include "mcpele/record_lowest_evalue_timeseries.h" 17 | 18 | #define EXPECT_NEAR_RELATIVE(A, B, T) EXPECT_NEAR(fabs(A)/(fabs(A)+fabs(B)+1), fabs(B)/(fabs(A)+fabs(B)+1), T) 19 | 20 | struct TrivialTakestep : public mcpele::TakeStep{ 21 | size_t call_count; 22 | TrivialTakestep() 23 | : call_count(0) 24 | {} 25 | virtual void displace(pele::Array &coords, mcpele::MC * mc=NULL) 26 | { 27 | call_count++; 28 | } 29 | }; 30 | 31 | TEST(EnergyTimeseries, Basic){ 32 | const size_t boxdim = 3; 33 | const size_t nparticles = 100; 34 | const size_t ndof = nparticles * boxdim; 35 | const size_t niter = 10000; 36 | const size_t record_every = 100; 37 | const double k = 400; 38 | pele::Array coords(ndof,2); 39 | pele::Array origin(ndof,0); 40 | std::shared_ptr potential = std::make_shared(origin, k, boxdim); 41 | const auto enumerical = potential->get_energy(coords); 42 | double etrue(0); 43 | for (size_t i = 0; i < ndof; ++i) { 44 | const auto delta = coords[i] - origin[i]; 45 | etrue += 0.5 * k * delta * delta; 46 | } 47 | EXPECT_DOUBLE_EQ(enumerical, etrue); 48 | std::shared_ptr mc = std::make_shared(potential, coords, 1); 49 | mcpele::RecordEnergyTimeseries* ts = new mcpele::RecordEnergyTimeseries(niter, record_every); 50 | mc->add_action(std::shared_ptr(ts)); 51 | mc->set_takestep(std::make_shared()); 52 | mc->run(niter); 53 | EXPECT_EQ(mc->get_iterations_count(), niter); 54 | pele::Array series = ts->get_time_series(); 55 | EXPECT_EQ(series.size(), niter/record_every); 56 | for (size_t i = 0; i < series.size(); ++i) { 57 | EXPECT_DOUBLE_EQ(series[i], enumerical); 58 | } 59 | } 60 | 61 | TEST(EVTimeseries, Works) { 62 | typedef mcpele::RecordLowestEValueTimeseries series_t; 63 | //typedef mcpele::RecordEnergyTimeseries series_t; 64 | const size_t boxdim = 3; 65 | const size_t nparticles = 4; 66 | const size_t ndof = nparticles * boxdim; 67 | const size_t niter = 100; 68 | const size_t record_every = 10; 69 | const double k = 400; 70 | pele::Array coords(ndof,2); 71 | for (size_t i = 0; i < coords.size(); ++i){ 72 | coords[i] += 0.1*i; 73 | } 74 | pele::Array origin(ndof, 1); 75 | for (size_t i = 0; i < origin.size(); ++i){ 76 | origin[i] -= 0.01 * i; 77 | } 78 | std::shared_ptr potential = std::make_shared(origin, k, boxdim); 79 | 80 | const double eps = 1; 81 | const double sca = 1; 82 | pele::Array radii(nparticles,1); 83 | std::shared_ptr > landscape_potential = std::make_shared >(eps, sca, radii); 84 | 85 | //pele::Harmonic* landscape_potential = new pele::Harmonic(origin, k, boxdim); 86 | //pele::LJ* landscape_potential = new pele::LJ(1, 1); 87 | 88 | const auto enumerical = potential->get_energy(coords); 89 | double etrue(0); 90 | for (size_t i = 0; i < ndof; ++i) { 91 | const auto delta = coords[i] - origin[i]; 92 | etrue += 0.5 * k * delta * delta; 93 | } 94 | EXPECT_DOUBLE_EQ(enumerical, etrue); 95 | std::shared_ptr mc = std::make_shared(potential, coords, 1); 96 | 97 | const size_t lbfgsniter = 30; 98 | pele::Array ranvec = origin.copy(); 99 | //series_t* ts = new series_t(niter, record_every); 100 | std::shared_ptr ts = std::make_shared(niter, record_every, landscape_potential, boxdim, ranvec, lbfgsniter); 101 | //series_t* ts = new series_t(niter, record_every, potential, boxdim, ranvec); 102 | 103 | mc->add_action(std::shared_ptr(ts)); 104 | mc->set_takestep(std::make_shared()); 105 | //mc->set_print_progress(); 106 | mc->run(niter); 107 | EXPECT_EQ(mc->get_iterations_count(), niter); 108 | pele::Array series = ts->get_time_series(); 109 | EXPECT_EQ(series.size(), niter / record_every); 110 | const double eigenvalue_reference = series[0]; 111 | for (size_t i = 0; i < series.size(); ++i) { 112 | EXPECT_NEAR_RELATIVE(series[i], eigenvalue_reference, 1e-9); 113 | } 114 | } 115 | 116 | TEST(ParticleDisplacementTimeseries, Works){ 117 | const size_t boxdim = 3; 118 | const size_t nparticles = 100; 119 | const size_t ndof = nparticles * boxdim; 120 | const size_t niter = 10000; 121 | const size_t record_every = 100; 122 | pele::Array coords(ndof,2); 123 | pele::Array origin(ndof,0); 124 | 125 | const double k = 400; 126 | std::shared_ptr potential = std::make_shared(origin, k, boxdim); 127 | std::shared_ptr mc = std::make_shared(potential, coords, 1); 128 | 129 | mcpele::RecordDisplacementPerParticleTimeseries* ts = new mcpele::RecordDisplacementPerParticleTimeseries(niter, record_every, origin, boxdim); 130 | mc->add_action(std::shared_ptr(ts)); 131 | mc->set_takestep(std::make_shared()); 132 | 133 | mc->run(niter); 134 | EXPECT_EQ(mc->get_iterations_count(), niter); 135 | 136 | pele::Array series = ts->get_time_series(); 137 | EXPECT_EQ(series.size(), niter/record_every); 138 | for (size_t i = 0; i < series.size(); ++i){ 139 | EXPECT_NEAR_RELATIVE(series[i], sqrt(12), 1e-14); 140 | } 141 | } 142 | 143 | TEST(MovingAverage, Works) 144 | { 145 | std::vector ts = {0, 0, 0, 1, 1, 1, 1, 4, 4, 5}; 146 | const double true_mean = std::accumulate(ts.begin(), ts.end(), double(0)) / ts.size(); 147 | std::cout << "true_mean: " << true_mean << std::endl; 148 | mcpele::MovingAverageAcc ma10(ts, ts.size(), ts.size()); 149 | ma10.reset(); 150 | EXPECT_DOUBLE_EQ(true_mean, ma10.get_mean()); 151 | mcpele::MovingAverageAcc ma2(ts, ts.size(), 2); 152 | EXPECT_DOUBLE_EQ(0, ma2.get_mean()); 153 | ma2.shift_right(); 154 | EXPECT_DOUBLE_EQ(0, ma2.get_mean()); 155 | ma2.shift_right(); 156 | EXPECT_DOUBLE_EQ(0.5, ma2.get_mean()); 157 | } 158 | 159 | TEST(RecordEnergyTimeseries, Throws) 160 | { 161 | bool threw = false; 162 | try { 163 | mcpele::RecordEnergyTimeseries(42, 0); 164 | } 165 | catch(...) { 166 | threw = true; 167 | } 168 | EXPECT_TRUE(threw); 169 | } 170 | -------------------------------------------------------------------------------- /cythonize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ cythonize 3 | 4 | Cythonize pyx files into C files as needed. 5 | 6 | Usage: cythonize [root_dir] 7 | 8 | Default [root_dir] is 'mcpele'. 9 | 10 | Checks pyx files to see if they have been changed relative to their 11 | corresponding C files. If they have, then runs cython on these files to 12 | recreate the C files. 13 | 14 | The script thinks that the pyx files have changed relative to the C files 15 | by comparing hashes stored in a database file. 16 | 17 | Simple script to invoke Cython (and Tempita) on all .pyx (.pyx.in) 18 | files; while waiting for a proper build system. Uses file hashes to 19 | figure out if rebuild is needed. 20 | 21 | For now, this script should be run by developers when changing Cython files 22 | only, and the resulting C files checked in, so that end-users (and Python-only 23 | developers) do not get the Cython/Tempita dependencies. 24 | 25 | Originally written by Dag Sverre Seljebotn, and copied here from: 26 | 27 | https://raw.github.com/dagss/private-scipy-refactor/cythonize/cythonize.py 28 | 29 | Note: this script does not check any of the dependent C libraries; it only 30 | operates on the Cython .pyx files. 31 | """ 32 | 33 | from __future__ import division, print_function, absolute_import 34 | 35 | import os 36 | import re 37 | import sys 38 | import hashlib 39 | import subprocess 40 | 41 | HASH_FILE = 'cythonize.dat' 42 | DEFAULT_ROOT = 'pele' 43 | 44 | # WindowsError is not defined on unix systems 45 | try: 46 | WindowsError 47 | except NameError: 48 | WindowsError = None 49 | 50 | _extra_flags = [] 51 | 52 | # 53 | # Rules 54 | # 55 | def process_pyx(fromfile, tofile): 56 | try: 57 | from Cython.Compiler.Version import version as cython_version 58 | from distutils.version import LooseVersion 59 | if LooseVersion(cython_version) < LooseVersion('0.16'): 60 | raise Exception('Building mcpele requires Cython >= 0.16') 61 | 62 | except ImportError: 63 | pass 64 | 65 | flags = ['--fast-fail'] 66 | if tofile.endswith('.cxx'): 67 | flags += ['--cplus'] 68 | 69 | if _extra_flags: 70 | flags += _extra_flags 71 | 72 | try: 73 | try: 74 | r = subprocess.call(['cython'] + flags + ["-o", tofile, fromfile]) 75 | if r != 0: 76 | raise Exception('Cython failed') 77 | except OSError: 78 | # There are ways of installing Cython that don't result in a cython 79 | # executable on the path, see gh-2397. 80 | r = subprocess.call([sys.executable, '-c', 81 | 'import sys; from Cython.Compiler.Main import ' 82 | 'setuptools_main as main; sys.exit(main())'] + flags + 83 | ["-o", tofile, fromfile]) 84 | if r != 0: 85 | raise Exception('Cython failed') 86 | except OSError: 87 | raise OSError('Cython needs to be installed') 88 | 89 | def process_tempita_pyx(fromfile, tofile): 90 | import tempita 91 | with open(fromfile, "rb") as f: 92 | tmpl = f.read() 93 | pyxcontent = tempita.sub(tmpl) 94 | assert fromfile.endswith('.pyx.in') 95 | pyxfile = fromfile[:-len('.pyx.in')] + '.pyx' 96 | with open(pyxfile, "wb") as f: 97 | f.write(pyxcontent) 98 | process_pyx(pyxfile, tofile) 99 | 100 | rules = { 101 | # fromext : function 102 | '.pyx' : process_pyx, 103 | '.pyx.in' : process_tempita_pyx 104 | } 105 | # 106 | # Hash db 107 | # 108 | def load_hashes(filename): 109 | # Return { filename : (sha1 of input, sha1 of output) } 110 | if os.path.isfile(filename): 111 | hashes = {} 112 | with open(filename, 'r') as f: 113 | for line in f: 114 | filename, inhash, outhash = line.split() 115 | hashes[filename] = (inhash, outhash) 116 | else: 117 | hashes = {} 118 | return hashes 119 | 120 | def save_hashes(hash_db, filename): 121 | with open(filename, 'w') as f: 122 | for key, value in sorted(hash_db.items()): 123 | f.write("%s %s %s\n" % (key, value[0], value[1])) 124 | 125 | def sha1_of_file(filename): 126 | h = hashlib.sha1() 127 | with open(filename, "rb") as f: 128 | h.update(f.read()) 129 | return h.hexdigest() 130 | 131 | # 132 | # Main program 133 | # 134 | 135 | def normpath(path): 136 | path = path.replace(os.sep, '/') 137 | if path.startswith('./'): 138 | path = path[2:] 139 | return path 140 | 141 | def get_hash(frompath, topath): 142 | from_hash = sha1_of_file(frompath) 143 | to_hash = sha1_of_file(topath) if os.path.exists(topath) else None 144 | return (from_hash, to_hash) 145 | 146 | def process(path, fromfile, tofile, processor_function, hash_db): 147 | fullfrompath = os.path.join(path, fromfile) 148 | fulltopath = os.path.join(path, tofile) 149 | current_hash = get_hash(fullfrompath, fulltopath) 150 | if current_hash == hash_db.get(normpath(fullfrompath), None): 151 | print('%s has not changed' % fullfrompath) 152 | return 153 | 154 | orig_cwd = os.getcwd() 155 | try: 156 | os.chdir(path) 157 | print('Processing %s' % fullfrompath) 158 | processor_function(fromfile, tofile) 159 | finally: 160 | os.chdir(orig_cwd) 161 | # changed target file, recompute hash 162 | current_hash = get_hash(fullfrompath, fulltopath) 163 | # store hash in db 164 | hash_db[normpath(fullfrompath)] = current_hash 165 | 166 | 167 | def find_process_files(root_dir): 168 | """loop through subdirectories finding pyx files and converting them""" 169 | hash_db = load_hashes(HASH_FILE) 170 | for cur_dir, dirs, files in os.walk(root_dir): 171 | for filename in files: 172 | for fromext, function in rules.items(): 173 | if filename.endswith(fromext): 174 | toext = ".c" 175 | with open(os.path.join(cur_dir, filename), 'rb') as f: 176 | data = f.read() 177 | m = re.search(br"^\s*#\s*distutils:\s*language\s*=\s*c\+\+\s*$", data, re.I|re.M) 178 | if m: 179 | toext = ".cxx" 180 | fromfile = filename 181 | tofile = filename[:-len(fromext)] + toext 182 | process(cur_dir, fromfile, tofile, function, hash_db) 183 | save_hashes(hash_db, HASH_FILE) 184 | 185 | def main(): 186 | try: 187 | root_dir = sys.argv[1] 188 | except IndexError: 189 | root_dir = DEFAULT_ROOT 190 | 191 | if len(sys.argv) > 2: 192 | global _extra_flags 193 | for f in sys.argv[2:]: 194 | _extra_flags.append(f) 195 | find_process_files(root_dir) 196 | 197 | if __name__ == '__main__': 198 | main() 199 | -------------------------------------------------------------------------------- /dark_example_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pele-python/mcpele/5ba07028e4efd1dd447f3c26800f50a7d9bbb08d/dark_example_code.png -------------------------------------------------------------------------------- /dark_example_run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pele-python/mcpele/5ba07028e4efd1dd447f3c26800f50a7d9bbb08d/dark_example_run.png -------------------------------------------------------------------------------- /diagram_fluid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pele-python/mcpele/5ba07028e4efd1dd447f3c26800f50a7d9bbb08d/diagram_fluid.png -------------------------------------------------------------------------------- /doc/AcceptTest.rst: -------------------------------------------------------------------------------- 1 | 2 | Acceptance Tests 3 | ================ 4 | 5 | .. currentmodule:: mcpele.monte_carlo 6 | 7 | .. autoclass:: MetropolisTest 8 | :members: 9 | :inherited-members: 10 | :undoc-members: 11 | :show-inheritance: 12 | -------------------------------------------------------------------------------- /doc/Action.rst: -------------------------------------------------------------------------------- 1 | Actions 2 | ======= 3 | 4 | .. currentmodule:: mcpele.monte_carlo 5 | 6 | .. autoclass:: RecordEnergyHistogram 7 | :members: 8 | :inherited-members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | .. autoclass:: RecordEnergyTimeseries 13 | :members: 14 | :inherited-members: 15 | :undoc-members: 16 | :show-inheritance: 17 | 18 | .. autoclass:: RecordPairDistHistogram 19 | :members: 20 | :inherited-members: 21 | :undoc-members: 22 | :show-inheritance: 23 | 24 | .. autoclass:: RecordLowestEValueTimeseries 25 | :members: 26 | :inherited-members: 27 | :undoc-members: 28 | :show-inheritance: 29 | 30 | .. autoclass:: RecordDisplacementPerParticleTimeseries 31 | :members: 32 | :inherited-members: 33 | :undoc-members: 34 | :show-inheritance: -------------------------------------------------------------------------------- /doc/BaseMCRunner.rst: -------------------------------------------------------------------------------- 1 | Base MCRunner 2 | ============= 3 | 4 | .. currentmodule:: mcpele.monte_carlo 5 | 6 | .. autoclass:: _BaseMCRunner 7 | :members: 8 | :inherited-members: 9 | :undoc-members: 10 | :show-inheritance: 11 | :exclude-members: niter,start_coords,temperature,potential -------------------------------------------------------------------------------- /doc/Base_MPI_Parallel_Tempering.rst: -------------------------------------------------------------------------------- 1 | Base MPI Parallel Tempering 2 | =========================== 3 | 4 | .. currentmodule:: mcpele.parallel_tempering 5 | 6 | .. autoclass:: _MPI_Parallel_Tempering 7 | :members: 8 | :private-members: 9 | :undoc-members: 10 | :exclude-members: _abc_cache,_abc_negative_cache,_abc_negative_cache_version,_abc_registry -------------------------------------------------------------------------------- /doc/ConfTest.rst: -------------------------------------------------------------------------------- 1 | 2 | Configuration Tests 3 | =================== 4 | 5 | .. currentmodule:: mcpele.monte_carlo 6 | 7 | .. autoclass:: CheckSphericalContainer 8 | :members: 9 | :inherited-members: 10 | :undoc-members: 11 | :show-inheritance: -------------------------------------------------------------------------------- /doc/MPI_Parallel_Tempering.rst: -------------------------------------------------------------------------------- 1 | MPI Parallel Tempering 2 | ====================== 3 | 4 | .. currentmodule:: mcpele.parallel_tempering 5 | 6 | .. autoclass:: MPI_PT_RLhandshake 7 | :members: 8 | :inherited-members: 9 | :undoc-members: 10 | :show-inheritance: -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # detail on automatically pushing the documentation to gh-pages here http://blog.nikhilism.com/2012/08/automatic-github-pages-generation-from.html 3 | # add .nojekill for gh-pages to look good 4 | 5 | # You can set these variables from the command line. 6 | SPHINXOPTS = 7 | SPHINXBUILD = sphinx-build 8 | PAPER = 9 | BUILDDIR = _build 10 | GH_PAGES_SOURCES = mcpele source cythonize.py setup_with_cmake.py CMakeLists.txt.in 11 | BRANCH = doxygen 12 | 13 | # User-friendly check for sphinx-build 14 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 15 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 16 | endif 17 | 18 | # Internal variables. 19 | PAPEROPT_a4 = -D latex_paper_size=a4 20 | PAPEROPT_letter = -D latex_paper_size=letter 21 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 22 | # the i18n builder cannot share the environment and doctrees with the others 23 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 24 | 25 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 26 | 27 | help: 28 | @echo "Please use \`make ' where is one of" 29 | @echo " html to make standalone HTML files" 30 | @echo " dirhtml to make HTML files named index.html in directories" 31 | @echo " singlehtml to make a single large HTML file" 32 | @echo " pickle to make pickle files" 33 | @echo " json to make JSON files" 34 | @echo " htmlhelp to make HTML files and a HTML help project" 35 | @echo " qthelp to make HTML files and a qthelp project" 36 | @echo " devhelp to make HTML files and a Devhelp project" 37 | @echo " epub to make an epub" 38 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 39 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 40 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 41 | @echo " text to make text files" 42 | @echo " man to make manual pages" 43 | @echo " texinfo to make Texinfo files" 44 | @echo " info to make Texinfo files and run them through makeinfo" 45 | @echo " gettext to make PO message catalogs" 46 | @echo " changes to make an overview of all changed/added/deprecated items" 47 | @echo " xml to make Docutils-native XML files" 48 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 49 | @echo " linkcheck to check all external links for integrity" 50 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 51 | @echo " gh-pages to push the documentation to the web" 52 | 53 | clean: 54 | rm -rf $(BUILDDIR)/* 55 | 56 | html: 57 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 58 | @echo 59 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 60 | 61 | dirhtml: 62 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 63 | @echo 64 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 65 | 66 | singlehtml: 67 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 68 | @echo 69 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 70 | 71 | pickle: 72 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 73 | @echo 74 | @echo "Build finished; now you can process the pickle files." 75 | 76 | json: 77 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 78 | @echo 79 | @echo "Build finished; now you can process the JSON files." 80 | 81 | htmlhelp: 82 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 83 | @echo 84 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 85 | ".hhp project file in $(BUILDDIR)/htmlhelp." 86 | 87 | qthelp: 88 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 89 | @echo 90 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 91 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 92 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/mcpele.qhcp" 93 | @echo "To view the help file:" 94 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/mcpele.qhc" 95 | 96 | devhelp: 97 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 98 | @echo 99 | @echo "Build finished." 100 | @echo "To view the help file:" 101 | @echo "# mkdir -p $$HOME/.local/share/devhelp/mcpele" 102 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/mcpele" 103 | @echo "# devhelp" 104 | 105 | epub: 106 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 107 | @echo 108 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 109 | 110 | latex: 111 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 112 | @echo 113 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 114 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 115 | "(use \`make latexpdf' here to do that automatically)." 116 | 117 | latexpdf: 118 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 119 | @echo "Running LaTeX files through pdflatex..." 120 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 121 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 122 | 123 | latexpdfja: 124 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 125 | @echo "Running LaTeX files through platex and dvipdfmx..." 126 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 127 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 128 | 129 | text: 130 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 131 | @echo 132 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 133 | 134 | man: 135 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 136 | @echo 137 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 138 | 139 | texinfo: 140 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 141 | @echo 142 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 143 | @echo "Run \`make' in that directory to run these through makeinfo" \ 144 | "(use \`make info' here to do that automatically)." 145 | 146 | info: 147 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 148 | @echo "Running Texinfo files through makeinfo..." 149 | make -C $(BUILDDIR)/texinfo info 150 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 151 | 152 | gettext: 153 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 154 | @echo 155 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 156 | 157 | changes: 158 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 159 | @echo 160 | @echo "The overview file is in $(BUILDDIR)/changes." 161 | 162 | linkcheck: 163 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 164 | @echo 165 | @echo "Link check complete; look for any errors in the above output " \ 166 | "or in $(BUILDDIR)/linkcheck/output.txt." 167 | 168 | doctest: 169 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 170 | @echo "Testing of doctests in the sources finished, look at the " \ 171 | "results in $(BUILDDIR)/doctest/output.txt." 172 | 173 | xml: 174 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 175 | @echo 176 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 177 | 178 | pseudoxml: 179 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 180 | @echo 181 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 182 | 183 | gh-pages: 184 | git checkout gh-pages 185 | cd ../ &&\ 186 | rm -rf build _build _sources _static _images _modules _templates sphinxext doxygen &&\ 187 | git checkout $(BRANCH) $(GH_PAGES_SOURCES) doc &&\ 188 | git reset HEAD &&\ 189 | python setup_with_cmake.py build_ext -i 190 | make html 191 | mv -fv _build/html/* ../ 192 | mv -fv -t ../ *.png *.rst _build sphinxext 193 | rm -rf conf.py _static _templates 194 | cd ../ &&\ 195 | mv -fv source/doc/html doxygen 196 | rm -rf $(GH_PAGES_SOURCES) &&\ 197 | git add -A && \ 198 | git commit -m "Generated gh-pages for `git log $(BRANCH) -1 --pretty=short --abbrev-commit`" && git push origin gh-pages ; git checkout $(BRANCH); 199 | -------------------------------------------------------------------------------- /doc/TakeStep.rst: -------------------------------------------------------------------------------- 1 | Take Step 2 | ========= 3 | 4 | .. currentmodule:: mcpele.monte_carlo 5 | 6 | .. autoclass:: RandomCoordsDisplacement 7 | :members: 8 | :inherited-members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | .. autoclass:: GaussianCoordsDisplacement 13 | :members: 14 | :inherited-members: 15 | :undoc-members: 16 | :show-inheritance: 17 | 18 | .. autoclass:: ParticlePairSwap 19 | :members: 20 | :inherited-members: 21 | :undoc-members: 22 | :show-inheritance: 23 | 24 | .. autoclass:: TakeStepPattern 25 | :members: 26 | :inherited-members: 27 | :undoc-members: 28 | :show-inheritance: 29 | 30 | .. autoclass:: TakeStepProbabilities 31 | :members: 32 | :inherited-members: 33 | :undoc-members: 34 | :show-inheritance: -------------------------------------------------------------------------------- /doc/_static/scipy.css: -------------------------------------------------------------------------------- 1 | @import "default.css"; 2 | 3 | /** 4 | * Spacing fixes 5 | */ 6 | 7 | div.body p, div.body dd, div.body li { 8 | line-height: 125%; 9 | } 10 | 11 | ul.simple { 12 | margin-top: 0; 13 | margin-bottom: 0; 14 | padding-top: 0; 15 | padding-bottom: 0; 16 | } 17 | 18 | /* spacing around blockquoted fields in parameters/attributes/returns */ 19 | td.field-body > blockquote { 20 | margin-top: 0.1em; 21 | margin-bottom: 0.5em; 22 | } 23 | 24 | /* spacing around example code */ 25 | div.highlight > pre { 26 | padding: 2px 5px 2px 5px; 27 | } 28 | 29 | /* spacing in see also definition lists */ 30 | dl.last > dd { 31 | margin-top: 1px; 32 | margin-bottom: 5px; 33 | margin-left: 30px; 34 | } 35 | 36 | /* hide overflowing content in the sidebar */ 37 | div.sphinxsidebarwrapper p.topless { 38 | overflow: hidden; 39 | } 40 | 41 | /** 42 | * Hide dummy toctrees 43 | */ 44 | 45 | ul { 46 | padding-top: 0; 47 | padding-bottom: 0; 48 | margin-top: 0; 49 | margin-bottom: 0; 50 | } 51 | ul li { 52 | padding-top: 0; 53 | padding-bottom: 0; 54 | margin-top: 0; 55 | margin-bottom: 0; 56 | } 57 | ul li a.reference { 58 | padding-top: 0; 59 | padding-bottom: 0; 60 | margin-top: 0; 61 | margin-bottom: 0; 62 | } 63 | 64 | /** 65 | * Make high-level subsections easier to distinguish from top-level ones 66 | */ 67 | div.body h3 { 68 | background-color: transparent; 69 | } 70 | 71 | div.body h4 { 72 | border: none; 73 | background-color: transparent; 74 | } 75 | 76 | /** 77 | * Scipy colors 78 | */ 79 | 80 | body { 81 | background-color: rgb(100,135,220); 82 | } 83 | 84 | div.document { 85 | background-color: rgb(230,230,230); 86 | } 87 | 88 | div.sphinxsidebar { 89 | background-color: rgb(230,230,230); 90 | overflow: hidden; 91 | } 92 | 93 | div.related { 94 | background-color: rgb(100,135,220); 95 | } 96 | 97 | div.sphinxsidebar h3 { 98 | color: rgb(0,102,204); 99 | } 100 | 101 | div.sphinxsidebar h3 a { 102 | color: rgb(0,102,204); 103 | } 104 | 105 | div.sphinxsidebar h4 { 106 | color: rgb(0,82,194); 107 | } 108 | 109 | div.sphinxsidebar p { 110 | color: black; 111 | } 112 | 113 | div.sphinxsidebar a { 114 | color: #355f7c; 115 | } 116 | 117 | div.sphinxsidebar ul.want-points { 118 | list-style: disc; 119 | } 120 | 121 | .field-list th { 122 | color: rgb(0,102,204); 123 | white-space: nowrap; 124 | } 125 | 126 | /** 127 | * Extra admonitions 128 | */ 129 | 130 | div.tip { 131 | background-color: #ffffe4; 132 | border: 1px solid #ee6; 133 | } 134 | 135 | div.plot-output { 136 | clear-after: both; 137 | } 138 | 139 | div.plot-output .figure { 140 | float: left; 141 | text-align: center; 142 | margin-bottom: 0; 143 | padding-bottom: 0; 144 | } 145 | 146 | div.plot-output .caption { 147 | margin-top: 2; 148 | padding-top: 0; 149 | } 150 | 151 | div.plot-output:after { 152 | content: ""; 153 | display: block; 154 | height: 0; 155 | clear: both; 156 | } 157 | 158 | 159 | /* 160 | div.admonition-example { 161 | background-color: #e4ffe4; 162 | border: 1px solid #ccc; 163 | }*/ 164 | 165 | 166 | /** 167 | * Styling for field lists 168 | */ 169 | 170 | table.field-list th { 171 | border-left: 1px solid #aaa !important; 172 | padding-left: 5px; 173 | } 174 | 175 | table.field-list { 176 | border-collapse: separate; 177 | border-spacing: 10px; 178 | } 179 | 180 | /** 181 | * Styling for footnotes 182 | */ 183 | 184 | table.footnote td, table.footnote th { 185 | border: none; 186 | } 187 | -------------------------------------------------------------------------------- /doc/_templates/autosummary/class.rst: -------------------------------------------------------------------------------- 1 | {% extends "!autosummary/class.rst" %} 2 | 3 | {% block methods %} 4 | {% if methods %} 5 | .. HACK 6 | .. autosummary:: 7 | :toctree: 8 | {% for item in all_methods %} 9 | {%- if not item.startswith('_') or item in ['__call__'] %} 10 | ~{{ name }}.{{ item }} 11 | {%- endif -%} 12 | {%- endfor %} 13 | {% endif %} 14 | {% endblock %} 15 | 16 | {% block attributes %} 17 | {% if attributes %} 18 | .. HACK 19 | .. autosummary:: 20 | :toctree: 21 | {% for item in all_attributes %} 22 | {%- if not item.startswith('_') %} 23 | ~{{ name }}.{{ item }} 24 | {%- endif -%} 25 | {%- endfor %} 26 | {% endif %} 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /doc/_templates/autosummary/module.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: {{ fullname }} 2 | {{ underline }} 3 | 4 | .. automodule:: {{ fullname }} 5 | :members: 6 | -------------------------------------------------------------------------------- /doc/diagram_fluid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pele-python/mcpele/5ba07028e4efd1dd447f3c26800f50a7d9bbb08d/doc/diagram_fluid.png -------------------------------------------------------------------------------- /doc/getting_started.rst: -------------------------------------------------------------------------------- 1 | Getting started 2 | =============== -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | .. mcpele documentation master file, created by 2 | sphinx-quickstart on Sun Nov 30 12:26:21 2014. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | mcpele : Monte Carlo Python Energy Landscape Explorer 7 | +++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 | 9 | Source code: https://github.com/pele-python/mcpele 10 | 11 | Documentation: http://pele-python.github.io/mcpele/ 12 | 13 | Flexible and efficient Monte Carlo general purpose framework 14 | and MPI/mpi4py based Replica Exchange Method, built on the `pele `_ 15 | foundations. mcpele provides a seamless integration of the 16 | tools for energy landscape exploration built in pele. 17 | The package also acts as a plugin for the `Nested Sampling `_ project. 18 | 19 | Through its c++ interface, mcpele makes Monte Carlo simulations available to 20 | researchers with little programming experience, without having to compromise 21 | on efficiency. Furthermore mcpele abstracts each element of a Monte Carlo 22 | simulation eliminating the need for frequent code rewriting that experienced 23 | Monte Carlo developers typically go through, thus reducing the time required for 24 | the implementation of an idea and reducing the occurrence of bugs. 25 | 26 | .. figure:: diagram_fluid.png 27 | 28 | Figure 1: Diagramatic representation of the mcpele framework. On the right 29 | is a hard spheres fluid equilibrated by uniform sampling in a cubic box with 30 | periodic boundary conditions. 31 | 32 | mcpele has been authored by Stefano Martiniani, Ken J Schrenk and Jacob Stevenson at the University of Cambridge. 33 | The project is publicly available under the GNU general public licence. 34 | 35 | Tutorials 36 | ----------- 37 | .. toctree:: 38 | :maxdepth: 3 39 | 40 | getting_started 41 | 42 | Reference 43 | --------- 44 | 45 | .. toctree:: 46 | :maxdepth: 2 47 | 48 | BaseMCRunner 49 | 50 | .. toctree:: 51 | :maxdepth: 2 52 | 53 | TakeStep 54 | 55 | .. toctree:: 56 | :maxdepth: 2 57 | 58 | ConfTest 59 | 60 | .. toctree:: 61 | :maxdepth: 2 62 | 63 | AcceptTest 64 | 65 | .. toctree:: 66 | :maxdepth: 2 67 | 68 | Action 69 | 70 | .. toctree:: 71 | :maxdepth: 2 72 | 73 | Base_MPI_Parallel_Tempering 74 | 75 | .. toctree:: 76 | :maxdepth: 2 77 | 78 | MPI_Parallel_Tempering 79 | 80 | Modules 81 | +++++++ 82 | .. toctree:: 83 | :maxdepth: 1 84 | 85 | monte_carlo 86 | parallel_tempering 87 | 88 | Indices and tables 89 | ------------------ 90 | 91 | * :ref:`genindex` 92 | * :ref:`modindex` 93 | * :ref:`search` 94 | 95 | -------------------------------------------------------------------------------- /doc/monte_carlo.rst: -------------------------------------------------------------------------------- 1 | Monte Carlo 2 | ----------- 3 | 4 | .. currentmodule:: mcpele.monte_carlo 5 | .. automodule:: mcpele.monte_carlo -------------------------------------------------------------------------------- /doc/parallel_tempering.rst: -------------------------------------------------------------------------------- 1 | Parallel Tempering 2 | ------------------ 3 | 4 | .. currentmodule:: mcpele.parallel_tempering 5 | 6 | .. automodule:: mcpele.parallel_tempering -------------------------------------------------------------------------------- /doc/sphinxext/viewcode-new.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | sphinx.ext.viewcode 4 | ~~~~~~~~~~~~~~~~~~~ 5 | 6 | Add links to module code in Python object descriptions. 7 | 8 | :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. 9 | :license: BSD, see LICENSE for details. 10 | """ 11 | 12 | from docutils import nodes 13 | 14 | from sphinx import addnodes 15 | from sphinx.locale import _ 16 | from sphinx.pycode import ModuleAnalyzer 17 | from sphinx.util.nodes import make_refnode 18 | 19 | import sys 20 | import traceback 21 | 22 | 23 | def doctree_read(app, doctree): 24 | env = app.builder.env 25 | if not hasattr(env, '_viewcode_modules'): 26 | env._viewcode_modules = {} 27 | 28 | def get_full_modname(modname, attribute): 29 | try: 30 | __import__(modname) 31 | except Exception, error: 32 | if not app.quiet: 33 | app.info(traceback.format_exc().rstrip()) 34 | app.warn('viewcode can\'t import %s, failed with error "%s"' % 35 | (modname, error)) 36 | return None 37 | module = sys.modules[modname] 38 | try: 39 | # Allow an attribute to have multiple parts and incidentially allow 40 | # repeated .s in the attribute. 41 | attr = attribute.split('.') 42 | value = module 43 | for attr in attribute.split('.'): 44 | if attr: 45 | value = getattr(value, attr) 46 | except AttributeError: 47 | app.warn('Didn\'t find %s in %s' % (attribute, module.__name__)) 48 | return None 49 | else: 50 | return getattr(value, '__module__', None) 51 | 52 | 53 | def has_tag(modname, fullname, docname, refname): 54 | entry = env._viewcode_modules.get(modname, None) 55 | if entry is None: 56 | try: 57 | analyzer = ModuleAnalyzer.for_module(modname) 58 | except Exception: 59 | env._viewcode_modules[modname] = False 60 | return 61 | analyzer.find_tags() 62 | if not isinstance(analyzer.code, unicode): 63 | code = analyzer.code.decode(analyzer.encoding) 64 | else: 65 | code = analyzer.code 66 | entry = code, analyzer.tags, {}, refname 67 | env._viewcode_modules[modname] = entry 68 | elif entry is False: 69 | return 70 | _crap1 = entry 71 | tags = _crap1[1] 72 | used = _crap1[2] 73 | if fullname in tags: 74 | used[fullname] = docname 75 | return True 76 | 77 | 78 | for objnode in doctree.traverse(addnodes.desc): 79 | if objnode.get('domain') != 'py': 80 | continue 81 | names = set() 82 | for signode in objnode: 83 | if not isinstance(signode, addnodes.desc_signature): 84 | continue 85 | modname = signode.get('module') 86 | fullname = signode.get('fullname') 87 | refname = modname 88 | if env.config.viewcode_import: 89 | modname = get_full_modname(modname, fullname) 90 | if not modname: 91 | continue 92 | if not has_tag(modname, fullname, env.docname, refname): 93 | continue 94 | if fullname in names: 95 | # only one link per name, please 96 | continue 97 | names.add(fullname) 98 | pagename = '_modules/' + modname.replace('.', '/') 99 | onlynode = addnodes.only(expr='html') 100 | onlynode += addnodes.pending_xref( 101 | '', reftype='viewcode', refdomain='std', refexplicit=False, 102 | reftarget=pagename, refid=fullname, 103 | refdoc=env.docname) 104 | onlynode[0] += nodes.inline('', _('[source]'), 105 | classes=['viewcode-link']) 106 | signode += onlynode 107 | 108 | 109 | def missing_reference(app, env, node, contnode): 110 | # resolve our "viewcode" reference nodes -- they need special treatment 111 | if node['reftype'] == 'viewcode': 112 | return make_refnode(app.builder, node['refdoc'], node['reftarget'], 113 | node['refid'], contnode) 114 | 115 | 116 | def collect_pages(app): 117 | env = app.builder.env 118 | if not hasattr(env, '_viewcode_modules'): 119 | return 120 | highlighter = app.builder.highlighter 121 | urito = app.builder.get_relative_uri 122 | 123 | modnames = set(env._viewcode_modules) 124 | 125 | app.builder.info(' (%d module code pages)' % 126 | len(env._viewcode_modules), nonl=1) 127 | 128 | for modname, entry in env._viewcode_modules.iteritems(): 129 | if not entry: 130 | continue 131 | if len(entry) < 4: continue 132 | #code, tags, used, refname = entry 133 | code = entry[0] 134 | tags = entry[1] 135 | used = entry[2] 136 | refname = entry[3] 137 | # construct a page name for the highlighted source 138 | pagename = '_modules/' + modname.replace('.', '/') 139 | # highlight the source using the builder's highlighter 140 | highlighted = highlighter.highlight_block(code, 'python', linenos=False) 141 | # split the code into lines 142 | lines = highlighted.splitlines() 143 | # split off wrap markup from the first line of the actual code 144 | before, after = lines[0].split('
')
145 |         lines[0:1] = [before + '
', after]
146 |         # nothing to do for the last line; it always starts with 
anyway 147 | # now that we have code lines (starting at index 1), insert anchors for 148 | # the collected tags (HACK: this only works if the tag boundaries are 149 | # properly nested!) 150 | maxindex = len(lines) - 1 151 | for name, docname in used.iteritems(): 152 | type, start, end = tags[name] 153 | backlink = urito(pagename, docname) + '#' + refname + '.' + name 154 | lines[start] = ( 155 | '
%s' % (name, backlink, _('[docs]')) 157 | + lines[start]) 158 | lines[min(end - 1, maxindex)] += '
' 159 | # try to find parents (for submodules) 160 | parents = [] 161 | parent = modname 162 | while '.' in parent: 163 | parent = parent.rsplit('.', 1)[0] 164 | if parent in modnames: 165 | parents.append({ 166 | 'link': urito(pagename, '_modules/' + 167 | parent.replace('.', '/')), 168 | 'title': parent}) 169 | parents.append({'link': urito(pagename, '_modules/index'), 170 | 'title': _('Module code')}) 171 | parents.reverse() 172 | # putting it all together 173 | context = { 174 | 'parents': parents, 175 | 'title': modname, 176 | 'body': _('

Source code for %s

') % modname + \ 177 | '\n'.join(lines) 178 | } 179 | yield (pagename, context, 'page.html') 180 | 181 | if not modnames: 182 | return 183 | 184 | app.builder.info(' _modules/index') 185 | html = ['\n'] 186 | # the stack logic is needed for using nested lists for submodules 187 | stack = [''] 188 | for modname in sorted(modnames): 189 | if modname.startswith(stack[-1]): 190 | stack.append(modname + '.') 191 | html.append('
    ') 192 | else: 193 | stack.pop() 194 | while not modname.startswith(stack[-1]): 195 | stack.pop() 196 | html.append('
') 197 | stack.append(modname + '.') 198 | html.append('
  • %s
  • \n' % ( 199 | urito('_modules/index', '_modules/' + modname.replace('.', '/')), 200 | modname)) 201 | html.append('' * (len(stack) - 1)) 202 | context = { 203 | 'title': _('Overview: module code'), 204 | 'body': _('

    All modules for which code is available

    ') + \ 205 | ''.join(html), 206 | } 207 | 208 | yield ('_modules/index', context, 'page.html') 209 | 210 | 211 | def setup(app): 212 | app.add_config_value('viewcode_import', True, False) 213 | app.connect('doctree-read', doctree_read) 214 | app.connect('html-collect-pages', collect_pages) 215 | app.connect('missing-reference', missing_reference) 216 | #app.add_config_value('viewcode_include_modules', [], 'env') 217 | #app.add_config_value('viewcode_exclude_modules', [], 'env') 218 | -------------------------------------------------------------------------------- /examples/compute_pi/compute_pi.py: -------------------------------------------------------------------------------- 1 | """ 2 | This example computes the numerical value of Pi by Monte Carlo. 3 | Points are sampled uniformly at random from an n-dimensional cube of 4 | side length 2R. By measuring the fraction of points contained within 5 | a ball of radius R contained in the cube, we determine Pi. 6 | """ 7 | from __future__ import division 8 | import numpy as np 9 | import copy 10 | from scipy.special import gamma 11 | from mcpele.monte_carlo import _BaseMCRunner 12 | from mcpele.monte_carlo import NullPotential 13 | from mcpele.monte_carlo import UniformRectangularSampling 14 | from mcpele.monte_carlo import CheckSphericalContainerConfig 15 | 16 | def volume_nball(radius, n): 17 | return np.power(np.pi, n / 2) * np.power(radius, n) / gamma(n / 2 + 1) 18 | 19 | def get_pi(accepted_fraction, ndim): 20 | return np.power(2 ** ndim * accepted_fraction * gamma(ndim / 2 + 1), 2 / ndim) 21 | 22 | class MC(_BaseMCRunner): 23 | def set_control(self, temp): 24 | self.set_temperature(temp) 25 | 26 | class ComputePi(object): 27 | def __init__(self, ndim=2, nsamples=1e4): 28 | # 29 | self.ndim = ndim 30 | self.nsamples = nsamples 31 | # 32 | self.radius = 44 33 | self.potential = NullPotential() 34 | self.mc = MC(self.potential, np.ones(self.ndim), 1, self.nsamples) 35 | self.step = UniformRectangularSampling(42, self.radius) 36 | self.mc.set_takestep(self.step) 37 | self.mc.set_report_steps(0) 38 | self.conftest_check_spherical_container = CheckSphericalContainerConfig(self.radius) 39 | self.mc.add_conf_test(self.conftest_check_spherical_container) 40 | self.mc.set_print_progress() 41 | self.mc.run() 42 | self.p = self.mc.get_accepted_fraction() 43 | self.pi = get_pi(self.p, self.ndim) 44 | 45 | if __name__ == "__main__": 46 | nsamples = 1e5 47 | ndim_ = [] 48 | res = [] 49 | for ndim in xrange(2, 16): 50 | print("computing pi in {} dimensions".format(ndim)) 51 | c = ComputePi(ndim=ndim, nsamples=nsamples) 52 | res.append(c.pi) 53 | ndim_.append(ndim) 54 | for (i, p) in zip(ndim_, res): 55 | print("dimension", i) 56 | print("pi", p) 57 | print("pi / np.pi", p / np.pi) 58 | -------------------------------------------------------------------------------- /examples/sfHS_WCA_fluid/radial_distribution_function.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | import numpy as np 3 | from scipy.special import gamma 4 | import matplotlib.pyplot as plt 5 | from pele.potentials import HS_WCA 6 | from pele.optimize import LBFGS_CPP 7 | from mcpele.monte_carlo import _BaseMCRunner 8 | from mcpele.monte_carlo import RandomCoordsDisplacement 9 | from mcpele.monte_carlo import RecordPairDistHistogram 10 | from mcpele.monte_carlo import MetropolisTest 11 | 12 | class MC(_BaseMCRunner): 13 | def set_control(self, temp): 14 | self.set_temperature(temp) 15 | 16 | class ComputeGR(): 17 | def __init__(self, boxdim=2, nr_particles=100, hard_phi=0.4, 18 | nr_steps=1e6, epsilon=1, alpha=0.1, verbose=False): 19 | # Settings. 20 | np.random.seed(42) 21 | # Input parameters. 22 | self.boxdim = boxdim 23 | self.nr_particles = nr_particles 24 | self.hard_phi = hard_phi 25 | self.nr_steps = nr_steps 26 | self.epsilon = epsilon 27 | self.alpha = alpha 28 | self.verbose = verbose 29 | # Derived quantities. 30 | self.hard_radii = np.ones(self.nr_particles) 31 | def volume_nball(radius, n): 32 | return np.power(np.pi, n / 2) * np.power(radius, n) / gamma(n / 2 + 1) 33 | self.box_length = np.power(np.sum(np.asarray([volume_nball(r, self.boxdim) for r in self.hard_radii])) / self.hard_phi, 1 / self.boxdim) 34 | self.box_vector = np.ones(self.boxdim) * self.box_length 35 | # HS-WCA potential. 36 | self.potential = HS_WCA(use_periodic=True, use_cell_lists=True, 37 | ndim=self.boxdim, eps=self.epsilon, 38 | sca=self.alpha, radii=self.hard_radii, 39 | boxvec=self.box_vector) 40 | # Initial configuration by minimization. 41 | self.nr_dof = self.boxdim * self.nr_particles 42 | self.x = np.random.uniform(-0.5 * self.box_length, 0.5 * self.box_length, self.nr_dof) 43 | optimizer = LBFGS_CPP(self.x, self.potential) 44 | optimizer.run() 45 | if not optimizer.get_result().success: 46 | print ("warning: minimization has not converged") 47 | self.x = optimizer.get_result().coords.copy() 48 | # Potential and MC rules. 49 | self.temperature = 1 50 | self.mc = MC(self.potential, self.x, self.temperature, self.nr_steps) 51 | self.step = RandomCoordsDisplacement(42, 1, single=True, nparticles=self.nr_particles, bdim=self.boxdim) 52 | if self.verbose: 53 | print ("initial MC stepsize") 54 | print self.step.get_stepsize() 55 | self.mc.set_takestep(self.step) 56 | self.eq_steps = self.nr_steps / 2 57 | self.mc.set_report_steps(self.eq_steps) 58 | self.gr_quench = RecordPairDistHistogram(self.box_vector, 50, self.eq_steps, self.nr_particles, optimizer=optimizer) 59 | self.gr = RecordPairDistHistogram(self.box_vector, 50, self.eq_steps, self.nr_particles) 60 | self.mc.add_action(self.gr_quench) 61 | self.mc.add_action(self.gr) 62 | self.test = MetropolisTest(44) 63 | self.mc.add_accept_test(self.test) 64 | def run(self): 65 | self.mc.set_print_progress() 66 | if not self.verbose: 67 | self.mc.disable_input_warnings() 68 | self.mc.run() 69 | if self.verbose: 70 | print ("adapted MC stepsize") 71 | print self.step.get_stepsize() 72 | def show_result(self): 73 | r = self.gr.get_hist_r() 74 | number_density = self.nr_particles / np.prod(self.box_vector) 75 | gr = self.gr.get_hist_gr(number_density, self.nr_particles) 76 | grq = self.gr_quench.get_hist_gr(number_density, self.nr_particles) 77 | plt.plot(r, gr, "o-", label="Equilibrium") 78 | plt.plot(r, grq, "x-", label="Quench") 79 | plt.xlabel(r"Distance $r$") 80 | plt.ylabel(r"Radial distr. function $g(r)$") 81 | plt.legend() 82 | plt.show() 83 | 84 | if __name__ == "__main__": 85 | box_dimension = 2 86 | nr_particles = 100 87 | hard_volume_fraction = 0.4 88 | nr_steps = 1e5 89 | alpha = 0.48 90 | verbose = False 91 | simulation = ComputeGR(boxdim=box_dimension, 92 | nr_particles=nr_particles, 93 | hard_phi=hard_volume_fraction, 94 | nr_steps=nr_steps, 95 | alpha=alpha, 96 | verbose=verbose) 97 | simulation.run() 98 | simulation.show_result() 99 | -------------------------------------------------------------------------------- /mcpele/__init__.py: -------------------------------------------------------------------------------- 1 | import logging as _mcpele_logging 2 | import sys as _mcpele_sys 3 | 4 | logger = _mcpele_logging.getLogger("mcpele") 5 | global_handler = _mcpele_logging.StreamHandler(_mcpele_sys.stdout) 6 | logger.addHandler(global_handler) 7 | logger.setLevel(_mcpele_logging.DEBUG) 8 | 9 | -------------------------------------------------------------------------------- /mcpele/monte_carlo/__init__.py: -------------------------------------------------------------------------------- 1 | from _accept_test_cpp import MetropolisTest 2 | from _conf_test_cpp import CheckSphericalContainer 3 | from _conf_test_cpp import CheckSphericalContainerConfig 4 | from _conf_test_cpp import ConfTestOR 5 | from _takestep_cpp import RandomCoordsDisplacement 6 | from _takestep_cpp import SampleGaussian 7 | from _takestep_cpp import GaussianCoordsDisplacement 8 | from _takestep_cpp import ParticlePairSwap 9 | from _takestep_cpp import TakeStepPattern 10 | from _takestep_cpp import TakeStepProbabilities 11 | from _takestep_cpp import UniformSphericalSampling 12 | from _takestep_cpp import UniformRectangularSampling 13 | from _monte_carlo_cpp import _BaseMCRunner 14 | from _action_cpp import RecordEnergyHistogram 15 | from _action_cpp import RecordEnergyTimeseries 16 | from _action_cpp import RecordPairDistHistogram 17 | from _action_cpp import RecordLowestEValueTimeseries 18 | from _action_cpp import RecordDisplacementPerParticleTimeseries 19 | from _action_cpp import RecordCoordsTimeseries 20 | from _nullpotential_cpp import NullPotential 21 | from mcrunner import Metropolis_MCrunner 22 | 23 | -------------------------------------------------------------------------------- /mcpele/monte_carlo/_accept_test_cpp.pxd: -------------------------------------------------------------------------------- 1 | from libcpp cimport bool as cbool 2 | from _pele_mc cimport cppAcceptTest,_Cdef_AcceptTest, shared_ptr 3 | 4 | #=============================================================================== 5 | # Metropolis acceptance criterion 6 | #=============================================================================== 7 | 8 | cdef extern from "mcpele/metropolis_test.h" namespace "mcpele": 9 | cdef cppclass cppMetropolisTest "mcpele::MetropolisTest": 10 | cppMetropolisTest(size_t) except + 11 | size_t get_seed() except + 12 | void set_generator_seed(size_t) except + 13 | -------------------------------------------------------------------------------- /mcpele/monte_carlo/_accept_test_cpp.pyx: -------------------------------------------------------------------------------- 1 | # distutils: language = c++ 2 | # distutils: sources = accept_test.cpp 3 | 4 | import sys 5 | 6 | #=============================================================================== 7 | # Metropolis acceptance criterion 8 | #=============================================================================== 9 | 10 | cdef class _Cdef_Metropolis(_Cdef_AcceptTest): 11 | cdef cppMetropolisTest* newptr 12 | def __cinit__(self, rseed): 13 | self.thisptr = shared_ptr[cppAcceptTest]( new cppMetropolisTest(rseed)) 14 | self.newptr = self.thisptr.get() 15 | 16 | def get_seed(self): 17 | """return random number generator seed 18 | 19 | Returns 20 | ------- 21 | int 22 | random number generator seed 23 | """ 24 | cdef res = self.newptr.get_seed() 25 | return res 26 | 27 | def set_generator_seed(self, input): 28 | """sets the random number generator seed 29 | 30 | Parameters 31 | ---------- 32 | input : pos int 33 | random number generator seed 34 | """ 35 | cdef inp = input 36 | self.newptr.set_generator_seed(inp) 37 | 38 | class MetropolisTest(_Cdef_Metropolis): 39 | """Metropolis acceptance criterion 40 | 41 | This class is the Python interface for the c++ mcpele::MetropolisTest 42 | acceptance test class implementation. The Metropolis acceptance criterion 43 | accepts each move with probability 44 | 45 | .. math:: P( x_{old} \Rightarrow x_{new}) = min \{ 1, \exp [- \\beta (E_{new} - E_{old})] \} 46 | 47 | where :math:`\\beta` is the reciprocal of the temperature. 48 | """ -------------------------------------------------------------------------------- /mcpele/monte_carlo/_action_cpp.pxd: -------------------------------------------------------------------------------- 1 | cimport pele.potentials._pele as _pele 2 | cimport pele.optimize._pele_opt as _pele_opt 3 | #from pele.potentials._pele cimport array_wrap_np 4 | from _pele_mc cimport cppAction,_Cdef_Action, shared_ptr 5 | from libcpp cimport bool as cbool 6 | from libcpp.deque cimport deque 7 | 8 | # cython has no support for integer template argument. This is a hack to get around it 9 | # https://groups.google.com/forum/#!topic/cython-users/xAZxdCFw6Xs 10 | # Basically you fool cython into thinking INT2 is the type integer, 11 | # but in the generated c++ code you use 2 instead. 12 | # The cython code MyClass[INT2] will create c++ code MyClass<2>. 13 | cdef extern from *: 14 | ctypedef int INT2 "2" # a fake type 15 | ctypedef int INT3 "3" # a fake type 16 | 17 | cdef extern from "mcpele/record_energy_histogram.h" namespace "mcpele": 18 | cdef cppclass cppRecordEnergyHistogram "mcpele::RecordEnergyHistogram": 19 | cppRecordEnergyHistogram(double, double, double, size_t) except + 20 | _pele.Array[double] get_histogram() except + 21 | void print_terminal() except + 22 | double get_max() except + 23 | double get_min() except + 24 | double get_mean() except + 25 | double get_variance() except + 26 | int get_count() except + 27 | 28 | cdef extern from "mcpele/record_pair_dist_histogram.h" namespace "mcpele": 29 | cdef cppclass cppRecordPairDistHistogram "mcpele::RecordPairDistHistogram"[ndim]: 30 | cppRecordPairDistHistogram(_pele.Array[double], size_t, size_t, size_t) except + 31 | cppRecordPairDistHistogram(_pele.Array[double], size_t, size_t, size_t, shared_ptr[_pele_opt.cGradientOptimizer]) except + 32 | _pele.Array[double] get_hist_r() except + 33 | _pele.Array[double] get_hist_gr(double, size_t) except + 34 | size_t get_eqsteps() except + 35 | 36 | cdef extern from "mcpele/record_scalar_timeseries.h" namespace "mcpele": 37 | cdef cppclass cppRecordScalarTimeseries "mcpele::RecordScalarTimeseries": 38 | _pele.Array[double] get_time_series() except + 39 | void clear() except + 40 | cbool moving_average_is_stable(size_t, double) except + 41 | 42 | cdef extern from "mcpele/record_energy_timeseries.h" namespace "mcpele": 43 | cdef cppclass cppRecordEnergyTimeseries "mcpele::RecordEnergyTimeseries": 44 | cppRecordEnergyTimeseries(size_t, size_t) except + 45 | 46 | cdef extern from "mcpele/record_lowest_evalue_timeseries.h" namespace "mcpele": 47 | cdef cppclass cppRecordLowestEValueTimeseries "mcpele::RecordLowestEValueTimeseries": 48 | cppRecordLowestEValueTimeseries(size_t, size_t, 49 | shared_ptr[_pele.cBasePotential], size_t, _pele.Array[double] 50 | , size_t) except + 51 | 52 | cdef extern from "mcpele/record_displacement_per_particle_timeseries.h" namespace "mcpele": 53 | cdef cppclass cppRecordDisplacementPerParticleTimeseries "mcpele::RecordDisplacementPerParticleTimeseries": 54 | cppRecordDisplacementPerParticleTimeseries(size_t, size_t, 55 | _pele.Array[double], size_t) except + 56 | 57 | cdef extern from "mcpele/record_vector_timeseries.h" namespace "mcpele": 58 | cdef cppclass cppRecordVectorTimeseries "mcpele::RecordVectorTimeseries": 59 | deque[_pele.Array[double]] get_time_series() except + 60 | void clear() except + 61 | size_t get_record_every() except + 62 | 63 | cdef extern from "mcpele/record_coords_timeseries.h" namespace "mcpele": 64 | cdef cppclass cppRecordCoordsTimeseries "mcpele::RecordCoordsTimeseries": 65 | cppRecordCoordsTimeseries(size_t, size_t, size_t) except + 66 | _pele.Array[double] get_mean_coordinate_vector() except + 67 | _pele.Array[double] get_mean2_coordinate_vector() except + 68 | _pele.Array[double] get_variance_coordinate_vector() except + 69 | size_t get_count() except + 70 | -------------------------------------------------------------------------------- /mcpele/monte_carlo/_conf_test_cpp.pxd: -------------------------------------------------------------------------------- 1 | from libcpp cimport bool as cbool 2 | from _pele_mc cimport cppConfTest, _Cdef_ConfTest, shared_ptr 3 | 4 | cdef extern from "mcpele/check_spherical_container.h" namespace "mcpele": 5 | cdef cppclass cppCheckSphericalContainer "mcpele::CheckSphericalContainer": 6 | cppCheckSphericalContainer(double, size_t) except + 7 | 8 | cdef extern from "mcpele/check_spherical_container_config.h" namespace "mcpele": 9 | cdef cppclass cppCheckSphericalContainerConfig "mcpele::CheckSphericalContainerConfig": 10 | cppCheckSphericalContainerConfig(double) except + 11 | 12 | cdef extern from "mcpele/conf_test_OR.h" namespace "mcpele": 13 | cdef cppclass cppConfTestOR "mcpele::ConfTestOR": 14 | cppConfTestOR() except + 15 | void add_test(shared_ptr[cppConfTest]) except + 16 | -------------------------------------------------------------------------------- /mcpele/monte_carlo/_conf_test_cpp.pyx: -------------------------------------------------------------------------------- 1 | # distutils: language = c++ 2 | # distutils: sources = conf_test.cpp 3 | 4 | 5 | import sys 6 | 7 | #=============================================================================== 8 | # Check spherical container 9 | #=============================================================================== 10 | 11 | cdef class _Cdef_CheckSphericalContainer(_Cdef_ConfTest): 12 | cdef cppCheckSphericalContainer* newptr 13 | def __cinit__(self, radius, ndim): 14 | self.thisptr = shared_ptr[cppConfTest]( new cppCheckSphericalContainer(radius, ndim)) 15 | self.newptr = self.thisptr.get() 16 | 17 | class CheckSphericalContainer(_Cdef_CheckSphericalContainer): 18 | """Check that the system is within a spherical container 19 | 20 | This class is the Python interface for the c++ pele::CheckSphericalContainer 21 | configuration test class implementation 22 | 23 | Parameters 24 | ---------- 25 | radius : double 26 | radius of the spherical container, centered at **0** 27 | ndim : int 28 | dimensionality of the space (box dimensionality) 29 | """ 30 | 31 | #=============================================================================== 32 | # Check spherical container config 33 | #=============================================================================== 34 | 35 | cdef class _Cdef_CheckSphericalContainerConfig(_Cdef_ConfTest): 36 | cdef cppCheckSphericalContainerConfig* newptr 37 | def __cinit__(self, radius): 38 | self.thisptr = shared_ptr[cppConfTest]( new cppCheckSphericalContainerConfig(radius)) 39 | self.newptr = self.thisptr.get() 40 | 41 | class CheckSphericalContainerConfig(_Cdef_CheckSphericalContainerConfig): 42 | """Check that the configuration point of the system is within a spherical container 43 | 44 | Parameters 45 | ---------- 46 | radius : double 47 | radius of the spherical container, centered at **0** 48 | """ 49 | 50 | #=============================================================================== 51 | # Union of configurational tests 52 | #=============================================================================== 53 | 54 | cdef class _Cdef_ConfTestOR(_Cdef_ConfTest): 55 | cdef cppConfTestOR* newptr 56 | def __cinit__(self): 57 | self.thisptr = shared_ptr[cppConfTest]( new cppConfTestOR()) 58 | self.newptr = self.thisptr.get() 59 | 60 | def add_test(self, _Cdef_ConfTest test): 61 | """add a conf test to the union 62 | 63 | Parameters 64 | ---------- 65 | step : :class:`ConfTest` 66 | object of class :class:`ConfTest` constructed beforehand 67 | """ 68 | self.newptr.add_test(test.thisptr) 69 | 70 | class ConfTestOR(_Cdef_ConfTestOR): 71 | """Creates a union of multiple configurational tests 72 | 73 | Python interface for c++ ConfTestOR. This configurational 74 | test takes multiple conf tests and generates an union, 75 | therefore it is sufficient to satisfy one of these 76 | subtests to pass their union. 77 | 78 | """ 79 | -------------------------------------------------------------------------------- /mcpele/monte_carlo/_monte_carlo_cpp.pxd: -------------------------------------------------------------------------------- 1 | cimport pele.potentials._pele as _pele 2 | from libcpp cimport bool as cbool 3 | from _pele_mc cimport * -------------------------------------------------------------------------------- /mcpele/monte_carlo/_nullpotential_cpp.pyx: -------------------------------------------------------------------------------- 1 | # distutils: language = C++ 2 | 3 | cimport cython 4 | cimport pele.potentials._pele as _pele 5 | from _pele_mc cimport shared_ptr 6 | from pele.potentials._pele cimport BasePotential 7 | 8 | # use external c++ class 9 | cdef extern from "mcpele/nullpotential.h" namespace "mcpele": 10 | cdef cppclass cNullPotential "mcpele::NullPotential": 11 | cNullPotential() except + 12 | 13 | cdef class _Cdef_NullPotential(BasePotential): 14 | """ 15 | this is the null potential 16 | """ 17 | cdef cNullPotential* newptr 18 | 19 | def __cinit__(self): 20 | self.thisptr = shared_ptr[_pele.cBasePotential]( <_pele.cBasePotential*>new cNullPotential() ) 21 | self.newptr = self.thisptr.get() 22 | 23 | class NullPotential(_Cdef_NullPotential): 24 | """ 25 | """ 26 | -------------------------------------------------------------------------------- /mcpele/monte_carlo/_pele_mc.pxd: -------------------------------------------------------------------------------- 1 | #cython: boundscheck=False 2 | #cython: wraparound=False 3 | 4 | cimport pele.potentials._pele as _pele 5 | from pele.potentials._pele cimport shared_ptr 6 | from libcpp cimport bool as cbool 7 | 8 | #=============================================================================== 9 | # mcpele::TakeStep 10 | #=============================================================================== 11 | 12 | cdef extern from "mcpele/mc.h" namespace "mcpele": 13 | cdef cppclass cppTakeStep "mcpele::TakeStep" 14 | 15 | cdef class _Cdef_TakeStep(object): 16 | """This class is the python interface for the c++ mcpele::TakeStep base class implementation 17 | """ 18 | cdef shared_ptr[cppTakeStep] thisptr 19 | 20 | #=============================================================================== 21 | # mcpele::AcceptTest 22 | #=============================================================================== 23 | 24 | cdef extern from "mcpele/mc.h" namespace "mcpele": 25 | cdef cppclass cppAcceptTest "mcpele::AcceptTest" 26 | 27 | cdef class _Cdef_AcceptTest(object): 28 | """This class is the python interface for the c++ mcpele::AcceptTest base class implementation 29 | """ 30 | cdef shared_ptr[cppAcceptTest] thisptr 31 | 32 | #=============================================================================== 33 | # mcpele::ConfTest 34 | #=============================================================================== 35 | 36 | cdef extern from "mcpele/mc.h" namespace "mcpele": 37 | cdef cppclass cppConfTest "mcpele::ConfTest" 38 | 39 | cdef class _Cdef_ConfTest(object): 40 | """This class is the python interface for the c++ mcpele::ConfTest base class implementation 41 | """ 42 | cdef shared_ptr[cppConfTest] thisptr 43 | 44 | #=============================================================================== 45 | # mcpele::Action 46 | #=============================================================================== 47 | 48 | cdef extern from "mcpele/mc.h" namespace "mcpele": 49 | cdef cppclass cppAction "mcpele::Action" 50 | 51 | cdef class _Cdef_Action(object): 52 | """This class is the python interface for the c++ mcpele::Action base class implementation 53 | """ 54 | cdef shared_ptr[cppAction] thisptr 55 | 56 | #=============================================================================== 57 | # mcpele::MC 58 | #=============================================================================== 59 | 60 | cdef extern from "mcpele/mc.h" namespace "mcpele": 61 | cdef cppclass cppMC "mcpele::MC": 62 | cppMC(shared_ptr[_pele.cBasePotential], _pele.Array[double]&, double) except + 63 | void one_iteration() except + 64 | void run(size_t) except + 65 | void set_temperature(double) except + 66 | double get_temperature() except + 67 | void set_stepsize(double) except + 68 | void add_action(shared_ptr[cppAction]) except + 69 | void add_accept_test(shared_ptr[cppAcceptTest]) except + 70 | void add_conf_test(shared_ptr[cppConfTest]) except + 71 | void add_late_conf_test(shared_ptr[cppConfTest]) except + 72 | void set_takestep(shared_ptr[cppTakeStep]) except + 73 | void set_coordinates(_pele.Array[double]&, double) except + 74 | void reset_energy() except + 75 | double get_energy() except + 76 | _pele.Array[double] get_coords() except + 77 | _pele.Array[double] get_trial_coords() except + 78 | double get_accepted_fraction() except + 79 | size_t get_iterations_count() except + 80 | double get_conf_rejection_fraction() except + 81 | double get_E_rejection_fraction() except + 82 | size_t get_neval() except + 83 | double get_norm_coords() except + 84 | void set_report_steps(size_t) except + 85 | void abort() except + 86 | void set_print_progress() except + 87 | void enable_input_warnings() except+ 88 | void disable_input_warnings() except + 89 | cbool get_success() except+ 90 | 91 | cdef class _Cdef_BaseMC(object): 92 | """This class is the python interface for the c++ mcpele::MC base class implementation 93 | """ 94 | cdef shared_ptr[cppMC] thisptr 95 | -------------------------------------------------------------------------------- /mcpele/monte_carlo/_pele_mc.pyx: -------------------------------------------------------------------------------- 1 | # distutils: language = c++ -------------------------------------------------------------------------------- /mcpele/monte_carlo/_takestep_cpp.pxd: -------------------------------------------------------------------------------- 1 | cimport pele.potentials._pele as _pele 2 | from _pele_mc cimport cppTakeStep,_Cdef_TakeStep, shared_ptr 3 | 4 | cdef extern from "mcpele/random_coords_displacement.h" namespace "mcpele": 5 | cdef cppclass cppRandomCoordsDisplacement "mcpele::RandomCoordsDisplacement": 6 | cppRandomCoordsDisplacement(size_t, double) except + 7 | size_t get_seed() except + 8 | void set_generator_seed(size_t) except + 9 | size_t get_count() except + 10 | double get_stepsize() except + 11 | cdef cppclass cppRandomCoordsDisplacementAll "mcpele::RandomCoordsDisplacementAll": 12 | cppRandomCoordsDisplacementAll(size_t, double) except + 13 | size_t get_seed() except + 14 | void set_generator_seed(size_t) except + 15 | double get_stepsize() except + 16 | cdef cppclass cppRandomCoordsDisplacementSingle "mcpele::RandomCoordsDisplacementSingle": 17 | cppRandomCoordsDisplacementSingle(size_t, size_t, size_t, double) except + 18 | size_t get_seed() except + 19 | void set_generator_seed(size_t) except + 20 | double get_stepsize() except + 21 | 22 | cdef extern from "mcpele/uniform_spherical_sampling.h" namespace "mcpele": 23 | cdef cppclass cppUniformSphericalSampling "mcpele::UniformSphericalSampling": 24 | cppUniformSphericalSampling(size_t, double) except + 25 | void set_generator_seed(size_t) except + 26 | 27 | cdef extern from "mcpele/uniform_rectangular_sampling.h" namespace "mcpele": 28 | cdef cppclass cppUniformRectangularSampling "mcpele::UniformRectangularSampling": 29 | cppUniformRectangularSampling(size_t, _pele.Array[double]) except + 30 | void set_generator_seed(size_t) except + 31 | 32 | cdef extern from "mcpele/gaussian_coords_displacement.h" namespace "mcpele": 33 | cdef cppclass cppGaussianTakeStep "mcpele::GaussianTakeStep": 34 | cppGaussianTakeStep(size_t, double, size_t) except + 35 | size_t get_seed() except + 36 | void set_generator_seed(size_t) except + 37 | size_t get_count() except + 38 | double get_stepsize() except + 39 | cdef cppclass cppGaussianCoordsDisplacement "mcpele::GaussianCoordsDisplacement": 40 | cppGaussianCoordsDisplacement(size_t, double, size_t) except + 41 | cdef cppclass cppSampleGaussian "mcpele::SampleGaussian": 42 | cppSampleGaussian(size_t, double, _pele.Array[double]) except + 43 | 44 | cdef extern from "mcpele/particle_pair_swap.h" namespace "mcpele": 45 | cdef cppclass cppParticlePairSwap "mcpele::ParticlePairSwap": 46 | cppParticlePairSwap(size_t, size_t) except + 47 | size_t get_seed() except + 48 | void set_generator_seed(size_t) except + 49 | 50 | cdef extern from "mcpele/adaptive_takestep.h" namespace "mcpele": 51 | cdef cppclass cppAdaptiveTakeStep "mcpele::AdaptiveTakeStep": 52 | cppAdaptiveTakeStep(shared_ptr[cppTakeStep], size_t, double, 53 | double, double) except + 54 | 55 | cdef extern from "mcpele/take_step_pattern.h" namespace "mcpele": 56 | cdef cppclass cppTakeStepPattern "mcpele::TakeStepPattern": 57 | cppTakeStepPattern() except + 58 | void add_step(shared_ptr[cppTakeStep], size_t) 59 | 60 | cdef extern from "mcpele/take_step_probabilities.h" namespace "mcpele": 61 | cdef cppclass cppTakeStepProbabilities "mcpele::TakeStepProbabilities": 62 | cppTakeStepProbabilities(size_t) except + 63 | void add_step(shared_ptr[cppTakeStep], size_t) 64 | -------------------------------------------------------------------------------- /mcpele/monte_carlo/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from test_metropolis_mcrunner import * 2 | 3 | if __name__ == "__main__": 4 | unittest.main() -------------------------------------------------------------------------------- /mcpele/monte_carlo/tests/test_take_step_probability.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | import numpy as np 3 | from pele.potentials import Harmonic 4 | from mcpele.monte_carlo import _BaseMCRunner, GaussianCoordsDisplacement 5 | from mcpele.monte_carlo import TakeStepProbabilities, TakeStepPattern 6 | from mcpele.monte_carlo import RandomCoordsDisplacement, MetropolisTest 7 | from mcpele.monte_carlo import RecordEnergyHistogram 8 | import unittest 9 | 10 | class MC(_BaseMCRunner): 11 | 12 | def set_control(self, temp): 13 | self.set_temperature(temp) 14 | 15 | class TestTakeStepProbability(unittest.TestCase): 16 | 17 | def setUp(self): 18 | self.ndim = 42 19 | self.k = 100 20 | self.bdim = 2 21 | self.origin = np.zeros(self.ndim) 22 | self.potential = Harmonic(self.origin, self.k, bdim=self.bdim, com=False) 23 | self.potential_pattern = Harmonic(self.origin, self.k, bdim=self.bdim, com=False) 24 | self.temp = 1 25 | self.nr_steps = 1e4 26 | self.mc = MC(self.potential, self.origin, self.temp, self.nr_steps) 27 | self.mc_pattern = MC(self.potential_pattern, self.origin, self.temp, self.nr_steps) 28 | 29 | def test_frequencies(self): 30 | self.tsA = GaussianCoordsDisplacement(42, 1, self.ndim) 31 | self.tsA_pattern = GaussianCoordsDisplacement(42, 1, self.ndim) 32 | self.tsB = GaussianCoordsDisplacement(44, 2, self.ndim) 33 | self.tsB_pattern = GaussianCoordsDisplacement(44, 2, self.ndim) 34 | self.step = TakeStepProbabilities(42) 35 | self.step.add_step(self.tsA, 1) 36 | self.step.add_step(self.tsB, 3) 37 | self.step_pattern = TakeStepPattern() 38 | self.step_pattern.add_step(self.tsA_pattern, 1) 39 | self.step_pattern.add_step(self.tsB_pattern, 3) 40 | freqA = 1 / (1 + 3) 41 | freqB = 1 - freqA 42 | self.mc.set_takestep(self.step) 43 | self.mc.run() 44 | self.mc_pattern.set_takestep(self.step_pattern) 45 | self.mc_pattern.run() 46 | self.assertAlmostEqual(freqA, self.tsA.get_count() / self.nr_steps, delta=1e-2) 47 | self.assertAlmostEqual(freqB, self.tsB.get_count() / self.nr_steps, delta=1e-2) 48 | self.assertAlmostEqual(freqA, self.tsA_pattern.get_count() / self.nr_steps, delta=1e-2) 49 | self.assertAlmostEqual(freqB, self.tsB_pattern.get_count() / self.nr_steps, delta=1e-2) 50 | 51 | class TestTakeStepProbabilityHarmoinc(unittest.TestCase): 52 | 53 | def setUp(self): 54 | self.box_dimension = 3 55 | self.nr_particles = 10 56 | self.k = 42 57 | self.nr_dof = self.box_dimension * self.nr_particles 58 | self.origin = np.zeros(self.nr_dof) 59 | self.potential = Harmonic(self.origin, self.k, bdim=self.box_dimension, com=True) 60 | self.temp = 1 61 | self.nr_steps = 6e4 62 | self.mc = MC(self.potential, self.origin, self.temp, self.nr_steps) 63 | self.take_step_A = RandomCoordsDisplacement(42, 4, single=True, nparticles=self.nr_particles, bdim=self.box_dimension, min_acc_ratio=0.2, max_acc_ratio=0.2) 64 | self.take_step_B = RandomCoordsDisplacement(44, 0.1, single=True, nparticles=self.nr_particles, bdim=self.box_dimension, min_acc_ratio=0.2, max_acc_ratio=0.2) 65 | self.step = TakeStepProbabilities(46) 66 | self.weight_A = 22 67 | self.weight_B = 78 68 | self.step.add_step(self.take_step_A, self.weight_A) 69 | self.step.add_step(self.take_step_B, self.weight_B) 70 | self.mc.set_takestep(self.step) 71 | self.frequency_step_A = self.weight_A / (self.weight_A + self.weight_B) 72 | self.frequency_step_B = self.weight_B / (self.weight_A + self.weight_B) 73 | self.metropolis = MetropolisTest(50) 74 | self.mc.add_accept_test(self.metropolis) 75 | self.hist_min = 0 76 | self.hist_max = 1e4 77 | self.eq_steps = self.nr_steps / 2 78 | self.mc.set_report_steps(self.eq_steps) 79 | self.measure_energy = RecordEnergyHistogram(self.hist_min, self.hist_max, (self.hist_max - self.hist_min)/14, self.eq_steps) 80 | self.mc.add_action(self.measure_energy) 81 | self.true_energy = self.box_dimension * (self.nr_particles - 1) / 2 82 | 83 | def test_basic_harmonic(self): 84 | self.mc.run() 85 | self.assertAlmostEqual(self.frequency_step_A, self.take_step_A.get_count() / self.nr_steps, delta=1e-2) 86 | self.assertAlmostEqual(self.frequency_step_B, self.take_step_B.get_count() / self.nr_steps, delta=1e-2) 87 | self.assertAlmostEqual(self.take_step_A.get_stepsize(), self.take_step_B.get_stepsize(), delta=1e-2) 88 | mean_energy, var_energy = self.measure_energy.get_mean_variance() 89 | self.assertAlmostEqual(mean_energy, self.true_energy, delta=3e-1) 90 | 91 | if __name__ == "__main__": 92 | unittest.main() 93 | -------------------------------------------------------------------------------- /mcpele/parallel_tempering/__init__.py: -------------------------------------------------------------------------------- 1 | from _base_mpi_ptmc import _MPI_Parallel_Tempering 2 | from mpi_ptmc import * -------------------------------------------------------------------------------- /mcpele/parallel_tempering/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from test_run_mpi_ptmc import * 2 | 3 | if __name__ == "__main__": 4 | unittest.main() -------------------------------------------------------------------------------- /mcpele/parallel_tempering/tests/_test_run_mpi_ptmc.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | import numpy as np 3 | import argparse 4 | from pele.potentials import Harmonic 5 | from mcpele.monte_carlo import Metropolis_MCrunner 6 | from mcpele.parallel_tempering import MPI_PT_RLhandshake 7 | 8 | if __name__ == "__main__": 9 | 10 | parser = argparse.ArgumentParser(description="do nested sampling on a Lennard Jones cluster") 11 | parser.add_argument("base_directory", type=str, help="directory in which to save results") 12 | #parser.add_argument("-K", "--nreplicas", type=int, help="number of replicas", default=300) 13 | args = parser.parse_args() 14 | 15 | natoms = 4 16 | bdim = 3 17 | k=1 18 | origin = np.zeros(natoms * bdim) 19 | potential = Harmonic(origin, k, bdim=bdim, com=False) 20 | path = args.base_directory 21 | 22 | #Parallel Tempering 23 | temperature = 1.0 24 | stepsize = 1 25 | niter = 1e4 26 | mcrunner = Metropolis_MCrunner(potential, origin, temperature, stepsize, niter, hEmax=100, adjustf=0.9, 27 | adjustf_niter=3000, radius=100000, seeds=dict(metropolis=44,takestep=42)) 28 | ptrunner = MPI_PT_RLhandshake(mcrunner, 0.2, 1.6, max_ptiter=501, pfreq=10, base_directory=path, verbose=False, suppress_histogram=False) 29 | ptrunner.run() 30 | 31 | -------------------------------------------------------------------------------- /mcpele/parallel_tempering/tests/test_run_mpi_ptmc.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tempfile 3 | import numpy as np 4 | import unittest 5 | import logging 6 | 7 | def read_Visits(fname): 8 | """HACKED""" 9 | data = np.genfromtxt(fname, delimiter='\t') 10 | return data[:,0], data[:,1] 11 | 12 | class TestPTRun(unittest.TestCase): 13 | 14 | def test_heat_capacity(self): 15 | self.bdim = 3 16 | self.natoms = 4 17 | self.nprocs = 4 18 | testdir = os.path.dirname(os.path.abspath(__file__)) 19 | # create a temporary directory using the context manager 20 | tmpdir = tempfile.mkdtemp() 21 | self.cmd = 'mpiexec -n {0} python {1}/_test_run_mpi_ptmc.py {2}'.format(self.nprocs, testdir, tmpdir) 22 | #print('created temporary directory', tmpdir) 23 | os.system(self.cmd) 24 | temperatures = np.genfromtxt(os.path.join(tmpdir, 'temperatures'), delimiter='\t') 25 | for i in xrange(self.nprocs): 26 | d = tmpdir + '/{}'.format(i) 27 | pre = 'Visits.his.' 28 | files = os.listdir(d) 29 | ftlist = [] 30 | for s in files: 31 | if pre in s: 32 | ftlist.append(s) 33 | timel = [] 34 | for s in ftlist: 35 | t = float(s[len(pre):]) 36 | timel.append(t) 37 | max_t = np.amax(timel) 38 | 39 | ener, hist = read_Visits(d + '/' + pre + '{}'.format(max_t)) 40 | 41 | T = temperatures[i] 42 | 43 | average = np.average(ener, weights=hist) 44 | 45 | average2 = np.average(np.square(ener), weights=hist) 46 | 47 | cv = (average2 - average ** 2) / (T ** 2) 48 | cv_true = self.natoms * self.bdim / 2.0 49 | 50 | self.assertLess(cv - cv_true, 0.1, 'failed for replica of rank {} cv = {}'.format(i, cv)) 51 | 52 | if __name__ == "__main__": 53 | logging.basicConfig(filename='ParallelTempering.log', level=logging.DEBUG) 54 | unittest.main() 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /mcpele/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from _utils import * -------------------------------------------------------------------------------- /mcpele/utils/_utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | import numpy as np 3 | import pandas as pd 4 | 5 | def write_2d_array_to_hf5(array, key, path): 6 | """ 7 | this function can be used to dump any 2d array to a hf5 database 8 | use this to dump a trajectory to a database from python 9 | """ 10 | assert array.ndim == 2 11 | nind , ncol = array.shape 12 | ind = [i for i in xrange(nind)] 13 | col = [i for i in xrange(ncol)] 14 | df = pd.DataFrame(np.array(array), index=ind, columns=col) 15 | df.to_hdf(path, key) 16 | 17 | def read_hf5_to_2d_array(path, key): 18 | """ 19 | read a 2d array from a hf5 database 20 | """ 21 | df = pd.read_hdf(path, key) 22 | array = np.array(df.values) 23 | return array -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import glob 2 | import os 3 | import sys 4 | import subprocess 5 | 6 | from numpy.distutils.core import setup 7 | from numpy.distutils.core import Extension 8 | from numpy.distutils.misc_util import has_cxx_sources 9 | import numpy as np 10 | import pele 11 | 12 | ## Numpy header files 13 | numpy_lib = os.path.split(np.__file__)[0] 14 | numpy_include = os.path.join(numpy_lib, 'core/include') 15 | 16 | # find pele path 17 | # note: this is used both for the c++ source files and for the cython pxd files, 18 | # neither of which are "installed". This should really point to the source directory. 19 | # So this will only work if pele was built in-place 20 | try: 21 | pelepath = os.path.dirname(pele.__file__)[:-5] 22 | except: 23 | sys.stderr.write("WARNING: could't find path to pele\n") 24 | sys.exit() 25 | 26 | def generate_cython(): 27 | cwd = os.path.abspath(os.path.dirname(__file__)) 28 | print("Cythonizing sources") 29 | p = subprocess.call([sys.executable, 30 | os.path.join(cwd, 'cythonize.py'), 31 | 'mcpele', "-I %s/pele/potentials/" % pelepath], 32 | cwd=cwd) 33 | if p != 0: 34 | raise RuntimeError("Running cythonize failed!") 35 | 36 | generate_cython() 37 | 38 | # 39 | # compile fortran extension modules 40 | # 41 | 42 | class ModuleList: 43 | def __init__(self, **kwargs): 44 | self.module_list = [] 45 | self.kwargs = kwargs 46 | def add_module(self, filename): 47 | modname = filename.replace("/", ".") 48 | modname, ext = os.path.splitext(modname) 49 | self.module_list.append(Extension(modname, [filename], **self.kwargs)) 50 | 51 | setup(name='mcpele', 52 | version='0.1', 53 | description="mcpele is a library of monte carlo and parallel tempering routines buil on the pele foundation", 54 | url='https://github.com/pele-python/mcpele', 55 | packages=["mcpele", 56 | "mcpele.monte_carlo", 57 | "mcpele.parallel_tempering", 58 | # add the test directories 59 | "mcpele.monte_carlo.tests", 60 | "mcpele.parallel_tempering.tests", 61 | ], 62 | ) 63 | 64 | # 65 | # build the c++ files 66 | # 67 | 68 | include_sources_mcpele = ["source/" + f for f in os.listdir("source/") 69 | if f.endswith(".cpp")] 70 | include_dirs = [numpy_include, "source"] 71 | 72 | include_sources_pele = [pelepath+"/source/" + f for f in os.listdir(pelepath+"/source") 73 | if f.endswith(".cpp")] 74 | 75 | depends_mcpele = [os.path.join("source/mcpele", f) for f in os.listdir("source/mcpele/") 76 | if f.endswith(".cpp") or f.endswith(".h") or f.endswith(".hpp")] 77 | 78 | depends_pele = [os.path.join(pelepath+"/source/pele", f) for f in os.listdir(pelepath+"/source/pele") 79 | if f.endswith(".cpp") or f.endswith(".h") or f.endswith(".hpp")] 80 | 81 | # note: on my computer (ubuntu 12.04 gcc version 4.6.3), when compiled with the 82 | # flag -march=native I run into problems. Everything seems to run ok, but when 83 | # I run it through valgrind, valgrind complains about an unrecognized 84 | # instruction. I don't have a clue what is causing this, but it's probably 85 | # better to be on the safe side and not use -march=native 86 | #extra_compile_args = ['-I/home/sm958/Work/pele/source','-std=c++0x',"-Wall", "-Wextra", "-O3", '-funroll-loops'] 87 | # uncomment the next line to add extra optimization options 88 | 89 | include_pele_source = '-I'+ pelepath + '/source' 90 | extra_compile_args = [include_pele_source,'-std=c++0x',"-Wall", '-Wextra','-pedantic','-O3'] #,'-DDEBUG' 91 | 92 | # note: to compile with debug on and to override extra_compile_args use, e.g. 93 | # OPT="-g -O2 -march=native" python setup.py ... 94 | 95 | include_sources_all = include_sources_mcpele + include_sources_pele 96 | 97 | depends_all = depends_mcpele + depends_pele 98 | 99 | cxx_modules = [ 100 | Extension("mcpele.monte_carlo._pele_mc", 101 | ["mcpele/monte_carlo/_pele_mc.cxx"] + include_sources_all, 102 | include_dirs=include_dirs, 103 | extra_compile_args=extra_compile_args, 104 | language="c++", depends=depends_all, 105 | ), 106 | Extension("mcpele.monte_carlo._monte_carlo_cpp", 107 | ["mcpele/monte_carlo/_monte_carlo_cpp.cxx"] + include_sources_all, 108 | include_dirs=include_dirs, 109 | extra_compile_args=extra_compile_args, 110 | language="c++", depends=depends_all, 111 | ), 112 | Extension("mcpele.monte_carlo._takestep_cpp", 113 | ["mcpele/monte_carlo/_takestep_cpp.cxx"] + include_sources_all, 114 | include_dirs=include_dirs, 115 | extra_compile_args=extra_compile_args, 116 | language="c++", depends=depends_all, 117 | ), 118 | Extension("mcpele.monte_carlo._accept_test_cpp", 119 | ["mcpele/monte_carlo/_accept_test_cpp.cxx"] + include_sources_all, 120 | include_dirs=include_dirs, 121 | extra_compile_args=extra_compile_args, 122 | language="c++", depends=depends_all, 123 | ), 124 | Extension("mcpele.monte_carlo._conf_test_cpp", 125 | ["mcpele/monte_carlo/_conf_test_cpp.cxx"] + include_sources_all, 126 | include_dirs=include_dirs, 127 | extra_compile_args=extra_compile_args, 128 | language="c++", depends=depends_all, 129 | ), 130 | Extension("mcpele.monte_carlo._action_cpp", 131 | ["mcpele/monte_carlo/_action_cpp.cxx"] + include_sources_all, 132 | include_dirs=include_dirs, 133 | extra_compile_args=extra_compile_args, 134 | language="c++", depends=depends_all, 135 | ), 136 | Extension("mcpele.monte_carlo._nullpotential_cpp", 137 | ["mcpele/monte_carlo/_nullpotential_cpp.cxx"] + include_sources_all, 138 | include_dirs=include_dirs, 139 | extra_compile_args=extra_compile_args, 140 | language="c++", depends=depends_all, 141 | ), 142 | ] 143 | setup(ext_modules=cxx_modules, 144 | ) 145 | -------------------------------------------------------------------------------- /source/CODING_STYLE.rst: -------------------------------------------------------------------------------- 1 | For this project, as well as pele, we use the K&R c++ coding standard (more or 2 | less) as a default 3 | 4 | http://en.wikipedia.org/wiki/Indent_style 5 | 6 | we use 4 spaces for indentation and *no tabs* 7 | 8 | In generall, this means it looks like this 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | ... 13 | while (x == y) { 14 | something(); 15 | somethingelse(); 16 | 17 | if (some_error) { 18 | do_correct(); 19 | } else { 20 | continue_as_usual(); 21 | } 22 | } 23 | 24 | finalthing(); 25 | ... 26 | } 27 | 28 | For a class it would be something like this 29 | 30 | class MyClass{ 31 | protected: 32 | double v1; 33 | double v2; 34 | public: 35 | MyClass() 36 | : v1(0), 37 | v2(0) 38 | { 39 | do_something(); 40 | } 41 | }; 42 | 43 | Some big things I noticed that we need to fix are 44 | 45 | if and while statements have the brace on the same line 46 | 47 | if (blah) { 48 | do something 49 | } 50 | 51 | functions have braces on separate lines 52 | 53 | void func() 54 | { 55 | do something 56 | } 57 | 58 | always add white space after commas and around most operators (this is a pet peeve of mine ;)) ) 59 | 60 | func(var1,var2,var3); // no! 61 | func(var1, var2, var3) // yes! 62 | a=b+4; //no! 63 | a = b + 4; //yes! 64 | 65 | with initializer lists, put the colon on a separate line from the name. And the braces also 66 | 67 | Minimizer::Minimizer() 68 | : val(0), 69 | ptr(1) 70 | { 71 | do something 72 | } 73 | 74 | Try to keep the lines not too much longer than 80 characters. 75 | 76 | Try to generally use braces with if statements. 77 | for loops should always have braces. it's just too dangerous otherwise. 78 | 79 | // very easy to introduce problems 80 | if (condition) 81 | do_something; 82 | 83 | add a space after for, if, while, etc 84 | 85 | for(i = 0; i < N; ++i){ // no 86 | for (i = 0; i < N; ++i) { // yes 87 | 88 | Put whitespace between operators 89 | 90 | // way too little whitespace 91 | std::vector energies()const{return property_listing(&Minimum::energy);} 92 | // better, but it's still quite long and hard to read 93 | std::vector energies() const { return property_listing(&Minimum::energy); } 94 | // best 95 | std::vector energies() const 96 | { 97 | return property_listing(&Minimum::energy); 98 | } 99 | 100 | If in doubt about white space and operators, check out this list: 101 | http://legacy.python.org/dev/peps/pep-0008/#other-recommendations 102 | In particular: 103 | "If operators with different priorities are used, consider adding whitespace 104 | around the operators with the lowest priority(ies). Use your own judgment; 105 | however, never use more than one space, and always have the same amount of 106 | whitespace on both sides of a binary operator." 107 | 108 | for naming, we follow the python convention and use CamelCase for class names 109 | and lower_case_under_score for function and variable names. 110 | 111 | Ideally functions should have a name that contains a verb. It should be the 112 | action that the function performs. 113 | 114 | value() //bad 115 | get_value() //good 116 | 117 | If you can't come up with a function name that describes what the function 118 | does, that might be an indication that your function does too many things. 119 | Try breaking up your function into many functions that each perform one action. 120 | Functions should be simple enough that you can know what it's going to do just 121 | by reading the name. 122 | 123 | When naming the c++ tests we follow the standard convention and use 124 | 125 | TEST(ClassNameOrTestGroup, ActionPerformed_ExpectedResult) 126 | 127 | the above is all CamelCase except for the single underscore separating the 128 | action and the expected result. 129 | 130 | For documentation, 131 | we try to follow the c++ Doxygen format. That way we can 132 | automatically generate nice looking documentation. 133 | http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html 134 | In particular, functions should be documented like so 135 | 136 | /** 137 | * return the energy 138 | */ 139 | double get_energy(); 140 | -------------------------------------------------------------------------------- /source/adaptive_takestep.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/adaptive_takestep.h" 2 | 3 | namespace mcpele { 4 | 5 | AdaptiveTakeStep::AdaptiveTakeStep(std::shared_ptr ts, 6 | const size_t interval, const double factor, 7 | const double min_acceptance_ratio, const double max_acceptance_ratio) 8 | : m_ts(ts), 9 | m_interval(interval), 10 | m_total_steps(0), 11 | m_accepted_steps(0), 12 | m_factor(factor), 13 | m_min_acceptance_ratio(min_acceptance_ratio), 14 | m_max_acceptance_ratio(max_acceptance_ratio) 15 | { 16 | if (factor <= 0 || factor >= 1) { 17 | throw std::runtime_error("AdaptiveTakeStep::AdaptiveTakeStep: input factor has illegal value"); 18 | } 19 | } 20 | 21 | void AdaptiveTakeStep::report(pele::Array&, const double, 22 | pele::Array&, const double, const bool success, MC* mc) 23 | { 24 | ++m_total_steps; 25 | if (success) { 26 | ++m_accepted_steps; 27 | } 28 | if (mc->get_iterations_count() % m_interval == 0) { 29 | const double acceptance_fraction = static_cast(m_accepted_steps) / static_cast(m_total_steps); 30 | m_accepted_steps = 0; 31 | m_total_steps = 0; 32 | if (acceptance_fraction < get_min_acceptance_ratio()) { 33 | m_ts->increase_acceptance(m_factor); 34 | } 35 | else if (acceptance_fraction > get_max_acceptance_ratio()) { 36 | m_ts->decrease_acceptance(m_factor); 37 | } 38 | } 39 | } 40 | 41 | } // namespace mcpele 42 | -------------------------------------------------------------------------------- /source/check_spherical_container.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/check_spherical_container.h" 2 | 3 | using std::runtime_error; 4 | using pele::Array; 5 | 6 | namespace mcpele{ 7 | 8 | CheckSphericalContainer::CheckSphericalContainer(const double radius, const size_t ndim) 9 | : m_radius2(radius * radius), 10 | m_ndim(ndim) 11 | {} 12 | 13 | bool CheckSphericalContainer::conf_test(Array &trial_coords, MC * mc) 14 | { 15 | const size_t N = trial_coords.size(); 16 | for (size_t i = 0; i < N; i += m_ndim) { 17 | double r2 = 0; 18 | for (size_t j = i; j < i + m_ndim; ++j) { 19 | r2 += trial_coords[j] * trial_coords[j]; 20 | } 21 | if (r2 > m_radius2) { 22 | //printf("fail spherical container %d %f %f %f %f\n", i, sqrt(r2), x[i], x[i+1], x[i+2]); 23 | //an atom is outside the spherical container 24 | return false; 25 | } 26 | } 27 | //printf("check spherical OK "); 28 | return true; 29 | } 30 | 31 | } // namespace mcpele 32 | -------------------------------------------------------------------------------- /source/conf_test_OR.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/conf_test_OR.h" 2 | 3 | namespace mcpele { 4 | 5 | ConfTestOR::ConfTestOR(){} 6 | 7 | void ConfTestOR::add_test(std::shared_ptr test_input) 8 | { 9 | m_tests.push_back(test_input); 10 | m_tests.swap(m_tests); 11 | } 12 | 13 | bool ConfTestOR::conf_test(pele::Array &trial_coords, MC * mc) 14 | { 15 | if (m_tests.size() == 0) { 16 | throw std::runtime_error("ConfTestOR::conf_test: no conf test specified"); 17 | } 18 | for(auto & test : m_tests){ 19 | bool result = test->conf_test(trial_coords, mc); 20 | if (result){ 21 | return true; 22 | } 23 | } 24 | return false; 25 | } 26 | 27 | } // namespace mcpele 28 | -------------------------------------------------------------------------------- /source/energy_window_test.cpp: -------------------------------------------------------------------------------- 1 | #include "pele/array.h" 2 | 3 | #include "mcpele/energy_window_test.h" 4 | 5 | using pele::Array; 6 | 7 | namespace mcpele { 8 | 9 | EnergyWindowTest::EnergyWindowTest(const double min_energy, const double max_energy) 10 | : m_min_energy(min_energy), 11 | m_max_energy(max_energy) 12 | {} 13 | 14 | bool EnergyWindowTest::test(Array&, double trial_energy, 15 | Array&, double, double, MC*) 16 | { 17 | return ((trial_energy >= m_min_energy) and (trial_energy <= m_max_energy)); 18 | } 19 | 20 | } // namespace mcpele 21 | -------------------------------------------------------------------------------- /source/gaussian_coords_displacement.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/gaussian_coords_displacement.h" 2 | 3 | namespace mcpele { 4 | 5 | GaussianTakeStep::GaussianTakeStep(const size_t rseed, const double stepsize, const size_t ndim) 6 | : m_seed(rseed), 7 | m_mean(0.0), 8 | m_stdev(1.0), 9 | m_generator(rseed), 10 | m_distribution(m_mean, m_stdev), 11 | m_stepsize(stepsize), 12 | m_count(0), 13 | m_ndim(ndim), 14 | m_normal_vec(ndim) 15 | { 16 | #ifdef DEBUG 17 | std::cout<<"seed TakeStep:"<<_seed<< "\n"; 18 | #endif 19 | } 20 | 21 | GaussianCoordsDisplacement::GaussianCoordsDisplacement(const size_t rseed, const double stepsize, const size_t ndim) 22 | : GaussianTakeStep(rseed, stepsize, ndim){} 23 | 24 | /*see https://en.wikipedia.org/wiki/Multivariate_normal_distribution*/ 25 | void GaussianCoordsDisplacement::displace(pele::Array& coords, MC* mc) 26 | { 27 | this->m_sample_normal_vec(); 28 | m_normal_vec /= norm(m_normal_vec); //sample from surface of unit hypersphere 29 | for(size_t i = 0; i < m_ndim; ++i){ 30 | coords[i] += m_normal_vec[i] * m_stepsize; //here the stepsize plays the same role as the stdev. This is sampled from N(0,stepsize) 31 | } 32 | ++m_count; 33 | } 34 | 35 | SampleGaussian::SampleGaussian(const size_t rseed, const double stepsize, const pele::Array origin) 36 | : GaussianTakeStep(rseed, stepsize, origin.size()), 37 | m_origin(origin.copy()) 38 | {} 39 | 40 | /*see https://en.wikipedia.org/wiki/Multivariate_normal_distribution 41 | * SampleGaussian::displace ignore the coords passed to it and it sample 42 | * with mean centered at the origin and stdev defined by the stepsize 43 | * */ 44 | void SampleGaussian::displace(pele::Array& coords, MC* mc) 45 | { 46 | this->m_sample_normal_vec(); 47 | for(size_t i = 0; i < m_ndim; ++i){ 48 | coords[i] = m_origin[i] + m_normal_vec[i] * m_stepsize; //here the stepsize plays the same role as the stdev. This is sampled from N(0,stepsize) 49 | } 50 | ++m_count; 51 | } 52 | 53 | } // namespace mcpele 54 | -------------------------------------------------------------------------------- /source/histogram.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/histogram.h" 2 | 3 | namespace mcpele{ 4 | 5 | Histogram::Histogram(const double min, const double max, const double bin) 6 | : m_max(floor((max / bin) + 1) * bin), 7 | m_min(floor((min / bin)) * bin), 8 | m_bin(bin), 9 | m_eps(std::numeric_limits::epsilon()), 10 | m_N((m_max - m_min) / bin), 11 | m_hist(m_N, 0), 12 | m_niter(0) 13 | { 14 | #ifdef DEBUG 15 | std::cout << "histogram is of size " << m_N << "\n"; 16 | #endif 17 | } 18 | 19 | void Histogram::add_entry(double E) 20 | { 21 | m_moments(E); 22 | int i; 23 | E = E + m_eps; //this is a dirty hack, not entirely sure of its generality and possible consequences, tests seem to be fine 24 | i = floor((E - m_min) / m_bin); 25 | if (i < m_N && i >= 0) { 26 | m_hist[i] += 1; 27 | ++m_niter; 28 | } 29 | else { 30 | this->resize(E, i); 31 | } 32 | 33 | /*THIS IS A TEST*/ 34 | /*int renorm = 0; 35 | * for(vector::iterator it = _hist.begin();it != _hist.end();++it) 36 | { 37 | renorm += *it; 38 | } 39 | 40 | if (renorm != _niter) 41 | { 42 | std::cout<<" E "<= m_N) { 51 | newlen = (i + 1) - m_N; 52 | m_hist.insert(m_hist.end(), (newlen - 1), 0); 53 | m_hist.push_back(1); 54 | ++m_niter; 55 | m_max = floor((E / m_bin) + 1) * m_bin; //round to nearest increment 56 | m_N = round((m_max - m_min) / m_bin); //was round 57 | if (static_cast(m_hist.size()) != m_N) { 58 | std::cout<< " E " << E << "\n niter " << m_niter<< "\n size " << m_hist.size() << "\n min " << m_min << "\n max " << m_max << "\n i " << i << "\n N " << m_N << "\n"; 59 | assert(static_cast(m_hist.size()) == m_N); 60 | exit (EXIT_FAILURE); 61 | } 62 | std::cout<< "resized above at niter " << m_niter << "\n"; 63 | } 64 | else if (i < 0) { 65 | newlen = -1 * i; 66 | m_hist.insert(m_hist.begin(), (newlen - 1), 0); 67 | m_hist.insert(m_hist.begin(),1); 68 | ++m_niter; 69 | m_min = floor((E / m_bin)) * m_bin; //round to nearest increment 70 | m_N = round((m_max - m_min) / m_bin); //was round 71 | if (static_cast(m_hist.size()) != m_N) { 72 | std::cout<<" E "<< E << "\n niter " << m_niter << "\n size " << m_hist.size() << "\n min " << m_min << "\n max " << m_max << "\n i " << i << "\n N " << m_N << "\n"; 73 | assert(static_cast(m_hist.size()) == m_N); 74 | exit (EXIT_FAILURE); 75 | } 76 | std::cout<< "resized below at niter " << m_niter << "\n"; 77 | } 78 | else { 79 | std::cerr << "histogram encountered unexpected condition\n"; 80 | std::cout << " E " << E << "\n niter " << m_niter << "\n min " << m_min << "\n max " << m_max << "\n i " << i << "\n N " << m_N << "\n"; 81 | } 82 | } 83 | 84 | /* 85 | * Note: This gives the error bar on a bin of width _bin, under the assumption that the sum of all bin areas is 1. 86 | * */ 87 | std::vector Histogram::get_vecdata_error() const 88 | { 89 | std::vector result(m_hist.size(), 0); 90 | for (size_t i = 0; i < result.size(); ++i) { 91 | const double this_fraction = static_cast(m_hist.at(i)) / static_cast(get_count()); 92 | result.at(i) = sqrt(this_fraction * (1 - this_fraction) / m_bin) / sqrt(get_count()); 93 | } 94 | return result; 95 | } 96 | 97 | std::vector Histogram::get_vecdata_normalized() const 98 | { 99 | std::vector result(m_hist.size(), 0); 100 | for (size_t i = 0; i < m_hist.size(); ++i) { 101 | const double this_fraction = static_cast(m_hist.at(i)) / static_cast(m_niter); 102 | result.at(i) = this_fraction / m_bin; 103 | } 104 | return result; 105 | } 106 | 107 | std::vector Histogram::get_vectics() const 108 | { 109 | std::vector result(m_hist.size(), 0); 110 | for (size_t i = 0; i < m_hist.size(); ++i) { 111 | result.at(i) = get_position(i); 112 | } 113 | return result; 114 | } 115 | 116 | void Histogram::print_terminal() const 117 | { 118 | for(size_t i = 0; i < m_hist.size(); ++i) { 119 | std::cout << i << "-" << (i + 1) << ": "; 120 | std::cout << std::string(m_hist[i] * 10000 / m_niter, '*') << "\n"; 121 | } 122 | } 123 | 124 | }//namespace mcpele 125 | -------------------------------------------------------------------------------- /source/lowest_eigenvalue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "mcpele/lowest_eigenvalue.h" 4 | 5 | namespace mcpele{ 6 | 7 | FindLowestEigenvalue::FindLowestEigenvalue(std::shared_ptr landscape_potential, const size_t boxdimension, 8 | const pele::Array ranvec, const size_t lbfgsniter) 9 | : m_lowesteigpot(std::make_shared(landscape_potential, ranvec.copy(), boxdimension)), 10 | m_ranvec((ranvec.copy() /= norm(ranvec))), 11 | m_lbfgs(m_lowesteigpot, m_ranvec.copy()) 12 | { 13 | if (std::isinf(double(1) / norm(ranvec))) { 14 | throw std::runtime_error("FindLowestEigenvalue: 1/norm(ranvec) is isinf"); 15 | } 16 | m_lbfgs.set_max_iter(lbfgsniter); 17 | } 18 | 19 | double FindLowestEigenvalue::compute_lowest_eigenvalue(pele::Array coords) 20 | { 21 | m_lowesteigpot->reset_coords(coords); 22 | m_lbfgs.reset(m_ranvec); 23 | m_lbfgs.set_use_relative_f(1); 24 | m_lbfgs.run(); 25 | const double lowesteig = m_lbfgs.get_f(); 26 | return lowesteig; 27 | } 28 | 29 | }//namespace mcpele 30 | -------------------------------------------------------------------------------- /source/mc.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/mc.h" 2 | #include "mcpele/progress.h" 3 | 4 | using pele::Array; 5 | 6 | namespace mcpele { 7 | 8 | MC::MC(std::shared_ptr potential, Array& coords, const double temperature) 9 | : m_potential(potential), 10 | m_coords(coords.copy()), 11 | m_trial_coords(m_coords.copy()), 12 | m_take_step(NULL), 13 | m_nitercount(0), 14 | m_accept_count(0), 15 | m_E_reject_count(0), 16 | m_conf_reject_count(0), 17 | m_success(true), 18 | m_print_progress(false), 19 | m_niter(0), 20 | m_neval(0), 21 | m_temperature(temperature), 22 | m_report_steps(0), 23 | m_enable_input_warnings(true) 24 | { 25 | m_energy = compute_energy(m_coords); 26 | m_trial_energy = m_energy; 27 | /*std::cout<<"mcrunner Energy is "<<_energy<< "\n"; 28 | std::cout<<"mcrunner potential ptr is "<<_potential<< "\n";*/ 29 | } 30 | 31 | /** 32 | * perform the configuration tests. Stop as soon as one of them fails 33 | */ 34 | bool MC::do_conf_tests(Array x) 35 | { 36 | bool result; 37 | for (auto & test : m_conf_tests) { 38 | result = test->conf_test(x, this); 39 | if (not result) { 40 | ++m_conf_reject_count; 41 | return false; 42 | } 43 | } 44 | return true; 45 | } 46 | 47 | /** 48 | * perform the acceptance tests. Stop as soon as one of them fails 49 | */ 50 | bool MC::do_accept_tests(Array xtrial, double etrial, Array xold, double eold) 51 | { 52 | bool result; 53 | for (auto & test : m_accept_tests) { 54 | result = test->test(xtrial, etrial, xold, eold, m_temperature, this); 55 | if (not result) { 56 | ++m_E_reject_count; 57 | return false; 58 | } 59 | } 60 | return true; 61 | } 62 | 63 | /** 64 | * perform the configuration tests. Stop as soon as one of them fails 65 | */ 66 | bool MC::do_late_conf_tests(Array x) 67 | { 68 | bool result; 69 | for (auto & test : m_late_conf_tests) { 70 | result = test->conf_test(x, this); 71 | if (not result) { 72 | ++m_conf_reject_count; 73 | return false; 74 | } 75 | } 76 | return true; 77 | } 78 | 79 | void MC::do_actions(Array x, double energy, bool success) 80 | { 81 | for (auto & action : m_actions) { 82 | action->action(x, energy, success, this); 83 | } 84 | } 85 | 86 | void MC::take_steps() 87 | { 88 | m_take_step->displace(m_trial_coords, this); 89 | } 90 | 91 | 92 | void MC::one_iteration() 93 | { 94 | m_success = true; 95 | ++m_niter; 96 | ++m_nitercount; 97 | 98 | m_trial_coords.assign(m_coords); 99 | 100 | // take a step with the trial coords 101 | //_takestep->takestep(_trial_coords, _stepsize, this); 102 | take_steps(); 103 | 104 | // perform the initial configuration tests 105 | m_success = do_conf_tests(m_trial_coords); 106 | 107 | // if the trial configuration is OK, compute the energy, and run the acceptance tests 108 | if (m_success) { 109 | // compute the energy 110 | m_trial_energy = compute_energy(m_trial_coords); 111 | 112 | // perform the acceptance tests. Stop as soon as one of them fails 113 | m_success = do_accept_tests(m_trial_coords, m_trial_energy, m_coords, m_energy); 114 | } 115 | 116 | // Do some final checks to ensure the configuration is OK. 117 | // These come last because they might be computationally demanding. 118 | if (m_success) { 119 | m_success = do_late_conf_tests(m_trial_coords); 120 | } 121 | 122 | // adapt stepsize etc. 123 | if (get_iterations_count() <= m_report_steps) { 124 | m_take_step->report(m_coords, m_energy, m_trial_coords, m_trial_energy, m_success, this); 125 | } 126 | 127 | // if the step is accepted, copy the coordinates and energy 128 | if (m_success) { 129 | m_coords.assign(m_trial_coords); 130 | m_energy = m_trial_energy; 131 | ++m_accept_count; 132 | } 133 | 134 | // perform the actions on the new configuration 135 | do_actions(m_coords, m_energy, m_success); 136 | } 137 | 138 | void MC::check_input() 139 | { 140 | if (!take_step_specified()) { 141 | throw std::runtime_error("MC::check_input: takestep not set"); 142 | } 143 | if (m_enable_input_warnings) { 144 | if (m_conf_tests.size()==0 && m_late_conf_tests.size()==0) { 145 | std::cout << "warning: no conf tests set" <<"\n"; 146 | } 147 | if (m_actions.size()==0) { 148 | std::cout << "warning: no actions set" << "\n"; 149 | } 150 | if (m_accept_tests.size()==0) { 151 | std::cout << "warning: no accept tests set" << "\n"; 152 | } 153 | } 154 | } 155 | 156 | void MC::set_coordinates(pele::Array& coords, double energy) 157 | { 158 | m_coords = coords.copy(); 159 | m_energy = energy; 160 | } 161 | 162 | //this function is necessary if for example some potential parameter has been varied 163 | void MC::reset_energy() 164 | { 165 | if(m_niter > 0) { 166 | throw std::runtime_error("MC::reset_energy after first iteration is forbidden"); 167 | } 168 | m_energy = compute_energy(m_coords); 169 | } 170 | 171 | void MC::run(size_t max_iter) 172 | { 173 | check_input(); 174 | progress stat(max_iter); 175 | while(m_niter < max_iter) { 176 | this->one_iteration(); 177 | if (m_print_progress) { 178 | stat.next(m_niter); 179 | } 180 | } 181 | m_niter = 0; 182 | } 183 | 184 | } // namespace mcpele 185 | -------------------------------------------------------------------------------- /source/mcpele/adaptive_takestep.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_ADAPTIVE_TAKESTEP_H__ 2 | #define _MCPELE_ADAPTIVE_TAKESTEP_H__ 3 | 4 | #include "mcpele/mc.h" 5 | 6 | namespace mcpele { 7 | 8 | class AdaptiveTakeStep : public TakeStep { 9 | protected: 10 | std::shared_ptr m_ts; 11 | size_t m_interval; 12 | size_t m_total_steps; 13 | size_t m_accepted_steps; 14 | const double m_factor; 15 | const double m_min_acceptance_ratio; 16 | const double m_max_acceptance_ratio; 17 | public: 18 | virtual ~AdaptiveTakeStep() {} 19 | AdaptiveTakeStep(std::shared_ptr ts, const size_t interval=100, 20 | const double factor=0.9, const double min_acceptance_ratio=0.2, 21 | const double max_acceptance_ratio=0.5); 22 | void displace(pele::Array &coords, MC * mc) { m_ts->displace(coords, mc); } 23 | void report(pele::Array& old_coords, const double old_energy, 24 | pele::Array& new_coords, const double new_energy, 25 | const bool success, MC* mc); 26 | double get_min_acceptance_ratio() const { return m_min_acceptance_ratio; } 27 | double get_max_acceptance_ratio() const { return m_max_acceptance_ratio; } 28 | }; 29 | 30 | } // namespace mcpele 31 | 32 | #endif // #ifndef _MCPELE_ADAPTIVE_TAKESTEP_H__ 33 | -------------------------------------------------------------------------------- /source/mcpele/check_spherical_container.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_CHECK_SPHERICAL_CONTAINER_H__ 2 | #define _MCPELE_CHECK_SPHERICAL_CONTAINER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "pele/array.h" 11 | #include "pele/optimizer.h" 12 | #include "pele/distance.h" 13 | 14 | #include "mc.h" 15 | 16 | namespace mcpele { 17 | 18 | class CheckSphericalContainer : public ConfTest { 19 | protected: 20 | double m_radius2; 21 | size_t m_ndim; 22 | public: 23 | CheckSphericalContainer(const double radius, const size_t ndim); 24 | virtual bool conf_test(pele::Array &trial_coords, MC * mc); 25 | virtual ~CheckSphericalContainer() {} 26 | }; 27 | 28 | } // namespace mcpele 29 | 30 | #endif // #ifndef _MCPELE_CHECK_SPHERICAL_CONTAINER_H__ 31 | -------------------------------------------------------------------------------- /source/mcpele/check_spherical_container_config.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_CHECK_SPHERICAL_CONTAINER_CONFIG_H__ 2 | #define _MCPELE_CHECK_SPHERICAL_CONTAINER_CONFIG_H__ 3 | 4 | #include "mc.h" 5 | 6 | namespace mcpele { 7 | 8 | class CheckSphericalContainerConfig : public ConfTest { 9 | protected: 10 | double m_radius2; 11 | public: 12 | CheckSphericalContainerConfig(const double radius) : m_radius2(radius * radius) {} 13 | bool conf_test(pele::Array &trial_coords, MC * mc) { return pele::dot(trial_coords, trial_coords) <= m_radius2; } 14 | virtual ~CheckSphericalContainerConfig() {} 15 | }; 16 | 17 | } // namespace mcpele 18 | 19 | #endif // #ifndef _MCPELE_CHECK_SPHERICAL_CONTAINER_CONFIG_H__ 20 | -------------------------------------------------------------------------------- /source/mcpele/conf_test_OR.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_CONF_TEST_OR_H__ 2 | #define _MCPELE_CONF_TEST_OR_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include "mc.h" 8 | 9 | namespace mcpele { 10 | 11 | /** 12 | * Create union of two configurational tests, 13 | * it is sufficient for one of them to be true in order to pass the overall test. 14 | * 15 | */ 16 | class ConfTestOR : public ConfTest { 17 | private: 18 | std::vector > m_tests; 19 | public: 20 | virtual ~ConfTestOR(){} 21 | ConfTestOR(); 22 | void add_test(std::shared_ptr test_input); 23 | bool conf_test(pele::Array &trial_coords, MC * mc); 24 | }; 25 | 26 | } // namespace mcpele 27 | 28 | #endif // #ifndef _MCPELE_CONF_TEST_OR_H__ 29 | -------------------------------------------------------------------------------- /source/mcpele/energy_window_test.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_ENERGY_WINDOW_TEST_H__ 2 | #define _MCPELE_ENERGY_WINDOW_TEST_H__ 3 | 4 | #include "pele/array.h" 5 | #include "mc.h" 6 | 7 | namespace mcpele { 8 | 9 | /** 10 | * Energy window test 11 | * This test checks that the energy of the system stays within a certain energy 12 | * window 13 | */ 14 | class EnergyWindowTest : public AcceptTest { 15 | protected: 16 | double m_min_energy; 17 | double m_max_energy; 18 | public: 19 | EnergyWindowTest(const double min_energy, const double max_energy); 20 | virtual ~EnergyWindowTest() {} 21 | virtual bool test(pele::Array &trial_coords, double trial_energy, 22 | pele::Array & old_coords, double old_energy, double temperature, 23 | MC * mc); 24 | }; 25 | 26 | } // namesapce mcpele 27 | 28 | #endif // #ifndef _MCPELE_ENERGY_WINDOW_TEST_H__ 29 | -------------------------------------------------------------------------------- /source/mcpele/gaussian_coords_displacement.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_GAUSSIAN_COORDS_DISPLACEMENT_H__ 2 | #define _MCPELE_GAUSSIAN_COORDS_DISPLACEMENT_H__ 3 | 4 | #include 5 | 6 | #include "mc.h" 7 | 8 | namespace mcpele { 9 | 10 | /*GaussianTakeStep is a base class from which all the gaussian based take step routines should derive 11 | * as it implements all its basic components 12 | * */ 13 | class GaussianTakeStep : public TakeStep { 14 | protected: 15 | size_t m_seed; 16 | double m_mean; 17 | double m_stdev; 18 | std::mt19937_64 m_generator; 19 | std::normal_distribution m_distribution; 20 | double m_stepsize; 21 | size_t m_count, m_ndim; 22 | pele::Array m_normal_vec; 23 | /*draw ndim random variates from N(0,1) and fill up the m_normal_vec array with them*/ 24 | inline void m_sample_normal_vec(){ 25 | for(size_t i = 0; i < m_ndim; ++i){ 26 | double randz = m_distribution(m_generator); //this is sample from N(0,1) 27 | m_normal_vec[i] = randz; 28 | } 29 | } 30 | public: 31 | GaussianTakeStep(const size_t rseed, const double stepsize, const size_t ndim); 32 | virtual ~GaussianTakeStep() {} 33 | virtual void displace(pele::Array& coords, MC* mc)=0; 34 | size_t get_seed() const { return m_seed; } 35 | void set_generator_seed(const size_t inp) { m_generator.seed(inp); } 36 | double get_stepsize() const { return m_stepsize; } 37 | void set_stepsize(const double input) { m_stepsize = input; } 38 | size_t get_count() const { return m_count; } 39 | /*Reference: http://mathworld.wolfram.com/NormalDistribution.html*/ 40 | double expected_mean() const { return 0; } 41 | double expected_variance(const double ss) const { return ss * ss; } 42 | }; 43 | 44 | class GaussianCoordsDisplacement : public GaussianTakeStep { 45 | public: 46 | GaussianCoordsDisplacement(const size_t rseed, const double stepsize, const size_t ndim); 47 | virtual ~GaussianCoordsDisplacement() {} 48 | virtual void displace(pele::Array& coords, MC* mc); 49 | }; 50 | 51 | /** 52 | * Sample a simple Gaussian distribution N(coords, stepsize) 53 | * this step samples first from the standard normal N(0, 1) and outputs a 54 | * random variate sampled from N(0, stepsize) 55 | */ 56 | 57 | class SampleGaussian : public GaussianTakeStep { 58 | protected: 59 | pele::Array m_origin; 60 | public: 61 | SampleGaussian(const size_t rseed, const double stepsize, const pele::Array origin); 62 | virtual ~SampleGaussian() {} 63 | virtual void displace(pele::Array& coords, MC* mc); 64 | }; 65 | 66 | } // namespace mcpele 67 | 68 | #endif // #ifndef _MCPELE_GAUSSIAN_COORDS_DISPLACEMENT_H__ 69 | -------------------------------------------------------------------------------- /source/mcpele/histogram.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_HISTOGRAM_H 2 | #define _MCPELE_HISTOGRAM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "pele/array.h" 11 | 12 | namespace mcpele { 13 | 14 | /*Dynamic histogram class that expand if energies outside of the initial bounds are found. 15 | * Being generous on the initial bounds saves a lot of time in reallocation of memory, at 16 | * the cost of memory preallocation. 17 | * Notes: 18 | * ->floor always casts towards minus infinity 19 | * ->a list is used instead of a vector because more efficient at pushing forward 20 | * ->begin and end return list iterators point to the beginning and the end of the 21 | * histogram respectively. 22 | * -> the most basic test that histogram must satisfy is that there must be as many 23 | * beads as the number of iterations (commented out at the end of the script) 24 | * */ 25 | 26 | class Moments { 27 | public: 28 | typedef double data_t; 29 | typedef size_t index_t; 30 | private: 31 | data_t m_mean; 32 | data_t m_mean2; 33 | index_t m_count; 34 | public: 35 | Moments() 36 | : m_mean(0), 37 | m_mean2(0), 38 | m_count(0) 39 | {} 40 | void update(const data_t input) 41 | { 42 | m_mean = (m_mean * m_count + input) / (m_count + 1); 43 | m_mean2 = (m_mean2 * m_count + (input * input)) / (m_count + 1); 44 | if (m_count == std::numeric_limits::max()) { 45 | throw std::runtime_error("Moments: update: integer overflow"); 46 | } 47 | ++m_count; 48 | } 49 | /** 50 | * replace a data point with another one 51 | */ 52 | void replace(const data_t old_data, const data_t new_data) 53 | { 54 | m_mean += (new_data - old_data) / m_count; 55 | m_mean2 += (new_data * new_data - old_data * old_data) / m_count; 56 | } 57 | void operator() (const data_t input) { update(input); } 58 | index_t count() const { return m_count; } 59 | data_t mean() const { return m_mean; } 60 | data_t variance() const { return (m_mean2 - m_mean * m_mean); } 61 | data_t std() const { return sqrt(variance()); } 62 | }; 63 | 64 | class Histogram{ 65 | private: 66 | double m_max; 67 | double m_min; 68 | double m_bin; 69 | double m_eps; 70 | int m_N; 71 | std::vector m_hist; 72 | int m_niter; 73 | Moments m_moments; 74 | public: 75 | Histogram(const double min, const double max, const double bin); 76 | ~Histogram() {} 77 | void add_entry(double entry); 78 | double max() const { return m_max; } 79 | double min() const { return m_min; } 80 | double bin() const { return m_bin; } 81 | size_t size() const { return m_N; } 82 | int get_count() const { return m_niter; } 83 | double get_mean() const { return m_moments.mean(); } 84 | double get_variance() const { return m_moments.variance(); } 85 | std::vector::iterator begin(){ return m_hist.begin(); } 86 | std::vector::iterator end(){ return m_hist.end(); } 87 | double get_position(const size_t bin_index) const { return m_min + (0.5 + bin_index) * m_bin; } 88 | std::vector get_vectics() const; 89 | std::vector get_vecdata() const { return m_hist; } 90 | double get_entry(const size_t bin_index) const { return m_hist.at(bin_index); } 91 | std::vector get_vecdata_error() const; 92 | std::vector get_vecdata_normalized() const; 93 | void print_terminal() const; 94 | void resize(const double E, const int i); 95 | }; 96 | 97 | } // namespace mcpele 98 | 99 | #endif // #ifndef _MCPELE_HISTOGRAM_H 100 | 101 | -------------------------------------------------------------------------------- /source/mcpele/lowest_eigenvalue.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_LOWEST_EIGENVALUE_H 2 | #define _MCPELE_LOWEST_EIGENVALUE_H 3 | 4 | #include "pele/base_potential.h" 5 | #include "pele/lbfgs.h" 6 | #include "pele/lowest_eig_potential.h" 7 | 8 | namespace mcpele{ 9 | 10 | 11 | class FindLowestEigenvalue{ 12 | private: 13 | std::shared_ptr m_lowesteigpot; 14 | pele::Array m_ranvec; 15 | pele::LBFGS m_lbfgs; 16 | public: 17 | FindLowestEigenvalue(std::shared_ptr landscape_potential, const size_t boxdimension, 18 | const pele::Array ranvec, const size_t lbfgsniter); 19 | double compute_lowest_eigenvalue(pele::Array coords); 20 | }; 21 | 22 | 23 | }//namespace mcpele 24 | 25 | #endif//#ifndef _MCPELE_LOWEST_EIGENVALUE_H 26 | -------------------------------------------------------------------------------- /source/mcpele/mc.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_MC_H 2 | #define _MCPELE_MC_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "pele/array.h" 10 | #include "pele/base_potential.h" 11 | 12 | namespace mcpele{ 13 | 14 | class MC; 15 | 16 | /* 17 | * Action 18 | */ 19 | 20 | class Action { 21 | public: 22 | //Action(){std::cout<< "Action()" << "\n";} 23 | //virtual ~Action(){std::cout << "~Action()" << "\n";} 24 | virtual ~Action(){} 25 | virtual void action(pele::Array &coords, double energy, bool accepted, 26 | MC* mc) =0; 27 | }; 28 | 29 | /* 30 | * Accept Test 31 | */ 32 | 33 | class AcceptTest{ 34 | public: 35 | //AcceptTest(){std::cout << "AcceptTest()" << "\n";} 36 | //virtual ~AcceptTest(){std::cout << "~AcceptTest()" << "\n";} 37 | virtual ~AcceptTest(){} 38 | virtual bool test(pele::Array &trial_coords, double trial_energy, 39 | pele::Array & old_coords, double old_energy, double temperature, 40 | MC * mc) =0; 41 | }; 42 | 43 | /* 44 | * Accept Test 45 | */ 46 | 47 | class ConfTest{ 48 | public: 49 | //ConfTest(){std::cout << "ConfTest()" << "\n";} 50 | //virtual ~ConfTest(){std::cout << "~ConfTest()" << "\n";} 51 | virtual ~ConfTest(){} 52 | virtual bool conf_test(pele::Array &trial_coords, MC * mc) =0; 53 | }; 54 | 55 | /* 56 | * Take Step 57 | */ 58 | 59 | class TakeStep { 60 | public: 61 | virtual ~TakeStep() {} 62 | virtual void displace(pele::Array& coords, MC* mc) = 0; 63 | virtual void report(pele::Array&, const double, 64 | pele::Array&, const double, const bool, MC*) {} 65 | virtual void increase_acceptance(const double) {} 66 | virtual void decrease_acceptance(const double) {} 67 | }; 68 | 69 | /** 70 | * Monte Carlo 71 | * _coords and _trialcoords are arrays that store coordinates and trial coordinates respectively 72 | * _potential is on object of Pele::BasePotential type that defines the interaction potential 73 | * _E_reject_count is the count of rejections due to an energy test (e.g. Metropolis) 74 | * _conf_reject_count is the count of rejections due to a configuration test (e.g. spherical container) 75 | * _niter is the count of steps whithin a MCMC run, it is reset to zero at the end of the run 76 | * _nitercount is the cumulative number of MCMC steps taken by the class 77 | * _neval is the number of energy evaluations 78 | * _temperature is the temperature at which the simulation is performed 79 | * _energy is the current energy of the system 80 | * _success records whether the step has been accepted or rejected 81 | */ 82 | 83 | class MC { 84 | public: 85 | typedef std::vector > actions_t; 86 | typedef std::vector > accept_t; 87 | typedef std::vector > conf_t; 88 | protected: 89 | std::shared_ptr m_potential; 90 | pele::Array m_coords; 91 | pele::Array m_trial_coords; 92 | actions_t m_actions; 93 | accept_t m_accept_tests; 94 | conf_t m_conf_tests; 95 | conf_t m_late_conf_tests; 96 | std::shared_ptr m_take_step; 97 | size_t m_nitercount; 98 | size_t m_accept_count; 99 | size_t m_E_reject_count; 100 | size_t m_conf_reject_count; 101 | bool m_success; 102 | /*nitercount is the cumulative count, it does not get reset at the end of run*/ 103 | bool m_print_progress; 104 | public: 105 | /*need to keep these public to make them accessible to tests and actions, be careful though!*/ 106 | size_t m_niter; 107 | size_t m_neval; 108 | double m_temperature; 109 | double m_energy; 110 | double m_trial_energy; 111 | private: 112 | size_t m_report_steps; 113 | bool m_enable_input_warnings; 114 | public: 115 | MC(std::shared_ptr potential, pele::Array& coords, const double temperature); 116 | virtual ~MC() {} 117 | void one_iteration(); 118 | void run(const size_t max_iter); 119 | void set_temperature(const double T) { m_temperature = T; } 120 | double get_temperature() const { return m_temperature; } 121 | void set_report_steps(const size_t report_steps) { m_report_steps = report_steps; } 122 | size_t get_report_steps() const { return m_report_steps; } 123 | void add_action(std::shared_ptr action) { m_actions.push_back(action); } 124 | void add_accept_test(std::shared_ptr accept_test) { m_accept_tests.push_back(accept_test); } 125 | void add_conf_test(std::shared_ptr conf_test) { m_conf_tests.push_back(conf_test); } 126 | void add_late_conf_test(std::shared_ptr conf_test) { m_late_conf_tests.push_back(conf_test); } 127 | void set_takestep(std::shared_ptr takestep) { m_take_step = takestep; } 128 | std::shared_ptr get_takestep() const { return m_take_step; } 129 | void set_coordinates(pele::Array& coords, double energy); 130 | double get_energy() const { return m_energy; } 131 | void reset_energy(); 132 | double get_trial_energy() const { return m_trial_energy; } 133 | pele::Array get_coords() const { return m_coords.copy(); } 134 | pele::Array get_trial_coords() const { return m_trial_coords.copy(); } 135 | double get_norm_coords() const { return norm(m_coords); } 136 | size_t get_naccept() const { return m_accept_count; } 137 | size_t get_nreject() const { return m_nitercount - m_accept_count; } 138 | double get_accepted_fraction() const { return static_cast(m_accept_count) / 139 | static_cast(m_nitercount); } 140 | double get_conf_rejection_fraction() const { return static_cast(m_conf_reject_count) / 141 | static_cast(m_nitercount); } 142 | double get_E_rejection_fraction() const { return static_cast(m_E_reject_count) / 143 | static_cast(m_nitercount); } 144 | size_t get_iterations_count() const { return m_nitercount; } 145 | size_t get_neval() const { return m_neval; } 146 | std::shared_ptr get_potential_ptr() { return m_potential; } 147 | bool take_step_specified() const { return m_take_step != NULL; } 148 | bool report_steps_specified() const { return get_report_steps() > 0; } 149 | void check_input(); 150 | void set_print_progress(const bool input) { m_print_progress = input; } 151 | void set_print_progress() { set_print_progress(true); } 152 | bool get_success() const { return m_success; } 153 | /** 154 | * this will trigger premature exit from the MC run loop 155 | */ 156 | void abort() { m_niter = std::numeric_limits::max(); } 157 | void enable_input_warnings() { m_enable_input_warnings = true; } 158 | void disable_input_warnings() { m_enable_input_warnings = false; } 159 | protected: 160 | inline double compute_energy(pele::Array x) 161 | { 162 | ++m_neval; 163 | return m_potential->get_energy(x); 164 | } 165 | bool do_conf_tests(pele::Array x); 166 | bool do_accept_tests(pele::Array xtrial, double etrial, pele::Array xold, double eold); 167 | bool do_late_conf_tests(pele::Array x); 168 | void do_actions(pele::Array x, double energy, bool success); 169 | void take_steps(); 170 | }; 171 | 172 | }//namespace mcpele 173 | 174 | #endif//#ifndef _MCPELE_MC_H 175 | -------------------------------------------------------------------------------- /source/mcpele/metropolis_test.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_METROPOLIS_TEST_H__ 2 | #define _MCPELE_METROPOLIS_TEST_H__ 3 | 4 | #include 5 | 6 | #include "pele/array.h" 7 | #include "mc.h" 8 | 9 | namespace mcpele { 10 | 11 | /** 12 | * Metropolis acceptance criterion 13 | */ 14 | class MetropolisTest : public AcceptTest { 15 | protected: 16 | size_t m_seed; 17 | std::mt19937_64 m_generator; 18 | std::uniform_real_distribution m_distribution; 19 | public: 20 | MetropolisTest(const size_t rseed); 21 | virtual ~MetropolisTest() {} 22 | virtual bool test(pele::Array &trial_coords, double trial_energy, 23 | pele::Array & old_coords, double old_energy, double temperature, 24 | MC * mc); 25 | size_t get_seed() const {return m_seed;} 26 | void set_generator_seed(const size_t inp) { m_generator.seed(inp); } 27 | }; 28 | 29 | } // namespace mcpele 30 | 31 | #endif // #ifndef _MCPELE_METROPOLIS_TEST_H__ 32 | -------------------------------------------------------------------------------- /source/mcpele/moving_average.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_MOVING_AVERAGE_H 2 | #define _MCPELE_MOVING_AVERAGE_H 3 | 4 | #include 5 | #include 6 | 7 | #include "histogram.h" 8 | 9 | namespace mcpele { 10 | 11 | /** 12 | * Computes moving averages of time series. 13 | * Reference to time series, from small to large times, is in m_time_series. 14 | * Assume that one wants to compute moving averages for the rightmost (latest) 15 | * m_nr_steps_total elements of the time series. 16 | * The number of time series steps that go into one moving average is 17 | * m_nr_steps_ma. 18 | * The number of different moving averages that one can compute, given these 19 | * two parameters (m_nr_steps_total and m_window_size) is m_nr_steps_ma. 20 | * Moving average is initialised to the leftmost moving average. 21 | * After that shift_right() moves the moving average window one time series 22 | * step further to the right (to the future). 23 | * In case shift_right() reaches the last step in the time series, the moving 24 | * average window returns to the initial position. 25 | */ 26 | class MovingAverageAcc { 27 | private: 28 | const std::vector& m_time_series; 29 | const size_t m_nr_steps_total; 30 | const size_t m_window_size; 31 | const size_t m_nr_steps_ma; 32 | std::vector::const_iterator m_begin; 33 | std::vector::const_iterator m_end; 34 | mcpele::Moments m_moments; 35 | public: 36 | MovingAverageAcc(const std::vector& time_series, const size_t nr_steps_total, const size_t nr_steps_ma) 37 | : m_time_series(time_series), 38 | m_nr_steps_total(nr_steps_total), 39 | m_window_size(nr_steps_ma), //window size 40 | m_nr_steps_ma(nr_steps_total - m_window_size + 1), //number of steps to move window from left to right end 41 | m_begin(m_time_series.end() - nr_steps_total), 42 | m_end(m_begin + m_window_size), 43 | m_moments() 44 | { 45 | if (nr_steps_ma % 2 != 0) { 46 | throw std::runtime_error("MovingAverageAcc: illegal input: nr_steps_ma"); 47 | } 48 | if (time_series.size() < nr_steps_total) { 49 | throw std::runtime_error("MovingAverageAcc: illegal input: time series too short"); 50 | } 51 | //initialise moments 52 | for(auto it = m_begin; it != m_end; ++it) { 53 | m_moments(*it); 54 | } 55 | } 56 | double get_mean() const { return m_moments.mean(); } 57 | double get_variance() const { return m_moments.variance(); } 58 | size_t get_nr_steps_ma() const { return m_nr_steps_ma; } 59 | void shift_right() 60 | { 61 | ++m_begin; 62 | ++m_end; 63 | if (m_end == m_time_series.end()) { 64 | reset(); 65 | } 66 | else { 67 | m_moments.replace(*(m_begin - 1), *(m_end - 1)); 68 | } 69 | } 70 | void reset() 71 | { 72 | m_begin = m_time_series.end() - m_nr_steps_total; 73 | m_end = m_begin + m_window_size; 74 | m_moments = mcpele::Moments(); 75 | //initialise moments 76 | for(auto it = m_begin; it != m_end; ++it) { 77 | m_moments(*it); 78 | } 79 | } 80 | }; 81 | 82 | } // namespace mcpele 83 | 84 | #endif // #ifndef _MCPELE_MOVING_AVERAGE_H 85 | -------------------------------------------------------------------------------- /source/mcpele/nullpotential.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_NULLPOTENTIAL_H 2 | #define _MCPELE_NULLPOTENTIAL_H 3 | 4 | #include 5 | #include 6 | 7 | #include "pele/base_potential.h" 8 | 9 | namespace mcpele { 10 | 11 | class NullPotential : public pele::BasePotential { 12 | public: 13 | NullPotential() {}; 14 | virtual ~NullPotential(){} 15 | virtual double inline get_energy(pele::Array x){return 0.;}; 16 | virtual double inline get_energy_gradient(pele::Array x, pele::Array grad){return 0.;}; 17 | }; 18 | 19 | } // namespace mcpele 20 | 21 | #endif // #ifndef _MCPELE_NULLPOTENTIAL_H 22 | -------------------------------------------------------------------------------- /source/mcpele/pair_dist_histogram.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_PAIR_DIST_HISTOGRAM_H 2 | #define _MCPELE_PAIR_DIST_HISTOGRAM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "pele/distance.h" 11 | 12 | #include "mcpele/histogram.h" 13 | 14 | namespace mcpele{ 15 | 16 | template 17 | class PairDistHistogram{ 18 | private: 19 | pele::periodic_distance m_distance; 20 | const size_t m_nr_bins; 21 | const double m_min_dist; 22 | const double m_max_dist; 23 | const double m_delta_bin; 24 | mcpele::Histogram m_hist; 25 | size_t m_nr_configs; 26 | public: 27 | PairDistHistogram(pele::Array boxvector, const size_t nr_bins) 28 | : m_distance(boxvector), 29 | m_nr_bins(nr_bins), 30 | m_min_dist(0), 31 | m_max_dist(0.5 * *std::min_element(boxvector.data(), boxvector.data() + BOXDIM)), 32 | m_delta_bin((m_max_dist - m_min_dist) / static_cast(m_nr_bins)), 33 | m_hist(m_min_dist, m_max_dist, m_delta_bin), 34 | m_nr_configs(0) 35 | { 36 | if (BOXDIM != boxvector.size()) { 37 | throw std::runtime_error("PairDistHistogram: illegal boxvector size"); 38 | } 39 | } 40 | virtual ~PairDistHistogram() {} 41 | void add_configuration(pele::Array coords) 42 | { 43 | ++m_nr_configs; 44 | const size_t nr_particles(coords.size() / BOXDIM); 45 | for (size_t i = 0; i < nr_particles; ++i) { 46 | for (size_t j = i + 1; j < nr_particles; ++j) { 47 | add_distance(i, j, coords.data()); 48 | } 49 | } 50 | } 51 | void add_distance(const size_t i, const size_t j, const double* coor) 52 | { 53 | double rij[BOXDIM]; 54 | m_distance.get_rij(rij, coor + i * BOXDIM, coor + j * BOXDIM); 55 | const double r = sqrt(std::inner_product(rij, rij + BOXDIM, rij, double(0))); 56 | if (r > m_max_dist) { 57 | // here, g(r) measurement is resticted to a disc domain of radius 58 | // m_max_dist in distance space; could be done differently 59 | return; 60 | } 61 | m_hist.add_entry(r); 62 | } 63 | double volume_nball(const double radius, const size_t ndim) const 64 | { 65 | return pow(M_PI, 0.5 * ndim) * pow(radius, ndim) / tgamma(0.5 * ndim + 1); 66 | } 67 | std::vector get_vecdata_r() const 68 | { 69 | std::vector result(m_nr_bins); 70 | for (size_t i = 0; i < m_nr_bins; ++i) { 71 | const double r = m_hist.get_position(i); 72 | result.at(i) = r; 73 | } 74 | return result; 75 | } 76 | std::vector get_vecdata_gr(const double number_density, const size_t nr_particles) const 77 | { 78 | std::vector result(m_nr_bins); 79 | for (size_t i = 0; i < m_nr_bins; ++i) { 80 | const double r = m_hist.get_position(i); 81 | const double delta_r = m_hist.bin(); 82 | const double shell_volume_r = volume_nball(r + 0.5 * delta_r, BOXDIM) - volume_nball(r - 0.5 * delta_r, BOXDIM); 83 | const double nid = shell_volume_r * number_density; 84 | const double normalization = 2.0 / (static_cast(m_nr_configs) * static_cast(nr_particles) * nid); 85 | const double g_of_r = normalization * static_cast(m_hist.get_entry(i)); 86 | result.at(i) = g_of_r; 87 | } 88 | return result; 89 | } 90 | }; 91 | 92 | } //namespace mcpele 93 | 94 | #endif//#ifndef _MCPELE_PAIR_DIST_HISTOGRAM_H 95 | -------------------------------------------------------------------------------- /source/mcpele/particle_pair_swap.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_PARTICLE_PAIR_SWAP_H__ 2 | #define _MCPELE_PARTICLE_PAIR_SWAP_H__ 3 | 4 | #include 5 | 6 | #include "mc.h" 7 | 8 | namespace mcpele { 9 | 10 | class ParticlePairSwap : public TakeStep { 11 | private: 12 | size_t m_seed; 13 | std::mt19937_64 m_generator; 14 | std::uniform_int_distribution m_distribution; 15 | const size_t m_nr_particles; 16 | public: 17 | virtual ~ParticlePairSwap() {} 18 | ParticlePairSwap(const size_t seed, const size_t nr_particles); 19 | void displace(pele::Array& coords, MC* mc); 20 | void swap_coordinates(const size_t particle_a, const size_t particle_b, pele::Array& coords); 21 | size_t get_seed() const { return m_seed; } 22 | void set_generator_seed(const size_t inp); 23 | }; 24 | 25 | } // namespace mcpele 26 | 27 | #endif // #ifndef _MCPELE_PARTICLE_PAIR_SWAP_H__ 28 | -------------------------------------------------------------------------------- /source/mcpele/pattern_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_PATTERN_MANAGER_H__ 2 | #define _MCPELE_PATTERN_MANAGER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "mc.h" 9 | 10 | namespace mcpele { 11 | 12 | template 13 | class PatternManager { 14 | public: 15 | typedef typename std::vector > vec_t; 16 | private: 17 | vec_t m_step_repetitions; 18 | size_t m_current_step_index; 19 | size_t m_current_step_count; 20 | bool m_initialized; 21 | public: 22 | virtual ~PatternManager() {} 23 | PatternManager() 24 | : m_initialized(false) 25 | {} 26 | const PatternManager& operator ++ () 27 | { 28 | --m_current_step_count; 29 | if (m_current_step_count == 0) { 30 | ++m_current_step_index; 31 | if (m_current_step_index == m_step_repetitions.size()) { 32 | m_current_step_index = 0; 33 | } 34 | m_current_step_count = m_step_repetitions.at(m_current_step_index).first; 35 | assert(m_current_step_count); 36 | } 37 | return *this; 38 | } 39 | void add(const T index_input, const size_t repetitions_input=1) 40 | { 41 | if (repetitions_input < 1) { 42 | throw std::range_error("PatternManager::add: illegal input"); 43 | } 44 | m_step_repetitions.push_back(std::make_pair(repetitions_input, index_input)); 45 | m_current_step_index = 0; 46 | m_current_step_count = m_step_repetitions.at(0).first; 47 | if (!m_initialized) { 48 | m_initialized = true; 49 | } 50 | } 51 | T get_step_ptr() const 52 | { 53 | if (!m_initialized) { 54 | throw std::runtime_error("PatternManager::get_step_index: illegal access"); 55 | } 56 | return m_step_repetitions.at(m_current_step_index).second; 57 | } 58 | /** 59 | * Return visualization of the step pattern. 60 | * Steps are represented by integer labels, starting from 0, in the order of 61 | * addition to the pattern. 62 | */ 63 | std::vector get_pattern() const 64 | { 65 | std::vector result; 66 | for (typename vec_t::const_iterator i = m_step_repetitions.begin(); i != m_step_repetitions.end(); ++i) { 67 | const std::vector tmp(i->first, static_cast(i - m_step_repetitions.begin())); 68 | result.insert(result.end(), tmp.begin(), tmp.end()); 69 | } 70 | result.swap(result); 71 | assert(result.front() == 0); 72 | assert(result.back() == m_step_repetitions.size() - 1); 73 | return result; 74 | } 75 | std::vector get_pattern_direct() 76 | { 77 | m_current_step_index = 0; 78 | m_current_step_count = m_step_repetitions.at(0).first; 79 | assert(m_current_step_index == 0); 80 | size_t pattern_length = 0; 81 | for (typename vec_t::const_iterator i = m_step_repetitions.begin(); i != m_step_repetitions.end(); ++i) { 82 | pattern_length += i->first; 83 | } 84 | assert(m_current_step_index == 0); 85 | std::vector result; 86 | for (size_t i = 0; i < pattern_length; ++i, ++*this) { 87 | result.push_back(m_current_step_index); 88 | } 89 | assert(result.size() == pattern_length); 90 | assert(result.front() == 0); 91 | assert(result.back() == m_step_repetitions.size() - 1); 92 | return result; 93 | } 94 | }; 95 | 96 | } // namespace mcpele 97 | 98 | #endif // #ifndef _MCPELE_PATTERN_MANAGER_H__ 99 | -------------------------------------------------------------------------------- /source/mcpele/progress.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_PROGRESS_H 2 | #define _MCPELE_PROGRESS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace mcpele{ 11 | 12 | /* 13 | * For a loop of total_iterations steps (assumed to take on average the same time), 14 | * progress keeps track of the time that elapsed, computes the likely total time 15 | * the whole loop will take, prints the local time at which the loop will likely 16 | * terminate, and prints how much time is left until loop terimnation. 17 | * Output is printed 100 times, for each percent of the loop that is done. 18 | * 19 | * The usage is as follows: 20 | * 21 | * const int iterations = 100000; 22 | * progress status(iterations); 23 | * size_t niter = 0; 24 | * while (niter < iterations) { 25 | * do_something; 26 | * ++niter; 27 | * status.next(niter); 28 | * } 29 | * 30 | * Example output: 31 | * 32 | * 28 %. done: 3 s. todo: 10 s. total: 14 s. ends: Thu Jul 24 13:56:51 2014 33 | * 34 | */ 35 | 36 | class progress{ 37 | public: 38 | typedef size_t index_t; 39 | typedef double float_t; 40 | typedef long long int long_t; 41 | private: 42 | const float_t m_inverse_of_total_iterations; 43 | const index_t m_total_iterations; 44 | index_t m_curr; 45 | index_t m_prev; 46 | const long_t m_start_time; 47 | public: 48 | 49 | progress(const index_t totalin) 50 | : m_inverse_of_total_iterations(1.0/static_cast(totalin)), 51 | m_total_iterations(totalin), 52 | m_curr(0), 53 | m_prev(0), 54 | m_start_time(clock()) 55 | {} 56 | 57 | index_t get_current_percentage() const { return m_curr; } 58 | 59 | void next(const index_t idx, std::ostream& stm = std::cout) 60 | { 61 | m_curr = std::round((static_cast(idx) / static_cast(m_total_iterations)) * float_t(100)); 62 | if (m_curr != m_prev) { 63 | print_time_percentage(idx - 1, stm); 64 | if (m_curr == 100) { 65 | stm << "\n"; 66 | } 67 | } 68 | } 69 | 70 | void print_time_percentage(const index_t smp, std::ostream& stm) 71 | { 72 | stm << "\r"; 73 | // percentage done 74 | update_and_print_percentage_complete(stm); 75 | stm << ". "; 76 | // time elapsed 77 | get_and_print_elapsed_time(stm); 78 | stm << ". "; 79 | // estimated time to completion 80 | estimate_and_print_time_to_complete(smp, stm); 81 | stm << ". "; 82 | // estimated total time 83 | estimate_and_print_total_time(smp, stm); 84 | stm << ". "; 85 | // estimated completion time in local time 86 | estimate_and_print_completion_local_time(smp, stm); 87 | stm << " "; 88 | stm.flush(); 89 | } 90 | 91 | void update_and_print_percentage_complete(std::ostream& stm) 92 | { 93 | stm << m_curr << " %"; 94 | m_prev = m_curr; 95 | } 96 | 97 | void get_and_print_elapsed_time(std::ostream& stm) 98 | { 99 | stm << "done" << ": "; 100 | print_estimated_time(clock() - m_start_time, stm); 101 | } 102 | 103 | void estimate_and_print_time_to_complete(const index_t smp, std::ostream& stm) 104 | { 105 | stm << "todo" << ": "; 106 | print_estimated_time(((float_t)(m_total_iterations - smp - 1) / (float_t)(smp + 1)) * (float_t)(clock() - m_start_time), stm); 107 | } 108 | 109 | void estimate_and_print_total_time(const index_t smp, std::ostream& stm) 110 | { 111 | stm << "total" << ": "; 112 | print_estimated_time(((float_t)m_total_iterations / (float_t)(smp + 1)) * (float_t)(clock() - m_start_time), stm); 113 | } 114 | 115 | void estimate_and_print_completion_local_time(const index_t smp, std::ostream& stm) 116 | { 117 | stm << "ends" << ": "; 118 | time_t timer = time(NULL); 119 | timer += (((float_t)(m_total_iterations - smp - 1) / (float_t)(smp + 1)) * (float_t)(clock() - m_start_time)) / CLOCKS_PER_SEC; 120 | std::string tmp(ctime(&timer)); 121 | tmp.erase(std::remove(tmp.begin(), tmp.end(), '\n'), tmp.end()); 122 | stm << tmp; 123 | } 124 | 125 | void print_estimated_time(const long_t inp, std::ostream& stm) 126 | { 127 | long_t tm = inp; 128 | long_t days = tm / ((long_t)CLOCKS_PER_SEC * (long_t)60 * (long_t)60 * (long_t)24); 129 | tm %= ((long_t)CLOCKS_PER_SEC * (long_t)60 * (long_t)60 * (long_t)24); 130 | long_t hours = tm / ((long_t)CLOCKS_PER_SEC * (long_t)60 * (long_t)60); 131 | tm %= ((long_t)CLOCKS_PER_SEC * (long_t)60 * (long_t)60); 132 | long_t minutes = tm / ((long_t)CLOCKS_PER_SEC * (long_t)60); 133 | tm %= ((long_t)CLOCKS_PER_SEC * (long_t)60); 134 | long_t seconds = tm / ((long_t)CLOCKS_PER_SEC); 135 | if (days) { 136 | stm << days << " d "; 137 | } 138 | if (hours) { 139 | stm << hours << " h "; 140 | } 141 | if (minutes) { 142 | stm << minutes << " m "; 143 | } 144 | if (seconds) { 145 | stm << seconds << " s"; 146 | } 147 | } 148 | 149 | }; 150 | 151 | 152 | }//namespace mcpele 153 | 154 | #endif//#ifndef _MCPELE_PROGRESS_H 155 | -------------------------------------------------------------------------------- /source/mcpele/random_coords_displacement.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_RANDOM_COORDS_DISPLACEMENT_H__ 2 | #define _MCPELE_RANDOM_COORDS_DISPLACEMENT_H__ 3 | 4 | #include 5 | 6 | #include "mc.h" 7 | 8 | namespace mcpele { 9 | 10 | /** 11 | * Random coords displacement, generates a random displacement for a N 12 | * dimensional system sampling from a N-dimensional sphere. 13 | * The stepsize is defined per coordinates, that's why the maximum stepsize is 14 | * sqrt(N) * stepsize. 15 | */ 16 | class RandomCoordsDisplacement : public TakeStep { 17 | protected: 18 | size_t m_seed; 19 | std::mt19937_64 m_generator; 20 | std::uniform_real_distribution m_real_distribution; 21 | double m_stepsize; 22 | size_t m_count; 23 | public: 24 | RandomCoordsDisplacement(const size_t rseed, const double stepsize=1); 25 | virtual ~RandomCoordsDisplacement() {} 26 | virtual void displace(pele::Array& coords, MC* mc) =0; 27 | size_t get_seed() const {return m_seed;} 28 | void set_generator_seed(const size_t inp) { m_generator.seed(inp); } 29 | double expected_mean() const { return 0; } 30 | double get_stepsize() const { return m_stepsize; } 31 | /** 32 | * Reference: http://mathworld.wolfram.com/UniformDistribution.html 33 | */ 34 | double expected_variance(const double ss) const { return ss * ss / static_cast(12); } 35 | void increase_acceptance(const double factor) { m_stepsize *= factor; } 36 | void decrease_acceptance(const double factor) { m_stepsize /= factor; } 37 | size_t get_count() const { return m_count; } 38 | }; 39 | 40 | class RandomCoordsDisplacementAll : public RandomCoordsDisplacement { 41 | public: 42 | RandomCoordsDisplacementAll(const size_t rseed, const double stepsize=1); 43 | virtual ~RandomCoordsDisplacementAll() {} 44 | virtual void displace(pele::Array& coords, MC* mc); 45 | }; 46 | 47 | class RandomCoordsDisplacementSingle : public RandomCoordsDisplacement { 48 | size_t m_nparticles, m_ndim, m_rand_particle; 49 | std::uniform_int_distribution m_int_distribution; 50 | public: 51 | RandomCoordsDisplacementSingle(const size_t rseed, const size_t nparticles, const size_t ndim, const double stepsize=1); 52 | virtual ~RandomCoordsDisplacementSingle() {} 53 | virtual void displace(pele::Array& coords, MC* mc); 54 | size_t get_rand_particle(){return m_rand_particle;} //dangerous function, should be used only for testing purposes 55 | }; 56 | 57 | } // namespace mcpele 58 | 59 | #endif // #ifndef _MCPELE_RANDOM_COORDS_DISPLACEMENT_H__ 60 | -------------------------------------------------------------------------------- /source/mcpele/record_coords_timeseries.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_RECORD_COORDS_TIMESERIES_H__ 2 | #define _MCPELE_RECORD_COORDS_TIMESERIES_H__ 3 | 4 | #include "record_vector_timeseries.h" 5 | 6 | namespace mcpele { 7 | 8 | class RecordCoordsTimeseries : public RecordVectorTimeseries { 9 | private: 10 | pele::Array m_mcv, m_mcv2; 11 | const size_t m_ndof; 12 | size_t m_count; 13 | double m_update_average(double avg, double x); 14 | void m_update_mean_coord_vector(pele::Array &new_coords); 15 | public: 16 | RecordCoordsTimeseries(const size_t ndof, const size_t record_every, const size_t eqsteps); 17 | virtual ~RecordCoordsTimeseries() {} 18 | virtual pele::Array get_recorded_vector(pele::Array &coords, 19 | const double energy, const bool accepted, MC* mc) { return coords; } 20 | virtual void action(pele::Array &coords, double energy, bool accepted, MC* mc); 21 | pele::Array get_mean_coordinate_vector(){return m_mcv.copy();} 22 | pele::Array get_mean2_coordinate_vector(){return m_mcv2.copy();} 23 | pele::Array get_variance_coordinate_vector() 24 | { 25 | pele::Array var = m_mcv2.copy(); 26 | for(size_t i=0; i initial_coords, 20 | const size_t boxdimension) 21 | : RecordScalarTimeseries(niter, record_every), 22 | m_rsm_displacement(initial_coords, boxdimension) 23 | {} 24 | virtual ~RecordDisplacementPerParticleTimeseries(){} 25 | virtual double get_recorded_scalar(pele::Array &coords, 26 | const double energy, const bool accepted, MC* mc) 27 | { return m_rsm_displacement.compute_mean_particle_displacement(coords); } 28 | }; 29 | 30 | } // namespace mcpele 31 | 32 | #endif // #ifndef _MCPELE_RECORD_DISPLACEMENT_PER_PARTICLE_TIMESERIES_H__ 33 | -------------------------------------------------------------------------------- /source/mcpele/record_energy_histogram.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE__RECORD_ENERGY_HISTOGRAM_H__ 2 | #define _MCPELE__RECORD_ENERGY_HISTOGRAM_H__ 3 | 4 | #include "mc.h" 5 | #include "histogram.h" 6 | 7 | namespace mcpele { 8 | 9 | /* 10 | * Record energy histogram 11 | */ 12 | 13 | class RecordEnergyHistogram : public Action { 14 | protected: 15 | mcpele::Histogram m_hist; 16 | private: 17 | const size_t m_eqsteps; 18 | size_t m_count; 19 | public: 20 | RecordEnergyHistogram(const double min, const double max, const double bin, const size_t eqsteps); 21 | virtual ~RecordEnergyHistogram() {} ; 22 | virtual void action(pele::Array &coords, double energy, bool accepted, MC* mc); 23 | pele::Array get_histogram() const; 24 | void print_terminal() const { m_hist.print_terminal(); } 25 | double get_max() const { return m_hist.max(); } 26 | double get_min() const { return m_hist.min(); } 27 | size_t get_eqsteps() const { return m_eqsteps; } 28 | double get_mean() const { return m_hist.get_mean(); } 29 | double get_variance() const { return m_hist.get_variance(); } 30 | int get_count() const { return m_hist.get_count(); } 31 | }; 32 | 33 | } // namespace mcpele 34 | 35 | #endif // #ifndef _MCPELE__RECORD_ENERGY_HISTOGRAM_H__ 36 | -------------------------------------------------------------------------------- /source/mcpele/record_energy_timeseries.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_RECORD_ENERGY_TIMESERIES_H__ 2 | #define _MCPELE_RECORD_ENERGY_TIMESERIES_H__ 3 | 4 | #include "record_scalar_timeseries.h" 5 | 6 | namespace mcpele { 7 | 8 | class RecordEnergyTimeseries : public RecordScalarTimeseries { 9 | public: 10 | RecordEnergyTimeseries(const size_t niter, const size_t record_every) 11 | : RecordScalarTimeseries(niter, record_every) 12 | {} 13 | virtual ~RecordEnergyTimeseries() {} 14 | virtual double get_recorded_scalar(pele::Array &coords, 15 | const double energy, const bool accepted, MC* mc) { return energy; } 16 | }; 17 | 18 | } // namespace mcpele 19 | 20 | #endif // #ifndef _MCPELE_RECORD_ENERGY_TIMESERIES_H__ 21 | -------------------------------------------------------------------------------- /source/mcpele/record_lowest_evalue_timeseries.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_RECORD_LOWEST_EVALUE_TIMESERIES_H__ 2 | #define _MCPELE_RECORD_LOWEST_EVALUE_TIMESERIES_H__ 3 | 4 | #include "record_scalar_timeseries.h" 5 | #include "lowest_eigenvalue.h" 6 | 7 | namespace mcpele { 8 | 9 | /** 10 | * Record time series of lowest eigenvalue 11 | */ 12 | 13 | class RecordLowestEValueTimeseries : public RecordScalarTimeseries{ 14 | private: 15 | FindLowestEigenvalue m_lowest_ev; 16 | public: 17 | RecordLowestEValueTimeseries(const size_t niter, 18 | const size_t record_every, 19 | std::shared_ptr landscape_potential, 20 | const size_t boxdimension, pele::Array ranvec, 21 | const size_t lbfgsniter = 30) 22 | : RecordScalarTimeseries(niter, record_every), 23 | m_lowest_ev(landscape_potential, boxdimension, ranvec, lbfgsniter) 24 | {} 25 | virtual ~RecordLowestEValueTimeseries(){} 26 | virtual double get_recorded_scalar(pele::Array &coords, 27 | const double energy, const bool accepted, MC* mc) 28 | { return m_lowest_ev.compute_lowest_eigenvalue(coords); } 29 | }; 30 | 31 | } // namespace mcpele 32 | 33 | #endif // #ifndef _MCPELE_RECORD_LOWEST_EVALUE_TIMESERIES_H__ 34 | -------------------------------------------------------------------------------- /source/mcpele/record_pair_dist_histogram.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_RECORD_PAIR_DIST_HISTOGRAM_H__ 2 | #define _MCPELE_RECORD_PAIR_DIST_HISTOGRAM_H__ 3 | 4 | #include "pele/optimizer.h" 5 | 6 | #include "mc.h" 7 | #include "pair_dist_histogram.h" 8 | 9 | namespace mcpele { 10 | 11 | /** 12 | * Record pair-distance distribution (radial distribution function) 13 | * Templated on boxdimension, should work fine with pele::periodic_distance 14 | * Input parameters: 15 | * --- boxvector: defines the (periodic) simlation box 16 | * --- nr_bins: number of bins for g(r) histogram 17 | * --- eqsteps: number of equilibration steps to be excluded from g(r) computation 18 | * --- record_every: after more than eqsteps steps have been done, record every record_everyth step 19 | * Everytime the action is called, it accumulates the present configuration into the same g(r) histogram. 20 | * The action function calls add_configuration which accumulates the current configuration into the g(r) histogram. 21 | * The g(r) histogram can be read out at any point after that. 22 | * To read out the data, two functions are used: 23 | * --- get_hist_r() gives the r value array for the g(r) histogram 24 | * --- get_hist_gr() gives the corresponding g(r) value array, normalized using the input number of particles and number density 25 | * (Admittedly number density could have been reconstructed independently of that input.) 26 | */ 27 | 28 | template 29 | class RecordPairDistHistogram : public Action { 30 | private: 31 | mcpele::PairDistHistogram m_hist_gr; 32 | const size_t m_eqsteps; 33 | const size_t m_record_every; 34 | const bool m_quench; 35 | std::shared_ptr m_optimizer; 36 | public: 37 | RecordPairDistHistogram(pele::Array boxvector, const size_t nr_bins, const size_t eqsteps, const size_t record_every) 38 | : m_hist_gr(boxvector, nr_bins), 39 | m_eqsteps(eqsteps), 40 | m_record_every(record_every), 41 | m_quench(false) 42 | {} 43 | RecordPairDistHistogram(pele::Array boxvector, const size_t nr_bins, const size_t eqsteps, const size_t record_every, std::shared_ptr optimizer) 44 | : m_hist_gr(boxvector, nr_bins), 45 | m_eqsteps(eqsteps), 46 | m_record_every(record_every), 47 | m_quench(true), 48 | m_optimizer(optimizer) 49 | {} 50 | virtual ~RecordPairDistHistogram() {} 51 | virtual void action(pele::Array& coords, double energy, bool accepted, MC* mc) 52 | { 53 | const size_t count = mc->get_iterations_count(); 54 | if (count > m_eqsteps) { 55 | if (count % m_record_every == 0) { 56 | process_add_configuration(coords); 57 | } 58 | } 59 | } 60 | virtual void process_add_configuration(pele::Array& coords) 61 | { 62 | pele::Array tmp = coords.copy(); 63 | if (m_quench) { 64 | m_optimizer->reset(tmp); 65 | m_optimizer->run(); 66 | tmp = m_optimizer->get_x().copy(); 67 | } 68 | m_hist_gr.add_configuration(tmp); 69 | } 70 | size_t get_eqsteps() const 71 | { 72 | return m_eqsteps; 73 | } 74 | pele::Array get_hist_r() const 75 | { 76 | std::vector vecdata(m_hist_gr.get_vecdata_r()); 77 | return pele::Array(vecdata).copy(); 78 | } 79 | pele::Array get_hist_gr(const double number_density, const size_t nr_particles) const 80 | { 81 | std::vector vecdata(m_hist_gr.get_vecdata_gr(number_density, nr_particles)); 82 | return pele::Array(vecdata).copy(); 83 | } 84 | }; 85 | 86 | } // namespace mcpele 87 | 88 | #endif // #ifndef _MCPELE_RECORD_PAIR_DIST_HISTOGRAM_H__ 89 | -------------------------------------------------------------------------------- /source/mcpele/record_scalar_timeseries.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_RECORD_SCALAR_TIMESERIES_H__ 2 | #define _MCPELE_RECORD_SCALAR_TIMESERIES_H__ 3 | 4 | #include "mc.h" 5 | 6 | namespace mcpele { 7 | 8 | /** 9 | * Record scalar time series, every record_every-th step. 10 | */ 11 | class RecordScalarTimeseries : public Action { 12 | private: 13 | const size_t m_record_every; 14 | std::vector m_time_series; 15 | void m_record_scalar_value(const double input) 16 | { 17 | m_time_series.push_back(input); 18 | } 19 | public: 20 | RecordScalarTimeseries(const size_t, const size_t); 21 | virtual ~RecordScalarTimeseries(){} 22 | virtual void action(pele::Array &coords, double energy, bool accepted, MC* mc); 23 | virtual double get_recorded_scalar(pele::Array &coords, const double energy, const bool accepted, MC* mc)=0; 24 | pele::Array get_time_series() 25 | { 26 | m_time_series.shrink_to_fit(); 27 | return pele::Array(m_time_series).copy(); 28 | } 29 | void clear() { m_time_series.clear(); } 30 | }; 31 | 32 | } // namespace mcpele 33 | 34 | #endif // #ifndef _MCPELE_RECORD_SCALAR_TIMESERIES_H__ 35 | -------------------------------------------------------------------------------- /source/mcpele/record_vector_timeseries.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_RECORD_VECTOR_TIMESERIES_H__ 2 | #define _MCPELE_RECORD_VECTOR_TIMESERIES_H__ 3 | 4 | #include "mc.h" 5 | #include 6 | #include 7 | 8 | namespace mcpele { 9 | 10 | /** 11 | * Record vector time series, every record_every-th step. 12 | */ 13 | class RecordVectorTimeseries : public Action { 14 | protected: 15 | const size_t m_record_every, m_eqsteps; 16 | std::deque> m_time_series; 17 | void m_record_vector_value(pele::Array input) 18 | { 19 | try{ 20 | m_time_series.push_back(input.copy()); 21 | } 22 | catch(std::bad_alloc &ba){ 23 | std::cerr<< "mcpele::RecordVectorTimeseries: bad_alloc caught: " << ba.what() << std::endl; 24 | std::exit(EXIT_FAILURE); 25 | } 26 | } 27 | public: 28 | RecordVectorTimeseries(const size_t record_every, const size_t eqsteps); 29 | virtual ~RecordVectorTimeseries(){} 30 | virtual void action(pele::Array &coords, double energy, bool accepted, MC* mc); 31 | virtual pele::Array get_recorded_vector(pele::Array &coords, const double energy, const bool accepted, MC* mc)=0; 32 | std::deque> get_time_series() 33 | { 34 | m_time_series.shrink_to_fit(); 35 | return m_time_series; 36 | } 37 | void clear() { m_time_series.clear(); } 38 | size_t get_record_every(){return m_record_every;} 39 | }; 40 | 41 | } // namespace mcpele 42 | 43 | #endif // #ifndef _MCPELE_RECORD_VECTOR_TIMESERIES_H__ 44 | -------------------------------------------------------------------------------- /source/mcpele/rsm_displacement.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_RSM_DISPLACEMENT_H 2 | #define _MCPELE_RSM_DISPLACEMENT_H 3 | 4 | #include "pele/array.h" 5 | 6 | namespace mcpele{ 7 | 8 | 9 | class GetDisplacementPerParticle{ 10 | private: 11 | pele::Array m_initial_coordinates; 12 | const size_t m_boxdimension; 13 | const size_t m_nr_particles; 14 | public: 15 | virtual ~GetDisplacementPerParticle(){} 16 | GetDisplacementPerParticle(pele::Array, const size_t); 17 | double compute_mean_particle_displacement(pele::Array); 18 | double get_particle_displ(const size_t, pele::Array); 19 | }; 20 | 21 | 22 | } //namespace mcpele 23 | 24 | #endif //#ifndef _MCPELE_RSM_DISPLACEMENT_H 25 | -------------------------------------------------------------------------------- /source/mcpele/take_step_pattern.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_TAKE_STEP_PATTERN_H__ 2 | #define _MCPELE_TAKE_STEP_PATTERN_H__ 3 | 4 | #include "pattern_manager.h" 5 | 6 | namespace mcpele { 7 | 8 | /** 9 | * Create a pattern of TakeSteps to be exectuted by MC. 10 | * 11 | * Example 12 | * ------- 13 | * 14 | * To have MC looping over a pattern consisting of 99 times step_A and 15 | * 1 time step_B, do e.g.: 16 | * auto pot = std::make_shared(SomeParameters); 17 | * auto mc = std::make_shared(pot, SomeCoordinates, SomeTemperature); 18 | * auto step_pattern = std::make_shared(); 19 | * auto step_A = std::make_shared(SomeParameters); 20 | * auto step_B = std::make_shared(SomeOtherParameters); 21 | * step_pattern->add_step(step_A, 99); 22 | * step_pattern->add_step(step_B, 1); 23 | * mc->set_takestep(step_pattern); 24 | * mc->run(1e6); 25 | */ 26 | class TakeStepPattern : public TakeStep { 27 | private: 28 | PatternManager m_steps; 29 | std::vector > m_step_storage; 30 | public: 31 | virtual ~TakeStepPattern() {} 32 | void add_step(std::shared_ptr step_input, 33 | const size_t repetitions_input=1) 34 | { 35 | m_steps.add(m_step_storage.size(), repetitions_input); 36 | m_step_storage.push_back(step_input); 37 | } 38 | void displace(pele::Array& coords, MC* mc); 39 | void report(pele::Array& old_coords, const double old_energy, 40 | pele::Array& new_coords, const double new_energy, 41 | const bool success, MC* mc) 42 | { 43 | m_step_storage.at(m_steps.get_step_ptr())->report(old_coords, 44 | old_energy, new_coords, new_energy, success, mc); 45 | } 46 | std::vector get_pattern() const { return m_steps.get_pattern(); } 47 | std::vector get_pattern_direct() { return m_steps.get_pattern_direct(); } 48 | }; 49 | 50 | } // namespace mcpele 51 | 52 | #endif // #ifndef _MCPELE_TAKE_STEP_PATTERN_H__ 53 | -------------------------------------------------------------------------------- /source/mcpele/take_step_probabilities.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_TAKE_STEP_PROBABILITIES_H__ 2 | #define _MCPELE_TAKE_STEP_PROBABILITIES_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include "mc.h" 8 | 9 | namespace mcpele { 10 | 11 | /** 12 | * Create a step pattern similar to TakeStepPattern. 13 | * However, the steps are specified together with their relative weights and 14 | * exectured accoringly. 15 | * 16 | * Reference 17 | * --------- 18 | * http://www.cplusplus.com/reference/random/discrete_distribution/ 19 | */ 20 | class TakeStepProbabilities : public TakeStep { 21 | private: 22 | std::vector > m_steps; 23 | std::vector m_weights; 24 | std::discrete_distribution m_distribution; 25 | std::mt19937_64 m_generator; 26 | size_t m_current_index; 27 | public: 28 | virtual ~TakeStepProbabilities() {} 29 | TakeStepProbabilities(const size_t seed); 30 | void add_step(std::shared_ptr step_input, const double weight_input=1); 31 | void displace(pele::Array& coords, MC* mc); 32 | void report(pele::Array& old_coords, const double old_energy, 33 | pele::Array& new_coords, const double new_energy, 34 | const bool success, MC* mc); 35 | std::vector get_weights() const { return m_weights; } 36 | }; 37 | 38 | } // namespace mcpele 39 | 40 | #endif // #ifndef _MCPELE_TAKE_STEP_PROBABILITIES_H__ 41 | -------------------------------------------------------------------------------- /source/mcpele/uniform_rectangular_sampling.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_UNIFORM_RECTANGULAR_SAMPLING_H__ 2 | #define _MCPELE_UNIFORM_RECTANGULAR_SAMPLING_H__ 3 | 4 | #include "pele/array.h" 5 | 6 | namespace mcpele { 7 | 8 | class UniformRectangularSampling : public TakeStep { 9 | protected: 10 | std::mt19937_64 m_gen; 11 | std::uniform_real_distribution m_dist05; 12 | pele::Array m_boxvec; 13 | bool m_cubic; 14 | public: 15 | virtual ~UniformRectangularSampling() {} 16 | UniformRectangularSampling(const size_t seed, const pele::Array boxvec) 17 | : m_gen(seed), 18 | m_dist05(-0.5, 0.5), 19 | m_boxvec(boxvec.copy()) 20 | {} 21 | void set_generator_seed(const size_t inp) { m_gen.seed(inp); } 22 | virtual void displace(pele::Array& coords, MC* mc) 23 | { 24 | if (coords.size() % m_boxvec.size()) { 25 | throw std::runtime_error("UniformRectangularSampling::displace: coods size incompatible with boxvec size"); 26 | } 27 | const size_t nr_particles = coords.size() / m_boxvec.size(); 28 | const size_t dim = m_boxvec.size(); 29 | for (size_t i = 0; i < nr_particles; ++i) { 30 | for (size_t k = 0; k < dim; ++k) { 31 | coords[i * dim + k] = m_boxvec[k] * m_dist05(m_gen); 32 | } 33 | } 34 | } 35 | }; 36 | 37 | } // namespace mcpele 38 | 39 | #endif // #ifndef _MCPELE_UNIFORM_RECTANGULAR_SAMPLING_H__ 40 | -------------------------------------------------------------------------------- /source/mcpele/uniform_spherical_sampling.h: -------------------------------------------------------------------------------- 1 | #ifndef _MCPELE_UNIFORM_SPHERICAL_SAMPLING_H__ 2 | #define _MCPELE_UNIFORM_SPHERICAL_SAMPLING_H__ 3 | 4 | namespace mcpele { 5 | 6 | /** 7 | * Sample points uniformly at random within an N-ball. 8 | * See also: http://math.stackexchange.com/questions/87230/picking-random-points-in-the-volume-of-sphere-with-uniform-probability 9 | */ 10 | 11 | class UniformSphericalSampling : public TakeStep { 12 | protected: 13 | std::mt19937_64 m_gen; 14 | const double m_radius; 15 | std::normal_distribution m_dist_normal; 16 | std::uniform_real_distribution m_dist_uniform; 17 | public: 18 | virtual ~UniformSphericalSampling() {} 19 | UniformSphericalSampling(const size_t seed=42, const double radius=1) 20 | : m_gen(seed), 21 | m_radius(radius), 22 | m_dist_normal(0, 1), 23 | m_dist_uniform(0, 1) 24 | {} 25 | void set_generator_seed(const size_t inp) { m_gen.seed(inp); } 26 | virtual void displace(pele::Array& coords, MC* mc) 27 | { 28 | for (size_t i = 0; i < coords.size(); ++i) { 29 | coords[i] = m_dist_normal(m_gen); 30 | } 31 | /** 32 | * From Numerical Recipes: 33 | * Picking a random point on a sphere: 34 | * 1) generate n independent, identically distributed, normal random numbers, y_0, ..., y_{n-1} 35 | * 2) get point {x} on unit sphere in n dimensions by {x} = {y} / norm({y}) 36 | * Picking a random point inside a sphere: 37 | * 3) generate an additional uniform random number u in [0,1] 38 | * 4) compute point x_i = y_i * u^{1/n} / norm({y}) 39 | */ 40 | // This computes 1 / norm({y}). 41 | double tmp = 1.0 / norm(coords); 42 | // This computes u^{1/n} / norm({y}) and rescales to a sphere of radius m_radius. 43 | tmp *= m_radius * std::pow(m_dist_uniform(m_gen), 1.0 / coords.size()); 44 | // This computes the sampled random point in the sphere. 45 | coords *= tmp; 46 | } 47 | }; 48 | 49 | } // namespace mcpele 50 | 51 | #endif // #ifndef _MCPELE_UNIFORM_SPHERICAL_SAMPLING_H__ 52 | -------------------------------------------------------------------------------- /source/metropolis_test.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/metropolis_test.h" 2 | 3 | #include 4 | //#include 5 | 6 | using pele::Array; 7 | 8 | namespace mcpele { 9 | 10 | MetropolisTest::MetropolisTest(const size_t rseed) 11 | : m_seed(rseed), 12 | m_generator(rseed), 13 | m_distribution(0.0, 1.0) 14 | { 15 | #ifdef DEBUG 16 | std::cout << "seed Metropolis:" << _seed << "\n"; 17 | //std::chrono::system_clock::now().time_since_epoch().count() 18 | #endif 19 | } 20 | 21 | bool MetropolisTest::test(Array &trial_coords, double trial_energy, 22 | Array& old_coords, double old_energy, double temperature, 23 | MC * mc) 24 | { 25 | double w, rand; 26 | bool success = true; 27 | double dE = trial_energy - old_energy; 28 | if (dE > 0.){ 29 | w = exp(-dE / temperature); 30 | rand = m_distribution(m_generator); 31 | if (rand > w) { 32 | success = false; 33 | } 34 | } 35 | return success; 36 | } 37 | 38 | } // namespace mcpele 39 | -------------------------------------------------------------------------------- /source/particle_pair_swap.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/particle_pair_swap.h" 2 | 3 | namespace mcpele { 4 | 5 | ParticlePairSwap::ParticlePairSwap(const size_t seed, const size_t nr_particles) 6 | : m_seed(seed), 7 | m_generator(seed), 8 | m_distribution(0, nr_particles - 1), 9 | m_nr_particles(nr_particles) 10 | { 11 | if (nr_particles == 0) { 12 | throw std::runtime_error("ParticlePairSwap: illegal input"); 13 | } 14 | } 15 | 16 | void ParticlePairSwap::displace(pele::Array& coords, MC* mc) 17 | { 18 | size_t particle_a = 42; 19 | size_t particle_b = 42; 20 | while (particle_a == particle_b) { 21 | particle_a = m_distribution(m_generator); 22 | particle_b = m_distribution(m_generator); 23 | } 24 | assert(particle_a < m_nr_particles && particle_b < m_nr_particles); 25 | assert(particle_a != particle_b); 26 | swap_coordinates(particle_a, particle_b, coords); 27 | } 28 | 29 | void ParticlePairSwap::swap_coordinates(const size_t particle_a, const size_t particle_b, pele::Array& coords) 30 | { 31 | if (particle_a == particle_b) { 32 | return; 33 | } 34 | const size_t box_dimension = coords.size() / m_nr_particles; 35 | const size_t index_a = particle_a * box_dimension; 36 | const size_t index_b = particle_b * box_dimension; 37 | double*const& x = coords.data(); 38 | double*const& xa = x + index_a; 39 | double*const& xb = x + index_b; 40 | std::swap_ranges(xa, xa + box_dimension, xb); 41 | } 42 | 43 | void ParticlePairSwap::set_generator_seed(const size_t inp) 44 | { 45 | m_generator.seed(inp); 46 | m_seed = inp; 47 | } 48 | 49 | } // namespace mcpele 50 | -------------------------------------------------------------------------------- /source/random_coords_displacement.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/random_coords_displacement.h" 2 | 3 | namespace mcpele { 4 | 5 | /*RandomCoordsDisplacement*/ 6 | 7 | RandomCoordsDisplacement::RandomCoordsDisplacement(const size_t rseed, const double stepsize) 8 | : m_seed(rseed), 9 | m_generator(rseed), 10 | m_real_distribution(0.0, 1.0), 11 | m_stepsize(stepsize), 12 | m_count(0) 13 | { 14 | #ifdef DEBUG 15 | std::cout<<"seed TakeStep:"<<_seed<< "\n"; 16 | #endif 17 | } 18 | 19 | /*RandomCoordsDisplacementAll*/ 20 | 21 | RandomCoordsDisplacementAll::RandomCoordsDisplacementAll(const size_t rseed, const double stepsize) 22 | : RandomCoordsDisplacement(rseed, stepsize){} 23 | 24 | void RandomCoordsDisplacementAll::displace(pele::Array& coords, MC* mc) 25 | { 26 | for (size_t i = 0; i < coords.size(); ++i) { 27 | double rand = m_real_distribution(m_generator); 28 | coords[i] += (0.5 - rand) * m_stepsize; 29 | } 30 | ++m_count; 31 | } 32 | 33 | /*RandomCoordsDisplacementSingle*/ 34 | 35 | RandomCoordsDisplacementSingle::RandomCoordsDisplacementSingle(const size_t rseed, const size_t nparticles, const size_t ndim, const double stepsize) 36 | : RandomCoordsDisplacement(rseed, stepsize), 37 | m_nparticles(nparticles), 38 | m_ndim(ndim), 39 | m_rand_particle(0), 40 | m_int_distribution(0, m_nparticles-1){} 41 | 42 | void RandomCoordsDisplacementSingle::displace(pele::Array& coords, MC* mc) 43 | { 44 | m_rand_particle = m_int_distribution(m_generator); 45 | size_t rand_particle_dof = m_rand_particle * m_ndim; 46 | for (size_t i = rand_particle_dof; i < rand_particle_dof + m_ndim; ++i) { 47 | double rand = m_real_distribution(m_generator); 48 | coords[i] += (0.5 - rand) * m_stepsize; 49 | } 50 | ++m_count; 51 | } 52 | 53 | } // namespace mcpele 54 | -------------------------------------------------------------------------------- /source/record_coords_timeseries.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mcpele/record_coords_timeseries.h" 3 | 4 | namespace mcpele{ 5 | /* 6 | * m_mcv mean coordinate vector 7 | * m_mcv2 element wise square mean coordinate vector, useful to compute the variance in each coordinate 8 | * */ 9 | RecordCoordsTimeseries::RecordCoordsTimeseries(const size_t ndof, const size_t record_every, const size_t eqsteps) 10 | : RecordVectorTimeseries(record_every, eqsteps), 11 | m_mcv(ndof,0), //it is important that m_mcv is initialised to vec{0} for the first update step to work correctly 12 | m_mcv2(ndof,0), 13 | m_ndof(ndof), 14 | m_count(0) 15 | {} 16 | 17 | double RecordCoordsTimeseries::m_update_average(double avg, double x) 18 | { 19 | double n = m_count; 20 | return (avg * n + x) / (n+1.); 21 | } 22 | 23 | void RecordCoordsTimeseries::m_update_mean_coord_vector(pele::Array &new_coords){ 24 | for(size_t i=0; im_update_average(m_mcv[i], newx); 27 | m_mcv2[i] = this->m_update_average(m_mcv2[i], newx*newx); 28 | } 29 | ++m_count; 30 | } 31 | 32 | void RecordCoordsTimeseries::action(pele::Array &coords, double energy, bool accepted, MC* mc) 33 | { 34 | 35 | if (coords.size() != m_ndof) { 36 | throw std::runtime_error("RecordCoordsTimeseries::action: ndof and new coords have different size"); 37 | } 38 | size_t counter = mc->get_iterations_count(); 39 | 40 | if (counter > m_eqsteps){ 41 | this->m_update_mean_coord_vector(coords); 42 | if (counter % m_record_every == 0) { 43 | m_record_vector_value(this->get_recorded_vector(coords, energy, accepted, mc)); 44 | } 45 | } 46 | } 47 | 48 | } //namespace mcpele 49 | -------------------------------------------------------------------------------- /source/record_energy_histogram.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/record_energy_histogram.h" 2 | 3 | using pele::Array; 4 | 5 | namespace mcpele { 6 | 7 | RecordEnergyHistogram::RecordEnergyHistogram(const double min, const double max, const double bin, const size_t eqsteps) 8 | : m_hist(min, max, bin), 9 | m_eqsteps(eqsteps), 10 | m_count(0) 11 | {} 12 | 13 | void RecordEnergyHistogram::action(Array &coords, double energy, bool accepted, MC* mc) 14 | { 15 | m_count = mc->get_iterations_count(); 16 | if (m_count > m_eqsteps){ 17 | m_hist.add_entry(energy); 18 | } 19 | } 20 | 21 | pele::Array RecordEnergyHistogram::get_histogram() const 22 | { 23 | std::vector vecdata(m_hist.get_vecdata()); 24 | pele::Array histogram(vecdata); 25 | return histogram.copy(); 26 | } 27 | 28 | } // namespace mcpele 29 | -------------------------------------------------------------------------------- /source/record_scalar_timeseries.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/record_scalar_timeseries.h" 2 | #include "mcpele/moving_average.h" 3 | 4 | using pele::Array; 5 | 6 | namespace mcpele { 7 | 8 | RecordScalarTimeseries::RecordScalarTimeseries(const size_t niter, const size_t record_every) 9 | : m_record_every(record_every) 10 | { 11 | if (record_every == 0) { 12 | throw std::runtime_error("RecordScalarTimeseries: record_every expected to be at least 1"); 13 | } 14 | m_time_series.reserve(niter / record_every); 15 | } 16 | 17 | void RecordScalarTimeseries::action(Array &coords, double energy, bool accepted, MC* mc) 18 | { 19 | const size_t counter = mc->get_iterations_count(); 20 | if (counter % m_record_every == 0) { 21 | m_record_scalar_value(this->get_recorded_scalar(coords, energy, accepted, mc)); 22 | } 23 | } 24 | 25 | } // namespace mcpele 26 | -------------------------------------------------------------------------------- /source/record_vector_timeseries.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/record_vector_timeseries.h" 2 | 3 | using pele::Array; 4 | 5 | namespace mcpele { 6 | 7 | RecordVectorTimeseries::RecordVectorTimeseries(const size_t record_every, const size_t eqsteps) 8 | : m_record_every(record_every), 9 | m_eqsteps(eqsteps) 10 | { 11 | if (record_every == 0) { 12 | throw std::runtime_error("RecordVectorTimeseries: record_every expected to be at least 1"); 13 | } 14 | } 15 | 16 | void RecordVectorTimeseries::action(Array &coords, double energy, bool accepted, MC* mc) 17 | { 18 | const size_t counter = mc->get_iterations_count(); 19 | if (counter % m_record_every == 0 && counter > m_eqsteps) { 20 | m_record_vector_value(this->get_recorded_vector(coords, energy, accepted, mc)); 21 | } 22 | } 23 | 24 | } // namespace mcpele 25 | -------------------------------------------------------------------------------- /source/rsm_displacement.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mcpele/histogram.h" 5 | #include "mcpele/rsm_displacement.h" 6 | 7 | namespace mcpele{ 8 | 9 | 10 | GetDisplacementPerParticle::GetDisplacementPerParticle(pele::Array initial_coordinates_, 11 | const size_t boxdimension_) 12 | : m_initial_coordinates(initial_coordinates_.copy()), 13 | m_boxdimension(boxdimension_), 14 | m_nr_particles(initial_coordinates_.size() / boxdimension_) 15 | {} 16 | 17 | double GetDisplacementPerParticle::compute_mean_particle_displacement(pele::Array new_coords) 18 | { 19 | if (new_coords.size() != m_initial_coordinates.size()) { 20 | throw std::runtime_error("GetMeanRMSDisplacement::compute_mean_rsm_displacement: illegal new coords"); 21 | } 22 | Moments mom; 23 | for (size_t particle = 0; particle < m_nr_particles; ++particle) { 24 | mom.update(get_particle_displ(particle, new_coords)); 25 | } 26 | return mom.mean(); 27 | } 28 | 29 | double GetDisplacementPerParticle::get_particle_displ(const size_t particle_idx, pele::Array new_coords) 30 | { 31 | const size_t particle_start = particle_idx * m_boxdimension; 32 | double sumsq(0); 33 | for (size_t i = particle_start; i < particle_start + m_boxdimension; ++i) { 34 | const double deltai = m_initial_coordinates[i] - new_coords[i]; 35 | sumsq += deltai*deltai; 36 | } 37 | return sqrt(sumsq); 38 | } 39 | 40 | 41 | } //namespace mcpele 42 | -------------------------------------------------------------------------------- /source/take_step_pattern.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/take_step_pattern.h" 2 | 3 | namespace mcpele { 4 | 5 | void TakeStepPattern::displace(pele::Array& coords, MC* mc) 6 | { 7 | ++m_steps; 8 | m_step_storage.at(m_steps.get_step_ptr())->displace(coords, mc); 9 | } 10 | 11 | } // namespace mcpele 12 | -------------------------------------------------------------------------------- /source/take_step_probabilities.cpp: -------------------------------------------------------------------------------- 1 | #include "mcpele/take_step_probabilities.h" 2 | 3 | namespace mcpele { 4 | 5 | TakeStepProbabilities::TakeStepProbabilities(const size_t seed) 6 | : m_generator(seed) 7 | {} 8 | 9 | void TakeStepProbabilities::add_step(std::shared_ptr step_input, const double weight_input) 10 | { 11 | m_steps.push_back(step_input); 12 | m_weights.push_back(weight_input); 13 | m_steps.swap(m_steps); 14 | m_weights.swap(m_weights); 15 | m_distribution = std::discrete_distribution(m_weights.begin(), m_weights.end()); 16 | } 17 | 18 | void TakeStepProbabilities::displace(pele::Array& coords, MC* mc) 19 | { 20 | if (m_steps.size() == 0) { 21 | throw std::runtime_error("TakeStepProbabilities::displace: no step specified"); 22 | } 23 | m_current_index = m_distribution(m_generator); 24 | m_steps.at(m_current_index)->displace(coords, mc); 25 | } 26 | 27 | void TakeStepProbabilities::report(pele::Array& old_coords, const double old_energy, pele::Array& new_coords, const double new_energy, const bool success, MC* mc) 28 | { 29 | m_steps.at(m_current_index)->report(old_coords, old_energy, new_coords, new_energy, success, mc); 30 | } 31 | 32 | } // namespace mcpele 33 | --------------------------------------------------------------------------------