diff --git a/.github/workflows/draft-pdf.yml b/.github/workflows/draft-pdf.yml new file mode 100644 index 0000000..623b369 --- /dev/null +++ b/.github/workflows/draft-pdf.yml @@ -0,0 +1,23 @@ +on: [push] + +jobs: + paper: + runs-on: ubuntu-latest + name: Paper Draft + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Build draft PDF + uses: openjournals/openjournals-draft-action@master + with: + journal: joss + # This should be the path to the paper within your repo. + paper-path: paper.md + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: paper + # This is the output path where Pandoc will write the compiled + # PDF. Note, this should be the same directory as the input + # paper.md + path: paper.pdf \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7939025..80dfe8c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ -*_debug *.o .vscode/ -build/ \ No newline at end of file +*_debug +build +result +.envrc +.cache +compile_commands.json +jats/ diff --git a/README.md b/README.md index 5833a3a..b7add64 100644 --- a/README.md +++ b/README.md @@ -1,386 +1,21 @@ -Reaction Network Monte Carlo (`RNMC`) is a collection of programs for kinetic Monte Carlo (kMC) simulation of physical systems heavily based on [SPPARKS](https://spparks.sandia.gov/). `RNMC` is designed to run large numbers of simulations of a fixed system in parallel. The project consists of three kMC modules for different domains which use `core` code for shared processes, for example IO, threading logic and model independent simulation logic. +Reaction Network Monte Carlo (`RNMC`) is a collection of programs for Monte Carlo simulation of statistical mechanical systems heavily inspired by [SPPARKS](https://spparks.sandia.gov/). `RNMC` is designed to run large numbers of simulations of a fixed system in parallel. The project currently consists of four parts: +- `core` : Core code shared by all simulators, for example IO, threading logic, and model independent simulation logic. +- `GMC` : Implementation of Gillespie's next reaction simulator. GMC is able to run simulations of reaction networks with hundreds of millions of reactions, even when the number of species is small. +- `NPMC` : A 3D statistical field theory simulator which supports one and two site interactions. Useful for simulating nano particles. +- `LGMC` : A simulator that can include a static or dynamic lattice region and a homogeneous region and allows electrochemical as well as chemical reactions. Suitable for multi-phase simulations (e.g., heterogeneous catalysis, electrochemical plating or stripping). -## Three Modules -- `GMC` - [Gillespie Monte Carlo](https://blaugroup.github.io/RNMC/GMC.html): Implementation of Gillespie's next reaction simulator. `GMC` is able to run simulations of reaction networks with hundreds of millions of reactions. -- `NPMC` - [Nano Particle Monte Carlo](https://blaugroup.github.io/RNMC/NPMC.html): A three dimensional statistical field theory simulator which supports one- and two-site interactions. `NPMC` is useful for simulating nano particles. -- `LGMC` - [Lattice Gillespie Monte Carlo](https://blaugroup.github.io/RNMC/LGMC.html): A kMC implementation coupling a homogeneous (Gillespie-like) region with a lattice, enabling simulations with reactions occurring in multiple phases and capable of electrochemical reactions. +Examples of research projects using `RNMC`: +- Spotte-Smith, Kam, et al., *ACS Energy Lett.* **7**(4), 1446–1453 (2022). [DOI: 10.1021/acsenergylett.2c00517](https://doi.org/10.1021/acsenergylett.2c00517) +- Barter, Spotte-Smith, et al., *Dig. Disc.* **2**, 123-137 (2023). [DOI: 10.1039/D2DD00117A](https://doi.org/10.1039/D2DD00117A) +- Spotte-Smith et al., *J. Am. Chem. Soc.* **145**(2), 12181–12192 (2023). [DOI: 10.1021/jacs.3c02222](https://doi.org/10.1021/jacs.3c02222) +- Xia et al., *Nano Lett.* **23**(23), 11129–11136 (2023). [DOI: 10.1021/acs.nanolett.3c03568](https://doi.org/10.1021/acs.nanolett.3c03568) -See [this](https://doi.org/10.26434/chemrxiv-2021-c2gp3) paper for an example of the kind of work being done with RNMC. +## Documentation -Please see the [documentation](https://blaugroup.github.io/RNMC/) for more information. +The complete documentation for `RNMC` can be found [here](https://blaugroup.github.io/RNMC/). This includes a guide to installation, setting up simulations, testing, and more. ## Dependencies -RNMC depends on [GSL](https://www.gnu.org/software/gsl/) for pseudo random number generation and [sqlite](https://www.sqlite.org/index.html) for the database interfaces. - -## Building - -On a machine with system versions of GSL and sqlite, the executables can be built with a makefile. There are makefiles inside the `GMC`, `NPMC`, or `LGMC` folders. - -To make an executable for `GMC`, `NPMC` or `LGMC` first enter that folder to use the makefile. To create an executable, use make and then the name of the module. - -For example, to use `GMC`: - -``` -$ cd GMC -``` - -``` -$ make GMC -``` - -For further help on the makefile and to view other commands: - -``` -$ make help -``` - -Note that the makefile uses the `gsl-config` utility to find headers and libraries for GSL. If you are on a cluster and sqlite is not present, it can be built as follows: - -``` -cd $HOME -wget https://www.sqlite.org/2021/sqlite-amalgamation-3360000.zip -unzip sqlite-amalgamation-3360000.zip -cd sqlite-amalgamation-3360000 -gcc -o libsqlite3.so -shared -fPIC sqlite3.c -lpthread -ldl -``` - -in which case, the simulators can be built like this: - -``` -export CPATH=$HOME/sqlite-amalgamation-3360000:$CPATH -export LIBRARY_PATH=$HOME/sqlite-amalgamation-3360000:$LIBRARY_PATH -make GMC -``` - -If you need to build [GSL](https://www.gnu.org/software/gsl/) from source: - -``` -wget https://mirror.ibcp.fr/pub/gnu/gsl/gsl-latest.tar.gz -mkdir gsl -mv gsl-latest.tar.gz gsl -tar -xvf gsl-latest.tar.gz -cd gsl-2.7.1 -./configure --prefix=/my/path/to/gsl -make -make install -echo $PKG_CONFIG_PATH -export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/my/path/to/gsl-2.7.1 -``` - -Note that if you build from source use `pkg-config gsl` instead of `gsl-config` inside each makefile - - -## Testing - -Inside the `tests` folder are unit tests using [GoogleTest](https://google.github.io/googletest/primer.html) and end-to-end tests for GMC and NPMC (LGMC trajectories are not deterministic). Unit tests can be run with the makefile and end-to-end tests can be run using `test.sh`. - -## Running GMC/NPMC/LGMC - -## GMC - -GMC is run as follows: - -``` -$ cd GMC -$ make GMC -``` - -When running `GMC` ensure that your input file paths are correct considering the executable is inside the `GMC` folder. Below is an example of how `GMC` can be run using the input files inside the examples directory (here `step_cutoff` is specified): - -``` -./GMC --reaction_database=../examples/GMC/rn.sqlite --initial_state_database=../examples/GMC/initial_state.sqlite --number_of_simulations=1000 --base_seed=1000 --thread_count=8 --step_cutoff=200 --energy_budget=0 -``` - -`GMC` requires six input arguments (either `step_cutoff` or `time_cutoff` must be specified): - -- reaction_database : a sqlite database containing the reaction network and metadata. -- initial_state_database : a sqlite database containing initial state. The simulation trajectories are also written into the database. -- number_of_simulation : an integer specifying how many simulations to run. -- base_seed : seeds used are `base_seed, base_seed+1, ..., base_seed+number_of_simulations-1`. -- thread_count : how many threads to use. -- step_cutoff : how many steps in each simulation. -- time_cutoff : how much time in each simulation [s]. -- energy_budget : allowed energy to be added into the system. - -### The Reaction Network Database -There are two tables in the reaction network database both of which **must be created and filled in by the user**: - -``` -CREATE TABLE metadata ( - number_of_species INTEGER NOT NULL, - number_of_reactions INTEGER NOT NULL -); -``` - -``` -CREATE TABLE reactions ( - reaction_id INTEGER NOT NULL PRIMARY KEY, - number_of_reactants INTEGER NOT NULL, - number_of_products INTEGER NOT NULL, - reactant_1 INTEGER NOT NULL, - reactant_2 INTEGER NOT NULL, - product_1 INTEGER NOT NULL, - product_2 INTEGER NOT NULL, - rate REAL NOT NULL -); -``` - -### The State Database -There are five tables in the initial state database all of which **must be created by the user**: - -``` -CREATE TABLE initial_state ( - species_id INTEGER NOT NULL PRIMARY KEY, - count INTEGER NOT NULL -); -``` -``` -CREATE TABLE trajectories ( - seed INTEGER NOT NULL, - step INTEGER NOT NULL, - time REAL NOT NULL, - reaction_id INTEGER NOT NULL -); -``` -``` -CREATE TABLE factors ( - factor_zero REAL NOT NULL, - factor_two REAL NOT NULL, - factor_duplicate REAL NOT NULL -); -``` -``` -CREATE TABLE interrupt_state ( - seed INTEGER NOT NULL, - species_id INTEGER NOT NULL, - count INTEGER NOT NULL -); -``` -``` -CREATE TABLE interrupt_cutoff ( - seed INTEGER NOT NULL, - step INTEGER NOT NULL, - time INTEGER NOT NULL -); -``` - -## Running NPMC -NPMC is run as follows: - -``` -$ cd NPMC -$ make NPMC -``` - -``` -./NPMC --nano_particle_database=../examples/NPMC/np.sqlite --initial_state_database=../examples/NPMC/initial_state.sqlite --number_of_simulations=1000 --base_seed=1000 --thread_count=8 --step_cutoff=200 -``` - -`NPMC` requires six input arguments (either `step_cutoff` or `time_cutoff` must be specified): - -- nano_particle_database : a sqlite database containing the nanoparticle data and metadata. -- initial_state_database : a sqlite database containing initial state. The simulation trajectories are also written into the database -- number_of_simulation : an integer specifying how many simulations to run -- base_seed : seeds used are `base_seed, base_seed+1, ..., base_seed+number_of_simulations-1` -- thread_count : how many threads to use. -- step_cutoff : how many steps in each simulation. -- time_cutoff : how much time in each simulation [s]. - -### The Nano Particle Database -There are four tables in the nanoparticle database all of which **must be created and filled in by the user**: - -``` -CREATE TABLE species ( - species_id INTEGER NOT NULL PRIMARY KEY, - degrees_of_freedom INTEGER NOT NULL -); -``` - -``` -CREATE TABLE sites ( - site_id INTEGER NOT NULL PRIMARY KEY, - x REAL NOT NULL, - y REAL NOT NULL, - z REAL NOT NULL, - species_id INTEGER NOT NULL -); -``` - -``` -CREATE TABLE interactions ( - interaction_id INTEGER NOT NULL PRIMARY KEY, - number_of_sites INTEGER NOT NULL, - species_id_1 INTEGER NOT NULL, - species_id_2 INTEGER NOT NULL, - left_state_1 INTEGER NOT NULL, - left_state_2 INTEGER NOT NULL, - right_state_1 INTEGER NOT NULL, - right_state_2 INTEGER NOT NULL, - rate REAL NOT NULL -); -``` - -``` -CREATE TABLE metadata ( - number_of_species INTEGER NOT NULL, - number_of_sites INTEGER NOT NULL, - number_of_interactions INTEGER NOT NULL -); -``` - -### The State Database -There are five tables in the initial state database all of which **must be created by the user**: - -``` -CREATE TABLE initial_state ( - site_id INTEGER NOT NULL PRIMARY KEY, - degree_of_freedom INTEGER NOT NULL -); -``` - -``` -CREATE TABLE trajectories ( - seed INTEGER NOT NULL, - step INTEGER NOT NULL, - time REAL NOT NULL, - site_id_1 INTEGER NOT NULL, - site_id_2 INTEGER NOT NULL, - interaction_id INTEGER NOT NULL -); -``` - -``` -CREATE TABLE factors ( - one_site_interaction_factor REAL NOT NULL, - two_site_interaction_factor REAL NOT NULL, - interaction_radius_bound REAL NOT NULL, - distance_factor_type TEXT NOT NULL -); -``` - -``` -CREATE TABLE interrupt_state ( - seed INTEGER NOT NULL, - site_id INTEGER NOT NULL, - degree_of_freedom INTEGER NOT NULL -); -``` - -``` -CREATE TABLE interrupt_cutoff ( - seed INTEGER NOT NULL, - step INTEGER NOT NULL, - time INTEGER NOT NULL -); -``` - -## LGMC -LGMC is run as follows: - -``` -$ cd LGMC -$ make LGMC -``` - -``` -./LGMC --lattice_reaction_database=../examples/LGMC/CO_oxidation/rn.sqlite --initial_state_database=../examples/LGMC/CO_oxidation/initial_state.sqlite --number_of_simulations=1000 --base_seed=1000 --thread_count=8 --step_cutoff=200 --parameters=../examples/LGMC/CO_oxidation/LGMC_params.txt -``` - -LGMC requires seven input arguments (either `step_cutoff` or `time_cutoff` must be specified): - -- reaction_database : a sqlite database containing the reaction network and metadata. -- initial_state_database : a sqlite database containing initial state. The simulation trajectories are also written into the database. -- number_of_simulation : an integer specifying how many simulations to run. -- base_seed : seeds used are `base_seed, base_seed+1, ..., base_seed+number_of_simulations-1`. -- thread_count : how many threads to use. -- step_cutoff : how many steps in each simulation. -- time_cutoff : how much time in each simulation [s]. -- parameters : name of .txt file containing additional parameters - - lattice_constant - - box x upper boundary - - box y upper boundary - - box z upper boundary - - temperature - - Electron free energy - - Is add site (T\|F) - - Charge transfer style (M\|B) - -### The Lattice Reaction Network Database - -There are two tables in the lattice reaction network database both of which **must be created and filled in by the user**: - -``` -CREATE TABLE metadata ( - number_of_species INTEGER NOT NULL, - number_of_reactions INTEGER NOT NULL -); -``` - -``` -CREATE TABLE reactions ( - reaction_id INTEGER NOT NULL PRIMARY KEY, - number_of_reactants INTEGER NOT NULL, - number_of_products INTEGER NOT NULL, - reactant_1 INTEGER NOT NULL, - reactant_2 INTEGER NOT NULL, - product_1 INTEGER NOT NULL, - product_2 INTEGER NOT NULL, - phase_reactant_1 CHAR(1) NOT NULL, - phase_reactant_2 CHAR(1) NOT NULL, - phase_product_1 CHAR(1) NOT NULL, - phase_product_2 CHAR(1) NOT NULL, - dG REAL NOT NULL, - prefactor REAL NOT NULL, - rate REAL NOT NULL, - electron_tunneling_coefficient REAL NOT NULL, - reorganization_energy REAL NOT NULL, - charge_transfer_coefficient REAL NOT NULL, - type CHAR(1) NOT NULL -); -``` -### The State Database -There are five tables in the initial state database all of which **must be created by the user**: -``` -CREATE TABLE initial_state ( - species_id INTEGER NOT NULL PRIMARY KEY, - count INTEGER NOT NULL -); -``` -``` -CREATE TABLE trajectories ( - seed INTEGER NOT NULL, - step INTEGER NOT NULL, - time REAL NOT NULL, - reaction_id INTEGER NOT NULL, - site_1_mapping INTEGER NOT NULL, - site_2_mapping INTEGER NOT NULL -); -``` -``` -CREATE TABLE factors ( - factor_zero REAL NOT NULL, - factor_two REAL NOT NULL, - factor_duplicate REAL NOT NULL -); -``` -``` -CREATE TABLE interrupt_state ( - seed INTEGER NOT NULL, - species_id INTEGER NOT NULL, - quantity INTEGER NOT NULL, - site_mapping INTEGER NOT NULL, - edge INTEGER NOT NULL - -); -``` -``` -CREATE TABLE interrupt_cutoff ( - seed INTEGER NOT NULL, - step INTEGER NOT NULL, - time INTEGER NOT NULL, - maxk INTEGER NOT NULL -); -``` \ No newline at end of file +RNMC depends on [GSL](https://www.gnu.org/software/gsl/) for pseudo random number generation and [sqlite](https://www.sqlite.org/index.html) for the database interfaces. \ No newline at end of file diff --git a/codemeta.json b/codemeta.json new file mode 100644 index 0000000..8951a09 --- /dev/null +++ b/codemeta.json @@ -0,0 +1,65 @@ +{ + "@context": "https://raw.githubusercontent.com/codemeta/codemeta/master/codemeta.jsonld", + "@type": "Code", + "author": [ + { + "@id": "https://orcid.org/0000-0003-3897-3097", + "@type": "Person", + "email": "laura.r.zichi@gmail.com", + "name": "Laura Zichi", + "affiliation": "University of Michigan - Ann Arbor; Lawrence Berkeley National Laboratory" + }, + { + "@id": "https://orcid.org/0000-0002-6408-1255", + "@type": "Person", + "email": "danielbarter@gmail.com", + "name": "Daniel Barter", + "affiliation": "Lawrence Berkeley National Laboratory" + }, + { + "@id": "https://orcid.org/0000-0002-6408-1255", + "@type": "Person", + "email": "esivonxay@lbl.gov", + "name": "Eric Sivonxay", + "affiliation": "Lawrence Berkeley National Laboratory" + }, + { + "@id": "https://orcid.org/0000-0003-1554-197X", + "@type": "Person", + "email": "espottesmith@gmail.com", + "name": "Evan Walter Clark Spotte-Smith", + "affiliation": "Lawrence Berkeley National Laboratory; Univeristy of California - Berkeley" + }, + { + "@id": "", + "@type": "Person", + "email": "rmohanakrishnan@lbl.gov", + "name": "Rohith Srinivaas Mohanakrishnan", + "affiliation": "Lawrence Berkeley National Laboratory; Univeristy of California - Berkeley" + }, + { + "@id": "https://orcid.org/0000-0003-2495-5509", + "@type": "Person", + "email": "kapersson@lbl.gov", + "name": "Kristin Aslaug Persson", + "affiliation": "Lawrence Berkeley National Laboratory; Univeristy of California - Berkeley" + }, + { + "@id": "https://orcid.org/0000-0003-3132-3032", + "@type": "Person", + "email": "smblau@lbl.gov", + "name": "Samuel M. Blau", + "affiliation": "Lawrence Berkeley National Laboratory" + } + ], + "identifier": "", + "codeRepository": "https://github.com/blauGroup/rnmc", + "datePublished": "2023-06-25", + "dateModified": "2023-06-25", + "dateCreated": "2023-06-25", + "description": "A core high-performance kinetic Monte Carlo (kMC) implementation designed for large reaction networks, with submodules for simulations of various types of physical and chemical systems.", + "keywords": "Python, C++, chemical dynamics, kinetic Monte Carlo", + "license": "UC Regents / LBNL", + "title": "RNMC", + "version": "v1.0.0" +} \ No newline at end of file diff --git a/core/simulation.h b/core/simulation.h index 69e2e07..011c484 100644 --- a/core/simulation.h +++ b/core/simulation.h @@ -56,4 +56,4 @@ class Simulation #include "simulation.cpp" -#endif +#endif \ No newline at end of file diff --git a/flake.lock b/flake.lock index d861045..4527318 100644 --- a/flake.lock +++ b/flake.lock @@ -1,23 +1,57 @@ { "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "mini-compile-commands": { + "flake": false, + "locked": { + "lastModified": 1668364794, + "narHash": "sha256-6NmqQOJmKtX3gtc8pOnJd7yfXIWX89hwdsq0te8/NwY=", + "owner": "danielbarter", + "repo": "mini_compile_commands", + "rev": "a609a8cf98e5ea8cafc624e9a5c96f18229c0996", + "type": "github" + }, + "original": { + "owner": "danielbarter", + "repo": "mini_compile_commands", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1650921206, - "narHash": "sha256-RGlfTC2ktqLVw0gBvZeCM//B4ig2CdQJm39sDvm0DBQ=", + "lastModified": 1668469466, + "narHash": "sha256-IBkBaXJ9ZQ6stveJctd3e8X6KJl9r0wwaI961TNhw9A=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3a9e0f239d80fa134e8fcbdee4dfc793902da37e", + "rev": "d4863da28cc397a1b72c08253cfa38f4c91fc2b7", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-21.11", + "ref": "master", "repo": "nixpkgs", "type": "github" } }, "root": { "inputs": { + "flake-compat": "flake-compat", + "mini-compile-commands": "mini-compile-commands", "nixpkgs": "nixpkgs" } } diff --git a/flake.nix b/flake.nix index 7a3fe68..eb7681b 100644 --- a/flake.nix +++ b/flake.nix @@ -1,36 +1,45 @@ { description = "High performance Monte Carlo simulator"; - inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-21.11; - - outputs = { self, nixpkgs }: + inputs = { + nixpkgs.url = github:NixOS/nixpkgs/master; + flake-compat = { + url = github:edolstra/flake-compat; + flake = false; + }; + mini-compile-commands = { + url = github:danielbarter/mini_compile_commands; + flake = false; + }; + }; + + outputs = { self, nixpkgs, flake-compat, mini-compile-commands }: # RNMC is so simple that the build derivation looks exactly the same on # all platforms. let genericDefaultPackage = systemString: with import nixpkgs { system = systemString; }; - stdenv.mkDerivation { + clang13Stdenv.mkDerivation { name = "RNMC"; src = self; buildInputs = [ - clang gsl sqlite ]; - buildPhase = "CC=clang++ ./build.sh"; + buildPhase = "./build.sh"; installPhase = "mkdir -p $out/bin; mv ./build/* $out/bin"; doCheck = true; checkPhase = "tests/test.sh"; - }; + in { devShell.x86_64-linux = with import nixpkgs { system = "x86_64-linux"; }; - mkShell { - + # (mkShell.override { stdenv = (callPackage mini-compile-commands {}).wrap clang13Stdenv; }) { + (mkShell.override { stdenv = clang13Stdenv; }) { buildInputs = [ gcc clang @@ -39,25 +48,6 @@ sqlitebrowser gdb valgrind - bintools-unwrapped # gprof - ]; - - # environment for CLANGD - # CPATH=$CLANGD_PATH emacs - CLANGD_PATH = builtins.concatStringsSep ":" [ - - # C++ stdlib headers - "${gcc-unwrapped}/include/c++/10.3.0" - "${gcc-unwrapped}/include/c++/10.3.0/x86_64-unknown-linux-gnu" - - # libc headers - "${glibc.dev}/include" - - # compiler specific headers - "${clang}/resource-root/include" - - "${sqlite.dev}/include" - "${gsl}/include" ]; }; @@ -66,11 +56,9 @@ x86_64-darwin = genericDefaultPackage "x86_64-darwin"; }; - checks = { - x86_64-linux.tests = genericDefaultPackage "x86_64-linux"; - x86_64-darwin.tests = genericDefaultPackage "x86_64-darwin"; - - }; - + checks = { + x86_64-linux.tests = genericDefaultPackage "x86_64-linux"; + x86_64-darwin.tests = genericDefaultPackage "x86_64-darwin"; + }; }; } diff --git a/generate b/generate new file mode 100755 index 0000000..768139d --- /dev/null +++ b/generate @@ -0,0 +1,146 @@ +#!/usr/bin/ruby + +# For an OO language, this is distinctly procedural. Should probably fix that. +require 'json' + +details = Hash.new({}) + +capture_params = [ + { :name => "title", :message => "Enter project name." }, + { :name => "url", :message => "Enter the URL of the project repository." }, + { :name => "description", :message => "Enter the (short) project description." }, + { :name => "license", :message => "Enter the license this software shared under. (hit enter to skip)\nFor example MIT, BSD, GPL v3.0, Apache 2.0" }, + { :name => "doi", :message => "Enter the DOI of the archived version of this code. (hit enter to skip)\nFor example http://dx.doi.org/10.6084/m9.figshare.828487" }, + { :name => "keywords", :message => "Enter keywords that should be associated with this project (hit enter to skip)\nComma-separated, for example: turkey, chicken, pot pie" }, + { :name => "version", :message => "Enter the version of your software (hit enter to skip)\nSEMVER preferred: http://semver.org e.g. v1.0.0" } +] + +puts "I'm going to try and help you prepare some things for your JOSS submission" +puts "If all goes well then we'll have a nice codemeta.json file soon..." +puts "" +puts "************************************" +puts "* First, some basic details *" +puts "************************************" +puts "" + +# Loop through the desired captures and print out for clarity +capture_params.each do |param| + puts param[:message] + print "> " + input = gets + + details[param[:name]] = input.chomp + + puts "" + puts "OK, your project has #{param[:name]}: #{input}" + puts "" +end + +puts "" +puts "************************************" +puts "* Experimental stuff *" +puts "************************************" +puts "" + +puts "Would you like me to try and build a list of authors for you?" +puts "(You need to be running this script in a git repository for this to work)" +print "> (Y/N)" +answer = gets.chomp + +case answer.downcase +when "y", "yes" + + # Use git shortlog to extract a list of author names and commit counts. + # Note we don't extract emails here as there's often different emails for + # each user. Instead we capture emails at the end. + + git_log = `git shortlog --summary --numbered --no-merges` + + # ["252\tMichael Jackson", "151\tMC Hammer"] + authors_and_counts = git_log.split("\n").map(&:strip) + + authors_and_counts.each do |author_count| + count, author = author_count.split("\t").map(&:strip) + + puts "Looks like #{author} made #{count} commits" + puts "Add them to the output?" + print "> (Y/N)" + answer = gets.chomp + + # If a user chooses to add this author to the output then we ask for some + # additional information including their email, ORCID and affiliation. + case answer.downcase + when "y", "yes" + puts "What is #{author}'s email address? (hit enter to skip)" + print "> " + email = gets.chomp + + puts "What is #{author}'s ORCID? (hit enter to skip)" + puts "For example: http://orcid.org/0000-0000-0000-0000" + print "> " + orcid = gets.chomp + + puts "What is #{author}'s affiliation? (hit enter to skip)" + print "> " + affiliation = gets.chomp + + + details['authors'].merge!(author => { 'commits' => count, + 'email' => email, + 'orcid' => orcid, + 'affiliation' => affiliation }) + + when "n", "no" + puts "OK boss..." + puts "" + end + end +when "n", "no" + puts "OK boss..." + puts "" +end + +puts "Reticulating splines" + +5.times do + print "." + sleep 0.5 +end + +puts "" +puts "Generating some JSON goodness..." + +# TODO: work out how to use some kind of JSON template here. +# Build the output list of authors from the inputs we've collected. +output_authors = [] + +details['authors'].each do |author_name, values| + entry = { + "@id" => values['orcid'], + "@type" => "Person", + "email" => values['email'], + "name" => author_name, + "affiliation" => values['affiliation'] + } + output_authors << entry +end + +# TODO: this is currently a static template (written out here). It would be good +# to do something smarter here. +output = { + "@context" => "https://raw.githubusercontent.com/codemeta/codemeta/master/codemeta.jsonld", + "@type" => "Code", + "author" => output_authors, + "identifier" => details['doi'], + "codeRepository" => details['url'], + "datePublished" => Time.now.strftime("%Y-%m-%d"), + "dateModified" => Time.now.strftime("%Y-%m-%d"), + "dateCreated" => Time.now.strftime("%Y-%m-%d"), + "description" => details['description'], + "keywords" => details['keywords'], + "license" => details['license'], + "title" => details['title'], + "version" => details['version'] +} + +File.open('codemeta.json', 'w') {|f| f.write(JSON.pretty_generate(output)) } \ No newline at end of file diff --git a/paper.bib b/paper.bib new file mode 100644 index 0000000..2fd1822 --- /dev/null +++ b/paper.bib @@ -0,0 +1,125 @@ +@article{marcus1965theory, + title={On the theory of electron-transfer reactions. VI. Unified treatment for homogeneous and electrode reactions}, + author={Marcus, Rudolph A}, + journal={The Journal of Chemical Physics}, + volume={43}, + number={2}, + pages={679--701}, + year={1965}, + publisher={American Institute of Physics} +} + +@article{gillespie1977exact, + title={Exact stochastic simulation of coupled chemical reactions}, + author={Gillespie, Daniel T}, + journal={The Journal of Physical Chemistry}, + volume={81}, + number={25}, + pages={2340--2361}, + year={1977}, + publisher={ACS Publications} +} + +@techreport{garcia2009crossing, + title={Crossing the mesoscale no-mans land via parallel kinetic Monte Carlo}, + author={Garcia Cardona, Cristina and Wagner, Gregory John and Tikare, Veena and Holm, Elizabeth Ann and Plimpton, Steven James and Thompson, Aidan Patrick and Slepoy, Alexander and Zhou, Xiao Wang and Battaile, Corbett Chandler and Chandross, Michael Evan}, + year={2009}, + institution={Sandia National Laboratories (SNL), Albuquerque, NM, and Livermore, CA} +} + +@article{hoffmann2014kmos, + title={kmos: A lattice kinetic Monte Carlo framework}, + author={Hoffmann, Max J and Matera, Sebastian and Reuter, Karsten}, + journal={Computer Physics Communications}, + volume={185}, + number={7}, + pages={2138--2150}, + year={2014}, + publisher={Elsevier} +} + +@book{newman2021electrochemical, + title={Electrochemical Systems}, + author={Newman, John and Balsara, Nitash P}, + year={2021}, + publisher={John Wiley \& Sons} +} + +@article{spotte2022toward, + title={Toward a Mechanistic Model of Solid--Electrolyte Interphase Formation and Evolution in Lithium-Ion Batteries}, + author={Spotte-Smith, Evan Walter Clark and Kam, Ronald L and Barter, Daniel and Xie, Xiaowei and Hou, Tingzheng and Dwaraknath, Shyam and Blau, Samuel M and Persson, Kristin A}, + journal={ACS Energy Letters}, + volume={7}, + number={4}, + pages={1446--1453}, + year={2022}, + publisher={ACS Publications} +} + +@article{barter2023predictive, + title={Predictive stochastic analysis of massive filter-based electrochemical reaction networks}, + author={Barter, Daniel and Spotte-Smith, Evan Walter Clark and Redkar, Nikita S and Khanwale, Aniruddh and Dwaraknath, Shyam and Persson, Kristin A and Blau, Samuel M}, + journal={Digital Discovery}, + volume={2}, + number={1}, + pages={123--137}, + year={2023}, + publisher={Royal Society of Chemistry} +} + +@article{spotte2023chemical, + title={Chemical reaction networks explain gas evolution mechanisms in mg-ion batteries}, + author={Spotte-Smith, Evan Walter Clark and Blau, Samuel M and Barter, Daniel and Leon, Noel J and Hahn, Nathan T and Redkar, Nikita S and Zavadil, Kevin R and Liao, Chen and Persson, Kristin A}, + journal={Journal of the American Chemical Society}, + volume={145}, + number={22}, + pages={12181--12192}, + year={2023}, + publisher={ACS Publications} +} + +@article{xia2023accelerating, + title={Accelerating the Design of Multishell Upconverting Nanoparticles through Bayesian Optimization}, + author={Xia, Xiaojing and Sivonxay, Eric and Helms, Brett A and Blau, Samuel M and Chan, Emory M}, + journal={Nano Letters}, + volume={23}, + number={23}, + pages={11129--11136}, + year={2023}, + publisher={ACS Publications} +} + +@article{chan2015combinatorial, + title={Combinatorial approaches for developing upconverting nanomaterials: high-throughput screening, modeling, and applications}, + author={Chan, Emory M}, + journal={Chemical Society Reviews}, + volume={44}, + number={6}, + pages={1653--1679}, + year={2015}, + publisher={Royal Society of Chemistry} +} + +@article{skripka2023NL, + author = {Skripka, Artiom and Lee, Minji and Qi, Xiao and Pan, Jia-Ahn and Yang, Haoran and Lee, Changhwan and Schuck, P. James and Cohen, Bruce E. and Jaque, Daniel and Chan, Emory M.}, + title = {A Generalized Approach to Photon Avalanche Upconversion in Luminescent Nanocrystals}, + journal = {Nano Letters}, + volume = {23}, + number = {15}, + pages = {7100-7106}, + year = {2023}, + doi = {10.1021/acs.nanolett.3c01955}, + URL = {https://doi.org/10.1021/acs.nanolett.3c01955}, + eprint = {https://doi.org/10.1021/acs.nanolett.3c01955}, +} + +@article{teitelboim2019energy, + title={Energy transfer networks within upconverting nanoparticles are complex systems with collective, robust, and history-dependent dynamics}, + author={Teitelboim, Ayelet and Tian, Bining and Garfield, David J and Fernandez-Bravo, Angel and Gotlin, Adam C and Schuck, P James and Cohen, Bruce E and Chan, Emory M}, + journal={The Journal of Physical Chemistry C}, + volume={123}, + number={4}, + pages={2678--2689}, + year={2019}, + publisher={ACS Publications} +} diff --git a/paper.md b/paper.md new file mode 100644 index 0000000..6896edb --- /dev/null +++ b/paper.md @@ -0,0 +1,98 @@ +--- +title: >- + RNMC: kinetic Monte Carlo implementations for complex reaction networks +tags: + - C++ + - chemical dynamics + - kinetic Monte Carlo +authors: + - name: Laura Zichi + orcid: 0000-0003-3897-3097 + equal-contrib: true + corresponding: false + affiliation: "1, 2" + - name: Daniel Barter + orcid: 0000-0002-6408-1255 + corresponding: false + equal-contrib: true + affiliation: 3 + - name: Eric Sivonxay + orcid: 0000-0002-6408-1255 + corresponding: false + equal-contrib: true + affiliation: 3 + - name: Evan Walter Clark Spotte-Smith + orcid: 0000-0003-1554-197X + corresponding: false + affiliation: "1, 4" + - name: Rohith Srinivaas Mohanakrishnan + corresponding: false + affiliation: "1, 4" + - name: Emory M. Chan + corresponding: false + affiliation: 5 + - name: Kristin Aslaug Persson + corresponding: true + affiliation: "4, 5" + - name: Samuel M. Blau + corresponding: true + affiliation: 3 +affiliations: + - name: Materials Science Division, Lawrence Berkeley National Laboratory, Berkeley, CA, USA 94720 + index: 1 + - name: Department of Physics, University of Michigan - Ann Arbor, Ann Arbor, MI, USA 48109 + index: 2 + - name: Energy Storage and Distributed Resources, Lawrence Berkeley National Laboratory, Berkeley, CA USA 94720 + index: 3 + - name: Department of Materials Science and Engineering, University of California - Berkeley, CA, USA 94720 + index: 4 + - name: Molecular Foundry, Lawrence Berkeley National Laboratory, Berkeley, CA, USA 94720 + index: 5 +date: 2024-08-14 +bibliography: paper.bib +--- + +# Summary +Macroscopic chemical and physical phenomena are driven by microscopic interactions at the atomic and molecular scales. +In order to capture complex processes with high fidelity, simulation methods that bridge disparate time and length scales are needed. +While techniques like molecular dynamics and *ab initio* simulations capture dynamics and reactivity at high resolution, they cannot be used beyond relatively small length (hundreds to thousands of atoms) and time scales (picoseconds to microseconds). +Kinetic Monte Carlo (kMC) approaches overcome these limitations to bridge length and time scales across several orders of magnitude while retaining relevant microscopic resolution, making it a powerful and flexible tool. + + +Here, we present `RNMC`, an easy-to-use, modular, high-performance kMC simulation framework that enables modeling of complex systems. +`RNMC` consists of a core module defining the common features of kMC algorithms, including an implementation of the Gillespie algorithm [@gillespie1977exact], input/output operations leveraging SQLite databases, threading logic for parallel execution, and dependency graphs for efficient event propensity updates. +In addition, there are currently three modules defining kMC implementations for different types of applications. +The `GMC` (Gillespie Monte Carlo) module enables simulations of reaction networks in a homogeneous (well-mixed) environment. +`GMC` is a basic tool that is appropriate for general simulations of solution-phase chemistry. +The `NPMC` (NanoParticle Monte Carlo) module enables simulation of dynamics in nanoparticles with 3D statistical field theory and supports one- and two-site interactions. +Finally, the `LGMC` (Lattice Gillespie Monte Carlo) module is designed for simulations of multi-phase systems (especially at solid-fluid interfaces) where chemical and electrochemical reactions can occur between a lattice region and a homogeneous region. +We have designed `RNMC` to be easily extensible, enabling users to add additional kMC modules for other diverse chemical and physical systems. + +# Statement of need + +Three are many existing kMC implementations, including several open source examples (e.g. the Stochastic Parallel PARticle Kinetic Simulator or `SPPARKS`[@garcia2009crossing] and `kmos`).[@hoffmann2014kmos] +`RNMC` began as a fork of SPPARKS but differs in several important ways. +First, because `RNMC` uses the widely supported SQLite database engine for simulation inputs and outputs, it facilitates the automation of simulations. +Second, `RNMC` has a focus on modularity; it is designed such that users can quickly develop new types of kMC simulations using a common core library. + +The simulation modules already implemented in `RNMC` provide unique capabilities that are not widely available in other open source codes. +`NPMC` is specifically designed for 3D simulations of the complex photophysical interaction networks in nanocrystals,[@teitelboim2019energy] particularly multi-domain heterostructures whose optical properties cannot be calculated deterministically.[@skripka2023NL] +`NPMC` can be used to simulate energy transfer interactions between dopants in nanoparticles, their radiative transitions, and nonlinear processes such as upconversion [@chan2015combinatorial] and photon avalanching.[@skripka2023NL] +`LGMC` is also somewhat unique in that it can simulate multi-phase systems and electrochemical processes. +Simulations using `LGMC` can include a lattice region and a homogeneous solution region which can interact *via* interfacial reactions. +Electrochemcial reactions can be treated using Marcus theory[@marcus1965theory] or Butler-Volmer kinetics.[@newman2021electrochemical] +Because it allows for a dynamic lattice region, `LGMC` is also appropriate for simulations of nucleation and growth, dissolution, precipitation, and related phenomena. + +We have already used the `GMC` module in a number of prior works in applications related to Li-ion and Mg-ion batteries.[@spotte2022toward; @barter2023predictive; @spotte2023chemical] We note that these simulations included tens of millions of reactions, demonstrating that `RNMC` is able to scale to large and complex reaction networks. In addition, we have used `NPMC` to perform Bayesian optimization of upconverting nanoparticles.[@xia2023accelerating] + +# Acknowledgements + +This project was intellectually led by the Laboratory Directed Research and Development Program of Lawrence Berkeley National Laboratory under U.S. Department of Energy Contract No. DE-AC02-05CH11231. +L.Z. was supported in part by the U.S. Department of Energy, Office of Science, Office of Workforce Development for Teachers and Scientists (WDTS) under the Science Undergraduate Laboratory Internships Program (SULI). +E.W.C.S.-S. was supported by the Kavli Energy NanoScience Institute Philomathia Graduate Student Fellowship. +Work at the Molecular Foundry (E.M.C., K.A.P) was supported by the Office of Science, Office of Basic Energy Sciences, of the U.S. Department of Energy under Contract No. DE-AC02-05CH11231. +Additional support came from the Joint Center for Energy Storage Research (JCESR), an Energy Innovation Hub funded by the U.S. Department of Energy, Office of Science, Basic Energy Sciences. +This code was developed and tested using computational resources provided by the National Energy Research Scientific Computing Center (NERSC), a U.S. Department of Energy Office of Science User Facility under Contract No. DE-AC02-05CH11231, the Eagle and Swift HPC systems at the National Renewable Energy Laboratory (NREL), and the Lawrencium HPC cluster at Lawrence Berkeley National Laboratory. + +# References + diff --git a/paper.pdf b/paper.pdf new file mode 100644 index 0000000..1d2efa9 Binary files /dev/null and b/paper.pdf differ diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..6234bb4 --- /dev/null +++ b/shell.nix @@ -0,0 +1,10 @@ +(import + ( + let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { src = ./.; } +).shellNix