diff --git a/doc/src/JPG/tutorial_additional_changes.png b/doc/src/JPG/tutorial_additional_changes.png new file mode 100644 index 0000000000..7cd13de1ee Binary files /dev/null and b/doc/src/JPG/tutorial_additional_changes.png differ diff --git a/doc/src/JPG/tutorial_automated_checks.png b/doc/src/JPG/tutorial_automated_checks.png new file mode 100644 index 0000000000..85d774c293 Binary files /dev/null and b/doc/src/JPG/tutorial_automated_checks.png differ diff --git a/doc/src/JPG/tutorial_automated_checks_passed.png b/doc/src/JPG/tutorial_automated_checks_passed.png new file mode 100644 index 0000000000..fda22a46d1 Binary files /dev/null and b/doc/src/JPG/tutorial_automated_checks_passed.png differ diff --git a/doc/src/JPG/tutorial_branch.png b/doc/src/JPG/tutorial_branch.png index 0c6d2c0881..b23c5fec9f 100644 Binary files a/doc/src/JPG/tutorial_branch.png and b/doc/src/JPG/tutorial_branch.png differ diff --git a/doc/src/JPG/tutorial_changes_others.png b/doc/src/JPG/tutorial_changes_others.png new file mode 100644 index 0000000000..009a8fc50d Binary files /dev/null and b/doc/src/JPG/tutorial_changes_others.png differ diff --git a/doc/src/JPG/tutorial_create_new_pull_request1.png b/doc/src/JPG/tutorial_create_new_pull_request1.png new file mode 100644 index 0000000000..80426ec55d Binary files /dev/null and b/doc/src/JPG/tutorial_create_new_pull_request1.png differ diff --git a/doc/src/JPG/tutorial_create_new_pull_request2.png b/doc/src/JPG/tutorial_create_new_pull_request2.png new file mode 100644 index 0000000000..5deb6b3266 Binary files /dev/null and b/doc/src/JPG/tutorial_create_new_pull_request2.png differ diff --git a/doc/src/JPG/tutorial_edits_maintainers.png b/doc/src/JPG/tutorial_edits_maintainers.png new file mode 100644 index 0000000000..c57c09a37a Binary files /dev/null and b/doc/src/JPG/tutorial_edits_maintainers.png differ diff --git a/doc/src/JPG/tutorial_fork.png b/doc/src/JPG/tutorial_fork.png index f22db97112..1d512ba3e7 100644 Binary files a/doc/src/JPG/tutorial_fork.png and b/doc/src/JPG/tutorial_fork.png differ diff --git a/doc/src/JPG/tutorial_https_block.png b/doc/src/JPG/tutorial_https_block.png index ffa4523681..6eecc6ad2c 100644 Binary files a/doc/src/JPG/tutorial_https_block.png and b/doc/src/JPG/tutorial_https_block.png differ diff --git a/doc/src/JPG/tutorial_new_pull_request.png b/doc/src/JPG/tutorial_new_pull_request.png new file mode 100644 index 0000000000..c442282c81 Binary files /dev/null and b/doc/src/JPG/tutorial_new_pull_request.png differ diff --git a/doc/src/JPG/tutorial_reverse_pull_request.png b/doc/src/JPG/tutorial_reverse_pull_request.png new file mode 100644 index 0000000000..051fa2f513 Binary files /dev/null and b/doc/src/JPG/tutorial_reverse_pull_request.png differ diff --git a/doc/src/JPG/tutorial_reverse_pull_request2.png b/doc/src/JPG/tutorial_reverse_pull_request2.png new file mode 100644 index 0000000000..28daacec96 Binary files /dev/null and b/doc/src/JPG/tutorial_reverse_pull_request2.png differ diff --git a/doc/src/JPG/tutorial_reverse_pull_request3.png b/doc/src/JPG/tutorial_reverse_pull_request3.png new file mode 100644 index 0000000000..40e6714d59 Binary files /dev/null and b/doc/src/JPG/tutorial_reverse_pull_request3.png differ diff --git a/doc/src/JPG/tutorial_reverse_pull_request4.png b/doc/src/JPG/tutorial_reverse_pull_request4.png new file mode 100644 index 0000000000..b18f449a8e Binary files /dev/null and b/doc/src/JPG/tutorial_reverse_pull_request4.png differ diff --git a/doc/src/JPG/tutorial_reverse_pull_request5.png b/doc/src/JPG/tutorial_reverse_pull_request5.png new file mode 100644 index 0000000000..ffd4c2db39 Binary files /dev/null and b/doc/src/JPG/tutorial_reverse_pull_request5.png differ diff --git a/doc/src/JPG/tutorial_reverse_pull_request6.png b/doc/src/JPG/tutorial_reverse_pull_request6.png new file mode 100644 index 0000000000..4647850bb4 Binary files /dev/null and b/doc/src/JPG/tutorial_reverse_pull_request6.png differ diff --git a/doc/src/JPG/tutorial_steve_assignee.png b/doc/src/JPG/tutorial_steve_assignee.png new file mode 100644 index 0000000000..5448dd91fc Binary files /dev/null and b/doc/src/JPG/tutorial_steve_assignee.png differ diff --git a/doc/src/Manual.txt b/doc/src/Manual.txt index a2c5ad3f0b..043868a145 100644 --- a/doc/src/Manual.txt +++ b/doc/src/Manual.txt @@ -1,7 +1,7 @@ LAMMPS Users Manual - + @@ -21,7 +21,7 @@

LAMMPS Documentation :c,h3 -21 Dec 2016 version :c,h4 +6 Jan 2017 version :c,h4 Version info: :h4 diff --git a/doc/src/PDF/colvars-refman-lammps.pdf b/doc/src/PDF/colvars-refman-lammps.pdf index 5acaf8260c..5b776defca 100644 Binary files a/doc/src/PDF/colvars-refman-lammps.pdf and b/doc/src/PDF/colvars-refman-lammps.pdf differ diff --git a/doc/src/Section_commands.txt b/doc/src/Section_commands.txt index 20503e8522..e1cef1b94c 100644 --- a/doc/src/Section_commands.txt +++ b/doc/src/Section_commands.txt @@ -581,7 +581,7 @@ USER-INTEL, k = KOKKOS, o = USER-OMP, t = OPT. "indent"_fix_indent.html, "langevin (k)"_fix_langevin.html, "lineforce"_fix_lineforce.html, -"momentum"_fix_momentum.html, +"momentum (k)"_fix_momentum.html, "move"_fix_move.html, "msst"_fix_msst.html, "neb"_fix_neb.html, @@ -702,6 +702,7 @@ package"_Section_start.html#start_3. "manifoldforce"_fix_manifoldforce.html, "meso/stationary"_fix_meso_stationary.html, "nve/manifold/rattle"_fix_nve_manifold_rattle.html, +"nvk"_fix_nvk.html, "nvt/manifold/rattle"_fix_nvt_manifold_rattle.html, "nph/eff"_fix_nh_eff.html, "npt/eff"_fix_nh_eff.html, diff --git a/doc/src/fix_colvars.txt b/doc/src/fix_colvars.txt index 1991496d19..e2be03f46b 100644 --- a/doc/src/fix_colvars.txt +++ b/doc/src/fix_colvars.txt @@ -31,21 +31,19 @@ fix abf all colvars colvars.inp tstat 1 :pre [Description:] -This fix interfaces LAMMPS to a "collective variables" or "colvars" -module library which allows to calculate potentials of mean force +This fix interfaces LAMMPS to the collective variables "Colvars" +library, which allows to calculate potentials of mean force (PMFs) for any set of colvars, using different sampling methods: currently implemented are the Adaptive Biasing Force (ABF) method, metadynamics, Steered Molecular Dynamics (SMD) and Umbrella Sampling -(US) via a flexible harmonic restraint bias. The colvars library is -hosted at "http://colvars.github.io/"_http://colvars.github.io/ +(US) via a flexible harmonic restraint bias. This documentation describes only the fix colvars command itself and LAMMPS specific parts of the code. The full documentation of the colvars library is available as "this supplementary PDF document"_PDF/colvars-refman-lammps.pdf -A detailed discussion of the implementation of the portable collective -variable library is in "(Fiorin)"_#Fiorin. Additional information can -be found in "(Henin)"_#Henin. +The Colvars library is developed at "https://github.com/colvars/colvars"_https://github.com/colvars/colvars +A detailed discussion of its implementation is in "(Fiorin)"_#Fiorin. There are some example scripts for using this package with LAMMPS in the examples/USER/colvars directory. @@ -129,8 +127,3 @@ and tstat = NULL. :link(Fiorin) [(Fiorin)] Fiorin , Klein, Henin, Mol. Phys., DOI:10.1080/00268976.2013.813594 - -:link(Henin) -[(Henin)] Henin, Fiorin, Chipot, Klein, J. Chem. Theory Comput., 6, -35-47 (2010) - diff --git a/doc/src/fix_momentum.txt b/doc/src/fix_momentum.txt index 52b99aaa0d..4f94e2a857 100644 --- a/doc/src/fix_momentum.txt +++ b/doc/src/fix_momentum.txt @@ -7,6 +7,7 @@ :line fix momentum command :h3 +fix momentum/kk command :h3 [Syntax:] @@ -55,6 +56,29 @@ of atoms by rescaling the velocities after the momentum was removed. Note that the "velocity"_velocity.html command can be used to create initial velocities with zero aggregate linear and/or angular momentum. +:line + +Styles with a {gpu}, {intel}, {kk}, {omp}, or {opt} suffix are +functionally the same as the corresponding style without the suffix. +They have been optimized to run faster, depending on your available +hardware, as discussed in "Section 5"_Section_accelerate.html +of the manual. The accelerated styles take the same arguments and +should produce the same results, except for round-off and precision +issues. + +These accelerated styles are part of the GPU, USER-INTEL, KOKKOS, +USER-OMP and OPT packages, respectively. They are only enabled if +LAMMPS was built with those packages. See the "Making +LAMMPS"_Section_start.html#start_3 section for more info. + +You can specify the accelerated styles explicitly in your input script +by including their suffix, or you can use the "-suffix command-line +switch"_Section_start.html#start_7 when you invoke LAMMPS, or you can +use the "suffix"_suffix.html command in your input script. + +See "Section 5"_Section_accelerate.html of the manual for +more instructions on how to use the accelerated styles effectively. + [Restart, fix_modify, output, run start/stop, minimize info:] No information about this fix is written to "binary restart diff --git a/doc/src/fix_nvk.txt b/doc/src/fix_nvk.txt new file mode 100644 index 0000000000..271483b441 --- /dev/null +++ b/doc/src/fix_nvk.txt @@ -0,0 +1,71 @@ +"LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c + +:link(lws,http://lammps.sandia.gov) +:link(ld,Manual.html) +:link(lc,Section_commands.html#comm) + +:line + +fix nvk command :h3 + +[Syntax:] + +fix ID group-ID nvk :pre + +ID, group-ID are documented in "fix"_fix.html command +nvk = style name of this fix command :ul + +[Examples:] + +fix 1 all nvk :pre + +[Description:] + +Perform constant kinetic energy integration using the Gaussian +thermostat to update position and velocity for atoms in the group each +timestep. V is volume; K is kinetic energy. This creates a system +trajectory consistent with the isokinetic ensemble. + +The equations of motion used are those of Minary et al in +"(Minary)"_#nvk-Minary, a variant of those initially given by Zhang in +"(Zhang)"_#nvk-Zhang. + +The kinetic energy will be held constant at its value given when fix +nvk is initiated. If a different kinetic energy is desired, the +"velocity"_velocity.html command should be used to change the kinetic +energy prior to this fix. + +:line + +[Restart, fix_modify, output, run start/stop, minimize info:] + +No information about this fix is written to "binary restart +files"_restart.html. None of the "fix_modify"_fix_modify.html options +are relevant to this fix. No global or per-atom quantities are stored +by this fix for access by various "output +commands"_Section_howto.html#howto_15. No parameter of this fix can +be used with the {start/stop} keywords of the "run"_run.html command. +This fix is not invoked during "energy minimization"_minimize.html. + +[Restrictions:] + +The Gaussian thermostat only works when it is applied to all atoms in +the simulation box. Therefore, the group must be set to all. + +This fix has not yet been implemented to work with the RESPA integrator. + +This fix is part of the USER-MISC package. It is only enabled if LAMMPS +was built with that package. See the "Making +LAMMPS"_Section_start.html#start_3 section for more info. + +[Related commands:] none + +[Default:] none + +:line + +:link(nvk-Minary) +[(Minary)] Minary, Martyna, and Tuckerman, J Chem Phys, 18, 2510 (2003). + +:link(nvk-Zhang) +[(Zhang)] Zhang, J Chem Phys, 106, 6102 (1997). diff --git a/doc/src/fixes.txt b/doc/src/fixes.txt index d17b88306d..ca43a1d1e7 100644 --- a/doc/src/fixes.txt +++ b/doc/src/fixes.txt @@ -90,6 +90,7 @@ Fixes :h1 fix_nve_noforce fix_nve_sphere fix_nve_tri + fix_nvk fix_nvt_asphere fix_nvt_body fix_nvt_manifold_rattle diff --git a/doc/src/lammps.book b/doc/src/lammps.book index ec689adf15..5f8af357b7 100644 --- a/doc/src/lammps.book +++ b/doc/src/lammps.book @@ -214,6 +214,7 @@ fix_nve_manifold_rattle.html fix_nve_noforce.html fix_nve_sphere.html fix_nve_tri.html +fix_nvk.html fix_nvt_asphere.html fix_nvt_body.html fix_nvt_manifold_rattle.html diff --git a/doc/src/tutorial_github.txt b/doc/src/tutorial_github.txt index f31de522cc..aed47a5733 100644 --- a/doc/src/tutorial_github.txt +++ b/doc/src/tutorial_github.txt @@ -11,10 +11,22 @@ LAMMPS GitHub tutorial :h3 :line -This document briefly describes how to use GitHub to merge changes you -make into LAMMPS, using GitHub. It assumes that you are familiar with -git. You may want to have a look at the "Git -book"_http://git-scm.com/book/ to reacquaint yourself. +This document describes the process of how to use GitHub to integrate +changes or additions you have made to LAMMPS into the official LAMMPS +distribution. It uses the process of updating this very tutorial as +an example to describe the individual steps and options. You need to +be familiar with git and you may want to have a look at the +"Git book"_http://git-scm.com/book/ to reacquaint yourself with some +of the more advanced git features used below. + +As of fall 2016, submitting contributions to LAMMPS via pull requests +on GitHub is the preferred option for integrating contributed features +or improvements to LAMMPS, as it significantly reduces the amount of +work required by the LAMMPS developers. Consequently, creating a pull +request will increase your chances to have your contribution included +and will reduce the time until the integration is complete. For more +information on the requirements to have your code included into LAMMPS +please see "Section 10.15"_Section_modify.html#mod_15 :line @@ -30,106 +42,121 @@ username or e-mail address and password. [Forking the repository] -To get changes into LAMMPS, you need to first fork the repository. At -the time of writing, LAMMPS-ICMS is the preferred fork. Go to "LAMMPS -on GitHub"_https://github.com/lammps/lammps and make sure branch is -set to "lammps-icms", see the figure below. +To get changes into LAMMPS, you need to first fork the `lammps/lammps` +repository on GitHub. At the time of writing, {master} is the preferred +target branch. Thus go to "LAMMPS on GitHub"_https://github.com/lammps/lammps +and make sure branch is set to "master", as shown in the figure below. :c,image(JPG/tutorial_branch.png) -Now, click on fork in the top right corner: +If it is not, use the button to change it to {master}. Once it is, use the +fork button to create a fork. :c,image(JPG/tutorial_fork.png) -This will create your own fork of the LAMMPS repository. You can make -changes in this fork and later file {pull requests} to allow the -upstream repository to merge changes from your own fork into the one -we just forked from. At the same time, you can set things up, so you -can include changes from upstream into your repository. + +This will create a fork (which is essentially a copy, but uses less +resources) of the LAMMPS repository under your own GitHub account. You +can make changes in this fork and later file {pull requests} to allow +the upstream repository to merge changes from your own fork into the one +we just forked from (or others that were forked from the same repository). +At the same time, you can set things up, so you can include changes from +upstream into your repository and thus keep it in sync with the ongoing +LAMMPS development. :line [Adding changes to your own fork] -Before adding changes, it is better to first create a new branch that -will contain these changes, a so-called feature branch. +Additions to the upstream version of LAMMPS are handled using {feature +branches}. For every new feature, a so-called feature branch is +created, which contains only those modification relevant to one specific +feature. For example, adding a single fix would consist of creating a +branch with only the fix header and source file and nothing else. It is +explained in more detail here: "feature branch +workflow"_https://www.atlassian.com/git/tutorials/comparing-workflows/feature-branch-workflow. [Feature branches] -Since LAMMPS is such a big project and most user contributions come in -small portions, the most ideal workflow for LAMMPS is the so-called -"Feature branch" workflow. It is explained in great detail here: -"feature branch -workflow"_https://www.atlassian.com/git/tutorials/comparing-workflows/feature-branch-workflow. +First of all, create a clone of your version on github on your local +machine via HTTPS: -The idea is that every new feature for LAMMPS gets its own -branch. This way, it is fairly painless to incorporate new features -into the upstream repository. I will explain briefly here how to do -it. In this feature branch, I will add a USER-package. + $ git clone https://github.com//lammps.git :pre -I assume that git is installed on the local machine and you know how -to use a command line. +or, if you have set up your GitHub account for using SSH keys, via SSH: -First of all, you need to clone your own fork of LAMMPS: - - $ git clone https://github.com//lammps.git :pre - -You can find the proper url to the right of the "HTTPS" block, see figure. + $ git clone git@github.com:/lammps.git :pre + +You can find the proper URL by clicking the "Clone or download"-button: :c,image(JPG/tutorial_https_block.png) The above command copies ("clones") the git repository to your local -machine. You can use this local clone to make changes and test them -without interfering with the repository on github. First, however, it -is recommended to make a new branch for a particular feature you would -like added to LAMMPS. In this example, I will try adding a new -USER-package called USER-MANIFOLD. +machine to a directory with the name you chose. If none is given, it will +default to "lammps". Typical names are "mylammps" or something similar. -To create a new branch, run the following git command in your repository: +You can use this local clone to make changes and +test them without interfering with the repository on Github. -$ git checkout -b add-user-manifold :pre +To pull changes from upstream into this copy, you can go to the directory +and use git pull: -The name of this new branch is "add-user-manifold" in my case. Just -name it after something that resembles the feature you want added to -LAMMPS. + $ cd mylammps + $ git checkout master + $ git pull https://github.com/lammps/lammps :pre -Now that you've changed branches, you can edit the files as you see -fit, add new files, and commit as much as you would like. Just -remember that if halfway you decide to add another, unrelated feature, -you should switch branches! +You can also add this URL as a remote: + + $ git remote add lammps_upstream https://www.github.com/lammps/lammps :pre + +At this point, you typically make a feature branch from the updated master +branch for the feature you want to work on. This tutorial contains the +workflow that updated this tutorial, and hence we will call the branch +"github-tutorial-update": + + $ git checkout -b github-tutorial-update master :pre + +Now that we have changed branches, we can make our changes to our local +repository. Just remember that if you want to start working on another, +unrelated feature, you should switch branches! + +[After changes are made] After everything is done, add the files to the branch and commit them: - $ git add src/USER-MANIFOLD examples/USER/manifold/ - $ git add doc/fix_nv\{t,e\}_manifold_rattle.txt - $ git add doc/fix_manifoldforce.txt doc/user_manifolds.txt :pre + $ git add doc/src/tutorial_github.txt + $ git add doc/src/JPG/tutorial*.png :pre -After the files are added, the change should be comitted: +IMPORTANT NOTE: Do not use {git commit -a} (or {git add -A}). The -a +flag (or -A flag) will automatically include _all_ modified or new files +and that is rarely the behavior you want. It can easily lead to +accidentally adding unrelated and unwanted changes into the repository. +Instead it is preferable to explicitly use {git add}, {git rm}, {git mv} +for adding, removing, renaming individual files, respectively, and then +{git commit} to finalize the commit. Carefully check all pending +changes with {git status} before committing them. If you find doing +this on the command line too tedious, consider using a GUI, for example +the one included in git distributions written in Tk, i.e. use {git gui} +(on some Linux distributions it may be required to install an additional +package to use it). - $ git commit -m 'Added user-manifold package' :pre +After adding all files, the change set can be committed with some +useful message that explains the change. -The "-m" switch is used to add a message to the commit. Use this to -indicate what type of change was commited. - -[Wisdom by Axel] - -{"Do not use "git commit -a". the -a flag will automatically include -*all* modified or new files. mercurial does that and it find it -hugely annoying and often leading to accidental commits of files you -don't want. use git add, git rm, git mv for adding, removing, -renaming and then git commit to finalize the commit. personally, i -find it very convenient to use the bundled gui for commits, i.e. git -gui. typically, i will do git add and other operations, but then -verify and review them with git gui. git gui also allows to do -line-by-line unstaging and other convenient operations."} + $ git commit -m 'Finally updated the github tutorial' :pre After the commit, the changes can be pushed to the same branch on GitHub: $ git push :pre Git will ask you for your user name and password on GitHub if you have -not configured anything. If you correctly type your user name and -password, the change should be added to your fork on GitHub. +not configured anything. If your local branch is not present on Github yet, +it will ask you to add it by running + + $ git push --set-upstream origin github-tutorial-update :pre + +If you correctly type your user name and +password, the feature branch should be added to your fork on GitHub. If you want to make really sure you push to the right repository (which is good practice), you can provide it explicitly: @@ -140,16 +167,20 @@ or using an explicit URL: $ git push git@github.com:Pakketeretet2/lammps.git :pre -After that, you can file a new pull request based on this -branch. GitHub will now look like this: +:line -:c,image(JPG/tutorial_pull_request_feature_branch1.png) +[Filing a pull request] + +Up to this point in the tutorial, all changes were to {your} clones of +LAMMPS. Eventually, however, you want this feature to be included into +the official LAMMPS version. To do this, you will want to file a pull +request by clicking on the "New pull request" button: + +:c,image(JPG/tutorial_new_pull_request.png) Make sure that the current branch is set to the correct one, which, in -this case, is "add-user-manifold". Now click "New pull request". If -done correctly, the only changes you will see are those that were made -on this branch, so in my case, I will see nothing related to -$\mathrm{pair\_dzugatov}.$ +this case, is "github-tutorial-update". If done correctly, the only +changes you will see are those that were made on this branch. This will open up a new window that lists changes made to the repository. If you are just adding new files, there is not much to do, @@ -158,36 +189,159 @@ changes in existing files. If all changes can automatically be merged, green text at the top will say so and you can click the "Create pull request" button, see image. -:c,image(JPG/tutorial_pull_request2.png) +:c,image(JPG/tutorial_create_new_pull_request1.png) -After this you have to specify a short title and a comment with -details about your pull request. I guess here you write what your -modifications do and why they should be incorporated upstream. After -that, click the "Create pull request" button, see image below. +Before creating the pull request, make sure the short title is accurate +and add a comment with details about your pull request. Here you write +what your modifications do and why they should be incorporated upstream. -:c,image(JPG/tutorial_pull_request3.png) +Note the checkbox that says "Allow edits from maintainers". +This is checked by default checkbox (although in my version of Firefox, only the checkmark is visible): -Now just write some nice comments, click "Comment", and that is it. It -is now up to the maintainer(s) of the upstream repository to -incorporate the changes into the repository and to close the pull -request. +:c,image(JPG/tutorial_edits_maintainers.png) -:c,image(JPG/tutorial_pull_request4.png) +If it is checked, maintainers can immediately add their own edits to the +pull request. This helps the inclusion of your branch significantly, as +simple/trivial changes can be added directly to your pull request branch +by the LAMMPS maintainers. The alternative would be that they make +changes on their own version of the branch and file a reverse pull +request to you. Just leave this box checked unless you have a very good +reason not to. + +Now just write some nice comments and click on "Create pull request". + +:c,image(JPG/tutorial_create_new_pull_request2.png) :line +[After filing a pull request] + +NOTE: When you submit a pull request (or ask for a pull request) for the +first time, you will receive an invitation to become a LAMMPS project +collaborator. Please accept this invite as being a collaborator will +simplify certain administrative tasks and will probably speed up the +merging of your feature, too. + +You will notice that after filing the pull request, some checks are +performed automatically: + +:c,image(JPG/tutorial_automated_checks.png) + +If all is fine, you will see this: + +:c,image(JPG/tutorial_automated_checks_passed.png) + +If any of the checks are failing, your pull request will not be +processed, as your changes may break compilation for certain +configurations or may not merge cleanly. It is your responsibility +to remove the reason(s) for the failed test(s). If you need help +with this, please contact the LAMMPS developers by adding a comment +explaining your problems with resolving the failed tests. + +A few further interesting things (can) happen to pull requests before +they are included. + [Additional changes] -Before the pull request is accepted, any additional changes you push -into your repository will automatically become part of the pull -request. +First of all, any additional changes you push into your branch in your +repository will automatically become part of the pull request: + +:c,image(JPG/tutorial_additional_changes.png) + +This means you can add changes that should be part of the feature after +filing the pull request, which is useful in case you have forgotten +them, or if a developer has requested that something needs to be changed +before the feature can be accepted into the official LAMMPS version. +After each push, the automated checks are run again. + +[Assignees] + +There is an assignee label for pull requests. If the request has not +been reviewed by any developer yet, it is not assigned to anyone. After +revision, a developer can choose to assign it to either a) you, b) a +LAMMPS developer (including him/herself) or c) Steve Plimpton (sjplimp). + +Case a) happens if changes are required on your part :ulb,l +Case b) means that at the moment, it is being tested and reviewed by a +LAMMPS developer with the expectation that some changes would be required. +After the review, the developer can choose to implement changes directly +or suggest them to you. :l +Case c) means that the pull request has been assigned to the lead +developer Steve Plimpton and means it is considered ready for merging. :ule,l + +In this case, Axel assigned the tutorial to Steve: + +:c,image(JPG/tutorial_steve_assignee.png) + +[Edits from LAMMPS maintainers] + +If you allowed edits from maintainers (the default), any LAMMPS +maintainer can add changes to your pull request. In this case, both +Axel and Richard made changes to the tutorial: + +:c,image(JPG/tutorial_changes_others.png) + +[Reverse pull requests] + +Sometimes, however, you might not feel comfortable having other people +push changes into your own branch, or maybe the maintainers are not sure +their idea was the right one. In such a case, they can make changes, +reassign you as the assignee, and file a "reverse pull request", i.e. +file a pull request in your GitHub repository to include changes in the +branch, that you have submitted as a pull request yourself. In that +case, you can choose to merge their changes back into your branch, +possibly make additional changes or corrections and proceed from there. +It looks something like this: + +:c,image(JPG/tutorial_reverse_pull_request.png) + +For some reason, the highlighted button didn't work in my case, but I +can go to my own repository and merge the pull request from there: + +:c,image(JPG/tutorial_reverse_pull_request2.png) + +Be sure to check the changes to see if you agree with them by clicking +on the tab button: + +:c,image(JPG/tutorial_reverse_pull_request3.png) + +In this case, most of it is changes in the markup and a short rewrite of +Axel's explanation of the "git gui" and "git add" commands. + +:c,image(JPG/tutorial_reverse_pull_request4.png) + +Because the changes are OK with us, we are going to merge by clicking on +"Merge pull request". After a merge it looks like this: + +:c,image(JPG/tutorial_reverse_pull_request5.png) + +Now, since in the meantime our local text for the tutorial also changed, +we need to pull Axel's change back into our branch, and merge them: + + $ git add tutorial_github.txt + $ git add JPG/tutorial_reverse_pull_request*.png + $ git commit -m "Updated text and images on reverse pull requests" + $ git pull :pre + +In this case, the merge was painless because git could auto-merge: + +:c,image(JPG/tutorial_reverse_pull_request6.png) + +With Axel's changes merged in and some final text updates, our feature +branch is now perfect as far as we are concerned, so we are going to +commit and push again: + + $ git add tutorial_github.txt + $ git add JPG/tutorial_reverse_pull_request6.png + $ git commit -m "Merged Axel's suggestions and updated text" + $ git push git@github.com:Pakketeretet2/lammps :pre + :line [After a merge] -When everything is fine the feature branch is merged into the LAMMPS -repositories: +When everything is fine, the feature branch is merged into the master branch. :c,image(JPG/tutorial_merged.png) @@ -198,17 +352,29 @@ It is in principle safe to delete them from your own fork. This helps keep it a bit more tidy. Note that you first have to switch to another branch! -$ git checkout lammps-icms -$ git pull lammps-icms -$ git branch -d add-user-manifold :pre +$ git checkout master +$ git pull master +$ git branch -d github-tutorial-update :pre If you do not pull first, it is not really a problem but git will warn you at the next statement that you are deleting a local branch that was not yet fully merged into HEAD. This is because git does not yet -know your branch just got merged into lammps-icms upstream. If you +know your branch just got merged into LAMMPS upstream. If you first delete and then pull, everything should still be fine. Finally, if you delete the branch locally, you might want to push this to your remote(s) as well: -$ git push origin :add-user-manifold :pre +$ git push origin :github-tutorial-update :pre + +[Recent changes in the workflow] + +Some changes to the workflow are not captured in this tutorial. For +example, in addition to the master branch, to which all new features +should be submitted, there is now also an "unstable" and a "stable" +branch; these have the same content as "master", but are only updated +after a patch release or stable release was made. +Furthermore, the naming of the patches now follow the pattern +"patch_" to simplify comparisons between releases. +Finally, all patches and submissions are subject to automatic testing +and code checks to make sure they at the very least compile. diff --git a/lib/colvars/Makefile.colvars b/lib/colvars/Makefile.colvars new file mode 100644 index 0000000000..d1a2044038 --- /dev/null +++ b/lib/colvars/Makefile.colvars @@ -0,0 +1,119 @@ +# library build -*- makefile -*- for colvars module + +# which file will be copied to Makefile.lammps + +EXTRAMAKE = Makefile.lammps.empty + +# ------ SETTINGS ------ + +CXX = g++ +CXXFLAGS = -O2 -g -Wall -fPIC -funroll-loops # -DCOLVARS_DEBUG +ARCHIVE = ar +ARCHFLAG = -rscv +SHELL = /bin/sh + +# ------ DEFINITIONS ------ + +SRC = colvaratoms.cpp colvarbias_abf.cpp colvarbias_alb.cpp colvarbias.cpp \ + colvarbias_histogram.cpp colvarbias_meta.cpp colvarbias_restraint.cpp \ + colvarcomp_angles.cpp colvarcomp_coordnums.cpp colvarcomp.cpp \ + colvarcomp_distances.cpp colvarcomp_protein.cpp colvarcomp_rotations.cpp \ + colvardeps.cpp colvar.cpp colvargrid.cpp colvarmodule.cpp colvarparse.cpp \ + colvarscript.cpp colvartypes.cpp colvarvalue.cpp + +LIB = libcolvars.a +OBJ = $(SRC:.cpp=.o) +EXE = #colvars_standalone + +# ------ MAKE PROCEDURE ------ + +default: $(LIB) $(EXE) Makefile.lammps + +Makefile.lammps: + @cp $(EXTRAMAKE) Makefile.lammps + +$(LIB): $(OBJ) + $(ARCHIVE) $(ARFLAGS) $(LIB) $(OBJ) + +colvars_standalone: colvars_main.o colvarproxy_standalone.o $(LIB) + $(CXX) -o $@ $(CXXFLAGS) $^ + +# ------ MAKE FLAGS ------ + +.SUFFIXES: +.SUFFIXES: .cpp .o + +.PHONY: default clean + +# ------ COMPILE RULES ------ + +.cpp.o: + $(CXX) $(CXXFLAGS) -c $< + +# ------ DEPENDENCIES ------ +# +colvaratoms.o: colvaratoms.cpp colvarmodule.h colvartypes.h colvarproxy.h \ + colvarvalue.h colvarparse.h colvardeps.h colvaratoms.h +colvarbias_abf.o: colvarbias_abf.cpp colvarmodule.h colvartypes.h \ + colvarproxy.h colvarvalue.h colvar.h colvarparse.h colvardeps.h \ + colvarbias_abf.h colvarbias.h colvargrid.h +colvarbias_alb.o: colvarbias_alb.cpp colvarmodule.h colvartypes.h \ + colvarproxy.h colvarvalue.h colvarbias_alb.h colvar.h colvarparse.h \ + colvardeps.h colvarbias_restraint.h colvarbias.h +colvarbias.o: colvarbias.cpp colvarmodule.h colvartypes.h colvarproxy.h \ + colvarvalue.h colvarbias.h colvar.h colvarparse.h colvardeps.h +colvarbias_histogram.o: colvarbias_histogram.cpp colvarmodule.h \ + colvartypes.h colvarproxy.h colvarvalue.h colvar.h colvarparse.h \ + colvardeps.h colvarbias_histogram.h colvarbias.h colvargrid.h +colvarbias_meta.o: colvarbias_meta.cpp colvar.h colvarmodule.h \ + colvartypes.h colvarproxy.h colvarvalue.h colvarparse.h colvardeps.h \ + colvarbias_meta.h colvarbias.h colvargrid.h +colvarbias_restraint.o: colvarbias_restraint.cpp colvarmodule.h \ + colvartypes.h colvarproxy.h colvarvalue.h colvarbias_restraint.h \ + colvarbias.h colvar.h colvarparse.h colvardeps.h +colvarcomp_angles.o: colvarcomp_angles.cpp colvarmodule.h colvartypes.h \ + colvarproxy.h colvarvalue.h colvar.h colvarparse.h colvardeps.h \ + colvarcomp.h colvaratoms.h +colvarcomp_coordnums.o: colvarcomp_coordnums.cpp colvarmodule.h \ + colvartypes.h colvarproxy.h colvarvalue.h colvarparse.h colvardeps.h \ + colvaratoms.h colvar.h colvarcomp.h +colvarcomp.o: colvarcomp.cpp colvarmodule.h colvartypes.h colvarproxy.h \ + colvarvalue.h colvar.h colvarparse.h colvardeps.h colvarcomp.h \ + colvaratoms.h +colvarcomp_distances.o: colvarcomp_distances.cpp colvarmodule.h \ + colvartypes.h colvarproxy.h colvarvalue.h colvarparse.h colvardeps.h \ + colvar.h colvarcomp.h colvaratoms.h +colvarcomp_protein.o: colvarcomp_protein.cpp colvarmodule.h colvartypes.h \ + colvarproxy.h colvarvalue.h colvarparse.h colvardeps.h colvar.h \ + colvarcomp.h colvaratoms.h +colvarcomp_rotations.o: colvarcomp_rotations.cpp colvarmodule.h \ + colvartypes.h colvarproxy.h colvarvalue.h colvarparse.h colvardeps.h \ + colvar.h colvarcomp.h colvaratoms.h +colvar.o: colvar.cpp colvarmodule.h colvartypes.h colvarproxy.h \ + colvarvalue.h colvarparse.h colvardeps.h colvar.h colvarcomp.h \ + colvaratoms.h colvarscript.h colvarbias.h +colvardeps.o: colvardeps.cpp colvardeps.h colvarmodule.h colvartypes.h \ + colvarproxy.h colvarvalue.h colvarparse.h +colvargrid.o: colvargrid.cpp colvarmodule.h colvartypes.h colvarproxy.h \ + colvarvalue.h colvarparse.h colvardeps.h colvar.h colvarcomp.h \ + colvaratoms.h colvargrid.h +colvarmodule.o: colvarmodule.cpp colvarmodule.h colvartypes.h \ + colvarproxy.h colvarvalue.h colvarparse.h colvardeps.h colvar.h \ + colvarbias.h colvarbias_abf.h colvargrid.h colvarbias_alb.h \ + colvarbias_restraint.h colvarbias_histogram.h colvarbias_meta.h \ + colvarscript.h +colvarparse.o: colvarparse.cpp colvarmodule.h colvartypes.h colvarproxy.h \ + colvarvalue.h colvarparse.h +colvarscript.o: colvarscript.cpp colvarscript.h colvarmodule.h \ + colvartypes.h colvarproxy.h colvarvalue.h colvarbias.h colvar.h \ + colvarparse.h colvardeps.h +colvartypes.o: colvartypes.cpp colvarmodule.h colvartypes.h colvarproxy.h \ + colvarvalue.h colvarparse.h +colvarvalue.o: colvarvalue.cpp colvarmodule.h colvartypes.h colvarproxy.h \ + colvarvalue.h + +# ------ CLEAN ------ + +clean: + -rm *.o *~ $(LIB) + diff --git a/lib/colvars/colvar.cpp b/lib/colvars/colvar.cpp index 78aa2608cf..d60a9e90f7 100644 --- a/lib/colvars/colvar.cpp +++ b/lib/colvars/colvar.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include "colvarmodule.h" #include "colvarvalue.h" #include "colvarparse.h" @@ -163,38 +170,38 @@ colvar::colvar(std::string const &conf) } feature_states[f_cv_homogeneous]->enabled = homogeneous; } - // Colvar is deemed periodic iff: + + // Colvar is deemed periodic if: // - it is homogeneous // - all cvcs are periodic // - all cvcs have the same period - - b_periodic = cvcs[0]->b_periodic && is_enabled(f_cv_homogeneous); - period = cvcs[0]->period; - for (i = 1; i < cvcs.size(); i++) { - if (!cvcs[i]->b_periodic || cvcs[i]->period != period) { - b_periodic = false; - period = 0.0; + if (cvcs[0]->b_periodic) { // TODO make this a CVC feature + bool b_periodic = true; + period = cvcs[0]->period; + for (i = 1; i < cvcs.size(); i++) { + if (!cvcs[i]->b_periodic || cvcs[i]->period != period) { + b_periodic = false; + period = 0.0; + cvm::log("Warning: although one component is periodic, this colvar will " + "not be treated as periodic, either because the exponent is not " + "1, or because components of different periodicity are defined. " + "Make sure that you know what you are doing!"); + } } + feature_states[f_cv_periodic]->enabled = b_periodic; } - feature_states[f_cv_periodic]->enabled = b_periodic; // check that cvcs are compatible for (i = 0; i < cvcs.size(); i++) { - if ((cvcs[i])->b_periodic && !b_periodic) { - cvm::log("Warning: although this component is periodic, the colvar will " - "not be treated as periodic, either because the exponent is not " - "1, or because multiple components are present. Make sure that " - "you know what you are doing!"); - } // components may have different types only for scripted functions if (!is_enabled(f_cv_scripted) && (colvarvalue::check_types(cvcs[i]->value(), - cvcs[0]->value())) ) { + cvcs[0]->value())) ) { cvm::error("ERROR: you are definining this collective variable " "by using components of different types. " "You must use the same type in order to " - " sum them together.\n", INPUT_ERROR); + "sum them together.\n", INPUT_ERROR); return; } } @@ -207,16 +214,15 @@ colvar::colvar(std::string const &conf) // at this point, the colvar's type is defined f.type(value()); f_accumulated.type(value()); - fb.type(value()); + + reset_bias_force(); get_keyval(conf, "width", width, 1.0); if (width <= 0.0) { cvm::error("Error: \"width\" must be positive.\n", INPUT_ERROR); + return; } - // NOTE: not porting wall stuff to new deps, as this will change to a separate bias - // the grid functions will wait a little as well - lower_boundary.type(value()); lower_wall.type(value()); @@ -308,6 +314,9 @@ colvar::colvar(std::string const &conf) enable(f_cv_extended_Lagrangian); provide(f_cv_Langevin); + // The extended mass will apply forces + enable(f_cv_gradient); + xr.type(value()); vr.type(value()); fr.type(value()); @@ -400,6 +409,9 @@ colvar::colvar(std::string const &conf) f_old.type(value()); f_old.reset(); + x_restart.type(value()); + after_restart = false; + if (cvm::b_analysis) parse_analysis(conf); @@ -761,9 +773,13 @@ int colvar::calc_cvcs(int first_cvc, size_t num_cvcs) return error_code; } + if (cvm::step_relative() > 0) { + // Total force depends on Jacobian derivative from previous timestep + error_code |= calc_cvc_total_force(first_cvc, num_cvcs); + } + // atom coordinates are updated by the next line error_code |= calc_cvc_values(first_cvc, num_cvcs); error_code |= calc_cvc_gradients(first_cvc, num_cvcs); - error_code |= calc_cvc_total_force(first_cvc, num_cvcs); error_code |= calc_cvc_Jacobians(first_cvc, num_cvcs); if (cvm::debug()) @@ -780,9 +796,12 @@ int colvar::collect_cvc_data() int error_code = COLVARS_OK; + if (cvm::step_relative() > 0) { + // Total force depends on Jacobian derivative from previous timestep + error_code |= collect_cvc_total_forces(); + } error_code |= collect_cvc_values(); error_code |= collect_cvc_gradients(); - error_code |= collect_cvc_total_forces(); error_code |= collect_cvc_Jacobians(); error_code |= calc_colvar_properties(); @@ -872,6 +891,22 @@ int colvar::collect_cvc_values() cvm::log("Colvar \""+this->name+"\" has value "+ cvm::to_str(x, cvm::cv_width, cvm::cv_prec)+".\n"); + if (after_restart) { + after_restart = false; + if (cvm::proxy->simulation_running()) { + cvm::real const jump2 = dist2(x, x_restart) / (width*width); + if (jump2 > 0.25) { + cvm::error("Error: the calculated value of colvar \""+name+ + "\":\n"+cvm::to_str(x)+"\n differs greatly from the value " + "last read from the state file:\n"+cvm::to_str(x_restart)+ + "\nPossible causes are changes in configuration, " + "wrong state file, or how PBC wrapping is handled.\n", + INPUT_ERROR); + return INPUT_ERROR; + } + } + } + return COLVARS_OK; } @@ -979,22 +1014,17 @@ int colvar::calc_cvc_total_force(int first_cvc, size_t num_cvcs) if (cvm::debug()) cvm::log("Calculating total force of colvar \""+this->name+"\".\n"); - // if (!tasks[task_extended_lagrangian] && (cvm::step_relative() > 0)) { - // Disabled check to allow for explicit total force calculation - // even with extended Lagrangian + cvm::increase_depth(); - if (cvm::step_relative() > 0) { - cvm::increase_depth(); - // get from the cvcs the total forces from the PREVIOUS step - for (i = first_cvc, cvc_count = 0; - (i < cvcs.size()) && (cvc_count < cvc_max_count); - i++) { - if (!cvcs[i]->is_enabled()) continue; - cvc_count++; - (cvcs[i])->calc_force_invgrads(); - } - cvm::decrease_depth(); + for (i = first_cvc, cvc_count = 0; + (i < cvcs.size()) && (cvc_count < cvc_max_count); + i++) { + if (!cvcs[i]->is_enabled()) continue; + cvc_count++; + (cvcs[i])->calc_force_invgrads(); } + cvm::decrease_depth(); + if (cvm::debug()) cvm::log("Done calculating total force of colvar \""+this->name+"\".\n"); @@ -1013,6 +1043,11 @@ int colvar::collect_cvc_total_forces() // get from the cvcs the total forces from the PREVIOUS step for (size_t i = 0; i < cvcs.size(); i++) { if (!cvcs[i]->is_enabled()) continue; + if (cvm::debug()) + cvm::log("Colvar component no. "+cvm::to_str(i+1)+ + " within colvar \""+this->name+"\" has total force "+ + cvm::to_str((cvcs[i])->total_force(), + cvm::cv_width, cvm::cv_prec)+".\n"); // linear combination is assumed ft += (cvcs[i])->total_force() * (cvcs[i])->sup_coeff / active_cvc_square_norm; } @@ -1056,6 +1091,11 @@ int colvar::collect_cvc_Jacobians() fj.reset(); for (size_t i = 0; i < cvcs.size(); i++) { if (!cvcs[i]->is_enabled()) continue; + if (cvm::debug()) + cvm::log("Colvar component no. "+cvm::to_str(i+1)+ + " within colvar \""+this->name+"\" has Jacobian derivative"+ + cvm::to_str((cvcs[i])->Jacobian_derivative(), + cvm::cv_width, cvm::cv_prec)+".\n"); // linear combination is assumed fj += (cvcs[i])->Jacobian_derivative() * (cvcs[i])->sup_coeff / active_cvc_square_norm; } @@ -1085,7 +1125,7 @@ int colvar::calc_colvar_properties() // TODO: put it in the restart information if (cvm::step_relative() == 0) { xr = x; - vr = 0.0; // (already 0; added for clarity) + vr.reset(); // (already 0; added for clarity) } // report the restraint center as "value" @@ -1128,15 +1168,16 @@ cvm::real colvar::update_forces_energy() if (is_enabled(f_cv_Jacobian)) { // the instantaneous Jacobian force was not included in the reported total force; // instead, it is subtracted from the applied force (silent Jacobian correction) + // This requires the Jacobian term for the *current* timestep if (is_enabled(f_cv_hide_Jacobian)) f -= fj; } - if (is_enabled(f_cv_lower_wall) || is_enabled(f_cv_upper_wall)) { + // Wall force + colvarvalue fw(x); + fw.reset(); - // Wall force - colvarvalue fw(x); - fw.reset(); + if (is_enabled(f_cv_lower_wall) || is_enabled(f_cv_upper_wall)) { if (cvm::debug()) cvm::log("Calculating wall forces for colvar \""+this->name+"\".\n"); @@ -1144,12 +1185,11 @@ cvm::real colvar::update_forces_energy() // For a periodic colvar, both walls may be applicable at the same time // in which case we pick the closer one if ( (!is_enabled(f_cv_upper_wall)) || - (this->dist2(x_reported, lower_wall) < this->dist2(x_reported, upper_wall)) ) { + (this->dist2(x, lower_wall) < this->dist2(x, upper_wall)) ) { - cvm::real const grad = this->dist2_lgrad(x_reported, lower_wall); + cvm::real const grad = this->dist2_lgrad(x, lower_wall); if (grad < 0.0) { fw = -0.5 * lower_wall_k * grad; - f += fw; if (cvm::debug()) cvm::log("Applying a lower wall force("+ cvm::to_str(fw)+") to \""+this->name+"\".\n"); @@ -1157,10 +1197,9 @@ cvm::real colvar::update_forces_energy() } else { - cvm::real const grad = this->dist2_lgrad(x_reported, upper_wall); + cvm::real const grad = this->dist2_lgrad(x, upper_wall); if (grad > 0.0) { fw = -0.5 * upper_wall_k * grad; - f += fw; if (cvm::debug()) cvm::log("Applying an upper wall force("+ cvm::to_str(fw)+") to \""+this->name+"\".\n"); @@ -1168,17 +1207,26 @@ cvm::real colvar::update_forces_energy() } } + // At this point f is the force f from external biases that will be applied to the + // extended variable if there is one + if (is_enabled(f_cv_extended_Lagrangian)) { + if (cvm::debug()) { + cvm::log("Updating extended-Lagrangian degrees of freedom.\n"); + } + cvm::real dt = cvm::dt(); - cvm::real f_ext; + colvarvalue f_ext(fr.type()); + f_ext.reset(); // the total force is applied to the fictitious mass, while the - // atoms only feel the harmonic force + // atoms only feel the harmonic force + wall force // fr: bias force on extended variable (without harmonic spring), for output in trajectory // f_ext: total force on extended variable (including harmonic spring) - // f: - initially, external biasing force (including wall forces) - // - after this code block, colvar force to be applied to atomic coordinates, ie. spring force + // f: - initially, external biasing force + // - after this code block, colvar force to be applied to atomic coordinates + // ie. spring force + wall force fr = f; f_ext = f + (-0.5 * ext_force_k) * this->dist2_lgrad(xr, x); f = (-0.5 * ext_force_k) * this->dist2_rgrad(xr, x); @@ -1200,15 +1248,24 @@ cvm::real colvar::update_forces_energy() potential_energy = 0.5 * ext_force_k * this->dist2(xr, x); // leap to v_(i+1/2) if (is_enabled(f_cv_Langevin)) { - vr -= dt * ext_gamma * vr.real_value; - vr += dt * ext_sigma * cvm::rand_gaussian() / ext_mass; + vr -= dt * ext_gamma * vr; + colvarvalue rnd(x); + rnd.set_random(); + vr += dt * ext_sigma * rnd / ext_mass; } vr += (0.5 * dt) * f_ext / ext_mass; xr += dt * vr; xr.apply_constraints(); - if (this->b_periodic) this->wrap(xr); + if (this->is_enabled(f_cv_periodic)) this->wrap(xr); } + // TODO remove the wall force + f += fw; + // Now adding the force on the actual colvar (for those biases who + // bypass the extended Lagrangian mass) + f += fb_actual; + + // Store force to be applied, possibly summed over several timesteps f_accumulated += f; if (is_enabled(f_cv_fdiff_velocity)) { @@ -1425,14 +1482,15 @@ std::istream & colvar::read_restart(std::istream &is) } } - if ( !(get_keyval(conf, "x", x, - colvarvalue(x.type()), colvarparse::parse_silent)) ) { + if ( !(get_keyval(conf, "x", x, x, colvarparse::parse_silent)) ) { cvm::log("Error: restart file does not contain " "the value of the colvar \""+ name+"\" .\n"); } else { cvm::log("Restarting collective variable \""+name+"\" from value: "+ cvm::to_str(x)+"\n"); + x_restart = x; + after_restart = true; } if (is_enabled(f_cv_extended_Lagrangian)) { diff --git a/lib/colvars/colvar.h b/lib/colvars/colvar.h index d7b1e6076f..2cf3d2dac5 100644 --- a/lib/colvars/colvar.h +++ b/lib/colvars/colvar.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVAR_H #define COLVAR_H @@ -170,6 +177,9 @@ public: /// the biases are updated colvarvalue fb; + /// \brief Bias force to the actual value (only useful with extended Lagrangian) + colvarvalue fb_actual; + /// \brief Total \em applied force; fr (if extended_lagrangian /// is defined), fb (if biases are applied) and the walls' forces /// (if defined) contribute to it @@ -183,13 +193,9 @@ public: colvarvalue ft; - /// Period, if it is a constant + /// Period, if this variable is periodic cvm::real period; - /// \brief Same as above, but also takes into account components - /// with a variable period, such as distanceZ - bool b_periodic; - /// \brief Expand the boundaries of multiples of width, to keep the /// value always within range @@ -290,6 +296,9 @@ public: /// Add to the total force from biases void add_bias_force(colvarvalue const &force); + /// Apply a force to the actual value (only meaningful with extended Lagrangian) + void add_bias_force_actual_value(colvarvalue const &force); + /// \brief Collect all forces on this colvar, integrate internal /// equations of motion of internal degrees of freedom; see also /// colvar::communicate_forces() @@ -386,6 +395,12 @@ protected: /// Previous value (to calculate velocities during analysis) colvarvalue x_old; + /// Value read from the most recent state file (if any) + colvarvalue x_restart; + + /// True if a state file was just read + bool after_restart; + /// Time series of values and velocities used in correlation /// functions std::list< std::list > acf_x_history, acf_v_history; @@ -577,9 +592,20 @@ inline void colvar::add_bias_force(colvarvalue const &force) } +inline void colvar::add_bias_force_actual_value(colvarvalue const &force) +{ + if (cvm::debug()) { + cvm::log("Adding biasing force "+cvm::to_str(force)+" to colvar \""+name+"\".\n"); + } + fb_actual += force; +} + + inline void colvar::reset_bias_force() { fb.type(value()); fb.reset(); + fb_actual.type(value()); + fb_actual.reset(); } #endif diff --git a/lib/colvars/colvaratoms.cpp b/lib/colvars/colvaratoms.cpp index e8046a97d5..48c16e887a 100644 --- a/lib/colvars/colvaratoms.cpp +++ b/lib/colvars/colvaratoms.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include "colvarmodule.h" #include "colvarparse.h" #include "colvaratoms.h" @@ -171,7 +178,10 @@ int cvm::atom_group::remove_atom(cvm::atom_iter ai) int cvm::atom_group::init() { - if (!key.size()) key = "atoms"; + if (!key.size()) key = "unnamed"; + description = "atom group " + key; + // These will be overwritten by parse(), if initializing from a config string + atoms.clear(); // TODO: check with proxy whether atom forces etc are available @@ -179,6 +189,7 @@ int cvm::atom_group::init() index = -1; + b_dummy = false; b_center = false; b_rotate = false; b_user_defined_fit = false; @@ -440,6 +451,7 @@ int cvm::atom_group::parse(std::string const &conf) if (b_print_atom_ids) { cvm::log("Internal definition of the atom group:\n"); + cvm::log(print_atom_ids()); } cvm::decrease_depth(); diff --git a/lib/colvars/colvaratoms.h b/lib/colvars/colvaratoms.h index a2a771a8a3..85f6212951 100644 --- a/lib/colvars/colvaratoms.h +++ b/lib/colvars/colvaratoms.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARATOMS_H #define COLVARATOMS_H @@ -64,7 +71,7 @@ public: /// \brief Initialize an atom for collective variable calculation /// and get its internal identifier \param atom_number Atom index in - /// the system topology (starting from 1) + /// the system topology (1-based) atom(int atom_number); /// \brief Initialize an atom for collective variable calculation @@ -453,6 +460,8 @@ public: /// are not used, either because they were not defined (e.g because /// the colvar has not a scalar value) or the biases require to /// micromanage the force. + /// This function will be phased out eventually, in favor of + /// apply_colvar_force() once that is implemented for non-scalar values void apply_force(cvm::rvector const &force); }; diff --git a/lib/colvars/colvarbias.cpp b/lib/colvars/colvarbias.cpp index 76d8489de9..fdd2b6254c 100644 --- a/lib/colvars/colvarbias.cpp +++ b/lib/colvars/colvarbias.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include "colvarmodule.h" #include "colvarvalue.h" #include "colvarbias.h" @@ -29,6 +36,7 @@ colvarbias::colvarbias(char const *key) has_data = false; b_output_energy = false; reset(); + state_file_step = 0; // Start in active state by default enable(f_cvb_active); @@ -141,20 +149,25 @@ int colvarbias::clear() int colvarbias::add_colvar(std::string const &cv_name) { if (colvar *cv = cvm::colvar_by_name(cv_name)) { - // Removed this as nor all biases apply forces eg histogram - // cv->enable(colvar::task_gradients); + if (cvm::debug()) { cvm::log("Applying this bias to collective variable \""+ cv->name+"\".\n"); } + colvars.push_back(cv); colvar_forces.push_back(colvarvalue()); colvar_forces.back().type(cv->value()); // make sure each force is initialized to zero + colvar_forces.back().is_derivative(); // colvar constraints are not applied to the force colvar_forces.back().reset(); cv->biases.push_back(this); // add back-reference to this bias to colvar + if (is_enabled(f_cvb_apply_force)) { + cv->enable(f_cv_gradient); + } + // Add dependency link. // All biases need at least the value of each colvar // although possibly not at all timesteps @@ -165,6 +178,7 @@ int colvarbias::add_colvar(std::string const &cv_name) cv_name+"\".\n", INPUT_ERROR); return INPUT_ERROR; } + return COLVARS_OK; } @@ -190,16 +204,19 @@ void colvarbias::communicate_forces() } -void colvarbias::change_configuration(std::string const &conf) +int colvarbias::change_configuration(std::string const &conf) { - cvm::error("Error: change_configuration() not implemented.\n"); + cvm::error("Error: change_configuration() not implemented.\n", + COLVARS_NOT_IMPLEMENTED); + return COLVARS_NOT_IMPLEMENTED; } cvm::real colvarbias::energy_difference(std::string const &conf) { - cvm::error("Error: energy_difference() not implemented.\n"); - return 0.; + cvm::error("Error: energy_difference() not implemented.\n", + COLVARS_NOT_IMPLEMENTED); + return 0.0; } @@ -225,6 +242,118 @@ int colvarbias::replica_share() return COLVARS_NOT_IMPLEMENTED; } + +std::string const colvarbias::get_state_params() const +{ + std::ostringstream os; + os << "step " << cvm::step_absolute() << "\n" + << "name " << this->name << "\n"; + return os.str(); +} + + +int colvarbias::set_state_params(std::string const &conf) +{ + std::string new_name = ""; + if (colvarparse::get_keyval(conf, "name", new_name, + std::string(""), colvarparse::parse_silent) && + (new_name != this->name)) { + cvm::error("Error: in the state file, the " + "\""+bias_type+"\" block has a different name, \""+new_name+ + "\": different system?\n", INPUT_ERROR); + } + + if (name.size() == 0) { + cvm::error("Error: \""+bias_type+"\" block within the restart file " + "has no identifiers.\n", INPUT_ERROR); + } + + colvarparse::get_keyval(conf, "step", state_file_step, + cvm::step_absolute(), colvarparse::parse_silent); + + return COLVARS_OK; +} + + +std::ostream & colvarbias::write_state(std::ostream &os) +{ + if (cvm::debug()) { + cvm::log("Writing state file for bias \""+name+"\"\n"); + } + os.setf(std::ios::scientific, std::ios::floatfield); + os.precision(cvm::cv_prec); + os << bias_type << " {\n" + << " configuration {\n"; + std::istringstream is(get_state_params()); + std::string line; + while (std::getline(is, line)) { + os << " " << line << "\n"; + } + os << " }\n"; + write_state_data(os); + os << "}\n\n"; + return os; +} + + +std::istream & colvarbias::read_state(std::istream &is) +{ + size_t const start_pos = is.tellg(); + + std::string key, brace, conf; + if ( !(is >> key) || !(key == bias_type) || + !(is >> brace) || !(brace == "{") || + !(is >> colvarparse::read_block("configuration", conf)) || + (set_state_params(conf) != COLVARS_OK) ) { + cvm::error("Error: in reading state configuration for \""+bias_type+"\" bias \""+ + this->name+"\" at position "+ + cvm::to_str(is.tellg())+" in stream.\n", INPUT_ERROR); + is.clear(); + is.seekg(start_pos, std::ios::beg); + is.setstate(std::ios::failbit); + return is; + } + + if (!read_state_data(is)) { + cvm::error("Error: in reading state data for \""+bias_type+"\" bias \""+ + this->name+"\" at position "+ + cvm::to_str(is.tellg())+" in stream.\n", INPUT_ERROR); + is.clear(); + is.seekg(start_pos, std::ios::beg); + is.setstate(std::ios::failbit); + } + + is >> brace; + if (brace != "}") { + cvm::error("Error: corrupt restart information for \""+bias_type+"\" bias \""+ + this->name+"\": no matching brace at position "+ + cvm::to_str(is.tellg())+" in stream.\n"); + is.setstate(std::ios::failbit); + } + + return is; +} + + +std::istream & colvarbias::read_state_data_key(std::istream &is, char const *key) +{ + size_t const start_pos = is.tellg(); + std::string key_in; + if ( !(is >> key_in) || + !(key_in == to_lower_cppstr(std::string(key))) ) { + cvm::error("Error: in reading restart configuration for "+ + bias_type+" bias \""+this->name+"\" at position "+ + cvm::to_str(is.tellg())+" in stream.\n", INPUT_ERROR); + is.clear(); + is.seekg(start_pos, std::ios::beg); + is.setstate(std::ios::failbit); + return is; + } + return is; +} + + + std::ostream & colvarbias::write_traj_label(std::ostream &os) { os << " "; diff --git a/lib/colvars/colvarbias.h b/lib/colvars/colvarbias.h index 8238f58f40..12397dcb8f 100644 --- a/lib/colvars/colvarbias.h +++ b/lib/colvars/colvarbias.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARBIAS_H #define COLVARBIAS_H @@ -9,7 +16,8 @@ /// \brief Collective variable bias, base class -class colvarbias : public colvarparse, public colvardeps { +class colvarbias + : public virtual colvarparse, public virtual colvardeps { public: /// Name of this bias @@ -24,6 +32,12 @@ public: /// Add a new collective variable to this bias int add_colvar(std::string const &cv_name); + /// Add a new collective variable to this bias + size_t number_of_colvars() const + { + return colvars.size(); + } + /// Retrieve colvar values and calculate their biasing forces /// Return bias energy virtual int update(); @@ -31,7 +45,7 @@ public: // TODO: move update_bias here (share with metadynamics) /// Load new configuration - force constant and/or centers only - virtual void change_configuration(std::string const &conf); + virtual int change_configuration(std::string const &conf); /// Calculate change in energy from using alternate configuration virtual cvm::real energy_difference(std::string const &conf); @@ -49,7 +63,7 @@ public: virtual void analyze() {} /// Send forces to the collective variables - void communicate_forces(); + virtual void communicate_forces(); /// \brief Constructor colvarbias(char const *key); @@ -60,13 +74,11 @@ public: /// \brief Set to zero all mutable data virtual int reset(); -protected: +private: /// Default constructor colvarbias(); -private: - /// Copy constructor colvarbias(colvarbias &); @@ -78,28 +90,59 @@ public: /// Destructor virtual ~colvarbias(); - /// Read the bias configuration from a restart file - virtual std::istream & read_restart(std::istream &is) = 0; + /// Write the values of specific mutable properties to a string + virtual std::string const get_state_params() const; - /// Write the bias configuration to a restart file - virtual std::ostream & write_restart(std::ostream &os) = 0; + /// Read the values of specific mutable properties from a string + virtual int set_state_params(std::string const &state_conf); + + /// Write all mutable data not already written by get_state_params() + virtual std::ostream & write_state_data(std::ostream &os) + { + return os; + } + + /// Read all mutable data not already set by set_state_params() + virtual std::istream & read_state_data(std::istream &is) + { + return is; + } + + /// Read a keyword from the state data (typically a header) + std::istream & read_state_data_key(std::istream &is, char const *key); + + /// Write the bias configuration to a restart file or other stream + virtual std::ostream & write_state(std::ostream &os); + + /// Read the bias configuration from a restart file or other stream + virtual std::istream & read_state(std::istream &is); /// Write a label to the trajectory file (comment line) virtual std::ostream & write_traj_label(std::ostream &os); - /// (Re)initialize the output files (does not write them yet) - virtual int setup_output() { return COLVARS_OK; } - /// Output quantities such as the bias energy to the trajectory file virtual std::ostream & write_traj(std::ostream &os); - /// Write output files (if defined, e.g. in analysis mode) + /// (Re)initialize the output files (does not write them yet) + virtual int setup_output() + { + return COLVARS_OK; + } + + /// Write any output files that this bias may have (e.g. PMF files) virtual int write_output_files() { return COLVARS_OK; } - inline cvm::real get_energy() { + /// If this bias is communicating with other replicas through files, send it to them + virtual int write_state_to_replicas() + { + return COLVARS_OK; + } + + inline cvm::real get_energy() + { return bias_energy; } @@ -107,9 +150,11 @@ public: static std::vector cvb_features; /// \brief Implementation of the feature list accessor for colvarbias - virtual std::vector &features() { + virtual std::vector &features() + { return cvb_features; } + protected: /// \brief Pointers to collective variables to which the bias is @@ -130,6 +175,9 @@ protected: /// (for history-dependent biases) bool has_data; + /// \brief Step number read from the last state file + size_t state_file_step; + }; #endif diff --git a/lib/colvars/colvarbias_abf.cpp b/lib/colvars/colvarbias_abf.cpp index 1665ea61a9..ccfa401697 100644 --- a/lib/colvars/colvarbias_abf.cpp +++ b/lib/colvars/colvarbias_abf.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include "colvarmodule.h" #include "colvar.h" #include "colvarbias_abf.h" @@ -23,6 +30,8 @@ int colvarbias_abf::init(std::string const &conf) { colvarbias::init(conf); + provide(f_cvb_scalar_variables); + enable(f_cvb_scalar_variables); provide(f_cvb_history_dependent); // TODO relax this in case of VMD plugin @@ -590,16 +599,10 @@ void colvarbias_abf::read_gradients_samples() } -std::ostream & colvarbias_abf::write_restart(std::ostream& os) +std::ostream & colvarbias_abf::write_state_data(std::ostream& os) { - std::ios::fmtflags flags(os.flags()); - os << "abf {\n" - << " configuration {\n" - << " name " << this->name << "\n"; - os << " }\n"; - os.setf(std::ios::fmtflags(0), std::ios::floatfield); // default floating-point format os << "\nsamples\n"; samples->write_raw(os, 8); @@ -617,117 +620,47 @@ std::ostream & colvarbias_abf::write_restart(std::ostream& os) z_gradients->write_raw(os, 8); } - os << "}\n\n"; - os.flags(flags); return os; } -std::istream & colvarbias_abf::read_restart(std::istream& is) +std::istream & colvarbias_abf::read_state_data(std::istream& is) { if ( input_prefix.size() > 0 ) { cvm::error("ERROR: cannot provide both inputPrefix and a colvars state file.\n", INPUT_ERROR); } - size_t const start_pos = is.tellg(); - - cvm::log("Restarting ABF bias \""+ - this->name+"\".\n"); - std::string key, brace, conf; - - if ( !(is >> key) || !(key == "abf") || - !(is >> brace) || !(brace == "{") || - !(is >> colvarparse::read_block("configuration", conf)) ) { - cvm::log("Error: in reading restart configuration for ABF bias \""+ - this->name+"\" at position "+ - cvm::to_str(is.tellg())+" in stream.\n"); - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); - return is; - } - - std::string name = ""; - if ( (colvarparse::get_keyval(conf, "name", name, std::string(""), colvarparse::parse_silent)) && - (name != this->name) ) - cvm::error("Error: in the restart file, the " - "\"abf\" block has wrong name(" + name + ")\n"); - if ( name == "" ) { - cvm::error("Error: \"abf\" block in the restart file has no name.\n"); - } - - if ( !(is >> key) || !(key == "samples")) { - cvm::log("Error: in reading restart configuration for ABF bias \""+ - this->name+"\" at position "+ - cvm::to_str(is.tellg())+" in stream.\n"); - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); + if (! read_state_data_key(is, "samples")) { return is; } if (! samples->read_raw(is)) { - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); return is; } - if ( !(is >> key) || !(key == "gradient")) { - cvm::log("Error: in reading restart configuration for ABF bias \""+ - this->name+"\" at position "+ - cvm::to_str(is.tellg())+" in stream.\n"); - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); + if (! read_state_data_key(is, "gradient")) { return is; } if (! gradients->read_raw(is)) { - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); return is; } if (z_gradients) { - if ( !(is >> key) || !(key == "z_samples")) { - cvm::log("Error: in reading restart configuration for ABF bias \""+ - this->name+"\" at position "+ - cvm::to_str(is.tellg())+" in stream.\n"); - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); + + if (! read_state_data_key(is, "z_samples")) { return is; } if (! z_samples->read_raw(is)) { - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); return is; } - if ( !(is >> key) || !(key == "z_gradient")) { - cvm::log("Error: in reading restart configuration for ABF bias \""+ - this->name+"\" at position "+ - cvm::to_str(is.tellg())+" in stream.\n"); - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); + if (! read_state_data_key(is, "z_gradient")) { return is; } if (! z_gradients->read_raw(is)) { - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); return is; } } - is >> brace; - if (brace != "}") { - cvm::error("Error: corrupt restart information for ABF bias \""+ - this->name+"\": no matching brace at position "+ - cvm::to_str(is.tellg())+" in the restart file.\n"); - is.setstate(std::ios::failbit); - } + return is; } diff --git a/lib/colvars/colvarbias_abf.h b/lib/colvars/colvarbias_abf.h index ee76240968..41a5475fa7 100644 --- a/lib/colvars/colvarbias_abf.h +++ b/lib/colvars/colvarbias_abf.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARBIAS_ABF_H #define COLVARBIAS_ABF_H @@ -107,8 +114,8 @@ private: /// Read human-readable FE gradients and sample count (if not using restart) void read_gradients_samples(); - std::istream& read_restart(std::istream&); - std::ostream& write_restart(std::ostream&); + std::istream& read_state_data(std::istream&); + std::ostream& write_state_data(std::ostream&); }; #endif diff --git a/lib/colvars/colvarbias_alb.cpp b/lib/colvars/colvarbias_alb.cpp index 8c8956082e..9e414d4db4 100644 --- a/lib/colvars/colvarbias_alb.cpp +++ b/lib/colvars/colvarbias_alb.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include #include @@ -33,6 +40,9 @@ int colvarbias_alb::init(std::string const &conf) { colvarbias::init(conf); + provide(f_cvb_scalar_variables); + enable(f_cvb_scalar_variables); + provide(f_cvb_history_dependent); size_t i; @@ -239,37 +249,8 @@ int colvarbias_alb::update() } -std::istream & colvarbias_alb::read_restart(std::istream &is) +int colvarbias_alb::set_state_params(std::string const &conf) { - size_t const start_pos = is.tellg(); - - cvm::log("Restarting adaptive linear bias \""+ - this->name+"\".\n"); - - std::string key, brace, conf; - if ( !(is >> key) || !(key == "ALB") || - !(is >> brace) || !(brace == "{") || - !(is >> colvarparse::read_block("configuration", conf)) ) { - - cvm::log("Error: in reading restart configuration for restraint bias \""+ - this->name+"\" at position "+ - cvm::to_str(is.tellg())+" in stream.\n"); - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); - return is; - } - - std::string name = ""; - if ( (colvarparse::get_keyval(conf, "name", name, std::string(""), colvarparse::parse_silent)) && - (name != this->name) ) - cvm::fatal_error("Error: in the restart file, the " - "\"ALB\" block has a wrong name\n"); - if (name.size() == 0) { - cvm::fatal_error("Error: \"ALB\" block in the restart file " - "has no identifiers.\n"); - } - if (!get_keyval(conf, "setCoupling", set_coupling)) cvm::fatal_error("Error: current setCoupling is missing from the restart.\n"); @@ -299,23 +280,13 @@ std::istream & colvarbias_alb::read_restart(std::istream &is) if (!get_keyval(conf, "b_equilibration", b_equilibration)) cvm::fatal_error("Error: current updateCalls is missing from the restart.\n"); - is >> brace; - if (brace != "}") { - cvm::fatal_error("Error: corrupt restart information for adaptive linear bias \""+ - this->name+"\": no matching brace at position "+ - cvm::to_str(is.tellg())+" in the restart file.\n"); - is.setstate(std::ios::failbit); - } - - return is; + return COLVARS_OK; } -std::ostream & colvarbias_alb::write_restart(std::ostream &os) +std::string const colvarbias_alb::get_state_params() const { - os << "ALB {\n" - << " configuration {\n" - << " name " << this->name << "\n"; + std::ostringstream os; os << " setCoupling "; size_t i; for (i = 0; i < colvars.size(); i++) { @@ -358,10 +329,7 @@ std::ostream & colvarbias_alb::write_restart(std::ostream &os) else os << " b_equilibration no\n"; - os << " }\n" - << "}\n\n"; - - return os; + return os.str(); } diff --git a/lib/colvars/colvarbias_alb.h b/lib/colvars/colvarbias_alb.h index a3c6133db2..d003c244e9 100644 --- a/lib/colvars/colvarbias_alb.h +++ b/lib/colvars/colvarbias_alb.h @@ -1,10 +1,18 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARBIAS_ALB_H #define COLVARBIAS_ALB_H #include "colvar.h" -#include "colvarbias_restraint.h" +#include "colvarbias.h" + class colvarbias_alb : public colvarbias { @@ -15,8 +23,8 @@ public: virtual int init(std::string const &conf); virtual int update(); - virtual std::istream & read_restart(std::istream &is); - virtual std::ostream & write_restart(std::ostream &os); + virtual std::string const get_state_params() const; + virtual int set_state_params(std::string const &conf); virtual std::ostream & write_traj_label(std::ostream &os); virtual std::ostream & write_traj(std::ostream &os); diff --git a/lib/colvars/colvarbias_histogram.cpp b/lib/colvars/colvarbias_histogram.cpp index eef4b506e3..900ad213d5 100644 --- a/lib/colvars/colvarbias_histogram.cpp +++ b/lib/colvars/colvarbias_histogram.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include "colvarmodule.h" #include "colvar.h" #include "colvarbias_histogram.h" @@ -17,6 +24,9 @@ int colvarbias_histogram::init(std::string const &conf) { colvarbias::init(conf); + provide(f_cvb_scalar_variables); + enable(f_cvb_scalar_variables); + provide(f_cvb_history_dependent); enable(f_cvb_history_dependent); @@ -196,78 +206,25 @@ int colvarbias_histogram::write_output_files() } -std::istream & colvarbias_histogram::read_restart(std::istream& is) +std::istream & colvarbias_histogram::read_state_data(std::istream& is) { - size_t const start_pos = is.tellg(); - - cvm::log("Restarting collective variable histogram \""+ - this->name+"\".\n"); - std::string key, brace, conf; - - if ( !(is >> key) || !(key == "histogram") || - !(is >> brace) || !(brace == "{") || - !(is >> colvarparse::read_block("configuration", conf)) ) { - cvm::log("Error: in reading restart configuration for histogram \""+ - this->name+"\" at position "+ - cvm::to_str(is.tellg())+" in stream.\n"); - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); - return is; - } - - int id = -1; - std::string name = ""; - if ( (colvarparse::get_keyval(conf, "name", name, std::string(""), colvarparse::parse_silent)) && - (name != this->name) ) - cvm::error("Error: in the restart file, the " - "\"histogram\" block has a wrong name: different system?\n"); - if ( (id == -1) && (name == "") ) { - cvm::error("Error: \"histogram\" block in the restart file " - "has no name.\n"); - } - - if ( !(is >> key) || !(key == "grid")) { - cvm::error("Error: in reading restart configuration for histogram \""+ - this->name+"\" at position "+ - cvm::to_str(is.tellg())+" in stream.\n"); - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); + if (! read_state_data_key(is, "grid")) { return is; } if (! grid->read_raw(is)) { - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); return is; } - is >> brace; - if (brace != "}") { - cvm::error("Error: corrupt restart information for ABF bias \""+ - this->name+"\": no matching brace at position "+ - cvm::to_str(is.tellg())+" in the restart file.\n"); - is.setstate(std::ios::failbit); - } return is; } -std::ostream & colvarbias_histogram::write_restart(std::ostream& os) + +std::ostream & colvarbias_histogram::write_state_data(std::ostream& os) { std::ios::fmtflags flags(os.flags()); os.setf(std::ios::fmtflags(0), std::ios::floatfield); - - os << "histogram {\n" - << " configuration {\n" - << " name " << this->name << "\n"; - os << " }\n"; - os << "grid\n"; grid->write_raw(os, 8); - - os << "}\n\n"; - os.flags(flags); return os; } diff --git a/lib/colvars/colvarbias_histogram.h b/lib/colvars/colvarbias_histogram.h index cca49b9901..b9c1b49950 100644 --- a/lib/colvars/colvarbias_histogram.h +++ b/lib/colvars/colvarbias_histogram.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARBIAS_HISTOGRAM_H #define COLVARBIAS_HISTOGRAM_H @@ -35,8 +42,8 @@ protected: /// If colvar_array_size is larger than 1, weigh each one by this number before accumulating the histogram std::vector weights; - virtual std::istream& read_restart(std::istream&); - virtual std::ostream& write_restart(std::ostream&); + virtual std::istream & read_state_data(std::istream &is); + virtual std::ostream & write_state_data(std::ostream &os); }; #endif diff --git a/lib/colvars/colvarbias_meta.cpp b/lib/colvars/colvarbias_meta.cpp index 2aa88bd12a..01a04d1a01 100644 --- a/lib/colvars/colvarbias_meta.cpp +++ b/lib/colvars/colvarbias_meta.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include #include @@ -26,10 +33,9 @@ colvarbias_meta::colvarbias_meta(char const *key) - : colvarbias(key), - new_hills_begin(hills.end()), - state_file_step(0) + : colvarbias(key) { + new_hills_begin = hills.end(); } @@ -164,11 +170,32 @@ int colvarbias_meta::init(std::string const &conf) target_dist = NULL; get_keyval(conf, "ebMeta", ebmeta, false); if(ebmeta){ + if (use_grids && expand_grids) { + cvm::fatal_error("Error: expandBoundaries is not supported with " + "ebMeta please allocate wide enough boundaries for " + "each colvar ahead of time and set targetdistfile " + "accordingly. \n"); + } target_dist = new colvar_grid_scalar(); target_dist->init_from_colvars(colvars); get_keyval(conf, "targetdistfile", target_dist_file); std::ifstream targetdiststream(target_dist_file.c_str()); target_dist->read_multicol(targetdiststream); + cvm::real min_val = target_dist->minimum_value(); + if(min_val<0){ + cvm::error("Error: Target distribution of ebMeta " + "has negative values!.\n", INPUT_ERROR); + } + cvm::real min_pos_val = target_dist->minimum_pos_value(); + if(min_pos_val<=0){ + cvm::error("Error: Target distribution of ebMeta has negative " + "or zero minimum positive value!.\n", INPUT_ERROR); + } + if(min_val==0){ + cvm::log("WARNING: Target distribution has zero values.\n"); + cvm::log("Zeros will be converted to the minimum positive value.\n"); + target_dist->remove_zeros(min_pos_val); + } // normalize target distribution and multiply by effective volume = exp(differential entropy) target_dist->multiply_constant(1.0/target_dist->integral()); cvm::real volume = std::exp(target_dist->entropy()); @@ -404,8 +431,10 @@ int colvarbias_meta::update() if (ebmeta) { hills_scale *= 1.0/target_dist->value(target_dist->get_colvars_index()); - if(cvm::step_absolute() <= ebmeta_equil_steps) { - cvm::real const hills_lambda=(cvm::real(ebmeta_equil_steps - cvm::step_absolute()))/(cvm::real(ebmeta_equil_steps)); + if(cvm::step_absolute() <= long(ebmeta_equil_steps)) { + cvm::real const hills_lambda = + (cvm::real(long(ebmeta_equil_steps) - cvm::step_absolute())) / + (cvm::real(ebmeta_equil_steps)); hills_scale = hills_lambda + (1-hills_lambda)*hills_scale; } } @@ -972,7 +1001,7 @@ void colvarbias_meta::read_replica_files() (replicas[ir])->replica_state_file+"\".\n"); std::ifstream is((replicas[ir])->replica_state_file.c_str()); - if (! (replicas[ir])->read_restart(is)) { + if (! (replicas[ir])->read_state(is)) { cvm::log("Reading from file \""+(replicas[ir])->replica_state_file+ "\" failed or incomplete: will try again in "+ cvm::to_str(replica_update_freq)+" steps.\n"); @@ -1068,63 +1097,24 @@ void colvarbias_meta::read_replica_files() } -// ********************************************************************** -// input functions -// ********************************************************************** - - -std::istream & colvarbias_meta::read_restart(std::istream& is) +int colvarbias_meta::set_state_params(std::string const &state_conf) { - size_t const start_pos = is.tellg(); - - if (comm == single_replica) { - // if using a multiple replicas scheme, output messages - // are printed before and after calling this function - cvm::log("Restarting metadynamics bias \""+this->name+"\""+ - ".\n"); - } - std::string key, brace, conf; - if ( !(is >> key) || !(key == "metadynamics") || - !(is >> brace) || !(brace == "{") || - !(is >> colvarparse::read_block("configuration", conf)) ) { - - if (comm == single_replica) - cvm::log("Error: in reading restart configuration for metadynamics bias \""+ - this->name+"\""+ - ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ - (replica_state_file_in_sync ? ("at position "+ - cvm::to_str(start_pos)+ - " in the state file") : "")+".\n"); - is.clear(); - is.seekg(start_pos, std::ios::beg); - is.setstate(std::ios::failbit); - return is; + std::string new_replica = ""; + if (colvarparse::get_keyval(state_conf, "replicaID", new_replica, + std::string(""), colvarparse::parse_silent) && + (new_replica != this->replica_id)) { + cvm::error("Error: in the state file, the " + "\"metadynamics\" block has a different replicaID: different system?\n", + INPUT_ERROR); + return INPUT_ERROR; } - std::string name = ""; - if ( colvarparse::get_keyval(conf, "name", name, - std::string(""), colvarparse::parse_silent) && - (name != this->name) ) - cvm::fatal_error("Error: in the restart file, the " - "\"metadynamics\" block has a different name: different system?\n"); + return COLVARS_OK; +} - if (name.size() == 0) { - cvm::fatal_error("Error: \"metadynamics\" block within the restart file " - "has no identifiers.\n"); - } - - if (comm != single_replica) { - std::string replica = ""; - if (colvarparse::get_keyval(conf, "replicaID", replica, - std::string(""), colvarparse::parse_silent) && - (replica != this->replica_id)) - cvm::fatal_error("Error: in the restart file, the " - "\"metadynamics\" block has a different replicaID: different system?\n"); - - colvarparse::get_keyval(conf, "step", state_file_step, - cvm::step_absolute(), colvarparse::parse_silent); - } +std::istream & colvarbias_meta::read_state_data(std::istream& is) +{ bool grids_from_restart_file = use_grids; if (use_grids) { @@ -1155,6 +1145,7 @@ std::istream & colvarbias_meta::read_restart(std::istream& is) } size_t const hills_energy_pos = is.tellg(); + std::string key; if (!(is >> key)) { if (hills_energy_backup != NULL) { delete hills_energy; @@ -1316,17 +1307,6 @@ std::istream & colvarbias_meta::read_restart(std::istream& is) } } - is >> brace; - if (brace != "}") { - cvm::log("Incomplete restart information for metadynamics bias \""+ - this->name+"\""+ - ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ - ": no closing brace at position "+ - cvm::to_str(is.tellg())+" in the file.\n"); - is.setstate(std::ios::failbit); - return is; - } - if (cvm::debug()) cvm::log("colvarbias_meta::read_restart() done\n"); @@ -1424,13 +1404,6 @@ std::istream & colvarbias_meta::read_hill(std::istream &is) } - - -// ********************************************************************** -// output functions -// ********************************************************************** - - int colvarbias_meta::setup_output() { @@ -1537,16 +1510,17 @@ int colvarbias_meta::setup_output() } -std::ostream & colvarbias_meta::write_restart(std::ostream& os) +std::string const colvarbias_meta::get_state_params() const { - os << "metadynamics {\n" - << " configuration {\n" - << " step " << cvm::step_absolute() << "\n" - << " name " << this->name << "\n"; + std::ostringstream os; if (this->comm != single_replica) - os << " replicaID " << this->replica_id << "\n"; - os << " }\n\n"; + os << "replicaID " << this->replica_id << "\n"; + return (colvarbias::get_state_params() + os.str()); +} + +std::ostream & colvarbias_meta::write_state_data(std::ostream& os) +{ if (use_grids) { // this is a very good time to project hills, if you haven't done @@ -1578,8 +1552,12 @@ std::ostream & colvarbias_meta::write_restart(std::ostream& os) } } - os << "}\n\n"; + return os; +} + +int colvarbias_meta::write_state_to_replicas() +{ if (comm != single_replica) { write_replica_state_file(); // schedule to reread the state files of the other replicas (they @@ -1588,12 +1566,16 @@ std::ostream & colvarbias_meta::write_restart(std::ostream& os) (replicas[ir])->replica_state_file_in_sync = false; } } + return COLVARS_OK; +} + +int colvarbias_meta::write_output_files() +{ if (dump_fes) { write_pmf(); } - - return os; + return COLVARS_OK; } @@ -1665,53 +1647,67 @@ void colvarbias_meta::write_pmf() -void colvarbias_meta::write_replica_state_file() +int colvarbias_meta::write_replica_state_file() { - // write down also the restart for the other replicas: TODO: this - // is duplicated code, that could be cleaned up later + if (cvm::debug()) { + cvm::log("Writing replica state file for bias \""+name+"\"\n"); + } + // write down also the restart for the other replicas cvm::backup_file(replica_state_file.c_str()); - cvm::ofstream rep_state_os(replica_state_file.c_str()); - if (!rep_state_os.is_open()) - cvm::fatal_error("Error: in opening file \""+ - replica_state_file+"\" for writing.\n"); - - rep_state_os.setf(std::ios::scientific, std::ios::floatfield); - rep_state_os << "\n" - << "metadynamics {\n" - << " configuration {\n" - << " name " << this->name << "\n" - << " step " << cvm::step_absolute() << "\n"; - if (this->comm != single_replica) { - rep_state_os << " replicaID " << this->replica_id << "\n"; - } - rep_state_os << " }\n\n"; - rep_state_os << " hills_energy\n"; - rep_state_os << std::setprecision(cvm::cv_prec) - << std::setw(cvm::cv_width); - hills_energy->write_restart(rep_state_os); - rep_state_os << " hills_energy_gradients\n"; - rep_state_os << std::setprecision(cvm::cv_prec) - << std::setw(cvm::cv_width); - hills_energy_gradients->write_restart(rep_state_os); - - if ( (!use_grids) || keep_hills ) { - // write all hills currently in memory - for (std::list::const_iterator h = this->hills.begin(); - h != this->hills.end(); - h++) { - rep_state_os << *h; - } - } else { - // write just those that are near the grid boundaries - for (std::list::const_iterator h = this->hills_off_grid.begin(); - h != this->hills_off_grid.end(); - h++) { - rep_state_os << *h; - } + std::ostream *rep_state_os = cvm::proxy->output_stream(replica_state_file); + if (rep_state_os == NULL) { + cvm::error("Error: in opening file \""+ + replica_state_file+"\" for writing.\n", FILE_ERROR); + return FILE_ERROR; } - rep_state_os << "}\n\n"; - rep_state_os.close(); + rep_state_os->setf(std::ios::scientific, std::ios::floatfield); + + if (!write_state(*rep_state_os)) { + cvm::error("Error: in writing to file \""+ + replica_state_file+"\".\n", FILE_ERROR); + cvm::proxy->close_output_stream(replica_state_file); + return FILE_ERROR; + } + + cvm::proxy->close_output_stream(replica_state_file); + + // rep_state_os.setf(std::ios::scientific, std::ios::floatfield); + // rep_state_os << "\n" + // << "metadynamics {\n" + // << " configuration {\n" + // << " name " << this->name << "\n" + // << " step " << cvm::step_absolute() << "\n"; + // if (this->comm != single_replica) { + // rep_state_os << " replicaID " << this->replica_id << "\n"; + // } + // rep_state_os << " }\n\n"; + // rep_state_os << " hills_energy\n"; + // rep_state_os << std::setprecision(cvm::cv_prec) + // << std::setw(cvm::cv_width); + // hills_energy->write_restart(rep_state_os); + // rep_state_os << " hills_energy_gradients\n"; + // rep_state_os << std::setprecision(cvm::cv_prec) + // << std::setw(cvm::cv_width); + // hills_energy_gradients->write_restart(rep_state_os); + + // if ( (!use_grids) || keep_hills ) { + // // write all hills currently in memory + // for (std::list::const_iterator h = this->hills.begin(); + // h != this->hills.end(); + // h++) { + // rep_state_os << *h; + // } + // } else { + // // write just those that are near the grid boundaries + // for (std::list::const_iterator h = this->hills_off_grid.begin(); + // h != this->hills_off_grid.end(); + // h++) { + // rep_state_os << *h; + // } + // } + // rep_state_os << "}\n\n"; + // rep_state_os.close(); // reopen the hills file replica_hills_os.close(); @@ -1721,8 +1717,11 @@ void colvarbias_meta::write_replica_state_file() cvm::fatal_error("Error: in opening file \""+ replica_hills_file+"\" for writing.\n"); replica_hills_os.setf(std::ios::scientific, std::ios::floatfield); + + return COLVARS_OK; } + std::string colvarbias_meta::hill::output_traj() { std::ostringstream os; diff --git a/lib/colvars/colvarbias_meta.h b/lib/colvars/colvarbias_meta.h index 6936e97954..a88a34ba00 100644 --- a/lib/colvars/colvarbias_meta.h +++ b/lib/colvars/colvarbias_meta.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARBIAS_META_H #define COLVARBIAS_META_H @@ -31,10 +38,16 @@ public: virtual int init(std::string const &conf); virtual ~colvarbias_meta(); virtual int update(); - virtual std::istream & read_restart(std::istream &is); - virtual std::ostream & write_restart(std::ostream &os); + + virtual std::string const get_state_params() const; + virtual int set_state_params(std::string const &state_conf); + virtual std::ostream & write_state_data(std::ostream &os); + virtual std::istream & read_state_data(std::istream &os); + virtual int setup_output(); + virtual int write_output_files(); virtual void write_pmf(); + virtual int write_state_to_replicas(); class hill; typedef std::list::iterator hill_iter; @@ -77,13 +90,6 @@ protected: /// Read a hill from a file std::istream & read_hill(std::istream &is); - /// \brief step present in a state file - /// - /// When using grids and reading state files containing them - /// (multiple replicas), this is used to check whether a hill is - /// newer or older than the grids - size_t state_file_step; - /// \brief Add a new hill; if a .hills trajectory is written, /// write it there; if there is more than one replica, communicate /// it to the others @@ -187,7 +193,7 @@ protected: virtual void read_replica_files(); /// \brief Write data to other replicas - virtual void write_replica_state_file(); + virtual int write_replica_state_file(); /// \brief Additional, "mirror" metadynamics biases, to collect info /// from the other replicas diff --git a/lib/colvars/colvarbias_restraint.cpp b/lib/colvars/colvarbias_restraint.cpp index bd37a430a1..84630984e5 100644 --- a/lib/colvars/colvarbias_restraint.cpp +++ b/lib/colvars/colvarbias_restraint.cpp @@ -1,10 +1,18 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include "colvarmodule.h" #include "colvarvalue.h" #include "colvarbias_restraint.h" + colvarbias_restraint::colvarbias_restraint(char const *key) : colvarbias(key) { @@ -14,127 +22,36 @@ colvarbias_restraint::colvarbias_restraint(char const *key) int colvarbias_restraint::init(std::string const &conf) { colvarbias::init(conf); + enable(f_cvb_apply_force); if (cvm::debug()) cvm::log("Initializing a new restraint bias.\n"); - // TODO move these initializations to constructor and let get_keyval - // only override existing values - target_nstages = 0; - target_nsteps = 0; - force_k = 0.0; + return COLVARS_OK; +} - get_keyval(conf, "forceConstant", force_k, 1.0); - { - // get the initial restraint centers - colvar_centers.resize(colvars.size()); - colvar_centers_raw.resize(colvars.size()); - size_t i; - - enable(f_cvb_apply_force); - - for (i = 0; i < colvars.size(); i++) { - colvar_centers[i].type(colvars[i]->value()); - colvar_centers_raw[i].type(colvars[i]->value()); - if (cvm::debug()) { - cvm::log("colvarbias_restraint: center size = "+ - cvm::to_str(colvar_centers[i].vector1d_value.size())+"\n"); - } - } - if (get_keyval(conf, "centers", colvar_centers, colvar_centers)) { - for (i = 0; i < colvars.size(); i++) { - if (cvm::debug()) { - cvm::log("colvarbias_restraint: parsing initial centers, i = "+cvm::to_str(i)+".\n"); - } - - colvar_centers[i].apply_constraints(); - colvar_centers_raw[i] = colvar_centers[i]; - } - } else { - colvar_centers.clear(); - cvm::error("Error: must define the initial centers of the restraints.\n"); - } - - if (colvar_centers.size() != colvars.size()) { - cvm::error("Error: number of centers does not match " - "that of collective variables.\n"); - } - } - - { - if (cvm::debug()) { - cvm::log("colvarbias_restraint: parsing target centers.\n"); - } - - size_t i; - if (get_keyval(conf, "targetCenters", target_centers, colvar_centers)) { - if (colvar_centers.size() != colvars.size()) { - cvm::error("Error: number of target centers does not match " - "that of collective variables.\n"); - } - b_chg_centers = true; - for (i = 0; i < target_centers.size(); i++) { - target_centers[i].apply_constraints(); - } - } else { - b_chg_centers = false; - target_centers.clear(); - } - } - - if (get_keyval(conf, "targetForceConstant", target_force_k, 0.0)) { - if (b_chg_centers) - cvm::error("Error: cannot specify both targetCenters and targetForceConstant.\n"); - - starting_force_k = force_k; - b_chg_force_k = true; - - get_keyval(conf, "targetEquilSteps", target_equil_steps, 0); - - get_keyval(conf, "lambdaSchedule", lambda_schedule, lambda_schedule); - if (lambda_schedule.size()) { - // There is one more lambda-point than stages - target_nstages = lambda_schedule.size() - 1; - } - } else { - b_chg_force_k = false; - } - - if (b_chg_centers || b_chg_force_k) { - get_keyval(conf, "targetNumSteps", target_nsteps, 0); - if (!target_nsteps) - cvm::error("Error: targetNumSteps must be non-zero.\n"); - - if (get_keyval(conf, "targetNumStages", target_nstages, target_nstages) && - lambda_schedule.size()) { - cvm::error("Error: targetNumStages and lambdaSchedule are incompatible.\n"); - } - - if (target_nstages) { - // This means that either numStages of lambdaSchedule has been provided - stage = 0; - restraint_FE = 0.0; - } - - if (get_keyval(conf, "targetForceExponent", force_k_exp, 1.0)) { - if (! b_chg_force_k) - cvm::log("Warning: not changing force constant: targetForceExponent will be ignored\n"); - if (force_k_exp < 1.0) - cvm::log("Warning: for all practical purposes, targetForceExponent should be 1.0 or greater.\n"); - } - } - - get_keyval(conf, "outputCenters", b_output_centers, false); - if (b_chg_centers) { - get_keyval(conf, "outputAccumulatedWork", b_output_acc_work, false); - } else { - b_output_acc_work = false; - } - acc_work = 0.0; +int colvarbias_restraint::update() +{ + bias_energy = 0.0; if (cvm::debug()) - cvm::log("Done initializing a new restraint bias.\n"); + cvm::log("Updating the restraint bias \""+this->name+"\".\n"); + + // Force and energy calculation + for (size_t i = 0; i < colvars.size(); i++) { + colvar_forces[i].type(colvars[i]->value()); + colvar_forces[i].is_derivative(); + colvar_forces[i] = restraint_force(i); + bias_energy += restraint_potential(i); + } + + if (cvm::debug()) + cvm::log("Done updating the restraint bias \""+this->name+"\".\n"); + + if (cvm::debug()) + cvm::log("Current forces for the restraint bias \""+ + this->name+"\": "+cvm::to_str(colvar_forces)+".\n"); return COLVARS_OK; } @@ -147,9 +64,83 @@ colvarbias_restraint::~colvarbias_restraint() } -void colvarbias_restraint::change_configuration(std::string const &conf) +std::string const colvarbias_restraint::get_state_params() const +{ + return colvarbias::get_state_params(); +} + + +int colvarbias_restraint::set_state_params(std::string const &conf) +{ + return colvarbias::set_state_params(conf); +} + + +std::ostream & colvarbias_restraint::write_traj_label(std::ostream &os) +{ + return colvarbias::write_traj_label(os); +} + + +std::ostream & colvarbias_restraint::write_traj(std::ostream &os) +{ + return colvarbias::write_traj(os); +} + + + +colvarbias_restraint_centers::colvarbias_restraint_centers(char const *key) + : colvarbias(key), colvarbias_restraint(key) +{ +} + + +int colvarbias_restraint_centers::init(std::string const &conf) +{ + size_t i; + + bool null_centers = (colvar_centers.size() == 0); + if (null_centers) { + // try to initialize the restraint centers for the first time + colvar_centers.resize(colvars.size()); + colvar_centers_raw.resize(colvars.size()); + for (i = 0; i < colvars.size(); i++) { + colvar_centers[i].type(colvars[i]->value()); + colvar_centers[i].reset(); + colvar_centers_raw[i].type(colvars[i]->value()); + colvar_centers_raw[i].reset(); + } + } + + if (get_keyval(conf, "centers", colvar_centers, colvar_centers)) { + for (i = 0; i < colvars.size(); i++) { + if (cvm::debug()) { + cvm::log("colvarbias_restraint: parsing initial centers, i = "+cvm::to_str(i)+".\n"); + } + colvar_centers_raw[i] = colvar_centers[i]; + colvar_centers[i].apply_constraints(); + } + null_centers = false; + } + + if (null_centers) { + colvar_centers.clear(); + cvm::error("Error: must define the initial centers of the restraints.\n", INPUT_ERROR); + return INPUT_ERROR; + } + + if (colvar_centers.size() != colvars.size()) { + cvm::error("Error: number of centers does not match " + "that of collective variables.\n", INPUT_ERROR); + return INPUT_ERROR; + } + + return COLVARS_OK; +} + + +int colvarbias_restraint_centers::change_configuration(std::string const &conf) { - get_keyval(conf, "forceConstant", force_k, force_k); if (get_keyval(conf, "centers", colvar_centers, colvar_centers)) { for (size_t i = 0; i < colvars.size(); i++) { colvar_centers[i].type(colvars[i]->value()); @@ -158,61 +149,159 @@ void colvarbias_restraint::change_configuration(std::string const &conf) colvar_centers_raw[i] = colvar_centers[i]; } } + return COLVARS_OK; } -cvm::real colvarbias_restraint::energy_difference(std::string const &conf) + +colvarbias_restraint_k::colvarbias_restraint_k(char const *key) + : colvarbias(key), colvarbias_restraint(key) { - std::vector alt_colvar_centers; - cvm::real alt_force_k; - cvm::real alt_bias_energy = 0.0; + force_k = -1.0; +} - get_keyval(conf, "forceConstant", alt_force_k, force_k); - alt_colvar_centers.resize(colvars.size()); +int colvarbias_restraint_k::init(std::string const &conf) +{ + get_keyval(conf, "forceConstant", force_k, (force_k > 0.0 ? force_k : 1.0)); + if (force_k < 0.0) { + cvm::error("Error: undefined or invalid force constant.\n", INPUT_ERROR); + return INPUT_ERROR; + } + return COLVARS_OK; +} + + +int colvarbias_restraint_k::change_configuration(std::string const &conf) +{ + get_keyval(conf, "forceConstant", force_k, force_k); + return COLVARS_OK; +} + + + +colvarbias_restraint_moving::colvarbias_restraint_moving(char const *key) +{ + target_nstages = 0; + target_nsteps = 0; + stage = 0; + b_chg_centers = false; + b_chg_force_k = false; +} + + +int colvarbias_restraint_moving::init(std::string const &conf) +{ + if (b_chg_centers && b_chg_force_k) { + cvm::error("Error: cannot specify both targetCenters and targetForceConstant.\n", + INPUT_ERROR); + return INPUT_ERROR; + } + + if (b_chg_centers || b_chg_force_k) { + + get_keyval(conf, "targetNumSteps", target_nsteps, target_nsteps); + if (!target_nsteps) { + cvm::error("Error: targetNumSteps must be non-zero.\n", INPUT_ERROR); + return cvm::get_error(); + } + + if (get_keyval(conf, "targetNumStages", target_nstages, target_nstages) && + lambda_schedule.size()) { + cvm::error("Error: targetNumStages and lambdaSchedule are incompatible.\n", INPUT_ERROR); + return cvm::get_error(); + } + } + + return COLVARS_OK; +} + + +std::string const colvarbias_restraint_moving::get_state_params() const +{ + std::ostringstream os; + os.setf(std::ios::scientific, std::ios::floatfield); + if (b_chg_centers || b_chg_force_k) { + // TODO move this + if (target_nstages) { + os << "stage " << std::setw(cvm::it_width) + << stage << "\n"; + } + } + return os.str(); +} + + +int colvarbias_restraint_moving::set_state_params(std::string const &conf) +{ + if (b_chg_centers || b_chg_force_k) { + if (target_nstages) { + // cvm::log ("Reading current stage from the restart.\n"); + if (!get_keyval(conf, "stage", stage)) + cvm::error("Error: current stage is missing from the restart.\n"); + } + } + return COLVARS_OK; +} + + + +colvarbias_restraint_centers_moving::colvarbias_restraint_centers_moving(char const *key) + : colvarbias(key), + colvarbias_restraint(key), + colvarbias_restraint_centers(key), + colvarbias_restraint_moving(key) +{ + b_chg_centers = false; + b_output_centers = false; + b_output_acc_work = false; + acc_work = 0.0; +} + + +int colvarbias_restraint_centers_moving::init(std::string const &conf) +{ + colvarbias_restraint_centers::init(conf); + + if (cvm::debug()) { + cvm::log("colvarbias_restraint: parsing target centers.\n"); + } + size_t i; - for (i = 0; i < colvars.size(); i++) { - alt_colvar_centers[i].type(colvars[i]->value()); - } - if (get_keyval(conf, "centers", alt_colvar_centers, colvar_centers)) { - for (i = 0; i < colvars.size(); i++) { - alt_colvar_centers[i].apply_constraints(); + if (get_keyval(conf, "targetCenters", target_centers, colvar_centers)) { + if (colvar_centers.size() != colvars.size()) { + cvm::error("Error: number of target centers does not match " + "that of collective variables.\n"); } - } - - for (i = 0; i < colvars.size(); i++) { - alt_bias_energy += restraint_potential(restraint_convert_k(alt_force_k, colvars[i]->width), - colvars[i], - alt_colvar_centers[i]); - } - - return alt_bias_energy - bias_energy; -} - - -int colvarbias_restraint::update() -{ - bias_energy = 0.0; - - if (cvm::debug()) - cvm::log("Updating the restraint bias \""+this->name+"\".\n"); - - // Setup first stage of staged variable force constant calculation - if (b_chg_force_k && target_nstages && cvm::step_absolute() == 0) { - cvm::real lambda; - if (lambda_schedule.size()) { - lambda = lambda_schedule[0]; - } else { - lambda = 0.0; + b_chg_centers = true; + for (i = 0; i < target_centers.size(); i++) { + target_centers[i].apply_constraints(); } - force_k = starting_force_k + (target_force_k - starting_force_k) - * std::pow(lambda, force_k_exp); - cvm::log("Restraint " + this->name + ", stage " + - cvm::to_str(stage) + " : lambda = " + cvm::to_str(lambda)); - cvm::log("Setting force constant to " + cvm::to_str(force_k)); } if (b_chg_centers) { + // parse moving restraint options + colvarbias_restraint_moving::init(conf); + } else { + target_centers.clear(); + return COLVARS_OK; + } + + get_keyval(conf, "outputCenters", b_output_centers, b_output_centers); + get_keyval(conf, "outputAccumulatedWork", b_output_acc_work, b_output_acc_work); + + return COLVARS_OK; +} + + +int colvarbias_restraint_centers_moving::update() +{ + if (b_chg_centers) { + + if (cvm::debug()) { + cvm::log("Updating centers for the restraint bias \""+ + this->name+"\": "+cvm::to_str(colvar_centers)+".\n"); + } if (!centers_incr.size()) { // if this is the first calculation, calculate the advancement @@ -224,30 +313,30 @@ int colvarbias_restraint::update() centers_incr[i].type(colvars[i]->value()); centers_incr[i] = (target_centers[i] - colvar_centers_raw[i]) / cvm::real( target_nstages ? (target_nstages - stage) : - (target_nsteps - cvm::step_absolute())); + (target_nsteps - cvm::step_absolute())); } if (cvm::debug()) { cvm::log("Center increment for the restraint bias \""+ - this->name+"\": "+cvm::to_str(centers_incr)+" at stage "+cvm::to_str(stage)+ ".\n"); + this->name+"\": "+cvm::to_str(centers_incr)+" at stage "+cvm::to_str(stage)+ ".\n"); } } if (target_nstages) { if ((cvm::step_relative() > 0) - && (cvm::step_absolute() % target_nsteps) == 0 - && stage < target_nstages) { + && (cvm::step_absolute() % target_nsteps) == 0 + && stage < target_nstages) { - for (size_t i = 0; i < colvars.size(); i++) { - colvar_centers_raw[i] += centers_incr[i]; - colvar_centers[i] = colvar_centers_raw[i]; - colvars[i]->wrap(colvar_centers[i]); - colvar_centers[i].apply_constraints(); - } - stage++; - cvm::log("Moving restraint \"" + this->name + - "\" stage " + cvm::to_str(stage) + - " : setting centers to " + cvm::to_str(colvar_centers) + - " at step " + cvm::to_str(cvm::step_absolute())); + for (size_t i = 0; i < colvars.size(); i++) { + colvar_centers_raw[i] += centers_incr[i]; + colvar_centers[i] = colvar_centers_raw[i]; + colvars[i]->wrap(colvar_centers[i]); + colvar_centers[i].apply_constraints(); + } + stage++; + cvm::log("Moving restraint \"" + this->name + + "\" stage " + cvm::to_str(stage) + + " : setting centers to " + cvm::to_str(colvar_centers) + + " at step " + cvm::to_str(cvm::step_absolute())); } } else if ((cvm::step_relative() > 0) && (cvm::step_absolute() <= target_nsteps)) { // move the restraint centers in the direction of the targets @@ -260,16 +349,201 @@ int colvarbias_restraint::update() } } - if (cvm::debug()) - cvm::log("Current centers for the restraint bias \""+ - this->name+"\": "+cvm::to_str(colvar_centers)+".\n"); + if (cvm::debug()) { + cvm::log("New centers for the restraint bias \""+ + this->name+"\": "+cvm::to_str(colvar_centers)+".\n"); + } + } + + return COLVARS_OK; +} + + +int colvarbias_restraint_centers_moving::update_acc_work() +{ + if (b_output_acc_work) { + if ((cvm::step_relative() > 0) || (cvm::step_absolute() == 0)) { + for (size_t i = 0; i < colvars.size(); i++) { + // project forces on the calculated increments at this step + acc_work += colvar_forces[i] * centers_incr[i]; + } + } + } + return COLVARS_OK; +} + + +std::string const colvarbias_restraint_centers_moving::get_state_params() const +{ + std::ostringstream os; + os.setf(std::ios::scientific, std::ios::floatfield); + + if (b_chg_centers) { + size_t i; + os << "centers "; + for (i = 0; i < colvars.size(); i++) { + os << " " + << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width) + << colvar_centers[i]; + } + os << "\n"; + os << "centers_raw "; + for (i = 0; i < colvars.size(); i++) { + os << " " + << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width) + << colvar_centers_raw[i]; + } + os << "\n"; + + if (b_output_acc_work) { + os << "accumulatedWork " + << std::setprecision(cvm::en_prec) << std::setw(cvm::en_width) + << acc_work << "\n"; + } + } + + return colvarbias_restraint_moving::get_state_params() + os.str(); +} + + +int colvarbias_restraint_centers_moving::set_state_params(std::string const &conf) +{ + colvarbias_restraint::set_state_params(conf); + + if (b_chg_centers) { + // cvm::log ("Reading the updated restraint centers from the restart.\n"); + if (!get_keyval(conf, "centers", colvar_centers)) + cvm::error("Error: restraint centers are missing from the restart.\n"); + if (!get_keyval(conf, "centers_raw", colvar_centers_raw)) + cvm::error("Error: \"raw\" restraint centers are missing from the restart.\n"); + if (b_output_acc_work) { + if (!get_keyval(conf, "accumulatedWork", acc_work)) + cvm::error("Error: accumulatedWork is missing from the restart.\n"); + } + } + + return COLVARS_OK; +} + + +std::ostream & colvarbias_restraint_centers_moving::write_traj_label(std::ostream &os) +{ + if (b_output_centers) { + for (size_t i = 0; i < colvars.size(); i++) { + size_t const this_cv_width = (colvars[i]->value()).output_width(cvm::cv_width); + os << " x0_" + << cvm::wrap_string(colvars[i]->name, this_cv_width-3); + } + } + + if (b_output_acc_work) { + os << " W_" + << cvm::wrap_string(this->name, cvm::en_width-2); + } + + return os; +} + + +std::ostream & colvarbias_restraint_centers_moving::write_traj(std::ostream &os) +{ + if (b_output_centers) { + for (size_t i = 0; i < colvars.size(); i++) { + os << " " + << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width) + << colvar_centers[i]; + } + } + + if (b_output_acc_work) { + os << " " + << std::setprecision(cvm::en_prec) << std::setw(cvm::en_width) + << acc_work; + } + + return os; +} + + + +colvarbias_restraint_k_moving::colvarbias_restraint_k_moving(char const *key) + : colvarbias(key), + colvarbias_restraint(key), + colvarbias_restraint_k(key), + colvarbias_restraint_moving(key) +{ + b_chg_force_k = false; + target_equil_steps = 0; + target_force_k = 0.0; + starting_force_k = 0.0; + force_k_exp = 1.0; + restraint_FE = 0.0; +} + + +int colvarbias_restraint_k_moving::init(std::string const &conf) +{ + colvarbias_restraint_k::init(conf); + + if (get_keyval(conf, "targetForceConstant", target_force_k, target_force_k)) { + starting_force_k = force_k; + b_chg_force_k = true; } if (b_chg_force_k) { - // Coupling parameter, between 0 and 1 + // parse moving restraint options + colvarbias_restraint_moving::init(conf); + } else { + return COLVARS_OK; + } + + get_keyval(conf, "targetEquilSteps", target_equil_steps, target_equil_steps); + + if (get_keyval(conf, "lambdaSchedule", lambda_schedule, lambda_schedule) && + target_nstages > 0) { + cvm::error("Error: targetNumStages and lambdaSchedule are incompatible.\n", INPUT_ERROR); + return cvm::get_error(); + } + + if (lambda_schedule.size()) { + // There is one more lambda-point than stages + target_nstages = lambda_schedule.size() - 1; + } + + if (get_keyval(conf, "targetForceExponent", force_k_exp, force_k_exp)) { + if (! b_chg_force_k) + cvm::log("Warning: not changing force constant: targetForceExponent will be ignored\n"); + } + if (force_k_exp < 1.0) { + cvm::log("Warning: for all practical purposes, targetForceExponent should be 1.0 or greater.\n"); + } + + return COLVARS_OK; +} + + +int colvarbias_restraint_k_moving::update() +{ + if (b_chg_force_k) { + cvm::real lambda; if (target_nstages) { + + if (cvm::step_absolute() == 0) { + // Setup first stage of staged variable force constant calculation + if (lambda_schedule.size()) { + lambda = lambda_schedule[0]; + } else { + lambda = 0.0; + } + force_k = starting_force_k + (target_force_k - starting_force_k) + * std::pow(lambda, force_k_exp); + cvm::log("Restraint " + this->name + ", stage " + + cvm::to_str(stage) + " : lambda = " + cvm::to_str(lambda)); + cvm::log("Setting force constant to " + cvm::to_str(force_k)); + } + // TI calculation: estimate free energy derivative // need current lambda if (lambda_schedule.size()) { @@ -284,8 +558,7 @@ int colvarbias_restraint::update() // Square distance normalized by square colvar width cvm::real dist_sq = 0.0; for (size_t i = 0; i < colvars.size(); i++) { - dist_sq += colvars[i]->dist2(colvars[i]->value(), colvar_centers[i]) - / (colvars[i]->width * colvars[i]->width); + dist_sq += d_restraint_potential_dk(i); } restraint_FE += 0.5 * force_k_exp * std::pow(lambda, force_k_exp - 1.0) @@ -296,8 +569,8 @@ int colvarbias_restraint::update() if (cvm::step_absolute() % target_nsteps == 0 && cvm::step_absolute() > 0) { - cvm::log("Lambda= " + cvm::to_str(lambda) + " dA/dLambda= " - + cvm::to_str(restraint_FE / cvm::real(target_nsteps - target_equil_steps))); + cvm::log("Lambda= " + cvm::to_str(lambda) + " dA/dLambda= " + + cvm::to_str(restraint_FE / cvm::real(target_nsteps - target_equil_steps))); // ...and move on to the next one if (stage < target_nstages) { @@ -310,220 +583,133 @@ int colvarbias_restraint::update() lambda = cvm::real(stage) / cvm::real(target_nstages); } force_k = starting_force_k + (target_force_k - starting_force_k) - * std::pow(lambda, force_k_exp); + * std::pow(lambda, force_k_exp); cvm::log("Restraint " + this->name + ", stage " + - cvm::to_str(stage) + " : lambda = " + cvm::to_str(lambda)); + cvm::to_str(stage) + " : lambda = " + cvm::to_str(lambda)); cvm::log("Setting force constant to " + cvm::to_str(force_k)); } } + } else if (cvm::step_absolute() <= target_nsteps) { + // update force constant (slow growth) lambda = cvm::real(cvm::step_absolute()) / cvm::real(target_nsteps); force_k = starting_force_k + (target_force_k - starting_force_k) - * std::pow(lambda, force_k_exp); + * std::pow(lambda, force_k_exp); } } - if (cvm::debug()) - cvm::log("Done updating the restraint bias \""+this->name+"\".\n"); - - // Force and energy calculation - for (size_t i = 0; i < colvars.size(); i++) { - colvar_forces[i].type(colvars[i]->value()); - colvar_forces[i] = -1.0 * restraint_force(restraint_convert_k(force_k, colvars[i]->width), - colvars[i], - colvar_centers[i]); - bias_energy += restraint_potential(restraint_convert_k(force_k, colvars[i]->width), - colvars[i], - colvar_centers[i]); - if (cvm::debug()) { - cvm::log("dist_grad["+cvm::to_str(i)+ - "] = "+cvm::to_str(colvars[i]->dist2_lgrad(colvars[i]->value(), - colvar_centers[i]))+"\n"); - } - } - - if (b_output_acc_work) { - if ((cvm::step_relative() > 0) || (cvm::step_absolute() == 0)) { - for (size_t i = 0; i < colvars.size(); i++) { - // project forces on the calculated increments at this step - acc_work += colvar_forces[i] * centers_incr[i]; - } - } - } - - if (cvm::debug()) - cvm::log("Current forces for the restraint bias \""+ - this->name+"\": "+cvm::to_str(colvar_forces)+".\n"); - return COLVARS_OK; } -std::istream & colvarbias_restraint::read_restart(std::istream &is) +std::string const colvarbias_restraint_k_moving::get_state_params() const +{ + std::ostringstream os; + os.setf(std::ios::scientific, std::ios::floatfield); + if (b_chg_force_k) { + os << "forceConstant " + << std::setprecision(cvm::en_prec) + << std::setw(cvm::en_width) << force_k << "\n"; + } + return colvarbias_restraint_moving::get_state_params() + os.str(); +} + + +int colvarbias_restraint_k_moving::set_state_params(std::string const &conf) +{ + colvarbias_restraint::set_state_params(conf); + + if (b_chg_force_k) { + // cvm::log ("Reading the updated force constant from the restart.\n"); + if (!get_keyval(conf, "forceConstant", force_k, force_k)) + cvm::error("Error: force constant is missing from the restart.\n"); + } + + return COLVARS_OK; +} + + +std::ostream & colvarbias_restraint_k_moving::write_traj_label(std::ostream &os) +{ + return os; +} + + +std::ostream & colvarbias_restraint_k_moving::write_traj(std::ostream &os) +{ + return os; +} + + + +// redefined due to legacy state file keyword "harmonic" +std::istream & colvarbias_restraint::read_state(std::istream &is) { size_t const start_pos = is.tellg(); - cvm::log("Restarting restraint bias \""+ - this->name+"\".\n"); - std::string key, brace, conf; if ( !(is >> key) || !(key == "restraint" || key == "harmonic") || !(is >> brace) || !(brace == "{") || - !(is >> colvarparse::read_block("configuration", conf)) ) { - - cvm::log("Error: in reading restart configuration for restraint bias \""+ - this->name+"\" at position "+ - cvm::to_str(is.tellg())+" in stream.\n"); + !(is >> colvarparse::read_block("configuration", conf)) || + (set_state_params(conf) != COLVARS_OK) ) { + cvm::error("Error: in reading state configuration for \""+bias_type+"\" bias \""+ + this->name+"\" at position "+ + cvm::to_str(is.tellg())+" in stream.\n", INPUT_ERROR); is.clear(); is.seekg(start_pos, std::ios::beg); is.setstate(std::ios::failbit); return is; } -// int id = -1; - std::string name = ""; -// if ( ( (colvarparse::get_keyval (conf, "id", id, -1, colvarparse::parse_silent)) && -// (id != this->id) ) || - if ( (colvarparse::get_keyval(conf, "name", name, std::string(""), colvarparse::parse_silent)) && - (name != this->name) ) - cvm::error("Error: in the restart file, the " - "\"restraint\" block has a wrong name\n"); -// if ( (id == -1) && (name == "") ) { - if (name.size() == 0) { - cvm::error("Error: \"restraint\" block in the restart file " - "has no identifiers.\n"); - } - - if (b_chg_centers) { -// cvm::log ("Reading the updated restraint centers from the restart.\n"); - if (!get_keyval(conf, "centers", colvar_centers)) - cvm::error("Error: restraint centers are missing from the restart.\n"); - if (!get_keyval(conf, "centers_raw", colvar_centers_raw)) - cvm::error("Error: \"raw\" restraint centers are missing from the restart.\n"); - } - - if (b_chg_force_k) { -// cvm::log ("Reading the updated force constant from the restart.\n"); - if (!get_keyval(conf, "forceConstant", force_k)) - cvm::error("Error: force constant is missing from the restart.\n"); - } - - if (target_nstages) { -// cvm::log ("Reading current stage from the restart.\n"); - if (!get_keyval(conf, "stage", stage)) - cvm::error("Error: current stage is missing from the restart.\n"); - } - - if (b_output_acc_work) { - if (!get_keyval(conf, "accumulatedWork", acc_work)) - cvm::error("Error: accumulatedWork is missing from the restart.\n"); + if (!read_state_data(is)) { + cvm::error("Error: in reading state data for \""+bias_type+"\" bias \""+ + this->name+"\" at position "+ + cvm::to_str(is.tellg())+" in stream.\n", INPUT_ERROR); + is.clear(); + is.seekg(start_pos, std::ios::beg); + is.setstate(std::ios::failbit); } is >> brace; if (brace != "}") { - cvm::error("Error: corrupt restart information for restraint bias \""+ - this->name+"\": no matching brace at position "+ - cvm::to_str(is.tellg())+" in the restart file.\n"); + cvm::log("brace = "+brace+"\n"); + cvm::error("Error: corrupt restart information for \""+bias_type+"\" bias \""+ + this->name+"\": no matching brace at position "+ + cvm::to_str(is.tellg())+" in stream.\n"); is.setstate(std::ios::failbit); } + return is; } -std::ostream & colvarbias_restraint::write_restart(std::ostream &os) +std::ostream & colvarbias_restraint::write_state(std::ostream &os) { + os.setf(std::ios::scientific, std::ios::floatfield); os << "restraint {\n" - << " configuration {\n" - // << " id " << this->id << "\n" - << " name " << this->name << "\n"; - - if (b_chg_centers) { - size_t i; - os << " centers "; - for (i = 0; i < colvars.size(); i++) { - os << " " << colvar_centers[i]; - } - os << "\n"; - os << " centers_raw "; - for (i = 0; i < colvars.size(); i++) { - os << " " << colvar_centers_raw[i]; - } - os << "\n"; + << " configuration {\n"; + std::istringstream is(get_state_params()); + std::string line; + while (std::getline(is, line)) { + os << " " << line << "\n"; } - - if (b_chg_force_k) { - os << " forceConstant " - << std::setprecision(cvm::en_prec) - << std::setw(cvm::en_width) << force_k << "\n"; - } - - if (target_nstages) { - os << " stage " << std::setw(cvm::it_width) - << stage << "\n"; - } - - if (b_output_acc_work) { - os << " accumulatedWork " << acc_work << "\n"; - } - - os << " }\n" - << "}\n\n"; - + os << " }\n"; + write_state_data(os); + os << "}\n\n"; return os; } -std::ostream & colvarbias_restraint::write_traj_label(std::ostream &os) -{ - os << " "; - - if (b_output_energy) - os << " E_" - << cvm::wrap_string(this->name, cvm::en_width-2); - - if (b_output_centers) - for (size_t i = 0; i < colvars.size(); i++) { - size_t const this_cv_width = (colvars[i]->value()).output_width(cvm::cv_width); - os << " x0_" - << cvm::wrap_string(colvars[i]->name, this_cv_width-3); - } - - if (b_output_acc_work) - os << " W_" - << cvm::wrap_string(this->name, cvm::en_width-2); - - return os; -} - - -std::ostream & colvarbias_restraint::write_traj(std::ostream &os) -{ - os << " "; - - if (b_output_energy) - os << " " - << std::setprecision(cvm::en_prec) << std::setw(cvm::en_width) - << bias_energy; - - if (b_output_centers) - for (size_t i = 0; i < colvars.size(); i++) { - os << " " - << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width) - << colvar_centers[i]; - } - - if (b_output_acc_work) - os << " " - << std::setprecision(cvm::en_prec) << std::setw(cvm::en_width) - << acc_work; - - return os; -} - colvarbias_restraint_harmonic::colvarbias_restraint_harmonic(char const *key) - : colvarbias_restraint(key) + : colvarbias(key), + colvarbias_restraint(key), + colvarbias_restraint_centers(key), + colvarbias_restraint_moving(key), + colvarbias_restraint_k(key), + colvarbias_restraint_centers_moving(key), + colvarbias_restraint_k_moving(key) { } @@ -531,44 +717,332 @@ colvarbias_restraint_harmonic::colvarbias_restraint_harmonic(char const *key) int colvarbias_restraint_harmonic::init(std::string const &conf) { colvarbias_restraint::init(conf); + colvarbias_restraint_moving::init(conf); + colvarbias_restraint_centers_moving::init(conf); + colvarbias_restraint_k_moving::init(conf); for (size_t i = 0; i < colvars.size(); i++) { if (colvars[i]->width != 1.0) cvm::log("The force constant for colvar \""+colvars[i]->name+ "\" will be rescaled to "+ - cvm::to_str(restraint_convert_k(force_k, colvars[i]->width))+ + cvm::to_str(force_k / (colvars[i]->width * colvars[i]->width))+ " according to the specified width.\n"); } + return COLVARS_OK; } -cvm::real colvarbias_restraint_harmonic::restraint_potential(cvm::real k, - colvar const *x, - colvarvalue const &xcenter) const +int colvarbias_restraint_harmonic::update() { - return 0.5 * k * x->dist2(x->value(), xcenter); + // update parameters (centers or force constant) + colvarbias_restraint_centers_moving::update(); + colvarbias_restraint_k_moving::update(); + + // update restraint energy and forces + colvarbias_restraint::update(); + + // update accumulated work using the current forces + colvarbias_restraint_centers_moving::update_acc_work(); + + return COLVARS_OK; } -colvarvalue colvarbias_restraint_harmonic::restraint_force(cvm::real k, - colvar const *x, - colvarvalue const &xcenter) const +cvm::real colvarbias_restraint_harmonic::restraint_potential(size_t i) const { - return 0.5 * k * x->dist2_lgrad(x->value(), xcenter); + return 0.5 * force_k / (colvars[i]->width * colvars[i]->width) * + colvars[i]->dist2(colvars[i]->value(), colvar_centers[i]); } -cvm::real colvarbias_restraint_harmonic::restraint_convert_k(cvm::real k, - cvm::real dist_measure) const +colvarvalue const colvarbias_restraint_harmonic::restraint_force(size_t i) const { - return k / (dist_measure * dist_measure); + return -0.5 * force_k / (colvars[i]->width * colvars[i]->width) * + colvars[i]->dist2_lgrad(colvars[i]->value(), colvar_centers[i]); +} + + +cvm::real colvarbias_restraint_harmonic::d_restraint_potential_dk(size_t i) const +{ + return 0.5 / (colvars[i]->width * colvars[i]->width) * + colvars[i]->dist2(colvars[i]->value(), colvar_centers[i]); +} + + +std::string const colvarbias_restraint_harmonic::get_state_params() const +{ + return colvarbias_restraint::get_state_params() + + colvarbias_restraint_centers_moving::get_state_params() + + colvarbias_restraint_k_moving::get_state_params(); +} + + +int colvarbias_restraint_harmonic::set_state_params(std::string const &conf) +{ + int error_code = COLVARS_OK; + error_code |= colvarbias_restraint::set_state_params(conf); + error_code |= colvarbias_restraint_centers_moving::set_state_params(conf); + error_code |= colvarbias_restraint_k_moving::set_state_params(conf); + return error_code; +} + + +std::ostream & colvarbias_restraint_harmonic::write_traj_label(std::ostream &os) +{ + colvarbias_restraint::write_traj_label(os); + colvarbias_restraint_centers_moving::write_traj_label(os); + colvarbias_restraint_k_moving::write_traj_label(os); + return os; +} + + +std::ostream & colvarbias_restraint_harmonic::write_traj(std::ostream &os) +{ + colvarbias_restraint::write_traj(os); + colvarbias_restraint_centers_moving::write_traj(os); + colvarbias_restraint_k_moving::write_traj(os); + return os; +} + + +int colvarbias_restraint_harmonic::change_configuration(std::string const &conf) +{ + return colvarbias_restraint_centers::change_configuration(conf) | + colvarbias_restraint_k::change_configuration(conf); +} + + +cvm::real colvarbias_restraint_harmonic::energy_difference(std::string const &conf) +{ + cvm::real const old_bias_energy = bias_energy; + cvm::real const old_force_k = force_k; + std::vector const old_centers = colvar_centers; + + change_configuration(conf); + update(); + + cvm::real const result = (bias_energy - old_bias_energy); + + bias_energy = old_bias_energy; + force_k = old_force_k; + colvar_centers = old_centers; + + return result; +} + + + +colvarbias_restraint_harmonic_walls::colvarbias_restraint_harmonic_walls(char const *key) + : colvarbias(key), + colvarbias_restraint(key), + colvarbias_restraint_k(key), + colvarbias_restraint_moving(key), + colvarbias_restraint_k_moving(key) +{ +} + + +int colvarbias_restraint_harmonic_walls::init(std::string const &conf) +{ + colvarbias_restraint::init(conf); + colvarbias_restraint_moving::init(conf); + colvarbias_restraint_k_moving::init(conf); + + provide(f_cvb_scalar_variables); + enable(f_cvb_scalar_variables); + + size_t i; + + bool b_null_lower_walls = false; + if (lower_walls.size() == 0) { + b_null_lower_walls = true; + lower_walls.resize(number_of_colvars()); + for (i = 0; i < colvars.size(); i++) { + lower_walls[i].type(colvars[i]->value()); + lower_walls[i].reset(); + } + } + if (!get_keyval(conf, "lowerWalls", lower_walls, lower_walls) && + b_null_lower_walls) { + cvm::log("Lower walls were not provided.\n"); + lower_walls.resize(0); + } + + bool b_null_upper_walls = false; + if (upper_walls.size() == 0) { + b_null_upper_walls = true; + upper_walls.resize(number_of_colvars()); + for (i = 0; i < colvars.size(); i++) { + upper_walls[i].type(colvars[i]->value()); + upper_walls[i].reset(); + } + } + if (!get_keyval(conf, "upperWalls", upper_walls, upper_walls) && + b_null_upper_walls) { + cvm::log("Upper walls were not provided.\n"); + upper_walls.resize(0); + } + + if ((lower_walls.size() == 0) && (upper_walls.size() == 0)) { + cvm::error("Error: no walls provided.\n", INPUT_ERROR); + return INPUT_ERROR; + } + + if ((lower_walls.size() == 0) || (upper_walls.size() == 0)) { + for (i = 0; i < colvars.size(); i++) { + if (colvars[i]->is_enabled(f_cv_periodic)) { + cvm::error("Error: at least one variable is periodic, " + "both walls must be provided .\n", INPUT_ERROR); + return INPUT_ERROR; + } + } + } + + if ((lower_walls.size() > 0) && (upper_walls.size() > 0)) { + for (i = 0; i < colvars.size(); i++) { + if (lower_walls[i] >= upper_walls[i]) { + cvm::error("Error: one upper wall, "+ + cvm::to_str(upper_walls[i])+ + ", is not higher than the lower wall, "+ + cvm::to_str(lower_walls[i])+".\n", + INPUT_ERROR); + } + } + } + + for (i = 0; i < colvars.size(); i++) { + if (colvars[i]->width != 1.0) + cvm::log("The force constant for colvar \""+colvars[i]->name+ + "\" will be rescaled to "+ + cvm::to_str(force_k / (colvars[i]->width * colvars[i]->width))+ + " according to the specified width.\n"); + } + + return COLVARS_OK; +} + + +int colvarbias_restraint_harmonic_walls::update() +{ + colvarbias_restraint_k_moving::update(); + + colvarbias_restraint::update(); + + return COLVARS_OK; +} + + +void colvarbias_restraint_harmonic_walls::communicate_forces() +{ + for (size_t i = 0; i < colvars.size(); i++) { + if (cvm::debug()) { + cvm::log("Communicating a force to colvar \""+ + colvars[i]->name+"\".\n"); + } + colvars[i]->add_bias_force_actual_value(colvar_forces[i]); + } +} + + +cvm::real colvarbias_restraint_harmonic_walls::colvar_distance(size_t i) const +{ + colvar *cv = colvars[i]; + colvarvalue const &cvv = colvars[i]->actual_value(); + + // For a periodic colvar, both walls may be applicable at the same time + // in which case we pick the closer one + + if (cv->is_enabled(f_cv_periodic)) { + cvm::real const lower_wall_dist2 = cv->dist2(cvv, lower_walls[i]); + cvm::real const upper_wall_dist2 = cv->dist2(cvv, upper_walls[i]); + if (lower_wall_dist2 < upper_wall_dist2) { + cvm::real const grad = cv->dist2_lgrad(cvv, lower_walls[i]); + if (grad < 0.0) { return grad; } + } else { + cvm::real const grad = cv->dist2_lgrad(cvv, upper_walls[i]); + if (grad > 0.0) { return grad; } + } + return 0.0; + } + + if (lower_walls.size() > 0) { + cvm::real const grad = cv->dist2_lgrad(cvv, lower_walls[i]); + if (grad < 0.0) { return grad; } + } + if (upper_walls.size() > 0) { + cvm::real const grad = cv->dist2_lgrad(cvv, upper_walls[i]); + if (grad > 0.0) { return grad; } + } + return 0.0; +} + + +cvm::real colvarbias_restraint_harmonic_walls::restraint_potential(size_t i) const +{ + cvm::real const dist = colvar_distance(i); + return 0.5 * force_k / (colvars[i]->width * colvars[i]->width) * + dist * dist; +} + + +colvarvalue const colvarbias_restraint_harmonic_walls::restraint_force(size_t i) const +{ + cvm::real const dist = colvar_distance(i); + return -0.5 * force_k / (colvars[i]->width * colvars[i]->width) * + dist; +} + + +cvm::real colvarbias_restraint_harmonic_walls::d_restraint_potential_dk(size_t i) const +{ + cvm::real const dist = colvar_distance(i); + return 0.5 / (colvars[i]->width * colvars[i]->width) * + dist * dist; +} + + +std::string const colvarbias_restraint_harmonic_walls::get_state_params() const +{ + return colvarbias_restraint::get_state_params() + + colvarbias_restraint_k_moving::get_state_params(); +} + + +int colvarbias_restraint_harmonic_walls::set_state_params(std::string const &conf) +{ + int error_code = COLVARS_OK; + error_code |= colvarbias_restraint::set_state_params(conf); + error_code |= colvarbias_restraint_k_moving::set_state_params(conf); + return error_code; +} + + +std::ostream & colvarbias_restraint_harmonic_walls::write_traj_label(std::ostream &os) +{ + colvarbias_restraint::write_traj_label(os); + colvarbias_restraint_k_moving::write_traj_label(os); + return os; +} + + +std::ostream & colvarbias_restraint_harmonic_walls::write_traj(std::ostream &os) +{ + colvarbias_restraint::write_traj(os); + colvarbias_restraint_k_moving::write_traj(os); + return os; } colvarbias_restraint_linear::colvarbias_restraint_linear(char const *key) - : colvarbias_restraint(key) + : colvarbias(key), + colvarbias_restraint(key), + colvarbias_restraint_centers(key), + colvarbias_restraint_moving(key), + colvarbias_restraint_k(key), + colvarbias_restraint_centers_moving(key), + colvarbias_restraint_k_moving(key) { } @@ -576,38 +1050,118 @@ colvarbias_restraint_linear::colvarbias_restraint_linear(char const *key) int colvarbias_restraint_linear::init(std::string const &conf) { colvarbias_restraint::init(conf); + colvarbias_restraint_moving::init(conf); + colvarbias_restraint_centers_moving::init(conf); + colvarbias_restraint_k_moving::init(conf); for (size_t i = 0; i < colvars.size(); i++) { + if (colvars[i]->is_enabled(f_cv_periodic)) { + cvm::error("Error: linear biases cannot be applied to periodic variables.\n", + INPUT_ERROR); + return INPUT_ERROR; + } if (colvars[i]->width != 1.0) cvm::log("The force constant for colvar \""+colvars[i]->name+ "\" will be rescaled to "+ - cvm::to_str(restraint_convert_k(force_k, colvars[i]->width))+ + cvm::to_str(force_k / colvars[i]->width)+ " according to the specified width.\n"); } + return COLVARS_OK; } -cvm::real colvarbias_restraint_linear::restraint_potential(cvm::real k, - colvar const *x, - colvarvalue const &xcenter) const +int colvarbias_restraint_linear::update() { - return k * (x->value() - xcenter); + // update parameters (centers or force constant) + colvarbias_restraint_centers_moving::update(); + colvarbias_restraint_k_moving::update(); + + // update restraint energy and forces + colvarbias_restraint::update(); + + // update accumulated work using the current forces + colvarbias_restraint_centers_moving::update_acc_work(); + + return COLVARS_OK; } -colvarvalue colvarbias_restraint_linear::restraint_force(cvm::real k, - colvar const *x, - colvarvalue const &xcenter) const +int colvarbias_restraint_linear::change_configuration(std::string const &conf) { - return k; + // Only makes sense to change the force constant + return colvarbias_restraint_k::change_configuration(conf); } -cvm::real colvarbias_restraint_linear::restraint_convert_k(cvm::real k, - cvm::real dist_measure) const +cvm::real colvarbias_restraint_linear::energy_difference(std::string const &conf) { - return k / dist_measure; + cvm::real const old_bias_energy = bias_energy; + cvm::real const old_force_k = force_k; + + change_configuration(conf); + update(); + + cvm::real const result = (bias_energy - old_bias_energy); + + bias_energy = old_bias_energy; + force_k = old_force_k; + + return result; +} + + +cvm::real colvarbias_restraint_linear::restraint_potential(size_t i) const +{ + return force_k / colvars[i]->width * (colvars[i]->value() - colvar_centers[i]); +} + + +colvarvalue const colvarbias_restraint_linear::restraint_force(size_t i) const +{ + return -1.0 * force_k / colvars[i]->width; +} + + +cvm::real colvarbias_restraint_linear::d_restraint_potential_dk(size_t i) const +{ + return 1.0 / colvars[i]->width * (colvars[i]->value() - colvar_centers[i]); +} + + +std::string const colvarbias_restraint_linear::get_state_params() const +{ + return colvarbias_restraint::get_state_params() + + colvarbias_restraint_centers_moving::get_state_params() + + colvarbias_restraint_k_moving::get_state_params(); +} + + +int colvarbias_restraint_linear::set_state_params(std::string const &conf) +{ + int error_code = COLVARS_OK; + error_code |= colvarbias_restraint::set_state_params(conf); + error_code |= colvarbias_restraint_centers_moving::set_state_params(conf); + error_code |= colvarbias_restraint_k_moving::set_state_params(conf); + return error_code; +} + + +std::ostream & colvarbias_restraint_linear::write_traj_label(std::ostream &os) +{ + colvarbias_restraint::write_traj_label(os); + colvarbias_restraint_centers_moving::write_traj_label(os); + colvarbias_restraint_k_moving::write_traj_label(os); + return os; +} + + +std::ostream & colvarbias_restraint_linear::write_traj(std::ostream &os) +{ + colvarbias_restraint::write_traj(os); + colvarbias_restraint_centers_moving::write_traj(os); + colvarbias_restraint_k_moving::write_traj(os); + return os; } diff --git a/lib/colvars/colvarbias_restraint.h b/lib/colvars/colvarbias_restraint.h index 54097bd524..cbdd9c44d1 100644 --- a/lib/colvars/colvarbias_restraint.h +++ b/lib/colvars/colvarbias_restraint.h @@ -1,36 +1,43 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARBIAS_RESTRAINT_H #define COLVARBIAS_RESTRAINT_H #include "colvarbias.h" -/// \brief Bias restraint, optionally moving towards a target +/// \brief Most general definition of a colvar restraint: +/// see derived classes for specific types /// (implementation of \link colvarbias \endlink) -class colvarbias_restraint : public colvarbias { +class colvarbias_restraint + : public virtual colvarbias +{ public: /// Retrieve colvar values and calculate their biasing forces virtual int update(); - // TODO the following can be supplanted by a new call to init() /// Load new configuration - force constant and/or centers only - virtual void change_configuration(std::string const &conf); + virtual int change_configuration(std::string const &conf) { return COLVARS_NOT_IMPLEMENTED; } /// Calculate change in energy from using alternate configuration - virtual cvm::real energy_difference(std::string const &conf); + virtual cvm::real energy_difference(std::string const &conf) { return 0.0; } - /// Read the bias configuration from a restart file - virtual std::istream & read_restart(std::istream &is); + virtual std::string const get_state_params() const; + virtual int set_state_params(std::string const &conf); + // virtual std::ostream & write_state_data(std::ostream &os); + // virtual std::istream & read_state_data(std::istream &os); + virtual std::ostream & write_state(std::ostream &os); + virtual std::istream & read_state(std::istream &is); - /// Write the bias configuration to a restart file - virtual std::ostream & write_restart(std::ostream &os); - - /// Write a label to the trajectory file (comment line) virtual std::ostream & write_traj_label(std::ostream &os); - - /// Output quantities such as the bias energy to the trajectory file virtual std::ostream & write_traj(std::ostream &os); /// \brief Constructor @@ -42,26 +49,110 @@ public: protected: - /// \brief Potential function - virtual cvm::real restraint_potential(cvm::real k, colvar const *x, - colvarvalue const &xcenter) const = 0; + /// \brief Potential function for the i-th colvar + virtual cvm::real restraint_potential(size_t i) const = 0; - /// \brief Force function - virtual colvarvalue restraint_force(cvm::real k, colvar const *x, - colvarvalue const &xcenter) const = 0; + /// \brief Force function for the i-th colvar + virtual colvarvalue const restraint_force(size_t i) const = 0; - ///\brief Unit scaling - virtual cvm::real restraint_convert_k(cvm::real k, cvm::real dist_measure) const = 0; + /// \brief Derivative of the potential function with respect to the force constant + virtual cvm::real d_restraint_potential_dk(size_t i) const = 0; +}; + + +/// Definition and parsing of the restraint centers +class colvarbias_restraint_centers + : public virtual colvarbias_restraint +{ +public: + + colvarbias_restraint_centers(char const *key); + virtual int init(std::string const &conf); + virtual int change_configuration(std::string const &conf); + +protected: /// \brief Restraint centers std::vector colvar_centers; - /// \brief Restraint centers without wrapping or constraints applied + /// \brief Restraint centers outside the domain of the colvars (no wrapping or constraints applied) std::vector colvar_centers_raw; +}; + + +/// Definition and parsing of the force constant +class colvarbias_restraint_k + : public virtual colvarbias_restraint +{ +public: + + colvarbias_restraint_k(char const *key); + virtual int init(std::string const &conf); + virtual int change_configuration(std::string const &conf); + +protected: + /// \brief Restraint force constant + cvm::real force_k; +}; + + +/// Options to change the restraint configuration over time (shared between centers and k moving) +class colvarbias_restraint_moving + : public virtual colvarparse { +public: + + colvarbias_restraint_moving(char const *key); + // Note: despite the diamond inheritance, most of this function gets only executed once + virtual int init(std::string const &conf); + virtual int update() { return COLVARS_OK; } + virtual int change_configuration(std::string const &conf) { return COLVARS_NOT_IMPLEMENTED; } + + virtual std::string const get_state_params() const; + virtual int set_state_params(std::string const &conf); + +protected: /// \brief Moving target? bool b_chg_centers; + /// \brief Changing force constant? + bool b_chg_force_k; + + /// \brief Number of stages over which to perform the change + /// If zero, perform a continuous change + int target_nstages; + + /// \brief Number of current stage of the perturbation + int stage; + + /// \brief Lambda-schedule for custom varying force constant + std::vector lambda_schedule; + + /// \brief Number of steps required to reach the target force constant + /// or restraint centers + long target_nsteps; +}; + + +/// Options to change the restraint centers over time +class colvarbias_restraint_centers_moving + : public virtual colvarbias_restraint_centers, + public virtual colvarbias_restraint_moving +{ +public: + + colvarbias_restraint_centers_moving(char const *key); + virtual int init(std::string const &conf); + virtual int update(); + virtual int change_configuration(std::string const &conf) { return COLVARS_NOT_IMPLEMENTED; } + + virtual std::string const get_state_params() const; + virtual int set_state_params(std::string const &conf); + virtual std::ostream & write_traj_label(std::ostream &os); + virtual std::ostream & write_traj(std::ostream &os); + +protected: + /// \brief New restraint centers std::vector target_centers; @@ -78,11 +169,29 @@ protected: /// \brief Accumulated work cvm::real acc_work; - /// \brief Restraint force constant - cvm::real force_k; + /// Update the accumulated work + int update_acc_work(); +}; - /// \brief Changing force constant? - bool b_chg_force_k; + +/// Options to change the restraint force constant over time +class colvarbias_restraint_k_moving + : public virtual colvarbias_restraint_k, + public virtual colvarbias_restraint_moving +{ +public: + + colvarbias_restraint_k_moving(char const *key); + virtual int init(std::string const &conf); + virtual int update(); + virtual int change_configuration(std::string const &conf) { return COLVARS_NOT_IMPLEMENTED; } + + virtual std::string const get_state_params() const; + virtual int set_state_params(std::string const &conf); + virtual std::ostream & write_traj_label(std::ostream &os); + virtual std::ostream & write_traj(std::ostream &os); + +protected: /// \brief Restraint force constant (target value) cvm::real target_force_k; @@ -90,9 +199,6 @@ protected: /// \brief Restraint force constant (starting value) cvm::real starting_force_k; - /// \brief Lambda-schedule for custom varying force constant - std::vector lambda_schedule; - /// \brief Exponent for varying the force constant cvm::real force_k_exp; @@ -100,71 +206,91 @@ protected: /// (in TI, would be the accumulating FE derivative) cvm::real restraint_FE; - /// \brief Equilibration steps for restraint FE calculation through TI cvm::real target_equil_steps; - - /// \brief Number of stages over which to perform the change - /// If zero, perform a continuous change - int target_nstages; - - /// \brief Number of current stage of the perturbation - int stage; - - /// \brief Number of steps required to reach the target force constant - /// or restraint centers - long target_nsteps; }; /// \brief Harmonic bias restraint /// (implementation of \link colvarbias_restraint \endlink) -class colvarbias_restraint_harmonic : public colvarbias_restraint { - +class colvarbias_restraint_harmonic + : public colvarbias_restraint_centers_moving, + public colvarbias_restraint_k_moving +{ public: - colvarbias_restraint_harmonic(char const *key); virtual int init(std::string const &conf); - // no additional members, destructor not needed + virtual int update(); + virtual std::string const get_state_params() const; + virtual int set_state_params(std::string const &conf); + virtual std::ostream & write_traj_label(std::ostream &os); + virtual std::ostream & write_traj(std::ostream &os); + virtual int change_configuration(std::string const &conf); + virtual cvm::real energy_difference(std::string const &conf); protected: - /// \brief Potential function - virtual cvm::real restraint_potential(cvm::real k, colvar const *x, - colvarvalue const &xcenter) const; + virtual cvm::real restraint_potential(size_t i) const; + virtual colvarvalue const restraint_force(size_t i) const; + virtual cvm::real d_restraint_potential_dk(size_t i) const; +}; - /// \brief Force function - virtual colvarvalue restraint_force(cvm::real k, colvar const *x, - colvarvalue const &xcenter) const; - ///\brief Unit scaling - virtual cvm::real restraint_convert_k(cvm::real k, cvm::real dist_measure) const; +/// \brief Wall restraint +/// (implementation of \link colvarbias_restraint \endlink) +class colvarbias_restraint_harmonic_walls + : public colvarbias_restraint_k_moving +{ +public: + colvarbias_restraint_harmonic_walls(char const *key); + virtual int init(std::string const &conf); + virtual int update(); + virtual void communicate_forces(); + virtual std::string const get_state_params() const; + virtual int set_state_params(std::string const &conf); + virtual std::ostream & write_traj_label(std::ostream &os); + virtual std::ostream & write_traj(std::ostream &os); + +protected: + + /// \brief Location of the lower walls + std::vector lower_walls; + + /// \brief Location of the upper walls + std::vector upper_walls; + + virtual cvm::real colvar_distance(size_t i) const; + virtual cvm::real restraint_potential(size_t i) const; + virtual colvarvalue const restraint_force(size_t i) const; + virtual cvm::real d_restraint_potential_dk(size_t i) const; }; /// \brief Linear bias restraint /// (implementation of \link colvarbias_restraint \endlink) -class colvarbias_restraint_linear : public colvarbias_restraint { +class colvarbias_restraint_linear + : public colvarbias_restraint_centers_moving, + public colvarbias_restraint_k_moving +{ public: colvarbias_restraint_linear(char const *key); virtual int init(std::string const &conf); - // no additional members, destructor not needed + virtual int update(); + virtual int change_configuration(std::string const &conf); + virtual cvm::real energy_difference(std::string const &conf); + + virtual std::string const get_state_params() const; + virtual int set_state_params(std::string const &conf); + virtual std::ostream & write_traj_label(std::ostream &os); + virtual std::ostream & write_traj(std::ostream &os); protected: - /// \brief Potential function - virtual cvm::real restraint_potential(cvm::real k, colvar const *x, - colvarvalue const &xcenter) const; - - /// \brief Force function - virtual colvarvalue restraint_force(cvm::real k, colvar const *x, - colvarvalue const &xcenter) const; - - ///\brief Unit scaling - virtual cvm::real restraint_convert_k(cvm::real k, cvm::real dist_measure) const; - + virtual cvm::real restraint_potential(size_t i) const; + virtual colvarvalue const restraint_force(size_t i) const; + virtual cvm::real d_restraint_potential_dk(size_t i) const; }; diff --git a/lib/colvars/colvarcomp.cpp b/lib/colvars/colvarcomp.cpp index 050e03f78e..d99da56386 100644 --- a/lib/colvars/colvarcomp.cpp +++ b/lib/colvars/colvarcomp.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include "colvarmodule.h" #include "colvarvalue.h" #include "colvar.h" @@ -154,15 +161,17 @@ void colvar::cvc::read_data() void colvar::cvc::calc_force_invgrads() { - cvm::fatal_error("Error: calculation of inverse gradients is not implemented " - "for colvar components of type \""+function_type+"\".\n"); + cvm::error("Error: calculation of inverse gradients is not implemented " + "for colvar components of type \""+function_type+"\".\n", + COLVARS_NOT_IMPLEMENTED); } void colvar::cvc::calc_Jacobian_derivative() { - cvm::fatal_error("Error: calculation of inverse gradients is not implemented " - "for colvar components of type \""+function_type+"\".\n"); + cvm::error("Error: calculation of inverse gradients is not implemented " + "for colvar components of type \""+function_type+"\".\n", + COLVARS_NOT_IMPLEMENTED); } @@ -281,6 +290,33 @@ void colvar::cvc::debug_gradients(cvm::atom_group *group) } +cvm::real colvar::cvc::dist2(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return x1.dist2(x2); +} + + +colvarvalue colvar::cvc::dist2_lgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return x1.dist2_grad(x2); +} + + +colvarvalue colvar::cvc::dist2_rgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return x2.dist2_grad(x1); +} + + +void colvar::cvc::wrap(colvarvalue &x) const +{ + return; +} + + // Static members std::vector colvar::cvc::cvc_features; diff --git a/lib/colvars/colvarcomp.h b/lib/colvars/colvarcomp.h index 0649895e45..a230cae8a9 100644 --- a/lib/colvars/colvarcomp.h +++ b/lib/colvars/colvarcomp.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARCOMP_H #define COLVARCOMP_H @@ -105,8 +112,8 @@ public: /// options from the provided configuration string /// Returns reference to new group cvm::atom_group *parse_group(std::string const &conf, - char const *group_key, - bool optional = false); + char const *group_key, + bool optional = false); /// \brief Parse options pertaining to total force calculation virtual int init_total_force_params(std::string const &conf); @@ -130,7 +137,7 @@ public: } /// \brief Obtain data needed for the calculation for the backend - void read_data(); + virtual void read_data(); /// \brief Calculate the variable virtual void calc_value() = 0; @@ -151,17 +158,14 @@ public: /// \brief Return the previously calculated value - virtual colvarvalue const & value() const; - - // /// \brief Return const pointer to the previously calculated value - // virtual const colvarvalue *p_value() const; + colvarvalue const & value() const; /// \brief Return the previously calculated total force - virtual colvarvalue const & total_force() const; + colvarvalue const & total_force() const; /// \brief Return the previously calculated divergence of the /// inverse atomic gradients - virtual colvarvalue const & Jacobian_derivative() const; + colvarvalue const & Jacobian_derivative() const; /// \brief Apply the collective variable force, by communicating the /// atomic forces to the simulation program (\b Note: the \link ft @@ -247,52 +251,24 @@ protected: }; - - inline colvarvalue const & colvar::cvc::value() const { return x; } -// inline const colvarvalue * colvar::cvc::p_value() const -// { -// return &x; -// } inline colvarvalue const & colvar::cvc::total_force() const { return ft; } + inline colvarvalue const & colvar::cvc::Jacobian_derivative() const { return jd; } -inline cvm::real colvar::cvc::dist2(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return x1.dist2(x2); -} - -inline colvarvalue colvar::cvc::dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return x1.dist2_grad(x2); -} - -inline colvarvalue colvar::cvc::dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return x2.dist2_grad(x1); -} - -inline void colvar::cvc::wrap(colvarvalue &x) const -{ - return; -} - /// \brief Colvar component: distance between the centers of mass of /// two groups (colvarvalue::type_scalar type, range [0:*)) @@ -312,7 +288,7 @@ protected: public: distance(std::string const &conf); distance(); - virtual inline ~distance() {} + virtual ~distance() {} virtual void calc_value(); virtual void calc_gradients(); virtual void calc_force_invgrads(); @@ -327,6 +303,7 @@ public: }; + // \brief Colvar component: distance vector between centers of mass // of two groups (\link colvarvalue::type_3vector \endlink type, // range (-*:*)x(-*:*)x(-*:*)) @@ -336,7 +313,7 @@ class colvar::distance_vec public: distance_vec(std::string const &conf); distance_vec(); - virtual inline ~distance_vec() {} + virtual ~distance_vec() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -352,6 +329,7 @@ public: }; + /// \brief Colvar component: distance unit vector (direction) between /// centers of mass of two groups (colvarvalue::type_unit3vector type, /// range [-1:1]x[-1:1]x[-1:1]) @@ -361,19 +339,14 @@ class colvar::distance_dir public: distance_dir(std::string const &conf); distance_dir(); - virtual inline ~distance_dir() {} + virtual ~distance_dir() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); - virtual cvm::real dist2(colvarvalue const &x1, - colvarvalue const &x2) const; - virtual colvarvalue dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const; - virtual colvarvalue dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const; }; + /// \brief Colvar component: projection of the distance vector along /// an axis(colvarvalue::type_scalar type, range (-*:*)) class colvar::distance_z @@ -399,7 +372,7 @@ protected: public: distance_z(std::string const &conf); distance_z(); - virtual inline ~distance_z() {} + virtual ~distance_z() {} virtual void calc_value(); virtual void calc_gradients(); virtual void calc_force_invgrads(); @@ -416,6 +389,7 @@ public: }; + /// \brief Colvar component: projection of the distance vector on a /// plane (colvarvalue::type_scalar type, range [0:*)) class colvar::distance_xy @@ -429,7 +403,7 @@ protected: public: distance_xy(std::string const &conf); distance_xy(); - virtual inline ~distance_xy() {} + virtual ~distance_xy() {} virtual void calc_value(); virtual void calc_gradients(); virtual void calc_force_invgrads(); @@ -444,6 +418,7 @@ public: }; + /// \brief Colvar component: average distance between two groups of atoms, weighted as the sixth power, /// as in NMR refinements(colvarvalue::type_scalar type, range (0:*)) class colvar::distance_inv @@ -455,7 +430,7 @@ protected: public: distance_inv(std::string const &conf); distance_inv(); - virtual inline ~distance_inv() {} + virtual ~distance_inv() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -468,6 +443,7 @@ public: }; + /// \brief Colvar component: N1xN2 vector of pairwise distances /// (colvarvalue::type_vector type, range (0:*) for each component) class colvar::distance_pairs @@ -483,16 +459,10 @@ protected: public: distance_pairs(std::string const &conf); distance_pairs(); - virtual inline ~distance_pairs() {} + virtual ~distance_pairs() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); - virtual cvm::real dist2(colvarvalue const &x1, - colvarvalue const &x2) const; - virtual colvarvalue dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const; - virtual colvarvalue dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const; }; @@ -509,7 +479,7 @@ public: /// Constructor gyration(std::string const &conf); gyration(); - virtual inline ~gyration() {} + virtual ~gyration() {} virtual void calc_value(); virtual void calc_gradients(); virtual void calc_force_invgrads(); @@ -524,6 +494,7 @@ public: }; + /// \brief Colvar component: moment of inertia of an atom group /// (colvarvalue::type_scalar type, range [0:*)) class colvar::inertia @@ -533,7 +504,7 @@ public: /// Constructor inertia(std::string const &conf); inertia(); - virtual inline ~inertia() {} + virtual ~inertia() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -546,6 +517,7 @@ public: }; + /// \brief Colvar component: moment of inertia of an atom group /// around a user-defined axis (colvarvalue::type_scalar type, range [0:*)) class colvar::inertia_z @@ -558,7 +530,7 @@ public: /// Constructor inertia_z(std::string const &conf); inertia_z(); - virtual inline ~inertia_z() {} + virtual ~inertia_z() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -571,6 +543,7 @@ public: }; + /// \brief Colvar component: projection of 3N coordinates onto an /// eigenvector(colvarvalue::type_scalar type, range (-*:*)) class colvar::eigenvector @@ -597,7 +570,7 @@ public: /// Constructor eigenvector(std::string const &conf); - virtual inline ~eigenvector() {} + virtual ~eigenvector() {} virtual void calc_value(); virtual void calc_gradients(); virtual void calc_force_invgrads(); @@ -645,7 +618,7 @@ public: /// \brief Initialize the three groups after three atoms angle(cvm::atom const &a1, cvm::atom const &a2, cvm::atom const &a3); angle(); - virtual inline ~angle() {} + virtual ~angle() {} virtual void calc_value(); virtual void calc_gradients(); virtual void calc_force_invgrads(); @@ -659,6 +632,8 @@ public: colvarvalue const &x2) const; }; + + /// \brief Colvar component: angle between the dipole of a molecule and an axis /// formed by two groups of atoms(colvarvalue::type_scalar type, range [0:PI]) class colvar::dipole_angle @@ -691,7 +666,7 @@ public: /// \brief Initialize the three groups after three atoms dipole_angle (cvm::atom const &a1, cvm::atom const &a2, cvm::atom const &a3); dipole_angle(); - virtual inline ~dipole_angle() {} + virtual ~dipole_angle() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force (colvarvalue const &force); @@ -703,6 +678,8 @@ public: colvarvalue const &x2) const; }; + + /// \brief Colvar component: dihedral between the centers of mass of /// four groups (colvarvalue::type_scalar type, range [-PI:PI]) class colvar::dihedral @@ -732,7 +709,7 @@ public: /// \brief Initialize the four groups after four atoms dihedral(cvm::atom const &a1, cvm::atom const &a2, cvm::atom const &a3, cvm::atom const &a4); dihedral(); - virtual inline ~dihedral() {} + virtual ~dihedral() {} virtual void calc_value(); virtual void calc_gradients(); virtual void calc_force_invgrads(); @@ -753,6 +730,7 @@ public: }; + /// \brief Colvar component: coordination number between two groups /// (colvarvalue::type_scalar type, range [0:N1*N2]) class colvar::coordnum @@ -781,7 +759,7 @@ public: /// Constructor coordnum(std::string const &conf); coordnum(); - virtual inline ~coordnum() {} + virtual ~coordnum() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -812,6 +790,8 @@ public: colvarvalue const &x2) const; }; + + /// \brief Colvar component: self-coordination number within a group /// (colvarvalue::type_scalar type, range [0:N*(N-1)/2]) class colvar::selfcoordnum @@ -830,7 +810,7 @@ public: /// Constructor selfcoordnum(std::string const &conf); selfcoordnum(); - virtual inline ~selfcoordnum() {} + virtual ~selfcoordnum() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -852,6 +832,7 @@ public: }; + /// \brief Colvar component: coordination number between two groups /// (colvarvalue::type_scalar type, range [0:N1*N2]) class colvar::groupcoordnum @@ -873,7 +854,7 @@ public: /// Constructor groupcoordnum(std::string const &conf); groupcoordnum(); - virtual inline ~groupcoordnum() {} + virtual ~groupcoordnum() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -896,6 +877,7 @@ public: static cvm::real switching_function(cvm::rvector const &r0_vec, int const &exp_num, int const &exp_den, cvm::atom &A1, cvm::atom &A2); + */ virtual cvm::real dist2(colvarvalue const &x1, colvarvalue const &x2) const; @@ -903,10 +885,10 @@ public: colvarvalue const &x2) const; virtual colvarvalue dist2_rgrad(colvarvalue const &x1, colvarvalue const &x2) const; - */ }; + /// \brief Colvar component: hydrogen bond, defined as the product of /// a colvar::coordnum and 1/2*(1-cos((180-ang)/ang_tol)) /// (colvarvalue::type_scalar type, range [0:1]) @@ -941,6 +923,7 @@ public: }; + /// \brief Colvar component: alpha helix content of a contiguous /// segment of 5 or more residues, implemented as a sum of phi/psi /// dihedral angles and hydrogen bonds (colvarvalue::type_scalar type, @@ -969,7 +952,7 @@ public: // alpha_dihedrals (std::string const &conf); // alpha_dihedrals(); -// virtual inline ~alpha_dihedrals() {} +// virtual ~alpha_dihedrals() {} // virtual void calc_value(); // virtual void calc_gradients(); // virtual void apply_force (colvarvalue const &force); @@ -982,6 +965,7 @@ public: // }; + /// \brief Colvar component: alpha helix content of a contiguous /// segment of 5 or more residues, implemented as a sum of Ca-Ca-Ca /// angles and hydrogen bonds (colvarvalue::type_scalar type, range @@ -1022,6 +1006,8 @@ public: colvarvalue const &x2) const; }; + + /// \brief Colvar component: dihedPC /// Projection of the config onto a dihedral principal component /// See e.g. Altis et al., J. Chem. Phys 126, 244111 (2007) @@ -1050,6 +1036,8 @@ public: colvarvalue const &x2) const; }; + + /// \brief Colvar component: orientation in space of an atom group, /// with respect to a set of reference coordinates /// (colvarvalue::type_quaternion type, range @@ -1078,7 +1066,7 @@ public: orientation(std::string const &conf); orientation(); - virtual inline ~orientation() {} + virtual ~orientation() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -1091,6 +1079,7 @@ public: }; + /// \brief Colvar component: angle of rotation with respect to a set /// of reference coordinates (colvarvalue::type_scalar type, range /// [0:PI)) @@ -1101,7 +1090,7 @@ public: orientation_angle(std::string const &conf); orientation_angle(); - virtual inline ~orientation_angle() {} + virtual ~orientation_angle() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -1114,6 +1103,7 @@ public: }; + /// \brief Colvar component: cosine of the angle of rotation with respect to a set /// of reference coordinates (colvarvalue::type_scalar type, range /// [-1:1]) @@ -1124,7 +1114,7 @@ public: orientation_proj(std::string const &conf); orientation_proj(); - virtual inline ~orientation_proj() {} + virtual ~orientation_proj() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -1137,6 +1127,7 @@ public: }; + /// \brief Colvar component: projection of the orientation vector onto /// a predefined axis (colvarvalue::type_scalar type, range [-1:1]) class colvar::tilt @@ -1150,7 +1141,7 @@ public: tilt(std::string const &conf); tilt(); - virtual inline ~tilt() {} + virtual ~tilt() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -1177,7 +1168,7 @@ public: spin_angle(std::string const &conf); spin_angle(); - virtual inline ~spin_angle() {} + virtual ~spin_angle() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -1215,7 +1206,7 @@ public: /// Constructor rmsd(std::string const &conf); - virtual inline ~rmsd() {} + virtual ~rmsd() {} virtual void calc_value(); virtual void calc_gradients(); virtual void calc_force_invgrads(); @@ -1230,6 +1221,7 @@ public: }; + // \brief Colvar component: flat vector of Cartesian coordinates // Mostly useful to compute scripted colvar values class colvar::cartesian @@ -1243,7 +1235,7 @@ protected: public: cartesian(std::string const &conf); cartesian(); - virtual inline ~cartesian() {} + virtual ~cartesian() {} virtual void calc_value(); virtual void calc_gradients(); virtual void apply_force(colvarvalue const &force); @@ -1260,255 +1252,26 @@ public: #define simple_scalar_dist_functions(TYPE) \ \ - inline cvm::real colvar::TYPE::dist2(colvarvalue const &x1, \ - colvarvalue const &x2) const \ + \ + cvm::real colvar::TYPE::dist2(colvarvalue const &x1, \ + colvarvalue const &x2) const \ { \ return (x1.real_value - x2.real_value)*(x1.real_value - x2.real_value); \ } \ \ - inline colvarvalue colvar::TYPE::dist2_lgrad(colvarvalue const &x1, \ - colvarvalue const &x2) const \ + \ + colvarvalue colvar::TYPE::dist2_lgrad(colvarvalue const &x1, \ + colvarvalue const &x2) const \ { \ return 2.0 * (x1.real_value - x2.real_value); \ } \ \ - inline colvarvalue colvar::TYPE::dist2_rgrad(colvarvalue const &x1, \ - colvarvalue const &x2) const \ + \ + colvarvalue colvar::TYPE::dist2_rgrad(colvarvalue const &x1, \ + colvarvalue const &x2) const \ { \ return this->dist2_lgrad(x2, x1); \ } \ \ -simple_scalar_dist_functions(distance) -// NOTE: distance_z has explicit functions, see below -simple_scalar_dist_functions(distance_xy) -simple_scalar_dist_functions(distance_inv) -simple_scalar_dist_functions(angle) -simple_scalar_dist_functions(dipole_angle) -simple_scalar_dist_functions(coordnum) -simple_scalar_dist_functions(selfcoordnum) -simple_scalar_dist_functions(h_bond) -simple_scalar_dist_functions(gyration) -simple_scalar_dist_functions(inertia) -simple_scalar_dist_functions(inertia_z) -simple_scalar_dist_functions(rmsd) -simple_scalar_dist_functions(orientation_angle) -simple_scalar_dist_functions(orientation_proj) -simple_scalar_dist_functions(tilt) -simple_scalar_dist_functions(eigenvector) -// simple_scalar_dist_functions (alpha_dihedrals) -simple_scalar_dist_functions(alpha_angles) -simple_scalar_dist_functions(dihedPC) - - -// metrics functions for cvc implementations with a periodicity - -inline cvm::real colvar::dihedral::dist2(colvarvalue const &x1, - colvarvalue const &x2) const -{ -cvm::real diff = x1.real_value - x2.real_value; -diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); -return diff * diff; -} - -inline colvarvalue colvar::dihedral::dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ -cvm::real diff = x1.real_value - x2.real_value; -diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); -return 2.0 * diff; -} - -inline colvarvalue colvar::dihedral::dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ -cvm::real diff = x1.real_value - x2.real_value; -diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); -return (-2.0) * diff; -} - -inline void colvar::dihedral::wrap(colvarvalue &x) const -{ -if ((x.real_value - wrap_center) >= 180.0) { -x.real_value -= 360.0; -return; -} - -if ((x.real_value - wrap_center) < -180.0) { -x.real_value += 360.0; -return; -} - -return; -} - -inline cvm::real colvar::spin_angle::dist2(colvarvalue const &x1, - colvarvalue const &x2) const -{ -cvm::real diff = x1.real_value - x2.real_value; -diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); -return diff * diff; -} - -inline colvarvalue colvar::spin_angle::dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ -cvm::real diff = x1.real_value - x2.real_value; -diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); -return 2.0 * diff; -} - -inline colvarvalue colvar::spin_angle::dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ -cvm::real diff = x1.real_value - x2.real_value; -diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); -return (-2.0) * diff; -} - -inline void colvar::spin_angle::wrap(colvarvalue &x) const -{ -if ((x.real_value - wrap_center) >= 180.0) { -x.real_value -= 360.0; -return; -} - -if ((x.real_value - wrap_center) < -180.0) { -x.real_value += 360.0; -return; -} - -return; -} - - -// Projected distance -// Differences should always be wrapped around 0 (ignoring wrap_center) -inline cvm::real colvar::distance_z::dist2(colvarvalue const &x1, - colvarvalue const &x2) const -{ - cvm::real diff = x1.real_value - x2.real_value; - if (period != 0.0) { - cvm::real shift = std::floor(diff/period + 0.5); - diff -= shift * period; - } - return diff * diff; -} - -inline colvarvalue colvar::distance_z::dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - cvm::real diff = x1.real_value - x2.real_value; - if (period != 0.0) { - cvm::real shift = std::floor(diff/period + 0.5); - diff -= shift * period; - } - return 2.0 * diff; -} - -inline colvarvalue colvar::distance_z::dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - cvm::real diff = x1.real_value - x2.real_value; - if (period != 0.0) { - cvm::real shift = std::floor(diff/period + 0.5); - diff -= shift * period; - } - return (-2.0) * diff; -} - -inline void colvar::distance_z::wrap(colvarvalue &x) const -{ - if (! this->b_periodic) { - // don't wrap if the period has not been set - return; - } - - cvm::real shift = std::floor((x.real_value - wrap_center) / period + 0.5); - x.real_value -= shift * period; - return; -} - - -// distance between three dimensional vectors -// -// TODO apply PBC to distance_vec -// Note: differences should be centered around (0, 0, 0)! - -inline cvm::real colvar::distance_vec::dist2(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return cvm::position_dist2(x1.rvector_value, x2.rvector_value); -} - -inline colvarvalue colvar::distance_vec::dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return 2.0 * cvm::position_distance(x2.rvector_value, x1.rvector_value); -} - -inline colvarvalue colvar::distance_vec::dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return 2.0 * cvm::position_distance(x2.rvector_value, x1.rvector_value); -} - -inline cvm::real colvar::distance_dir::dist2(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return (x1.rvector_value - x2.rvector_value).norm2(); -} - -inline colvarvalue colvar::distance_dir::dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return colvarvalue((x1.rvector_value - x2.rvector_value), colvarvalue::type_unit3vector); -} - -inline colvarvalue colvar::distance_dir::dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return colvarvalue((x2.rvector_value - x1.rvector_value), colvarvalue::type_unit3vector); -} - -inline cvm::real colvar::distance_pairs::dist2(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return (x1.vector1d_value - x2.vector1d_value).norm2(); -} - -inline colvarvalue colvar::distance_pairs::dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return colvarvalue((x1.vector1d_value - x2.vector1d_value), colvarvalue::type_vector); -} - -inline colvarvalue colvar::distance_pairs::dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return colvarvalue((x2.vector1d_value - x1.vector1d_value), colvarvalue::type_vector); -} - - -// distance between quaternions - -inline cvm::real colvar::orientation::dist2(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return x1.quaternion_value.dist2(x2); -} - -inline colvarvalue colvar::orientation::dist2_lgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return x1.quaternion_value.dist2_grad(x2); -} - -inline colvarvalue colvar::orientation::dist2_rgrad(colvarvalue const &x1, - colvarvalue const &x2) const -{ - return x2.quaternion_value.dist2_grad(x1); -} - - #endif diff --git a/lib/colvars/colvarcomp_angles.cpp b/lib/colvars/colvarcomp_angles.cpp index 6b05fb16eb..4c3390a8bd 100644 --- a/lib/colvars/colvarcomp_angles.cpp +++ b/lib/colvars/colvarcomp_angles.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include "colvarmodule.h" #include "colvar.h" #include "colvarcomp.h" @@ -7,6 +14,7 @@ #include + colvar::angle::angle(std::string const &conf) : cvc(conf) { @@ -85,6 +93,7 @@ void colvar::angle::calc_gradients() group3->set_weighted_gradient(dxdr3); } + void colvar::angle::calc_force_invgrads() { // This uses a force measurement on groups 1 and 3 only @@ -107,6 +116,7 @@ void colvar::angle::calc_force_invgrads() return; } + void colvar::angle::calc_Jacobian_derivative() { // det(J) = (2 pi) r^2 * sin(theta) @@ -129,6 +139,8 @@ void colvar::angle::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(angle) + colvar::dipole_angle::dipole_angle(std::string const &conf) @@ -235,6 +247,8 @@ void colvar::dipole_angle::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(dipole_angle) + colvar::dihedral::dihedral(std::string const &conf) @@ -453,3 +467,46 @@ void colvar::dihedral::apply_force(colvarvalue const &force) } +// metrics functions for cvc implementations with a periodicity + +cvm::real colvar::dihedral::dist2(colvarvalue const &x1, + colvarvalue const &x2) const +{ + cvm::real diff = x1.real_value - x2.real_value; + diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); + return diff * diff; +} + + +colvarvalue colvar::dihedral::dist2_lgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + cvm::real diff = x1.real_value - x2.real_value; + diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); + return 2.0 * diff; +} + + +colvarvalue colvar::dihedral::dist2_rgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + cvm::real diff = x1.real_value - x2.real_value; + diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); + return (-2.0) * diff; +} + + +void colvar::dihedral::wrap(colvarvalue &x) const +{ + if ((x.real_value - wrap_center) >= 180.0) { + x.real_value -= 360.0; + return; + } + + if ((x.real_value - wrap_center) < -180.0) { + x.real_value += 360.0; + return; + } + + return; +} diff --git a/lib/colvars/colvarcomp_coordnums.cpp b/lib/colvars/colvarcomp_coordnums.cpp index d5e87e6b1e..987a16a816 100644 --- a/lib/colvars/colvarcomp_coordnums.cpp +++ b/lib/colvars/colvarcomp_coordnums.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include "colvarmodule.h" @@ -13,10 +20,10 @@ template cvm::real colvar::coordnum::switching_function(cvm::real const &r0, - int const &en, - int const &ed, - cvm::atom &A1, - cvm::atom &A2) + int const &en, + int const &ed, + cvm::atom &A1, + cvm::atom &A2) { cvm::rvector const diff = cvm::position_distance(A1.pos, A2.pos); cvm::real const l2 = diff.norm2()/(r0*r0); @@ -42,10 +49,10 @@ cvm::real colvar::coordnum::switching_function(cvm::real const &r0, template cvm::real colvar::coordnum::switching_function(cvm::rvector const &r0_vec, - int const &en, - int const &ed, - cvm::atom &A1, - cvm::atom &A2) + int const &en, + int const &ed, + cvm::atom &A1, + cvm::atom &A2) { cvm::rvector const diff = cvm::position_distance(A1.pos, A2.pos); cvm::rvector const scal_diff(diff.x/r0_vec.x, diff.y/r0_vec.y, diff.z/r0_vec.z); @@ -190,6 +197,7 @@ void colvar::coordnum::calc_gradients() } } + void colvar::coordnum::apply_force(colvarvalue const &force) { if (!group1->noforce) @@ -200,6 +208,9 @@ void colvar::coordnum::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(coordnum) + + // h_bond member functions @@ -252,6 +263,7 @@ colvar::h_bond::h_bond(cvm::atom const &acceptor, atom_groups[0]->add_atom(donor); } + colvar::h_bond::h_bond() : cvc() { @@ -284,6 +296,8 @@ void colvar::h_bond::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(h_bond) + colvar::selfcoordnum::selfcoordnum(std::string const &conf) @@ -339,6 +353,9 @@ void colvar::selfcoordnum::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(selfcoordnum) + + // groupcoordnum member functions colvar::groupcoordnum::groupcoordnum(std::string const &conf) : distance(conf), b_anisotropic(false) @@ -448,7 +465,6 @@ cvm::real colvar::groupcoordnum::switching_function(cvm::rvector const &r0_vec, #endif - void colvar::groupcoordnum::calc_value() { @@ -460,7 +476,6 @@ void colvar::groupcoordnum::calc_value() x.real_value = coordnum::switching_function(r0, en, ed, group1_com_atom, group2_com_atom); - } @@ -486,3 +501,6 @@ void colvar::groupcoordnum::apply_force(colvarvalue const &force) if (!group2->noforce) group2->apply_colvar_force(force.real_value); } + + +simple_scalar_dist_functions(groupcoordnum) diff --git a/lib/colvars/colvarcomp_distances.cpp b/lib/colvars/colvarcomp_distances.cpp index 15693778b2..7481dd360b 100644 --- a/lib/colvars/colvarcomp_distances.cpp +++ b/lib/colvars/colvarcomp_distances.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include "colvarmodule.h" @@ -91,6 +98,9 @@ void colvar::distance::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(distance) + + colvar::distance_vec::distance_vec(std::string const &conf) : distance(conf) @@ -138,6 +148,27 @@ void colvar::distance_vec::apply_force(colvarvalue const &force) } +cvm::real colvar::distance_vec::dist2(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return cvm::position_dist2(x1.rvector_value, x2.rvector_value); +} + + +colvarvalue colvar::distance_vec::dist2_lgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return 2.0 * cvm::position_distance(x2.rvector_value, x1.rvector_value); +} + + +colvarvalue colvar::distance_vec::dist2_rgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return 2.0 * cvm::position_distance(x2.rvector_value, x1.rvector_value); +} + + colvar::distance_z::distance_z(std::string const &conf) : cvc(conf) @@ -191,6 +222,7 @@ colvar::distance_z::distance_z(std::string const &conf) } + colvar::distance_z::distance_z() { function_type = "distance_z"; @@ -200,6 +232,7 @@ colvar::distance_z::distance_z() x.type(colvarvalue::type_scalar); } + void colvar::distance_z::calc_value() { if (fixed_axis) { @@ -227,6 +260,7 @@ void colvar::distance_z::calc_value() this->wrap(x); } + void colvar::distance_z::calc_gradients() { main->set_weighted_gradient( axis ); @@ -248,6 +282,7 @@ void colvar::distance_z::calc_gradients() } } + void colvar::distance_z::calc_force_invgrads() { main->read_total_forces(); @@ -260,11 +295,13 @@ void colvar::distance_z::calc_force_invgrads() } } + void colvar::distance_z::calc_Jacobian_derivative() { jd.real_value = 0.0; } + void colvar::distance_z::apply_force(colvarvalue const &force) { if (!ref1->noforce) @@ -278,6 +315,56 @@ void colvar::distance_z::apply_force(colvarvalue const &force) } +// Differences should always be wrapped around 0 (ignoring wrap_center) +cvm::real colvar::distance_z::dist2(colvarvalue const &x1, + colvarvalue const &x2) const +{ + cvm::real diff = x1.real_value - x2.real_value; + if (b_periodic) { + cvm::real shift = std::floor(diff/period + 0.5); + diff -= shift * period; + } + return diff * diff; +} + + +colvarvalue colvar::distance_z::dist2_lgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + cvm::real diff = x1.real_value - x2.real_value; + if (b_periodic) { + cvm::real shift = std::floor(diff/period + 0.5); + diff -= shift * period; + } + return 2.0 * diff; +} + + +colvarvalue colvar::distance_z::dist2_rgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + cvm::real diff = x1.real_value - x2.real_value; + if (b_periodic) { + cvm::real shift = std::floor(diff/period + 0.5); + diff -= shift * period; + } + return (-2.0) * diff; +} + + +void colvar::distance_z::wrap(colvarvalue &x) const +{ + if (!b_periodic) { + // don't wrap if the period has not been set + return; + } + + cvm::real shift = std::floor((x.real_value - wrap_center) / period + 0.5); + x.real_value -= shift * period; + return; +} + + colvar::distance_xy::distance_xy(std::string const &conf) : distance_z(conf) @@ -289,6 +376,7 @@ colvar::distance_xy::distance_xy(std::string const &conf) x.type(colvarvalue::type_scalar); } + colvar::distance_xy::distance_xy() : distance_z() { @@ -299,6 +387,7 @@ colvar::distance_xy::distance_xy() x.type(colvarvalue::type_scalar); } + void colvar::distance_xy::calc_value() { if (b_no_PBC) { @@ -321,6 +410,7 @@ void colvar::distance_xy::calc_value() x.real_value = dist_v_ortho.norm(); } + void colvar::distance_xy::calc_gradients() { // Intermediate quantity (r_P3 / r_12 where P is the projection @@ -348,6 +438,7 @@ void colvar::distance_xy::calc_gradients() } } + void colvar::distance_xy::calc_force_invgrads() { main->read_total_forces(); @@ -360,11 +451,13 @@ void colvar::distance_xy::calc_force_invgrads() } } + void colvar::distance_xy::calc_Jacobian_derivative() { jd.real_value = x.real_value ? (1.0 / x.real_value) : 0.0; } + void colvar::distance_xy::apply_force(colvarvalue const &force) { if (!ref1->noforce) @@ -378,6 +471,9 @@ void colvar::distance_xy::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(distance_xy) + + colvar::distance_dir::distance_dir(std::string const &conf) : distance(conf) @@ -403,7 +499,7 @@ void colvar::distance_dir::calc_value() dist_v = group2->center_of_mass() - group1->center_of_mass(); } else { dist_v = cvm::position_distance(group1->center_of_mass(), - group2->center_of_mass()); + group2->center_of_mass()); } x.rvector_value = dist_v.unit(); } @@ -460,6 +556,7 @@ colvar::distance_inv::distance_inv(std::string const &conf) x.type(colvarvalue::type_scalar); } + colvar::distance_inv::distance_inv() { function_type = "distance_inv"; @@ -467,6 +564,7 @@ colvar::distance_inv::distance_inv() x.type(colvarvalue::type_scalar); } + void colvar::distance_inv::calc_value() { x.real_value = 0.0; @@ -504,6 +602,7 @@ void colvar::distance_inv::calc_value() x.real_value = std::pow(x.real_value, -1.0/(cvm::real(exponent))); } + void colvar::distance_inv::calc_gradients() { cvm::real const dxdsum = (-1.0/(cvm::real(exponent))) * std::pow(x.real_value, exponent+1) / cvm::real(group1->size() * group2->size()); @@ -515,6 +614,7 @@ void colvar::distance_inv::calc_gradients() } } + void colvar::distance_inv::apply_force(colvarvalue const &force) { if (!group1->noforce) @@ -525,6 +625,9 @@ void colvar::distance_inv::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(distance_inv) + + colvar::distance_pairs::distance_pairs(std::string const &conf) : cvc(conf) @@ -579,11 +682,13 @@ void colvar::distance_pairs::calc_value() } } + void colvar::distance_pairs::calc_gradients() { // will be calculated on the fly in apply_force() } + void colvar::distance_pairs::apply_force(colvarvalue const &force) { if (b_no_PBC) { @@ -608,6 +713,7 @@ void colvar::distance_pairs::apply_force(colvarvalue const &force) } + colvar::gyration::gyration(std::string const &conf) : cvc(conf) { @@ -621,6 +727,7 @@ colvar::gyration::gyration(std::string const &conf) } else { atoms->b_center = true; atoms->ref_pos.assign(1, cvm::atom_pos(0.0, 0.0, 0.0)); + atoms->fit_gradients.assign(atoms->size(), cvm::rvector(0.0, 0.0, 0.0)); } x.type(colvarvalue::type_scalar); @@ -681,6 +788,9 @@ void colvar::gyration::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(gyration) + + colvar::inertia::inertia(std::string const &conf) : gyration(conf) @@ -721,6 +831,10 @@ void colvar::inertia::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(inertia_z) + + + colvar::inertia_z::inertia_z(std::string const &conf) : inertia(conf) { @@ -771,6 +885,10 @@ void colvar::inertia_z::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(inertia) + + + colvar::rmsd::rmsd(std::string const &conf) : cvc(conf) @@ -970,6 +1088,8 @@ void colvar::rmsd::calc_Jacobian_derivative() } +simple_scalar_dist_functions(rmsd) + colvar::eigenvector::eigenvector(std::string const &conf) @@ -1254,6 +1374,10 @@ void colvar::eigenvector::calc_Jacobian_derivative() } +simple_scalar_dist_functions(eigenvector) + + + colvar::cartesian::cartesian(std::string const &conf) : cvc(conf) { diff --git a/lib/colvars/colvarcomp_protein.cpp b/lib/colvars/colvarcomp_protein.cpp index e5db3a4b50..393c7dcf9a 100644 --- a/lib/colvars/colvarcomp_protein.cpp +++ b/lib/colvars/colvarcomp_protein.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include "colvarmodule.h" @@ -119,6 +126,7 @@ colvar::alpha_angles::alpha_angles() x.type(colvarvalue::type_scalar); } + colvar::alpha_angles::~alpha_angles() { while (theta.size() != 0) { @@ -131,6 +139,7 @@ colvar::alpha_angles::~alpha_angles() } } + void colvar::alpha_angles::calc_value() { x.real_value = 0.0; @@ -222,6 +231,10 @@ void colvar::alpha_angles::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(alpha_angles) + + + ////////////////////////////////////////////////////////////////////// // dihedral principal component ////////////////////////////////////////////////////////////////////// @@ -337,14 +350,22 @@ colvar::dihedPC::dihedPC(std::string const &conf) for (size_t i = 0; i < residues.size()-1; i++) { // Psi theta.push_back(new colvar::dihedral(cvm::atom(r[i ], "N", sid), - cvm::atom(r[i ], "CA", sid), - cvm::atom(r[i ], "C", sid), - cvm::atom(r[i+1], "N", sid))); + cvm::atom(r[i ], "CA", sid), + cvm::atom(r[i ], "C", sid), + cvm::atom(r[i+1], "N", sid))); + atom_groups.push_back(theta.back()->atom_groups[0]); + atom_groups.push_back(theta.back()->atom_groups[1]); + atom_groups.push_back(theta.back()->atom_groups[2]); + atom_groups.push_back(theta.back()->atom_groups[3]); // Phi (next res) theta.push_back(new colvar::dihedral(cvm::atom(r[i ], "C", sid), - cvm::atom(r[i+1], "N", sid), - cvm::atom(r[i+1], "CA", sid), - cvm::atom(r[i+1], "C", sid))); + cvm::atom(r[i+1], "N", sid), + cvm::atom(r[i+1], "CA", sid), + cvm::atom(r[i+1], "C", sid))); + atom_groups.push_back(theta.back()->atom_groups[0]); + atom_groups.push_back(theta.back()->atom_groups[1]); + atom_groups.push_back(theta.back()->atom_groups[2]); + atom_groups.push_back(theta.back()->atom_groups[3]); } if (cvm::debug()) @@ -400,3 +421,6 @@ void colvar::dihedPC::apply_force(colvarvalue const &force) coeffs[2*i+1] * dsindt) * force); } } + + +simple_scalar_dist_functions(dihedPC) diff --git a/lib/colvars/colvarcomp_rotations.cpp b/lib/colvars/colvarcomp_rotations.cpp index a3cbbb2908..936e770169 100644 --- a/lib/colvars/colvarcomp_rotations.cpp +++ b/lib/colvars/colvarcomp_rotations.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include "colvarmodule.h" @@ -123,6 +130,27 @@ void colvar::orientation::apply_force(colvarvalue const &force) } +cvm::real colvar::orientation::dist2(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return x1.quaternion_value.dist2(x2); +} + + +colvarvalue colvar::orientation::dist2_lgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return x1.quaternion_value.dist2_grad(x2); +} + + +colvarvalue colvar::orientation::dist2_rgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + return x2.quaternion_value.dist2_grad(x1); +} + + colvar::orientation_angle::orientation_angle(std::string const &conf) : orientation(conf) @@ -176,6 +204,9 @@ void colvar::orientation_angle::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(orientation_angle) + + colvar::orientation_proj::orientation_proj(std::string const &conf) : orientation(conf) @@ -220,6 +251,9 @@ void colvar::orientation_proj::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(orientation_proj) + + colvar::tilt::tilt(std::string const &conf) : orientation(conf) @@ -278,6 +312,9 @@ void colvar::tilt::apply_force(colvarvalue const &force) } +simple_scalar_dist_functions(tilt) + + colvar::spin_angle::spin_angle(std::string const &conf) : orientation(conf) @@ -339,3 +376,46 @@ void colvar::spin_angle::apply_force(colvarvalue const &force) atoms->apply_colvar_force(fw); } } + + +cvm::real colvar::spin_angle::dist2(colvarvalue const &x1, + colvarvalue const &x2) const +{ + cvm::real diff = x1.real_value - x2.real_value; + diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); + return diff * diff; +} + + +colvarvalue colvar::spin_angle::dist2_lgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + cvm::real diff = x1.real_value - x2.real_value; + diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); + return 2.0 * diff; +} + + +colvarvalue colvar::spin_angle::dist2_rgrad(colvarvalue const &x1, + colvarvalue const &x2) const +{ + cvm::real diff = x1.real_value - x2.real_value; + diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff)); + return (-2.0) * diff; +} + + +void colvar::spin_angle::wrap(colvarvalue &x) const +{ + if ((x.real_value - wrap_center) >= 180.0) { + x.real_value -= 360.0; + return; + } + + if ((x.real_value - wrap_center) < -180.0) { + x.real_value += 360.0; + return; + } + + return; +} diff --git a/lib/colvars/colvardeps.cpp b/lib/colvars/colvardeps.cpp index a44f86c292..e3ccd4ecf5 100644 --- a/lib/colvars/colvardeps.cpp +++ b/lib/colvars/colvardeps.cpp @@ -1,3 +1,13 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + + #include "colvardeps.h" @@ -219,6 +229,9 @@ void colvardeps::init_cvb_requires() { f_description(f_cvb_history_dependent, "history-dependent"); + f_description(f_cvb_scalar_variables, "require scalar variables"); + f_req_children(f_cvb_scalar_variables, f_cv_scalar); + // Initialize feature_states for each instance feature_states.reserve(f_cvb_ntot); for (i = 0; i < f_cvb_ntot; i++) { @@ -229,6 +242,9 @@ void colvardeps::init_cvb_requires() { // some biases are not history-dependent feature_states[f_cvb_history_dependent]->available = false; + + // by default, biases should work with vector variables, too + feature_states[f_cvb_scalar_variables]->available = false; } @@ -321,6 +337,7 @@ void colvardeps::init_cv_requires() { // The features below are set programmatically f_description(f_cv_scripted, "scripted"); f_description(f_cv_periodic, "periodic"); + f_req_self(f_cv_periodic, f_cv_homogeneous); f_description(f_cv_scalar, "scalar"); f_description(f_cv_linear, "linear"); f_description(f_cv_homogeneous, "homogeneous"); @@ -407,6 +424,11 @@ void colvardeps::init_cvc_requires() { // Each cvc specifies what other features are available feature_states[f_cvc_active]->available = true; feature_states[f_cvc_gradient]->available = true; + + // Features that are implemented by default if their requirements are + feature_states[f_cvc_one_site_total_force]->available = true; + + // Features That are implemented only for certain simulation engine configurations feature_states[f_cvc_scalable_com]->available = (cvm::proxy->scalable_group_coms() == COLVARS_OK); feature_states[f_cvc_scalable]->available = feature_states[f_cvc_scalable_com]->available; } diff --git a/lib/colvars/colvardeps.h b/lib/colvars/colvardeps.h index 31dfd0e302..4ef27ded85 100644 --- a/lib/colvars/colvardeps.h +++ b/lib/colvars/colvardeps.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARDEPS_H #define COLVARDEPS_H @@ -157,6 +164,7 @@ public: f_cvb_apply_force, // will apply forces f_cvb_get_total_force, // requires total forces f_cvb_history_dependent, // depends on simulation history + f_cvb_scalar_variables, // requires scalar colvars f_cvb_ntot }; diff --git a/lib/colvars/colvargrid.cpp b/lib/colvars/colvargrid.cpp index ca2d935e1c..3b25acd2ef 100644 --- a/lib/colvars/colvargrid.cpp +++ b/lib/colvars/colvargrid.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include "colvarmodule.h" #include "colvarvalue.h" #include "colvarparse.h" @@ -73,6 +80,21 @@ cvm::real colvar_grid_scalar::minimum_value() const return min; } +cvm::real colvar_grid_scalar::minimum_pos_value() const +{ + cvm::real minpos = data[0]; + size_t i; + for (i = 0; i < nt; i++) { + if(data[i] > 0) { + minpos = data[i]; + break; + } + } + for (i = 0; i < nt; i++) { + if (data[i] > 0 && data[i] < minpos) minpos = data[i]; + } + return minpos; +} cvm::real colvar_grid_scalar::integral() const { diff --git a/lib/colvars/colvargrid.h b/lib/colvars/colvargrid.h index 91d8be9573..d4b9295c6e 100644 --- a/lib/colvars/colvargrid.h +++ b/lib/colvars/colvargrid.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARGRID_H #define COLVARGRID_H @@ -378,6 +385,13 @@ public: return value_to_bin_scalar(actual_value[i] ? cv[i]->actual_value() : cv[i]->value(), i); } + /// \brief Report the bin corresponding to the current value of variable i + /// and assign first or last bin if out of boundaries + inline int current_bin_scalar_bound(int const i) const + { + return value_to_bin_scalar_bound(actual_value[i] ? cv[i]->actual_value() : cv[i]->value(), i); + } + /// \brief Report the bin corresponding to the current value of item iv in variable i inline int current_bin_scalar(int const i, int const iv) const { @@ -393,6 +407,16 @@ public: return (int) std::floor( (value.real_value - lower_boundaries[i].real_value) / widths[i] ); } + /// \brief Use the lower boundary and the width to report which bin + /// the provided value is in and assign first or last bin if out of boundaries + inline int value_to_bin_scalar_bound(colvarvalue const &value, const int i) const + { + int bin_index = std::floor( (value.real_value - lower_boundaries[i].real_value) / widths[i] ); + if (bin_index < 0) bin_index=0; + if (bin_index >=int(nx[i])) bin_index=int(nx[i])-1; + return (int) bin_index; + } + /// \brief Same as the standard version, but uses another grid definition inline int value_to_bin_scalar(colvarvalue const &value, colvarvalue const &new_offset, @@ -514,6 +538,13 @@ public: data[i] *= a; } + /// \brief Assign all zero elements a scalar constant (fast loop) + inline void remove_zeros(cvm::real const &a) + { + for (size_t i = 0; i < nt; i++) + if(data[i]==0) data[i] = a; + } + /// \brief Get the bin indices corresponding to the provided values of /// the colvars @@ -537,6 +568,17 @@ public: return index; } + /// \brief Get the bin indices corresponding to the provided values of + /// the colvars and assign first or last bin if out of boundaries + inline std::vector const get_colvars_index_bound() const + { + std::vector index = new_index(); + for (size_t i = 0; i < nd; i++) { + index[i] = current_bin_scalar_bound(i); + } + return index; + } + /// \brief Get the minimal distance (in number of bins) from the /// boundaries; a negative number is returned if the given point is /// off-grid @@ -1071,7 +1113,7 @@ public: { // write the header os << "object 1 class gridpositions counts"; - int icv; + size_t icv; for (icv = 0; icv < number_of_colvars(); icv++) { os << " " << number_of_points(icv); } @@ -1166,45 +1208,49 @@ public: /// \brief Return the log-gradient from finite differences /// on the *same* grid for dimension n - inline const cvm::real log_gradient_finite_diff( const std::vector &ix0, - int n = 0) + inline cvm::real log_gradient_finite_diff(const std::vector &ix0, + int n = 0) { - cvm::real A0, A1; - std::vector ix; - - // factor for mesh width, 2.0 for central finite difference - // but only 1.0 on edges for non-PBC coordinates - cvm::real factor; + int A0, A1, A2; + std::vector ix = ix0; if (periodic[n]) { - factor = 2.; - ix = ix0; ix[n]--; wrap(ix); A0 = data[address(ix)]; ix = ix0; ix[n]++; wrap(ix); A1 = data[address(ix)]; - } else { - factor = 0.; - ix = ix0; - if (ix[n] > 0) { // not left edge - ix[n]--; - factor += 1.; + if (A0 * A1 == 0) { + return 0.; // can't handle empty bins + } else { + return (std::log((cvm::real)A1) - std::log((cvm::real)A0)) + / (widths[n] * 2.); } + } else if (ix[n] > 0 && ix[n] < nx[n]-1) { // not an edge + ix[n]--; A0 = data[address(ix)]; ix = ix0; - if (ix[n]+1 < nx[n]) { // not right edge - ix[n]++; - factor += 1.; - } + ix[n]++; A1 = data[address(ix)]; - } - if (A0 == 0 || A1 == 0) { - // can't handle empty bins - return 0.; + if (A0 * A1 == 0) { + return 0.; // can't handle empty bins + } else { + return (std::log((cvm::real)A1) - std::log((cvm::real)A0)) + / (widths[n] * 2.); + } } else { - return (std::log((cvm::real)A1) - std::log((cvm::real)A0)) - / (widths[n] * factor); + // edge: use 2nd order derivative + int increment = (ix[n] == 0 ? 1 : -1); + // move right from left edge, or the other way around + A0 = data[address(ix)]; + ix[n] += increment; A1 = data[address(ix)]; + ix[n] += increment; A2 = data[address(ix)]; + if (A0 * A1 * A2 == 0) { + return 0.; // can't handle empty bins + } else { + return (-1.5 * std::log((cvm::real)A0) + 2. * std::log((cvm::real)A1) + - 0.5 * std::log((cvm::real)A2)) * increment / widths[n]; + } } } }; @@ -1322,6 +1368,9 @@ public: /// \brief Return the lowest value cvm::real minimum_value() const; + /// \brief Return the lowest positive value + cvm::real minimum_pos_value() const; + /// \brief Calculates the integral of the map (uses widths if they are defined) cvm::real integral() const; diff --git a/lib/colvars/colvarmodule.cpp b/lib/colvars/colvarmodule.cpp index 8e110275b2..b9a435152b 100644 --- a/lib/colvars/colvarmodule.cpp +++ b/lib/colvars/colvarmodule.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include @@ -296,6 +303,9 @@ int colvarmodule::parse_biases(std::string const &conf) /// initialize harmonic restraints parse_biases_type(conf, "harmonic", n_rest_biases); + /// initialize harmonic walls restraints + parse_biases_type(conf, "harmonicWalls", n_rest_biases); + /// initialize histograms parse_biases_type(conf, "histogram", n_histo_biases); @@ -562,7 +572,6 @@ int colvarmodule::calc_colvars() colvars_smp_items.reserve(colvars.size()); // set up a vector containing all components - size_t num_colvar_items = 0; cvm::increase_depth(); for (cvi = colvars.begin(); cvi != colvars.end(); cvi++) { @@ -576,8 +585,6 @@ int colvarmodule::calc_colvars() colvars_smp.push_back(*cvi); colvars_smp_items.push_back(icvc); } - - num_colvar_items += num_items; } cvm::decrease_depth(); @@ -641,7 +648,7 @@ int colvarmodule::calc_biases() for (bi = biases.begin(); bi != biases.end(); bi++) { error_code |= (*bi)->update(); if (cvm::get_error()) { - return COLVARS_ERROR; + return error_code; } } cvm::decrease_depth(); @@ -1007,7 +1014,7 @@ std::istream & colvarmodule::read_restart(std::istream &is) for (std::vector::iterator bi = biases.begin(); bi != biases.end(); bi++) { - if (!((*bi)->read_restart(is))) { + if (!((*bi)->read_state(is))) { cvm::error("Error: in reading restart configuration for bias \""+ (*bi)->name+"\".\n", INPUT_ERROR); @@ -1070,15 +1077,15 @@ continue the previous simulation.\n\n"); cvm::log(cvm::line_marker); // update this ahead of time in this special case - output_prefix = proxy->output_prefix(); + output_prefix = proxy->input_prefix(); cvm::log("All output files will now be saved with the prefix \""+output_prefix+".tmp.*\".\n"); - output_prefix = output_prefix+".tmp"; - write_output_files(); cvm::log(cvm::line_marker); cvm::log("Please review the important warning above. After that, you may rename:\n\ \""+output_prefix+".tmp.colvars.state\"\n\ to:\n\ -\""+output_prefix+".colvars.state\"\n"); +\""+ proxy->input_prefix()+".colvars.state\"\n"); + output_prefix = output_prefix+".tmp"; + write_output_files(); cvm::error("Exiting with error until issue is addressed.\n", FATAL_ERROR); } @@ -1120,6 +1127,7 @@ int colvarmodule::write_output_files() bi != biases.end(); bi++) { (*bi)->write_output_files(); + (*bi)->write_state_to_replicas(); } cvm::decrease_depth(); @@ -1212,20 +1220,30 @@ std::ostream & colvarmodule::write_restart(std::ostream &os) << " version " << std::string(COLVARS_VERSION) << "\n" << "}\n\n"; + int error_code = COLVARS_OK; + cvm::increase_depth(); for (std::vector::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { (*cvi)->write_restart(os); + error_code |= (*cvi)->write_output_files(); } for (std::vector::iterator bi = biases.begin(); bi != biases.end(); bi++) { - (*bi)->write_restart(os); + (*bi)->write_state(os); + error_code |= (*bi)->write_state_to_replicas(); + error_code |= (*bi)->write_output_files(); } cvm::decrease_depth(); + if (error_code != COLVARS_OK) { + // TODO make this function return an int instead + os.setstate(std::ios::failbit); + } + return os; } diff --git a/lib/colvars/colvarmodule.h b/lib/colvars/colvarmodule.h index c8df6c7b5e..0e98709adb 100644 --- a/lib/colvars/colvarmodule.h +++ b/lib/colvars/colvarmodule.h @@ -1,10 +1,17 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARMODULE_H #define COLVARMODULE_H #ifndef COLVARS_VERSION -#define COLVARS_VERSION "2016-10-21" +#define COLVARS_VERSION "2016-12-27" #endif #ifndef COLVARS_DEBUG @@ -198,7 +205,7 @@ public: } /// \brief How many objects are configured yet? - inline size_t const size() const + inline size_t size() const { return colvars.size() + biases.size(); } diff --git a/lib/colvars/colvarparse.cpp b/lib/colvars/colvarparse.cpp index 86cd00ad29..4d2e17f098 100644 --- a/lib/colvars/colvarparse.cpp +++ b/lib/colvars/colvarparse.cpp @@ -1,3 +1,11 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. #include diff --git a/lib/colvars/colvarparse.h b/lib/colvars/colvarparse.h index 892f1632e1..acdc46ddc9 100644 --- a/lib/colvars/colvarparse.h +++ b/lib/colvars/colvarparse.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARPARSE_H #define COLVARPARSE_H diff --git a/lib/colvars/colvarproxy.h b/lib/colvars/colvarproxy.h index 59f6dc9bb2..bdf65c0b1f 100644 --- a/lib/colvars/colvarproxy.h +++ b/lib/colvars/colvarproxy.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARPROXY_H #define COLVARPROXY_H @@ -24,11 +31,18 @@ public: /// Pointer to the main object colvarmodule *colvars; - /// Default constructor - inline colvarproxy() : script(NULL), b_smp_active(true) {} + /// Constructor + colvarproxy() + { + colvars = NULL; + b_simulation_running = true; + b_smp_active = true; + script = NULL; + } - /// Default destructor - virtual ~colvarproxy() {} + /// Destructor + virtual ~colvarproxy() + {} /// (Re)initialize required member data after construction virtual int setup() @@ -104,6 +118,19 @@ public: return 0; } +protected: + + /// Whether a simulation is running (and try to prevent irrecovarable errors) + bool b_simulation_running; + +public: + + /// Whether a simulation is running (and try to prevent irrecovarable errors) + virtual bool simulation_running() const + { + return b_simulation_running; + } + protected: /// \brief Currently opened output files: by default, these are ofstream objects. diff --git a/lib/colvars/colvarscript.cpp b/lib/colvars/colvarscript.cpp index a0269aa7a9..ffb83e9780 100644 --- a/lib/colvars/colvarscript.cpp +++ b/lib/colvars/colvarscript.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include #include diff --git a/lib/colvars/colvarscript.h b/lib/colvars/colvarscript.h index 7778c3757f..bfb8381e3b 100644 --- a/lib/colvars/colvarscript.h +++ b/lib/colvars/colvarscript.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARSCRIPT_H #define COLVARSCRIPT_H diff --git a/lib/colvars/colvartypes.cpp b/lib/colvars/colvartypes.cpp index 6f773bd5f7..5200d4d041 100644 --- a/lib/colvars/colvartypes.cpp +++ b/lib/colvars/colvartypes.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include diff --git a/lib/colvars/colvartypes.h b/lib/colvars/colvartypes.h index 2c3d49f686..e0cebb83bc 100644 --- a/lib/colvars/colvartypes.h +++ b/lib/colvars/colvartypes.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARTYPES_H #define COLVARTYPES_H diff --git a/lib/colvars/colvarvalue.cpp b/lib/colvars/colvarvalue.cpp index d009e12f31..deccc6b7e0 100644 --- a/lib/colvars/colvarvalue.cpp +++ b/lib/colvars/colvarvalue.cpp @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include #include @@ -70,45 +77,30 @@ void colvarvalue::set_elem(int const icv, colvarvalue const &x) } -colvarvalue colvarvalue::inverse() const +void colvarvalue::set_random() { - switch (value_type) { + size_t ic; + switch (this->type()) { case colvarvalue::type_scalar: - return colvarvalue(1.0/real_value); + this->real_value = cvm::rand_gaussian(); break; case colvarvalue::type_3vector: case colvarvalue::type_unit3vector: case colvarvalue::type_unit3vectorderiv: - return colvarvalue(cvm::rvector(1.0/rvector_value.x, - 1.0/rvector_value.y, - 1.0/rvector_value.z)); + this->rvector_value.x = cvm::rand_gaussian(); + this->rvector_value.y = cvm::rand_gaussian(); + this->rvector_value.z = cvm::rand_gaussian(); break; case colvarvalue::type_quaternion: case colvarvalue::type_quaternionderiv: - return colvarvalue(cvm::quaternion(1.0/quaternion_value.q0, - 1.0/quaternion_value.q1, - 1.0/quaternion_value.q2, - 1.0/quaternion_value.q3)); + this->quaternion_value.q0 = cvm::rand_gaussian(); + this->quaternion_value.q1 = cvm::rand_gaussian(); + this->quaternion_value.q2 = cvm::rand_gaussian(); + this->quaternion_value.q3 = cvm::rand_gaussian(); break; case colvarvalue::type_vector: - { - cvm::vector1d result(vector1d_value); - if (elem_types.size() > 0) { - // if we have information about non-scalar types, use it - size_t i; - for (i = 0; i < elem_types.size(); i++) { - result.sliceassign(elem_indices[i], elem_indices[i]+elem_sizes[i], - cvm::vector1d((this->get_elem(i)).inverse())); - } - } else { - size_t i; - for (i = 0; i < result.size(); i++) { - if (result[i] != 0.0) { - result = 1.0/result[i]; - } - } - } - return colvarvalue(result, type_vector); + for (ic = 0; ic < this->vector1d_value.size(); ic++) { + this->vector1d_value[ic] = cvm::rand_gaussian(); } break; case colvarvalue::type_notset: @@ -116,7 +108,6 @@ colvarvalue colvarvalue::inverse() const undef_op(); break; } - return colvarvalue(); } @@ -288,7 +279,7 @@ colvarvalue colvarvalue::dist2_grad(colvarvalue const &x2) const (-1.0) * sin_t * v2.z + cos_t/sin_t * (v1.z - cos_t*v2.z) ), - colvarvalue::type_unit3vector ); + colvarvalue::type_unit3vectorderiv ); } case colvarvalue::type_quaternion: case colvarvalue::type_quaternionderiv: diff --git a/lib/colvars/colvarvalue.h b/lib/colvars/colvarvalue.h index 6f63bd64a2..e369feefcd 100644 --- a/lib/colvars/colvarvalue.h +++ b/lib/colvars/colvarvalue.h @@ -1,5 +1,12 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #ifndef COLVARVALUE_H #define COLVARVALUE_H @@ -128,30 +135,23 @@ public: {} /// \brief Copy constructor from rvector base type (Note: this sets - /// automatically a type \link type_3vector \endlink , if you want a + /// by default a type \link type_3vector \endlink , if you want a /// \link type_unit3vector \endlink you must set it explicitly) - inline colvarvalue(cvm::rvector const &v) - : value_type(type_3vector), rvector_value(v) - {} - - /// \brief Copy constructor from rvector base type (additional - /// argument to make possible to choose a \link type_unit3vector - /// \endlink - inline colvarvalue(cvm::rvector const &v, Type const &vti) + inline colvarvalue(cvm::rvector const &v, Type vti = type_3vector) : value_type(vti), rvector_value(v) {} /// \brief Copy constructor from quaternion base type - inline colvarvalue(cvm::quaternion const &q) - : value_type(type_quaternion), quaternion_value(q) + inline colvarvalue(cvm::quaternion const &q, Type vti = type_quaternion) + : value_type(vti), quaternion_value(q) {} + /// Copy constructor from vector1d base type + colvarvalue(cvm::vector1d const &v, Type vti = type_vector); + /// Copy constructor from another \link colvarvalue \endlink colvarvalue(colvarvalue const &x); - /// Copy constructor from vector1d base type - colvarvalue(cvm::vector1d const &v, Type const &vti); - /// Set to the null value for the data type currently defined void reset(); @@ -211,10 +211,6 @@ public: return std::sqrt(this->norm2()); } - /// \brief Return the value whose scalar product with this value is - /// 1 - inline colvarvalue inverse() const; - /// Square distance between this \link colvarvalue \endlink and another cvm::real dist2(colvarvalue const &x2) const; @@ -297,6 +293,9 @@ public: /// Set elements of the vector from a single colvarvalue void set_elem(int const i_begin, int const i_end, colvarvalue const &x); + /// Make each element a random number in N(0,1) + void set_random(); + /// Get a single colvarvalue out of elements of the vector colvarvalue const get_elem(int const icv) const; @@ -533,7 +532,7 @@ inline colvarvalue::colvarvalue(colvarvalue const &x) } } -inline colvarvalue::colvarvalue(cvm::vector1d const &v, Type const &vti) +inline colvarvalue::colvarvalue(cvm::vector1d const &v, Type vti) { if ((vti != type_vector) && (v.size() != num_dimensions(vti))) { cvm::error("Error: trying to initialize a variable of type \""+type_desc(vti)+ @@ -617,11 +616,22 @@ inline int colvarvalue::check_types_assign(colvarvalue::Type const &vt1, } if (vt1 != type_notset) { - if (vt1 != vt2) { - cvm::error("Trying to assign a colvar value with type \""+ - type_desc(vt2)+"\" to one with type \""+ - type_desc(vt1)+"\".\n"); - return COLVARS_ERROR; + if (((vt1 == type_unit3vector) && + (vt2 == type_unit3vectorderiv)) || + ((vt2 == type_unit3vector) && + (vt1 == type_unit3vectorderiv)) || + ((vt1 == type_quaternion) && + (vt2 == type_quaternionderiv)) || + ((vt2 == type_quaternion) && + (vt1 == type_quaternionderiv))) { + return COLVARS_OK; + } else { + if (vt1 != vt2) { + cvm::error("Trying to assign a colvar value with type \""+ + type_desc(vt2)+"\" to one with type \""+ + type_desc(vt1)+"\".\n"); + return COLVARS_ERROR; + } } } return COLVARS_OK; diff --git a/src/.gitignore b/src/.gitignore index 6b90b64752..6290aa9259 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -24,6 +24,7 @@ /kokkos.cpp /kokkos.h /kokkos_type.h +/kokkos_few.h /manifold*.cpp /manifold*.h diff --git a/src/KOKKOS/Install.sh b/src/KOKKOS/Install.sh index 96ec348b30..d796de5e2f 100644 --- a/src/KOKKOS/Install.sh +++ b/src/KOKKOS/Install.sh @@ -97,6 +97,8 @@ action fix_reaxc_species_kokkos.cpp fix_reaxc_species.cpp action fix_reaxc_species_kokkos.h fix_reaxc_species.h action fix_setforce_kokkos.cpp action fix_setforce_kokkos.h +action fix_momentum_kokkos.cpp +action fix_momentum_kokkos.h action fix_wall_reflect_kokkos.cpp action fix_wall_reflect_kokkos.h action fix_dpd_energy_kokkos.cpp fix_dpd_energy.cpp @@ -108,6 +110,7 @@ action improper_harmonic_kokkos.h improper_harmonic.h action kokkos.cpp action kokkos.h action kokkos_type.h +action kokkos_few.h action memory_kokkos.h action modify_kokkos.cpp action modify_kokkos.h diff --git a/src/KOKKOS/atom_vec_angle_kokkos.cpp b/src/KOKKOS/atom_vec_angle_kokkos.cpp index 6d063793e0..221a5e738a 100644 --- a/src/KOKKOS/atom_vec_angle_kokkos.cpp +++ b/src/KOKKOS/atom_vec_angle_kokkos.cpp @@ -1593,7 +1593,7 @@ int AtomVecAngleKokkos::unpack_restart(double *buf) double **extra = atom->extra; if (atom->nextra_store) { - int size = static_cast (ubuf(buf[m++]).i) - m; + int size = static_cast (buf[0]) - m; for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++]; } diff --git a/src/KOKKOS/atom_vec_atomic_kokkos.cpp b/src/KOKKOS/atom_vec_atomic_kokkos.cpp index 2117073077..0a03cf9f6a 100644 --- a/src/KOKKOS/atom_vec_atomic_kokkos.cpp +++ b/src/KOKKOS/atom_vec_atomic_kokkos.cpp @@ -1232,7 +1232,7 @@ int AtomVecAtomicKokkos::unpack_restart(double *buf) double **extra = atom->extra; if (atom->nextra_store) { - int size = static_cast (ubuf(buf[m++]).i) - m; + int size = static_cast (buf[0]) - m; for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++]; } diff --git a/src/KOKKOS/atom_vec_bond_kokkos.cpp b/src/KOKKOS/atom_vec_bond_kokkos.cpp index d42ec04834..f7bbb4dad5 100644 --- a/src/KOKKOS/atom_vec_bond_kokkos.cpp +++ b/src/KOKKOS/atom_vec_bond_kokkos.cpp @@ -1460,7 +1460,7 @@ int AtomVecBondKokkos::unpack_restart(double *buf) double **extra = atom->extra; if (atom->nextra_store) { - int size = static_cast (ubuf(buf[m++]).i) - m; + int size = static_cast (buf[0]) - m; for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++]; } diff --git a/src/KOKKOS/atom_vec_charge_kokkos.cpp b/src/KOKKOS/atom_vec_charge_kokkos.cpp index 4669dd8d7c..b7b5cbac7d 100644 --- a/src/KOKKOS/atom_vec_charge_kokkos.cpp +++ b/src/KOKKOS/atom_vec_charge_kokkos.cpp @@ -1314,7 +1314,7 @@ int AtomVecChargeKokkos::unpack_restart(double *buf) double **extra = atom->extra; if (atom->nextra_store) { - int size = static_cast (ubuf(buf[m++]).i) - m; + int size = static_cast (buf[0]) - m; for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++]; } diff --git a/src/KOKKOS/atom_vec_full_kokkos.cpp b/src/KOKKOS/atom_vec_full_kokkos.cpp index 7c1ebeed3a..731168b6ea 100644 --- a/src/KOKKOS/atom_vec_full_kokkos.cpp +++ b/src/KOKKOS/atom_vec_full_kokkos.cpp @@ -1936,7 +1936,7 @@ int AtomVecFullKokkos::unpack_restart(double *buf) double **extra = atom->extra; if (atom->nextra_store) { - int size = static_cast (ubuf(buf[m++]).i) - m; + int size = static_cast (buf[0]) - m; for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++]; } diff --git a/src/KOKKOS/atom_vec_molecular_kokkos.cpp b/src/KOKKOS/atom_vec_molecular_kokkos.cpp index 7217ad49cb..b4370e239d 100644 --- a/src/KOKKOS/atom_vec_molecular_kokkos.cpp +++ b/src/KOKKOS/atom_vec_molecular_kokkos.cpp @@ -1850,7 +1850,7 @@ int AtomVecMolecularKokkos::unpack_restart(double *buf) double **extra = atom->extra; if (atom->nextra_store) { - int size = static_cast (ubuf(buf[m++]).i) - m; + int size = static_cast (buf[0]) - m; for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++]; } diff --git a/src/KOKKOS/comm_tiled_kokkos.cpp b/src/KOKKOS/comm_tiled_kokkos.cpp index f3ea9d7abf..adcc634aa1 100644 --- a/src/KOKKOS/comm_tiled_kokkos.cpp +++ b/src/KOKKOS/comm_tiled_kokkos.cpp @@ -262,5 +262,5 @@ void CommTiledKokkos::forward_comm_array(int nsize, double **array) int CommTiledKokkos::exchange_variable(int n, double *inbuf, double *&outbuf) { - CommTiled::exchange_variable(n,inbuf,outbuf); -} \ No newline at end of file + return CommTiled::exchange_variable(n,inbuf,outbuf); +} diff --git a/src/KOKKOS/compute_temp_kokkos.h b/src/KOKKOS/compute_temp_kokkos.h index 2bb0f9cbb2..a01bb42f8c 100644 --- a/src/KOKKOS/compute_temp_kokkos.h +++ b/src/KOKKOS/compute_temp_kokkos.h @@ -45,14 +45,13 @@ namespace LAMMPS_NS { } KOKKOS_INLINE_FUNCTION - volatile s_CTEMP& operator+=(const volatile s_CTEMP &rhs) volatile { + void operator+=(const volatile s_CTEMP &rhs) volatile { t0 += rhs.t0; t1 += rhs.t1; t2 += rhs.t2; t3 += rhs.t3; t4 += rhs.t4; t5 += rhs.t5; - return *this; } }; typedef s_CTEMP CTEMP; diff --git a/src/KOKKOS/domain_kokkos.h b/src/KOKKOS/domain_kokkos.h index 50429008dc..7b8504dba8 100644 --- a/src/KOKKOS/domain_kokkos.h +++ b/src/KOKKOS/domain_kokkos.h @@ -16,6 +16,7 @@ #include "domain.h" #include "kokkos_type.h" +#include "kokkos_few.h" namespace LAMMPS_NS { @@ -35,6 +36,10 @@ class DomainKokkos : public Domain { void image_flip(int, int, int); void x2lamda(int); void lamda2x(int); + // these lines bring in the x2lamda signatures from Domain + // that are not overloaded here + using Domain::x2lamda; + using Domain::lamda2x; int closest_image(const int, int) const; @@ -50,6 +55,10 @@ class DomainKokkos : public Domain { KOKKOS_INLINE_FUNCTION void operator()(TagDomain_x2lamda, const int&) const; + static KOKKOS_INLINE_FUNCTION + Few unmap(Few prd, Few h, int triclinic, + Few x, imageint image); + private: double lo[3],hi[3],period[3]; int n_flip, m_flip, p_flip; @@ -57,6 +66,26 @@ class DomainKokkos : public Domain { ArrayTypes::t_imageint_1d image; }; +KOKKOS_INLINE_FUNCTION +Few DomainKokkos::unmap(Few prd, Few h, + int triclinic, Few x, imageint image) +{ + int xbox = (image & IMGMASK) - IMGMAX; + int ybox = (image >> IMGBITS & IMGMASK) - IMGMAX; + int zbox = (image >> IMG2BITS) - IMGMAX; + Few y; + if (triclinic == 0) { + y[0] = x[0] + xbox*prd[0]; + y[1] = x[1] + ybox*prd[1]; + y[2] = x[2] + zbox*prd[2]; + } else { + y[0] = x[0] + h[0]*xbox + h[5]*ybox + h[4]*zbox; + y[1] = x[1] + h[1]*ybox + h[3]*zbox; + y[2] = x[2] + h[2]*zbox; + } + return y; +} + } #endif diff --git a/src/KOKKOS/fix_momentum_kokkos.cpp b/src/KOKKOS/fix_momentum_kokkos.cpp new file mode 100644 index 0000000000..8dc4a15551 --- /dev/null +++ b/src/KOKKOS/fix_momentum_kokkos.cpp @@ -0,0 +1,204 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#include +#include +#include "fix_momentum_kokkos.h" +#include "atom_kokkos.h" +#include "atom_masks.h" +#include "domain.h" +#include "domain_kokkos.h" +#include "group.h" +#include "error.h" +#include "force.h" +#include "kokkos_few.h" + +using namespace LAMMPS_NS; +using namespace FixConst; + +/* ---------------------------------------------------------------------- + Contributing author: Dan Ibanez (SNL) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- */ + +template +FixMomentumKokkos::FixMomentumKokkos(LAMMPS *lmp, int narg, char **arg) : + FixMomentum(lmp, narg, arg) +{ + kokkosable = 1; + atomKK = (AtomKokkos *) atom; + execution_space = ExecutionSpaceFromDevice::space; + datamask_read = EMPTY_MASK; + datamask_modify = EMPTY_MASK; +} + +/* ---------------------------------------------------------------------- */ + +template +static double get_kinetic_energy( + AtomKokkos* atomKK, + MPI_Comm world, + int groupbit, + int nlocal, + typename ArrayTypes::t_v_array_randomread v, + typename ArrayTypes::t_int_1d_randomread mask) +{ + using AT = ArrayTypes; + auto execution_space = ExecutionSpaceFromDevice::space; + double ke=0.0; + if (atomKK->rmass) { + atomKK->sync(execution_space, RMASS_MASK); + typename AT::t_float_1d_randomread rmass = atomKK->k_rmass.view(); + Kokkos::parallel_reduce(nlocal, LAMMPS_LAMBDA(int i, double& update) { + if (mask(i) & groupbit) + update += rmass(i) * + (v(i,0)*v(i,0) + v(i,1)*v(i,1) + v(i,2)*v(i,2)); + }, ke); + } else { + // D.I. : why is there no MASS_MASK ? + atomKK->sync(execution_space, TYPE_MASK); + typename AT::t_int_1d_randomread type = atomKK->k_type.view(); + typename AT::t_float_1d_randomread mass = atomKK->k_mass.view(); + Kokkos::parallel_reduce(nlocal, LAMMPS_LAMBDA(int i, double& update) { + if (mask(i) & groupbit) + update += mass(type(i)) * + (v(i,0)*v(i,0) + v(i,1)*v(i,1) + v(i,2)*v(i,2)); + }, ke); + } + double ke_total; + MPI_Allreduce(&ke,&ke_total,1,MPI_DOUBLE,MPI_SUM,world); + return ke_total; +} + +template +void FixMomentumKokkos::end_of_step() +{ + atomKK->sync(execution_space, V_MASK | MASK_MASK); + + typename AT::t_v_array v = atomKK->k_v.view(); + typename AT::t_int_1d_randomread mask = atomKK->k_mask.view(); + + const int nlocal = atom->nlocal; + double ekin_old,ekin_new; + ekin_old = ekin_new = 0.0; + + if (dynamic) + masstotal = group->mass(igroup); // change once Group is ported to Kokkos + + // do nothing if group is empty, i.e. mass is zero; + + if (masstotal == 0.0) return; + + // compute kinetic energy before momentum removal, if needed + + if (rescale) { + ekin_old = get_kinetic_energy(atomKK, world, groupbit, nlocal, v, mask); + } + + auto groupbit2 = groupbit; + if (linear) { + /* this is needed because Group is not Kokkos-aware ! */ + atomKK->sync(ExecutionSpaceFromDevice::space, + V_MASK | MASK_MASK | TYPE_MASK | RMASS_MASK); + Few vcm; + group->vcm(igroup,masstotal,&vcm[0]); + + // adjust velocities by vcm to zero linear momentum + // only adjust a component if flag is set + + auto xflag2 = xflag; + auto yflag2 = yflag; + auto zflag2 = zflag; + + Kokkos::parallel_for(nlocal, LAMMPS_LAMBDA(int i) { + if (mask(i) & groupbit2) { + if (xflag2) v(i,0) -= vcm[0]; + if (yflag2) v(i,1) -= vcm[1]; + if (zflag2) v(i,2) -= vcm[2]; + } + }); + atomKK->modified(execution_space, V_MASK); + } + + if (angular) { + Few xcm, angmom, omega; + double inertia[3][3]; + /* syncs for each Kokkos-unaware Group method */ + atomKK->sync(ExecutionSpaceFromDevice::space, + X_MASK | MASK_MASK | TYPE_MASK | IMAGE_MASK | RMASS_MASK); + group->xcm(igroup,masstotal,&xcm[0]); + atomKK->sync(ExecutionSpaceFromDevice::space, + X_MASK | V_MASK | MASK_MASK | TYPE_MASK | IMAGE_MASK | RMASS_MASK); + group->angmom(igroup,&xcm[0],&angmom[0]); + atomKK->sync(ExecutionSpaceFromDevice::space, + X_MASK | MASK_MASK | TYPE_MASK | IMAGE_MASK | RMASS_MASK); + group->inertia(igroup,&xcm[0],inertia); + group->omega(&angmom[0],inertia,&omega[0]); + + // adjust velocities to zero omega + // vnew_i = v_i - w x r_i + // must use unwrapped coords to compute r_i correctly + + atomKK->sync(execution_space, X_MASK | IMAGE_MASK); + typename AT::t_x_array_randomread x = atomKK->k_x.view(); + typename AT::t_imageint_1d_randomread image = atomKK->k_image.view(); + int nlocal = atom->nlocal; + + auto prd = Few(domain->prd); + auto h = Few(domain->h); + auto triclinic = domain->triclinic; + Kokkos::parallel_for(nlocal, LAMMPS_LAMBDA(int i) { + if (mask[i] & groupbit2) { + Few x_i; + x_i[0] = x(i,0); + x_i[1] = x(i,1); + x_i[2] = x(i,2); + auto unwrap = DomainKokkos::unmap(prd,h,triclinic,x_i,image(i)); + auto dx = unwrap[0] - xcm[0]; + auto dy = unwrap[1] - xcm[1]; + auto dz = unwrap[2] - xcm[2]; + v(i,0) -= omega[1]*dz - omega[2]*dy; + v(i,1) -= omega[2]*dx - omega[0]*dz; + v(i,2) -= omega[0]*dy - omega[1]*dx; + } + }); + atomKK->modified(execution_space, V_MASK); + } + + // compute kinetic energy after momentum removal, if needed + + if (rescale) { + + ekin_new = get_kinetic_energy(atomKK, world, groupbit, nlocal, v, mask); + + double factor = 1.0; + if (ekin_new != 0.0) factor = sqrt(ekin_old/ekin_new); + Kokkos::parallel_for(nlocal, LAMMPS_LAMBDA(int i) { + if (mask(i) & groupbit2) { + v(i,0) *= factor; + v(i,1) *= factor; + v(i,2) *= factor; + } + }); + atomKK->modified(execution_space, V_MASK); + } +} + +namespace LAMMPS_NS { +template class FixMomentumKokkos; +#ifdef KOKKOS_HAVE_CUDA +template class FixMomentumKokkos; +#endif +} + diff --git a/src/KOKKOS/fix_momentum_kokkos.h b/src/KOKKOS/fix_momentum_kokkos.h new file mode 100644 index 0000000000..bc370fe674 --- /dev/null +++ b/src/KOKKOS/fix_momentum_kokkos.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS + +FixStyle(momentum/kk,FixMomentumKokkos) +FixStyle(momentum/kk/device,FixMomentumKokkos) +FixStyle(momentum/kk/host,FixMomentumKokkos) + +#else + +#ifndef LMP_FIX_MOMENTUM_KOKKOS_H +#define LMP_FIX_MOMENTUM_KOKKOS_H + +#include "fix_momentum.h" +#include "kokkos_type.h" + +namespace LAMMPS_NS { + +template +class FixMomentumKokkos : public FixMomentum { + public: + typedef ArrayTypes AT; + + FixMomentumKokkos(class LAMMPS *, int, char **); + void end_of_step(); +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +*/ diff --git a/src/KOKKOS/fix_setforce_kokkos.h b/src/KOKKOS/fix_setforce_kokkos.h index ccf3863900..dffa22c93a 100644 --- a/src/KOKKOS/fix_setforce_kokkos.h +++ b/src/KOKKOS/fix_setforce_kokkos.h @@ -43,11 +43,10 @@ struct s_double_3 { } KOKKOS_INLINE_FUNCTION - volatile s_double_3& operator+=(const volatile s_double_3 &rhs) volatile { + void operator+=(const volatile s_double_3 &rhs) volatile { d0 += rhs.d0; d1 += rhs.d1; d2 += rhs.d2; - return *this; } }; typedef s_double_3 double_3; diff --git a/src/KOKKOS/kokkos_few.h b/src/KOKKOS/kokkos_few.h new file mode 100644 index 0000000000..4c62b13fea --- /dev/null +++ b/src/KOKKOS/kokkos_few.h @@ -0,0 +1,68 @@ +#ifndef KOKKOS_FEW_H +#define KOKKOS_FEW_H + +#include + +template +class Few { + alignas(T) char array_[n * sizeof(T)]; + + public: + enum { size = n }; + Few(std::initializer_list l) { + std::size_t i = 0; + for (auto it = l.begin(); it != l.end(); ++it) { + new (data() + (i++)) T(*it); + } + } + KOKKOS_INLINE_FUNCTION Few(T const a[]) { + for (std::size_t i = 0; i < n; ++i) new (data() + i) T(a[i]); + } + KOKKOS_INLINE_FUNCTION Few() { + for (std::size_t i = 0; i < n; ++i) new (data() + i) T(); + } + KOKKOS_INLINE_FUNCTION ~Few() { + for (std::size_t i = 0; i < n; ++i) (data()[i]).~T(); + } + KOKKOS_INLINE_FUNCTION Few(Few const& rhs) { + for (std::size_t i = 0; i < n; ++i) new (data() + i) T(rhs[i]); + } + KOKKOS_INLINE_FUNCTION Few(Few const volatile& rhs) { + for (std::size_t i = 0; i < n; ++i) new (data() + i) T(rhs[i]); + } + KOKKOS_INLINE_FUNCTION void operator=(Few const& rhs) volatile { + for (std::size_t i = 0; i < n; ++i) data()[i] = rhs[i]; + } + KOKKOS_INLINE_FUNCTION void operator=(Few const& rhs) { + for (std::size_t i = 0; i < n; ++i) data()[i] = rhs[i]; + } + KOKKOS_INLINE_FUNCTION void operator=(Few const volatile& rhs) { + for (std::size_t i = 0; i < n; ++i) data()[i] = rhs[i]; + } + KOKKOS_INLINE_FUNCTION T* data() { + return reinterpret_cast(array_); + } + KOKKOS_INLINE_FUNCTION T const* data() const { + return reinterpret_cast(array_); + } + KOKKOS_INLINE_FUNCTION T volatile* data() volatile { + return reinterpret_cast(array_); + } + KOKKOS_INLINE_FUNCTION T const volatile* data() const volatile { + return reinterpret_cast(array_); + } + KOKKOS_INLINE_FUNCTION T& operator[](std::size_t i) { + return data()[i]; + } + KOKKOS_INLINE_FUNCTION T const& operator[](std::size_t i) const { + return data()[i]; + } + KOKKOS_INLINE_FUNCTION T volatile& operator[](std::size_t i) volatile { + return data()[i]; + } + KOKKOS_INLINE_FUNCTION T const volatile& operator[](std::size_t i) const volatile { + return data()[i]; + } +}; + +#endif diff --git a/src/KOKKOS/modify_kokkos.cpp b/src/KOKKOS/modify_kokkos.cpp index 9a035ac20c..ec3831dff8 100644 --- a/src/KOKKOS/modify_kokkos.cpp +++ b/src/KOKKOS/modify_kokkos.cpp @@ -81,7 +81,7 @@ void ModifyKokkos::setup_pre_exchange() atomKK->sync(fix[list_min_pre_exchange[i]]->execution_space, fix[list_min_pre_exchange[i]]->datamask_read); if (!fix[list_min_pre_exchange[i]]->kokkosable) lmp->kokkos->auto_sync = 1; - fix[list_min_pre_exchange[i]]->min_setup_pre_exchange(); + fix[list_min_pre_exchange[i]]->setup_pre_exchange(); lmp->kokkos->auto_sync = 0; atomKK->modified(fix[list_min_pre_exchange[i]]->execution_space, fix[list_min_pre_exchange[i]]->datamask_modify); @@ -110,7 +110,7 @@ void ModifyKokkos::setup_pre_neighbor() atomKK->sync(fix[list_min_pre_neighbor[i]]->execution_space, fix[list_min_pre_neighbor[i]]->datamask_read); if (!fix[list_min_pre_neighbor[i]]->kokkosable) lmp->kokkos->auto_sync = 1; - fix[list_min_pre_neighbor[i]]->min_setup_pre_neighbor(); + fix[list_min_pre_neighbor[i]]->setup_pre_neighbor(); lmp->kokkos->auto_sync = 0; atomKK->modified(fix[list_min_pre_neighbor[i]]->execution_space, fix[list_min_pre_neighbor[i]]->datamask_modify); @@ -139,13 +139,42 @@ void ModifyKokkos::setup_pre_force(int vflag) atomKK->sync(fix[list_min_pre_force[i]]->execution_space, fix[list_min_pre_force[i]]->datamask_read); if (!fix[list_min_pre_force[i]]->kokkosable) lmp->kokkos->auto_sync = 1; - fix[list_min_pre_force[i]]->min_setup_pre_force(vflag); + fix[list_min_pre_force[i]]->setup_pre_force(vflag); lmp->kokkos->auto_sync = 0; atomKK->modified(fix[list_min_pre_force[i]]->execution_space, fix[list_min_pre_force[i]]->datamask_modify); } } +/* ---------------------------------------------------------------------- + setup pre_reverse call, only for fixes that define pre_reverse + called from Verlet, RESPA, Min +------------------------------------------------------------------------- */ + +void ModifyKokkos::setup_pre_reverse(int eflag, int vflag) +{ + if (update->whichflag == 1) + for (int i = 0; i < n_pre_reverse; i++) { + atomKK->sync(fix[list_pre_reverse[i]]->execution_space, + fix[list_pre_reverse[i]]->datamask_read); + if (!fix[list_pre_reverse[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_pre_reverse[i]]->setup_pre_reverse(eflag,vflag); + lmp->kokkos->auto_sync = 0; + atomKK->modified(fix[list_pre_reverse[i]]->execution_space, + fix[list_pre_reverse[i]]->datamask_modify); + } + else if (update->whichflag == 2) + for (int i = 0; i < n_min_pre_reverse; i++) { + atomKK->sync(fix[list_min_pre_reverse[i]]->execution_space, + fix[list_min_pre_reverse[i]]->datamask_read); + if (!fix[list_min_pre_reverse[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_min_pre_reverse[i]]->setup_pre_reverse(eflag,vflag); + lmp->kokkos->auto_sync = 0; + atomKK->modified(fix[list_min_pre_reverse[i]]->execution_space, + fix[list_min_pre_reverse[i]]->datamask_modify); + } +} + /* ---------------------------------------------------------------------- 1st half of integrate call, only for relevant fixes ------------------------------------------------------------------------- */ @@ -231,6 +260,23 @@ void ModifyKokkos::pre_force(int vflag) } } +/* ---------------------------------------------------------------------- + pre_reverse call, only for relevant fixes +------------------------------------------------------------------------- */ + +void ModifyKokkos::pre_reverse(int eflag, int vflag) +{ + for (int i = 0; i < n_pre_reverse; i++) { + atomKK->sync(fix[list_pre_reverse[i]]->execution_space, + fix[list_pre_reverse[i]]->datamask_read); + if (!fix[list_pre_reverse[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_pre_reverse[i]]->pre_reverse(eflag,vflag); + lmp->kokkos->auto_sync = 0; + atomKK->modified(fix[list_pre_reverse[i]]->execution_space, + fix[list_pre_reverse[i]]->datamask_modify); + } +} + /* ---------------------------------------------------------------------- post_force call, only for relevant fixes ------------------------------------------------------------------------- */ @@ -476,6 +522,23 @@ void ModifyKokkos::min_pre_force(int vflag) } } +/* ---------------------------------------------------------------------- + minimizer pre-reverse call, only for relevant fixes +------------------------------------------------------------------------- */ + +void ModifyKokkos::min_pre_reverse(int eflag, int vflag) +{ + for (int i = 0; i < n_min_pre_reverse; i++) { + atomKK->sync(fix[list_min_pre_reverse[i]]->execution_space, + fix[list_min_pre_reverse[i]]->datamask_read); + if (!fix[list_min_pre_reverse[i]]->kokkosable) lmp->kokkos->auto_sync = 1; + fix[list_min_pre_reverse[i]]->min_pre_reverse(eflag,vflag); + lmp->kokkos->auto_sync = 0; + atomKK->modified(fix[list_min_pre_reverse[i]]->execution_space, + fix[list_min_pre_reverse[i]]->datamask_modify); + } +} + /* ---------------------------------------------------------------------- minimizer force adjustment call, only for relevant fixes ------------------------------------------------------------------------- */ @@ -658,4 +721,3 @@ int ModifyKokkos::min_reset_ref() } return itmpall; } - diff --git a/src/KOKKOS/modify_kokkos.h b/src/KOKKOS/modify_kokkos.h index b8e5f8de30..32dfb2fd97 100644 --- a/src/KOKKOS/modify_kokkos.h +++ b/src/KOKKOS/modify_kokkos.h @@ -26,12 +26,14 @@ class ModifyKokkos : public Modify { void setup_pre_exchange(); void setup_pre_neighbor(); void setup_pre_force(int); + void setup_pre_reverse(int, int); void initial_integrate(int); void post_integrate(); void pre_decide(); void pre_exchange(); void pre_neighbor(); void pre_force(int); + void pre_reverse(int,int); void post_force(int); void final_integrate(); void end_of_step(); @@ -48,6 +50,7 @@ class ModifyKokkos : public Modify { void min_pre_exchange(); void min_pre_neighbor(); void min_pre_force(int); + void min_pre_reverse(int,int); void min_post_force(int); double min_energy(double *); diff --git a/src/KOKKOS/pair_buck_coul_cut_kokkos.h b/src/KOKKOS/pair_buck_coul_cut_kokkos.h index 89730e32e0..8bccabf8de 100644 --- a/src/KOKKOS/pair_buck_coul_cut_kokkos.h +++ b/src/KOKKOS/pair_buck_coul_cut_kokkos.h @@ -75,7 +75,7 @@ class PairBuckCoulCutKokkos : public PairBuckCoulCut { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_buck_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_buck_coul_long_kokkos.h b/src/KOKKOS/pair_buck_coul_long_kokkos.h index 04586bd1a3..c4af7e19f3 100644 --- a/src/KOKKOS/pair_buck_coul_long_kokkos.h +++ b/src/KOKKOS/pair_buck_coul_long_kokkos.h @@ -76,7 +76,7 @@ class PairBuckCoulLongKokkos : public PairBuckCoulLong { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_buck_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_buck_kokkos.h b/src/KOKKOS/pair_buck_kokkos.h index e95fa903fe..6b6e6f793e 100644 --- a/src/KOKKOS/pair_buck_kokkos.h +++ b/src/KOKKOS/pair_buck_kokkos.h @@ -68,7 +68,7 @@ class PairBuckKokkos : public PairBuck { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - params_buck m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; // hardwired to space for 15 atom types + params_buck m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; // hardwired to space for 12 atom types F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; typename ArrayTypes::t_x_array_randomread x; typename ArrayTypes::t_x_array c_x; diff --git a/src/KOKKOS/pair_coul_cut_kokkos.h b/src/KOKKOS/pair_coul_cut_kokkos.h index 754706ef4d..2049385c3f 100644 --- a/src/KOKKOS/pair_coul_cut_kokkos.h +++ b/src/KOKKOS/pair_coul_cut_kokkos.h @@ -81,7 +81,7 @@ class PairCoulCutKokkos : public PairCoulCut { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_coul_debye_kokkos.h b/src/KOKKOS/pair_coul_debye_kokkos.h index 4007108588..1f6d222e04 100644 --- a/src/KOKKOS/pair_coul_debye_kokkos.h +++ b/src/KOKKOS/pair_coul_debye_kokkos.h @@ -79,7 +79,7 @@ class PairCoulDebyeKokkos : public PairCoulDebye { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_coul_long_kokkos.h b/src/KOKKOS/pair_coul_long_kokkos.h index af38686d68..19789fbd86 100644 --- a/src/KOKKOS/pair_coul_long_kokkos.h +++ b/src/KOKKOS/pair_coul_long_kokkos.h @@ -80,7 +80,7 @@ class PairCoulLongKokkos : public PairCoulLong { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_charmm_coul_charmm_implicit_kokkos.cpp b/src/KOKKOS/pair_lj_charmm_coul_charmm_implicit_kokkos.cpp index 914711a8e5..1cf2dfe054 100644 --- a/src/KOKKOS/pair_lj_charmm_coul_charmm_implicit_kokkos.cpp +++ b/src/KOKKOS/pair_lj_charmm_coul_charmm_implicit_kokkos.cpp @@ -490,14 +490,11 @@ double PairLJCharmmCoulCharmmImplicitKokkos::init_one(int i, int j) m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsqm; } - k_cutsq.h_view(i,j) = cutone*cutone; - k_cutsq.h_view(j,i) = k_cutsq.h_view(i,j); + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_ljsq.h_view(i,j) = cut_ljsqm; - k_cut_ljsq.h_view(j,i) = k_cut_ljsq.h_view(i,j); + k_cut_ljsq.h_view(i,j) = k_cut_ljsq.h_view(j,i) = cut_ljsqm; k_cut_ljsq.template modify(); - k_cut_coulsq.h_view(i,j) = cut_coulsqm; - k_cut_coulsq.h_view(j,i) = k_cut_coulsq.h_view(i,j); + k_cut_coulsq.h_view(i,j) = k_cut_coulsq.h_view(j,i) = cut_coulsqm; k_cut_coulsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_charmm_coul_charmm_implicit_kokkos.h b/src/KOKKOS/pair_lj_charmm_coul_charmm_implicit_kokkos.h index 431aca589f..3c0b7d46ae 100644 --- a/src/KOKKOS/pair_lj_charmm_coul_charmm_implicit_kokkos.h +++ b/src/KOKKOS/pair_lj_charmm_coul_charmm_implicit_kokkos.h @@ -76,7 +76,7 @@ class PairLJCharmmCoulCharmmImplicitKokkos : public PairLJCharmmCoulCharmmImplic Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_charmm_coul_charmm_kokkos.cpp b/src/KOKKOS/pair_lj_charmm_coul_charmm_kokkos.cpp index 4af6a896d0..a4d0316ca7 100644 --- a/src/KOKKOS/pair_lj_charmm_coul_charmm_kokkos.cpp +++ b/src/KOKKOS/pair_lj_charmm_coul_charmm_kokkos.cpp @@ -491,14 +491,11 @@ double PairLJCharmmCoulCharmmKokkos::init_one(int i, int j) m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsqm; } - k_cutsq.h_view(i,j) = cutone*cutone; - k_cutsq.h_view(j,i) = k_cutsq.h_view(i,j); + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_ljsq.h_view(i,j) = cut_ljsqm; - k_cut_ljsq.h_view(j,i) = k_cut_ljsq.h_view(i,j); + k_cut_ljsq.h_view(i,j) = k_cut_ljsq.h_view(j,i) = cut_ljsqm; k_cut_ljsq.template modify(); - k_cut_coulsq.h_view(i,j) = cut_coulsqm; - k_cut_coulsq.h_view(j,i) = k_cut_coulsq.h_view(i,j); + k_cut_coulsq.h_view(i,j) = k_cut_coulsq.h_view(j,i) = cut_coulsqm; k_cut_coulsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_charmm_coul_charmm_kokkos.h b/src/KOKKOS/pair_lj_charmm_coul_charmm_kokkos.h index 9dc7914d3d..202cda68b3 100644 --- a/src/KOKKOS/pair_lj_charmm_coul_charmm_kokkos.h +++ b/src/KOKKOS/pair_lj_charmm_coul_charmm_kokkos.h @@ -76,7 +76,7 @@ class PairLJCharmmCoulCharmmKokkos : public PairLJCharmmCoulCharmm { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_charmm_coul_long_kokkos.cpp b/src/KOKKOS/pair_lj_charmm_coul_long_kokkos.cpp index 5efba2742d..5b1176278a 100644 --- a/src/KOKKOS/pair_lj_charmm_coul_long_kokkos.cpp +++ b/src/KOKKOS/pair_lj_charmm_coul_long_kokkos.cpp @@ -521,14 +521,11 @@ double PairLJCharmmCoulLongKokkos::init_one(int i, int j) m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsqm; } - k_cutsq.h_view(i,j) = cutone*cutone; - k_cutsq.h_view(j,i) = k_cutsq.h_view(i,j); + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_ljsq.h_view(i,j) = cut_ljsqm; - k_cut_ljsq.h_view(j,i) = k_cut_ljsq.h_view(i,j); + k_cut_ljsq.h_view(i,j) = k_cut_ljsq.h_view(j,i) = cut_ljsqm; k_cut_ljsq.template modify(); - k_cut_coulsq.h_view(i,j) = cut_coulsqm; - k_cut_coulsq.h_view(j,i) = k_cut_coulsq.h_view(i,j); + k_cut_coulsq.h_view(i,j) = k_cut_coulsq.h_view(j,i) = cut_coulsqm; k_cut_coulsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_charmm_coul_long_kokkos.h b/src/KOKKOS/pair_lj_charmm_coul_long_kokkos.h index 8f50722e01..fcdab7ddb6 100644 --- a/src/KOKKOS/pair_lj_charmm_coul_long_kokkos.h +++ b/src/KOKKOS/pair_lj_charmm_coul_long_kokkos.h @@ -75,7 +75,7 @@ class PairLJCharmmCoulLongKokkos : public PairLJCharmmCoulLong { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_class2_coul_cut_kokkos.cpp b/src/KOKKOS/pair_lj_class2_coul_cut_kokkos.cpp index 96507a599e..0e33958a22 100644 --- a/src/KOKKOS/pair_lj_class2_coul_cut_kokkos.cpp +++ b/src/KOKKOS/pair_lj_class2_coul_cut_kokkos.cpp @@ -326,11 +326,12 @@ double PairLJClass2CoulCutKokkos::init_one(int i, int j) m_cut_ljsq[j][i] = m_cut_ljsq[i][j] = cut_ljsqm; m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsqm; } - k_cutsq.h_view(i,j) = cutone*cutone; + + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_ljsq.h_view(i,j) = cut_ljsqm; + k_cut_ljsq.h_view(i,j) = k_cut_ljsq.h_view(j,i) = cut_ljsqm; k_cut_ljsq.template modify(); - k_cut_coulsq.h_view(i,j) = cut_coulsqm; + k_cut_coulsq.h_view(i,j) = k_cut_coulsq.h_view(j,i) = cut_coulsqm; k_cut_coulsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_class2_coul_cut_kokkos.h b/src/KOKKOS/pair_lj_class2_coul_cut_kokkos.h index a1d8a8bded..1ea5bc69bf 100644 --- a/src/KOKKOS/pair_lj_class2_coul_cut_kokkos.h +++ b/src/KOKKOS/pair_lj_class2_coul_cut_kokkos.h @@ -75,7 +75,7 @@ class PairLJClass2CoulCutKokkos : public PairLJClass2CoulCut { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_class2_coul_long_kokkos.cpp b/src/KOKKOS/pair_lj_class2_coul_long_kokkos.cpp index 2d1abc9cd3..00becd0ec6 100644 --- a/src/KOKKOS/pair_lj_class2_coul_long_kokkos.cpp +++ b/src/KOKKOS/pair_lj_class2_coul_long_kokkos.cpp @@ -480,11 +480,11 @@ double PairLJClass2CoulLongKokkos::init_one(int i, int j) m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsqm; } - k_cutsq.h_view(i,j) = cutone*cutone; + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_ljsq.h_view(i,j) = cut_ljsqm; + k_cut_ljsq.h_view(i,j) = k_cut_ljsq.h_view(j,i) = cut_ljsqm; k_cut_ljsq.template modify(); - k_cut_coulsq.h_view(i,j) = cut_coulsqm; + k_cut_coulsq.h_view(i,j) = k_cut_coulsq.h_view(j,i) = cut_coulsqm; k_cut_coulsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_class2_coul_long_kokkos.h b/src/KOKKOS/pair_lj_class2_coul_long_kokkos.h index 72b0b8609e..0b1b2dc90b 100644 --- a/src/KOKKOS/pair_lj_class2_coul_long_kokkos.h +++ b/src/KOKKOS/pair_lj_class2_coul_long_kokkos.h @@ -76,7 +76,7 @@ class PairLJClass2CoulLongKokkos : public PairLJClass2CoulLong { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_class2_kokkos.cpp b/src/KOKKOS/pair_lj_class2_kokkos.cpp index b5c4c19b8e..9f9e3c72a5 100644 --- a/src/KOKKOS/pair_lj_class2_kokkos.cpp +++ b/src/KOKKOS/pair_lj_class2_kokkos.cpp @@ -258,7 +258,7 @@ double PairLJClass2Kokkos::init_one(int i, int j) m_params[i][j] = m_params[j][i] = k_params.h_view(i,j); m_cutsq[j][i] = m_cutsq[i][j] = cutone*cutone; } - k_cutsq.h_view(i,j) = cutone*cutone; + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_class2_kokkos.h b/src/KOKKOS/pair_lj_class2_kokkos.h index e8ac07da80..73865928f5 100644 --- a/src/KOKKOS/pair_lj_class2_kokkos.h +++ b/src/KOKKOS/pair_lj_class2_kokkos.h @@ -75,7 +75,7 @@ class PairLJClass2Kokkos : public PairLJClass2 { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - params_lj m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; // hardwired to space for 15 atom types + params_lj m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; // hardwired to space for 12 atom types F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; typename ArrayTypes::t_x_array_randomread x; typename ArrayTypes::t_x_array c_x; diff --git a/src/KOKKOS/pair_lj_cut_coul_cut_kokkos.cpp b/src/KOKKOS/pair_lj_cut_coul_cut_kokkos.cpp index e68ec5579c..f1a7950521 100644 --- a/src/KOKKOS/pair_lj_cut_coul_cut_kokkos.cpp +++ b/src/KOKKOS/pair_lj_cut_coul_cut_kokkos.cpp @@ -317,11 +317,12 @@ double PairLJCutCoulCutKokkos::init_one(int i, int j) m_cut_ljsq[j][i] = m_cut_ljsq[i][j] = cut_ljsqm; m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsqm; } - k_cutsq.h_view(i,j) = cutone*cutone; + + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_ljsq.h_view(i,j) = cut_ljsqm; + k_cut_ljsq.h_view(i,j) = k_cut_ljsq.h_view(j,i) = cut_ljsqm; k_cut_ljsq.template modify(); - k_cut_coulsq.h_view(i,j) = cut_coulsqm; + k_cut_coulsq.h_view(i,j) = k_cut_coulsq.h_view(j,i) = cut_coulsqm; k_cut_coulsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_cut_coul_cut_kokkos.h b/src/KOKKOS/pair_lj_cut_coul_cut_kokkos.h index 20b2de2b8e..36f31d176c 100644 --- a/src/KOKKOS/pair_lj_cut_coul_cut_kokkos.h +++ b/src/KOKKOS/pair_lj_cut_coul_cut_kokkos.h @@ -77,7 +77,7 @@ class PairLJCutCoulCutKokkos : public PairLJCutCoulCut { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_cut_coul_debye_kokkos.cpp b/src/KOKKOS/pair_lj_cut_coul_debye_kokkos.cpp index f4011b6f5c..3eb793c52a 100644 --- a/src/KOKKOS/pair_lj_cut_coul_debye_kokkos.cpp +++ b/src/KOKKOS/pair_lj_cut_coul_debye_kokkos.cpp @@ -347,11 +347,12 @@ double PairLJCutCoulDebyeKokkos::init_one(int i, int j) m_cut_ljsq[j][i] = m_cut_ljsq[i][j] = cut_ljsqm; m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsqm; } - k_cutsq.h_view(i,j) = cutone*cutone; + + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_ljsq.h_view(i,j) = cut_ljsqm; + k_cut_ljsq.h_view(i,j) = k_cut_ljsq.h_view(j,i) = cut_ljsqm; k_cut_ljsq.template modify(); - k_cut_coulsq.h_view(i,j) = cut_coulsqm; + k_cut_coulsq.h_view(i,j) = k_cut_coulsq.h_view(j,i) = cut_coulsqm; k_cut_coulsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_cut_coul_debye_kokkos.h b/src/KOKKOS/pair_lj_cut_coul_debye_kokkos.h index 7d4527cb7f..9e1e30abad 100644 --- a/src/KOKKOS/pair_lj_cut_coul_debye_kokkos.h +++ b/src/KOKKOS/pair_lj_cut_coul_debye_kokkos.h @@ -75,7 +75,7 @@ class PairLJCutCoulDebyeKokkos : public PairLJCutCoulDebye { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_cut_coul_dsf_kokkos.cpp b/src/KOKKOS/pair_lj_cut_coul_dsf_kokkos.cpp index 13c930a15b..6507bb0272 100644 --- a/src/KOKKOS/pair_lj_cut_coul_dsf_kokkos.cpp +++ b/src/KOKKOS/pair_lj_cut_coul_dsf_kokkos.cpp @@ -338,11 +338,12 @@ double PairLJCutCoulDSFKokkos::init_one(int i, int j) m_cut_ljsq[j][i] = m_cut_ljsq[i][j] = cut_ljsqm; m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsqm; } - k_cutsq.h_view(i,j) = cutone*cutone; + + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_ljsq.h_view(i,j) = cut_ljsqm; + k_cut_ljsq.h_view(i,j) = k_cut_ljsq.h_view(j,i) = cut_ljsqm; k_cut_ljsq.template modify(); - k_cut_coulsq.h_view(i,j) = cut_coulsqm; + k_cut_coulsq.h_view(i,j) = k_cut_coulsq.h_view(j,i) = cut_coulsqm; k_cut_coulsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_cut_coul_dsf_kokkos.h b/src/KOKKOS/pair_lj_cut_coul_dsf_kokkos.h index dad5fd0b98..b1f578ec0b 100644 --- a/src/KOKKOS/pair_lj_cut_coul_dsf_kokkos.h +++ b/src/KOKKOS/pair_lj_cut_coul_dsf_kokkos.h @@ -74,7 +74,7 @@ class PairLJCutCoulDSFKokkos : public PairLJCutCoulDSF { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_cut_coul_long_kokkos.cpp b/src/KOKKOS/pair_lj_cut_coul_long_kokkos.cpp index 42319cfa99..11095bf4de 100644 --- a/src/KOKKOS/pair_lj_cut_coul_long_kokkos.cpp +++ b/src/KOKKOS/pair_lj_cut_coul_long_kokkos.cpp @@ -499,11 +499,11 @@ double PairLJCutCoulLongKokkos::init_one(int i, int j) m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsqm; } - k_cutsq.h_view(i,j) = cutone*cutone; + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_ljsq.h_view(i,j) = cut_ljsqm; + k_cut_ljsq.h_view(i,j) = k_cut_ljsq.h_view(j,i) = cut_ljsqm; k_cut_ljsq.template modify(); - k_cut_coulsq.h_view(i,j) = cut_coulsqm; + k_cut_coulsq.h_view(i,j) = k_cut_coulsq.h_view(j,i) = cut_coulsqm; k_cut_coulsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_cut_coul_long_kokkos.h b/src/KOKKOS/pair_lj_cut_coul_long_kokkos.h index ed35c6d471..5bdaaf96ca 100644 --- a/src/KOKKOS/pair_lj_cut_coul_long_kokkos.h +++ b/src/KOKKOS/pair_lj_cut_coul_long_kokkos.h @@ -76,7 +76,7 @@ class PairLJCutCoulLongKokkos : public PairLJCutCoulLong { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_cut_kokkos.cpp b/src/KOKKOS/pair_lj_cut_kokkos.cpp index 5f2805622a..066961cc89 100644 --- a/src/KOKKOS/pair_lj_cut_kokkos.cpp +++ b/src/KOKKOS/pair_lj_cut_kokkos.cpp @@ -276,7 +276,8 @@ double PairLJCutKokkos::init_one(int i, int j) m_params[i][j] = m_params[j][i] = k_params.h_view(i,j); m_cutsq[j][i] = m_cutsq[i][j] = cutone*cutone; } - k_cutsq.h_view(i,j) = cutone*cutone; + + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_cut_kokkos.h b/src/KOKKOS/pair_lj_cut_kokkos.h index b779874fe8..81c25c20d8 100644 --- a/src/KOKKOS/pair_lj_cut_kokkos.h +++ b/src/KOKKOS/pair_lj_cut_kokkos.h @@ -71,7 +71,7 @@ class PairLJCutKokkos : public PairLJCut { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - params_lj m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; // hardwired to space for 15 atom types + params_lj m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; // hardwired to space for 12 atom types F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; typename ArrayTypes::t_x_array_randomread x; typename ArrayTypes::t_x_array c_x; diff --git a/src/KOKKOS/pair_lj_expand_kokkos.cpp b/src/KOKKOS/pair_lj_expand_kokkos.cpp index 3ed03f0d0b..d7daef2a66 100644 --- a/src/KOKKOS/pair_lj_expand_kokkos.cpp +++ b/src/KOKKOS/pair_lj_expand_kokkos.cpp @@ -262,7 +262,8 @@ double PairLJExpandKokkos::init_one(int i, int j) m_params[i][j] = m_params[j][i] = k_params.h_view(i,j); m_cutsq[j][i] = m_cutsq[i][j] = cutone*cutone; } - k_cutsq.h_view(i,j) = cutone*cutone; + + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_expand_kokkos.h b/src/KOKKOS/pair_lj_expand_kokkos.h index 339950a6b2..125c638527 100644 --- a/src/KOKKOS/pair_lj_expand_kokkos.h +++ b/src/KOKKOS/pair_lj_expand_kokkos.h @@ -75,7 +75,7 @@ class PairLJExpandKokkos : public PairLJExpand { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - params_lj m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; // hardwired to space for 15 atom types + params_lj m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; // hardwired to space for 12 atom types F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; typename ArrayTypes::t_x_array_randomread x; typename ArrayTypes::t_x_array c_x; diff --git a/src/KOKKOS/pair_lj_gromacs_coul_gromacs_kokkos.cpp b/src/KOKKOS/pair_lj_gromacs_coul_gromacs_kokkos.cpp index 943cf988c9..499a826676 100644 --- a/src/KOKKOS/pair_lj_gromacs_coul_gromacs_kokkos.cpp +++ b/src/KOKKOS/pair_lj_gromacs_coul_gromacs_kokkos.cpp @@ -478,11 +478,11 @@ double PairLJGromacsCoulGromacsKokkos::init_one(int i, int j) m_cut_coulsq[j][i] = m_cut_coulsq[i][j] = cut_coulsqm; } - k_cutsq.h_view(i,j) = cutone*cutone; + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_ljsq.h_view(i,j) = cut_ljsqm; + k_cut_ljsq.h_view(i,j) = k_cut_ljsq.h_view(j,i) = cut_ljsqm; k_cut_ljsq.template modify(); - k_cut_coulsq.h_view(i,j) = cut_coulsqm; + k_cut_coulsq.h_view(i,j) = k_cut_coulsq.h_view(j,i) = cut_coulsqm; k_cut_coulsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_gromacs_coul_gromacs_kokkos.h b/src/KOKKOS/pair_lj_gromacs_coul_gromacs_kokkos.h index 492ef0c369..8b10eb71a3 100644 --- a/src/KOKKOS/pair_lj_gromacs_coul_gromacs_kokkos.h +++ b/src/KOKKOS/pair_lj_gromacs_coul_gromacs_kokkos.h @@ -76,7 +76,7 @@ class PairLJGromacsCoulGromacsKokkos : public PairLJGromacsCoulGromacs { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj_coul m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_gromacs_kokkos.cpp b/src/KOKKOS/pair_lj_gromacs_kokkos.cpp index bb4dcb39bf..a72fb7dbf9 100644 --- a/src/KOKKOS/pair_lj_gromacs_kokkos.cpp +++ b/src/KOKKOS/pair_lj_gromacs_kokkos.cpp @@ -314,9 +314,9 @@ double PairLJGromacsKokkos::init_one(int i, int j) m_cut_inner_sq[j][i] = m_cut_inner_sq[i][j] = cut_inner_sqm; } - k_cutsq.h_view(i,j) = cutone*cutone; + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); - k_cut_inner_sq.h_view(i,j) = cut_inner_sqm; + k_cut_inner_sq.h_view(i,j) = k_cut_inner_sq.h_view(j,i) = cut_inner_sqm; k_cut_inner_sq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_gromacs_kokkos.h b/src/KOKKOS/pair_lj_gromacs_kokkos.h index bfe752e93f..4c03bf6e9b 100644 --- a/src/KOKKOS/pair_lj_gromacs_kokkos.h +++ b/src/KOKKOS/pair_lj_gromacs_kokkos.h @@ -79,7 +79,7 @@ class PairLJGromacsKokkos : public PairLJGromacs { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types params_lj m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; diff --git a/src/KOKKOS/pair_lj_sdk_kokkos.cpp b/src/KOKKOS/pair_lj_sdk_kokkos.cpp index 46715e6fa3..1acf35f18d 100644 --- a/src/KOKKOS/pair_lj_sdk_kokkos.cpp +++ b/src/KOKKOS/pair_lj_sdk_kokkos.cpp @@ -290,7 +290,8 @@ double PairLJSDKKokkos::init_one(int i, int j) m_params[i][j] = m_params[j][i] = k_params.h_view(i,j); m_cutsq[j][i] = m_cutsq[i][j] = cutone*cutone; } - k_cutsq.h_view(i,j) = cutone*cutone; + + k_cutsq.h_view(i,j) = k_cutsq.h_view(j,i) = cutone*cutone; k_cutsq.template modify(); k_params.template modify(); diff --git a/src/KOKKOS/pair_lj_sdk_kokkos.h b/src/KOKKOS/pair_lj_sdk_kokkos.h index 03ca361c1b..0b9056a23e 100644 --- a/src/KOKKOS/pair_lj_sdk_kokkos.h +++ b/src/KOKKOS/pair_lj_sdk_kokkos.h @@ -72,7 +72,7 @@ class PairLJSDKKokkos : public PairLJSDK { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um params; - params_lj m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; // hardwired to space for 15 atom types + params_lj m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; // hardwired to space for 12 atom types F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; typename ArrayTypes::t_x_array_randomread x; typename ArrayTypes::t_x_array c_x; diff --git a/src/KOKKOS/pair_table_kokkos.cpp b/src/KOKKOS/pair_table_kokkos.cpp index 5230d1a91f..88773af7b3 100644 --- a/src/KOKKOS/pair_table_kokkos.cpp +++ b/src/KOKKOS/pair_table_kokkos.cpp @@ -33,20 +33,13 @@ using namespace LAMMPS_NS; -enum{NONE,RLINEAR,RSQ,BMP}; -enum{FULL,HALFTHREAD,HALF}; - -#define MAXLINE 1024 - /* ---------------------------------------------------------------------- */ template -PairTableKokkos::PairTableKokkos(LAMMPS *lmp) : Pair(lmp) +PairTableKokkos::PairTableKokkos(LAMMPS *lmp) : PairTable(lmp) { update_table = 0; atomKK = (AtomKokkos *) atom; - ntables = 0; - tables = NULL; execution_space = ExecutionSpaceFromDevice::space; datamask_read = X_MASK | F_MASK | TYPE_MASK | ENERGY_MASK | VIRIAL_MASK; datamask_modify = F_MASK | ENERGY_MASK | VIRIAL_MASK; @@ -59,17 +52,12 @@ PairTableKokkos::PairTableKokkos(LAMMPS *lmp) : Pair(lmp) template PairTableKokkos::~PairTableKokkos() { -/* for (int m = 0; m < ntables; m++) free_table(&tables[m]); - memory->sfree(tables); - - if (allocated) { - memory->destroy(setflag); - memory->destroy(cutsq); - memory->destroy(tabindex); - }*/ + if (copymode) return; delete h_table; + h_table = nullptr; delete d_table; - + d_table = nullptr; + copymode = true; //prevents base class destructor from running } /* ---------------------------------------------------------------------- */ @@ -190,26 +178,15 @@ compute_fpair(const F_FLOAT& rsq, const int& i, const int&j, const int& itype, c union_int_float_t rsq_lookup; double fpair; const int tidx = d_table_const.tabindex(itype,jtype); - //const Table* const tb = &tables[tabindex[itype][jtype]]; - - //if (rsq < d_table_const.innersq(tidx)) - // error->one(FLERR,"Pair distance < table inner cutoff"); - if (Specialisation::TabStyle == LOOKUP) { const int itable = static_cast ((rsq - d_table_const.innersq(tidx)) * d_table_const.invdelta(tidx)); - //if (itable >= tlm1) - // error->one(FLERR,"Pair distance > table outer cutoff"); fpair = d_table_const.f(tidx,itable); } else if (Specialisation::TabStyle == LINEAR) { const int itable = static_cast ((rsq - d_table_const.innersq(tidx)) * d_table_const.invdelta(tidx)); - //if (itable >= tlm1) - // error->one(FLERR,"Pair distance > table outer cutoff"); const double fraction = (rsq - d_table_const.rsq(tidx,itable)) * d_table_const.invdelta(tidx); fpair = d_table_const.f(tidx,itable) + fraction*d_table_const.df(tidx,itable); } else if (Specialisation::TabStyle == SPLINE) { const int itable = static_cast ((rsq - d_table_const.innersq(tidx)) * d_table_const.invdelta(tidx)); - //if (itable >= tlm1) - // error->one(FLERR,"Pair distance > table outer cutoff"); const double b = (rsq - d_table_const.rsq(tidx,itable)) * d_table_const.invdelta(tidx); const double a = 1.0 - b; fpair = a * d_table_const.f(tidx,itable) + b * d_table_const.f(tidx,itable+1) + @@ -235,26 +212,15 @@ compute_evdwl(const F_FLOAT& rsq, const int& i, const int&j, const int& itype, c double evdwl; union_int_float_t rsq_lookup; const int tidx = d_table_const.tabindex(itype,jtype); - //const Table* const tb = &tables[tabindex[itype][jtype]]; - - //if (rsq < d_table_const.innersq(tidx)) - // error->one(FLERR,"Pair distance < table inner cutoff"); - if (Specialisation::TabStyle == LOOKUP) { const int itable = static_cast ((rsq - d_table_const.innersq(tidx)) * d_table_const.invdelta(tidx)); - //if (itable >= tlm1) - // error->one(FLERR,"Pair distance > table outer cutoff"); evdwl = d_table_const.e(tidx,itable); } else if (Specialisation::TabStyle == LINEAR) { const int itable = static_cast ((rsq - d_table_const.innersq(tidx)) * d_table_const.invdelta(tidx)); - //if (itable >= tlm1) - // error->one(FLERR,"Pair distance > table outer cutoff"); const double fraction = (rsq - d_table_const.rsq(tidx,itable)) * d_table_const.invdelta(tidx); evdwl = d_table_const.e(tidx,itable) + fraction*d_table_const.de(tidx,itable); } else if (Specialisation::TabStyle == SPLINE) { const int itable = static_cast ((rsq - d_table_const.innersq(tidx)) * d_table_const.invdelta(tidx)); - //if (itable >= tlm1) - // error->one(FLERR,"Pair distance > table outer cutoff"); const double b = (rsq - d_table_const.rsq(tidx,itable)) * d_table_const.invdelta(tidx); const double a = 1.0 - b; evdwl = a * d_table_const.e(tidx,itable) + b * d_table_const.e(tidx,itable+1) + @@ -343,36 +309,69 @@ void PairTableKokkos::create_kokkos_tables() Kokkos::deep_copy(d_table->nshiftbits,h_table->nshiftbits); - Kokkos::deep_copy(d_table->nmask,h_table->nmask); - Kokkos::deep_copy(d_table->innersq,h_table->innersq); - Kokkos::deep_copy(d_table->invdelta,h_table->invdelta); - Kokkos::deep_copy(d_table->deltasq6,h_table->deltasq6); - Kokkos::deep_copy(d_table->rsq,h_table->rsq); - Kokkos::deep_copy(d_table->drsq,h_table->drsq); - Kokkos::deep_copy(d_table->e,h_table->e); - Kokkos::deep_copy(d_table->de,h_table->de); - Kokkos::deep_copy(d_table->f,h_table->f); - Kokkos::deep_copy(d_table->df,h_table->df); - Kokkos::deep_copy(d_table->e2,h_table->e2); - Kokkos::deep_copy(d_table->f2,h_table->f2); - Kokkos::deep_copy(d_table->tabindex,h_table->tabindex); - d_table_const.nshiftbits = d_table->nshiftbits; + Kokkos::deep_copy(d_table->nmask,h_table->nmask); d_table_const.nmask = d_table->nmask; + Kokkos::deep_copy(d_table->innersq,h_table->innersq); d_table_const.innersq = d_table->innersq; + Kokkos::deep_copy(d_table->invdelta,h_table->invdelta); d_table_const.invdelta = d_table->invdelta; + Kokkos::deep_copy(d_table->deltasq6,h_table->deltasq6); d_table_const.deltasq6 = d_table->deltasq6; - d_table_const.rsq = d_table->rsq; - d_table_const.drsq = d_table->drsq; - d_table_const.e = d_table->e; - d_table_const.de = d_table->de; - d_table_const.f = d_table->f; - d_table_const.df = d_table->df; - d_table_const.e2 = d_table->e2; - d_table_const.f2 = d_table->f2; + if(tabstyle == LOOKUP) { + Kokkos::deep_copy(d_table->e,h_table->e); + d_table_const.e = d_table->e; + Kokkos::deep_copy(d_table->f,h_table->f); + d_table_const.f = d_table->f; + } + + if(tabstyle == LINEAR) { + Kokkos::deep_copy(d_table->rsq,h_table->rsq); + d_table_const.rsq = d_table->rsq; + Kokkos::deep_copy(d_table->e,h_table->e); + d_table_const.e = d_table->e; + Kokkos::deep_copy(d_table->f,h_table->f); + d_table_const.f = d_table->f; + Kokkos::deep_copy(d_table->de,h_table->de); + d_table_const.de = d_table->de; + Kokkos::deep_copy(d_table->df,h_table->df); + d_table_const.df = d_table->df; + } + + if(tabstyle == SPLINE) { + Kokkos::deep_copy(d_table->rsq,h_table->rsq); + d_table_const.rsq = d_table->rsq; + Kokkos::deep_copy(d_table->e,h_table->e); + d_table_const.e = d_table->e; + Kokkos::deep_copy(d_table->f,h_table->f); + d_table_const.f = d_table->f; + Kokkos::deep_copy(d_table->e2,h_table->e2); + d_table_const.e2 = d_table->e2; + Kokkos::deep_copy(d_table->f2,h_table->f2); + d_table_const.f2 = d_table->f2; + } + + if(tabstyle == BITMAP) { + Kokkos::deep_copy(d_table->rsq,h_table->rsq); + d_table_const.rsq = d_table->rsq; + Kokkos::deep_copy(d_table->e,h_table->e); + d_table_const.e = d_table->e; + Kokkos::deep_copy(d_table->f,h_table->f); + d_table_const.f = d_table->f; + Kokkos::deep_copy(d_table->de,h_table->de); + d_table_const.de = d_table->de; + Kokkos::deep_copy(d_table->df,h_table->df); + d_table_const.df = d_table->df; + Kokkos::deep_copy(d_table->drsq,h_table->drsq); + d_table_const.drsq = d_table->drsq; + } Kokkos::deep_copy(d_table->cutsq,h_table->cutsq); + d_table_const.cutsq = d_table->cutsq; + Kokkos::deep_copy(d_table->tabindex,h_table->tabindex); + d_table_const.tabindex = d_table->tabindex; + update_table = 0; } @@ -389,9 +388,9 @@ void PairTableKokkos::allocate() memory->create(setflag,nt,nt,"pair:setflag"); memory->create_kokkos(d_table->cutsq,h_table->cutsq,cutsq,nt,nt,"pair:cutsq"); memory->create_kokkos(d_table->tabindex,h_table->tabindex,tabindex,nt,nt,"pair:tabindex"); - d_table_const.cutsq = d_table->cutsq; d_table_const.tabindex = d_table->tabindex; + memset(&setflag[0][0],0,nt*nt*sizeof(int)); memset(&cutsq[0][0],0,nt*nt*sizeof(double)); memset(&tabindex[0][0],0,nt*nt*sizeof(int)); @@ -451,85 +450,6 @@ void PairTableKokkos::settings(int narg, char **arg) tables = NULL; } -/* ---------------------------------------------------------------------- - set coeffs for one or more type pairs -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::coeff(int narg, char **arg) -{ - if (narg != 4 && narg != 5) error->all(FLERR,"Illegal pair_coeff command"); - if (!allocated) allocate(); - - int ilo,ihi,jlo,jhi; - force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi); - force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi); - - int me; - MPI_Comm_rank(world,&me); - tables = (Table *) - memory->srealloc(tables,(ntables+1)*sizeof(Table),"pair:tables"); - Table *tb = &tables[ntables]; - null_table(tb); - if (me == 0) read_table(tb,arg[2],arg[3]); - bcast_table(tb); - - // set table cutoff - - if (narg == 5) tb->cut = force->numeric(FLERR,arg[4]); - else if (tb->rflag) tb->cut = tb->rhi; - else tb->cut = tb->rfile[tb->ninput-1]; - - // error check on table parameters - // insure cutoff is within table - // for BITMAP tables, file values can be in non-ascending order - - if (tb->ninput <= 1) error->one(FLERR,"Invalid pair table length"); - double rlo,rhi; - if (tb->rflag == 0) { - rlo = tb->rfile[0]; - rhi = tb->rfile[tb->ninput-1]; - } else { - rlo = tb->rlo; - rhi = tb->rhi; - } - if (tb->cut <= rlo || tb->cut > rhi) - error->all(FLERR,"Invalid pair table cutoff"); - if (rlo <= 0.0) error->all(FLERR,"Invalid pair table cutoff"); - - // match = 1 if don't need to spline read-in tables - // this is only the case if r values needed by final tables - // exactly match r values read from file - // for tabstyle SPLINE, always need to build spline tables - - tb->match = 0; - if (tabstyle == LINEAR && tb->ninput == tablength && - tb->rflag == RSQ && tb->rhi == tb->cut) tb->match = 1; - if (tabstyle == BITMAP && tb->ninput == 1 << tablength && - tb->rflag == BMP && tb->rhi == tb->cut) tb->match = 1; - if (tb->rflag == BMP && tb->match == 0) - error->all(FLERR,"Bitmapped table in file does not match requested table"); - - // spline read-in values and compute r,e,f vectors within table - - if (tb->match == 0) spline_table(tb); - compute_table(tb); - - // store ptr to table in tabindex - - int count = 0; - for (int i = ilo; i <= ihi; i++) { - for (int j = MAX(jlo,i); j <= jhi; j++) { - tabindex[i][j] = ntables; - setflag[i][j] = 1; - count++; - } - } - - if (count == 0) error->all(FLERR,"Illegal pair_coeff command"); - ntables++; -} - /* ---------------------------------------------------------------------- init for one type pair i,j and corresponding j,i ------------------------------------------------------------------------- */ @@ -548,202 +468,6 @@ double PairTableKokkos::init_one(int i, int j) return tables[tabindex[i][j]].cut; } -/* ---------------------------------------------------------------------- - read a table section from a tabulated potential file - only called by proc 0 - this function sets these values in Table: - ninput,rfile,efile,ffile,rflag,rlo,rhi,fpflag,fplo,fphi,ntablebits -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::read_table(Table *tb, char *file, char *keyword) -{ - char line[MAXLINE]; - - // open file - - FILE *fp = force->open_potential(file); - if (fp == NULL) { - char str[128]; - sprintf(str,"Cannot open file %s",file); - error->one(FLERR,str); - } - - // loop until section found with matching keyword - - while (1) { - if (fgets(line,MAXLINE,fp) == NULL) - error->one(FLERR,"Did not find keyword in table file"); - if (strspn(line," \t\n\r") == strlen(line)) continue; // blank line - if (line[0] == '#') continue; // comment - char *word = strtok(line," \t\n\r"); - if (strcmp(word,keyword) == 0) break; // matching keyword - fgets(line,MAXLINE,fp); // no match, skip section - param_extract(tb,line); - fgets(line,MAXLINE,fp); - for (int i = 0; i < tb->ninput; i++) fgets(line,MAXLINE,fp); - } - - // read args on 2nd line of section - // allocate table arrays for file values - - fgets(line,MAXLINE,fp); - param_extract(tb,line); - memory->create(tb->rfile,tb->ninput,"pair:rfile"); - memory->create(tb->efile,tb->ninput,"pair:efile"); - memory->create(tb->ffile,tb->ninput,"pair:ffile"); - - // setup bitmap parameters for table to read in - - tb->ntablebits = 0; - int masklo,maskhi,nmask,nshiftbits; - if (tb->rflag == BMP) { - while (1 << tb->ntablebits < tb->ninput) tb->ntablebits++; - if (1 << tb->ntablebits != tb->ninput) - error->one(FLERR,"Bitmapped table is incorrect length in table file"); - init_bitmap(tb->rlo,tb->rhi,tb->ntablebits,masklo,maskhi,nmask,nshiftbits); - } - - // read r,e,f table values from file - // if rflag set, compute r - // if rflag not set, use r from file - - int itmp; - double rtmp; - union_int_float_t rsq_lookup; - - fgets(line,MAXLINE,fp); - for (int i = 0; i < tb->ninput; i++) { - fgets(line,MAXLINE,fp); - sscanf(line,"%d %lg %lg %lg",&itmp,&rtmp,&tb->efile[i],&tb->ffile[i]); - - if (tb->rflag == RLINEAR) - rtmp = tb->rlo + (tb->rhi - tb->rlo)*i/(tb->ninput-1); - else if (tb->rflag == RSQ) { - rtmp = tb->rlo*tb->rlo + - (tb->rhi*tb->rhi - tb->rlo*tb->rlo)*i/(tb->ninput-1); - rtmp = sqrt(rtmp); - } else if (tb->rflag == BMP) { - rsq_lookup.i = i << nshiftbits; - rsq_lookup.i |= masklo; - if (rsq_lookup.f < tb->rlo*tb->rlo) { - rsq_lookup.i = i << nshiftbits; - rsq_lookup.i |= maskhi; - } - rtmp = sqrtf(rsq_lookup.f); - } - - tb->rfile[i] = rtmp; - } - - // close file - - fclose(fp); -} - -/* ---------------------------------------------------------------------- - broadcast read-in table info from proc 0 to other procs - this function communicates these values in Table: - ninput,rfile,efile,ffile,rflag,rlo,rhi,fpflag,fplo,fphi -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::bcast_table(Table *tb) -{ - MPI_Bcast(&tb->ninput,1,MPI_INT,0,world); - - int me; - MPI_Comm_rank(world,&me); - if (me > 0) { - memory->create(tb->rfile,tb->ninput,"pair:rfile"); - memory->create(tb->efile,tb->ninput,"pair:efile"); - memory->create(tb->ffile,tb->ninput,"pair:ffile"); - } - - MPI_Bcast(tb->rfile,tb->ninput,MPI_DOUBLE,0,world); - MPI_Bcast(tb->efile,tb->ninput,MPI_DOUBLE,0,world); - MPI_Bcast(tb->ffile,tb->ninput,MPI_DOUBLE,0,world); - - MPI_Bcast(&tb->rflag,1,MPI_INT,0,world); - if (tb->rflag) { - MPI_Bcast(&tb->rlo,1,MPI_DOUBLE,0,world); - MPI_Bcast(&tb->rhi,1,MPI_DOUBLE,0,world); - } - MPI_Bcast(&tb->fpflag,1,MPI_INT,0,world); - if (tb->fpflag) { - MPI_Bcast(&tb->fplo,1,MPI_DOUBLE,0,world); - MPI_Bcast(&tb->fphi,1,MPI_DOUBLE,0,world); - } -} - -/* ---------------------------------------------------------------------- - build spline representation of e,f over entire range of read-in table - this function sets these values in Table: e2file,f2file -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::spline_table(Table *tb) -{ - memory->create(tb->e2file,tb->ninput,"pair:e2file"); - memory->create(tb->f2file,tb->ninput,"pair:f2file"); - - double ep0 = - tb->ffile[0]; - double epn = - tb->ffile[tb->ninput-1]; - spline(tb->rfile,tb->efile,tb->ninput,ep0,epn,tb->e2file); - - if (tb->fpflag == 0) { - tb->fplo = (tb->ffile[1] - tb->ffile[0]) / (tb->rfile[1] - tb->rfile[0]); - tb->fphi = (tb->ffile[tb->ninput-1] - tb->ffile[tb->ninput-2]) / - (tb->rfile[tb->ninput-1] - tb->rfile[tb->ninput-2]); - } - - double fp0 = tb->fplo; - double fpn = tb->fphi; - spline(tb->rfile,tb->ffile,tb->ninput,fp0,fpn,tb->f2file); -} - -/* ---------------------------------------------------------------------- - extract attributes from parameter line in table section - format of line: N value R/RSQ/BITMAP lo hi FP fplo fphi - N is required, other params are optional -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::param_extract(Table *tb, char *line) -{ - tb->ninput = 0; - tb->rflag = NONE; - tb->fpflag = 0; - - char *word = strtok(line," \t\n\r\f"); - while (word) { - if (strcmp(word,"N") == 0) { - word = strtok(NULL," \t\n\r\f"); - tb->ninput = atoi(word); - } else if (strcmp(word,"R") == 0 || strcmp(word,"RSQ") == 0 || - strcmp(word,"BITMAP") == 0) { - if (strcmp(word,"R") == 0) tb->rflag = RLINEAR; - else if (strcmp(word,"RSQ") == 0) tb->rflag = RSQ; - else if (strcmp(word,"BITMAP") == 0) tb->rflag = BMP; - word = strtok(NULL," \t\n\r\f"); - tb->rlo = atof(word); - word = strtok(NULL," \t\n\r\f"); - tb->rhi = atof(word); - } else if (strcmp(word,"FP") == 0) { - tb->fpflag = 1; - word = strtok(NULL," \t\n\r\f"); - tb->fplo = atof(word); - word = strtok(NULL," \t\n\r\f"); - tb->fphi = atof(word); - } else { - error->one(FLERR,"Invalid keyword in pair table parameters"); - } - word = strtok(NULL," \t\n\r\f"); - } - - if (tb->ninput == 0) error->one(FLERR,"Pair table parameters did not set N"); -} - /* ---------------------------------------------------------------------- compute r,e,f vectors from splined values ------------------------------------------------------------------------- */ @@ -752,471 +476,7 @@ template void PairTableKokkos::compute_table(Table *tb) { update_table = 1; - int tlm1 = tablength-1; - - // inner = inner table bound - // cut = outer table bound - // delta = table spacing in rsq for N-1 bins - - double inner; - if (tb->rflag) inner = tb->rlo; - else inner = tb->rfile[0]; - tb->innersq = inner*inner; - tb->delta = (tb->cut*tb->cut - tb->innersq) / tlm1; - tb->invdelta = 1.0/tb->delta; - - // direct lookup tables - // N-1 evenly spaced bins in rsq from inner to cut - // e,f = value at midpt of bin - // e,f are N-1 in length since store 1 value at bin midpt - // f is converted to f/r when stored in f[i] - // e,f are never a match to read-in values, always computed via spline interp - - if (tabstyle == LOOKUP) { - memory->create(tb->e,tlm1,"pair:e"); - memory->create(tb->f,tlm1,"pair:f"); - - double r,rsq; - for (int i = 0; i < tlm1; i++) { - rsq = tb->innersq + (i+0.5)*tb->delta; - r = sqrt(rsq); - tb->e[i] = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,r); - tb->f[i] = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,r)/r; - } - } - - // linear tables - // N-1 evenly spaced bins in rsq from inner to cut - // rsq,e,f = value at lower edge of bin - // de,df values = delta from lower edge to upper edge of bin - // rsq,e,f are N in length so de,df arrays can compute difference - // f is converted to f/r when stored in f[i] - // e,f can match read-in values, else compute via spline interp - - if (tabstyle == LINEAR) { - memory->create(tb->rsq,tablength,"pair:rsq"); - memory->create(tb->e,tablength,"pair:e"); - memory->create(tb->f,tablength,"pair:f"); - memory->create(tb->de,tlm1,"pair:de"); - memory->create(tb->df,tlm1,"pair:df"); - - double r,rsq; - for (int i = 0; i < tablength; i++) { - rsq = tb->innersq + i*tb->delta; - r = sqrt(rsq); - tb->rsq[i] = rsq; - if (tb->match) { - tb->e[i] = tb->efile[i]; - tb->f[i] = tb->ffile[i]/r; - } else { - tb->e[i] = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,r); - tb->f[i] = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,r)/r; - } - } - - for (int i = 0; i < tlm1; i++) { - tb->de[i] = tb->e[i+1] - tb->e[i]; - tb->df[i] = tb->f[i+1] - tb->f[i]; - } - } - - // cubic spline tables - // N-1 evenly spaced bins in rsq from inner to cut - // rsq,e,f = value at lower edge of bin - // e2,f2 = spline coefficient for each bin - // rsq,e,f,e2,f2 are N in length so have N-1 spline bins - // f is converted to f/r after e is splined - // e,f can match read-in values, else compute via spline interp - - if (tabstyle == SPLINE) { - memory->create(tb->rsq,tablength,"pair:rsq"); - memory->create(tb->e,tablength,"pair:e"); - memory->create(tb->f,tablength,"pair:f"); - memory->create(tb->e2,tablength,"pair:e2"); - memory->create(tb->f2,tablength,"pair:f2"); - - tb->deltasq6 = tb->delta*tb->delta / 6.0; - - double r,rsq; - for (int i = 0; i < tablength; i++) { - rsq = tb->innersq + i*tb->delta; - r = sqrt(rsq); - tb->rsq[i] = rsq; - if (tb->match) { - tb->e[i] = tb->efile[i]; - tb->f[i] = tb->ffile[i]/r; - } else { - tb->e[i] = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,r); - tb->f[i] = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,r); - } - } - - // ep0,epn = dh/dg at inner and at cut - // h(r) = e(r) and g(r) = r^2 - // dh/dg = (de/dr) / 2r = -f/2r - - double ep0 = - tb->f[0] / (2.0 * sqrt(tb->innersq)); - double epn = - tb->f[tlm1] / (2.0 * tb->cut); - spline(tb->rsq,tb->e,tablength,ep0,epn,tb->e2); - - // fp0,fpn = dh/dg at inner and at cut - // h(r) = f(r)/r and g(r) = r^2 - // dh/dg = (1/r df/dr - f/r^2) / 2r - // dh/dg in secant approx = (f(r2)/r2 - f(r1)/r1) / (g(r2) - g(r1)) - - double fp0,fpn; - double secant_factor = 0.1; - if (tb->fpflag) fp0 = (tb->fplo/sqrt(tb->innersq) - tb->f[0]/tb->innersq) / - (2.0 * sqrt(tb->innersq)); - else { - double rsq1 = tb->innersq; - double rsq2 = rsq1 + secant_factor*tb->delta; - fp0 = (splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,sqrt(rsq2)) / - sqrt(rsq2) - tb->f[0] / sqrt(rsq1)) / (secant_factor*tb->delta); - } - - if (tb->fpflag && tb->cut == tb->rfile[tb->ninput-1]) fpn = - (tb->fphi/tb->cut - tb->f[tlm1]/(tb->cut*tb->cut)) / (2.0 * tb->cut); - else { - double rsq2 = tb->cut * tb->cut; - double rsq1 = rsq2 - secant_factor*tb->delta; - fpn = (tb->f[tlm1] / sqrt(rsq2) - - splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,sqrt(rsq1)) / - sqrt(rsq1)) / (secant_factor*tb->delta); - } - - for (int i = 0; i < tablength; i++) tb->f[i] /= sqrt(tb->rsq[i]); - spline(tb->rsq,tb->f,tablength,fp0,fpn,tb->f2); - } - - // bitmapped linear tables - // 2^N bins from inner to cut, spaced in bitmapped manner - // f is converted to f/r when stored in f[i] - // e,f can match read-in values, else compute via spline interp - - if (tabstyle == BITMAP) { - double r; - union_int_float_t rsq_lookup; - int masklo,maskhi; - - // linear lookup tables of length ntable = 2^n - // stored value = value at lower edge of bin - - init_bitmap(inner,tb->cut,tablength,masklo,maskhi,tb->nmask,tb->nshiftbits); - int ntable = 1 << tablength; - int ntablem1 = ntable - 1; - - memory->create(tb->rsq,ntable,"pair:rsq"); - memory->create(tb->e,ntable,"pair:e"); - memory->create(tb->f,ntable,"pair:f"); - memory->create(tb->de,ntable,"pair:de"); - memory->create(tb->df,ntable,"pair:df"); - memory->create(tb->drsq,ntable,"pair:drsq"); - - union_int_float_t minrsq_lookup; - minrsq_lookup.i = 0 << tb->nshiftbits; - minrsq_lookup.i |= maskhi; - - for (int i = 0; i < ntable; i++) { - rsq_lookup.i = i << tb->nshiftbits; - rsq_lookup.i |= masklo; - if (rsq_lookup.f < tb->innersq) { - rsq_lookup.i = i << tb->nshiftbits; - rsq_lookup.i |= maskhi; - } - r = sqrtf(rsq_lookup.f); - tb->rsq[i] = rsq_lookup.f; - if (tb->match) { - tb->e[i] = tb->efile[i]; - tb->f[i] = tb->ffile[i]/r; - } else { - tb->e[i] = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,r); - tb->f[i] = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,r)/r; - } - minrsq_lookup.f = MIN(minrsq_lookup.f,rsq_lookup.f); - } - - tb->innersq = minrsq_lookup.f; - - for (int i = 0; i < ntablem1; i++) { - tb->de[i] = tb->e[i+1] - tb->e[i]; - tb->df[i] = tb->f[i+1] - tb->f[i]; - tb->drsq[i] = 1.0/(tb->rsq[i+1] - tb->rsq[i]); - } - - // get the delta values for the last table entries - // tables are connected periodically between 0 and ntablem1 - - tb->de[ntablem1] = tb->e[0] - tb->e[ntablem1]; - tb->df[ntablem1] = tb->f[0] - tb->f[ntablem1]; - tb->drsq[ntablem1] = 1.0/(tb->rsq[0] - tb->rsq[ntablem1]); - - // get the correct delta values at itablemax - // smallest r is in bin itablemin - // largest r is in bin itablemax, which is itablemin-1, - // or ntablem1 if itablemin=0 - - // deltas at itablemax only needed if corresponding rsq < cut*cut - // if so, compute deltas between rsq and cut*cut - // if tb->match, data at cut*cut is unavailable, so we'll take - // deltas at itablemax-1 as a good approximation - - double e_tmp,f_tmp; - int itablemin = minrsq_lookup.i & tb->nmask; - itablemin >>= tb->nshiftbits; - int itablemax = itablemin - 1; - if (itablemin == 0) itablemax = ntablem1; - int itablemaxm1 = itablemax - 1; - if (itablemax == 0) itablemaxm1 = ntablem1; - rsq_lookup.i = itablemax << tb->nshiftbits; - rsq_lookup.i |= maskhi; - if (rsq_lookup.f < tb->cut*tb->cut) { - if (tb->match) { - tb->de[itablemax] = tb->de[itablemaxm1]; - tb->df[itablemax] = tb->df[itablemaxm1]; - tb->drsq[itablemax] = tb->drsq[itablemaxm1]; - } else { - rsq_lookup.f = tb->cut*tb->cut; - r = sqrtf(rsq_lookup.f); - e_tmp = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,r); - f_tmp = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,r)/r; - tb->de[itablemax] = e_tmp - tb->e[itablemax]; - tb->df[itablemax] = f_tmp - tb->f[itablemax]; - tb->drsq[itablemax] = 1.0/(rsq_lookup.f - tb->rsq[itablemax]); - } - } - } -} - -/* ---------------------------------------------------------------------- - set all ptrs in a table to NULL, so can be freed safely -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::null_table(Table *tb) -{ - tb->rfile = tb->efile = tb->ffile = NULL; - tb->e2file = tb->f2file = NULL; - tb->rsq = tb->drsq = tb->e = tb->de = NULL; - tb->f = tb->df = tb->e2 = tb->f2 = NULL; -} - -/* ---------------------------------------------------------------------- - free all arrays in a table -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::free_table(Table *tb) -{ - memory->destroy(tb->rfile); - memory->destroy(tb->efile); - memory->destroy(tb->ffile); - memory->destroy(tb->e2file); - memory->destroy(tb->f2file); - - memory->destroy(tb->rsq); - memory->destroy(tb->drsq); - memory->destroy(tb->e); - memory->destroy(tb->de); - memory->destroy(tb->f); - memory->destroy(tb->df); - memory->destroy(tb->e2); - memory->destroy(tb->f2); -} - -/* ---------------------------------------------------------------------- - spline and splint routines modified from Numerical Recipes -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::spline(double *x, double *y, int n, - double yp1, double ypn, double *y2) -{ - int i,k; - double p,qn,sig,un; - double *u = new double[n]; - - if (yp1 > 0.99e30) y2[0] = u[0] = 0.0; - else { - y2[0] = -0.5; - u[0] = (3.0/(x[1]-x[0])) * ((y[1]-y[0]) / (x[1]-x[0]) - yp1); - } - for (i = 1; i < n-1; i++) { - sig = (x[i]-x[i-1]) / (x[i+1]-x[i-1]); - p = sig*y2[i-1] + 2.0; - y2[i] = (sig-1.0) / p; - u[i] = (y[i+1]-y[i]) / (x[i+1]-x[i]) - (y[i]-y[i-1]) / (x[i]-x[i-1]); - u[i] = (6.0*u[i] / (x[i+1]-x[i-1]) - sig*u[i-1]) / p; - } - if (ypn > 0.99e30) qn = un = 0.0; - else { - qn = 0.5; - un = (3.0/(x[n-1]-x[n-2])) * (ypn - (y[n-1]-y[n-2]) / (x[n-1]-x[n-2])); - } - y2[n-1] = (un-qn*u[n-2]) / (qn*y2[n-2] + 1.0); - for (k = n-2; k >= 0; k--) y2[k] = y2[k]*y2[k+1] + u[k]; - - delete [] u; -} - -/* ---------------------------------------------------------------------- */ - -template -double PairTableKokkos::splint(double *xa, double *ya, double *y2a, int n, double x) -{ - int klo,khi,k; - double h,b,a,y; - - klo = 0; - khi = n-1; - while (khi-klo > 1) { - k = (khi+klo) >> 1; - if (xa[k] > x) khi = k; - else klo = k; - } - h = xa[khi]-xa[klo]; - a = (xa[khi]-x) / h; - b = (x-xa[klo]) / h; - y = a*ya[klo] + b*ya[khi] + - ((a*a*a-a)*y2a[klo] + (b*b*b-b)*y2a[khi]) * (h*h)/6.0; - return y; -} - -/* ---------------------------------------------------------------------- - proc 0 writes to restart file -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::write_restart(FILE *fp) -{ - write_restart_settings(fp); -} - -/* ---------------------------------------------------------------------- - proc 0 reads from restart file, bcasts -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::read_restart(FILE *fp) -{ - read_restart_settings(fp); - allocate(); -} - -/* ---------------------------------------------------------------------- - proc 0 writes to restart file -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::write_restart_settings(FILE *fp) -{ - fwrite(&tabstyle,sizeof(int),1,fp); - fwrite(&tablength,sizeof(int),1,fp); - fwrite(&ewaldflag,sizeof(int),1,fp); - fwrite(&pppmflag,sizeof(int),1,fp); - fwrite(&msmflag,sizeof(int),1,fp); - fwrite(&dispersionflag,sizeof(int),1,fp); - fwrite(&tip4pflag,sizeof(int),1,fp); -} - -/* ---------------------------------------------------------------------- - proc 0 reads from restart file, bcasts -------------------------------------------------------------------------- */ - -template -void PairTableKokkos::read_restart_settings(FILE *fp) -{ - if (comm->me == 0) { - fread(&tabstyle,sizeof(int),1,fp); - fread(&tablength,sizeof(int),1,fp); - fread(&ewaldflag,sizeof(int),1,fp); - fread(&pppmflag,sizeof(int),1,fp); - fread(&msmflag,sizeof(int),1,fp); - fread(&dispersionflag,sizeof(int),1,fp); - fread(&tip4pflag,sizeof(int),1,fp); - } - MPI_Bcast(&tabstyle,1,MPI_INT,0,world); - MPI_Bcast(&tablength,1,MPI_INT,0,world); - MPI_Bcast(&ewaldflag,1,MPI_INT,0,world); - MPI_Bcast(&pppmflag,1,MPI_INT,0,world); - MPI_Bcast(&msmflag,1,MPI_INT,0,world); - MPI_Bcast(&dispersionflag,1,MPI_INT,0,world); - MPI_Bcast(&tip4pflag,1,MPI_INT,0,world); -} - -/* ---------------------------------------------------------------------- */ - -template -double PairTableKokkos::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, - double &fforce) -{ - int itable; - double fraction,value,a,b,phi; - int tlm1 = tablength - 1; - - Table *tb = &tables[tabindex[itype][jtype]]; - if (rsq < tb->innersq) error->one(FLERR,"Pair distance < table inner cutoff"); - - if (tabstyle == LOOKUP) { - itable = static_cast ((rsq-tb->innersq) * tb->invdelta); - if (itable >= tlm1) error->one(FLERR,"Pair distance > table outer cutoff"); - fforce = factor_lj * tb->f[itable]; - } else if (tabstyle == LINEAR) { - itable = static_cast ((rsq-tb->innersq) * tb->invdelta); - if (itable >= tlm1) error->one(FLERR,"Pair distance > table outer cutoff"); - fraction = (rsq - tb->rsq[itable]) * tb->invdelta; - value = tb->f[itable] + fraction*tb->df[itable]; - fforce = factor_lj * value; - } else if (tabstyle == SPLINE) { - itable = static_cast ((rsq-tb->innersq) * tb->invdelta); - if (itable >= tlm1) error->one(FLERR,"Pair distance > table outer cutoff"); - b = (rsq - tb->rsq[itable]) * tb->invdelta; - a = 1.0 - b; - value = a * tb->f[itable] + b * tb->f[itable+1] + - ((a*a*a-a)*tb->f2[itable] + (b*b*b-b)*tb->f2[itable+1]) * - tb->deltasq6; - fforce = factor_lj * value; - } else { - union_int_float_t rsq_lookup; - rsq_lookup.f = rsq; - itable = rsq_lookup.i & tb->nmask; - itable >>= tb->nshiftbits; - fraction = (rsq_lookup.f - tb->rsq[itable]) * tb->drsq[itable]; - value = tb->f[itable] + fraction*tb->df[itable]; - fforce = factor_lj * value; - } - - if (tabstyle == LOOKUP) - phi = tb->e[itable]; - else if (tabstyle == LINEAR || tabstyle == BITMAP) - phi = tb->e[itable] + fraction*tb->de[itable]; - else - phi = a * tb->e[itable] + b * tb->e[itable+1] + - ((a*a*a-a)*tb->e2[itable] + (b*b*b-b)*tb->e2[itable+1]) * tb->deltasq6; - return factor_lj*phi; -} - -/* ---------------------------------------------------------------------- - return the Coulomb cutoff for tabled potentials - called by KSpace solvers which require that all pairwise cutoffs be the same - loop over all tables not just those indexed by tabindex[i][j] since - no way to know which tables are active since pair::init() not yet called -------------------------------------------------------------------------- */ - -template -void *PairTableKokkos::extract(const char *str, int &dim) -{ - if (strcmp(str,"cut_coul") != 0) return NULL; - if (ntables == 0) error->all(FLERR,"All pair coeffs are not set"); - - double cut_coul = tables[0].cut; - for (int m = 1; m < ntables; m++) - if (tables[m].cut != cut_coul) - error->all(FLERR, - "Pair table cutoffs must all be equal to use with KSpace"); - dim = 0; - return &tables[0].cut; + PairTable::compute_table(tb); } template @@ -1246,91 +506,6 @@ void PairTableKokkos::init_style() } } -/* -template template -KOKKOS_INLINE_FUNCTION -void PairTableKokkos:: -ev_tally(EV_FLOAT &ev, const int &i, const int &j, const F_FLOAT &fpair, - const F_FLOAT &delx, const F_FLOAT &dely, const F_FLOAT &delz) const -{ - const int EFLAG = eflag; - const int NEWTON_PAIR = newton_pair; - const int VFLAG = vflag_either; - - if (EFLAG) { - if (eflag_atom) { - E_FLOAT epairhalf = 0.5 * (ev.evdwl + ev.ecoul); - if (NEWTON_PAIR || i < nlocal) eatom[i] += epairhalf; - if (NEWTON_PAIR || j < nlocal) eatom[j] += epairhalf; - } - } - - if (VFLAG) { - const E_FLOAT v0 = delx*delx*fpair; - const E_FLOAT v1 = dely*dely*fpair; - const E_FLOAT v2 = delz*delz*fpair; - const E_FLOAT v3 = delx*dely*fpair; - const E_FLOAT v4 = delx*delz*fpair; - const E_FLOAT v5 = dely*delz*fpair; - - if (vflag_global) { - if (NEIGHFLAG) { - if (NEWTON_PAIR) { - ev.v[0] += v0; - ev.v[1] += v1; - ev.v[2] += v2; - ev.v[3] += v3; - ev.v[4] += v4; - ev.v[5] += v5; - } else { - if (i < nlocal) { - ev.v[0] += 0.5*v0; - ev.v[1] += 0.5*v1; - ev.v[2] += 0.5*v2; - ev.v[3] += 0.5*v3; - ev.v[4] += 0.5*v4; - ev.v[5] += 0.5*v5; - } - if (j < nlocal) { - ev.v[0] += 0.5*v0; - ev.v[1] += 0.5*v1; - ev.v[2] += 0.5*v2; - ev.v[3] += 0.5*v3; - ev.v[4] += 0.5*v4; - ev.v[5] += 0.5*v5; - } - } - } else { - ev.v[0] += 0.5*v0; - ev.v[1] += 0.5*v1; - ev.v[2] += 0.5*v2; - ev.v[3] += 0.5*v3; - ev.v[4] += 0.5*v4; - ev.v[5] += 0.5*v5; - } - } - - if (vflag_atom) { - if (NEWTON_PAIR || i < nlocal) { - d_vatom(i,0) += 0.5*v0; - d_vatom(i,1) += 0.5*v1; - d_vatom(i,2) += 0.5*v2; - d_vatom(i,3) += 0.5*v3; - d_vatom(i,4) += 0.5*v4; - d_vatom(i,5) += 0.5*v5; - } - if (NEWTON_PAIR || (NEIGHFLAG && j < nlocal)) { - d_vatom(j,0) += 0.5*v0; - d_vatom(j,1) += 0.5*v1; - d_vatom(j,2) += 0.5*v2; - d_vatom(j,3) += 0.5*v3; - d_vatom(j,4) += 0.5*v4; - d_vatom(j,5) += 0.5*v5; - } - } - } -} -*/ template void PairTableKokkos::cleanup_copy() { // WHY needed: this prevents parent copy from deallocating any arrays diff --git a/src/KOKKOS/pair_table_kokkos.h b/src/KOKKOS/pair_table_kokkos.h index e768c97164..ce8b2e3ee5 100644 --- a/src/KOKKOS/pair_table_kokkos.h +++ b/src/KOKKOS/pair_table_kokkos.h @@ -22,7 +22,7 @@ PairStyle(table/kk/host,PairTableKokkos) #ifndef LMP_PAIR_TABLE_KOKKOS_H #define LMP_PAIR_TABLE_KOKKOS_H -#include "pair.h" +#include "pair_table.h" #include "pair_kokkos.h" #include "neigh_list_kokkos.h" #include "atom_kokkos.h" @@ -38,7 +38,7 @@ template class PairTableComputeFunctor; template -class PairTableKokkos : public Pair { +class PairTableKokkos : public PairTable { public: enum {EnabledNeighFlags=FULL|HALFTHREAD|HALF|N2}; @@ -53,28 +53,14 @@ class PairTableKokkos : public Pair { template void compute_style(int, int); - /*template - KOKKOS_FUNCTION - EV_FLOAT compute_item(const int& i, - const NeighListKokkos &list) const; -*/ void settings(int, char **); - void coeff(int, char **); double init_one(int, int); - void write_restart(FILE *); - void read_restart(FILE *); - void write_restart_settings(FILE *); - void read_restart_settings(FILE *); - double single(int, int, int, int, double, double, double, double &); - void *extract(const char *, int &); void init_style(); protected: - enum{LOOKUP,LINEAR,SPLINE,BITMAP}; - int tabstyle,tablength; /*struct TableDeviceConst { typename ArrayTypes::t_ffloat_2d_randomread cutsq; typename ArrayTypes::t_int_2d_randomread tabindex; @@ -107,36 +93,16 @@ class PairTableKokkos : public Pair { typename ArrayTypes::t_ffloat_2d rsq,drsq,e,de,f,df,e2,f2; }; - struct Table { - int ninput,rflag,fpflag,match,ntablebits; - int nshiftbits,nmask; - double rlo,rhi,fplo,fphi,cut; - double *rfile,*efile,*ffile; - double *e2file,*f2file; - double innersq,delta,invdelta,deltasq6; - double *rsq,*drsq,*e,*de,*f,*df,*e2,*f2; - }; - int ntables; - Table *tables; TableDeviceConst d_table_const; TableDevice* d_table; TableHost* h_table; - int **tabindex; F_FLOAT m_cutsq[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; typename ArrayTypes::t_ffloat_2d d_cutsq; - void allocate(); - void read_table(Table *, char *, char *); - void param_extract(Table *, char *); - void bcast_table(Table *); - void spline_table(Table *); + virtual void allocate(); void compute_table(Table *); - void null_table(Table *); - void free_table(Table *); - void spline(double *, double *, int, double, double, double *); - double splint(double *, double *, double *, int, double); typename ArrayTypes::t_x_array_randomread x; typename ArrayTypes::t_x_array_const c_x; diff --git a/src/KOKKOS/pair_tersoff_kokkos.cpp b/src/KOKKOS/pair_tersoff_kokkos.cpp index 40e54df33b..66faa956c6 100644 --- a/src/KOKKOS/pair_tersoff_kokkos.cpp +++ b/src/KOKKOS/pair_tersoff_kokkos.cpp @@ -99,6 +99,9 @@ void PairTersoffKokkos::init_style() neighbor->requests[irequest]-> kokkos_device = Kokkos::Impl::is_same::value; + if (neighflag == FULL) + error->all(FLERR,"Cannot (yet) use full neighbor list style with tersoff/kk"); + if (neighflag == FULL || neighflag == HALF || neighflag == HALFTHREAD) { //if (neighflag == FULL || neighflag == HALFTHREAD) { neighbor->requests[irequest]->full = 1; diff --git a/src/KOKKOS/pair_tersoff_kokkos.h b/src/KOKKOS/pair_tersoff_kokkos.h index 7490d3f45a..9a3c152604 100644 --- a/src/KOKKOS/pair_tersoff_kokkos.h +++ b/src/KOKKOS/pair_tersoff_kokkos.h @@ -186,7 +186,7 @@ class PairTersoffKokkos : public PairTersoff { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um paramskk; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types //params_ters m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; int inum; @@ -225,6 +225,10 @@ class PairTersoffKokkos : public PairTersoff { /* ERROR/WARNING messages: +E: Cannot (yet) use full neighbor list style with tersoff/kk + +Self-explanatory. + E: Cannot use chosen neighbor list style with tersoff/kk Self-explanatory. diff --git a/src/KOKKOS/pair_tersoff_mod_kokkos.cpp b/src/KOKKOS/pair_tersoff_mod_kokkos.cpp index dd6adb128c..d89b411110 100644 --- a/src/KOKKOS/pair_tersoff_mod_kokkos.cpp +++ b/src/KOKKOS/pair_tersoff_mod_kokkos.cpp @@ -99,6 +99,9 @@ void PairTersoffMODKokkos::init_style() neighbor->requests[irequest]-> kokkos_device = Kokkos::Impl::is_same::value; + if (neighflag == FULL) + error->all(FLERR,"Cannot (yet) use full neighbor list style with tersoff/mod/kk"); + if (neighflag == FULL || neighflag == HALF || neighflag == HALFTHREAD) { neighbor->requests[irequest]->full = 1; neighbor->requests[irequest]->half = 0; @@ -107,7 +110,7 @@ void PairTersoffMODKokkos::init_style() else neighbor->requests[irequest]->ghost = 0; } else { - error->all(FLERR,"Cannot use chosen neighbor list style with tersoff/kk"); + error->all(FLERR,"Cannot use chosen neighbor list style with tersoff/mod/kk"); } } diff --git a/src/KOKKOS/pair_tersoff_mod_kokkos.h b/src/KOKKOS/pair_tersoff_mod_kokkos.h index 5a26fa1557..38320ca1be 100644 --- a/src/KOKKOS/pair_tersoff_mod_kokkos.h +++ b/src/KOKKOS/pair_tersoff_mod_kokkos.h @@ -186,7 +186,7 @@ class PairTersoffMODKokkos : public PairTersoffMOD { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um paramskk; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types //params_ters m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; int inum; @@ -225,7 +225,11 @@ class PairTersoffMODKokkos : public PairTersoffMOD { /* ERROR/WARNING messages: -E: Cannot use chosen neighbor list style with tersoff/kk +E: Cannot (yet) use full neighbor list style with tersoff/mod/kk + +Self-explanatory. + +E: Cannot use chosen neighbor list style with tersoff/mod/kk Self-explanatory. diff --git a/src/KOKKOS/pair_tersoff_zbl_kokkos.cpp b/src/KOKKOS/pair_tersoff_zbl_kokkos.cpp index 40145dbec0..04195d4e45 100644 --- a/src/KOKKOS/pair_tersoff_zbl_kokkos.cpp +++ b/src/KOKKOS/pair_tersoff_zbl_kokkos.cpp @@ -110,6 +110,9 @@ void PairTersoffZBLKokkos::init_style() neighbor->requests[irequest]-> kokkos_device = Kokkos::Impl::is_same::value; + if (neighflag == FULL) + error->all(FLERR,"Cannot (yet) use full neighbor list style with tersoff/zbl/kk"); + if (neighflag == FULL || neighflag == HALF || neighflag == HALFTHREAD) { neighbor->requests[irequest]->full = 1; neighbor->requests[irequest]->half = 0; diff --git a/src/KOKKOS/pair_tersoff_zbl_kokkos.h b/src/KOKKOS/pair_tersoff_zbl_kokkos.h index 136366d3fa..31c5912ff6 100644 --- a/src/KOKKOS/pair_tersoff_zbl_kokkos.h +++ b/src/KOKKOS/pair_tersoff_zbl_kokkos.h @@ -191,7 +191,7 @@ class PairTersoffZBLKokkos : public PairTersoffZBL { Kokkos::DualView k_params; typename Kokkos::DualView::t_dev_const_um paramskk; - // hardwired to space for 15 atom types + // hardwired to space for 12 atom types //params_ters m_params[MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1][MAX_TYPES_STACKPARAMS+1]; int inum; @@ -239,6 +239,10 @@ E: Pair tersoff/zbl/kk requires metal or real units This is a current restriction of this pair potential. +E: Cannot (yet) use full neighbor list style with tersoff/zbl/kk + +Self-explanatory. + E: Cannot use chosen neighbor list style with tersoff/zbl/kk Self-explanatory. diff --git a/src/KOKKOS/region_block_kokkos.cpp b/src/KOKKOS/region_block_kokkos.cpp index 68cc7e49c2..6734d7fdd1 100644 --- a/src/KOKKOS/region_block_kokkos.cpp +++ b/src/KOKKOS/region_block_kokkos.cpp @@ -46,7 +46,7 @@ RegBlockKokkos::~RegBlockKokkos() template KOKKOS_INLINE_FUNCTION -int RegBlockKokkos::inside(double x, double y, double z) const +int RegBlockKokkos::k_inside(double x, double y, double z) const { if (x >= xlo && x <= xhi && y >= ylo && y <= yhi && z >= zlo && z <= zhi) return 1; @@ -85,7 +85,7 @@ void RegBlockKokkos::operator()(TagRegBlockMatchAll, const int &i) c /* ---------------------------------------------------------------------- determine if point x,y,z is a match to region volume XOR computes 0 if 2 args are the same, 1 if different - note that inside() returns 1 for points on surface of region + note that k_inside() returns 1 for points on surface of region thus point on surface of exterior region will not match if region has variable shape, invoke shape_update() once per timestep if region is dynamic, apply inverse transform to x,y,z @@ -99,7 +99,7 @@ KOKKOS_INLINE_FUNCTION int RegBlockKokkos::match(double x, double y, double z) const { if (dynamic) inverse_transform(x,y,z); - return !(inside(x,y,z) ^ interior); + return !(k_inside(x,y,z) ^ interior); } /* ---------------------------------------------------------------------- diff --git a/src/KOKKOS/region_block_kokkos.h b/src/KOKKOS/region_block_kokkos.h index 19b3204973..f570e3ed33 100644 --- a/src/KOKKOS/region_block_kokkos.h +++ b/src/KOKKOS/region_block_kokkos.h @@ -52,7 +52,7 @@ class RegBlockKokkos : public RegBlock { typename AT::t_int_1d_randomread mask; KOKKOS_INLINE_FUNCTION - int inside(double, double, double) const; + int k_inside(double, double, double) const; KOKKOS_INLINE_FUNCTION int match(double, double, double) const; KOKKOS_INLINE_FUNCTION diff --git a/src/KSPACE/pair_lj_cut_tip4p_long.cpp b/src/KSPACE/pair_lj_cut_tip4p_long.cpp index 6e855e41f0..146d4e6f37 100644 --- a/src/KSPACE/pair_lj_cut_tip4p_long.cpp +++ b/src/KSPACE/pair_lj_cut_tip4p_long.cpp @@ -88,8 +88,8 @@ void PairLJCutTIP4PLong::compute(int eflag, int vflag) double r,r2inv,r6inv,forcecoul,forcelj,cforce; double factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; - double fO[3],fH[3],fd[3],v[6],xH1[3],xH2[3]; - double *x1,*x2; + double fO[3],fH[3],fd[3],v[6]; + double *x1,*x2,*xH1,*xH2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; @@ -146,14 +146,20 @@ void PairLJCutTIP4PLong::compute(int eflag, int vflag) if (itype == typeO) { if (hneigh[i][0] < 0) { - hneigh[i][0] = iH1 = atom->map(tag[i] + 1); - hneigh[i][1] = iH2 = atom->map(tag[i] + 2); - hneigh[i][2] = 1; + iH1 = atom->map(tag[i] + 1); + iH2 = atom->map(tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); + hneigh[i][0] = iH1; + hneigh[i][1] = iH2; + hneigh[i][2] = 1; + } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; @@ -216,14 +222,20 @@ void PairLJCutTIP4PLong::compute(int eflag, int vflag) if (jtype == typeO) { if (hneigh[j][0] < 0) { - hneigh[j][0] = jH1 = atom->map(tag[j] + 1); - hneigh[j][1] = jH2 = atom->map(tag[j] + 2); - hneigh[j][2] = 1; + jH1 = atom->map(tag[j] + 1); + jH2 = atom->map(tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); + hneigh[j][0] = jH1; + hneigh[j][1] = jH2; + hneigh[j][2] = 1; + } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; @@ -327,9 +339,8 @@ void PairLJCutTIP4PLong::compute(int eflag, int vflag) f[iH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[i],x[iH1],xH1); - domain->closest_image(x[i],x[iH2],xH2); - + xH1 = x[iH1]; + xH2 = x[iH2]; v[0] = x[i][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] = x[i][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] = x[i][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -385,9 +396,8 @@ void PairLJCutTIP4PLong::compute(int eflag, int vflag) f[jH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[j],x[jH1],xH1); - domain->closest_image(x[j],x[jH2],xH2); - + xH1 = x[jH1]; + xH2 = x[jH2]; v[0] += x[j][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] += x[j][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] += x[j][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -565,12 +575,10 @@ void PairLJCutTIP4PLong::compute_newsite(double *xO, double *xH1, double delx1 = xH1[0] - xO[0]; double dely1 = xH1[1] - xO[1]; double delz1 = xH1[2] - xO[2]; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2[0] - xO[0]; double dely2 = xH2[1] - xO[1]; double delz2 = xH2[2] - xO[2]; - domain->minimum_image(delx2,dely2,delz2); xM[0] = xO[0] + alpha * 0.5 * (delx1 + delx2); xM[1] = xO[1] + alpha * 0.5 * (dely1 + dely2); diff --git a/src/KSPACE/pair_lj_long_tip4p_long.cpp b/src/KSPACE/pair_lj_long_tip4p_long.cpp index b8ce8ece4c..c3d95c37a6 100644 --- a/src/KSPACE/pair_lj_long_tip4p_long.cpp +++ b/src/KSPACE/pair_lj_long_tip4p_long.cpp @@ -86,8 +86,8 @@ void PairLJLongTIP4PLong::compute(int eflag, int vflag) double r,r2inv,forcecoul,forcelj,cforce; double factor_coul; double grij,expm2,prefactor,t,erfc; - double fO[3],fH[3],fd[3],v[6],xH1[3],xH2[3];// f1[3]; - double *x1,*x2; + double fO[3],fH[3],fd[3],v[6]; + double *x1,*x2,*xH1,*xH2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; @@ -145,14 +145,20 @@ void PairLJLongTIP4PLong::compute(int eflag, int vflag) itype = type[i]; if (itype == typeO) { if (hneigh[i][0] < 0) { - hneigh[i][0] = iH1 = atom->map(tag[i] + 1); - hneigh[i][1] = iH2 = atom->map(tag[i] + 2); - hneigh[i][2] = 1; + iH1 = atom->map(tag[i] + 1); + iH2 = atom->map(tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); + hneigh[i][0] = iH1; + hneigh[i][1] = iH2; + hneigh[i][2] = 1; + } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; @@ -253,14 +259,20 @@ void PairLJLongTIP4PLong::compute(int eflag, int vflag) if (itype == typeO || jtype == typeO) { if (jtype == typeO) { if (hneigh[j][0] < 0) { - hneigh[j][0] = jH1 = atom->map(tag[j] + 1); - hneigh[j][1] = jH2 = atom->map(tag[j] + 2); - hneigh[j][2] = 1; + jH1 = atom->map(tag[j] + 1); + jH2 = atom->map(tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); + hneigh[j][0] = jH1; + hneigh[j][1] = jH2; + hneigh[j][2] = 1; + } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; @@ -365,9 +377,8 @@ void PairLJLongTIP4PLong::compute(int eflag, int vflag) f[iH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[i],x[iH1],xH1); - domain->closest_image(x[i],x[iH2],xH2); - + xH1 = x[iH1]; + xH2 = x[iH2]; v[0] = x[i][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] = x[i][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] = x[i][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -423,9 +434,8 @@ void PairLJLongTIP4PLong::compute(int eflag, int vflag) f[jH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[j],x[jH1],xH1); - domain->closest_image(x[j],x[jH2],xH2); - + xH1 = x[jH1]; + xH2 = x[jH2]; v[0] += x[j][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] += x[j][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] += x[j][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -1548,12 +1558,10 @@ void PairLJLongTIP4PLong::compute_newsite(double *xO, double *xH1, double delx1 = xH1[0] - xO[0]; double dely1 = xH1[1] - xO[1]; double delz1 = xH1[2] - xO[2]; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2[0] - xO[0]; double dely2 = xH2[1] - xO[1]; double delz2 = xH2[2] - xO[2]; - domain->minimum_image(delx2,dely2,delz2); xM[0] = xO[0] + alpha * 0.5 * (delx1 + delx2); xM[1] = xO[1] + alpha * 0.5 * (dely1 + dely2); diff --git a/src/KSPACE/pair_tip4p_long.cpp b/src/KSPACE/pair_tip4p_long.cpp index 0753a3f34d..1dd57ce822 100644 --- a/src/KSPACE/pair_tip4p_long.cpp +++ b/src/KSPACE/pair_tip4p_long.cpp @@ -84,8 +84,8 @@ void PairTIP4PLong::compute(int eflag, int vflag) double r,r2inv,forcecoul,cforce; double factor_coul; double grij,expm2,prefactor,t,erfc; - double fO[3],fH[3],fd[3],v[6],xH1[3],xH2[3]; - double *x1,*x2; + double fO[3],fH[3],fd[3],v[6]; + double *x1,*x2,*xH1,*xH2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; @@ -140,14 +140,20 @@ void PairTIP4PLong::compute(int eflag, int vflag) if (itype == typeO) { if (hneigh[i][0] < 0) { - hneigh[i][0] = iH1 = atom->map(tag[i] + 1); - hneigh[i][1] = iH2 = atom->map(tag[i] + 2); - hneigh[i][2] = 1; + iH1 = atom->map(tag[i] + 1); + iH2 = atom->map(tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); + hneigh[i][0] = iH1; + hneigh[i][1] = iH2; + hneigh[i][2] = 1; + } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; @@ -184,14 +190,20 @@ void PairTIP4PLong::compute(int eflag, int vflag) if (jtype == typeO) { if (hneigh[j][0] < 0) { - hneigh[j][0] = jH1 = atom->map(tag[j] + 1); - hneigh[j][1] = jH2 = atom->map(tag[j] + 2); - hneigh[j][2] = 1; + jH1 = atom->map(tag[j] + 1); + jH2 = atom->map(tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); + hneigh[j][0] = jH1; + hneigh[j][1] = jH2; + hneigh[j][2] = 1; + } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; @@ -295,9 +307,8 @@ void PairTIP4PLong::compute(int eflag, int vflag) f[iH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[i],x[iH1],xH1); - domain->closest_image(x[i],x[iH2],xH2); - + xH1 = x[iH1]; + xH2 = x[iH2]; v[0] = x[i][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] = x[i][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] = x[i][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -353,9 +364,8 @@ void PairTIP4PLong::compute(int eflag, int vflag) f[jH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[j],x[jH1],xH1); - domain->closest_image(x[j],x[jH2],xH2); - + xH1 = x[jH1]; + xH2 = x[jH2]; v[0] += x[j][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] += x[j][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] += x[j][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -488,12 +498,10 @@ void PairTIP4PLong::compute_newsite(double *xO, double *xH1, double delx1 = xH1[0] - xO[0]; double dely1 = xH1[1] - xO[1]; double delz1 = xH1[2] - xO[2]; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2[0] - xO[0]; double dely2 = xH2[1] - xO[1]; double delz2 = xH2[2] - xO[2]; - domain->minimum_image(delx2,dely2,delz2); xM[0] = xO[0] + alpha * 0.5 * (delx1 + delx2); xM[1] = xO[1] + alpha * 0.5 * (dely1 + dely2); diff --git a/src/KSPACE/pppm.cpp b/src/KSPACE/pppm.cpp old mode 100644 new mode 100755 diff --git a/src/KSPACE/pppm_cg.cpp b/src/KSPACE/pppm_cg.cpp index bbc238284d..8076f0f058 100644 --- a/src/KSPACE/pppm_cg.cpp +++ b/src/KSPACE/pppm_cg.cpp @@ -54,8 +54,6 @@ PPPMCG::PPPMCG(LAMMPS *lmp, int narg, char **arg) : PPPM(lmp, narg, arg), if ((narg < 1) || (narg > 2)) error->all(FLERR,"Illegal kspace_style pppm/cg command"); - triclinic_support = 0; - if (narg == 2) smallq = fabs(force->numeric(FLERR,arg[1])); else smallq = SMALLQ; @@ -91,6 +89,17 @@ void PPPMCG::compute(int eflag, int vflag) cg_peratom->setup(); } + // if atom count has changed, update qsum and qsqsum + + if (atom->natoms != natoms_original) { + qsum_qsq(); + natoms_original = atom->natoms; + } + + // return if there are no charges + + if (qsqsum == 0.0) return; + // convert atoms from box to lamda coords if (triclinic == 0) boxlo = domain->boxlo; @@ -207,13 +216,6 @@ void PPPMCG::compute(int eflag, int vflag) if (evflag_atom) fieldforce_peratom(); - // update qsum and qsqsum, if atom count has changed and energy needed - - if ((eflag_global || eflag_atom) && atom->natoms != natoms_original) { - qsum_qsq(); - natoms_original = atom->natoms; - } - // sum global energy across procs and add in volume-dependent term const double qscale = qqrd2e * scale; diff --git a/src/KSPACE/pppm_disp_tip4p.cpp b/src/KSPACE/pppm_disp_tip4p.cpp index d5a85abb4c..cf3a3943b9 100644 --- a/src/KSPACE/pppm_disp_tip4p.cpp +++ b/src/KSPACE/pppm_disp_tip4p.cpp @@ -502,17 +502,20 @@ void PPPMDispTIP4P::find_M(int i, int &iH1, int &iH2, double *xM) if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); + double **x = atom->x; double delx1 = x[iH1][0] - x[i][0]; double dely1 = x[iH1][1] - x[i][1]; double delz1 = x[iH1][2] - x[i][2]; - domain->minimum_image(delx1,dely1,delz1); double delx2 = x[iH2][0] - x[i][0]; double dely2 = x[iH2][1] - x[i][1]; double delz2 = x[iH2][2] - x[i][2]; - domain->minimum_image(delx2,dely2,delz2); xM[0] = x[i][0] + alpha * 0.5 * (delx1 + delx2); xM[1] = x[i][1] + alpha * 0.5 * (dely1 + dely2); diff --git a/src/KSPACE/pppm_tip4p.cpp b/src/KSPACE/pppm_tip4p.cpp old mode 100644 new mode 100755 index 34d0616fe9..fa5820cb34 --- a/src/KSPACE/pppm_tip4p.cpp +++ b/src/KSPACE/pppm_tip4p.cpp @@ -493,17 +493,20 @@ void PPPMTIP4P::find_M(int i, int &iH1, int &iH2, double *xM) if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); + double **x = atom->x; double delx1 = x[iH1][0] - x[i][0]; double dely1 = x[iH1][1] - x[i][1]; double delz1 = x[iH1][2] - x[i][2]; - domain->minimum_image(delx1,dely1,delz1); double delx2 = x[iH2][0] - x[i][0]; double dely2 = x[iH2][1] - x[i][1]; double delz2 = x[iH2][2] - x[i][2]; - domain->minimum_image(delx2,dely2,delz2); xM[0] = x[i][0] + alpha * 0.5 * (delx1 + delx2); xM[1] = x[i][1] + alpha * 0.5 * (dely1 + dely2); diff --git a/src/KSPACE/pppm_tip4p.h b/src/KSPACE/pppm_tip4p.h old mode 100644 new mode 100755 diff --git a/src/MAKE/MACHINES/Makefile.white b/src/MAKE/MACHINES/Makefile.white new file mode 100644 index 0000000000..ae31664b0d --- /dev/null +++ b/src/MAKE/MACHINES/Makefile.white @@ -0,0 +1,125 @@ +# kokkos_cuda = KOKKOS/CUDA package, OpenMPI with nvcc compiler, Kepler GPU + +SHELL = /bin/sh + +# --------------------------------------------------------------------- +# compiler/linker settings +# specify flags and libraries needed for your compiler + +KOKKOS_ABSOLUTE_PATH = $(shell cd $(KOKKOS_PATH); pwd) +export OMPI_CXX = $(KOKKOS_ABSOLUTE_PATH)/config/nvcc_wrapper +CC = mpicxx +CCFLAGS = -g -O3 +SHFLAGS = -fPIC +DEPFLAGS = -M + +LINK = mpicxx +LINKFLAGS = -g -O3 +LIB = +SIZE = size + +ARCHIVE = ar +ARFLAGS = -rc +SHLIBFLAGS = -shared +KOKKOS_DEVICES = Cuda, OpenMP +KOKKOS_ARCH = Kepler35 +KOKKOS_CUDA_OPTIONS = enable_lambda + +# --------------------------------------------------------------------- +# LAMMPS-specific settings, all OPTIONAL +# specify settings for LAMMPS features you will use +# if you change any -D setting, do full re-compile after "make clean" + +# LAMMPS ifdef settings +# see possible settings in Section 2.2 (step 4) of manual + +LMP_INC = -DLAMMPS_GZIP + +# MPI library +# see discussion in Section 2.2 (step 5) of manual +# MPI wrapper compiler/linker can provide this info +# can point to dummy MPI library in src/STUBS as in Makefile.serial +# use -D MPICH and OMPI settings in INC to avoid C++ lib conflicts +# INC = path for mpi.h, MPI compiler settings +# PATH = path for MPI library +# LIB = name of MPI library + +MPI_INC = -DMPICH_SKIP_MPICXX -DOMPI_SKIP_MPICXX=1 +MPI_PATH = +MPI_LIB = + +# FFT library +# see discussion in Section 2.2 (step 6) of manaul +# can be left blank to use provided KISS FFT library +# INC = -DFFT setting, e.g. -DFFT_FFTW, FFT compiler settings +# PATH = path for FFT library +# LIB = name of FFT library + +FFT_INC = +FFT_PATH = +FFT_LIB = + +# JPEG and/or PNG library +# see discussion in Section 2.2 (step 7) of manual +# only needed if -DLAMMPS_JPEG or -DLAMMPS_PNG listed with LMP_INC +# INC = path(s) for jpeglib.h and/or png.h +# PATH = path(s) for JPEG library and/or PNG library +# LIB = name(s) of JPEG library and/or PNG library + +JPG_INC = +JPG_PATH = +JPG_LIB = + +# --------------------------------------------------------------------- +# build rules and dependencies +# do not edit this section + +include Makefile.package.settings +include Makefile.package + +EXTRA_INC = $(LMP_INC) $(PKG_INC) $(MPI_INC) $(FFT_INC) $(JPG_INC) $(PKG_SYSINC) +EXTRA_PATH = $(PKG_PATH) $(MPI_PATH) $(FFT_PATH) $(JPG_PATH) $(PKG_SYSPATH) +EXTRA_LIB = $(PKG_LIB) $(MPI_LIB) $(FFT_LIB) $(JPG_LIB) $(PKG_SYSLIB) +EXTRA_CPP_DEPENDS = $(PKG_CPP_DEPENDS) +EXTRA_LINK_DEPENDS = $(PKG_LINK_DEPENDS) + +# Path to src files + +vpath %.cpp .. +vpath %.h .. + +# Link target + +$(EXE): $(OBJ) $(EXTRA_LINK_DEPENDS) + $(LINK) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(EXTRA_LIB) $(LIB) -o $(EXE) + $(SIZE) $(EXE) + +# Library targets + +lib: $(OBJ) $(EXTRA_LINK_DEPENDS) + $(ARCHIVE) $(ARFLAGS) $(EXE) $(OBJ) + +shlib: $(OBJ) $(EXTRA_LINK_DEPENDS) + $(CC) $(CCFLAGS) $(SHFLAGS) $(SHLIBFLAGS) $(EXTRA_PATH) -o $(EXE) \ + $(OBJ) $(EXTRA_LIB) $(LIB) + +# Compilation rules + +%.o:%.cpp $(EXTRA_CPP_DEPENDS) + $(CC) $(CCFLAGS) $(SHFLAGS) $(EXTRA_INC) -c $< + +%.d:%.cpp $(EXTRA_CPP_DEPENDS) + $(CC) $(CCFLAGS) $(EXTRA_INC) $(DEPFLAGS) $< > $@ + +%.o:%.cu $(EXTRA_CPP_DEPENDS) + $(CC) $(CCFLAGS) $(SHFLAGS) $(EXTRA_INC) -c $< + +# Individual dependencies + +depend : fastdep.exe $(SRC) + @./fastdep.exe $(EXTRA_INC) -- $^ > .depend || exit 1 + +fastdep.exe: ../DEPEND/fastdep.c + gcc -O -o $@ $< + +sinclude .depend diff --git a/src/MOLECULE/fix_cmap.cpp b/src/MOLECULE/fix_cmap.cpp index da7d337b9b..26aaef60d7 100644 --- a/src/MOLECULE/fix_cmap.cpp +++ b/src/MOLECULE/fix_cmap.cpp @@ -62,10 +62,13 @@ using namespace MathConst; /* ---------------------------------------------------------------------- */ -FixCMAP::FixCMAP(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg), - crosstermlist(NULL), num_crossterm(NULL), crossterm_type(NULL), crossterm_atom1(NULL), - crossterm_atom2(NULL), crossterm_atom3(NULL), crossterm_atom4(NULL), crossterm_atom5(NULL), - g_axis(NULL), cmapgrid(NULL), d1cmapgrid(NULL), d2cmapgrid(NULL), d12cmapgrid(NULL) +FixCMAP::FixCMAP(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg), + crosstermlist(NULL), num_crossterm(NULL), crossterm_type(NULL), + crossterm_atom1(NULL), crossterm_atom2(NULL), crossterm_atom3(NULL), + crossterm_atom4(NULL), crossterm_atom5(NULL), + g_axis(NULL), cmapgrid(NULL), d1cmapgrid(NULL), d2cmapgrid(NULL), + d12cmapgrid(NULL) { if (narg != 4) error->all(FLERR,"Illegal fix cmap command"); @@ -208,6 +211,13 @@ void FixCMAP::setup_pre_neighbor() /* --------------------------------------------------------------------- */ +void FixCMAP::setup_pre_reverse(int eflag, int vflag) +{ + pre_reverse(eflag,vflag); +} + +/* --------------------------------------------------------------------- */ + void FixCMAP::min_setup(int vflag) { pre_neighbor(); diff --git a/src/MOLECULE/fix_cmap.h b/src/MOLECULE/fix_cmap.h index 3573d213e8..d384d61d7d 100644 --- a/src/MOLECULE/fix_cmap.h +++ b/src/MOLECULE/fix_cmap.h @@ -31,6 +31,7 @@ class FixCMAP : public Fix { void init(); void setup(int); void setup_pre_neighbor(); + void setup_pre_reverse(int, int); void min_setup(int); void pre_neighbor(); void pre_reverse(int, int); diff --git a/src/MOLECULE/pair_lj_cut_tip4p_cut.cpp b/src/MOLECULE/pair_lj_cut_tip4p_cut.cpp index a9e00e80b4..15f5d52961 100644 --- a/src/MOLECULE/pair_lj_cut_tip4p_cut.cpp +++ b/src/MOLECULE/pair_lj_cut_tip4p_cut.cpp @@ -87,8 +87,8 @@ void PairLJCutTIP4PCut::compute(int eflag, int vflag) int n,vlist[6]; int iH1,iH2,jH1,jH2; double cforce; - double fO[3],fH[3],fd[3],v[6],xH1[3],xH2[3]; - double *x1,*x2; + double fO[3],fH[3],fd[3],v[6]; + double *x1,*x2,*xH1,*xH2; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); @@ -139,14 +139,20 @@ void PairLJCutTIP4PCut::compute(int eflag, int vflag) if (itype == typeO) { if (hneigh[i][0] < 0) { - hneigh[i][0] = iH1 = atom->map(tag[i] + 1); - hneigh[i][1] = iH2 = atom->map(tag[i] + 2); - hneigh[i][2] = 1; + iH1 = atom->map(tag[i] + 1); + iH2 = atom->map(tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); + hneigh[i][0] = iH1; + hneigh[i][1] = iH2; + hneigh[i][2] = 1; + } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; @@ -209,14 +215,20 @@ void PairLJCutTIP4PCut::compute(int eflag, int vflag) if (jtype == typeO) { if (hneigh[j][0] < 0) { - hneigh[j][0] = jH1 = atom->map(tag[j] + 1); - hneigh[j][1] = jH2 = atom->map(tag[j] + 2); - hneigh[j][2] = 1; + jH1 = atom->map(tag[j] + 1); + jH2 = atom->map(tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); + hneigh[j][0] = jH1; + hneigh[j][1] = jH2; + hneigh[j][2] = 1; + } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; @@ -294,10 +306,9 @@ void PairLJCutTIP4PCut::compute(int eflag, int vflag) f[iH2][1] += fH[1]; f[iH2][2] += fH[2]; - if(vflag) { - domain->closest_image(x[i],x[iH1],xH1); - domain->closest_image(x[i],x[iH2],xH2); - + if (vflag) { + xH1 = x[iH1]; + xH2 = x[iH2]; v[0] = x[i][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] = x[i][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] = x[i][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -353,9 +364,8 @@ void PairLJCutTIP4PCut::compute(int eflag, int vflag) f[jH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[j],x[jH1],xH1); - domain->closest_image(x[j],x[jH2],xH2); - + xH1 = x[jH1]; + xH2 = x[jH2]; v[0] += x[j][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] += x[j][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] += x[j][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -711,12 +721,10 @@ void PairLJCutTIP4PCut::compute_newsite(double *xO, double *xH1, double delx1 = xH1[0] - xO[0]; double dely1 = xH1[1] - xO[1]; double delz1 = xH1[2] - xO[2]; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2[0] - xO[0]; double dely2 = xH2[1] - xO[1]; double delz2 = xH2[2] - xO[2]; - domain->minimum_image(delx2,dely2,delz2); xM[0] = xO[0] + alpha * 0.5 * (delx1 + delx2); xM[1] = xO[1] + alpha * 0.5 * (dely1 + dely2); diff --git a/src/MOLECULE/pair_tip4p_cut.cpp b/src/MOLECULE/pair_tip4p_cut.cpp index dd48637f23..954bd35435 100644 --- a/src/MOLECULE/pair_tip4p_cut.cpp +++ b/src/MOLECULE/pair_tip4p_cut.cpp @@ -75,8 +75,8 @@ void PairTIP4PCut::compute(int eflag, int vflag) int n,vlist[6]; int iH1,iH2,jH1,jH2; double cforce; - double fO[3],fH[3],fd[3],v[6],xH1[3],xH2[3]; - double *x1,*x2; + double fO[3],fH[3],fd[3],v[6]; + double *x1,*x2,*xH1,*xH2; ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); @@ -125,14 +125,20 @@ void PairTIP4PCut::compute(int eflag, int vflag) if (itype == typeO) { if (hneigh[i][0] < 0) { - hneigh[i][0] = iH1 = atom->map(tag[i] + 1); - hneigh[i][1] = iH2 = atom->map(tag[i] + 2); - hneigh[i][2] = 1; + iH1 = atom->map(tag[i] + 1); + iH2 = atom->map(tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); + hneigh[i][0] = iH1; + hneigh[i][1] = iH2; + hneigh[i][2] = 1; + } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; @@ -169,14 +175,20 @@ void PairTIP4PCut::compute(int eflag, int vflag) if (jtype == typeO) { if (hneigh[j][0] < 0) { - hneigh[j][0] = jH1 = atom->map(tag[j] + 1); - hneigh[j][1] = jH2 = atom->map(tag[j] + 2); - hneigh[j][2] = 1; + jH1 = atom->map(tag[j] + 1); + jH2 = atom->map(tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); + hneigh[j][0] = jH1; + hneigh[j][1] = jH2; + hneigh[j][2] = 1; + } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; @@ -255,9 +267,8 @@ void PairTIP4PCut::compute(int eflag, int vflag) f[iH2][2] += fH[2]; if(vflag) { - domain->closest_image(x[i],x[iH1],xH1); - domain->closest_image(x[i],x[iH2],xH2); - + xH1 = x[iH1]; + xH2 = x[iH2]; v[0] = x[i][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] = x[i][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] = x[i][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -313,9 +324,8 @@ void PairTIP4PCut::compute(int eflag, int vflag) f[jH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[j],x[jH1],xH1); - domain->closest_image(x[j],x[jH2],xH2); - + xH1 = x[jH1]; + xH2 = x[jH2]; v[0] += x[j][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] += x[j][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] += x[j][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -526,12 +536,10 @@ void PairTIP4PCut::compute_newsite(double *xO, double *xH1, double delx1 = xH1[0] - xO[0]; double dely1 = xH1[1] - xO[1]; double delz1 = xH1[2] - xO[2]; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2[0] - xO[0]; double dely2 = xH2[1] - xO[1]; double delz2 = xH2[2] - xO[2]; - domain->minimum_image(delx2,dely2,delz2); xM[0] = xO[0] + alpha * 0.5 * (delx1 + delx2); xM[1] = xO[1] + alpha * 0.5 * (dely1 + dely2); diff --git a/src/OPT/pair_lj_cut_tip4p_long_opt.cpp b/src/OPT/pair_lj_cut_tip4p_long_opt.cpp index 2cca32baec..db9402b521 100644 --- a/src/OPT/pair_lj_cut_tip4p_long_opt.cpp +++ b/src/OPT/pair_lj_cut_tip4p_long_opt.cpp @@ -111,9 +111,9 @@ void PairLJCutTIP4PLongOpt::eval() double r,rsq,r2inv,r6inv,forcecoul,forcelj,cforce; double factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; - double v[6],xH1[3],xH2[3]; + double v[6]; double fdx,fdy,fdz,fOx,fOy,fOz,fHx,fHy,fHz; - const double *x1,*x2; + const double *x1,*x2,*xH1,*xH2; int *ilist,*jlist,*numneigh,**firstneigh; int i,j,ii,jj,inum,jnum,itype,jtype,itable,key; @@ -155,14 +155,21 @@ void PairLJCutTIP4PLongOpt::eval() if (itype == typeO) { if (hneigh[i][0] < 0) { - hneigh[i][0] = iH1 = atom->map(tag[i] + 1); - hneigh[i][1] = iH2 = atom->map(tag[i] + 2); + iH1 = atom->map(tag[i] + 1); + iH2 = atom->map(tag[i] + 2); hneigh[i][2] = 1; if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite_opt(x[i],x[iH1],x[iH2],newsite[i]); + hneigh[i][0] = iH1; + hneigh[i][1] = iH2; + hneigh[i][2] = 1; + } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; @@ -226,14 +233,21 @@ void PairLJCutTIP4PLongOpt::eval() if (jtype == typeO) { if (hneigh[j][0] < 0) { - hneigh[j][0] = jH1 = atom->map(tag[j] + 1); - hneigh[j][1] = jH2 = atom->map(tag[j] + 2); + jH1 = atom->map(tag[j] + 1); + jH2 = atom->map(tag[j] + 2); hneigh[j][2] = 1; if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite_opt(x[j],x[jH1],x[jH2],newsite[j]); + hneigh[j][0] = jH1; + hneigh[j][1] = jH2; + hneigh[j][2] = 1; + } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; @@ -339,9 +353,8 @@ void PairLJCutTIP4PLongOpt::eval() f[iH2][2] += fHz; if (VFLAG) { - domain->closest_image(x[i],x[iH1],xH1); - domain->closest_image(x[i],x[iH2],xH2); - + xH1 = x[iH1]; + xH2 = x[iH2]; v[0] = x[i][0]*fOx + xH1[0]*fHx + xH2[0]*fHx; v[1] = x[i][1]*fOy + xH1[1]*fHy + xH2[1]*fHy; v[2] = x[i][2]*fOz + xH1[2]*fHz + xH2[2]*fHz; @@ -399,9 +412,8 @@ void PairLJCutTIP4PLongOpt::eval() f[jH2][2] += fHz; if (VFLAG) { - domain->closest_image(x[j],x[jH1],xH1); - domain->closest_image(x[j],x[jH2],xH2); - + xH1 = x[jH1]; + xH2 = x[jH2]; v[0] += x[j][0]*fOx + xH1[0]*fHx + xH2[0]*fHx; v[1] += x[j][1]*fOy + xH1[1]*fHy + xH2[1]*fHy; v[2] += x[j][2]*fOz + xH1[2]*fHz + xH2[2]*fHz; @@ -448,12 +460,10 @@ void PairLJCutTIP4PLongOpt::compute_newsite_opt(const double * xO, double delx1 = xH1[0] - xO[0]; double dely1 = xH1[1] - xO[1]; double delz1 = xH1[2] - xO[2]; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2[0] - xO[0]; double dely2 = xH2[1] - xO[1]; double delz2 = xH2[2] - xO[2]; - domain->minimum_image(delx2,dely2,delz2); const double prefac = alpha * 0.5; xM[0] = xO[0] + prefac * (delx1 + delx2); diff --git a/src/QEQ/fix_qeq.cpp b/src/QEQ/fix_qeq.cpp index 01d51e12ed..7e8db7632c 100644 --- a/src/QEQ/fix_qeq.cpp +++ b/src/QEQ/fix_qeq.cpp @@ -310,13 +310,6 @@ void FixQEq::setup_pre_force_respa(int vflag, int ilevel) /* ---------------------------------------------------------------------- */ -void FixQEq::min_setup_pre_force(int vflag) -{ - setup_pre_force(vflag); -} - -/* ---------------------------------------------------------------------- */ - void FixQEq::init_storage() { nlocal = atom->nlocal; diff --git a/src/QEQ/fix_qeq.h b/src/QEQ/fix_qeq.h index 152ffd4e32..ed87412284 100644 --- a/src/QEQ/fix_qeq.h +++ b/src/QEQ/fix_qeq.h @@ -33,7 +33,6 @@ class FixQEq : public Fix { void setup_pre_force(int); void setup_pre_force_respa(int, int); void pre_force_respa(int, int, int); - void min_setup_pre_force(int); void min_pre_force(int); // derived child classes must provide these functions diff --git a/src/REPLICA/compute_event_displace.cpp b/src/REPLICA/compute_event_displace.cpp index cdd0e5de40..1431fc202e 100644 --- a/src/REPLICA/compute_event_displace.cpp +++ b/src/REPLICA/compute_event_displace.cpp @@ -48,7 +48,7 @@ ComputeEventDisplace::ComputeEventDisplace(LAMMPS *lmp, int narg, char **arg) : error->all(FLERR,"Distance must be > 0 for compute event/displace"); displace_distsq = displace_dist * displace_dist; - // fix event ID will be set later by PRD + // fix event ID will be set later by accelerated dynamics method id_event = NULL; } @@ -75,7 +75,8 @@ void ComputeEventDisplace::init() fix_event = (FixEvent*) modify->fix[ifix]; if (strcmp(fix_event->style,"EVENT/PRD") != 0 && - strcmp(fix_event->style,"EVENT/TAD") != 0) + strcmp(fix_event->style,"EVENT/TAD") != 0 && + strcmp(fix_event->style,"EVENT/HYPER") != 0) error->all(FLERR,"Compute event/displace has invalid fix event assigned"); } diff --git a/src/REPLICA/fix_neb.cpp b/src/REPLICA/fix_neb.cpp index 939e4d7fac..249339191a 100644 --- a/src/REPLICA/fix_neb.cpp +++ b/src/REPLICA/fix_neb.cpp @@ -395,7 +395,7 @@ void FixNEB::inter_replica_comm() // ----------------------------------------------------- // single proc per replica - // all atoms are NEB atoms and no atom sorting + // all atoms are NEB atoms and no atom sorting is enabled // direct comm of x -> xprev and x -> xnext if (cmode == SINGLE_PROC_DIRECT) { diff --git a/src/USER-ATC/fix_atc.cpp b/src/USER-ATC/fix_atc.cpp index 0dc10e1773..96ad93481d 100644 --- a/src/USER-ATC/fix_atc.cpp +++ b/src/USER-ATC/fix_atc.cpp @@ -632,16 +632,6 @@ void FixATC::min_pre_exchange() throw; } } -void FixATC::min_setup_pre_exchange() -{ - try { - atc_->setup_pre_exchange(); - } - catch (ATC::ATC_Error& atcError) { - ATC::LammpsInterface::instance()->print_msg(atcError.error_description()); - throw; - } -} double FixATC::memory_usage() { @@ -896,19 +886,6 @@ void FixATC::setup_pre_neighbor() } } /* ---------------------------------------------------------------------- */ -void FixATC::min_setup_pre_neighbor() -{ - if (atc_->is_initialized()) { - try { - atc_->pre_neighbor(); - } - catch (ATC::ATC_Error& atcError) { - ATC::LammpsInterface::instance()->print_msg(atcError.error_description()); - throw; - } - } -} -/* ---------------------------------------------------------------------- */ void FixATC::min_pre_force(int vflag) { try { diff --git a/src/USER-ATC/fix_atc.h b/src/USER-ATC/fix_atc.h index b87c585e73..2512c658db 100644 --- a/src/USER-ATC/fix_atc.h +++ b/src/USER-ATC/fix_atc.h @@ -52,7 +52,6 @@ namespace LAMMPS_NS { and is called before domain->pbc() and comm->exchange(). */ void setup_pre_exchange(); void pre_exchange(); - void min_setup_pre_exchange(); void min_pre_exchange(); double memory_usage(); @@ -84,7 +83,6 @@ namespace LAMMPS_NS { neighbor->build(). */ void pre_neighbor(); void setup_pre_neighbor(); - void min_setup_pre_neighbor(); /** pre/post_force is used to modify fix-specific data and is before/after the various force computations. */ diff --git a/src/USER-COLVARS/README b/src/USER-COLVARS/README index 759556aeb5..9090a07ead 100644 --- a/src/USER-COLVARS/README +++ b/src/USER-COLVARS/README @@ -1,49 +1,46 @@ -This package implements the "fix colvars" command which can be used +This package implements the "fix colvars" command, which can be used in a LAMMPS input script. -This fix allows use of "collective variables" to implement Adaptive -Biasing Force, Metadynamics, Steered MD, Umbrella Sampling and -Restraints. +The fix allows use of enhanced sampling methods based on a reduced set +of "collective variables", including free-energy estimators based on +thermodynamic forces, non-equilibrium work and probability +distributions. -This package uses an external library in lib/colvars which must be -compiled before making LAMMPS. See the lib/colvars/README file and -the LAMMPS manual for information on building LAMMPS with external -libraries. The settings in the Makefile.lammps file in that directory -must be correct for LAMMPS to build correctly with this package -installed. +The package uses the "Colvars" library, whose source code is included +in the LAMMPS source code distribution and must be linked with LAMMPS. +See the lib/colvars/README file and the LAMMPS manual for information +on building LAMMPS with external libraries. The settings in the +Makefile.lammps file in that directory must be correct for LAMMPS to +build correctly with this package installed. -The external library is a portable collective variable module library -written and maintained by Giacomo Fiorin (ICMS, Temple University, -Philadelphia, PA, USA) and Jerome Henin (IBPC, CNRS, Paris, France). +The files in the USER-COLVARS package folder implement an interface +between LAMMPS and Colvars, originally written by Axel Kohlmeyer +(akohlmey@gmail.com) and maintained by Giacomo Fiorin +(giacomo.fiorin@gmail.com). -More info about this library can be found at: http://colvars.github.io +More info about the Colvars library can be found at: -and in these publications: +https://github.com/colvars/colvars + +and in the reference article: Using collective variables to drive molecular dynamics simulations, -Giacomo Fiorin, Michael L. Klein & Jérôme Hénin: Molecular Physics, -111, 3345-3362 (2013) +G. Fiorin, M. L. Klein, and J. Henin, +Molecular Physics 111, 3345 (2013) +http://dx.doi.org/10.1080/00268976.2013.813594 -Exploring Multidimensional Free Energy Landscapes Using Time-Dependent -Biases on Collective Variables, J. Hénin, G. Fiorin, C. Chipot, and -M. L. Klein, J. Chem. Theory Comput., 6, 35-47 (2010). +A reference manual for the package and library is included with the +LAMMPS doc pages: +doc/PDF/colvars-refman-lammps.pdf +which also includes citations to the articles documenting the various +methods that make use Colvars. -The colvars fix implementes a thin interface layer, which exchanges -information between LAMMPS and the collective variable module. This -interface was written and is maintained by Axel Kohlmeyer -(akohlmey@gmail.com) +There are also example scripts for using this package in the folder +examples/USER/colvars, as well as the GitHub page for Colvars. -See the doc page of fix colvars for more details. - -There is a reference manual for the package included with the LAMMPS -doc pages: doc/PDF/colvars-refman-lammps.pdf - -There are example scripts for using this package in -examples/USER/colvars. - -The person who created this package is Axel Kohlmeyer at Temple U -(akohlmey at gmail.com). Contact him directly if you have questions. +Please contact Giacomo Fiorin (giacomo.fiorin@gmail.com) for questions +regarding this package. --------------------------------- -Version: 2015-01-08 +Version: 2016-12-22 diff --git a/src/USER-COLVARS/colvarproxy_lammps.cpp b/src/USER-COLVARS/colvarproxy_lammps.cpp index 350009f6bf..7320263ba7 100644 --- a/src/USER-COLVARS/colvarproxy_lammps.cpp +++ b/src/USER-COLVARS/colvarproxy_lammps.cpp @@ -1,3 +1,12 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + #include #include "lammps.h" diff --git a/src/USER-COLVARS/colvarproxy_lammps.h b/src/USER-COLVARS/colvarproxy_lammps.h index f1636e112b..c0b4ea20fe 100644 --- a/src/USER-COLVARS/colvarproxy_lammps.h +++ b/src/USER-COLVARS/colvarproxy_lammps.h @@ -1,5 +1,13 @@ // -*- c++ -*- +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + + #ifndef COLVARPROXY_LAMMPS_H #define COLVARPROXY_LAMMPS_H @@ -21,7 +29,7 @@ #endif #ifndef COLVARPROXY_VERSION -#define COLVARPROXY_VERSION "2016-10-05" +#define COLVARPROXY_VERSION "2016-12-27" #endif /* struct for packed data communication of coordinates and forces. */ diff --git a/src/USER-COLVARS/fix_colvars.cpp b/src/USER-COLVARS/fix_colvars.cpp index 6a3613d76a..59e6c46b76 100644 --- a/src/USER-COLVARS/fix_colvars.cpp +++ b/src/USER-COLVARS/fix_colvars.cpp @@ -1,3 +1,12 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories diff --git a/src/USER-COLVARS/fix_colvars.h b/src/USER-COLVARS/fix_colvars.h index a1dae0d757..c00b18aa46 100644 --- a/src/USER-COLVARS/fix_colvars.h +++ b/src/USER-COLVARS/fix_colvars.h @@ -1,3 +1,12 @@ +// -*- c++ -*- + +// This file is part of the Collective Variables module (Colvars). +// The original version of Colvars and its updates are located at: +// https://github.com/colvars/colvars +// Please update all Colvars source files before making any changes. +// If you wish to distribute your changes, please submit them to the +// Colvars repository at GitHub. + /* -*- c++ -*- ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories diff --git a/src/USER-COLVARS/group_ndx.cpp b/src/USER-COLVARS/group_ndx.cpp index 06b404098c..5076918039 100644 --- a/src/USER-COLVARS/group_ndx.cpp +++ b/src/USER-COLVARS/group_ndx.cpp @@ -1,3 +1,5 @@ +// -*- c++ -*- + /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories diff --git a/src/USER-COLVARS/group_ndx.h b/src/USER-COLVARS/group_ndx.h index e0104f176f..25c38dcf9f 100644 --- a/src/USER-COLVARS/group_ndx.h +++ b/src/USER-COLVARS/group_ndx.h @@ -1,4 +1,6 @@ -/* -*- c++ -*- ---------------------------------------------------------- +// -*- c++ -*- + +/* ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov diff --git a/src/USER-COLVARS/ndx_group.cpp b/src/USER-COLVARS/ndx_group.cpp index 31d8332c9c..c7972e372e 100644 --- a/src/USER-COLVARS/ndx_group.cpp +++ b/src/USER-COLVARS/ndx_group.cpp @@ -1,3 +1,5 @@ +// -*- c++ -*- + /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories @@ -10,9 +12,8 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ - /* ---------------------------------------------------------------------- - Contributing author: Axel Kohlmeyer (Temple U) + Contributing author: Axel Kohlmeyer (Temple U) ------------------------------------------------------------------------- */ #include "ndx_group.h" @@ -35,7 +36,7 @@ static char *find_section(FILE *fp, const char *name) { char linebuf[BUFLEN]; char *n,*p,*t,*r; - + while ((p = fgets(linebuf,BUFLEN,fp))) { t = strtok(p," \t\n\r\f"); if ((t != NULL) && *t == '[') { diff --git a/src/USER-COLVARS/ndx_group.h b/src/USER-COLVARS/ndx_group.h index 479c442f61..cd3250a1d5 100644 --- a/src/USER-COLVARS/ndx_group.h +++ b/src/USER-COLVARS/ndx_group.h @@ -1,4 +1,6 @@ -/* -*- c++ -*- ---------------------------------------------------------- +// -*- c++ -*- + +/* ---------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov diff --git a/src/USER-DPD/fix_shardlow.cpp b/src/USER-DPD/fix_shardlow.cpp index 108b82a5b6..5a25220730 100644 --- a/src/USER-DPD/fix_shardlow.cpp +++ b/src/USER-DPD/fix_shardlow.cpp @@ -180,13 +180,6 @@ void FixShardlow::min_pre_exchange() /* ---------------------------------------------------------------------- */ -void FixShardlow::min_setup_pre_exchange() -{ - memset(atom->ssaAIR, 0, sizeof(int)*atom->nlocal); -} - -/* ---------------------------------------------------------------------- */ - void FixShardlow::setup(int vflag) { bool fixShardlow = false; diff --git a/src/USER-DPD/fix_shardlow.h b/src/USER-DPD/fix_shardlow.h index 45a7b030b9..139a6de02c 100644 --- a/src/USER-DPD/fix_shardlow.h +++ b/src/USER-DPD/fix_shardlow.h @@ -37,7 +37,6 @@ class FixShardlow : public Fix { virtual void initial_integrate(int); void setup_pre_exchange(); void pre_exchange(); - void min_setup_pre_exchange(); void min_pre_exchange(); void grow_arrays(int); diff --git a/src/USER-FEP/pair_lj_cut_tip4p_long_soft.cpp b/src/USER-FEP/pair_lj_cut_tip4p_long_soft.cpp index 2edad28bf3..5beed08b72 100644 --- a/src/USER-FEP/pair_lj_cut_tip4p_long_soft.cpp +++ b/src/USER-FEP/pair_lj_cut_tip4p_long_soft.cpp @@ -86,8 +86,8 @@ void PairLJCutTIP4PLongSoft::compute(int eflag, int vflag) double factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; double denc, denlj, r4sig6; - double fO[3],fH[3],fd[3],v[6],xH1[3],xH2[3]; - double *x1,*x2; + double fO[3],fH[3],fd[3],v[6]; + double *x1,*x2,*xH1,*xH2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; @@ -143,14 +143,20 @@ void PairLJCutTIP4PLongSoft::compute(int eflag, int vflag) if (itype == typeO) { if (hneigh[i][0] < 0) { - hneigh[i][0] = iH1 = atom->map(atom->tag[i] + 1); - hneigh[i][1] = iH2 = atom->map(atom->tag[i] + 2); - hneigh[i][2] = 1; + iH1 = atom->map(atom->tag[i] + 1); + iH2 = atom->map(atom->tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); + hneigh[i][0] = iH1; + hneigh[i][1] = iH2; + hneigh[i][2] = 1; + } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; @@ -216,14 +222,20 @@ void PairLJCutTIP4PLongSoft::compute(int eflag, int vflag) if (jtype == typeO) { if (hneigh[j][0] < 0) { - hneigh[j][0] = jH1 = atom->map(atom->tag[j] + 1); - hneigh[j][1] = jH2 = atom->map(atom->tag[j] + 2); - hneigh[j][2] = 1; + jH1 = atom->map(atom->tag[j] + 1); + jH2 = atom->map(atom->tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); + hneigh[j][0] = jH1; + hneigh[j][1] = jH2; + hneigh[j][2] = 1; + } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; @@ -314,9 +326,8 @@ void PairLJCutTIP4PLongSoft::compute(int eflag, int vflag) f[iH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[i],x[iH1],xH1); - domain->closest_image(x[i],x[iH2],xH2); - + xH1 = x[iH1]; + xH2 = x[iH2]; v[0] = x[i][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] = x[i][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] = x[i][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -372,9 +383,8 @@ void PairLJCutTIP4PLongSoft::compute(int eflag, int vflag) f[jH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[j],x[jH1],xH1); - domain->closest_image(x[j],x[jH2],xH2); - + xH1 = x[jH1]; + xH2 = x[jH2]; v[0] += x[j][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] += x[j][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] += x[j][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -549,12 +559,10 @@ void PairLJCutTIP4PLongSoft::compute_newsite(double *xO, double *xH1, double delx1 = xH1[0] - xO[0]; double dely1 = xH1[1] - xO[1]; double delz1 = xH1[2] - xO[2]; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2[0] - xO[0]; double dely2 = xH2[1] - xO[1]; double delz2 = xH2[2] - xO[2]; - domain->minimum_image(delx2,dely2,delz2); xM[0] = xO[0] + alpha * 0.5 * (delx1 + delx2); xM[1] = xO[1] + alpha * 0.5 * (dely1 + dely2); diff --git a/src/USER-FEP/pair_tip4p_long_soft.cpp b/src/USER-FEP/pair_tip4p_long_soft.cpp index 027882cfba..7ad654d95c 100644 --- a/src/USER-FEP/pair_tip4p_long_soft.cpp +++ b/src/USER-FEP/pair_tip4p_long_soft.cpp @@ -85,8 +85,8 @@ void PairTIP4PLongSoft::compute(int eflag, int vflag) double factor_coul; double grij,expm2,prefactor,t,erfc; double denc; - double fO[3],fH[3],fd[3],v[6],xH1[3],xH2[3]; - double *x1,*x2; + double fO[3],fH[3],fd[3],v[6]; + double *x1,*x2,*xH1,*xH2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; @@ -140,14 +140,20 @@ void PairTIP4PLongSoft::compute(int eflag, int vflag) if (itype == typeO) { if (hneigh[i][0] < 0) { - hneigh[i][0] = iH1 = atom->map(atom->tag[i] + 1); - hneigh[i][1] = iH2 = atom->map(atom->tag[i] + 2); - hneigh[i][2] = 1; + iH1 = atom->map(atom->tag[i] + 1); + iH2 = atom->map(atom->tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite(x[i],x[iH1],x[iH2],newsite[i]); + hneigh[i][0] = iH1; + hneigh[i][1] = iH2; + hneigh[i][2] = 1; + } else { iH1 = hneigh[i][0]; iH2 = hneigh[i][1]; @@ -184,14 +190,20 @@ void PairTIP4PLongSoft::compute(int eflag, int vflag) if (jtype == typeO) { if (hneigh[j][0] < 0) { - hneigh[j][0] = jH1 = atom->map(atom->tag[j] + 1); - hneigh[j][1] = jH2 = atom->map(atom->tag[j] + 2); - hneigh[j][2] = 1; + jH1 = atom->map(atom->tag[j] + 1); + jH2 = atom->map(atom->tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite(x[j],x[jH1],x[jH2],newsite[j]); + hneigh[j][0] = jH1; + hneigh[j][1] = jH2; + hneigh[j][2] = 1; + } else { jH1 = hneigh[j][0]; jH2 = hneigh[j][1]; @@ -282,9 +294,8 @@ void PairTIP4PLongSoft::compute(int eflag, int vflag) f[iH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[i],x[iH1],xH1); - domain->closest_image(x[i],x[iH2],xH2); - + xH1 = x[iH1]; + xH2 = x[iH2]; v[0] = x[i][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] = x[i][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] = x[i][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -340,9 +351,8 @@ void PairTIP4PLongSoft::compute(int eflag, int vflag) f[jH2][2] += fH[2]; if (vflag) { - domain->closest_image(x[j],x[jH1],xH1); - domain->closest_image(x[j],x[jH2],xH2); - + xH1 = x[jH1]; + xH2 = x[jH2]; v[0] += x[j][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; v[1] += x[j][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; v[2] += x[j][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; @@ -473,12 +483,10 @@ void PairTIP4PLongSoft::compute_newsite(double *xO, double *xH1, double delx1 = xH1[0] - xO[0]; double dely1 = xH1[1] - xO[1]; double delz1 = xH1[2] - xO[2]; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2[0] - xO[0]; double dely2 = xH2[1] - xO[1]; double delz2 = xH2[2] - xO[2]; - domain->minimum_image(delx2,dely2,delz2); xM[0] = xO[0] + alpha * 0.5 * (delx1 + delx2); xM[1] = xO[1] + alpha * 0.5 * (dely1 + dely2); diff --git a/src/USER-INTEL/fix_intel.cpp b/src/USER-INTEL/fix_intel.cpp index 7c5dd0b34c..edd33eb72b 100644 --- a/src/USER-INTEL/fix_intel.cpp +++ b/src/USER-INTEL/fix_intel.cpp @@ -356,6 +356,13 @@ void FixIntel::setup(int vflag) /* ---------------------------------------------------------------------- */ +void FixIntel::setup_pre_reverse(int eflag, int vflag) +{ + pre_reverse(eflag,vflag); +} + +/* ---------------------------------------------------------------------- */ + void FixIntel::pair_init_check(const bool cdmessage) { #ifdef INTEL_VMASK diff --git a/src/USER-INTEL/fix_intel.h b/src/USER-INTEL/fix_intel.h index 6ffcb4ccab..f4c02b37b5 100644 --- a/src/USER-INTEL/fix_intel.h +++ b/src/USER-INTEL/fix_intel.h @@ -43,6 +43,8 @@ class FixIntel : public Fix { virtual int setmask(); virtual void init(); virtual void setup(int); + void setup_pre_reverse(int eflag = 0, int vflag = 0); + void pair_init_check(const bool cdmessage=false); void bond_init_check(); void kspace_init_check(); diff --git a/src/USER-MISC/README b/src/USER-MISC/README index 513973b4f5..8aed797235 100644 --- a/src/USER-MISC/README +++ b/src/USER-MISC/README @@ -43,6 +43,7 @@ fix gle, Michele Ceriotti (EPFL Lausanne), michele.ceriotti at gmail.com, 24 Nov fix grem, David Stelter, dstelter@bu.edu, 22 Nov 16 fix imd, Axel Kohlmeyer, akohlmey at gmail.com, 9 Nov 2009 fix ipi, Michele Ceriotti (EPFL Lausanne), michele.ceriotti at gmail.com, 24 Nov 2014 +fix nvk, Efrem Braun (UC Berkeley), efrem.braun at gmail.com, https://github.com/lammps/lammps/pull/310 fix pimd, Yuxing Peng (U Chicago), yuxing at uchicago.edu, 24 Nov 2014 fix smd, Axel Kohlmeyer, akohlmey at gmail.com, 19 May 2008 fix ti/spring, Rodrigo Freitas (Unicamp/Brazil), rodrigohb at gmail.com, 7 Nov 2013 diff --git a/src/USER-MISC/fix_nvk.cpp b/src/USER-MISC/fix_nvk.cpp new file mode 100644 index 0000000000..5dcfe53e78 --- /dev/null +++ b/src/USER-MISC/fix_nvk.cpp @@ -0,0 +1,219 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing author: Efrem Braun (UC Berkeley) +------------------------------------------------------------------------- */ + +#include +#include +#include +#include "fix_nvk.h" +#include "atom.h" +#include "force.h" +#include "update.h" +#include "respa.h" +#include "error.h" +#include "compute.h" +#include "math_extra.h" +#include "domain.h" + +using namespace LAMMPS_NS; +using namespace FixConst; + +FixNVK::FixNVK(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg) +{ + if (narg < 3) + error->all(FLERR,"Illegal fix nvk command"); + if (igroup) error->all(FLERR,"Fix nvk only supports group all"); + + dynamic_group_allow = 1; + time_integrate = 1; +} + +/* ---------------------------------------------------------------------- */ + +int FixNVK::setmask() +{ + int mask = 0; + mask |= INITIAL_INTEGRATE; + mask |= FINAL_INTEGRATE; + mask |= INITIAL_INTEGRATE_RESPA; + mask |= FINAL_INTEGRATE_RESPA; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixNVK::init() +{ + dtv = update->dt; + dtf = 0.5 * update->dt; + + if (strstr(update->integrate_style,"respa")) { + error->all(FLERR,"Fix nvk not yet enabled for RESPA"); + step_respa = ((Respa *) update->integrate)->step; + } + + // compute initial kinetic energy + // make better by calling compute_ke instead of copy/pasting code from compute_ke.cpp + double pfactor = 0.5 * force->mvv2e; + double **v = atom->v; + double *rmass = atom->rmass; + double *mass = atom->mass; + int *mask = atom->mask; + int *type = atom->type; + int nlocal = atom->nlocal; + double ke = 0.0; + if (rmass) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + ke += rmass[i] * (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]); + } else { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + ke += mass[type[i]] * + (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]); + } + MPI_Allreduce(&ke,&K_target,1,MPI_DOUBLE,MPI_SUM,world); + K_target *= pfactor; +} + +/* ---------------------------------------------------------------------- + allow for both per-type and per-atom mass +------------------------------------------------------------------------- */ + +void FixNVK::initial_integrate(int vflag) +{ + double sm; + double a,b,sqtb,s,sdot; + + double **x = atom->x; + double **v = atom->v; + double **f = atom->f; + double *rmass = atom->rmass; + double *mass = atom->mass; + int *type = atom->type; + int *mask = atom->mask; + int nlocal = atom->nlocal; + if (igroup == atom->firstgroup) nlocal = atom->nfirst; + + // calculate s and sdot from Minary 2003, equations 4.12 and 4.13 + double a_local = 0.0; + double b_local = 0.0; + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + a_local += MathExtra::dot3(f[i], v[i]); + if (rmass) b_local += MathExtra::dot3(f[i], f[i]) / rmass[i]; + else b_local += MathExtra::dot3(f[i], f[i]) / mass[type[i]]; + } + MPI_Allreduce(&a_local,&a,1,MPI_DOUBLE,MPI_SUM,world); + MPI_Allreduce(&b_local,&b,1,MPI_DOUBLE,MPI_SUM,world); + a /= (2.0*K_target); // units of inverse time + b /= (2.0*K_target * force->mvv2e); // units of inverse time squared + sqtb = sqrt(b); + s = a/b * (cosh(dtf*sqtb) - 1.0) + sinh(dtf*sqtb) / sqtb; + sdot = a/b * sqtb * sinh(dtf*sqtb) + cosh(dtf*sqtb); + + // update v and x of atoms in group per Minary 2003, equations 4.15-4.17 + // note that equation 4.15, 4.17 should read p = (p+F*s/m)/sdot + // note that equation 4.16 should read r = r + delt*p/m + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + if (rmass) sm = s / rmass[i]; + else sm = s / mass[type[i]]; + v[i][0] = (v[i][0] + f[i][0] * sm * force->ftm2v) / sdot; + v[i][1] = (v[i][1] + f[i][1] * sm * force->ftm2v) / sdot; + v[i][2] = (v[i][2] + f[i][2] * sm * force->ftm2v) / sdot; + x[i][0] += dtv * v[i][0]; + x[i][1] += dtv * v[i][1]; + x[i][2] += dtv * v[i][2]; + } +} + +/* ---------------------------------------------------------------------- */ + +void FixNVK::final_integrate() +{ + double sm; + double a,b,sqtb,s,sdot; + + double **v = atom->v; + double **f = atom->f; + double *rmass = atom->rmass; + double *mass = atom->mass; + int *type = atom->type; + int *mask = atom->mask; + int nlocal = atom->nlocal; + if (igroup == atom->firstgroup) nlocal = atom->nfirst; + + // calculate s and sdot from Minary 2003, equations 4.12 and 4.13 + double a_local = 0.0; + double b_local = 0.0; + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + a_local += MathExtra::dot3(f[i], v[i]); + if (rmass) b_local += MathExtra::dot3(f[i], f[i]) / rmass[i]; + else b_local += MathExtra::dot3(f[i], f[i]) / mass[type[i]]; + } + MPI_Allreduce(&a_local,&a,1,MPI_DOUBLE,MPI_SUM,world); + MPI_Allreduce(&b_local,&b,1,MPI_DOUBLE,MPI_SUM,world); + a /= (2.0*K_target); // units of inverse time + b /= (2.0*K_target * force->mvv2e); // units of inverse time squared + sqtb = sqrt(b); + s = a/b * (cosh(dtf*sqtb) - 1.0) + sinh(dtf*sqtb) / sqtb; + sdot = a/b * sqtb * sinh(dtf*sqtb) + cosh(dtf*sqtb); + + // update v and x of atoms in group per Minary 2003, equations 4.15-4.17 + // note that equation 4.15, 4.17 should read p = (p+F*s/m)/sdot + // note that equation 4.16 should read r = r + delt*p/m + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + if (rmass) sm = s / rmass[i]; + else sm = s / mass[type[i]]; + v[i][0] = (v[i][0] + f[i][0] * sm * force->ftm2v) / sdot; + v[i][1] = (v[i][1] + f[i][1] * sm * force->ftm2v) / sdot; + v[i][2] = (v[i][2] + f[i][2] * sm * force->ftm2v) / sdot; + } +} + +/* ---------------------------------------------------------------------- */ + +void FixNVK::initial_integrate_respa(int vflag, int ilevel, int iloop) +{ + dtv = step_respa[ilevel]; + dtf = 0.5 * step_respa[ilevel]; + + // innermost level - NVK update of v and x + // all other levels - NVK update of v + + if (ilevel == 0) initial_integrate(vflag); + else final_integrate(); +} + +/* ---------------------------------------------------------------------- */ + +void FixNVK::final_integrate_respa(int ilevel, int iloop) +{ + dtf = 0.5 * step_respa[ilevel]; + final_integrate(); +} + +/* ---------------------------------------------------------------------- */ + +void FixNVK::reset_dt() +{ + dtv = update->dt; + dtf = 0.5 * update->dt; +} diff --git a/src/USER-MISC/fix_nvk.h b/src/USER-MISC/fix_nvk.h new file mode 100644 index 0000000000..1d73e2f5df --- /dev/null +++ b/src/USER-MISC/fix_nvk.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS + +FixStyle(nvk,FixNVK) + +#else + +#ifndef LMP_FIX_NVK_H +#define LMP_FIX_NVK_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixNVK : public Fix { + public: + FixNVK(class LAMMPS *, int, char **); + virtual ~FixNVK() {} + int setmask(); + virtual void init(); + virtual void initial_integrate(int); + virtual void final_integrate(); + virtual void initial_integrate_respa(int, int, int); + virtual void final_integrate_respa(int, int); + virtual void reset_dt(); + + protected: + double dtv,dtf; + double *step_respa; + int mass_require; + double K_target; +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal ... command + +Self-explanatory. Check the input script syntax and compare to the +documentation for the command. You can use -echo screen as a +command-line option when running LAMMPS to see the offending line. + +E: Fix nvk only supports group all + +Self-explanatory. + +E: Fix nvk not yet enabled for RESPA + +Self-explanatory. + +*/ diff --git a/src/USER-OMP/pair_lj_cut_tip4p_cut_omp.cpp b/src/USER-OMP/pair_lj_cut_tip4p_cut_omp.cpp index 3b028fb67b..3b4d616149 100644 --- a/src/USER-OMP/pair_lj_cut_tip4p_cut_omp.cpp +++ b/src/USER-OMP/pair_lj_cut_tip4p_cut_omp.cpp @@ -127,9 +127,9 @@ void PairLJCutTIP4PCutOMP::eval(int iifrom, int iito, ThrData * const thr) double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul; double r,rsq,r2inv,r6inv,forcecoul,forcelj,cforce; double factor_coul,factor_lj; - double v[6],xH1[3],xH2[3]; + double v[6]; double fdx,fdy,fdz,fOx,fOy,fOz,fHx,fHy,fHz; - dbl3_t x1,x2; + dbl3_t x1,x2,xH1,xH2; int *ilist,*jlist,*numneigh,**firstneigh; int i,j,ii,jj,jnum,itype,jtype,key; @@ -179,10 +179,14 @@ void PairLJCutTIP4PCutOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite_thr(x[i],x[iH1],x[iH2],newsite_thr[i]); hneigh_thr[i].t = 1; hneigh_thr[i].b = iH2; hneigh_thr[i].a = iH1; + } else { iH1 = hneigh_thr[i].a; iH2 = hneigh_thr[i].b; @@ -256,6 +260,9 @@ void PairLJCutTIP4PCutOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite_thr(x[j],x[jH1],x[jH2],newsite_thr[j]); hneigh_thr[j].t = 1; hneigh_thr[j].b = jH2; @@ -341,15 +348,14 @@ void PairLJCutTIP4PCutOMP::eval(int iifrom, int iito, ThrData * const thr) f[iH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[i].x,&x[iH1].x,xH1); - domain->closest_image(&x[i].x,&x[iH2].x,xH2); - - v[0] = x[i].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] = x[i].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] = x[i].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] = x[i].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] = x[i].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] = x[i].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[iH1]; + xH2 = x[iH2]; + v[0] = x[i].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] = x[i].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] = x[i].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] = x[i].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] = x[i].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] = x[i].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = i; @@ -401,15 +407,14 @@ void PairLJCutTIP4PCutOMP::eval(int iifrom, int iito, ThrData * const thr) f[jH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[j].x,&x[jH1].x,xH1); - domain->closest_image(&x[j].x,&x[jH2].x,xH2); - - v[0] += x[j].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] += x[j].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] += x[j].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] += x[j].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] += x[j].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] += x[j].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[jH1]; + xH2 = x[jH2]; + v[0] += x[j].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] += x[j].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] += x[j].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] += x[j].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] += x[j].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] += x[j].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = j; @@ -446,12 +451,10 @@ void PairLJCutTIP4PCutOMP::compute_newsite_thr(const dbl3_t &xO, double delx1 = xH1.x - xO.x; double dely1 = xH1.y - xO.y; double delz1 = xH1.z - xO.z; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2.x - xO.x; double dely2 = xH2.y - xO.y; double delz2 = xH2.z - xO.z; - domain->minimum_image(delx2,dely2,delz2); const double prefac = alpha * 0.5; xM.x = xO.x + prefac * (delx1 + delx2); diff --git a/src/USER-OMP/pair_lj_cut_tip4p_long_omp.cpp b/src/USER-OMP/pair_lj_cut_tip4p_long_omp.cpp index 70be3e5228..2f1b98fc4f 100644 --- a/src/USER-OMP/pair_lj_cut_tip4p_long_omp.cpp +++ b/src/USER-OMP/pair_lj_cut_tip4p_long_omp.cpp @@ -141,9 +141,9 @@ void PairLJCutTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) double r,rsq,r2inv,r6inv,forcecoul,forcelj,cforce; double factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; - double v[6],xH1[3],xH2[3]; + double v[6]; double fdx,fdy,fdz,fOx,fOy,fOz,fHx,fHy,fHz; - dbl3_t x1,x2; + dbl3_t x1,x2,xH1,xH2; int *ilist,*jlist,*numneigh,**firstneigh; int i,j,ii,jj,jnum,itype,jtype,itable, key; @@ -193,6 +193,9 @@ void PairLJCutTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite_thr(x[i],x[iH1],x[iH2],newsite_thr[i]); hneigh_thr[i].t = 1; hneigh_thr[i].b = iH2; @@ -270,6 +273,9 @@ void PairLJCutTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite_thr(x[j],x[jH1],x[jH2],newsite_thr[j]); hneigh_thr[j].t = 1; hneigh_thr[j].b = jH2; @@ -379,15 +385,14 @@ void PairLJCutTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) f[iH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[i].x,&x[iH1].x,xH1); - domain->closest_image(&x[i].x,&x[iH2].x,xH2); - - v[0] = x[i].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] = x[i].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] = x[i].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] = x[i].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] = x[i].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] = x[i].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[iH1]; + xH2 = x[iH2]; + v[0] = x[i].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] = x[i].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] = x[i].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] = x[i].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] = x[i].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] = x[i].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = i; @@ -439,15 +444,14 @@ void PairLJCutTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) f[jH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[j].x,&x[jH1].x,xH1); - domain->closest_image(&x[j].x,&x[jH2].x,xH2); - - v[0] += x[j].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] += x[j].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] += x[j].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] += x[j].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] += x[j].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] += x[j].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[jH1]; + xH2 = x[jH2]; + v[0] += x[j].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] += x[j].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] += x[j].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] += x[j].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] += x[j].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] += x[j].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = j; @@ -489,12 +493,10 @@ void PairLJCutTIP4PLongOMP::compute_newsite_thr(const dbl3_t &xO, double delx1 = xH1.x - xO.x; double dely1 = xH1.y - xO.y; double delz1 = xH1.z - xO.z; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2.x - xO.x; double dely2 = xH2.y - xO.y; double delz2 = xH2.z - xO.z; - domain->minimum_image(delx2,dely2,delz2); const double prefac = alpha * 0.5; xM.x = xO.x + prefac * (delx1 + delx2); diff --git a/src/USER-OMP/pair_lj_cut_tip4p_long_soft_omp.cpp b/src/USER-OMP/pair_lj_cut_tip4p_long_soft_omp.cpp index 2d4be0d884..b31c1c109b 100644 --- a/src/USER-OMP/pair_lj_cut_tip4p_long_soft_omp.cpp +++ b/src/USER-OMP/pair_lj_cut_tip4p_long_soft_omp.cpp @@ -129,9 +129,9 @@ void PairLJCutTIP4PLongSoftOMP::eval(int iifrom, int iito, ThrData * const thr) double factor_coul,factor_lj; double grij,expm2,prefactor,t,erfc; double denc, denlj, r4sig6; - double v[6],xH1[3],xH2[3]; + double v[6]; double fdx,fdy,fdz,fOx,fOy,fOz,fHx,fHy,fHz; - dbl3_t x1,x2; + dbl3_t x1,x2,xH1,xH2; int *ilist,*jlist,*numneigh,**firstneigh; int i,j,ii,jj,jnum,itype,jtype,key; @@ -181,6 +181,9 @@ void PairLJCutTIP4PLongSoftOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite_thr(x[i],x[iH1],x[iH2],newsite_thr[i]); hneigh_thr[i].t = 1; hneigh_thr[i].b = iH2; @@ -261,6 +264,9 @@ void PairLJCutTIP4PLongSoftOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite_thr(x[j],x[jH1],x[jH2],newsite_thr[j]); hneigh_thr[j].t = 1; hneigh_thr[j].b = jH2; @@ -357,15 +363,14 @@ void PairLJCutTIP4PLongSoftOMP::eval(int iifrom, int iito, ThrData * const thr) f[iH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[i].x,&x[iH1].x,xH1); - domain->closest_image(&x[i].x,&x[iH2].x,xH2); - - v[0] = x[i].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] = x[i].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] = x[i].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] = x[i].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] = x[i].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] = x[i].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[iH1]; + xH2 = x[iH2]; + v[0] = x[i].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] = x[i].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] = x[i].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] = x[i].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] = x[i].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] = x[i].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = i; @@ -417,15 +422,14 @@ void PairLJCutTIP4PLongSoftOMP::eval(int iifrom, int iito, ThrData * const thr) f[jH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[j].x,&x[jH1].x,xH1); - domain->closest_image(&x[j].x,&x[jH2].x,xH2); - - v[0] += x[j].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] += x[j].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] += x[j].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] += x[j].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] += x[j].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] += x[j].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[jH1]; + xH2 = x[jH2]; + v[0] += x[j].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] += x[j].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] += x[j].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] += x[j].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] += x[j].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] += x[j].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = j; @@ -463,12 +467,10 @@ void PairLJCutTIP4PLongSoftOMP::compute_newsite_thr(const dbl3_t &xO, double delx1 = xH1.x - xO.x; double dely1 = xH1.y - xO.y; double delz1 = xH1.z - xO.z; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2.x - xO.x; double dely2 = xH2.y - xO.y; double delz2 = xH2.z - xO.z; - domain->minimum_image(delx2,dely2,delz2); const double prefac = alpha * 0.5; xM.x = xO.x + prefac * (delx1 + delx2); diff --git a/src/USER-OMP/pair_lj_long_tip4p_long_omp.cpp b/src/USER-OMP/pair_lj_long_tip4p_long_omp.cpp index f04e6380c8..5072496cc6 100644 --- a/src/USER-OMP/pair_lj_long_tip4p_long_omp.cpp +++ b/src/USER-OMP/pair_lj_long_tip4p_long_omp.cpp @@ -737,8 +737,8 @@ void PairLJLongTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) double r,r2inv,forcecoul,forcelj,cforce; double factor_coul; double grij,expm2,prefactor,t,erfc; - double fO[3],fH[3],fd[3],v[6],xH1[3],xH2[3]; - dbl3_t x1,x2; + double fO[3],fH[3],fd[3],v[6]; + dbl3_t x1,x2,xH1,xH2; int *ilist,*jlist,*numneigh,**firstneigh; double rsq; @@ -763,14 +763,20 @@ void PairLJLongTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) itype = type[i]; if (itype == typeO) { if (hneigh_thr[i].a < 0) { - hneigh_thr[i].a = iH1 = atom->map(atom->tag[i] + 1); - hneigh_thr[i].b = iH2 = atom->map(atom->tag[i] + 2); - hneigh_thr[i].t = 1; + iH1 = atom->map(atom->tag[i] + 1); + iH2 = atom->map(atom->tag[i] + 2); if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite_thr(x[i],x[iH1],x[iH2],newsite_thr[i]); + hneigh_thr[i].a = iH1; + hneigh_thr[i].b = iH2; + hneigh_thr[i].t = 1; + } else { iH1 = hneigh_thr[i].a; iH2 = hneigh_thr[i].b; @@ -871,14 +877,20 @@ void PairLJLongTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) if (itype == typeO || jtype == typeO) { if (jtype == typeO) { if (hneigh_thr[j].a < 0) { - hneigh_thr[j].a = jH1 = atom->map(atom->tag[j] + 1); - hneigh_thr[j].b = jH2 = atom->map(atom->tag[j] + 2); - hneigh_thr[j].t = 1; + jH1 = atom->map(atom->tag[j] + 1); + jH2 = atom->map(atom->tag[j] + 2); if (jH1 == -1 || jH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite_thr(x[j],x[jH1],x[jH2],newsite_thr[j]); + hneigh_thr[j].a = jH1; + hneigh_thr[j].b = jH2; + hneigh_thr[j].t = 1; + } else { jH1 = hneigh_thr[j].a; jH2 = hneigh_thr[j].b; @@ -983,15 +995,14 @@ void PairLJLongTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) f[iH2][2] += fH[2]; if (EVFLAG) { - domain->closest_image(&x[i].x,&x[iH1].x,xH1); - domain->closest_image(&x[i].x,&x[iH2].x,xH2); - - v[0] = x[i].x*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; - v[1] = x[i].y*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; - v[2] = x[i].z*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; - v[3] = x[i].x*fO[1] + xH1[0]*fH[1] + xH2[0]*fH[1]; - v[4] = x[i].x*fO[2] + xH1[0]*fH[2] + xH2[0]*fH[2]; - v[5] = x[i].y*fO[2] + xH1[1]*fH[2] + xH2[1]*fH[2]; + xH1 = x[iH1]; + xH2 = x[iH2]; + v[0] = x[i].x*fO[0] + xH1.x*fH[0] + xH2.x*fH[0]; + v[1] = x[i].y*fO[1] + xH1.y*fH[1] + xH2.y*fH[1]; + v[2] = x[i].z*fO[2] + xH1.z*fH[2] + xH2.z*fH[2]; + v[3] = x[i].x*fO[1] + xH1.x*fH[1] + xH2.x*fH[1]; + v[4] = x[i].x*fO[2] + xH1.x*fH[2] + xH2.x*fH[2]; + v[5] = x[i].y*fO[2] + xH1.y*fH[2] + xH2.y*fH[2]; } vlist[n++] = i; vlist[n++] = iH1; @@ -1041,15 +1052,14 @@ void PairLJLongTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) f[jH2][2] += fH[2]; if (EVFLAG) { - domain->closest_image(&x[j].x,&x[jH1].x,xH1); - domain->closest_image(&x[j].x,&x[jH2].x,xH2); - - v[0] += x[j].x*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0]; - v[1] += x[j].y*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1]; - v[2] += x[j].z*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2]; - v[3] += x[j].x*fO[1] + xH1[0]*fH[1] + xH2[0]*fH[1]; - v[4] += x[j].x*fO[2] + xH1[0]*fH[2] + xH2[0]*fH[2]; - v[5] += x[j].y*fO[2] + xH1[1]*fH[2] + xH2[1]*fH[2]; + xH1 = x[jH1]; + xH2 = x[jH2]; + v[0] += x[j].x*fO[0] + xH1.x*fH[0] + xH2.x*fH[0]; + v[1] += x[j].y*fO[1] + xH1.y*fH[1] + xH2.y*fH[1]; + v[2] += x[j].z*fO[2] + xH1.z*fH[2] + xH2.z*fH[2]; + v[3] += x[j].x*fO[1] + xH1.x*fH[1] + xH2.x*fH[1]; + v[4] += x[j].x*fO[2] + xH1.x*fH[2] + xH2.x*fH[2]; + v[5] += x[j].y*fO[2] + xH1.y*fH[2] + xH2.y*fH[2]; } vlist[n++] = j; vlist[n++] = jH1; @@ -1981,12 +1991,10 @@ void PairLJLongTIP4PLongOMP::compute_newsite_thr(const dbl3_t &xO, double delx1 = xH1.x - xO.x; double dely1 = xH1.y - xO.y; double delz1 = xH1.z - xO.z; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2.x - xO.x; double dely2 = xH2.y - xO.y; double delz2 = xH2.z - xO.z; - domain->minimum_image(delx2,dely2,delz2); const double prefac = alpha * 0.5; xM.x = xO.x + prefac * (delx1 + delx2); diff --git a/src/USER-OMP/pair_tip4p_cut_omp.cpp b/src/USER-OMP/pair_tip4p_cut_omp.cpp index 2b125fde7f..3edd2b688f 100644 --- a/src/USER-OMP/pair_tip4p_cut_omp.cpp +++ b/src/USER-OMP/pair_tip4p_cut_omp.cpp @@ -126,9 +126,9 @@ void PairTIP4PCutOMP::eval(int iifrom, int iito, ThrData * const thr) double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,ecoul; double r,rsq,r2inv,forcecoul,cforce; double factor_coul; - double v[6],xH1[3],xH2[3]; + double v[6]; double fdx,fdy,fdz,fOx,fOy,fOz,fHx,fHy,fHz; - dbl3_t x1,x2; + dbl3_t x1,x2,xH1,xH2; int *ilist,*jlist,*numneigh,**firstneigh; int i,j,ii,jj,jnum,itype,jtype,key; @@ -176,10 +176,14 @@ void PairTIP4PCutOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite_thr(x[i],x[iH1],x[iH2],newsite_thr[i]); hneigh_thr[i].t = 1; hneigh_thr[i].b = iH2; hneigh_thr[i].a = iH1; + } else { iH1 = hneigh_thr[i].a; iH2 = hneigh_thr[i].b; @@ -227,6 +231,9 @@ void PairTIP4PCutOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite_thr(x[j],x[jH1],x[jH2],newsite_thr[j]); hneigh_thr[j].t = 1; hneigh_thr[j].b = jH2; @@ -312,15 +319,14 @@ void PairTIP4PCutOMP::eval(int iifrom, int iito, ThrData * const thr) f[iH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[i].x,&x[iH1].x,xH1); - domain->closest_image(&x[i].x,&x[iH2].x,xH2); - - v[0] = x[i].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] = x[i].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] = x[i].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] = x[i].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] = x[i].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] = x[i].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[iH1]; + xH2 = x[iH2]; + v[0] = x[i].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] = x[i].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] = x[i].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] = x[i].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] = x[i].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] = x[i].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = i; @@ -372,15 +378,14 @@ void PairTIP4PCutOMP::eval(int iifrom, int iito, ThrData * const thr) f[jH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[j].x,&x[jH1].x,xH1); - domain->closest_image(&x[j].x,&x[jH2].x,xH2); - - v[0] += x[j].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] += x[j].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] += x[j].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] += x[j].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] += x[j].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] += x[j].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[jH1]; + xH2 = x[jH2]; + v[0] += x[j].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] += x[j].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] += x[j].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] += x[j].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] += x[j].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] += x[j].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = j; @@ -417,12 +422,10 @@ void PairTIP4PCutOMP::compute_newsite_thr(const dbl3_t &xO, double delx1 = xH1.x - xO.x; double dely1 = xH1.y - xO.y; double delz1 = xH1.z - xO.z; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2.x - xO.x; double dely2 = xH2.y - xO.y; double delz2 = xH2.z - xO.z; - domain->minimum_image(delx2,dely2,delz2); const double prefac = alpha * 0.5; xM.x = xO.x + prefac * (delx1 + delx2); diff --git a/src/USER-OMP/pair_tip4p_long_omp.cpp b/src/USER-OMP/pair_tip4p_long_omp.cpp index 96ebc64a90..bcd8659a54 100644 --- a/src/USER-OMP/pair_tip4p_long_omp.cpp +++ b/src/USER-OMP/pair_tip4p_long_omp.cpp @@ -141,9 +141,9 @@ void PairTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) double r,rsq,r2inv,forcecoul,cforce; double factor_coul; double grij,expm2,prefactor,t,erfc; - double v[6],xH1[3],xH2[3]; + double v[6]; double fdx,fdy,fdz,fOx,fOy,fOz,fHx,fHy,fHz; - dbl3_t x1,x2; + dbl3_t x1,x2,xH1,xH2; int *ilist,*jlist,*numneigh,**firstneigh; int i,j,ii,jj,jnum,itype,jtype,itable, key; @@ -191,10 +191,14 @@ void PairTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite_thr(x[i],x[iH1],x[iH2],newsite_thr[i]); hneigh_thr[i].t = 1; hneigh_thr[i].b = iH2; hneigh_thr[i].a = iH1; + } else { iH1 = hneigh_thr[i].a; iH2 = hneigh_thr[i].b; @@ -242,10 +246,14 @@ void PairTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite_thr(x[j],x[jH1],x[jH2],newsite_thr[j]); hneigh_thr[j].t = 1; hneigh_thr[j].b = jH2; hneigh_thr[j].a = jH1; + } else { jH1 = hneigh_thr[j].a; jH2 = hneigh_thr[j].b; @@ -351,15 +359,14 @@ void PairTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) f[iH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[i].x,&x[iH1].x,xH1); - domain->closest_image(&x[i].x,&x[iH2].x,xH2); - - v[0] = x[i].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] = x[i].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] = x[i].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] = x[i].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] = x[i].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] = x[i].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[iH1]; + xH2 = x[iH2]; + v[0] = x[i].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] = x[i].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] = x[i].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] = x[i].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] = x[i].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] = x[i].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = i; @@ -411,15 +418,14 @@ void PairTIP4PLongOMP::eval(int iifrom, int iito, ThrData * const thr) f[jH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[j].x,&x[jH1].x,xH1); - domain->closest_image(&x[j].x,&x[jH2].x,xH2); - - v[0] += x[j].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] += x[j].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] += x[j].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] += x[j].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] += x[j].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] += x[j].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[jH1]; + xH2 = x[jH2]; + v[0] += x[j].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] += x[j].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] += x[j].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] += x[j].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] += x[j].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] += x[j].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = j; @@ -461,12 +467,10 @@ void PairTIP4PLongOMP::compute_newsite_thr(const dbl3_t &xO, double delx1 = xH1.x - xO.x; double dely1 = xH1.y - xO.y; double delz1 = xH1.z - xO.z; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2.x - xO.x; double dely2 = xH2.y - xO.y; double delz2 = xH2.z - xO.z; - domain->minimum_image(delx2,dely2,delz2); const double prefac = alpha * 0.5; xM.x = xO.x + prefac * (delx1 + delx2); diff --git a/src/USER-OMP/pair_tip4p_long_soft_omp.cpp b/src/USER-OMP/pair_tip4p_long_soft_omp.cpp index ac3bcfc393..2f16a28b8c 100644 --- a/src/USER-OMP/pair_tip4p_long_soft_omp.cpp +++ b/src/USER-OMP/pair_tip4p_long_soft_omp.cpp @@ -128,9 +128,9 @@ void PairTIP4PLongSoftOMP::eval(int iifrom, int iito, ThrData * const thr) double r,rsq,forcecoul,cforce; double factor_coul,denc; double grij,expm2,prefactor,t,erfc; - double v[6],xH1[3],xH2[3]; + double v[6]; double fdx,fdy,fdz,fOx,fOy,fOz,fHx,fHy,fHz; - dbl3_t x1,x2; + dbl3_t x1,x2,xH1,xH2; int *ilist,*jlist,*numneigh,**firstneigh; int i,j,ii,jj,jnum,itype,jtype,key; @@ -178,10 +178,14 @@ void PairTIP4PLongSoftOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); compute_newsite_thr(x[i],x[iH1],x[iH2],newsite_thr[i]); hneigh_thr[i].t = 1; hneigh_thr[i].b = iH2; hneigh_thr[i].a = iH1; + } else { iH1 = hneigh_thr[i].a; iH2 = hneigh_thr[i].b; @@ -229,10 +233,14 @@ void PairTIP4PLongSoftOMP::eval(int iifrom, int iito, ThrData * const thr) error->one(FLERR,"TIP4P hydrogen is missing"); if (atom->type[jH1] != typeH || atom->type[jH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set jH1,jH2 to closest image to O + jH1 = domain->closest_image(j,jH1); + jH2 = domain->closest_image(j,jH2); compute_newsite_thr(x[j],x[jH1],x[jH2],newsite_thr[j]); hneigh_thr[j].t = 1; hneigh_thr[j].b = jH2; hneigh_thr[j].a = jH1; + } else { jH1 = hneigh_thr[j].a; jH2 = hneigh_thr[j].b; @@ -326,15 +334,14 @@ void PairTIP4PLongSoftOMP::eval(int iifrom, int iito, ThrData * const thr) f[iH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[i].x,&x[iH1].x,xH1); - domain->closest_image(&x[i].x,&x[iH2].x,xH2); - - v[0] = x[i].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] = x[i].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] = x[i].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] = x[i].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] = x[i].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] = x[i].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[iH1]; + xH2 = x[iH2]; + v[0] = x[i].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] = x[i].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] = x[i].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] = x[i].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] = x[i].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] = x[i].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = i; @@ -386,15 +393,14 @@ void PairTIP4PLongSoftOMP::eval(int iifrom, int iito, ThrData * const thr) f[jH2].z += fHz; if (VFLAG) { - domain->closest_image(&x[j].x,&x[jH1].x,xH1); - domain->closest_image(&x[j].x,&x[jH2].x,xH2); - - v[0] += x[j].x*fOx + xH1[0]*fHx + xH2[0]*fHx; - v[1] += x[j].y*fOy + xH1[1]*fHy + xH2[1]*fHy; - v[2] += x[j].z*fOz + xH1[2]*fHz + xH2[2]*fHz; - v[3] += x[j].x*fOy + xH1[0]*fHy + xH2[0]*fHy; - v[4] += x[j].x*fOz + xH1[0]*fHz + xH2[0]*fHz; - v[5] += x[j].y*fOz + xH1[1]*fHz + xH2[1]*fHz; + xH1 = x[jH1]; + xH2 = x[jH2]; + v[0] += x[j].x*fOx + xH1.x*fHx + xH2.x*fHx; + v[1] += x[j].y*fOy + xH1.y*fHy + xH2.y*fHy; + v[2] += x[j].z*fOz + xH1.z*fHz + xH2.z*fHz; + v[3] += x[j].x*fOy + xH1.x*fHy + xH2.x*fHy; + v[4] += x[j].x*fOz + xH1.x*fHz + xH2.x*fHz; + v[5] += x[j].y*fOz + xH1.y*fHz + xH2.y*fHz; } if (EVFLAG) { vlist[n++] = j; @@ -432,12 +438,10 @@ void PairTIP4PLongSoftOMP::compute_newsite_thr(const dbl3_t &xO, double delx1 = xH1.x - xO.x; double dely1 = xH1.y - xO.y; double delz1 = xH1.z - xO.z; - domain->minimum_image(delx1,dely1,delz1); double delx2 = xH2.x - xO.x; double dely2 = xH2.y - xO.y; double delz2 = xH2.z - xO.z; - domain->minimum_image(delx2,dely2,delz2); const double prefac = alpha * 0.5; xM.x = xO.x + prefac * (delx1 + delx2); diff --git a/src/USER-OMP/pppm_disp_tip4p_omp.cpp b/src/USER-OMP/pppm_disp_tip4p_omp.cpp index 6606c9602c..8872c849f3 100644 --- a/src/USER-OMP/pppm_disp_tip4p_omp.cpp +++ b/src/USER-OMP/pppm_disp_tip4p_omp.cpp @@ -1852,17 +1852,20 @@ void PPPMDispTIP4POMP::find_M_thr(int i, int &iH1, int &iH2, dbl3_t &xM) if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); + const dbl3_t * _noalias const x = (dbl3_t *) atom->x[0]; double delx1 = x[iH1].x - x[i].x; double dely1 = x[iH1].y - x[i].y; double delz1 = x[iH1].z - x[i].z; - domain->minimum_image(delx1,dely1,delz1); double delx2 = x[iH2].x - x[i].x; double dely2 = x[iH2].y - x[i].y; double delz2 = x[iH2].z - x[i].z; - domain->minimum_image(delx2,dely2,delz2); xM.x = x[i].x + alpha * 0.5 * (delx1 + delx2); xM.y = x[i].y + alpha * 0.5 * (dely1 + dely2); diff --git a/src/USER-OMP/pppm_tip4p_omp.cpp b/src/USER-OMP/pppm_tip4p_omp.cpp index 21da813123..fdc58bce10 100644 --- a/src/USER-OMP/pppm_tip4p_omp.cpp +++ b/src/USER-OMP/pppm_tip4p_omp.cpp @@ -742,17 +742,20 @@ void PPPMTIP4POMP::find_M_thr(int i, int &iH1, int &iH2, dbl3_t &xM) if (atom->type[iH1] != typeH || atom->type[iH2] != typeH) error->one(FLERR,"TIP4P hydrogen has incorrect atom type"); + // set iH1,iH2 to index of closest image to O + + iH1 = domain->closest_image(i,iH1); + iH2 = domain->closest_image(i,iH2); + const dbl3_t * _noalias const x = (dbl3_t *) atom->x[0]; double delx1 = x[iH1].x - x[i].x; double dely1 = x[iH1].y - x[i].y; double delz1 = x[iH1].z - x[i].z; - domain->minimum_image(delx1,dely1,delz1); double delx2 = x[iH2].x - x[i].x; double dely2 = x[iH2].y - x[i].y; double delz2 = x[iH2].z - x[i].z; - domain->minimum_image(delx2,dely2,delz2); xM.x = x[i].x + alpha * 0.5 * (delx1 + delx2); xM.y = x[i].y + alpha * 0.5 * (dely1 + dely2); diff --git a/src/USER-REAXC/fix_qeq_reax.cpp b/src/USER-REAXC/fix_qeq_reax.cpp index 5fa0ef6d79..26cf03f60a 100644 --- a/src/USER-REAXC/fix_qeq_reax.cpp +++ b/src/USER-REAXC/fix_qeq_reax.cpp @@ -440,13 +440,6 @@ void FixQEqReax::setup_pre_force_respa(int vflag, int ilevel) /* ---------------------------------------------------------------------- */ -void FixQEqReax::min_setup_pre_force(int vflag) -{ - setup_pre_force(vflag); -} - -/* ---------------------------------------------------------------------- */ - void FixQEqReax::init_storage() { int NN; diff --git a/src/USER-REAXC/fix_qeq_reax.h b/src/USER-REAXC/fix_qeq_reax.h index a0d29d6561..7c3e8a8f96 100644 --- a/src/USER-REAXC/fix_qeq_reax.h +++ b/src/USER-REAXC/fix_qeq_reax.h @@ -48,7 +48,6 @@ class FixQEqReax : public Fix { void setup_pre_force_respa(int, int); void pre_force_respa(int, int, int); - void min_setup_pre_force(int); void min_pre_force(int); int matvecs; diff --git a/src/atom.cpp b/src/atom.cpp index c7f8345898..0920dc3a02 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -392,6 +392,8 @@ void Atom::create_avec(const char *style, int narg, char **arg, int trysuffix) { delete [] atom_style; if (avec) delete avec; + atom_style = NULL; + avec = NULL; // unset atom style and array existence flags // may have been set by old avec diff --git a/src/domain.cpp b/src/domain.cpp index 54183f6f2c..f627048cfa 100644 --- a/src/domain.cpp +++ b/src/domain.cpp @@ -938,28 +938,31 @@ void Domain::subbox_too_small_check(double thresh) } /* ---------------------------------------------------------------------- - minimum image convention + minimum image convention in periodic dimensions use 1/2 of box size as test for triclinic, also add/subtract tilt factors in other dims as needed + changed "if" to "while" to enable distance to + far-away ghost atom returned by atom->map() to be wrapped back into box + could be problem for looking up atom IDs when cutoff > boxsize ------------------------------------------------------------------------- */ void Domain::minimum_image(double &dx, double &dy, double &dz) { if (triclinic == 0) { if (xperiodic) { - if (fabs(dx) > xprd_half) { + while (fabs(dx) > xprd_half) { if (dx < 0.0) dx += xprd; else dx -= xprd; } } if (yperiodic) { - if (fabs(dy) > yprd_half) { + while (fabs(dy) > yprd_half) { if (dy < 0.0) dy += yprd; else dy -= yprd; } } if (zperiodic) { - if (fabs(dz) > zprd_half) { + while (fabs(dz) > zprd_half) { if (dz < 0.0) dz += zprd; else dz -= zprd; } @@ -967,7 +970,7 @@ void Domain::minimum_image(double &dx, double &dy, double &dz) } else { if (zperiodic) { - if (fabs(dz) > zprd_half) { + while (fabs(dz) > zprd_half) { if (dz < 0.0) { dz += zprd; dy += yz; @@ -980,7 +983,7 @@ void Domain::minimum_image(double &dx, double &dy, double &dz) } } if (yperiodic) { - if (fabs(dy) > yprd_half) { + while (fabs(dy) > yprd_half) { if (dy < 0.0) { dy += yprd; dx += xy; @@ -991,7 +994,7 @@ void Domain::minimum_image(double &dx, double &dy, double &dz) } } if (xperiodic) { - if (fabs(dx) > xprd_half) { + while (fabs(dx) > xprd_half) { if (dx < 0.0) dx += xprd; else dx -= xprd; } @@ -1000,28 +1003,31 @@ void Domain::minimum_image(double &dx, double &dy, double &dz) } /* ---------------------------------------------------------------------- - minimum image convention + minimum image convention in periodic dimensions use 1/2 of box size as test for triclinic, also add/subtract tilt factors in other dims as needed + changed "if" to "while" to enable distance to + far-away ghost atom returned by atom->map() to be wrapped back into box + could be problem for looking up atom IDs when cutoff > boxsize ------------------------------------------------------------------------- */ void Domain::minimum_image(double *delta) { if (triclinic == 0) { if (xperiodic) { - if (fabs(delta[0]) > xprd_half) { + while (fabs(delta[0]) > xprd_half) { if (delta[0] < 0.0) delta[0] += xprd; else delta[0] -= xprd; } } if (yperiodic) { - if (fabs(delta[1]) > yprd_half) { + while (fabs(delta[1]) > yprd_half) { if (delta[1] < 0.0) delta[1] += yprd; else delta[1] -= yprd; } } if (zperiodic) { - if (fabs(delta[2]) > zprd_half) { + while (fabs(delta[2]) > zprd_half) { if (delta[2] < 0.0) delta[2] += zprd; else delta[2] -= zprd; } @@ -1029,7 +1035,7 @@ void Domain::minimum_image(double *delta) } else { if (zperiodic) { - if (fabs(delta[2]) > zprd_half) { + while (fabs(delta[2]) > zprd_half) { if (delta[2] < 0.0) { delta[2] += zprd; delta[1] += yz; @@ -1042,7 +1048,7 @@ void Domain::minimum_image(double *delta) } } if (yperiodic) { - if (fabs(delta[1]) > yprd_half) { + while (fabs(delta[1]) > yprd_half) { if (delta[1] < 0.0) { delta[1] += yprd; delta[0] += xy; @@ -1053,7 +1059,7 @@ void Domain::minimum_image(double *delta) } } if (xperiodic) { - if (fabs(delta[0]) > xprd_half) { + while (fabs(delta[0]) > xprd_half) { if (delta[0] < 0.0) delta[0] += xprd; else delta[0] -= xprd; } @@ -1092,12 +1098,16 @@ int Domain::closest_image(int i, int j) closest = j; } } + return closest; } /* ---------------------------------------------------------------------- find and return Xj image = periodic image of Xj that is closest to Xi for triclinic, add/subtract tilt factors in other dims as needed + not currently used (Jan 2017): + used to be called by pair TIP4P styles but no longer, + due to use of other closest_image() method ------------------------------------------------------------------------- */ void Domain::closest_image(const double * const xi, const double * const xj, @@ -1441,7 +1451,7 @@ void Domain::unmap(double *x, imageint image) for triclinic, use h[] to add in tilt factors in other dims as needed ------------------------------------------------------------------------- */ -void Domain::unmap(double *x, imageint image, double *y) +void Domain::unmap(const double *x, imageint image, double *y) { int xbox = (image & IMGMASK) - IMGMAX; int ybox = (image >> IMGBITS & IMGMASK) - IMGMAX; @@ -1984,7 +1994,7 @@ void Domain::subbox_corners() /* ---------------------------------------------------------------------- compute 8 corner pts of any triclinic box with lo/hi in lamda coords - 8 output conners are ordered with x changing fastest, then y, finally z + 8 output corners are ordered with x changing fastest, then y, finally z could be more efficient if just coded with xy,yz,xz explicitly ------------------------------------------------------------------------- */ @@ -2004,6 +2014,6 @@ void Domain::lamda_box_corners(double *lo, double *hi) lamda2x(corners[5],corners[5]); corners[6][0] = lo[0]; corners[6][1] = hi[1]; corners[6][2] = hi[2]; lamda2x(corners[6],corners[6]); - corners[7][0] = hi[0]; corners[7][1] = hi[1]; corners[7][2] = subhi_lamda[2]; + corners[7][0] = hi[0]; corners[7][1] = hi[1]; corners[7][2] = hi[2]; lamda2x(corners[7],corners[7]); } diff --git a/src/domain.h b/src/domain.h index ad55f051cf..b8bf1657ce 100644 --- a/src/domain.h +++ b/src/domain.h @@ -119,7 +119,7 @@ class Domain : protected Pointers { void remap(double *); void remap_near(double *, double *); void unmap(double *, imageint); - void unmap(double *, imageint, double *); + void unmap(const double *, imageint, double *); void image_flip(int, int, int); int ownatom(int, double *, imageint *, int); diff --git a/src/finish.cpp b/src/finish.cpp index 850bc0b019..9222d4e868 100644 --- a/src/finish.cpp +++ b/src/finish.cpp @@ -65,7 +65,8 @@ void Finish::end(int flag) { int i,m,nneigh,nneighfull; int histo[10]; - int minflag,prdflag,tadflag,timeflag,fftflag,histoflag,neighflag; + int minflag,prdflag,tadflag,hyperflag; + int timeflag,fftflag,histoflag,neighflag; double time,tmp,ave,max,min; double time_loop,time_other,cpu_loop; @@ -86,9 +87,11 @@ void Finish::end(int flag) // flag = 1 = dynamics or minimization // flag = 2 = PRD // flag = 3 = TAD + // flag = 4 = HYPER // turn off neighflag for Kspace partition of verlet/split integrator - minflag = prdflag = tadflag = timeflag = fftflag = histoflag = neighflag = 0; + minflag = prdflag = tadflag = hyperflag = 0; + timeflag = fftflag = histoflag = neighflag = 0; time_loop = cpu_loop = time_other = 0.0; if (flag == 1) { @@ -103,6 +106,7 @@ void Finish::end(int flag) } if (flag == 2) prdflag = timeflag = histoflag = neighflag = 1; if (flag == 3) tadflag = histoflag = neighflag = 1; + if (flag == 4) hyperflag = timeflag = histoflag = neighflag = 1; // loop stats @@ -161,8 +165,10 @@ void Finish::end(int flag) if (lmp->kokkos) { const char fmt2[] = "%.1f%% CPU use with %d MPI tasks x %d OpenMP threads\n"; - if (screen) fprintf(screen,fmt2,cpu_loop,nprocs,lmp->kokkos->num_threads); - if (logfile) fprintf(logfile,fmt2,cpu_loop,nprocs,lmp->kokkos->num_threads); + if (screen) fprintf(screen,fmt2,cpu_loop,nprocs, + lmp->kokkos->num_threads); + if (logfile) fprintf(logfile,fmt2,cpu_loop,nprocs, + lmp->kokkos->num_threads); } else { #if defined(_OPENMP) const char fmt2[] = @@ -409,12 +415,61 @@ void Finish::end(int flag) } } + // HYPER stats using PAIR,BOND,KSPACE for dynamics,quench + + if (hyperflag) { + if (me == 0) { + if (screen) fprintf(screen,"\nHyper stats:\n"); + if (logfile) fprintf(logfile,"\nHyper stats:\n"); + } + + time = timer->get_wall(Timer::DYNAMICS); + MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); + time = tmp/nprocs; + if (me == 0) { + if (screen) + fprintf(screen," Dynamics time (%%) = %g (%g)\n", + time,time/time_loop*100.0); + if (logfile) + fprintf(logfile," Dynamics time (%%) = %g (%g)\n", + time,time/time_loop*100.0); + } + + time = timer->get_wall(Timer::QUENCH); + MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); + time = tmp/nprocs; + if (me == 0) { + if (screen) + fprintf(screen," Quench time (%%) = %g (%g)\n", + time,time/time_loop*100.0); + if (logfile) + fprintf(logfile," Quench time (%%) = %g (%g)\n", + time,time/time_loop*100.0); + } + + time = time_other; + MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world); + time = tmp/nprocs; + if (me == 0) { + if (screen) + fprintf(screen," Other time (%%) = %g (%g)\n", + time,time/time_loop*100.0); + if (logfile) + fprintf(logfile," Other time (%%) = %g (%g)\n", + time,time/time_loop*100.0); + } + } + + // further timing breakdowns + if (timeflag && timer->has_normal()) { if (timer->has_full()) { const char hdr[] = "\nMPI task timing breakdown:\n" - "Section | min time | avg time | max time |%varavg| %CPU | %total\n" - "-----------------------------------------------------------------------\n"; + "Section | min time | avg time | max time " + "|%varavg| %CPU | %total\n" + "-----------------------------------------------" + "------------------------\n"; if (me == 0) { if (screen) fputs(hdr,screen); if (logfile) fputs(hdr,logfile); @@ -516,8 +571,10 @@ void Finish::end(int flag) if (lmp->kokkos && lmp->kokkos->ngpu > 0) if (const char* env_clb = getenv("CUDA_LAUNCH_BLOCKING")) if (!(strcmp(env_clb,"1") == 0)) { - error->warning(FLERR,"Timing breakdown may not be accurate since GPU/CPU overlap is enabled. " - "Using 'export CUDA_LAUNCH_BLOCKING=1' will give an accurate timing breakdown but will reduce performance"); + error->warning(FLERR,"Timing breakdown may not be accurate " + "since GPU/CPU overlap is enabled\n" + "Using 'export CUDA_LAUNCH_BLOCKING=1' will give an " + "accurate timing breakdown but will reduce performance"); } // FFT timing statistics diff --git a/src/fix.h b/src/fix.h index 65ababf287..bd3189afe7 100644 --- a/src/fix.h +++ b/src/fix.h @@ -113,6 +113,7 @@ class Fix : protected Pointers { virtual void setup_pre_exchange() {} virtual void setup_pre_neighbor() {} virtual void setup_pre_force(int) {} + virtual void setup_pre_reverse(int, int) {} virtual void min_setup(int) {} virtual void initial_integrate(int) {} virtual void post_integrate() {} @@ -151,12 +152,10 @@ class Fix : protected Pointers { virtual void post_force_respa(int, int, int) {} virtual void final_integrate_respa(int, int) {} - virtual void min_setup_pre_exchange() {} - virtual void min_setup_pre_neighbor() {} - virtual void min_setup_pre_force(int) {} virtual void min_pre_exchange() {} virtual void min_pre_neighbor() {} virtual void min_pre_force(int) {} + virtual void min_pre_reverse(int,int) {} virtual void min_post_force(int) {} virtual double min_energy(double *) {return 0.0;} @@ -241,23 +240,24 @@ namespace FixConst { static const int PRE_EXCHANGE = 1<<2; static const int PRE_NEIGHBOR = 1<<3; static const int PRE_FORCE = 1<<4; - static const int POST_FORCE = 1<<5; - static const int FINAL_INTEGRATE = 1<<6; - static const int END_OF_STEP = 1<<7; - static const int THERMO_ENERGY = 1<<8; - static const int INITIAL_INTEGRATE_RESPA = 1<<9; - static const int POST_INTEGRATE_RESPA = 1<<10; - static const int PRE_FORCE_RESPA = 1<<11; - static const int POST_FORCE_RESPA = 1<<12; - static const int FINAL_INTEGRATE_RESPA = 1<<13; - static const int MIN_PRE_EXCHANGE = 1<<14; - static const int MIN_PRE_NEIGHBOR = 1<<15; - static const int MIN_PRE_FORCE = 1<<16; - static const int MIN_POST_FORCE = 1<<17; - static const int MIN_ENERGY = 1<<18; - static const int POST_RUN = 1<<19; - static const int PRE_REVERSE = 1<<20; - static const int FIX_CONST_LAST = 1<<21; + static const int PRE_REVERSE = 1<<5; + static const int POST_FORCE = 1<<6; + static const int FINAL_INTEGRATE = 1<<7; + static const int END_OF_STEP = 1<<8; + static const int POST_RUN = 1<<9; + static const int THERMO_ENERGY = 1<<10; + static const int INITIAL_INTEGRATE_RESPA = 1<<11; + static const int POST_INTEGRATE_RESPA = 1<<12; + static const int PRE_FORCE_RESPA = 1<<13; + static const int POST_FORCE_RESPA = 1<<14; + static const int FINAL_INTEGRATE_RESPA = 1<<15; + static const int MIN_PRE_EXCHANGE = 1<<16; + static const int MIN_PRE_NEIGHBOR = 1<<17; + static const int MIN_PRE_FORCE = 1<<18; + static const int MIN_PRE_REVERSE = 1<<19; + static const int MIN_POST_FORCE = 1<<20; + static const int MIN_ENERGY = 1<<21; + static const int FIX_CONST_LAST = 1<<22; } } diff --git a/src/fix_momentum.h b/src/fix_momentum.h index ffe33880e0..05fd7ff7c8 100644 --- a/src/fix_momentum.h +++ b/src/fix_momentum.h @@ -31,7 +31,7 @@ class FixMomentum : public Fix { void init(); void end_of_step(); - private: + protected: int linear,angular,rescale; int xflag,yflag,zflag; int dynamic; diff --git a/src/fix_restrain.cpp b/src/fix_restrain.cpp index 067f1014d5..f276be76af 100644 --- a/src/fix_restrain.cpp +++ b/src/fix_restrain.cpp @@ -45,7 +45,8 @@ enum{BOND,ANGLE,DIHEDRAL}; FixRestrain::FixRestrain(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg), - rstyle(NULL), ids(NULL), kstart(NULL), kstop(NULL), target(NULL), cos_target(NULL), sin_target(NULL) + rstyle(NULL), ids(NULL), kstart(NULL), kstop(NULL), target(NULL), + cos_target(NULL), sin_target(NULL) { if (narg < 4) error->all(FLERR,"Illegal fix restrain command"); diff --git a/src/force.cpp b/src/force.cpp index 95a6ff4f6d..3dd28cc710 100644 --- a/src/force.cpp +++ b/src/force.cpp @@ -195,6 +195,8 @@ void Force::create_pair(const char *style, int trysuffix) { delete [] pair_style; if (pair) delete pair; + pair_style = NULL; + pair = NULL; int sflag; pair = new_pair(style,trysuffix,sflag); diff --git a/src/min.cpp b/src/min.cpp index 6e568aee0b..9207c6bdc2 100644 --- a/src/min.cpp +++ b/src/min.cpp @@ -284,7 +284,7 @@ void Min::setup() else force->kspace->compute_dummy(eflag,vflag); } - modify->pre_reverse(eflag,vflag); + modify->setup_pre_reverse(eflag,vflag); if (force->newton) comm->reverse_comm(); // update per-atom minimization variables stored by pair styles @@ -365,7 +365,7 @@ void Min::setup_minimal(int flag) else force->kspace->compute_dummy(eflag,vflag); } - modify->pre_reverse(eflag,vflag); + modify->setup_pre_reverse(eflag,vflag); if (force->newton) comm->reverse_comm(); // update per-atom minimization variables stored by pair styles @@ -493,6 +493,11 @@ double Min::energy_force(int resetflag) comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); timer->stamp(Timer::COMM); + if (modify->n_min_pre_neighbor) { + timer->stamp(); + modify->min_pre_neighbor(); + timer->stamp(Timer::MODIFY); + } neighbor->build(); timer->stamp(Timer::NEIGH); } @@ -525,8 +530,8 @@ double Min::energy_force(int resetflag) timer->stamp(Timer::KSPACE); } - if (modify->n_pre_reverse) { - modify->pre_reverse(eflag,vflag); + if (modify->n_min_pre_reverse) { + modify->min_pre_reverse(eflag,vflag); timer->stamp(Timer::MODIFY); } diff --git a/src/modify.cpp b/src/modify.cpp index 2e5bd78504..14e55ab414 100644 --- a/src/modify.cpp +++ b/src/modify.cpp @@ -47,7 +47,8 @@ Modify::Modify(LAMMPS *lmp) : Pointers(lmp) n_thermo_energy_atom = 0; n_initial_integrate_respa = n_post_integrate_respa = 0; n_pre_force_respa = n_post_force_respa = n_final_integrate_respa = 0; - n_min_pre_exchange = n_min_pre_force = n_min_post_force = n_min_energy = 0; + n_min_pre_exchange = n_min_pre_force = n_min_pre_reverse = 0; + n_min_post_force = n_min_energy = 0; fix = NULL; fmask = NULL; @@ -60,7 +61,7 @@ Modify::Modify(LAMMPS *lmp) : Pointers(lmp) list_pre_force_respa = list_post_force_respa = NULL; list_final_integrate_respa = NULL; list_min_pre_exchange = list_min_pre_neighbor = NULL; - list_min_pre_force = list_min_post_force = NULL; + list_min_pre_force = list_min_pre_reverse = list_min_post_force = NULL; list_min_energy = NULL; end_of_step_every = NULL; @@ -136,6 +137,7 @@ Modify::~Modify() delete [] list_min_pre_exchange; delete [] list_min_pre_neighbor; delete [] list_min_pre_force; + delete [] list_min_pre_reverse; delete [] list_min_post_force; delete [] list_min_energy; @@ -188,6 +190,7 @@ void Modify::init() list_init(MIN_PRE_EXCHANGE,n_min_pre_exchange,list_min_pre_exchange); list_init(MIN_PRE_NEIGHBOR,n_min_pre_neighbor,list_min_pre_neighbor); list_init(MIN_PRE_FORCE,n_min_pre_force,list_min_pre_force); + list_init(MIN_PRE_REVERSE,n_min_pre_reverse,list_min_pre_reverse); list_init(MIN_POST_FORCE,n_min_post_force,list_min_post_force); list_init(MIN_ENERGY,n_min_energy,list_min_energy); @@ -307,7 +310,7 @@ void Modify::setup_pre_exchange() fix[list_pre_exchange[i]]->setup_pre_exchange(); else if (update->whichflag == 2) for (int i = 0; i < n_min_pre_exchange; i++) - fix[list_min_pre_exchange[i]]->min_setup_pre_exchange(); + fix[list_min_pre_exchange[i]]->setup_pre_exchange(); } /* ---------------------------------------------------------------------- @@ -322,7 +325,7 @@ void Modify::setup_pre_neighbor() fix[list_pre_neighbor[i]]->setup_pre_neighbor(); else if (update->whichflag == 2) for (int i = 0; i < n_min_pre_neighbor; i++) - fix[list_min_pre_neighbor[i]]->min_setup_pre_neighbor(); + fix[list_min_pre_neighbor[i]]->setup_pre_neighbor(); } /* ---------------------------------------------------------------------- @@ -337,7 +340,22 @@ void Modify::setup_pre_force(int vflag) fix[list_pre_force[i]]->setup_pre_force(vflag); else if (update->whichflag == 2) for (int i = 0; i < n_min_pre_force; i++) - fix[list_min_pre_force[i]]->min_setup_pre_force(vflag); + fix[list_min_pre_force[i]]->setup_pre_force(vflag); +} + +/* ---------------------------------------------------------------------- + setup pre_reverse call, only for fixes that define pre_reverse + called from Verlet, RESPA, Min +------------------------------------------------------------------------- */ + +void Modify::setup_pre_reverse(int eflag, int vflag) +{ + if (update->whichflag == 1) + for (int i = 0; i < n_pre_reverse; i++) + fix[list_pre_reverse[i]]->setup_pre_reverse(eflag,vflag); + else if (update->whichflag == 2) + for (int i = 0; i < n_min_pre_reverse; i++) + fix[list_min_pre_reverse[i]]->setup_pre_reverse(eflag,vflag); } /* ---------------------------------------------------------------------- @@ -580,6 +598,16 @@ void Modify::min_pre_force(int vflag) fix[list_min_pre_force[i]]->min_pre_force(vflag); } +/* ---------------------------------------------------------------------- + minimizer pre-reverse call, only for relevant fixes +------------------------------------------------------------------------- */ + +void Modify::min_pre_reverse(int eflag, int vflag) +{ + for (int i = 0; i < n_min_pre_reverse; i++) + fix[list_min_pre_reverse[i]]->min_pre_reverse(eflag,vflag); +} + /* ---------------------------------------------------------------------- minimizer force adjustment call, only for relevant fixes ------------------------------------------------------------------------- */ diff --git a/src/modify.h b/src/modify.h index f6f59a6a9c..d6793a754e 100644 --- a/src/modify.h +++ b/src/modify.h @@ -35,7 +35,7 @@ class Modify : protected Pointers { int n_initial_integrate_respa,n_post_integrate_respa; int n_pre_force_respa,n_post_force_respa,n_final_integrate_respa; int n_min_pre_exchange,n_min_pre_neighbor; - int n_min_pre_force,n_min_post_force,n_min_energy; + int n_min_pre_force,n_min_pre_reverse,n_min_post_force,n_min_energy; int restart_pbc_any; // 1 if any fix sets restart_pbc int nfix_restart_global; // stored fix global info from restart file @@ -54,6 +54,7 @@ class Modify : protected Pointers { virtual void setup_pre_exchange(); virtual void setup_pre_neighbor(); virtual void setup_pre_force(int); + virtual void setup_pre_reverse(int, int); virtual void initial_integrate(int); virtual void post_integrate(); virtual void pre_exchange(); @@ -78,6 +79,7 @@ class Modify : protected Pointers { virtual void min_pre_exchange(); virtual void min_pre_neighbor(); virtual void min_pre_force(int); + virtual void min_pre_reverse(int,int); virtual void min_post_force(int); virtual double min_energy(double *); @@ -124,7 +126,7 @@ class Modify : protected Pointers { int *list_pre_force_respa,*list_post_force_respa; int *list_final_integrate_respa; int *list_min_pre_exchange,*list_min_pre_neighbor; - int *list_min_pre_force,*list_min_post_force; + int *list_min_pre_force,*list_min_pre_reverse,*list_min_post_force; int *list_min_energy; int *end_of_step_every; diff --git a/src/neighbor.cpp b/src/neighbor.cpp index b02d88955c..59abc29f19 100644 --- a/src/neighbor.cpp +++ b/src/neighbor.cpp @@ -73,7 +73,8 @@ static const char cite_neigh_multi[] = /* ---------------------------------------------------------------------- */ -Neighbor::Neighbor(LAMMPS *lmp) : Pointers(lmp) +Neighbor::Neighbor(LAMMPS *lmp) : Pointers(lmp), +pairclass(NULL), pairnames(NULL), pairmasks(NULL) { MPI_Comm_rank(world,&me); MPI_Comm_size(world,&nprocs); diff --git a/src/pair_table.cpp b/src/pair_table.cpp index c4bc3e7dd2..b36843ff44 100644 --- a/src/pair_table.cpp +++ b/src/pair_table.cpp @@ -46,6 +46,8 @@ PairTable::PairTable(LAMMPS *lmp) : Pair(lmp) PairTable::~PairTable() { + if (copymode) return; + for (int m = 0; m < ntables; m++) free_table(&tables[m]); memory->sfree(tables); diff --git a/src/pair_table.h b/src/pair_table.h index 358491f7cf..59de59145f 100644 --- a/src/pair_table.h +++ b/src/pair_table.h @@ -63,7 +63,7 @@ class PairTable : public Pair { void param_extract(Table *, char *); void bcast_table(Table *); void spline_table(Table *); - void compute_table(Table *); + virtual void compute_table(Table *); void null_table(Table *); void free_table(Table *); void spline(double *, double *, int, double, double, double *); diff --git a/src/respa.cpp b/src/respa.cpp index db0f11d5b3..7646115fa9 100644 --- a/src/respa.cpp +++ b/src/respa.cpp @@ -44,8 +44,10 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ -Respa::Respa(LAMMPS *lmp, int narg, char **arg) : Integrate(lmp, narg, arg), -step(NULL), loop(NULL), hybrid_level(NULL), hybrid_compute(NULL), newton(NULL), fix_respa(NULL) +Respa::Respa(LAMMPS *lmp, int narg, char **arg) : + Integrate(lmp, narg, arg), + step(NULL), loop(NULL), hybrid_level(NULL), hybrid_compute(NULL), + newton(NULL), fix_respa(NULL) { nhybrid_styles = 0; if (narg < 1) error->all(FLERR,"Illegal run_style respa command"); @@ -473,7 +475,7 @@ void Respa::setup() if (kspace_compute_flag) force->kspace->compute(eflag,vflag); } - modify->pre_reverse(eflag,vflag); + modify->setup_pre_reverse(eflag,vflag); if (newton[ilevel]) comm->reverse_comm(); copy_f_flevel(ilevel); } @@ -549,7 +551,7 @@ void Respa::setup_minimal(int flag) if (kspace_compute_flag) force->kspace->compute(eflag,vflag); } - modify->pre_reverse(eflag,vflag); + modify->setup_pre_reverse(eflag,vflag); if (newton[ilevel]) comm->reverse_comm(); copy_f_flevel(ilevel); } diff --git a/src/run.cpp b/src/run.cpp index f238e7852b..3317545342 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -43,6 +43,7 @@ void Run::command(int narg, char **arg) error->all(FLERR,"Run command before simulation box is defined"); // ignore run command, if walltime limit was already reached + if (timer->is_timeout()) return; bigint nsteps_input = force->bnumeric(FLERR,arg[0]); diff --git a/src/verlet.cpp b/src/verlet.cpp index 035cab79ef..915648040e 100644 --- a/src/verlet.cpp +++ b/src/verlet.cpp @@ -144,7 +144,7 @@ void Verlet::setup() else force->kspace->compute_dummy(eflag,vflag); } - modify->pre_reverse(eflag,vflag); + modify->setup_pre_reverse(eflag,vflag); if (force->newton) comm->reverse_comm(); modify->setup(vflag); @@ -205,7 +205,7 @@ void Verlet::setup_minimal(int flag) else force->kspace->compute_dummy(eflag,vflag); } - modify->pre_reverse(eflag,vflag); + modify->setup_pre_reverse(eflag,vflag); if (force->newton) comm->reverse_comm(); modify->setup(vflag); diff --git a/src/version.h b/src/version.h index fb2e3c5784..175eddeba6 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define LAMMPS_VERSION "21 Dec 2016" +#define LAMMPS_VERSION "6 Jan 2017"