Commit 457d7bd2 authored by peastman's avatar peastman
Browse files

Merge pull request #1120 from peastman/pmeparams

Created getPMEParametersInContext()
parents cef58048 b20fe9a6
...@@ -579,6 +579,10 @@ void OpenCLParallelCalcNonbondedForceKernel::copyParametersToContext(ContextImpl ...@@ -579,6 +579,10 @@ void OpenCLParallelCalcNonbondedForceKernel::copyParametersToContext(ContextImpl
getKernel(i).copyParametersToContext(context, force); getKernel(i).copyParametersToContext(context, force);
} }
void OpenCLParallelCalcNonbondedForceKernel::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const {
dynamic_cast<const OpenCLCalcNonbondedForceKernel&>(kernels[0].getImpl()).getPMEParameters(alpha, nx, ny, nz);
}
class OpenCLParallelCalcCustomNonbondedForceKernel::Task : public OpenCLContext::WorkTask { class OpenCLParallelCalcCustomNonbondedForceKernel::Task : public OpenCLContext::WorkTask {
public: public:
Task(ContextImpl& context, OpenCLCalcCustomNonbondedForceKernel& kernel, bool includeForce, Task(ContextImpl& context, OpenCLCalcCustomNonbondedForceKernel& kernel, bool includeForce,
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "openmm/LangevinIntegrator.h" #include "openmm/LangevinIntegrator.h"
#include "openmm/VerletIntegrator.h" #include "openmm/VerletIntegrator.h"
#include "openmm/internal/ContextImpl.h" #include "openmm/internal/ContextImpl.h"
#include "openmm/internal/NonbondedForceImpl.h"
#include "SimTKOpenMMRealType.h" #include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h" #include "sfmt/SFMT.h"
#include <iostream> #include <iostream>
...@@ -299,6 +300,19 @@ void testErrorTolerance(NonbondedForce::NonbondedMethod method) { ...@@ -299,6 +300,19 @@ void testErrorTolerance(NonbondedForce::NonbondedMethod method) {
diff = sqrt(diff)/norm; diff = sqrt(diff)/norm;
ASSERT(diff < 2*tol); ASSERT(diff < 2*tol);
} }
if (method == NonbondedForce::PME) {
// See if the PME parameters were calculated correctly.
double expectedAlpha, actualAlpha;
int expectedSize[3], actualSize[3];
NonbondedForceImpl::calcPMEParameters(system, *force, expectedAlpha, expectedSize[0], expectedSize[1], expectedSize[2]);
force->getPMEParametersInContext(context, actualAlpha, actualSize[0], actualSize[1], actualSize[2]);
ASSERT_EQUAL_TOL(expectedAlpha, actualAlpha, 1e-5);
for (int i = 0; i < 3; i++) {
ASSERT(actualSize[i] >= expectedSize[i]);
ASSERT(actualSize[i] < expectedSize[i]+10);
}
}
} }
} }
} }
......
...@@ -578,6 +578,15 @@ public: ...@@ -578,6 +578,15 @@ public:
* @param force the NonbondedForce to copy the parameters from * @param force the NonbondedForce to copy the parameters from
*/ */
void copyParametersToContext(ContextImpl& context, const NonbondedForce& force); void copyParametersToContext(ContextImpl& context, const NonbondedForce& force);
/**
* Get the parameters being used for PME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
private: private:
int numParticles, num14; int numParticles, num14;
int **bonded14IndexArray; int **bonded14IndexArray;
......
...@@ -969,6 +969,15 @@ void ReferenceCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& con ...@@ -969,6 +969,15 @@ void ReferenceCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& con
dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(context.getSystem(), force); dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(context.getSystem(), force);
} }
void ReferenceCalcNonbondedForceKernel::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const {
if (nonbondedMethod != PME)
throw OpenMMException("getPMEParametersInContext: This Context is not using PME");
alpha = ewaldAlpha;
nx = gridSize[0];
ny = gridSize[1];
nz = gridSize[2];
}
ReferenceCalcCustomNonbondedForceKernel::~ReferenceCalcCustomNonbondedForceKernel() { ReferenceCalcCustomNonbondedForceKernel::~ReferenceCalcCustomNonbondedForceKernel() {
disposeRealArray(particleParamArray, numParticles); disposeRealArray(particleParamArray, numParticles);
if (neighborList != NULL) if (neighborList != NULL)
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "SimTKOpenMMRealType.h" #include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h" #include "sfmt/SFMT.h"
#include "openmm/HarmonicBondForce.h" #include "openmm/HarmonicBondForce.h"
#include "openmm/internal/NonbondedForceImpl.h"
#include <iostream> #include <iostream>
#include <vector> #include <vector>
...@@ -397,6 +398,19 @@ void testErrorTolerance(NonbondedForce::NonbondedMethod method) { ...@@ -397,6 +398,19 @@ void testErrorTolerance(NonbondedForce::NonbondedMethod method) {
diff = sqrt(diff)/norm; diff = sqrt(diff)/norm;
ASSERT(diff < 2*tol); ASSERT(diff < 2*tol);
} }
if (method == NonbondedForce::PME) {
// See if the PME parameters were calculated correctly.
double expectedAlpha, actualAlpha;
int expectedSize[3], actualSize[3];
NonbondedForceImpl::calcPMEParameters(system, *force, expectedAlpha, expectedSize[0], expectedSize[1], expectedSize[2]);
force->getPMEParametersInContext(context, actualAlpha, actualSize[0], actualSize[1], actualSize[2]);
ASSERT_EQUAL_TOL(expectedAlpha, actualAlpha, 1e-5);
for (int i = 0; i < 3; i++) {
ASSERT(actualSize[i] >= expectedSize[i]);
ASSERT(actualSize[i] < expectedSize[i]+10);
}
}
} }
} }
} }
......
...@@ -175,6 +175,20 @@ public: ...@@ -175,6 +175,20 @@ public:
*/ */
void setPmeGridDimensions(const std::vector<int>& gridDimension); void setPmeGridDimensions(const std::vector<int>& gridDimension);
/**
* Get the parameters being used for PME in a particular Context. Because some platforms have restrictions
* on the allowed grid sizes, the values that are actually used may be slightly different from those
* specified with setPmeGridDimensions(), or the standard values calculated based on the Ewald error tolerance.
* See the manual for details.
*
* @param context the Context for which to get the parameters
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void getPMEParametersInContext(const Context& context, double& alpha, int& nx, int& ny, int& nz) const;
/** /**
* Add multipole-related info for a particle * Add multipole-related info for a particle
* *
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2012 Stanford University and the Authors. * * Portions copyright (c) 2008-2015 Stanford University and the Authors. *
* Authors: * * Authors: *
* Contributors: * * Contributors: *
* * * *
...@@ -361,6 +361,16 @@ public: ...@@ -361,6 +361,16 @@ public:
* @param force the AmoebaMultipoleForce to copy the parameters from * @param force the AmoebaMultipoleForce to copy the parameters from
*/ */
virtual void copyParametersToContext(ContextImpl& context, const AmoebaMultipoleForce& force) = 0; virtual void copyParametersToContext(ContextImpl& context, const AmoebaMultipoleForce& force) = 0;
/**
* Get the parameters being used for PME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
virtual void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const = 0;
}; };
/** /**
......
...@@ -89,6 +89,7 @@ public: ...@@ -89,6 +89,7 @@ public:
void getSystemMultipoleMoments(ContextImpl& context, std::vector< double >& outputMultipoleMoments); void getSystemMultipoleMoments(ContextImpl& context, std::vector< double >& outputMultipoleMoments);
void updateParametersInContext(ContextImpl& context); void updateParametersInContext(ContextImpl& context);
void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
private: private:
......
...@@ -103,6 +103,10 @@ void AmoebaMultipoleForce::setPmeGridDimensions(const std::vector<int>& gridDime ...@@ -103,6 +103,10 @@ void AmoebaMultipoleForce::setPmeGridDimensions(const std::vector<int>& gridDime
return; return;
} }
void AmoebaMultipoleForce::getPMEParametersInContext(const Context& context, double& alpha, int& nx, int& ny, int& nz) const {
dynamic_cast<const AmoebaMultipoleForceImpl&>(getImplInContext(context)).getPMEParameters(alpha, nx, ny, nz);
}
int AmoebaMultipoleForce::getMutualInducedMaxIterations() const { int AmoebaMultipoleForce::getMutualInducedMaxIterations() const {
return mutualInducedMaxIterations; return mutualInducedMaxIterations;
} }
......
...@@ -199,3 +199,7 @@ void AmoebaMultipoleForceImpl::getSystemMultipoleMoments(ContextImpl& context, s ...@@ -199,3 +199,7 @@ void AmoebaMultipoleForceImpl::getSystemMultipoleMoments(ContextImpl& context, s
void AmoebaMultipoleForceImpl::updateParametersInContext(ContextImpl& context) { void AmoebaMultipoleForceImpl::updateParametersInContext(ContextImpl& context) {
kernel.getAs<CalcAmoebaMultipoleForceKernel>().copyParametersToContext(context, owner); kernel.getAs<CalcAmoebaMultipoleForceKernel>().copyParametersToContext(context, owner);
} }
void AmoebaMultipoleForceImpl::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const {
kernel.getAs<CalcAmoebaMultipoleForceKernel>().getPMEParameters(alpha, nx, ny, nz);
}
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "openmm/internal/AmoebaVdwForceImpl.h" #include "openmm/internal/AmoebaVdwForceImpl.h"
#include "openmm/internal/NonbondedForceImpl.h" #include "openmm/internal/NonbondedForceImpl.h"
#include "CudaBondedUtilities.h" #include "CudaBondedUtilities.h"
#include "CudaFFT3D.h"
#include "CudaForceInfo.h" #include "CudaForceInfo.h"
#include "CudaKernelSources.h" #include "CudaKernelSources.h"
#include "CudaNonbondedUtilities.h" #include "CudaNonbondedUtilities.h"
...@@ -902,26 +903,6 @@ CudaCalcAmoebaMultipoleForceKernel::~CudaCalcAmoebaMultipoleForceKernel() { ...@@ -902,26 +903,6 @@ CudaCalcAmoebaMultipoleForceKernel::~CudaCalcAmoebaMultipoleForceKernel() {
cufftDestroy(fft); cufftDestroy(fft);
} }
/**
* Select a size for an FFT that is a multiple of 2, 3, 5, and 7.
*/
static int findFFTDimension(int minimum) {
if (minimum < 1)
return 1;
while (true) {
// Attempt to factor the current value.
int unfactored = minimum;
for (int factor = 2; factor < 8; factor++) {
while (unfactored > 1 && unfactored%factor == 0)
unfactored /= factor;
}
if (unfactored == 1)
return minimum;
minimum++;
}
}
void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const AmoebaMultipoleForce& force) { void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const AmoebaMultipoleForce& force) {
cu.setAsCurrent(); cu.setAsCurrent();
...@@ -1063,7 +1044,7 @@ void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const ...@@ -1063,7 +1044,7 @@ void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const
} }
else else
maxInducedIterations = 0; maxInducedIterations = 0;
bool usePME = (force.getNonbondedMethod() == AmoebaMultipoleForce::PME); usePME = (force.getNonbondedMethod() == AmoebaMultipoleForce::PME);
// See whether there's an AmoebaGeneralizedKirkwoodForce in the System. // See whether there's an AmoebaGeneralizedKirkwoodForce in the System.
...@@ -1099,8 +1080,7 @@ void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const ...@@ -1099,8 +1080,7 @@ void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const
int endExclusionIndex = (cu.getContextIndex()+1)*numExclusionTiles/numContexts; int endExclusionIndex = (cu.getContextIndex()+1)*numExclusionTiles/numContexts;
defines["FIRST_EXCLUSION_TILE"] = cu.intToString(startExclusionIndex); defines["FIRST_EXCLUSION_TILE"] = cu.intToString(startExclusionIndex);
defines["LAST_EXCLUSION_TILE"] = cu.intToString(endExclusionIndex); defines["LAST_EXCLUSION_TILE"] = cu.intToString(endExclusionIndex);
double alpha = force.getAEwald(); alpha = force.getAEwald();
int gridSizeX, gridSizeY, gridSizeZ;
if (usePME) { if (usePME) {
vector<int> pmeGridDimension; vector<int> pmeGridDimension;
force.getPmeGridDimensions(pmeGridDimension); force.getPmeGridDimensions(pmeGridDimension);
...@@ -1109,13 +1089,13 @@ void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const ...@@ -1109,13 +1089,13 @@ void CudaCalcAmoebaMultipoleForceKernel::initialize(const System& system, const
nb.setEwaldErrorTolerance(force.getEwaldErrorTolerance()); nb.setEwaldErrorTolerance(force.getEwaldErrorTolerance());
nb.setCutoffDistance(force.getCutoffDistance()); nb.setCutoffDistance(force.getCutoffDistance());
NonbondedForceImpl::calcPMEParameters(system, nb, alpha, gridSizeX, gridSizeY, gridSizeZ); NonbondedForceImpl::calcPMEParameters(system, nb, alpha, gridSizeX, gridSizeY, gridSizeZ);
gridSizeX = findFFTDimension(gridSizeX); gridSizeX = CudaFFT3D::findLegalDimension(gridSizeX);
gridSizeY = findFFTDimension(gridSizeY); gridSizeY = CudaFFT3D::findLegalDimension(gridSizeY);
gridSizeZ = findFFTDimension(gridSizeZ); gridSizeZ = CudaFFT3D::findLegalDimension(gridSizeZ);
} else { } else {
gridSizeX = pmeGridDimension[0]; gridSizeX = CudaFFT3D::findLegalDimension(pmeGridDimension[0]);
gridSizeY = pmeGridDimension[1]; gridSizeY = CudaFFT3D::findLegalDimension(pmeGridDimension[1]);
gridSizeZ = pmeGridDimension[2]; gridSizeZ = CudaFFT3D::findLegalDimension(pmeGridDimension[2]);
} }
defines["EWALD_ALPHA"] = cu.doubleToString(alpha); defines["EWALD_ALPHA"] = cu.doubleToString(alpha);
defines["SQRT_PI"] = cu.doubleToString(sqrt(M_PI)); defines["SQRT_PI"] = cu.doubleToString(sqrt(M_PI));
...@@ -2035,6 +2015,15 @@ void CudaCalcAmoebaMultipoleForceKernel::copyParametersToContext(ContextImpl& co ...@@ -2035,6 +2015,15 @@ void CudaCalcAmoebaMultipoleForceKernel::copyParametersToContext(ContextImpl& co
multipolesAreValid = false; multipolesAreValid = false;
} }
void CudaCalcAmoebaMultipoleForceKernel::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const {
if (!usePME)
throw OpenMMException("getPMEParametersInContext: This Context is not using PME");
alpha = this->alpha;
nx = gridSizeX;
ny = gridSizeY;
nz = gridSizeZ;
}
/* -------------------------------------------------------------------------- * /* -------------------------------------------------------------------------- *
* AmoebaGeneralizedKirkwood * * AmoebaGeneralizedKirkwood *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
......
...@@ -363,6 +363,15 @@ public: ...@@ -363,6 +363,15 @@ public:
* @param force the AmoebaMultipoleForce to copy the parameters from * @param force the AmoebaMultipoleForce to copy the parameters from
*/ */
void copyParametersToContext(ContextImpl& context, const AmoebaMultipoleForce& force); void copyParametersToContext(ContextImpl& context, const AmoebaMultipoleForce& force);
/**
* Get the parameters being used for PME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
private: private:
class ForceInfo; class ForceInfo;
class SortTrait : public CudaSort::SortTrait { class SortTrait : public CudaSort::SortTrait {
...@@ -381,8 +390,9 @@ private: ...@@ -381,8 +390,9 @@ private:
template <class T, class T4, class M4> void computeSystemMultipoleMoments(ContextImpl& context, std::vector<double>& outputMultipoleMoments); template <class T, class T4, class M4> void computeSystemMultipoleMoments(ContextImpl& context, std::vector<double>& outputMultipoleMoments);
int numMultipoles, maxInducedIterations; int numMultipoles, maxInducedIterations;
int fixedFieldThreads, inducedFieldThreads, electrostaticsThreads; int fixedFieldThreads, inducedFieldThreads, electrostaticsThreads;
double inducedEpsilon; int gridSizeX, gridSizeY, gridSizeZ;
bool hasQuadrupoles, hasInitializedScaleFactors, hasInitializedFFT, multipolesAreValid; double alpha, inducedEpsilon;
bool usePME, hasQuadrupoles, hasInitializedScaleFactors, hasInitializedFFT, multipolesAreValid;
CudaContext& cu; CudaContext& cu;
const System& system; const System& system;
std::vector<int3> covalentFlagValues; std::vector<int3> covalentFlagValues;
......
...@@ -1943,7 +1943,16 @@ static void setupAndGetForcesEnergyMultipoleLargeWater(AmoebaMultipoleForce::Non ...@@ -1943,7 +1943,16 @@ static void setupAndGetForcesEnergyMultipoleLargeWater(AmoebaMultipoleForce::Non
energy = state.getPotentialEnergy(); energy = state.getPotentialEnergy();
} }
return; if (nonbondedMethod == AmoebaMultipoleForce::PME) {
double actualAlpha;
int actualSize[3];
amoebaMultipoleForce->getPMEParametersInContext(context, actualAlpha, actualSize[0], actualSize[1], actualSize[2]);
ASSERT_EQUAL_TOL(amoebaMultipoleForce->getAEwald(), actualAlpha, 1e-5);
for (int i = 0; i < 3; i++) {
ASSERT(actualSize[i] >= inputPmeGridDimension);
ASSERT(actualSize[i] < inputPmeGridDimension+10);
}
}
} }
// test multipole mutual polarization using PME for box of water // test multipole mutual polarization using PME for box of water
......
...@@ -790,6 +790,15 @@ void ReferenceCalcAmoebaMultipoleForceKernel::copyParametersToContext(ContextImp ...@@ -790,6 +790,15 @@ void ReferenceCalcAmoebaMultipoleForceKernel::copyParametersToContext(ContextImp
} }
} }
void ReferenceCalcAmoebaMultipoleForceKernel::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const {
if (!usePme)
throw OpenMMException("getPMEParametersInContext: This Context is not using PME");
alpha = alphaEwald;
nx = pmeGridDimension[0];
ny = pmeGridDimension[1];
nz = pmeGridDimension[2];
}
/* -------------------------------------------------------------------------- * /* -------------------------------------------------------------------------- *
* AmoebaGeneralizedKirkwood * * AmoebaGeneralizedKirkwood *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008 Stanford University and the Authors. * * Portions copyright (c) 2008-2015 Stanford University and the Authors. *
* Authors: * * Authors: *
* Contributors: * * Contributors: *
* * * *
...@@ -403,6 +403,15 @@ public: ...@@ -403,6 +403,15 @@ public:
* @param force the AmoebaMultipoleForce to copy the parameters from * @param force the AmoebaMultipoleForce to copy the parameters from
*/ */
void copyParametersToContext(ContextImpl& context, const AmoebaMultipoleForce& force); void copyParametersToContext(ContextImpl& context, const AmoebaMultipoleForce& force);
/**
* Get the parameters being used for PME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
private: private:
......
...@@ -1864,7 +1864,16 @@ static void setupAndGetForcesEnergyMultipoleLargeWater(AmoebaMultipoleForce::Non ...@@ -1864,7 +1864,16 @@ static void setupAndGetForcesEnergyMultipoleLargeWater(AmoebaMultipoleForce::Non
energy = state.getPotentialEnergy(); energy = state.getPotentialEnergy();
} }
return; if (nonbondedMethod == AmoebaMultipoleForce::PME) {
double actualAlpha;
int actualSize[3];
amoebaMultipoleForce->getPMEParametersInContext(context, actualAlpha, actualSize[0], actualSize[1], actualSize[2]);
ASSERT_EQUAL_TOL(amoebaMultipoleForce->getAEwald(), actualAlpha, 1e-5);
for (int i = 0; i < 3; i++) {
ASSERT(actualSize[i] >= inputPmeGridDimension);
ASSERT(actualSize[i] < inputPmeGridDimension+10);
}
}
} }
// test multipole mutual polarization using PME for box of water // test multipole mutual polarization using PME for box of water
......
...@@ -583,6 +583,13 @@ bool CpuCalcPmeReciprocalForceKernel::isProcessorSupported() { ...@@ -583,6 +583,13 @@ bool CpuCalcPmeReciprocalForceKernel::isProcessorSupported() {
return isVec4Supported(); return isVec4Supported();
} }
void CpuCalcPmeReciprocalForceKernel::getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const {
alpha = this->alpha;
nx = gridx;
ny = gridy;
nz = gridz;
}
int CpuCalcPmeReciprocalForceKernel::findFFTDimension(int minimum, bool isZ) { int CpuCalcPmeReciprocalForceKernel::findFFTDimension(int minimum, bool isZ) {
if (minimum < 1) if (minimum < 1)
return 1; return 1;
......
...@@ -91,6 +91,15 @@ public: ...@@ -91,6 +91,15 @@ public:
* Get whether the current CPU supports all features needed by this kernel. * Get whether the current CPU supports all features needed by this kernel.
*/ */
static bool isProcessorSupported(); static bool isProcessorSupported();
/**
* Get the parameters being used for PME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
private: private:
class ComputeTask; class ComputeTask;
/** /**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment