Unverified Commit 1dac981a authored by Peter Eastman's avatar Peter Eastman Committed by GitHub
Browse files

Use PocketFFT (#3667)

* Use PocketFFT instead of FFTW

* Minor cleanup

* Use PocketFFT instead of fftpack for reference platform

* Remove FFTW as a dependency

* Converted a test case to use PocketFFT

* Fixed an incorrect comment
parent 583471a6
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,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) 2011-2016 Stanford University and the Authors. * * Portions copyright (c) 2011-2022 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
/** /**
* This tests the OpenCL implementation of sorting. * This tests the OpenCL implementation of FFT.
*/ */
#include "openmm/internal/AssertionUtilities.h" #include "openmm/internal/AssertionUtilities.h"
...@@ -38,12 +38,16 @@ ...@@ -38,12 +38,16 @@
#include "OpenCLContext.h" #include "OpenCLContext.h"
#include "OpenCLFFT3D.h" #include "OpenCLFFT3D.h"
#include "OpenCLSort.h" #include "OpenCLSort.h"
#include "fftpack.h"
#include "sfmt/SFMT.h" #include "sfmt/SFMT.h"
#include "openmm/System.h" #include "openmm/System.h"
#include <complex>
#include <iostream> #include <iostream>
#include <cmath> #include <cmath>
#include <set> #include <set>
#ifdef _MSC_VER
#define POCKETFFT_NO_VECTORS
#endif
#include "pocketfft_hdronly.h"
using namespace OpenMM; using namespace OpenMM;
using namespace std; using namespace std;
...@@ -60,17 +64,17 @@ void testTransform(bool realToComplex, int xsize, int ysize, int zsize) { ...@@ -60,17 +64,17 @@ void testTransform(bool realToComplex, int xsize, int ysize, int zsize) {
OpenMM_SFMT::SFMT sfmt; OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt); init_gen_rand(0, sfmt);
vector<Real2> original(xsize*ysize*zsize); vector<Real2> original(xsize*ysize*zsize);
vector<t_complex> reference(original.size()); vector<complex<double> > reference(original.size());
for (int i = 0; i < (int) original.size(); i++) { for (int i = 0; i < (int) original.size(); i++) {
Real2 value = Real2((cl_float) genrand_real2(sfmt), (cl_float) genrand_real2(sfmt)); Real2 value = Real2((cl_float) genrand_real2(sfmt), (cl_float) genrand_real2(sfmt));
original[i] = value; original[i] = value;
reference[i] = t_complex(value.x, value.y); reference[i] = complex<double>(value.x, value.y);
} }
for (int i = 0; i < (int) reference.size(); i++) { for (int i = 0; i < (int) reference.size(); i++) {
if (realToComplex) if (realToComplex)
reference[i] = t_complex(i%2 == 0 ? original[i/2].x : original[i/2].y, 0); reference[i] = complex<double>(i%2 == 0 ? original[i/2].x : original[i/2].y, 0);
else else
reference[i] = t_complex(original[i].x, original[i].y); reference[i] = complex<double>(original[i].x, original[i].y);
} }
OpenCLArray grid1(context, original.size(), sizeof(Real2), "grid1"); OpenCLArray grid1(context, original.size(), sizeof(Real2), "grid1");
OpenCLArray grid2(context, original.size(), sizeof(Real2), "grid2"); OpenCLArray grid2(context, original.size(), sizeof(Real2), "grid2");
...@@ -82,19 +86,21 @@ void testTransform(bool realToComplex, int xsize, int ysize, int zsize) { ...@@ -82,19 +86,21 @@ void testTransform(bool realToComplex, int xsize, int ysize, int zsize) {
fft.execFFT(grid1, grid2, true); fft.execFFT(grid1, grid2, true);
vector<Real2> result; vector<Real2> result;
grid2.download(result); grid2.download(result);
fftpack_t plan; vector<size_t> shape = {(size_t) xsize, (size_t) ysize, (size_t) zsize};
fftpack_init_3d(&plan, xsize, ysize, zsize); vector<size_t> axes = {0, 1, 2};
fftpack_exec_3d(plan, FFTPACK_FORWARD, &reference[0], &reference[0]); vector<ptrdiff_t> stride = {(ptrdiff_t) (ysize*zsize*sizeof(complex<double>)),
(ptrdiff_t) (zsize*sizeof(complex<double>)),
(ptrdiff_t) sizeof(complex<double>)};
pocketfft::c2c(shape, stride, stride, axes, true, reference.data(), reference.data(), 1.0);
int outputZSize = (realToComplex ? zsize/2+1 : zsize); int outputZSize = (realToComplex ? zsize/2+1 : zsize);
for (int x = 0; x < xsize; x++) for (int x = 0; x < xsize; x++)
for (int y = 0; y < ysize; y++) for (int y = 0; y < ysize; y++)
for (int z = 0; z < outputZSize; z++) { for (int z = 0; z < outputZSize; z++) {
int index1 = x*ysize*zsize + y*zsize + z; int index1 = x*ysize*zsize + y*zsize + z;
int index2 = x*ysize*outputZSize + y*outputZSize + z; int index2 = x*ysize*outputZSize + y*outputZSize + z;
ASSERT_EQUAL_TOL(reference[index1].re, result[index2].x, 1e-3); ASSERT_EQUAL_TOL(reference[index1].real(), result[index2].x, 1e-3);
ASSERT_EQUAL_TOL(reference[index1].im, result[index2].y, 1e-3); ASSERT_EQUAL_TOL(reference[index1].imag(), result[index2].y, 1e-3);
} }
fftpack_destroy(plan);
// Perform a backward transform and see if we get the original values. // Perform a backward transform and see if we get the original values.
......
/*
* This file contains a Fortran to C translation of the 1D transformations
* based on the original FFTPACK, written by paul n swarztrauber
* at the national center for atmospheric research and available
* at www.netlib.org. FFTPACK is in the public domain.
*
* Higher-dimension transforms written by Erik Lindahl, 2008-2009.
* Just as FFTPACK, this file may be redistributed freely, and can be
* considered to be in the public domain.
*
* Any errors in this (threadsafe, but not threaded) C version
* are probably due to the f2c translator, or hacks by Erik Lindahl,
* rather than FFTPACK. If you find a bug, it would be great if you could
* drop a line to lindahl@cbr.su.se and let me know about it!
*/
#ifndef _FFTPACK_H_
#define _FFTPACK_H_
#include <stdio.h>
#include "openmm/internal/windowsExport.h"
#ifdef __cplusplus
extern "C" {
#endif
#if 0
} /* fixes auto-indentation problems */
#endif
class t_complex {
public:
double re;
double im;
t_complex() : re(0.0), im(0.0) {
}
t_complex(double re, double im) : re(re), im(im) {
}
t_complex(const t_complex& c) : re(c.re), im(c.im) {
}
t_complex operator*(double r) {
return t_complex(re*r, im*r);
}
t_complex operator+(const t_complex& c) const {
return t_complex(re+c.re, im+c.im);
}
t_complex operator-(const t_complex& c) const {
return t_complex(re-c.re, im-c.im);
}
t_complex& operator+=(const t_complex& c) {
re += c.re;
im += c.im;
return *this;
}
t_complex& operator-=(const t_complex& c) {
re -= c.re;
im -= c.im;
return *this;
}
};
/*! \brief Datatype for FFT setup
*
* The fftpack_t type contains all the setup information, e.g. twiddle
* factors, necessary to perform an FFT. Internally it is mapped to
* whatever FFT library we are using, or the built-in FFTPACK if no fast
* external library is available.
*/
typedef struct fftpack *
fftpack_t;
/*! \brief Specifier for FFT direction.
*
* The definition of the 1D forward transform from input x[] to output y[] is
* \f[
* y_{k} = \sum_{j=0}^{N-1} x_{j} \exp{-i 2 \pi j k /N}
* \f]
*
* while the corresponding backward transform is
*
* \f[
* y_{k} = \sum_{j=0}^{N-1} x_{j} \exp{i 2 \pi j k /N}
* \f]
*
* A forward-backward transform pair will this result in data scaled by N.
*
*/
typedef enum fftpack_direction
{
FFTPACK_FORWARD, /*!< Forward complex-to-complex transform */
FFTPACK_BACKWARD, /*!< Backward complex-to-complex transform */
} fftpack_direction;
/*! \brief Setup a 1-dimensional complex-to-complex transform
*
* \param fft Pointer to opaque Gromacs FFT datatype
* \param nx Length of transform
*
* \return status - 0 or a standard error message.
*/
int
OPENMM_EXPORT
fftpack_init_1d (fftpack_t * fft,
int nx);
/*! \brief Setup a 2-dimensional complex-to-complex transform
*
* \param fft Pointer to opaque Gromacs FFT datatype
* \param nx Length of transform in first dimension
* \param ny Length of transform in second dimension
*
* \return status - 0 or a standard error message.
*
*/
int
OPENMM_EXPORT
fftpack_init_2d (fftpack_t * fft,
int nx,
int ny);
/*! \brief Setup a 3-dimensional complex-to-complex transform
*
* \param fft Pointer to opaque Gromacs FFT datatype
* \param nx Length of transform in first dimension
* \param ny Length of transform in second dimension
* \param nz Length of transform in third dimension
*
* \return status - 0 or a standard error message.
*
*/
int
OPENMM_EXPORT
fftpack_init_3d (fftpack_t * fft,
int nx,
int ny,
int nz);
/*! \brief Perform a 1-dimensional complex-to-complex transform
*
* Performs an instance of a transform previously initiated.
*
* \param setup Setup returned from fftpack_init_1d()
* \param dir Forward or Backward
* \param in_data Input grid data.
* \param out_data Output grid data.
* You can provide the same pointer for in_data and out_data
* to perform an in-place transform.
*
* \return 0 on success, or an error code.
*
* \note Data pointers are declared as void, to avoid casting pointers
* depending on your grid type.
*/
int
OPENMM_EXPORT
fftpack_exec_1d (fftpack_t setup,
enum fftpack_direction dir,
t_complex * in_data,
t_complex * out_data);
/*! \brief Perform a 2-dimensional complex-to-complex transform
*
* Performs an instance of a transform previously initiated.
*
* \param setup Setup returned from fftpack_init_1d()
* \param dir Forward or Backward
* \param in_data Input grid data.
* \param out_data Output grid data.
* You can provide the same pointer for in_data and out_data
* to perform an in-place transform.
*
* \return 0 on success, or an error code.
*
* \note Data pointers are declared as void, to avoid casting pointers
* depending on your grid type.
*/
int
OPENMM_EXPORT
fftpack_exec_2d (fftpack_t setup,
enum fftpack_direction dir,
t_complex * in_data,
t_complex * out_data);
/*! \brief Perform a 3-dimensional complex-to-complex transform
*
* Performs an instance of a transform previously initiated.
*
* \param setup Setup returned from fftpack_init_1d()
* \param dir Forward or Backward
* \param in_data Input grid data.
* \param out_data Output grid data.
* You can provide the same pointer for in_data and out_data
* to perform an in-place transform.
*
* \return 0 on success, or an error code.
*
* \note Data pointers are declared as void, to avoid casting pointers
* depending on your grid type.
*/
int
OPENMM_EXPORT
fftpack_exec_3d (fftpack_t setup,
enum fftpack_direction dir,
t_complex * in_data,
t_complex * out_data);
/*! \brief Release an FFT setup structure
*
* Destroy setup and release all allocated memory.
*
* \param setup Setup returned from fftpack_init_1d(), or one
* of the other initializers.
*
*/
void
OPENMM_EXPORT
fftpack_destroy (fftpack_t setup);
#ifdef __cplusplus
}
#endif
#endif /* _FFTPACK_H_ */
/* /*
* Reference implementation of PME reciprocal space interactions. * Reference implementation of PME reciprocal space interactions.
* *
* Copyright (c) 2009, Erik Lindahl, Rossen Apostolov, Szilard Pall * Copyright (c) 2009-2022, Erik Lindahl, Rossen Apostolov, Szilard Pall, Peter Eastman
* All rights reserved. * All rights reserved.
* Contact: lindahl@cbr.su.se Stockholm University, Sweden. * Contact: lindahl@cbr.su.se Stockholm University, Sweden.
* *
...@@ -32,12 +32,17 @@ ...@@ -32,12 +32,17 @@
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <complex>
#include "ReferencePME.h" #include "ReferencePME.h"
#include "fftpack.h"
#include "SimTKOpenMMRealType.h" #include "SimTKOpenMMRealType.h"
using std::vector; #ifdef _MSC_VER
#define POCKETFFT_NO_VECTORS
#endif
#include "pocketfft_hdronly.h"
using namespace std;
typedef int ivec[3]; typedef int ivec[3];
...@@ -48,12 +53,11 @@ struct pme ...@@ -48,12 +53,11 @@ struct pme
int natoms; int natoms;
double ewaldcoeff; double ewaldcoeff;
t_complex * grid; /* Memory for the grid we spread charges on. complex<double>* grid; /* Memory for the grid we spread charges on.
* Element (i,j,k) is accessed as: * Element (i,j,k) is accessed as:
* grid[i*ngrid[1]*ngrid[2] + j*ngrid[2] + k] * grid[i*ngrid[1]*ngrid[2] + j*ngrid[2] + k]
*/ */
int ngrid[3]; /* Total grid dimensions (all data is complex!) */ int ngrid[3]; /* Total grid dimensions (all data is complex!) */
fftpack_t fftplan; /* Handle to fourier transform setup */
int order; /* PME interpolation order. Almost always 4 */ int order; /* PME interpolation order. Almost always 4 */
...@@ -346,7 +350,7 @@ pme_grid_spread_charge(pme_t pme, const vector<double>& charges) ...@@ -346,7 +350,7 @@ pme_grid_spread_charge(pme_t pme, const vector<double>& charges)
/* Reset the grid */ /* Reset the grid */
for (i=0;i<pme->ngrid[0]*pme->ngrid[1]*pme->ngrid[2];i++) for (i=0;i<pme->ngrid[0]*pme->ngrid[1]*pme->ngrid[2];i++)
{ {
pme->grid[i].re = pme->grid[i].im = 0; pme->grid[i] = complex<double>(0, 0);
} }
for (i=0;i<pme->natoms;i++) for (i=0;i<pme->natoms;i++)
...@@ -393,11 +397,11 @@ pme_grid_spread_charge(pme_t pme, const vector<double>& charges) ...@@ -393,11 +397,11 @@ pme_grid_spread_charge(pme_t pme, const vector<double>& charges)
for (iz=0;iz<order;iz++) for (iz=0;iz<order;iz++)
{ {
/* Can be optimized, but we keep it simple here */ /* Can be optimized, but we keep it simple here */
zindex = (z0index + iz) % pme->ngrid[2]; zindex = (z0index + iz) % pme->ngrid[2];
/* Calculate index in the charge grid */ /* Calculate index in the charge grid */
index = xindex*pme->ngrid[1]*pme->ngrid[2] + yindex*pme->ngrid[2] + zindex; index = xindex*pme->ngrid[1]*pme->ngrid[2] + yindex*pme->ngrid[2] + zindex;
/* Add the charge times the bspline spread/interpolation factors to this grid position */ /* Add the charge times the bspline spread/interpolation factors to this grid position */
pme->grid[index].re += q*thetax[ix]*thetay[iy]*thetaz[iz]; pme->grid[index] += q*thetax[ix]*thetay[iy]*thetaz[iz];
} }
} }
} }
...@@ -427,7 +431,7 @@ pme_reciprocal_convolution(pme_t pme, ...@@ -427,7 +431,7 @@ pme_reciprocal_convolution(pme_t pme,
double boxfactor; double boxfactor;
double maxkx,maxky,maxkz; double maxkx,maxky,maxkz;
t_complex *ptr; complex<double> *ptr;
nx = pme->ngrid[0]; nx = pme->ngrid[0];
ny = pme->ngrid[1]; ny = pme->ngrid[1];
...@@ -486,8 +490,8 @@ pme_reciprocal_convolution(pme_t pme, ...@@ -486,8 +490,8 @@ pme_reciprocal_convolution(pme_t pme,
ptr = pme->grid + kx*ny*nz + ky*nz + kz; ptr = pme->grid + kx*ny*nz + ky*nz + kz;
/* Get grid data for this frequency */ /* Get grid data for this frequency */
d1 = ptr->re; d1 = ptr->real();
d2 = ptr->im; d2 = ptr->imag();
/* Calculate the convolution - see the Essman/Darden paper for the equation! */ /* Calculate the convolution - see the Essman/Darden paper for the equation! */
m2 = mhx*mhx+mhy*mhy+mhz*mhz; m2 = mhx*mhx+mhy*mhy+mhz*mhz;
...@@ -497,8 +501,8 @@ pme_reciprocal_convolution(pme_t pme, ...@@ -497,8 +501,8 @@ pme_reciprocal_convolution(pme_t pme,
eterm = one_4pi_eps*exp(-factor*m2)/denom; eterm = one_4pi_eps*exp(-factor*m2)/denom;
/* write back convolution data to grid */ /* write back convolution data to grid */
ptr->re = d1*eterm; ptr->real(d1*eterm);
ptr->im = d2*eterm; ptr->imag(d2*eterm);
struct2 = (d1*d1+d2*d2); struct2 = (d1*d1+d2*d2);
...@@ -532,7 +536,7 @@ dpme_reciprocal_convolution(pme_t pme, ...@@ -532,7 +536,7 @@ dpme_reciprocal_convolution(pme_t pme,
double boxfactor; double boxfactor;
double maxkx,maxky,maxkz; double maxkx,maxky,maxkz;
t_complex *ptr; complex<double> *ptr;
nx = pme->ngrid[0]; nx = pme->ngrid[0];
ny = pme->ngrid[1]; ny = pme->ngrid[1];
...@@ -580,8 +584,8 @@ dpme_reciprocal_convolution(pme_t pme, ...@@ -580,8 +584,8 @@ dpme_reciprocal_convolution(pme_t pme,
ptr = pme->grid + kx*ny*nz + ky*nz + kz; ptr = pme->grid + kx*ny*nz + ky*nz + kz;
/* Get grid data for this frequency */ /* Get grid data for this frequency */
d1 = ptr->re; d1 = ptr->real();
d2 = ptr->im; d2 = ptr->imag();
/* Calculate the convolution - see the Essman/Darden paper for the equation! */ /* Calculate the convolution - see the Essman/Darden paper for the equation! */
m2 = mhx*mhx+mhy*mhy+mhz*mhz; m2 = mhx*mhx+mhy*mhy+mhz*mhz;
...@@ -598,8 +602,8 @@ dpme_reciprocal_convolution(pme_t pme, ...@@ -598,8 +602,8 @@ dpme_reciprocal_convolution(pme_t pme,
eterm = (fac1*erfcterm*m3 + expterm*(fac2 + fac3*m2)) * denom; eterm = (fac1*erfcterm*m3 + expterm*(fac2 + fac3*m2)) * denom;
/* write back convolution data to grid */ /* write back convolution data to grid */
ptr->re = d1*eterm; ptr->real(d1*eterm);
ptr->im = d2*eterm; ptr->imag(d2*eterm);
struct2 = (d1*d1+d2*d2); struct2 = (d1*d1+d2*d2);
...@@ -696,7 +700,7 @@ pme_grid_interpolate_force(pme_t pme, ...@@ -696,7 +700,7 @@ pme_grid_interpolate_force(pme_t pme,
/* Get the fft+convoluted+ifft:d data from the grid, which must be real by definition */ /* Get the fft+convoluted+ifft:d data from the grid, which must be real by definition */
/* Checking that the imaginary part is indeed zero might be a good check :-) */ /* Checking that the imaginary part is indeed zero might be a good check :-) */
gridvalue = pme->grid[index].re; gridvalue = pme->grid[index].real();
/* The d component of the force is calculated by taking the derived bspline in dimension d, normal bsplines in the other two */ /* The d component of the force is calculated by taking the derived bspline in dimension d, normal bsplines in the other two */
fx += dtx*ty*tz*gridvalue; fx += dtx*ty*tz*gridvalue;
...@@ -745,9 +749,7 @@ pme_init(pme_t * ppme, ...@@ -745,9 +749,7 @@ pme_init(pme_t * ppme,
pme->particleindex = (ivec *)malloc(sizeof(ivec)*natoms); pme->particleindex = (ivec *)malloc(sizeof(ivec)*natoms);
/* Allocate charge grid storage */ /* Allocate charge grid storage */
pme->grid = (t_complex *)malloc(sizeof(t_complex)*ngrid[0]*ngrid[1]*ngrid[2]); pme->grid = (complex<double> *)malloc(sizeof(complex<double>)*ngrid[0]*ngrid[1]*ngrid[2]);
fftpack_init_3d(&pme->fftplan,ngrid[0],ngrid[1],ngrid[2]);
/* Setup bspline moduli (see Essman paper) */ /* Setup bspline moduli (see Essman paper) */
pme_calculate_bsplines_moduli(pme); pme_calculate_bsplines_moduli(pme);
...@@ -790,13 +792,18 @@ int pme_exec(pme_t pme, ...@@ -790,13 +792,18 @@ int pme_exec(pme_t pme,
pme_grid_spread_charge(pme, charges); pme_grid_spread_charge(pme, charges);
/* do 3d-fft */ /* do 3d-fft */
fftpack_exec_3d(pme->fftplan,FFTPACK_FORWARD,pme->grid,pme->grid); vector<size_t> shape = {(size_t) pme->ngrid[0], (size_t) pme->ngrid[1], (size_t) pme->ngrid[2]};
vector<size_t> axes = {0, 1, 2};
vector<ptrdiff_t> stride = {(ptrdiff_t) (pme->ngrid[1]*pme->ngrid[2]*sizeof(complex<double>)),
(ptrdiff_t) (pme->ngrid[2]*sizeof(complex<double>)),
(ptrdiff_t) sizeof(complex<double>)};
pocketfft::c2c(shape, stride, stride, axes, true, pme->grid, pme->grid, 1.0, 0);
/* solve in k-space */ /* solve in k-space */
pme_reciprocal_convolution(pme,periodicBoxVectors,recipBoxVectors,energy); pme_reciprocal_convolution(pme,periodicBoxVectors,recipBoxVectors,energy);
/* do 3d-invfft */ /* do 3d-invfft */
fftpack_exec_3d(pme->fftplan,FFTPACK_BACKWARD,pme->grid,pme->grid); pocketfft::c2c(shape, stride, stride, axes, false, pme->grid, pme->grid, 1.0, 0);
/* Get the particle forces from the grid and bsplines in the pme structure */ /* Get the particle forces from the grid and bsplines in the pme structure */
pme_grid_interpolate_force(pme,recipBoxVectors,charges,forces); pme_grid_interpolate_force(pme,recipBoxVectors,charges,forces);
...@@ -834,13 +841,18 @@ int pme_exec_dpme(pme_t pme, ...@@ -834,13 +841,18 @@ int pme_exec_dpme(pme_t pme,
pme_grid_spread_charge(pme, c6s); pme_grid_spread_charge(pme, c6s);
/* do 3d-fft */ /* do 3d-fft */
fftpack_exec_3d(pme->fftplan,FFTPACK_FORWARD,pme->grid,pme->grid); vector<size_t> shape = {(size_t) pme->ngrid[0], (size_t) pme->ngrid[1], (size_t) pme->ngrid[2]};
vector<size_t> axes = {0, 1, 2};
vector<ptrdiff_t> stride = {(ptrdiff_t) (pme->ngrid[1]*pme->ngrid[2]*sizeof(complex<double>)),
(ptrdiff_t) (pme->ngrid[2]*sizeof(complex<double>)),
(ptrdiff_t) sizeof(complex<double>)};
pocketfft::c2c(shape, stride, stride, axes, true, pme->grid, pme->grid, 1.0, 0);
/* solve in k-space */ /* solve in k-space */
dpme_reciprocal_convolution(pme,periodicBoxVectors,recipBoxVectors,energy); dpme_reciprocal_convolution(pme,periodicBoxVectors,recipBoxVectors,energy);
/* do 3d-invfft */ /* do 3d-invfft */
fftpack_exec_3d(pme->fftplan,FFTPACK_BACKWARD,pme->grid,pme->grid); pocketfft::c2c(shape, stride, stride, axes, false, pme->grid, pme->grid, 1.0, 0);
/* Get the particle forces from the grid and bsplines in the pme structure */ /* Get the particle forces from the grid and bsplines in the pme structure */
pme_grid_interpolate_force(pme,recipBoxVectors,c6s,forces); pme_grid_interpolate_force(pme,recipBoxVectors,c6s,forces);
...@@ -866,8 +878,6 @@ pme_destroy(pme_t pme) ...@@ -866,8 +878,6 @@ pme_destroy(pme_t pme)
free(pme->particlefraction); free(pme->particlefraction);
free(pme->particleindex); free(pme->particleindex);
fftpack_destroy(pme->fftplan);
/* destroy structure itself */ /* destroy structure itself */
free(pme); free(pme);
......
This diff is collapsed.
/* Portions copyright (c) 2006-2019 Stanford University and Simbios. /* Portions copyright (c) 2006-2022 Stanford University and Simbios.
* Contributors: Pande Group * Contributors: Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include "SimTKOpenMMRealType.h" #include "SimTKOpenMMRealType.h"
#include "jama_svd.h" #include "jama_svd.h"
#include <algorithm> #include <algorithm>
#ifdef _MSC_VER
#define POCKETFFT_NO_VECTORS
#endif
#include "pocketfft_hdronly.h"
// In case we're using some primitive version of Visual Studio this will // In case we're using some primitive version of Visual Studio this will
// make sure that erf() and erfc() are defined. // make sure that erf() and erfc() are defined.
...@@ -1396,7 +1400,6 @@ const double AmoebaReferencePmeHippoNonbondedForce::SQRT_PI = sqrt(M_PI); ...@@ -1396,7 +1400,6 @@ const double AmoebaReferencePmeHippoNonbondedForce::SQRT_PI = sqrt(M_PI);
AmoebaReferencePmeHippoNonbondedForce::AmoebaReferencePmeHippoNonbondedForce(const HippoNonbondedForce& force, const System& system) : AmoebaReferencePmeHippoNonbondedForce::AmoebaReferencePmeHippoNonbondedForce(const HippoNonbondedForce& force, const System& system) :
AmoebaReferenceHippoNonbondedForce(force) { AmoebaReferenceHippoNonbondedForce(force) {
_fftplan = NULL;
force.getPMEParameters(_alphaEwald, _pmeGridDimensions[0], _pmeGridDimensions[1], _pmeGridDimensions[2]); force.getPMEParameters(_alphaEwald, _pmeGridDimensions[0], _pmeGridDimensions[1], _pmeGridDimensions[2]);
force.getDPMEParameters(_dalphaEwald, _dpmeGridDimensions[0], _dpmeGridDimensions[1], _dpmeGridDimensions[2]); force.getDPMEParameters(_dalphaEwald, _dpmeGridDimensions[0], _dpmeGridDimensions[1], _dpmeGridDimensions[2]);
if (_alphaEwald == 0.0 || _dalphaEwald == 0.0) { if (_alphaEwald == 0.0 || _dalphaEwald == 0.0) {
...@@ -1408,15 +1411,9 @@ AmoebaReferencePmeHippoNonbondedForce::AmoebaReferencePmeHippoNonbondedForce(con ...@@ -1408,15 +1411,9 @@ AmoebaReferencePmeHippoNonbondedForce::AmoebaReferencePmeHippoNonbondedForce(con
if (_dalphaEwald == 0.0) if (_dalphaEwald == 0.0)
NonbondedForceImpl::calcPMEParameters(system, nb, _dalphaEwald, _dpmeGridDimensions[0], _dpmeGridDimensions[1], _dpmeGridDimensions[2], true); NonbondedForceImpl::calcPMEParameters(system, nb, _dalphaEwald, _dpmeGridDimensions[0], _dpmeGridDimensions[1], _dpmeGridDimensions[2], true);
} }
fftpack_init_3d(&_fftplan, _pmeGridDimensions[0], _pmeGridDimensions[1], _pmeGridDimensions[2]);
initializeBSplineModuli(); initializeBSplineModuli();
} }
AmoebaReferencePmeHippoNonbondedForce::~AmoebaReferencePmeHippoNonbondedForce() {
if (_fftplan != NULL)
fftpack_destroy(_fftplan);
};
double AmoebaReferencePmeHippoNonbondedForce::getCutoffDistance() const { double AmoebaReferencePmeHippoNonbondedForce::getCutoffDistance() const {
return _cutoffDistance; return _cutoffDistance;
}; };
...@@ -1451,11 +1448,6 @@ void AmoebaReferencePmeHippoNonbondedForce::setPmeGridDimensions(vector<int>& pm ...@@ -1451,11 +1448,6 @@ void AmoebaReferencePmeHippoNonbondedForce::setPmeGridDimensions(vector<int>& pm
(pmeGridDimensions[2] == _pmeGridDimensions[2])) (pmeGridDimensions[2] == _pmeGridDimensions[2]))
return; return;
if (_fftplan) {
fftpack_destroy(_fftplan);
}
fftpack_init_3d(&_fftplan,pmeGridDimensions[0], pmeGridDimensions[1], pmeGridDimensions[2]);
_pmeGridDimensions[0] = pmeGridDimensions[0]; _pmeGridDimensions[0] = pmeGridDimensions[0];
_pmeGridDimensions[1] = pmeGridDimensions[1]; _pmeGridDimensions[1] = pmeGridDimensions[1];
_pmeGridDimensions[2] = pmeGridDimensions[2]; _pmeGridDimensions[2] = pmeGridDimensions[2];
...@@ -1469,11 +1461,6 @@ void AmoebaReferencePmeHippoNonbondedForce::setDispersionPmeGridDimensions(vecto ...@@ -1469,11 +1461,6 @@ void AmoebaReferencePmeHippoNonbondedForce::setDispersionPmeGridDimensions(vecto
(pmeGridDimensions[2] == _dpmeGridDimensions[2])) (pmeGridDimensions[2] == _dpmeGridDimensions[2]))
return; return;
if (_fftplan) {
fftpack_destroy(_fftplan);
}
fftpack_init_3d(&_fftplan,pmeGridDimensions[0], pmeGridDimensions[1], pmeGridDimensions[2]);
_dpmeGridDimensions[0] = pmeGridDimensions[0]; _dpmeGridDimensions[0] = pmeGridDimensions[0];
_dpmeGridDimensions[1] = pmeGridDimensions[1]; _dpmeGridDimensions[1] = pmeGridDimensions[1];
_dpmeGridDimensions[2] = pmeGridDimensions[2]; _dpmeGridDimensions[2] = pmeGridDimensions[2];
...@@ -1516,7 +1503,7 @@ void AmoebaReferencePmeHippoNonbondedForce::resizePmeArrays() { ...@@ -1516,7 +1503,7 @@ void AmoebaReferencePmeHippoNonbondedForce::resizePmeArrays() {
void AmoebaReferencePmeHippoNonbondedForce::initializePmeGrid() { void AmoebaReferencePmeHippoNonbondedForce::initializePmeGrid() {
for (int jj = 0; jj < _pmeGrid.size(); jj++) for (int jj = 0; jj < _pmeGrid.size(); jj++)
_pmeGrid[jj].re = _pmeGrid[jj].im = 0.0; _pmeGrid[jj] = complex<double>(0, 0);
} }
void AmoebaReferencePmeHippoNonbondedForce::getPeriodicDelta(Vec3& deltaR) const { void AmoebaReferencePmeHippoNonbondedForce::getPeriodicDelta(Vec3& deltaR) const {
...@@ -1674,9 +1661,14 @@ void AmoebaReferencePmeHippoNonbondedForce::calculateFixedMultipoleField() { ...@@ -1674,9 +1661,14 @@ void AmoebaReferencePmeHippoNonbondedForce::calculateFixedMultipoleField() {
computeAmoebaBsplines(particleData); computeAmoebaBsplines(particleData);
initializePmeGrid(); initializePmeGrid();
spreadFixedMultipolesOntoGrid(particleData); spreadFixedMultipolesOntoGrid(particleData);
fftpack_exec_3d(_fftplan, FFTPACK_FORWARD, _pmeGrid.data(), _pmeGrid.data()); vector<size_t> shape = {(size_t) _pmeGridDimensions[0], (size_t) _pmeGridDimensions[1], (size_t) _pmeGridDimensions[2]};
vector<size_t> axes = {0, 1, 2};
vector<ptrdiff_t> stride = {(ptrdiff_t) (_pmeGridDimensions[1]*_pmeGridDimensions[2]*sizeof(complex<double>)),
(ptrdiff_t) (_pmeGridDimensions[2]*sizeof(complex<double>)),
(ptrdiff_t) sizeof(complex<double>)};
pocketfft::c2c(shape, stride, stride, axes, true, _pmeGrid.data(), _pmeGrid.data(), 1.0, 0);
performAmoebaReciprocalConvolution(); performAmoebaReciprocalConvolution();
fftpack_exec_3d(_fftplan, FFTPACK_BACKWARD, _pmeGrid.data(), _pmeGrid.data()); pocketfft::c2c(shape, stride, stride, axes, false, _pmeGrid.data(), _pmeGrid.data(), 1.0, 0);
computeFixedPotentialFromGrid(); computeFixedPotentialFromGrid();
recordFixedMultipoleField(); recordFixedMultipoleField();
...@@ -1875,7 +1867,7 @@ void AmoebaReferencePmeHippoNonbondedForce::spreadFixedMultipolesOntoGrid(const ...@@ -1875,7 +1867,7 @@ void AmoebaReferencePmeHippoNonbondedForce::spreadFixedMultipolesOntoGrid(const
// Clear the grid. // Clear the grid.
for (int gridIndex = 0; gridIndex < _pmeGrid.size(); gridIndex++) for (int gridIndex = 0; gridIndex < _pmeGrid.size(); gridIndex++)
_pmeGrid[gridIndex] = t_complex(0, 0); _pmeGrid[gridIndex] = complex<double>(0, 0);
// Loop over atoms and spread them on the grid. // Loop over atoms and spread them on the grid.
...@@ -1904,8 +1896,8 @@ void AmoebaReferencePmeHippoNonbondedForce::spreadFixedMultipolesOntoGrid(const ...@@ -1904,8 +1896,8 @@ void AmoebaReferencePmeHippoNonbondedForce::spreadFixedMultipolesOntoGrid(const
for (int iz = 0; iz < AMOEBA_PME_ORDER; iz++) { for (int iz = 0; iz < AMOEBA_PME_ORDER; iz++) {
int z = (gridPoint[2]+iz) % _pmeGridDimensions[2]; int z = (gridPoint[2]+iz) % _pmeGridDimensions[2];
HippoDouble4 v = _thetai[2][atomIndex*AMOEBA_PME_ORDER+iz]; HippoDouble4 v = _thetai[2][atomIndex*AMOEBA_PME_ORDER+iz];
t_complex& gridValue = _pmeGrid[x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z]; complex<double>& gridValue = _pmeGrid[x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z];
gridValue.re += term0*v[0] + term1*v[1] + term2*v[2]; gridValue += term0*v[0] + term1*v[1] + term2*v[2];
} }
} }
} }
...@@ -1923,7 +1915,7 @@ void AmoebaReferencePmeHippoNonbondedForce::performAmoebaReciprocalConvolution() ...@@ -1923,7 +1915,7 @@ void AmoebaReferencePmeHippoNonbondedForce::performAmoebaReciprocalConvolution()
int kz = remainder-ky*_pmeGridDimensions[2]; int kz = remainder-ky*_pmeGridDimensions[2];
if (kx == 0 && ky == 0 && kz == 0) { if (kx == 0 && ky == 0 && kz == 0) {
_pmeGrid[index].re = _pmeGrid[index].im = 0.0; _pmeGrid[index] = complex<double>(0, 0);
continue; continue;
} }
...@@ -1943,8 +1935,7 @@ void AmoebaReferencePmeHippoNonbondedForce::performAmoebaReciprocalConvolution() ...@@ -1943,8 +1935,7 @@ void AmoebaReferencePmeHippoNonbondedForce::performAmoebaReciprocalConvolution()
double denom = m2*bx*by*bz; double denom = m2*bx*by*bz;
double eterm = scaleFactor*exp(-expFactor*m2)/denom; double eterm = scaleFactor*exp(-expFactor*m2)/denom;
_pmeGrid[index].re *= eterm; _pmeGrid[index] *= eterm;
_pmeGrid[index].im *= eterm;
} }
} }
...@@ -1993,7 +1984,7 @@ void AmoebaReferencePmeHippoNonbondedForce::computeFixedPotentialFromGrid() { ...@@ -1993,7 +1984,7 @@ void AmoebaReferencePmeHippoNonbondedForce::computeFixedPotentialFromGrid() {
for (int ix = 0; ix < AMOEBA_PME_ORDER; ix++) { for (int ix = 0; ix < AMOEBA_PME_ORDER; ix++) {
int i = gridPoint[0]+ix-(gridPoint[0]+ix >= _pmeGridDimensions[0] ? _pmeGridDimensions[0] : 0); int i = gridPoint[0]+ix-(gridPoint[0]+ix >= _pmeGridDimensions[0] ? _pmeGridDimensions[0] : 0);
int gridIndex = i*_pmeGridDimensions[1]*_pmeGridDimensions[2] + j*_pmeGridDimensions[2] + k; int gridIndex = i*_pmeGridDimensions[1]*_pmeGridDimensions[2] + j*_pmeGridDimensions[2] + k;
double tq = _pmeGrid[gridIndex].re; double tq = _pmeGrid[gridIndex].real();
HippoDouble4 tadd = _thetai[0][m*AMOEBA_PME_ORDER+ix]; HippoDouble4 tadd = _thetai[0][m*AMOEBA_PME_ORDER+ix];
t[0] += tq*tadd[0]; t[0] += tq*tadd[0];
t[1] += tq*tadd[1]; t[1] += tq*tadd[1];
...@@ -2066,7 +2057,7 @@ void AmoebaReferencePmeHippoNonbondedForce::spreadInducedDipolesOnGrid(const vec ...@@ -2066,7 +2057,7 @@ void AmoebaReferencePmeHippoNonbondedForce::spreadInducedDipolesOnGrid(const vec
// Clear the grid. // Clear the grid.
for (int gridIndex = 0; gridIndex < _pmeGrid.size(); gridIndex++) for (int gridIndex = 0; gridIndex < _pmeGrid.size(); gridIndex++)
_pmeGrid[gridIndex] = t_complex(0, 0); _pmeGrid[gridIndex] = complex<double>(0, 0);
// Loop over atoms and spread them on the grid. // Loop over atoms and spread them on the grid.
...@@ -2086,8 +2077,8 @@ void AmoebaReferencePmeHippoNonbondedForce::spreadInducedDipolesOnGrid(const vec ...@@ -2086,8 +2077,8 @@ void AmoebaReferencePmeHippoNonbondedForce::spreadInducedDipolesOnGrid(const vec
for (int iz = 0; iz < AMOEBA_PME_ORDER; iz++) { for (int iz = 0; iz < AMOEBA_PME_ORDER; iz++) {
int z = (gridPoint[2]+iz) % _pmeGridDimensions[2]; int z = (gridPoint[2]+iz) % _pmeGridDimensions[2];
HippoDouble4 v = _thetai[2][atomIndex*AMOEBA_PME_ORDER+iz]; HippoDouble4 v = _thetai[2][atomIndex*AMOEBA_PME_ORDER+iz];
t_complex& gridValue = _pmeGrid[x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z]; complex<double>& gridValue = _pmeGrid[x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z];
gridValue.re += term01*v[0] + term11*v[1]; gridValue += term01*v[0] + term11*v[1];
} }
} }
} }
...@@ -2142,12 +2133,12 @@ void AmoebaReferencePmeHippoNonbondedForce::computeInducedPotentialFromGrid() { ...@@ -2142,12 +2133,12 @@ void AmoebaReferencePmeHippoNonbondedForce::computeInducedPotentialFromGrid() {
for (int ix = 0; ix < AMOEBA_PME_ORDER; ix++) { for (int ix = 0; ix < AMOEBA_PME_ORDER; ix++) {
int i = gridPoint[0]+ix-(gridPoint[0]+ix >= _pmeGridDimensions[0] ? _pmeGridDimensions[0] : 0); int i = gridPoint[0]+ix-(gridPoint[0]+ix >= _pmeGridDimensions[0] ? _pmeGridDimensions[0] : 0);
int gridIndex = i*_pmeGridDimensions[1]*_pmeGridDimensions[2] + j*_pmeGridDimensions[2] + k; int gridIndex = i*_pmeGridDimensions[1]*_pmeGridDimensions[2] + j*_pmeGridDimensions[2] + k;
t_complex tq = _pmeGrid[gridIndex]; complex<double> tq = _pmeGrid[gridIndex];
HippoDouble4 tadd = _thetai[0][m*AMOEBA_PME_ORDER+ix]; HippoDouble4 tadd = _thetai[0][m*AMOEBA_PME_ORDER+ix];
t0 += tq.re*tadd[0]; t0 += tq.real()*tadd[0];
t1 += tq.re*tadd[1]; t1 += tq.real()*tadd[1];
t2 += tq.re*tadd[2]; t2 += tq.real()*tadd[2];
t3 += tq.re*tadd[3]; t3 += tq.real()*tadd[3];
} }
tu00 += t0*u[0]; tu00 += t0*u[0];
tu10 += t1*u[0]; tu10 += t1*u[0];
...@@ -2412,9 +2403,14 @@ void AmoebaReferencePmeHippoNonbondedForce::calculateReciprocalSpaceInducedDipol ...@@ -2412,9 +2403,14 @@ void AmoebaReferencePmeHippoNonbondedForce::calculateReciprocalSpaceInducedDipol
initializePmeGrid(); initializePmeGrid();
spreadInducedDipolesOnGrid(_inducedDipole); spreadInducedDipolesOnGrid(_inducedDipole);
fftpack_exec_3d(_fftplan, FFTPACK_FORWARD, _pmeGrid.data(), _pmeGrid.data()); vector<size_t> shape = {(size_t) _pmeGridDimensions[0], (size_t) _pmeGridDimensions[1], (size_t) _pmeGridDimensions[2]};
vector<size_t> axes = {0, 1, 2};
vector<ptrdiff_t> stride = {(ptrdiff_t) (_pmeGridDimensions[1]*_pmeGridDimensions[2]*sizeof(complex<double>)),
(ptrdiff_t) (_pmeGridDimensions[2]*sizeof(complex<double>)),
(ptrdiff_t) sizeof(complex<double>)};
pocketfft::c2c(shape, stride, stride, axes, true, _pmeGrid.data(), _pmeGrid.data(), 1.0, 0);
performAmoebaReciprocalConvolution(); performAmoebaReciprocalConvolution();
fftpack_exec_3d(_fftplan, FFTPACK_BACKWARD, _pmeGrid.data(), _pmeGrid.data()); pocketfft::c2c(shape, stride, stride, axes, false, _pmeGrid.data(), _pmeGrid.data(), 1.0, 0);
computeInducedPotentialFromGrid(); computeInducedPotentialFromGrid();
recordInducedDipoleField(_inducedDipoleField); recordInducedDipoleField(_inducedDipoleField);
} }
......
/* Portions copyright (c) 2006-2019 Stanford University and Simbios. /* Portions copyright (c) 2006-2022 Stanford University and Simbios.
* Contributors: Pande Group * Contributors: Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include <map> #include <map>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "fftpack.h"
#include <complex> #include <complex>
namespace OpenMM { namespace OpenMM {
...@@ -109,12 +108,6 @@ public: ...@@ -109,12 +108,6 @@ public:
* *
*/ */
AmoebaReferenceHippoNonbondedForce(const HippoNonbondedForce& force); AmoebaReferenceHippoNonbondedForce(const HippoNonbondedForce& force);
/**
* Destructor
*
*/
virtual ~AmoebaReferenceHippoNonbondedForce() {};
/** /**
* Get nonbonded method. * Get nonbonded method.
...@@ -655,9 +648,7 @@ private: ...@@ -655,9 +648,7 @@ private:
int _pmeGridDimensions[3]; int _pmeGridDimensions[3];
int _dpmeGridDimensions[3]; int _dpmeGridDimensions[3];
fftpack_t _fftplan; std::vector<std::complex<double> > _pmeGrid;
std::vector<t_complex> _pmeGrid;
std::vector<double> _pmeBsplineModuli[3]; std::vector<double> _pmeBsplineModuli[3];
std::vector<HippoDouble4> _thetai[3]; std::vector<HippoDouble4> _thetai[3];
......
/* Portions copyright (c) 2006-2015 Stanford University and Simbios. /* Portions copyright (c) 2006-222 Stanford University and Simbios.
* Contributors: Pande Group * Contributors: Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -26,6 +26,10 @@ ...@@ -26,6 +26,10 @@
#include "SimTKOpenMMRealType.h" #include "SimTKOpenMMRealType.h"
#include "jama_svd.h" #include "jama_svd.h"
#include <algorithm> #include <algorithm>
#ifdef _MSC_VER
#define POCKETFFT_NO_VECTORS
#endif
#include "pocketfft_hdronly.h"
// In case we're using some primitive version of Visual Studio this will // In case we're using some primitive version of Visual Studio this will
// make sure that erf() and erfc() are defined. // make sure that erf() and erfc() are defined.
...@@ -4809,16 +4813,12 @@ AmoebaReferencePmeMultipoleForce::AmoebaReferencePmeMultipoleForce() : ...@@ -4809,16 +4813,12 @@ AmoebaReferencePmeMultipoleForce::AmoebaReferencePmeMultipoleForce() :
_pmeGridSize(0), _totalGridSize(0), _alphaEwald(0.0) _pmeGridSize(0), _totalGridSize(0), _alphaEwald(0.0)
{ {
_fftplan = NULL;
_pmeGrid = NULL; _pmeGrid = NULL;
_pmeGridDimensions = IntVec(-1, -1, -1); _pmeGridDimensions = IntVec(-1, -1, -1);
} }
AmoebaReferencePmeMultipoleForce::~AmoebaReferencePmeMultipoleForce() AmoebaReferencePmeMultipoleForce::~AmoebaReferencePmeMultipoleForce()
{ {
if (_fftplan) {
fftpack_destroy(_fftplan);
}
if (_pmeGrid) { if (_pmeGrid) {
delete[] _pmeGrid; delete[] _pmeGrid;
} }
...@@ -4863,11 +4863,6 @@ void AmoebaReferencePmeMultipoleForce::setPmeGridDimensions(vector<int>& pmeGrid ...@@ -4863,11 +4863,6 @@ void AmoebaReferencePmeMultipoleForce::setPmeGridDimensions(vector<int>& pmeGrid
(pmeGridDimensions[2] == _pmeGridDimensions[2])) (pmeGridDimensions[2] == _pmeGridDimensions[2]))
return; return;
if (_fftplan) {
fftpack_destroy(_fftplan);
}
fftpack_init_3d(&_fftplan,pmeGridDimensions[0], pmeGridDimensions[1], pmeGridDimensions[2]);
_pmeGridDimensions[0] = pmeGridDimensions[0]; _pmeGridDimensions[0] = pmeGridDimensions[0];
_pmeGridDimensions[1] = pmeGridDimensions[1]; _pmeGridDimensions[1] = pmeGridDimensions[1];
_pmeGridDimensions[2] = pmeGridDimensions[2]; _pmeGridDimensions[2] = pmeGridDimensions[2];
...@@ -4908,7 +4903,7 @@ void AmoebaReferencePmeMultipoleForce::resizePmeArrays() ...@@ -4908,7 +4903,7 @@ void AmoebaReferencePmeMultipoleForce::resizePmeArrays()
if (_pmeGrid) { if (_pmeGrid) {
delete[] _pmeGrid; delete[] _pmeGrid;
} }
_pmeGrid = new t_complex[_totalGridSize]; _pmeGrid = new complex<double>[_totalGridSize];
_pmeGridSize = _totalGridSize; _pmeGridSize = _totalGridSize;
} }
...@@ -4930,7 +4925,7 @@ void AmoebaReferencePmeMultipoleForce::initializePmeGrid() ...@@ -4930,7 +4925,7 @@ void AmoebaReferencePmeMultipoleForce::initializePmeGrid()
return; return;
for (int jj = 0; jj < _totalGridSize; jj++) for (int jj = 0; jj < _totalGridSize; jj++)
_pmeGrid[jj].re = _pmeGrid[jj].im = 0.0; _pmeGrid[jj] = complex<double>(0, 0);
} }
void AmoebaReferencePmeMultipoleForce::getPeriodicDelta(Vec3& deltaR) const void AmoebaReferencePmeMultipoleForce::getPeriodicDelta(Vec3& deltaR) const
...@@ -5175,9 +5170,14 @@ void AmoebaReferencePmeMultipoleForce::calculateFixedMultipoleField(const vector ...@@ -5175,9 +5170,14 @@ void AmoebaReferencePmeMultipoleForce::calculateFixedMultipoleField(const vector
computeAmoebaBsplines(particleData); computeAmoebaBsplines(particleData);
initializePmeGrid(); initializePmeGrid();
spreadFixedMultipolesOntoGrid(particleData); spreadFixedMultipolesOntoGrid(particleData);
fftpack_exec_3d(_fftplan, FFTPACK_FORWARD, _pmeGrid, _pmeGrid); vector<size_t> shape = {(size_t) _pmeGridDimensions[0], (size_t) _pmeGridDimensions[1], (size_t) _pmeGridDimensions[2]};
vector<size_t> axes = {0, 1, 2};
vector<ptrdiff_t> stride = {(ptrdiff_t) (_pmeGridDimensions[1]*_pmeGridDimensions[2]*sizeof(complex<double>)),
(ptrdiff_t) (_pmeGridDimensions[2]*sizeof(complex<double>)),
(ptrdiff_t) sizeof(complex<double>)};
pocketfft::c2c(shape, stride, stride, axes, true, _pmeGrid, _pmeGrid, 1.0, 0);
performAmoebaReciprocalConvolution(); performAmoebaReciprocalConvolution();
fftpack_exec_3d(_fftplan, FFTPACK_BACKWARD, _pmeGrid, _pmeGrid); pocketfft::c2c(shape, stride, stride, axes, false, _pmeGrid, _pmeGrid, 1.0, 0);
computeFixedPotentialFromGrid(); computeFixedPotentialFromGrid();
recordFixedMultipoleField(); recordFixedMultipoleField();
...@@ -5385,7 +5385,7 @@ void AmoebaReferencePmeMultipoleForce::spreadFixedMultipolesOntoGrid(const vecto ...@@ -5385,7 +5385,7 @@ void AmoebaReferencePmeMultipoleForce::spreadFixedMultipolesOntoGrid(const vecto
// Clear the grid. // Clear the grid.
for (int gridIndex = 0; gridIndex < _totalGridSize; gridIndex++) for (int gridIndex = 0; gridIndex < _totalGridSize; gridIndex++)
_pmeGrid[gridIndex] = t_complex(0, 0); _pmeGrid[gridIndex] = complex<double>(0, 0);
// Loop over atoms and spread them on the grid. // Loop over atoms and spread them on the grid.
...@@ -5414,8 +5414,8 @@ void AmoebaReferencePmeMultipoleForce::spreadFixedMultipolesOntoGrid(const vecto ...@@ -5414,8 +5414,8 @@ void AmoebaReferencePmeMultipoleForce::spreadFixedMultipolesOntoGrid(const vecto
for (int iz = 0; iz < AMOEBA_PME_ORDER; iz++) { for (int iz = 0; iz < AMOEBA_PME_ORDER; iz++) {
int z = (gridPoint[2]+iz) % _pmeGridDimensions[2]; int z = (gridPoint[2]+iz) % _pmeGridDimensions[2];
double4 v = _thetai[2][atomIndex*AMOEBA_PME_ORDER+iz]; double4 v = _thetai[2][atomIndex*AMOEBA_PME_ORDER+iz];
t_complex& gridValue = _pmeGrid[x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z]; complex<double>& gridValue = _pmeGrid[x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z];
gridValue.re += term0*v[0] + term1*v[1] + term2*v[2]; gridValue += term0*v[0] + term1*v[1] + term2*v[2];
} }
} }
} }
...@@ -5436,7 +5436,7 @@ void AmoebaReferencePmeMultipoleForce::performAmoebaReciprocalConvolution() ...@@ -5436,7 +5436,7 @@ void AmoebaReferencePmeMultipoleForce::performAmoebaReciprocalConvolution()
int kz = remainder-ky*_pmeGridDimensions[2]; int kz = remainder-ky*_pmeGridDimensions[2];
if (kx == 0 && ky == 0 && kz == 0) { if (kx == 0 && ky == 0 && kz == 0) {
_pmeGrid[index].re = _pmeGrid[index].im = 0.0; _pmeGrid[index] = complex<double>(0, 0);
continue; continue;
} }
...@@ -5456,8 +5456,7 @@ void AmoebaReferencePmeMultipoleForce::performAmoebaReciprocalConvolution() ...@@ -5456,8 +5456,7 @@ void AmoebaReferencePmeMultipoleForce::performAmoebaReciprocalConvolution()
double denom = m2*bx*by*bz; double denom = m2*bx*by*bz;
double eterm = scaleFactor*exp(-expFactor*m2)/denom; double eterm = scaleFactor*exp(-expFactor*m2)/denom;
_pmeGrid[index].re *= eterm; _pmeGrid[index] *= eterm;
_pmeGrid[index].im *= eterm;
} }
} }
...@@ -5507,7 +5506,7 @@ void AmoebaReferencePmeMultipoleForce::computeFixedPotentialFromGrid() ...@@ -5507,7 +5506,7 @@ void AmoebaReferencePmeMultipoleForce::computeFixedPotentialFromGrid()
for (int ix = 0; ix < AMOEBA_PME_ORDER; ix++) { for (int ix = 0; ix < AMOEBA_PME_ORDER; ix++) {
int i = gridPoint[0]+ix-(gridPoint[0]+ix >= _pmeGridDimensions[0] ? _pmeGridDimensions[0] : 0); int i = gridPoint[0]+ix-(gridPoint[0]+ix >= _pmeGridDimensions[0] ? _pmeGridDimensions[0] : 0);
int gridIndex = i*_pmeGridDimensions[1]*_pmeGridDimensions[2] + j*_pmeGridDimensions[2] + k; int gridIndex = i*_pmeGridDimensions[1]*_pmeGridDimensions[2] + j*_pmeGridDimensions[2] + k;
double tq = _pmeGrid[gridIndex].re; double tq = _pmeGrid[gridIndex].real();
double4 tadd = _thetai[0][m*AMOEBA_PME_ORDER+ix]; double4 tadd = _thetai[0][m*AMOEBA_PME_ORDER+ix];
t[0] += tq*tadd[0]; t[0] += tq*tadd[0];
t[1] += tq*tadd[1]; t[1] += tq*tadd[1];
...@@ -5581,7 +5580,7 @@ void AmoebaReferencePmeMultipoleForce::spreadInducedDipolesOnGrid(const vector<V ...@@ -5581,7 +5580,7 @@ void AmoebaReferencePmeMultipoleForce::spreadInducedDipolesOnGrid(const vector<V
// Clear the grid. // Clear the grid.
for (int gridIndex = 0; gridIndex < _totalGridSize; gridIndex++) for (int gridIndex = 0; gridIndex < _totalGridSize; gridIndex++)
_pmeGrid[gridIndex] = t_complex(0, 0); _pmeGrid[gridIndex] = complex<double>(0, 0);
// Loop over atoms and spread them on the grid. // Loop over atoms and spread them on the grid.
...@@ -5606,9 +5605,8 @@ void AmoebaReferencePmeMultipoleForce::spreadInducedDipolesOnGrid(const vector<V ...@@ -5606,9 +5605,8 @@ void AmoebaReferencePmeMultipoleForce::spreadInducedDipolesOnGrid(const vector<V
for (int iz = 0; iz < AMOEBA_PME_ORDER; iz++) { for (int iz = 0; iz < AMOEBA_PME_ORDER; iz++) {
int z = (gridPoint[2]+iz) % _pmeGridDimensions[2]; int z = (gridPoint[2]+iz) % _pmeGridDimensions[2];
double4 v = _thetai[2][atomIndex*AMOEBA_PME_ORDER+iz]; double4 v = _thetai[2][atomIndex*AMOEBA_PME_ORDER+iz];
t_complex& gridValue = _pmeGrid[x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z]; complex<double>& gridValue = _pmeGrid[x*_pmeGridDimensions[1]*_pmeGridDimensions[2]+y*_pmeGridDimensions[2]+z];
gridValue.re += term01*v[0] + term11*v[1]; gridValue += complex<double>(term01*v[0] + term11*v[1], term02*v[0] + term12*v[1]);
gridValue.im += term02*v[0] + term12*v[1];
} }
} }
} }
...@@ -5697,15 +5695,15 @@ void AmoebaReferencePmeMultipoleForce::computeInducedPotentialFromGrid() ...@@ -5697,15 +5695,15 @@ void AmoebaReferencePmeMultipoleForce::computeInducedPotentialFromGrid()
for (int ix = 0; ix < AMOEBA_PME_ORDER; ix++) { for (int ix = 0; ix < AMOEBA_PME_ORDER; ix++) {
int i = gridPoint[0]+ix-(gridPoint[0]+ix >= _pmeGridDimensions[0] ? _pmeGridDimensions[0] : 0); int i = gridPoint[0]+ix-(gridPoint[0]+ix >= _pmeGridDimensions[0] ? _pmeGridDimensions[0] : 0);
int gridIndex = i*_pmeGridDimensions[1]*_pmeGridDimensions[2] + j*_pmeGridDimensions[2] + k; int gridIndex = i*_pmeGridDimensions[1]*_pmeGridDimensions[2] + j*_pmeGridDimensions[2] + k;
t_complex tq = _pmeGrid[gridIndex]; complex<double> tq = _pmeGrid[gridIndex];
double4 tadd = _thetai[0][m*AMOEBA_PME_ORDER+ix]; double4 tadd = _thetai[0][m*AMOEBA_PME_ORDER+ix];
t0_1 += tq.re*tadd[0]; t0_1 += tq.real()*tadd[0];
t1_1 += tq.re*tadd[1]; t1_1 += tq.real()*tadd[1];
t2_1 += tq.re*tadd[2]; t2_1 += tq.real()*tadd[2];
t0_2 += tq.im*tadd[0]; t0_2 += tq.imag()*tadd[0];
t1_2 += tq.im*tadd[1]; t1_2 += tq.imag()*tadd[1];
t2_2 += tq.im*tadd[2]; t2_2 += tq.imag()*tadd[2];
t3 += (tq.re+tq.im)*tadd[3]; t3 += (tq.real()+tq.imag())*tadd[3];
} }
tu00_1 += t0_1*u[0]; tu00_1 += t0_1*u[0];
tu10_1 += t1_1*u[0]; tu10_1 += t1_1*u[0];
...@@ -6049,9 +6047,14 @@ void AmoebaReferencePmeMultipoleForce::calculateReciprocalSpaceInducedDipoleFiel ...@@ -6049,9 +6047,14 @@ void AmoebaReferencePmeMultipoleForce::calculateReciprocalSpaceInducedDipoleFiel
initializePmeGrid(); initializePmeGrid();
spreadInducedDipolesOnGrid(*updateInducedDipoleFields[0].inducedDipoles, *updateInducedDipoleFields[1].inducedDipoles); spreadInducedDipolesOnGrid(*updateInducedDipoleFields[0].inducedDipoles, *updateInducedDipoleFields[1].inducedDipoles);
fftpack_exec_3d(_fftplan, FFTPACK_FORWARD, _pmeGrid, _pmeGrid); vector<size_t> shape = {(size_t) _pmeGridDimensions[0], (size_t) _pmeGridDimensions[1], (size_t) _pmeGridDimensions[2]};
vector<size_t> axes = {0, 1, 2};
vector<ptrdiff_t> stride = {(ptrdiff_t) (_pmeGridDimensions[1]*_pmeGridDimensions[2]*sizeof(complex<double>)),
(ptrdiff_t) (_pmeGridDimensions[2]*sizeof(complex<double>)),
(ptrdiff_t) sizeof(complex<double>)};
pocketfft::c2c(shape, stride, stride, axes, true, _pmeGrid, _pmeGrid, 1.0, 0);
performAmoebaReciprocalConvolution(); performAmoebaReciprocalConvolution();
fftpack_exec_3d(_fftplan, FFTPACK_BACKWARD, _pmeGrid, _pmeGrid); pocketfft::c2c(shape, stride, stride, axes, false, _pmeGrid, _pmeGrid, 1.0, 0);
computeInducedPotentialFromGrid(); computeInducedPotentialFromGrid();
recordInducedDipoleField(updateInducedDipoleFields[0].inducedDipoleField, updateInducedDipoleFields[1].inducedDipoleField); recordInducedDipoleField(updateInducedDipoleFields[0].inducedDipoleField, updateInducedDipoleFields[1].inducedDipoleField);
} }
......
/* Portions copyright (c) 2006-2015 Stanford University and Simbios. /* Portions copyright (c) 2006-2022 Stanford University and Simbios.
* Contributors: Pande Group * Contributors: Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include "openmm/Vec3.h" #include "openmm/Vec3.h"
#include "AmoebaReferenceGeneralizedKirkwoodForce.h" #include "AmoebaReferenceGeneralizedKirkwoodForce.h"
#include <map> #include <map>
#include "fftpack.h"
#include <complex> #include <complex>
namespace OpenMM { namespace OpenMM {
...@@ -1474,10 +1473,8 @@ private: ...@@ -1474,10 +1473,8 @@ private:
int _totalGridSize; int _totalGridSize;
IntVec _pmeGridDimensions; IntVec _pmeGridDimensions;
fftpack_t _fftplan;
unsigned int _pmeGridSize; unsigned int _pmeGridSize;
t_complex* _pmeGrid; std::complex<double>* _pmeGrid;
std::vector<double> _pmeBsplineModuli[3]; std::vector<double> _pmeBsplineModuli[3];
std::vector<double4> _thetai[3]; std::vector<double4> _thetai[3];
......
...@@ -64,17 +64,14 @@ IF(NOT MSVC) ...@@ -64,17 +64,14 @@ IF(NOT MSVC)
ENDIF() ENDIF()
ENDIF() ENDIF()
# Include FFTW related files. # Include PocketFFT.
INCLUDE_DIRECTORIES(${FFTW_INCLUDES}) INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/libraries/include/pocketfft")
# Build the shared plugin library. # Build the shared plugin library.
IF (OPENMM_BUILD_SHARED_LIB) IF (OPENMM_BUILD_SHARED_LIB)
ADD_LIBRARY(${SHARED_TARGET} SHARED ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_INCLUDE_FILES}) ADD_LIBRARY(${SHARED_TARGET} SHARED ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_INCLUDE_FILES})
TARGET_LINK_LIBRARIES(${SHARED_TARGET} ${OPENMM_LIBRARY_NAME} ${PTHREADS_LIB} ${FFTW_LIBRARY}) TARGET_LINK_LIBRARIES(${SHARED_TARGET} ${OPENMM_LIBRARY_NAME} ${PTHREADS_LIB})
IF (FFTW_THREADS_LIBRARY)
TARGET_LINK_LIBRARIES(${SHARED_TARGET} ${FFTW_THREADS_LIBRARY})
ENDIF (FFTW_THREADS_LIBRARY)
SET_TARGET_PROPERTIES(${SHARED_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}" COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_PME_BUILDING_SHARED_LIBRARY") SET_TARGET_PROPERTIES(${SHARED_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}" COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_PME_BUILDING_SHARED_LIBRARY")
INSTALL_TARGETS(/lib/plugins RUNTIME_DIRECTORY /lib/plugins ${SHARED_TARGET}) INSTALL_TARGETS(/lib/plugins RUNTIME_DIRECTORY /lib/plugins ${SHARED_TARGET})
...@@ -84,10 +81,7 @@ ENDIF (OPENMM_BUILD_SHARED_LIB) ...@@ -84,10 +81,7 @@ ENDIF (OPENMM_BUILD_SHARED_LIB)
IF(OPENMM_BUILD_STATIC_LIB) IF(OPENMM_BUILD_STATIC_LIB)
ADD_LIBRARY(${STATIC_TARGET} STATIC ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_INCLUDE_FILES}) ADD_LIBRARY(${STATIC_TARGET} STATIC ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_INCLUDE_FILES})
TARGET_LINK_LIBRARIES(${STATIC_TARGET} ${OPENMM_LIBRARY_NAME}_static ${PTHREADS_LIB} ${FFTW_LIBRARY}) TARGET_LINK_LIBRARIES(${STATIC_TARGET} ${OPENMM_LIBRARY_NAME}_static ${PTHREADS_LIB})
IF (FFTW_THREADS_LIBRARY)
TARGET_LINK_LIBRARIES(${STATIC_TARGET} ${FFTW_THREADS_LIBRARY})
ENDIF (FFTW_THREADS_LIBRARY)
SET_TARGET_PROPERTIES(${STATIC_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}" COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_PME_BUILDING_STATIC_LIBRARY") SET_TARGET_PROPERTIES(${STATIC_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}" COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_PME_BUILDING_STATIC_LIBRARY")
INSTALL_TARGETS(/lib/plugins RUNTIME_DIRECTORY /lib/plugins ${STATIC_TARGET}) INSTALL_TARGETS(/lib/plugins RUNTIME_DIRECTORY /lib/plugins ${STATIC_TARGET})
......
This diff is collapsed.
...@@ -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) 2013-2018 Stanford University and the Authors. * * Portions copyright (c) 2013-2022 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include "openmm/Vec3.h" #include "openmm/Vec3.h"
#include "openmm/internal/ThreadPool.h" #include "openmm/internal/ThreadPool.h"
#include <atomic> #include <atomic>
#include <fftw3.h> #include <complex>
#include <pthread.h> #include <pthread.h>
#include <vector> #include <vector>
...@@ -46,13 +46,13 @@ namespace OpenMM { ...@@ -46,13 +46,13 @@ namespace OpenMM {
/** /**
* This is an optimized CPU implementation of CalcPmeReciprocalForceKernel. It is both * This is an optimized CPU implementation of CalcPmeReciprocalForceKernel. It is both
* vectorized (requiring SSE 4.1) and multithreaded. It uses FFTW to perform the FFTs. * vectorized (requiring SSE 4.1) and multithreaded. It uses PocketFFT to perform the FFTs.
*/ */
class OPENMM_EXPORT_PME CpuCalcPmeReciprocalForceKernel : public CalcPmeReciprocalForceKernel { class OPENMM_EXPORT_PME CpuCalcPmeReciprocalForceKernel : public CalcPmeReciprocalForceKernel {
public: public:
CpuCalcPmeReciprocalForceKernel(const std::string& name, const Platform& platform) : CalcPmeReciprocalForceKernel(name, platform), CpuCalcPmeReciprocalForceKernel(const std::string& name, const Platform& platform) : CalcPmeReciprocalForceKernel(name, platform),
hasCreatedPlan(false), isDeleted(false), realGrid(NULL), complexGrid(NULL) { isDeleted(false) {
} }
/** /**
* Initialize the kernel. * Initialize the kernel.
...@@ -104,24 +104,24 @@ public: ...@@ -104,24 +104,24 @@ public:
void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const; void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
private: private:
/** /**
* Select a size for one grid dimension that FFTW can handle efficiently. * Select a size for one grid dimension that PocketFFT can handle efficiently.
*/ */
int findFFTDimension(int minimum, bool isZ); int findFFTDimension(int minimum);
static bool hasInitializedThreads; static bool hasInitializedThreads;
static int numThreads; static int numThreads;
int gridx, gridy, gridz, numParticles; int gridx, gridy, gridz, numParticles;
double alpha; double alpha;
bool deterministic; bool deterministic;
bool hasCreatedPlan, isFinished, isDeleted; bool isFinished, isDeleted;
std::vector<float> force; std::vector<float> force;
std::vector<float> bsplineModuli[3]; std::vector<float> bsplineModuli[3];
std::vector<float> recipEterm; std::vector<float> recipEterm;
Vec3 lastBoxVectors[3]; Vec3 lastBoxVectors[3];
std::vector<float> threadEnergy; std::vector<float> threadEnergy;
std::vector<float*> tempGrid; std::vector<std::vector<float> > realGrids;
float* realGrid; std::vector<std::complex<float> > complexGrid;
fftwf_complex* complexGrid; std::vector<std::size_t> gridShape, fftAxes;
fftwf_plan forwardFFT, backwardFFT; std::vector<std::ptrdiff_t> realGridStride, complexGridStride;
int waitCount; int waitCount;
pthread_cond_t startCondition, endCondition; pthread_cond_t startCondition, endCondition;
pthread_mutex_t lock; pthread_mutex_t lock;
...@@ -139,13 +139,13 @@ private: ...@@ -139,13 +139,13 @@ private:
/** /**
* This is an optimized CPU implementation of CalcDispersionPmeReciprocalForceKernel. It is both * This is an optimized CPU implementation of CalcDispersionPmeReciprocalForceKernel. It is both
* vectorized (requiring SSE 4.1) and multithreaded. It uses FFTW to perform the FFTs. * vectorized (requiring SSE 4.1) and multithreaded. It uses PocketFFT to perform the FFTs.
*/ */
class OPENMM_EXPORT_PME CpuCalcDispersionPmeReciprocalForceKernel : public CalcDispersionPmeReciprocalForceKernel { class OPENMM_EXPORT_PME CpuCalcDispersionPmeReciprocalForceKernel : public CalcDispersionPmeReciprocalForceKernel {
public: public:
CpuCalcDispersionPmeReciprocalForceKernel(const std::string& name, const Platform& platform) : CalcDispersionPmeReciprocalForceKernel(name, platform), CpuCalcDispersionPmeReciprocalForceKernel(const std::string& name, const Platform& platform) : CalcDispersionPmeReciprocalForceKernel(name, platform),
hasCreatedPlan(false), isDeleted(false), realGrid(NULL), complexGrid(NULL) { isDeleted(false) {
} }
/** /**
* Initialize the kernel. * Initialize the kernel.
...@@ -198,24 +198,24 @@ public: ...@@ -198,24 +198,24 @@ public:
private: private:
class ComputeTask; class ComputeTask;
/** /**
* Select a size for one grid dimension that FFTW can handle efficiently. * Select a size for one grid dimension that PocketFFT can handle efficiently.
*/ */
int findFFTDimension(int minimum, bool isZ); int findFFTDimension(int minimum);
static bool hasInitializedThreads; static bool hasInitializedThreads;
static int numThreads; static int numThreads;
int gridx, gridy, gridz, numParticles; int gridx, gridy, gridz, numParticles;
double alpha; double alpha;
bool deterministic; bool deterministic;
bool hasCreatedPlan, isFinished, isDeleted; bool isFinished, isDeleted;
std::vector<float> force; std::vector<float> force;
std::vector<float> bsplineModuli[3]; std::vector<float> bsplineModuli[3];
std::vector<float> recipEterm; std::vector<float> recipEterm;
Vec3 lastBoxVectors[3]; Vec3 lastBoxVectors[3];
std::vector<float> threadEnergy; std::vector<float> threadEnergy;
std::vector<float*> tempGrid; std::vector<std::vector<float> > realGrids;
float* realGrid; std::vector<std::complex<float> > complexGrid;
fftwf_complex* complexGrid; std::vector<std::size_t> gridShape, fftAxes;
fftwf_plan forwardFFT, backwardFFT; std::vector<std::ptrdiff_t> realGridStride, complexGridStride;
int waitCount; int waitCount;
pthread_cond_t startCondition, endCondition; pthread_cond_t startCondition, endCondition;
pthread_mutex_t lock; pthread_mutex_t lock;
......
...@@ -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) 2011-2013 Stanford University and the Authors. * * Portions copyright (c) 2011-2022 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include "ReferencePlatform.h" #include "ReferencePlatform.h"
#include "openmm/RpmdKernels.h" #include "openmm/RpmdKernels.h"
#include "openmm/Vec3.h" #include "openmm/Vec3.h"
#include "fftpack.h"
namespace OpenMM { namespace OpenMM {
...@@ -46,9 +45,8 @@ namespace OpenMM { ...@@ -46,9 +45,8 @@ namespace OpenMM {
class ReferenceIntegrateRPMDStepKernel : public IntegrateRPMDStepKernel { class ReferenceIntegrateRPMDStepKernel : public IntegrateRPMDStepKernel {
public: public:
ReferenceIntegrateRPMDStepKernel(const std::string& name, const Platform& platform) : ReferenceIntegrateRPMDStepKernel(const std::string& name, const Platform& platform) :
IntegrateRPMDStepKernel(name, platform), fft(NULL) { IntegrateRPMDStepKernel(name, platform) {
} }
~ReferenceIntegrateRPMDStepKernel();
/** /**
* Initialize the kernel. * Initialize the kernel.
* *
...@@ -93,8 +91,6 @@ private: ...@@ -93,8 +91,6 @@ private:
std::vector<std::vector<Vec3> > contractedForces; std::vector<std::vector<Vec3> > contractedForces;
std::map<int, int> groupsByCopies; std::map<int, int> groupsByCopies;
int groupsNotContracted; int groupsNotContracted;
fftpack* fft;
std::map<int, fftpack*> contractionFFT;
}; };
} // namespace OpenMM } // namespace OpenMM
......
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