/* -------------------------------------------------------------------------- * * OpenMM * * -------------------------------------------------------------------------- * * This is part of the OpenMM molecular simulation toolkit originating from * * Simbios, the NIH National Center for Physics-Based Simulation of * * Biological Structures at Stanford, funded under the NIH Roadmap for * * Medical Research, grant U54 GM072970. See https://simtk.org. * * * * Portions copyright (c) 2010 Stanford University and the Authors. * * Authors: Peter Eastman * * Contributors: * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the "Software"), * * to deal in the Software without restriction, including without limitation * * the rights to use, copy, modify, merge, publish, distribute, sublicense, * * and/or sell copies of the Software, and to permit persons to whom the * * Software is furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included in * * all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * * USE OR OTHER DEALINGS IN THE SOFTWARE. * * -------------------------------------------------------------------------- */ #include "openmm/internal/MonteCarloBarostatImpl.h" #include "openmm/internal/ContextImpl.h" #include "openmm/Context.h" #include "openmm/kernels.h" #include #include using namespace OpenMM; using namespace OpenMM_SFMT; using std::vector; const float BOLTZMANN = 1.380658e-23f; // (J/K) const float AVOGADRO = 6.0221367e23f; const float RGAS = BOLTZMANN*AVOGADRO; // (J/(mol K)) const float BOLTZ = RGAS/1000; // (kJ/(mol K)) MonteCarloBarostatImpl::MonteCarloBarostatImpl(MonteCarloBarostat& owner) : owner(owner), step(0) { } void MonteCarloBarostatImpl::initialize(ContextImpl& context) { kernel = context.getPlatform().createKernel(ApplyMonteCarloBarostatKernel::Name(), context); dynamic_cast(kernel.getImpl()).initialize(context.getSystem(), owner); Vec3 box[3]; context.getPeriodicBoxVectors(box[0], box[1], box[2]); double volume = box[0][0]*box[1][1]*box[2][2]; volumeScale = 0.01*volume; init_gen_rand(owner.getRandomNumberSeed(), random); } void MonteCarloBarostatImpl::updateContextState(ContextImpl& context) { if (++step < owner.getFrequency()) return; step = 0; // Compute the current potential energy. double initialEnergy = context.getOwner().getState(State::Energy).getPotentialEnergy(); // Modify the periodic box size. Vec3 box[3]; context.getPeriodicBoxVectors(box[0], box[1], box[2]); double volume = box[0][0]*box[1][1]*box[2][2]; double deltaVolume = volumeScale*2*(genrand_real2(random)-0.5); double newVolume = volume+deltaVolume; double lengthScale = std::pow(newVolume/volume, 1.0/3.0); dynamic_cast(kernel.getImpl()).scaleCoordinates(context, lengthScale); context.getOwner().setPeriodicBoxVectors(box[0]*lengthScale, box[1]*lengthScale, box[2]*lengthScale); // Compute the energy of the modified system. double finalEnergy = context.getOwner().getState(State::Energy).getPotentialEnergy(); double pressure = context.getParameter(MonteCarloBarostat::Pressure())*(AVOGADRO*1e-25); double kT = BOLTZ*owner.getTemperature(); double w = finalEnergy-initialEnergy + pressure*deltaVolume - context.getMolecules().size()*kT*std::log(newVolume/volume); if (w > 0 && genrand_real2(random) > std::exp(-w/kT)) { // Reject the step. dynamic_cast(kernel.getImpl()).restoreCoordinates(context); context.getOwner().setPeriodicBoxVectors(box[0], box[1], box[2]); volumeScale /= 1.1; } else volumeScale = std::min(volumeScale*1.1, newVolume*0.1); } std::map MonteCarloBarostatImpl::getDefaultParameters() { std::map parameters; parameters[MonteCarloBarostat::Pressure()] = getOwner().getDefaultPressure(); return parameters; } std::vector MonteCarloBarostatImpl::getKernelNames() { std::vector names; names.push_back(ApplyMonteCarloBarostatKernel::Name()); return names; }