Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
f1533707
"...ssh:/git@developer.sourcefind.cn:2222/tsoc/openmm.git" did not exist on "f7f701363753918f51443d42150ea92f9d602923"
Commit
f1533707
authored
Oct 14, 2013
by
peastman
Browse files
Tabulate the Ewald scale factor
parent
9491eb72
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
85 additions
and
35 deletions
+85
-35
platforms/cpu/include/CpuNonbondedForce.h
platforms/cpu/include/CpuNonbondedForce.h
+21
-2
platforms/cpu/src/CpuNonbondedForce.cpp
platforms/cpu/src/CpuNonbondedForce.cpp
+64
-33
No files found.
platforms/cpu/include/CpuNonbondedForce.h
View file @
f1533707
...
@@ -166,6 +166,8 @@ private:
...
@@ -166,6 +166,8 @@ private:
float
alphaEwald
;
float
alphaEwald
;
int
numRx
,
numRy
,
numRz
;
int
numRx
,
numRy
,
numRz
;
int
meshDim
[
3
];
int
meshDim
[
3
];
std
::
vector
<
float
>
ewaldScaleX
,
ewaldScaleY
,
ewaldScaleDeriv
;
float
ewaldDX
,
ewaldDXInv
;
__m128
boxSize
,
invBoxSize
,
half
;
__m128
boxSize
,
invBoxSize
,
half
;
bool
isDeleted
;
bool
isDeleted
;
int
numThreads
,
waitCount
;
int
numThreads
,
waitCount
;
...
@@ -179,7 +181,8 @@ private:
...
@@ -179,7 +181,8 @@ private:
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
bool
includeEnergy
;
bool
includeEnergy
;
static
float
TWO_OVER_SQRT_PI
;
static
const
float
TWO_OVER_SQRT_PI
;
static
const
int
NUM_TABLE_POINTS
;
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
@@ -207,10 +210,26 @@ private:
...
@@ -207,10 +210,26 @@ private:
void
calculateOneEwaldIxn
(
int
atom1
,
int
atom2
,
float
*
forces
,
double
*
totalEnergy
);
void
calculateOneEwaldIxn
(
int
atom1
,
int
atom2
,
float
*
forces
,
double
*
totalEnergy
);
/**
* Compute the displacement and squared distance between two points, optionally using
* periodic boundary conditions.
*/
void
getDeltaR
(
const
__m128
&
posI
,
const
__m128
&
posJ
,
__m128
&
deltaR
,
float
&
r2
,
bool
periodic
)
const
;
void
getDeltaR
(
const
__m128
&
posI
,
const
__m128
&
posJ
,
__m128
&
deltaR
,
float
&
r2
,
bool
periodic
)
const
;
/**
* Compute a fast approximation to erfc(x).
*/
static
float
erfcApprox
(
float
x
);
static
float
erfcApprox
(
float
x
);
/**
* Create a lookup table for the scale factor used with Ewald and PME.
*/
void
tabulateEwaldScaleFactor
();
/**
* Evaluate the scale factor used with Ewald and PME: erfc(alpha*r) + 2*alpha*r*exp(-alpha*alpha*r*r)/sqrt(PI)
*/
float
ewaldScaleFunction
(
float
x
);
};
};
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
...
...
platforms/cpu/src/CpuNonbondedForce.cpp
View file @
f1533707
...
@@ -31,15 +31,17 @@
...
@@ -31,15 +31,17 @@
#include "ReferenceForce.h"
#include "ReferenceForce.h"
#include "ReferencePME.h"
#include "ReferencePME.h"
#include "openmm/internal/hardware.h"
#include "openmm/internal/hardware.h"
#include "openmm/internal/SplineFitter.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.
#include "openmm/internal/MSVC_erfc.h"
#include "openmm/internal/MSVC_erfc.h"
using
namespace
std
;
using
namespace
std
;
using
namespace
OpenMM
;
float
CpuNonbondedForce
::
TWO_OVER_SQRT_PI
=
(
float
)
(
2
/
sqrt
(
PI_M
));
const
float
CpuNonbondedForce
::
TWO_OVER_SQRT_PI
=
(
float
)
(
2
/
sqrt
(
PI_M
));
const
int
CpuNonbondedForce
::
NUM_TABLE_POINTS
=
1025
;
class
CpuNonbondedForce
::
ThreadData
{
class
CpuNonbondedForce
::
ThreadData
{
public:
public:
...
@@ -175,6 +177,7 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
...
@@ -175,6 +177,7 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
numRy
=
kmaxy
;
numRy
=
kmaxy
;
numRz
=
kmaxz
;
numRz
=
kmaxz
;
ewald
=
true
;
ewald
=
true
;
tabulateEwaldScaleFactor
();
}
}
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
...
@@ -192,11 +195,36 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
...
@@ -192,11 +195,36 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
meshDim
[
1
]
=
meshSize
[
1
];
meshDim
[
1
]
=
meshSize
[
1
];
meshDim
[
2
]
=
meshSize
[
2
];
meshDim
[
2
]
=
meshSize
[
2
];
pme
=
true
;
pme
=
true
;
tabulateEwaldScaleFactor
();
}
}
void
CpuNonbondedForce
::
calculateReciprocalIxn
(
int
numberOfAtoms
,
float
*
posq
,
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
void
CpuNonbondedForce
::
tabulateEwaldScaleFactor
()
{
ewaldDX
=
cutoffDistance
/
(
NUM_TABLE_POINTS
-
2
);
ewaldDXInv
=
1.0
f
/
ewaldDX
;
vector
<
double
>
x
(
NUM_TABLE_POINTS
);
vector
<
double
>
y
(
NUM_TABLE_POINTS
);
vector
<
double
>
deriv
;
for
(
int
i
=
0
;
i
<
NUM_TABLE_POINTS
;
i
++
)
{
double
r
=
i
*
cutoffDistance
/
(
NUM_TABLE_POINTS
-
2
);
double
alphaR
=
alphaEwald
*
r
;
x
[
i
]
=
r
;
y
[
i
]
=
erfc
(
alphaR
)
+
TWO_OVER_SQRT_PI
*
alphaR
*
exp
(
-
alphaR
*
alphaR
);
}
SplineFitter
::
createNaturalSpline
(
x
,
y
,
deriv
);
ewaldScaleX
.
resize
(
NUM_TABLE_POINTS
);
ewaldScaleY
.
resize
(
NUM_TABLE_POINTS
);
ewaldScaleDeriv
.
resize
(
NUM_TABLE_POINTS
);
for
(
int
i
=
0
;
i
<
NUM_TABLE_POINTS
;
i
++
)
{
ewaldScaleX
[
i
]
=
(
float
)
x
[
i
];
ewaldScaleY
[
i
]
=
(
float
)
y
[
i
];
ewaldScaleDeriv
[
i
]
=
(
float
)
(
deriv
[
i
]
*
ewaldDX
*
ewaldDX
/
6
);
}
}
void
CpuNonbondedForce
::
calculateReciprocalIxn
(
int
numberOfAtoms
,
float
*
posq
,
vector
<
RealVec
>&
atomCoordinates
,
const
vector
<
pair
<
float
,
float
>
>&
atomParameters
,
const
vector
<
set
<
int
>
>&
exclusions
,
const
vector
<
pair
<
float
,
float
>
>&
atomParameters
,
const
vector
<
set
<
int
>
>&
exclusions
,
vector
<
OpenMM
::
RealVec
>&
forces
,
float
*
totalEnergy
)
const
{
vector
<
RealVec
>&
forces
,
float
*
totalEnergy
)
const
{
typedef
std
::
complex
<
float
>
d_complex
;
typedef
std
::
complex
<
float
>
d_complex
;
static
const
float
epsilon
=
1.0
;
static
const
float
epsilon
=
1.0
;
...
@@ -344,27 +372,23 @@ void CpuNonbondedForce::calculateDirectIxn(int numberOfAtoms, float* posq, const
...
@@ -344,27 +372,23 @@ void CpuNonbondedForce::calculateDirectIxn(int numberOfAtoms, float* posq, const
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
)
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
)
for
(
set
<
int
>::
const_iterator
iter
=
exclusions
[
i
].
begin
();
iter
!=
exclusions
[
i
].
end
();
++
iter
)
{
for
(
set
<
int
>::
const_iterator
iter
=
exclusions
[
i
].
begin
();
iter
!=
exclusions
[
i
].
end
();
++
iter
)
{
if
(
*
iter
>
i
)
{
if
(
*
iter
>
i
)
{
int
ii
=
i
;
int
ii
=
i
;
int
jj
=
*
iter
;
int
jj
=
*
iter
;
__m128
deltaR
;
__m128
deltaR
;
__m128
posI
=
_mm_loadu_ps
(
posq
+
4
*
ii
);
__m128
posI
=
_mm_loadu_ps
(
posq
+
4
*
ii
);
__m128
posJ
=
_mm_loadu_ps
(
posq
+
4
*
jj
);
__m128
posJ
=
_mm_loadu_ps
(
posq
+
4
*
jj
);
float
r2
;
float
r2
;
getDeltaR
(
posJ
,
posI
,
deltaR
,
r2
,
false
);
getDeltaR
(
posJ
,
posI
,
deltaR
,
r2
,
false
);
float
r
=
sqrtf
(
r2
);
float
r
=
sqrtf
(
r2
);
float
inverseR
=
1
/
r
;
float
inverseR
=
1
/
r
;
float
alphaR
=
alphaEwald
*
r
;
float
chargeProd
=
ONE_4PI_EPS0
*
posq
[
4
*
ii
+
3
]
*
posq
[
4
*
jj
+
3
];
float
erfAlphaR
=
1.0
f
-
erfcApprox
(
alphaR
);
float
dEdR
=
(
float
)
(
chargeProd
*
inverseR
*
inverseR
*
inverseR
);
if
(
erfAlphaR
>
1e-6
)
{
dEdR
=
(
float
)
(
dEdR
*
(
1.0
f
-
ewaldScaleFunction
(
r
)));
float
chargeProd
=
ONE_4PI_EPS0
*
posq
[
4
*
ii
+
3
]
*
posq
[
4
*
jj
+
3
];
__m128
result
=
_mm_mul_ps
(
deltaR
,
_mm_set1_ps
(
dEdR
));
float
dEdR
=
(
float
)
(
chargeProd
*
inverseR
*
inverseR
*
inverseR
);
_mm_storeu_ps
(
forces
+
4
*
ii
,
_mm_sub_ps
(
_mm_loadu_ps
(
forces
+
4
*
ii
),
result
));
dEdR
=
(
float
)
(
dEdR
*
(
erfAlphaR
-
TWO_OVER_SQRT_PI
*
alphaR
*
exp
(
-
alphaR
*
alphaR
)));
_mm_storeu_ps
(
forces
+
4
*
jj
,
_mm_add_ps
(
_mm_loadu_ps
(
forces
+
4
*
jj
),
result
));
__m128
result
=
_mm_mul_ps
(
deltaR
,
_mm_set1_ps
(
dEdR
));
if
(
includeEnergy
)
_mm_storeu_ps
(
forces
+
4
*
ii
,
_mm_sub_ps
(
_mm_loadu_ps
(
forces
+
4
*
ii
),
result
));
directEnergy
-=
chargeProd
*
inverseR
*
(
1.0
f
-
erfcApprox
(
alphaEwald
*
r
));
_mm_storeu_ps
(
forces
+
4
*
jj
,
_mm_add_ps
(
_mm_loadu_ps
(
forces
+
4
*
jj
),
result
));
if
(
includeEnergy
)
directEnergy
-=
chargeProd
*
inverseR
*
erfAlphaR
;
}
}
}
}
}
}
}
...
@@ -451,7 +475,7 @@ void CpuNonbondedForce::calculateOneIxn(int ii, int jj, float* forces, double* t
...
@@ -451,7 +475,7 @@ void CpuNonbondedForce::calculateOneIxn(int ii, int jj, float* forces, double* t
dEdR
+=
(
float
)
(
chargeProd
*
(
inverseR
-
2.0
f
*
krf
*
r2
));
dEdR
+=
(
float
)
(
chargeProd
*
(
inverseR
-
2.0
f
*
krf
*
r2
));
else
else
dEdR
+=
(
float
)
(
chargeProd
*
inverseR
);
dEdR
+=
(
float
)
(
chargeProd
*
inverseR
);
dEdR
*=
inverseR
*
inverseR
;
dEdR
*=
inverseR
*
inverseR
;
float
energy
=
eps
*
(
sig6
-
1.0
f
)
*
sig6
;
float
energy
=
eps
*
(
sig6
-
1.0
f
)
*
sig6
;
if
(
useSwitch
)
{
if
(
useSwitch
)
{
dEdR
-=
energy
*
switchDeriv
*
inverseR
;
dEdR
-=
energy
*
switchDeriv
*
inverseR
;
...
@@ -491,18 +515,15 @@ void CpuNonbondedForce::calculateOneEwaldIxn(int ii, int jj, float* forces, doub
...
@@ -491,18 +515,15 @@ void CpuNonbondedForce::calculateOneEwaldIxn(int ii, int jj, float* forces, doub
switchValue
=
1
+
t
*
t
*
t
*
(
-
10
+
t
*
(
15
-
t
*
6
));
switchValue
=
1
+
t
*
t
*
t
*
(
-
10
+
t
*
(
15
-
t
*
6
));
switchDeriv
=
t
*
t
*
(
-
30
+
t
*
(
60
-
t
*
30
))
/
(
cutoffDistance
-
switchingDistance
);
switchDeriv
=
t
*
t
*
(
-
30
+
t
*
(
60
-
t
*
30
))
/
(
cutoffDistance
-
switchingDistance
);
}
}
float
alphaR
=
alphaEwald
*
r
;
float
erfcAlphaR
=
erfcApprox
(
alphaR
);
float
chargeProd
=
ONE_4PI_EPS0
*
posq
[
4
*
ii
+
3
]
*
posq
[
4
*
jj
+
3
];
float
chargeProd
=
ONE_4PI_EPS0
*
posq
[
4
*
ii
+
3
]
*
posq
[
4
*
jj
+
3
];
float
dEdR
=
(
float
)
(
chargeProd
*
inverseR
*
inverseR
*
inverseR
);
float
dEdR
=
chargeProd
*
inverseR
*
ewaldScaleFunction
(
r
);
dEdR
=
(
float
)
(
dEdR
*
(
erfcAlphaR
+
TWO_OVER_SQRT_PI
*
alphaR
*
exp
(
-
alphaR
*
alphaR
)));
float
sig
=
atomParameters
[
ii
].
first
+
atomParameters
[
jj
].
first
;
float
sig
=
atomParameters
[
ii
].
first
+
atomParameters
[
jj
].
first
;
float
sig2
=
inverseR
*
sig
;
float
sig2
=
inverseR
*
sig
;
sig2
*=
sig2
;
sig2
*=
sig2
;
float
sig6
=
sig2
*
sig2
*
sig2
;
float
sig6
=
sig2
*
sig2
*
sig2
;
float
eps
=
atomParameters
[
ii
].
second
*
atomParameters
[
jj
].
second
;
float
eps
=
atomParameters
[
ii
].
second
*
atomParameters
[
jj
].
second
;
dEdR
+=
switchValue
*
eps
*
(
12.0
f
*
sig6
-
6.0
f
)
*
sig6
*
inverseR
*
inverseR
;
dEdR
+=
switchValue
*
eps
*
(
12.0
f
*
sig6
-
6.0
f
)
*
sig6
;
dEdR
*=
inverseR
*
inverseR
;
float
energy
=
eps
*
(
sig6
-
1.0
f
)
*
sig6
;
float
energy
=
eps
*
(
sig6
-
1.0
f
)
*
sig6
;
if
(
useSwitch
)
{
if
(
useSwitch
)
{
dEdR
-=
energy
*
switchDeriv
*
inverseR
;
dEdR
-=
energy
*
switchDeriv
*
inverseR
;
...
@@ -518,7 +539,7 @@ void CpuNonbondedForce::calculateOneEwaldIxn(int ii, int jj, float* forces, doub
...
@@ -518,7 +539,7 @@ void CpuNonbondedForce::calculateOneEwaldIxn(int ii, int jj, float* forces, doub
// accumulate energies
// accumulate energies
if
(
totalEnergy
)
{
if
(
totalEnergy
)
{
energy
+=
(
float
)
(
chargeProd
*
inverseR
*
erfcA
lphaR
);
energy
+=
(
float
)
(
chargeProd
*
inverseR
*
erfcA
pprox
(
alphaEwald
*
r
)
);
*
totalEnergy
+=
energy
;
*
totalEnergy
+=
energy
;
}
}
}
}
...
@@ -543,3 +564,13 @@ float CpuNonbondedForce::erfcApprox(float x) {
...
@@ -543,3 +564,13 @@ float CpuNonbondedForce::erfcApprox(float x) {
t
*=
t
;
t
*=
t
;
return
1.0
f
/
(
t
*
t
);
return
1.0
f
/
(
t
*
t
);
}
}
float
CpuNonbondedForce
::
ewaldScaleFunction
(
float
x
)
{
// Compute the tabulated Ewald scale factor: erfc(alpha*r) + 2*alpha*r*exp(-alpha*alpha*r*r)/sqrt(PI)
int
lower
=
(
int
)
(
x
*
ewaldDXInv
);
int
upper
=
lower
+
1
;
float
a
=
(
ewaldScaleX
[
upper
]
-
x
)
*
ewaldDXInv
;
float
b
=
1.0
f
-
a
;
return
a
*
ewaldScaleY
[
lower
]
+
b
*
ewaldScaleY
[
upper
]
+
((
a
*
a
*
a
-
a
)
*
ewaldScaleDeriv
[
lower
]
+
(
b
*
b
*
b
-
b
)
*
ewaldScaleDeriv
[
upper
]);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment