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
61d5cc0f
Commit
61d5cc0f
authored
Apr 16, 2015
by
Peter
Browse files
Merge branch 'master' into applecl
parents
e2999354
afae4bc8
Changes
248
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1653 additions
and
280 deletions
+1653
-280
platforms/cpu/src/CpuKernelFactory.cpp
platforms/cpu/src/CpuKernelFactory.cpp
+2
-0
platforms/cpu/src/CpuKernels.cpp
platforms/cpu/src/CpuKernels.cpp
+227
-35
platforms/cpu/src/CpuLangevinDynamics.cpp
platforms/cpu/src/CpuLangevinDynamics.cpp
+0
-2
platforms/cpu/src/CpuNeighborList.cpp
platforms/cpu/src/CpuNeighborList.cpp
+195
-119
platforms/cpu/src/CpuNonbondedForce.cpp
platforms/cpu/src/CpuNonbondedForce.cpp
+32
-20
platforms/cpu/src/CpuNonbondedForceVec4.cpp
platforms/cpu/src/CpuNonbondedForceVec4.cpp
+137
-18
platforms/cpu/src/CpuNonbondedForceVec8.cpp
platforms/cpu/src/CpuNonbondedForceVec8.cpp
+145
-20
platforms/cpu/src/CpuPlatform.cpp
platforms/cpu/src/CpuPlatform.cpp
+1
-0
platforms/cpu/src/CpuRandom.cpp
platforms/cpu/src/CpuRandom.cpp
+6
-1
platforms/cpu/tests/TestCpuCustomGBForce.cpp
platforms/cpu/tests/TestCpuCustomGBForce.cpp
+483
-0
platforms/cpu/tests/TestCpuCustomManyParticleForce.cpp
platforms/cpu/tests/TestCpuCustomManyParticleForce.cpp
+65
-19
platforms/cpu/tests/TestCpuCustomNonbondedForce.cpp
platforms/cpu/tests/TestCpuCustomNonbondedForce.cpp
+60
-0
platforms/cpu/tests/TestCpuEwald.cpp
platforms/cpu/tests/TestCpuEwald.cpp
+52
-0
platforms/cpu/tests/TestCpuGBSAOBCForce.cpp
platforms/cpu/tests/TestCpuGBSAOBCForce.cpp
+32
-4
platforms/cpu/tests/TestCpuNeighborList.cpp
platforms/cpu/tests/TestCpuNeighborList.cpp
+23
-13
platforms/cpu/tests/TestCpuNonbondedForce.cpp
platforms/cpu/tests/TestCpuNonbondedForce.cpp
+63
-1
platforms/cuda/include/CudaContext.h
platforms/cuda/include/CudaContext.h
+73
-18
platforms/cuda/include/CudaKernels.h
platforms/cuda/include/CudaKernels.h
+42
-7
platforms/cuda/include/CudaNonbondedUtilities.h
platforms/cuda/include/CudaNonbondedUtilities.h
+1
-1
platforms/cuda/include/CudaParallelKernels.h
platforms/cuda/include/CudaParallelKernels.h
+14
-2
No files found.
Too many changes to show.
To preserve performance only
248 of 248+
files are displayed.
Plain diff
Email patch
platforms/cpu/src/CpuKernelFactory.cpp
View file @
61d5cc0f
...
...
@@ -53,6 +53,8 @@ KernelImpl* CpuKernelFactory::createKernelImpl(std::string name, const Platform&
return
new
CpuCalcCustomManyParticleForceKernel
(
name
,
platform
,
data
);
if
(
name
==
CalcGBSAOBCForceKernel
::
Name
())
return
new
CpuCalcGBSAOBCForceKernel
(
name
,
platform
,
data
);
if
(
name
==
CalcCustomGBForceKernel
::
Name
())
return
new
CpuCalcCustomGBForceKernel
(
name
,
platform
,
data
);
if
(
name
==
IntegrateLangevinStepKernel
::
Name
())
return
new
CpuIntegrateLangevinStepKernel
(
name
,
platform
,
data
);
throw
OpenMMException
((
std
::
string
(
"Tried to create kernel with illegal kernel name '"
)
+
name
+
"'"
).
c_str
());
...
...
platforms/cpu/src/CpuKernels.cpp
View file @
61d5cc0f
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013-201
4
Stanford University and the Authors. *
* Portions copyright (c) 2013-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -73,6 +73,11 @@ static RealVec& extractBoxSize(ContextImpl& context) {
return
*
(
RealVec
*
)
data
->
periodicBoxSize
;
}
static
RealVec
*
extractBoxVectors
(
ContextImpl
&
context
)
{
ReferencePlatform
::
PlatformData
*
data
=
reinterpret_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
return
(
RealVec
*
)
data
->
periodicBoxVectors
;
}
static
ReferenceConstraints
&
extractConstraints
(
ContextImpl
&
context
)
{
ReferencePlatform
::
PlatformData
*
data
=
reinterpret_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
return
*
(
ReferenceConstraints
*
)
data
->
constraints
;
...
...
@@ -140,26 +145,43 @@ public:
class
CpuCalcForcesAndEnergyKernel
::
InitForceTask
:
public
ThreadPool
::
Task
{
public:
InitForceTask
(
int
numParticles
,
ContextImpl
&
context
,
CpuPlatform
::
PlatformData
&
data
)
:
numParticles
(
numParticles
),
context
(
context
),
data
(
data
)
{
InitForceTask
(
int
numParticles
,
ContextImpl
&
context
,
CpuPlatform
::
PlatformData
&
data
)
:
numParticles
(
numParticles
),
positionsValid
(
true
),
context
(
context
),
data
(
data
)
{
}
void
execute
(
ThreadPool
&
threads
,
int
threadIndex
)
{
// Convert the positions to single precision and apply periodic boundary conditions
AlignedArray
<
float
>&
posq
=
data
.
posq
;
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
RealVec
boxSize
=
extractBoxSize
(
context
);
double
invBoxSize
[
3
]
=
{
1
/
boxSize
[
0
],
1
/
boxSize
[
1
],
1
/
boxSize
[
2
]};
RealVec
*
boxVectors
=
extractBoxVectors
(
context
);
double
boxSize
[
3
]
=
{
boxVectors
[
0
][
0
],
boxVectors
[
1
][
1
],
boxVectors
[
2
][
2
]};
double
invBoxSize
[
3
]
=
{
1
/
boxVectors
[
0
][
0
],
1
/
boxVectors
[
1
][
1
],
1
/
boxVectors
[
2
][
2
]};
bool
triclinic
=
(
boxVectors
[
0
][
1
]
!=
0
||
boxVectors
[
0
][
2
]
!=
0
||
boxVectors
[
1
][
0
]
!=
0
||
boxVectors
[
1
][
2
]
!=
0
||
boxVectors
[
2
][
0
]
!=
0
||
boxVectors
[
2
][
1
]
!=
0
);
int
numParticles
=
context
.
getSystem
().
getNumParticles
();
int
numThreads
=
threads
.
getNumThreads
();
int
start
=
threadIndex
*
numParticles
/
numThreads
;
int
end
=
(
threadIndex
+
1
)
*
numParticles
/
numThreads
;
if
(
data
.
isPeriodic
)
for
(
int
i
=
start
;
i
<
end
;
i
++
)
if
(
data
.
isPeriodic
)
{
if
(
triclinic
)
{
for
(
int
i
=
start
;
i
<
end
;
i
++
)
{
RealVec
pos
=
posData
[
i
];
pos
-=
boxVectors
[
2
]
*
floor
(
pos
[
2
]
*
invBoxSize
[
2
]);
pos
-=
boxVectors
[
1
]
*
floor
(
pos
[
1
]
*
invBoxSize
[
1
]);
pos
-=
boxVectors
[
0
]
*
floor
(
pos
[
0
]
*
invBoxSize
[
0
]);
posq
[
4
*
i
]
=
(
float
)
pos
[
0
];
posq
[
4
*
i
+
1
]
=
(
float
)
pos
[
1
];
posq
[
4
*
i
+
2
]
=
(
float
)
pos
[
2
];
}
}
else
{
for
(
int
i
=
start
;
i
<
end
;
i
++
)
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
RealOpenMM
x
=
posData
[
i
][
j
];
double
base
=
floor
(
x
*
invBoxSize
[
j
])
*
boxSize
[
j
];
posq
[
4
*
i
+
j
]
=
(
float
)
(
x
-
base
);
}
}
}
}
else
for
(
int
i
=
start
;
i
<
end
;
i
++
)
{
posq
[
4
*
i
]
=
(
float
)
posData
[
i
][
0
];
...
...
@@ -167,6 +189,12 @@ public:
posq
[
4
*
i
+
2
]
=
(
float
)
posData
[
i
][
2
];
}
// Check for invalid positions.
for
(
int
i
=
4
*
start
;
i
<
4
*
end
;
i
+=
4
)
if
(
posq
[
i
]
!=
posq
[
i
]
||
posq
[
i
+
1
]
!=
posq
[
i
+
1
]
||
posq
[
i
+
2
]
!=
posq
[
i
+
2
])
positionsValid
=
false
;
// Clear the forces.
fvec4
zero
(
0.0
f
);
...
...
@@ -174,6 +202,7 @@ public:
zero
.
store
(
&
data
.
threadForce
[
threadIndex
][
j
*
4
]);
}
int
numParticles
;
bool
positionsValid
;
ContextImpl
&
context
;
CpuPlatform
::
PlatformData
&
data
;
};
...
...
@@ -198,15 +227,17 @@ void CpuCalcForcesAndEnergyKernel::beginComputation(ContextImpl& context, bool i
InitForceTask
task
(
context
.
getSystem
().
getNumParticles
(),
context
,
data
);
data
.
threads
.
execute
(
task
);
data
.
threads
.
waitForThreads
();
if
(
!
task
.
positionsValid
)
throw
OpenMMException
(
"Particle coordinate is nan"
);
}
double
CpuCalcForcesAndEnergyKernel
::
finishComputation
(
ContextImpl
&
context
,
bool
includeForce
,
bool
includeEnergy
,
int
groups
)
{
double
CpuCalcForcesAndEnergyKernel
::
finishComputation
(
ContextImpl
&
context
,
bool
includeForce
,
bool
includeEnergy
,
int
groups
,
bool
&
valid
)
{
// Sum the forces from all the threads.
SumForceTask
task
(
context
.
getSystem
().
getNumParticles
(),
extractForces
(
context
),
data
);
data
.
threads
.
execute
(
task
);
data
.
threads
.
waitForThreads
();
return
referenceKernel
.
getAs
<
ReferenceCalcForcesAndEnergyKernel
>
().
finishComputation
(
context
,
includeForce
,
includeEnergy
,
groups
);
return
referenceKernel
.
getAs
<
ReferenceCalcForcesAndEnergyKernel
>
().
finishComputation
(
context
,
includeForce
,
includeEnergy
,
groups
,
valid
);
}
CpuCalcPeriodicTorsionForceKernel
::~
CpuCalcPeriodicTorsionForceKernel
()
{
...
...
@@ -477,21 +508,19 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
if
(
nonbondedMethod
==
PME
)
{
// If available, use the optimized PME implementation.
try
{
vector
<
string
>
kernelNames
;
kernelNames
.
push_back
(
"CalcPmeReciprocalForce"
);
useOptimizedPme
=
getPlatform
().
supportsKernels
(
kernelNames
);
if
(
useOptimizedPme
)
{
optimizedPme
=
getPlatform
().
createKernel
(
CalcPmeReciprocalForceKernel
::
Name
(),
context
);
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
initialize
(
gridSize
[
0
],
gridSize
[
1
],
gridSize
[
2
],
numParticles
,
ewaldAlpha
);
useOptimizedPme
=
true
;
}
catch
(
OpenMMException
&
ex
)
{
// The CPU PME plugin isn't available.
}
}
}
AlignedArray
<
float
>&
posq
=
data
.
posq
;
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
RealVec
boxSize
=
extractBoxSize
(
context
);
float
floatBoxSize
[
3
]
=
{(
float
)
boxSize
[
0
],
(
float
)
boxSize
[
1
],
(
float
)
boxSize
[
2
]};
RealVec
*
boxVectors
=
extractBoxVectors
(
context
);
double
energy
=
(
includeReciprocal
?
ewaldSelfEnergy
:
0.0
);
bool
ewald
=
(
nonbondedMethod
==
Ewald
);
bool
pme
=
(
nonbondedMethod
==
PME
);
...
...
@@ -537,16 +566,17 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
}
}
if
(
needRecompute
)
{
neighborList
->
computeNeighborList
(
numParticles
,
posq
,
exclusions
,
floatBoxSize
,
data
.
isPeriodic
,
nonbondedCutoff
+
padding
,
data
.
threads
);
neighborList
->
computeNeighborList
(
numParticles
,
posq
,
exclusions
,
boxVectors
,
data
.
isPeriodic
,
nonbondedCutoff
+
padding
,
data
.
threads
);
lastPositions
=
posData
;
}
nonbonded
->
setUseCutoff
(
nonbondedCutoff
,
*
neighborList
,
rfDielectric
);
}
if
(
data
.
isPeriodic
)
{
RealVec
*
boxVectors
=
extractBoxVectors
(
context
);
double
minAllowedSize
=
1.999999
*
nonbondedCutoff
;
if
(
box
Size
[
0
]
<
minAllowedSize
||
box
Size
[
1
]
<
minAllowedSize
||
box
Size
[
2
]
<
minAllowedSize
)
if
(
box
Vectors
[
0
]
[
0
]
<
minAllowedSize
||
box
Vectors
[
1
]
[
1
]
<
minAllowedSize
||
box
Vectors
[
2
]
[
2
]
<
minAllowedSize
)
throw
OpenMMException
(
"The periodic box size has decreased to less than twice the nonbonded cutoff."
);
nonbonded
->
setPeriodic
(
floatBoxSize
);
nonbonded
->
setPeriodic
(
boxVectors
);
}
if
(
ewald
)
nonbonded
->
setUseEwald
(
ewaldAlpha
,
kmax
[
0
],
kmax
[
1
],
kmax
[
2
]);
...
...
@@ -560,8 +590,8 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
if
(
includeReciprocal
)
{
if
(
useOptimizedPme
)
{
PmeIO
io
(
&
posq
[
0
],
&
data
.
threadForce
[
0
][
0
],
numParticles
);
Vec3
periodicBox
Size
(
boxSize
[
0
],
box
Size
[
1
],
box
Size
[
2
]
)
;
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
beginComputation
(
io
,
periodicBox
Size
,
includeEnergy
);
Vec3
periodicBox
Vectors
[
3
]
=
{
boxVectors
[
0
],
box
Vectors
[
1
],
box
Vectors
[
2
]
}
;
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
beginComputation
(
io
,
periodicBox
Vectors
,
includeEnergy
);
nonbondedEnergy
+=
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
finishComputation
(
io
);
}
else
...
...
@@ -573,7 +603,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
ReferenceLJCoulomb14
nonbonded14
;
refBondForce
.
calculateForce
(
num14
,
bonded14IndexArray
,
posData
,
bonded14ParamArray
,
forceData
,
includeEnergy
?
&
energy
:
NULL
,
nonbonded14
);
if
(
data
.
isPeriodic
)
energy
+=
dispersionCoefficient
/
(
box
Size
[
0
]
*
boxSize
[
1
]
*
boxSize
[
2
]);
energy
+=
dispersionCoefficient
/
(
box
Vectors
[
0
][
0
]
*
boxVectors
[
1
][
1
]
*
boxVectors
[
2
]
[
2
]);
}
return
energy
;
}
...
...
@@ -727,19 +757,18 @@ void CpuCalcCustomNonbondedForceKernel::initialize(const System& system, const C
double
CpuCalcCustomNonbondedForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
RealVec
&
box
=
extractBoxSize
(
context
);
float
floatBoxSize
[
3
]
=
{(
float
)
box
[
0
],
(
float
)
box
[
1
],
(
float
)
box
[
2
]};
RealVec
*
boxVectors
=
extractBoxVectors
(
context
);
double
energy
=
0
;
bool
periodic
=
(
nonbondedMethod
==
CutoffPeriodic
);
if
(
nonbondedMethod
!=
NoCutoff
)
{
neighborList
->
computeNeighborList
(
numParticles
,
data
.
posq
,
exclusions
,
floatBoxSize
,
data
.
isPeriodic
,
nonbondedCutoff
,
data
.
threads
);
neighborList
->
computeNeighborList
(
numParticles
,
data
.
posq
,
exclusions
,
boxVectors
,
data
.
isPeriodic
,
nonbondedCutoff
,
data
.
threads
);
nonbonded
->
setUseCutoff
(
nonbondedCutoff
,
*
neighborList
);
}
if
(
periodic
)
{
double
minAllowedSize
=
2
*
nonbondedCutoff
;
if
(
box
[
0
]
<
minAllowedSize
||
box
[
1
]
<
minAllowedSize
||
box
[
2
]
<
minAllowedSize
)
if
(
box
Vectors
[
0
]
[
0
]
<
minAllowedSize
||
box
Vectors
[
1
]
[
1
]
<
minAllowedSize
||
box
Vectors
[
2
]
[
2
]
<
minAllowedSize
)
throw
OpenMMException
(
"The periodic box size has decreased to less than twice the nonbonded cutoff."
);
nonbonded
->
setPeriodic
(
box
);
nonbonded
->
setPeriodic
(
box
Vectors
);
}
bool
globalParamsChanged
=
false
;
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
{
...
...
@@ -758,7 +787,7 @@ double CpuCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool inc
longRangeCoefficient
=
CustomNonbondedForceImpl
::
calcLongRangeCorrection
(
*
forceCopy
,
context
.
getOwner
());
hasInitializedLongRangeCorrection
=
true
;
}
energy
+=
longRangeCoefficient
/
(
box
[
0
]
*
box
[
1
]
*
box
[
2
]);
energy
+=
longRangeCoefficient
/
(
box
Vectors
[
0
][
0
]
*
boxVectors
[
1
][
1
]
*
boxVectors
[
2
]
[
2
]);
return
energy
;
}
...
...
@@ -802,6 +831,7 @@ void CpuCalcGBSAOBCForceKernel::initialize(const System& system, const GBSAOBCFo
obc
.
setParticleParameters
(
particleParams
);
obc
.
setSolventDielectric
((
float
)
force
.
getSolventDielectric
());
obc
.
setSoluteDielectric
((
float
)
force
.
getSoluteDielectric
());
obc
.
setSurfaceAreaEnergy
((
float
)
force
.
getSurfaceAreaEnergy
());
if
(
force
.
getNonbondedMethod
()
!=
GBSAOBCForce
::
NoCutoff
)
obc
.
setUseCutoff
((
float
)
force
.
getCutoffDistance
());
data
.
isPeriodic
=
(
force
.
getNonbondedMethod
()
==
GBSAOBCForce
::
CutoffPeriodic
);
...
...
@@ -835,6 +865,167 @@ void CpuCalcGBSAOBCForceKernel::copyParametersToContext(ContextImpl& context, co
obc
.
setParticleParameters
(
particleParams
);
}
CpuCalcCustomGBForceKernel
::~
CpuCalcCustomGBForceKernel
()
{
if
(
particleParamArray
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
delete
[]
particleParamArray
[
i
];
delete
[]
particleParamArray
;
}
if
(
neighborList
!=
NULL
)
delete
neighborList
;
if
(
ixn
!=
NULL
)
delete
ixn
;
}
void
CpuCalcCustomGBForceKernel
::
initialize
(
const
System
&
system
,
const
CustomGBForce
&
force
)
{
if
(
force
.
getNumComputedValues
()
>
0
)
{
string
name
,
expression
;
CustomGBForce
::
ComputationType
type
;
force
.
getComputedValueParameters
(
0
,
name
,
expression
,
type
);
if
(
type
==
CustomGBForce
::
SingleParticle
)
throw
OpenMMException
(
"CpuPlatform requires that the first computed value for a CustomGBForce be of type ParticlePair or ParticlePairNoExclusions."
);
for
(
int
i
=
1
;
i
<
force
.
getNumComputedValues
();
i
++
)
{
force
.
getComputedValueParameters
(
i
,
name
,
expression
,
type
);
if
(
type
!=
CustomGBForce
::
SingleParticle
)
throw
OpenMMException
(
"CpuPlatform requires that a CustomGBForce only have one computed value of type ParticlePair or ParticlePairNoExclusions."
);
}
}
// Record the exclusions.
numParticles
=
force
.
getNumParticles
();
exclusions
.
resize
(
numParticles
);
for
(
int
i
=
0
;
i
<
force
.
getNumExclusions
();
i
++
)
{
int
particle1
,
particle2
;
force
.
getExclusionParticles
(
i
,
particle1
,
particle2
);
exclusions
[
particle1
].
insert
(
particle2
);
exclusions
[
particle2
].
insert
(
particle1
);
}
// Build the arrays.
int
numPerParticleParameters
=
force
.
getNumPerParticleParameters
();
particleParamArray
=
new
double
*
[
numParticles
];
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
particleParamArray
[
i
]
=
new
double
[
numPerParticleParameters
];
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
vector
<
double
>
parameters
;
force
.
getParticleParameters
(
i
,
parameters
);
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
particleParamArray
[
i
][
j
]
=
static_cast
<
RealOpenMM
>
(
parameters
[
j
]);
}
for
(
int
i
=
0
;
i
<
numPerParticleParameters
;
i
++
)
particleParameterNames
.
push_back
(
force
.
getPerParticleParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
nonbondedMethod
=
CalcCustomGBForceKernel
::
NonbondedMethod
(
force
.
getNonbondedMethod
());
nonbondedCutoff
=
(
RealOpenMM
)
force
.
getCutoffDistance
();
if
(
nonbondedMethod
==
NoCutoff
)
neighborList
=
NULL
;
else
neighborList
=
new
CpuNeighborList
(
4
);
// Create custom functions for the tabulated functions.
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
for
(
int
i
=
0
;
i
<
force
.
getNumFunctions
();
i
++
)
functions
[
force
.
getTabulatedFunctionName
(
i
)]
=
createReferenceTabulatedFunction
(
force
.
getTabulatedFunction
(
i
));
// Parse the expressions for computed values.
vector
<
vector
<
Lepton
::
CompiledExpression
>
>
valueDerivExpressions
(
force
.
getNumComputedValues
());
vector
<
vector
<
Lepton
::
CompiledExpression
>
>
valueGradientExpressions
(
force
.
getNumComputedValues
());
vector
<
Lepton
::
CompiledExpression
>
valueExpressions
;
vector
<
Lepton
::
CompiledExpression
>
energyExpressions
;
for
(
int
i
=
0
;
i
<
force
.
getNumComputedValues
();
i
++
)
{
string
name
,
expression
;
CustomGBForce
::
ComputationType
type
;
force
.
getComputedValueParameters
(
i
,
name
,
expression
,
type
);
Lepton
::
ParsedExpression
ex
=
Lepton
::
Parser
::
parse
(
expression
,
functions
).
optimize
();
valueExpressions
.
push_back
(
ex
.
createCompiledExpression
());
valueTypes
.
push_back
(
type
);
valueNames
.
push_back
(
name
);
if
(
i
==
0
)
valueDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"r"
).
createCompiledExpression
());
else
{
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"x"
).
createCompiledExpression
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"y"
).
createCompiledExpression
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"z"
).
createCompiledExpression
());
for
(
int
j
=
0
;
j
<
i
;
j
++
)
valueDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]).
createCompiledExpression
());
}
}
// Parse the expressions for energy terms.
vector
<
vector
<
Lepton
::
CompiledExpression
>
>
energyDerivExpressions
(
force
.
getNumEnergyTerms
());
vector
<
vector
<
Lepton
::
CompiledExpression
>
>
energyGradientExpressions
(
force
.
getNumEnergyTerms
());
for
(
int
i
=
0
;
i
<
force
.
getNumEnergyTerms
();
i
++
)
{
string
expression
;
CustomGBForce
::
ComputationType
type
;
force
.
getEnergyTermParameters
(
i
,
expression
,
type
);
Lepton
::
ParsedExpression
ex
=
Lepton
::
Parser
::
parse
(
expression
,
functions
).
optimize
();
energyExpressions
.
push_back
(
ex
.
createCompiledExpression
());
energyTypes
.
push_back
(
type
);
if
(
type
!=
CustomGBForce
::
SingleParticle
)
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"r"
).
createCompiledExpression
());
for
(
int
j
=
0
;
j
<
force
.
getNumComputedValues
();
j
++
)
{
if
(
type
==
CustomGBForce
::
SingleParticle
)
{
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]).
createCompiledExpression
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"x"
).
createCompiledExpression
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"y"
).
createCompiledExpression
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"z"
).
createCompiledExpression
());
}
else
{
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]
+
"1"
).
createCompiledExpression
());
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]
+
"2"
).
createCompiledExpression
());
}
}
}
// Delete the custom functions.
for
(
map
<
string
,
Lepton
::
CustomFunction
*>::
iterator
iter
=
functions
.
begin
();
iter
!=
functions
.
end
();
iter
++
)
delete
iter
->
second
;
ixn
=
new
CpuCustomGBForce
(
numParticles
,
exclusions
,
valueExpressions
,
valueDerivExpressions
,
valueGradientExpressions
,
valueNames
,
valueTypes
,
energyExpressions
,
energyDerivExpressions
,
energyGradientExpressions
,
energyTypes
,
particleParameterNames
,
data
.
threads
);
data
.
isPeriodic
=
(
force
.
getNonbondedMethod
()
==
CustomGBForce
::
CutoffPeriodic
);
}
double
CpuCalcCustomGBForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
RealOpenMM
energy
=
0
;
RealVec
*
boxVectors
=
extractBoxVectors
(
context
);
if
(
data
.
isPeriodic
)
ixn
->
setPeriodic
(
extractBoxSize
(
context
));
if
(
nonbondedMethod
!=
NoCutoff
)
{
vector
<
set
<
int
>
>
noExclusions
(
numParticles
);
neighborList
->
computeNeighborList
(
numParticles
,
data
.
posq
,
exclusions
,
boxVectors
,
data
.
isPeriodic
,
nonbondedCutoff
,
data
.
threads
);
ixn
->
setUseCutoff
(
nonbondedCutoff
,
*
neighborList
);
}
map
<
string
,
double
>
globalParameters
;
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
globalParameters
[
globalParameterNames
[
i
]]
=
context
.
getParameter
(
globalParameterNames
[
i
]);
ixn
->
calculateIxn
(
numParticles
,
&
data
.
posq
[
0
],
particleParamArray
,
globalParameters
,
data
.
threadForce
,
includeForces
,
includeEnergy
,
energy
);
return
energy
;
}
void
CpuCalcCustomGBForceKernel
::
copyParametersToContext
(
ContextImpl
&
context
,
const
CustomGBForce
&
force
)
{
if
(
numParticles
!=
force
.
getNumParticles
())
throw
OpenMMException
(
"updateParametersInContext: The number of particles has changed"
);
// Record the values.
int
numParameters
=
force
.
getNumPerParticleParameters
();
vector
<
double
>
params
;
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
vector
<
double
>
parameters
;
force
.
getParticleParameters
(
i
,
parameters
);
for
(
int
j
=
0
;
j
<
numParameters
;
j
++
)
particleParamArray
[
i
][
j
]
=
static_cast
<
RealOpenMM
>
(
parameters
[
j
]);
}
}
CpuCalcCustomManyParticleForceKernel
::~
CpuCalcCustomManyParticleForceKernel
()
{
if
(
particleParamArray
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
...
...
@@ -866,6 +1057,7 @@ void CpuCalcCustomManyParticleForceKernel::initialize(const System& system, cons
ixn
=
new
CpuCustomManyParticleForce
(
force
,
data
.
threads
);
nonbondedMethod
=
CalcCustomManyParticleForceKernel
::
NonbondedMethod
(
force
.
getNonbondedMethod
());
cutoffDistance
=
force
.
getCutoffDistance
();
data
.
isPeriodic
=
(
nonbondedMethod
==
CutoffPeriodic
);
}
double
CpuCalcCustomManyParticleForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
...
...
@@ -873,11 +1065,11 @@ double CpuCalcCustomManyParticleForceKernel::execute(ContextImpl& context, bool
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
globalParameters
[
globalParameterNames
[
i
]]
=
context
.
getParameter
(
globalParameterNames
[
i
]);
if
(
nonbondedMethod
==
CutoffPeriodic
)
{
RealVec
&
box
=
extractBox
Size
(
context
);
RealVec
*
box
Vectors
=
extractBox
Vectors
(
context
);
double
minAllowedSize
=
2
*
cutoffDistance
;
if
(
box
[
0
]
<
minAllowedSize
||
box
[
1
]
<
minAllowedSize
||
box
[
2
]
<
minAllowedSize
)
if
(
box
Vectors
[
0
]
[
0
]
<
minAllowedSize
||
box
Vectors
[
1
]
[
1
]
<
minAllowedSize
||
box
Vectors
[
2
]
[
2
]
<
minAllowedSize
)
throw
OpenMMException
(
"The periodic box size has decreased to less than twice the nonbonded cutoff."
);
ixn
->
setPeriodic
(
box
);
ixn
->
setPeriodic
(
box
Vectors
);
}
double
energy
=
0
;
ixn
->
calculateIxn
(
data
.
posq
,
particleParamArray
,
globalParameters
,
data
.
threadForce
,
includeForces
,
includeEnergy
,
energy
);
...
...
platforms/cpu/src/CpuLangevinDynamics.cpp
View file @
61d5cc0f
...
...
@@ -23,8 +23,6 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMLog.h"
#include "SimTKOpenMMUtilities.h"
#include "CpuLangevinDynamics.h"
...
...
platforms/cpu/src/CpuNeighborList.cpp
View file @
61d5cc0f
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013 Stanford University and the Authors.
*
* Portions copyright (c) 2013
-2015
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -45,12 +45,12 @@ namespace OpenMM {
class
VoxelIndex
{
public:
VoxelIndex
()
:
x
(
0
),
y
(
0
)
{
VoxelIndex
()
:
y
(
0
),
z
(
0
)
{
}
VoxelIndex
(
int
x
,
int
y
)
:
x
(
x
),
y
(
y
)
{
VoxelIndex
(
int
y
,
int
z
)
:
y
(
y
),
z
(
z
)
{
}
int
x
;
int
y
;
int
z
;
};
/**
...
...
@@ -59,26 +59,35 @@ public:
*/
class
CpuNeighborList
::
Voxels
{
public:
Voxels
(
int
blockSize
,
float
vsx
,
float
vsy
,
float
minx
,
float
maxx
,
float
miny
,
float
maxy
,
const
float
*
periodicBoxSize
,
bool
usePeriodic
)
:
blockSize
(
blockSize
),
voxelSizeX
(
vsx
),
voxelSizeY
(
vsy
),
minx
(
minx
),
maxx
(
maxx
),
miny
(
miny
),
maxy
(
maxy
),
periodicBoxSize
(
periodicBoxSize
),
usePeriodic
(
usePeriodic
)
{
Voxels
(
int
blockSize
,
float
vsy
,
float
vsz
,
float
miny
,
float
maxy
,
float
minz
,
float
maxz
,
const
RealVec
*
periodicBoxVectors
,
bool
usePeriodic
)
:
blockSize
(
blockSize
),
voxelSizeY
(
vsy
),
voxelSizeZ
(
vsz
),
miny
(
miny
),
maxy
(
maxy
),
minz
(
minz
),
maxz
(
maxz
),
periodicBoxVectors
(
periodicBoxVectors
),
usePeriodic
(
usePeriodic
)
{
periodicBoxSize
[
0
]
=
(
float
)
periodicBoxVectors
[
0
][
0
];
periodicBoxSize
[
1
]
=
(
float
)
periodicBoxVectors
[
1
][
1
];
periodicBoxSize
[
2
]
=
(
float
)
periodicBoxVectors
[
2
][
2
];
recipBoxSize
[
0
]
=
(
float
)
(
1
/
periodicBoxVectors
[
0
][
0
]);
recipBoxSize
[
1
]
=
(
float
)
(
1
/
periodicBoxVectors
[
1
][
1
]);
recipBoxSize
[
2
]
=
(
float
)
(
1
/
periodicBoxVectors
[
2
][
2
]);
triclinic
=
(
periodicBoxVectors
[
0
][
1
]
!=
0.0
||
periodicBoxVectors
[
0
][
2
]
!=
0.0
||
periodicBoxVectors
[
1
][
0
]
!=
0.0
||
periodicBoxVectors
[
1
][
2
]
!=
0.0
||
periodicBoxVectors
[
2
][
0
]
!=
0.0
||
periodicBoxVectors
[
2
][
1
]
!=
0.0
);
if
(
usePeriodic
)
{
n
x
=
(
int
)
floorf
(
periodicBox
Size
[
0
]
/
voxelSize
X
+
0.5
f
);
n
y
=
(
int
)
floorf
(
periodicBox
Size
[
1
]
/
voxelSize
Y
+
0.5
f
);
voxelSize
X
=
periodicBox
Size
[
0
]
/
n
x
;
voxelSize
Y
=
periodicBox
Size
[
1
]
/
n
y
;
n
y
=
(
int
)
floorf
(
periodicBox
Vectors
[
1
][
1
]
/
voxelSize
Y
+
0.5
f
);
n
z
=
(
int
)
floorf
(
periodicBox
Vectors
[
2
][
2
]
/
voxelSize
Z
+
0.5
f
);
voxelSize
Y
=
periodicBox
Vectors
[
1
][
1
]
/
n
y
;
voxelSize
Z
=
periodicBox
Vectors
[
2
][
2
]
/
n
z
;
}
else
{
nx
=
max
(
1
,
(
int
)
floorf
((
maxx
-
minx
)
/
voxelSizeX
+
0.5
f
));
ny
=
max
(
1
,
(
int
)
floorf
((
maxy
-
miny
)
/
voxelSizeY
+
0.5
f
));
if
(
maxx
>
minx
)
voxelSizeX
=
(
maxx
-
minx
)
/
nx
;
nz
=
max
(
1
,
(
int
)
floorf
((
maxz
-
minz
)
/
voxelSizeZ
+
0.5
f
));
if
(
maxy
>
miny
)
voxelSizeY
=
(
maxy
-
miny
)
/
ny
;
if
(
maxz
>
minz
)
voxelSizeZ
=
(
maxz
-
minz
)
/
nz
;
}
bins
.
resize
(
n
x
);
for
(
int
i
=
0
;
i
<
n
x
;
i
++
)
{
bins
[
i
].
resize
(
n
y
);
for
(
int
j
=
0
;
j
<
n
y
;
j
++
)
bins
.
resize
(
n
y
);
for
(
int
i
=
0
;
i
<
n
y
;
i
++
)
{
bins
[
i
].
resize
(
n
z
);
for
(
int
j
=
0
;
j
<
n
z
;
j
++
)
bins
[
i
][
j
].
resize
(
0
);
}
}
...
...
@@ -88,28 +97,28 @@ public:
*/
void
insert
(
const
int
&
atom
,
const
float
*
location
)
{
VoxelIndex
voxelIndex
=
getVoxelIndex
(
location
);
bins
[
voxelIndex
.
x
][
voxelIndex
.
y
].
push_back
(
make_pair
(
location
[
2
],
atom
));
bins
[
voxelIndex
.
y
][
voxelIndex
.
z
].
push_back
(
make_pair
(
location
[
0
],
atom
));
}
/**
* Sort the particles in each voxel by
z
coordinate.
* Sort the particles in each voxel by
x
coordinate.
*/
void
sortItems
()
{
for
(
int
i
=
0
;
i
<
n
x
;
i
++
)
for
(
int
j
=
0
;
j
<
n
y
;
j
++
)
for
(
int
i
=
0
;
i
<
n
y
;
i
++
)
for
(
int
j
=
0
;
j
<
n
z
;
j
++
)
sort
(
bins
[
i
][
j
].
begin
(),
bins
[
i
][
j
].
end
());
}
/**
* Find the index of the first particle in voxel (
x,y
) whose
z
coordinate in >= the specified value.
* Find the index of the first particle in voxel (
y,z
) whose
x
coordinate in >= the specified value.
*/
int
findLowerBound
(
int
x
,
int
y
,
double
z
)
const
{
const
vector
<
pair
<
float
,
int
>
>&
bin
=
bins
[
x
][
y
];
int
findLowerBound
(
int
y
,
int
z
,
double
x
)
const
{
const
vector
<
pair
<
float
,
int
>
>&
bin
=
bins
[
y
][
z
];
int
lower
=
0
;
int
upper
=
bin
.
size
();
while
(
lower
<
upper
)
{
int
middle
=
(
lower
+
upper
)
/
2
;
if
(
bin
[
middle
].
first
<
z
)
if
(
bin
[
middle
].
first
<
x
)
lower
=
middle
+
1
;
else
upper
=
middle
;
...
...
@@ -118,15 +127,15 @@ public:
}
/**
* Find the index of the first particle in voxel (
x,y
) whose
z
coordinate in greater than the specified value.
* Find the index of the first particle in voxel (
y,z
) whose
x
coordinate in greater than the specified value.
*/
int
findUpperBound
(
int
x
,
int
y
,
double
z
)
const
{
const
vector
<
pair
<
float
,
int
>
>&
bin
=
bins
[
x
][
y
];
int
findUpperBound
(
int
y
,
int
z
,
double
x
)
const
{
const
vector
<
pair
<
float
,
int
>
>&
bin
=
bins
[
y
][
z
];
int
lower
=
0
;
int
upper
=
bin
.
size
();
while
(
lower
<
upper
)
{
int
middle
=
(
lower
+
upper
)
/
2
;
if
(
bin
[
middle
].
first
>
z
)
if
(
bin
[
middle
].
first
>
x
)
upper
=
middle
;
else
lower
=
middle
+
1
;
...
...
@@ -138,131 +147,167 @@ public:
* Get the voxel index containing a particular location.
*/
VoxelIndex
getVoxelIndex
(
const
float
*
location
)
const
{
float
x
periodic
,
y
periodic
;
float
y
periodic
,
z
periodic
;
if
(
!
usePeriodic
)
{
xperiodic
=
location
[
0
]
-
minx
;
yperiodic
=
location
[
1
]
-
miny
;
zperiodic
=
location
[
2
]
-
minz
;
}
else
{
xperiodic
=
location
[
0
]
-
periodicBoxSize
[
0
]
*
floorf
(
location
[
0
]
/
periodicBoxSize
[
0
]);
yperiodic
=
location
[
1
]
-
periodicBoxSize
[
1
]
*
floorf
(
location
[
1
]
/
periodicBoxSize
[
1
]);
float
scale2
=
floorf
(
location
[
2
]
*
recipBoxSize
[
2
]);
yperiodic
=
location
[
1
]
-
periodicBoxVectors
[
2
][
1
]
*
scale2
;
zperiodic
=
location
[
2
]
-
periodicBoxVectors
[
2
][
2
]
*
scale2
;
float
scale1
=
floorf
(
yperiodic
*
recipBoxSize
[
1
]);
yperiodic
-=
periodicBoxVectors
[
1
][
0
]
*
scale1
;
}
int
x
=
min
(
nx
-
1
,
int
(
floorf
(
xperiodic
/
voxelSizeX
)));
int
y
=
min
(
ny
-
1
,
int
(
floorf
(
yperiodic
/
voxelSizeY
)));
int
z
=
min
(
nz
-
1
,
int
(
floorf
(
zperiodic
/
voxelSizeZ
)));
return
VoxelIndex
(
x
,
y
);
return
VoxelIndex
(
y
,
z
);
}
void
getNeighbors
(
vector
<
int
>&
neighbors
,
int
blockIndex
,
const
fvec4
&
blockCenter
,
const
fvec4
&
blockWidth
,
const
vector
<
int
>&
sortedAtoms
,
vector
<
char
>&
exclusions
,
float
maxDistance
,
const
vector
<
int
>&
blockAtoms
,
const
float
*
atomLoca
tions
,
const
vector
<
VoxelIndex
>&
atomVoxelIndex
)
const
{
void
getNeighbors
(
vector
<
int
>&
neighbors
,
int
blockIndex
,
const
fvec4
&
blockCenter
,
const
fvec4
&
blockWidth
,
const
vector
<
int
>&
sortedAtoms
,
vector
<
char
>&
exclusions
,
float
maxDistance
,
const
vector
<
int
>&
blockAtoms
,
const
vector
<
float
>&
blockAtomX
,
const
vector
<
float
>&
blockAtomY
,
const
vector
<
float
>&
blockAtomZ
,
const
vector
<
float
>&
sortedPosi
tions
,
const
vector
<
VoxelIndex
>&
atomVoxelIndex
)
const
{
neighbors
.
resize
(
0
);
exclusions
.
resize
(
0
);
fvec4
boxSize
(
periodicBoxSize
[
0
],
periodicBoxSize
[
1
],
periodicBoxSize
[
2
],
0
);
fvec4
invBoxSize
(
1
/
periodicBoxSize
[
0
],
1
/
periodicBoxSize
[
1
],
1
/
periodicBoxSize
[
2
],
0
);
fvec4
invBoxSize
(
recipBoxSize
[
0
],
recipBoxSize
[
1
],
recipBoxSize
[
2
],
0
);
fvec4
periodicBoxVec4
[
3
];
periodicBoxVec4
[
0
]
=
fvec4
(
periodicBoxVectors
[
0
][
0
],
periodicBoxVectors
[
0
][
1
],
periodicBoxVectors
[
0
][
2
],
0
);
periodicBoxVec4
[
1
]
=
fvec4
(
periodicBoxVectors
[
1
][
0
],
periodicBoxVectors
[
1
][
1
],
periodicBoxVectors
[
1
][
2
],
0
);
periodicBoxVec4
[
2
]
=
fvec4
(
periodicBoxVectors
[
2
][
0
],
periodicBoxVectors
[
2
][
1
],
periodicBoxVectors
[
2
][
2
],
0
);
float
maxDistanceSquared
=
maxDistance
*
maxDistance
;
float
refineCutoff
=
maxDistance
-
max
(
max
(
blockWidth
[
0
],
blockWidth
[
1
]),
blockWidth
[
2
]);
float
refineCutoffSquared
=
refineCutoff
*
refineCutoff
;
int
dIndex
X
=
int
((
maxDistance
+
blockWidth
[
0
])
/
voxelSize
X
)
+
1
;
// How may voxels away do we have to look?
int
dIndex
Y
=
int
((
maxDistance
+
blockWidth
[
1
])
/
voxelSize
Y
)
+
1
;
int
dIndex
Y
=
int
((
maxDistance
+
blockWidth
[
1
])
/
voxelSize
Y
)
+
1
;
// How may voxels away do we have to look?
int
dIndex
Z
=
int
((
maxDistance
+
blockWidth
[
2
])
/
voxelSize
Z
)
+
1
;
if
(
usePeriodic
)
{
dIndexX
=
min
(
nx
/
2
,
dIndexX
);
dIndexY
=
min
(
ny
/
2
,
dIndexY
);
dIndexZ
=
min
(
nz
/
2
,
dIndexZ
);
}
float
centerPos
[
4
];
blockCenter
.
store
(
centerPos
);
VoxelIndex
centerVoxelIndex
=
getVoxelIndex
(
centerPos
);
int
startx
=
centerVoxelIndex
.
x
-
dIndexX
;
// Loop over voxels along the z axis.
int
startz
=
centerVoxelIndex
.
z
-
dIndexZ
;
int
endz
=
centerVoxelIndex
.
z
+
dIndexZ
;
if
(
usePeriodic
)
endz
=
min
(
endz
,
startz
+
nz
-
1
);
else
{
startz
=
max
(
startz
,
0
);
endz
=
min
(
endz
,
nz
-
1
);
}
int
lastSortedIndex
=
blockSize
*
(
blockIndex
+
1
);
VoxelIndex
voxelIndex
(
0
,
0
);
for
(
int
z
=
startz
;
z
<=
endz
;
++
z
)
{
voxelIndex
.
z
=
z
;
if
(
usePeriodic
)
voxelIndex
.
z
=
(
z
<
0
?
z
+
nz
:
(
z
>=
nz
?
z
-
nz
:
z
));
// Loop over voxels along the y axis.
int
boxz
=
(
int
)
floor
((
float
)
z
/
nz
);
int
starty
=
centerVoxelIndex
.
y
-
dIndexY
;
int
endx
=
centerVoxelIndex
.
x
+
dIndexX
;
int
endy
=
centerVoxelIndex
.
y
+
dIndexY
;
int
numRanges
;
float
yoffset
=
(
float
)
(
usePeriodic
?
boxz
*
periodicBoxVectors
[
2
][
1
]
:
0
)
;
if
(
usePeriodic
)
{
endx
=
min
(
endx
,
centerVoxelIndex
.
x
-
dIndexX
+
nx
-
1
);
endy
=
min
(
endy
,
centerVoxelIndex
.
y
-
dIndexY
+
ny
-
1
);
starty
-=
(
int
)
ceil
(
yoffset
/
voxelSizeY
);
endy
-=
(
int
)
floor
(
yoffset
/
voxelSizeY
);
endy
=
min
(
endy
,
starty
+
ny
-
1
);
}
else
{
startx
=
max
(
startx
,
0
);
starty
=
max
(
starty
,
0
);
endx
=
min
(
endx
,
nx
-
1
);
endy
=
min
(
endy
,
ny
-
1
);
}
int
lastSortedIndex
=
blockSize
*
(
blockIndex
+
1
);
VoxelIndex
voxelIndex
(
0
,
0
);
for
(
int
x
=
startx
;
x
<=
endx
;
++
x
)
{
voxelIndex
.
x
=
x
;
if
(
usePeriodic
)
voxelIndex
.
x
=
(
x
<
0
?
x
+
nx
:
(
x
>=
nx
?
x
-
nx
:
x
));
for
(
int
y
=
starty
;
y
<=
endy
;
++
y
)
{
voxelIndex
.
y
=
y
;
if
(
usePeriodic
)
voxelIndex
.
y
=
(
y
<
0
?
y
+
ny
:
(
y
>=
ny
?
y
-
ny
:
y
));
int
boxy
=
(
int
)
floor
((
float
)
y
/
ny
);
float
xoffset
=
(
float
)
(
usePeriodic
?
boxy
*
periodicBoxVectors
[
1
][
0
]
+
boxz
*
periodicBoxVectors
[
2
][
0
]
:
0
);
// Identify the range of atoms within this bin we need to search. When using periodic boundary
// conditions, there may be two separate ranges.
float
minz
=
centerPos
[
2
];
float
maxz
=
centerPos
[
2
];
fvec4
offset
(
voxelSizeX
*
x
+
(
usePeriodic
?
0.0
f
:
minx
),
voxelSizeY
*
y
+
(
usePeriodic
?
0.0
f
:
miny
),
0
,
0
);
for
(
int
k
=
0
;
k
<
(
int
)
blockAtoms
.
size
();
k
++
)
{
const
float
*
atomPos
=
&
atomLocations
[
4
*
blockAtoms
[
k
]];
fvec4
posVec
(
atomPos
);
fvec4
delta1
=
offset
-
posVec
;
fvec4
delta2
=
delta1
+
fvec4
(
voxelSizeX
,
voxelSizeY
,
0
,
0
);
float
minx
=
centerPos
[
0
];
float
maxx
=
centerPos
[
0
];
float
offset
[
3
]
=
{
-
xoffset
,
-
yoffset
+
voxelSizeY
*
y
+
(
usePeriodic
?
0.0
f
:
miny
),
voxelSizeZ
*
z
+
(
usePeriodic
?
0.0
f
:
minz
)};
for
(
int
k
=
0
;
k
<
(
int
)
blockAtoms
.
size
();
k
+=
4
)
{
fvec4
dist2
=
maxDistanceSquared
;
if
(
y
!=
atomVoxelIndex
[
k
].
y
)
{
fvec4
dy1
=
offset
[
1
]
-
fvec4
(
&
blockAtomY
[
k
]);
fvec4
dy2
=
dy1
+
voxelSizeY
;
if
(
usePeriodic
)
{
dy1
-=
round
(
dy1
*
invBoxSize
[
1
])
*
boxSize
[
1
];
dy2
-=
round
(
dy2
*
invBoxSize
[
1
])
*
boxSize
[
1
];
}
fvec4
dy
=
min
(
abs
(
dy1
),
abs
(
dy2
));
dist2
-=
dy
*
dy
;
}
if
(
z
!=
atomVoxelIndex
[
k
].
z
)
{
fvec4
dz1
=
offset
[
2
]
-
fvec4
(
&
blockAtomZ
[
k
]);
fvec4
dz2
=
dz1
+
voxelSizeZ
;
if
(
usePeriodic
)
{
delta1
-=
round
(
delta1
*
invBoxSize
)
*
boxSize
;
delta2
-=
round
(
delta2
*
invBoxSize
)
*
boxSize
;
dz1
-=
round
(
dz1
*
invBoxSize
[
2
])
*
boxSize
[
2
];
dz2
-=
round
(
dz2
*
invBoxSize
[
2
])
*
boxSize
[
2
];
}
fvec4
dz
=
min
(
abs
(
dz1
),
abs
(
dz2
));
dist2
-=
dz
*
dz
;
}
fvec4
delta
=
min
(
abs
(
delta1
),
abs
(
delta2
));
float
dx
=
(
x
==
atomVoxelIndex
[
k
].
x
?
0.0
f
:
delta
[
0
]);
float
dy
=
(
y
==
atomVoxelIndex
[
k
].
y
?
0.0
f
:
delta
[
1
]);
float
dist2
=
maxDistanceSquared
-
dx
*
dx
-
dy
*
dy
;
if
(
dist2
>
0
)
{
float
dist
=
sqrtf
(
dist2
);
minz
=
min
(
minz
,
atomPos
[
2
]
-
dist
);
maxz
=
max
(
maxz
,
atomPos
[
2
]
+
dist
);
fvec4
dist
=
sqrt
(
dist2
);
int
numToCheck
=
min
(
4
,
(
int
)
(
blockAtoms
.
size
()
-
k
));
for
(
int
m
=
0
;
m
<
numToCheck
;
m
++
)
{
minx
=
min
(
minx
,
blockAtomX
[
k
+
m
]
-
dist
[
m
]
-
xoffset
);
maxx
=
max
(
maxx
,
blockAtomX
[
k
+
m
]
+
dist
[
m
]
-
xoffset
);
}
}
if
(
min
z
==
max
z
)
if
(
min
x
==
max
x
)
continue
;
bool
needPeriodic
=
(
centerPos
[
0
]
-
blockWidth
[
0
]
<
maxDistance
||
centerPos
[
0
]
+
blockWidth
[
0
]
>
periodicBoxSize
[
0
]
-
maxDistance
||
centerPos
[
1
]
-
blockWidth
[
1
]
<
maxDistance
||
centerPos
[
1
]
+
blockWidth
[
1
]
>
periodicBoxSize
[
1
]
-
maxDistance
||
minz
<
0.0
f
||
maxz
>
periodicBoxSize
[
2
]);
bool
needPeriodic
=
(
centerPos
[
1
]
-
blockWidth
[
1
]
<
maxDistance
||
centerPos
[
1
]
+
blockWidth
[
1
]
>
periodicBoxSize
[
1
]
-
maxDistance
||
centerPos
[
2
]
-
blockWidth
[
2
]
<
maxDistance
||
centerPos
[
2
]
+
blockWidth
[
2
]
>
periodicBoxSize
[
2
]
-
maxDistance
||
minx
<
0.0
f
||
maxx
>
periodicBoxVectors
[
0
][
0
]);
int
numRanges
;
int
rangeStart
[
2
];
int
rangeEnd
[
2
];
rangeStart
[
0
]
=
findLowerBound
(
voxelIndex
.
x
,
voxelIndex
.
y
,
min
z
);
rangeStart
[
0
]
=
findLowerBound
(
voxelIndex
.
y
,
voxelIndex
.
z
,
min
x
);
if
(
needPeriodic
)
{
numRanges
=
2
;
rangeEnd
[
0
]
=
findUpperBound
(
voxelIndex
.
x
,
voxelIndex
.
y
,
max
z
);
rangeEnd
[
0
]
=
findUpperBound
(
voxelIndex
.
y
,
voxelIndex
.
z
,
max
x
);
if
(
rangeStart
[
0
]
>
0
)
{
rangeStart
[
1
]
=
0
;
rangeEnd
[
1
]
=
min
(
findUpperBound
(
voxelIndex
.
x
,
voxelIndex
.
y
,
max
z
-
periodicBoxSize
[
2
]),
rangeStart
[
0
]);
rangeEnd
[
1
]
=
min
(
findUpperBound
(
voxelIndex
.
y
,
voxelIndex
.
z
,
max
x
-
periodicBoxSize
[
0
]),
rangeStart
[
0
]);
}
else
{
rangeStart
[
1
]
=
max
(
findLowerBound
(
voxelIndex
.
x
,
voxelIndex
.
y
,
min
z
+
periodicBoxSize
[
2
]),
rangeEnd
[
0
]);
rangeEnd
[
1
]
=
bins
[
voxelIndex
.
x
][
voxelIndex
.
y
].
size
();
rangeStart
[
1
]
=
max
(
findLowerBound
(
voxelIndex
.
y
,
voxelIndex
.
z
,
min
x
+
periodicBoxSize
[
0
]),
rangeEnd
[
0
]);
rangeEnd
[
1
]
=
bins
[
voxelIndex
.
y
][
voxelIndex
.
z
].
size
();
}
}
else
{
numRanges
=
1
;
rangeEnd
[
0
]
=
findUpperBound
(
voxelIndex
.
x
,
voxelIndex
.
y
,
max
z
);
rangeEnd
[
0
]
=
findUpperBound
(
voxelIndex
.
y
,
voxelIndex
.
z
,
max
x
);
}
bool
periodicRectangular
=
(
needPeriodic
&&
!
triclinic
);
// Loop over atoms and check to see if they are neighbors of this block.
for
(
int
range
=
0
;
range
<
numRanges
;
range
++
)
{
for
(
int
item
=
rangeStart
[
range
];
item
<
rangeEnd
[
range
];
item
++
)
{
const
int
sortedIndex
=
bins
[
voxelIndex
.
x
][
voxelIndex
.
y
][
item
].
second
;
const
int
sortedIndex
=
bins
[
voxelIndex
.
y
][
voxelIndex
.
z
][
item
].
second
;
// Avoid duplicate entries.
if
(
sortedIndex
>=
lastSortedIndex
)
continue
;
fvec4
atomPos
(
atomLocations
+
4
*
sortedAtoms
[
sortedIndex
]);
fvec4
atomPos
(
&
sortedPositions
[
4
*
sortedIndex
]);
fvec4
delta
=
atomPos
-
centerPos
;
if
(
needPeriodic
)
{
fvec4
base
=
round
(
delta
*
invBoxSize
)
*
boxSize
;
delta
=
delta
-
base
;
if
(
periodicRectangular
)
delta
-=
round
(
delta
*
invBoxSize
)
*
boxSize
;
else
if
(
needPeriodic
)
{
delta
-=
periodicBoxVec4
[
2
]
*
floorf
(
delta
[
2
]
*
recipBoxSize
[
2
]
+
0.5
f
);
delta
-=
periodicBoxVec4
[
1
]
*
floorf
(
delta
[
1
]
*
recipBoxSize
[
1
]
+
0.5
f
);
delta
-=
periodicBoxVec4
[
0
]
*
floorf
(
delta
[
0
]
*
recipBoxSize
[
0
]
+
0.5
f
);
}
delta
=
max
(
0.0
f
,
abs
(
delta
)
-
blockWidth
);
float
dSquared
=
dot3
(
delta
,
delta
);
...
...
@@ -273,21 +318,34 @@ public:
// The distance is large enough that there might not be any actual interactions.
// Check individual atom pairs to be sure.
bool
any
=
false
;
for
(
int
k
=
0
;
k
<
(
int
)
blockAtoms
.
size
();
k
++
)
{
fvec4
pos1
(
&
atomLocations
[
4
*
blockAtoms
[
k
]]);
delta
=
atomPos
-
pos1
;
if
(
needPeriodic
)
{
fvec4
base
=
round
(
delta
*
invBoxSize
)
*
boxSize
;
delta
=
delta
-
base
;
}
float
r2
=
dot3
(
delta
,
delta
);
if
(
r2
<
maxDistanceSquared
)
{
any
=
true
;
bool
anyInteraction
=
false
;
for
(
int
k
=
0
;
k
<
(
int
)
blockAtoms
.
size
();
k
+=
4
)
{
fvec4
dx
=
fvec4
(
&
blockAtomX
[
k
])
-
atomPos
[
0
];
fvec4
dy
=
fvec4
(
&
blockAtomY
[
k
])
-
atomPos
[
1
];
fvec4
dz
=
fvec4
(
&
blockAtomZ
[
k
])
-
atomPos
[
2
];
if
(
periodicRectangular
)
{
dx
-=
round
(
dx
*
invBoxSize
[
0
])
*
boxSize
[
0
];
dy
-=
round
(
dy
*
invBoxSize
[
1
])
*
boxSize
[
1
];
dz
-=
round
(
dz
*
invBoxSize
[
2
])
*
boxSize
[
2
];
}
else
if
(
needPeriodic
)
{
fvec4
scale3
=
floor
(
dz
*
recipBoxSize
[
2
]
+
0.5
f
);
dx
-=
scale3
*
periodicBoxVectors
[
2
][
0
];
dy
-=
scale3
*
periodicBoxVectors
[
2
][
1
];
dz
-=
scale3
*
periodicBoxVectors
[
2
][
2
];
fvec4
scale2
=
floor
(
dy
*
recipBoxSize
[
1
]
+
0.5
f
);
dx
-=
scale2
*
periodicBoxVectors
[
1
][
0
];
dy
-=
scale2
*
periodicBoxVectors
[
1
][
1
];
fvec4
scale1
=
floor
(
dx
*
recipBoxSize
[
0
]
+
0.5
f
);
dx
-=
scale1
*
periodicBoxVectors
[
0
][
0
];
}
fvec4
r2
=
dx
*
dx
+
dy
*
dy
+
dz
*
dz
;
if
(
any
(
r2
<
maxDistanceSquared
))
{
anyInteraction
=
true
;
break
;
}
}
if
(
!
any
)
if
(
!
any
Interaction
)
continue
;
}
...
...
@@ -308,10 +366,12 @@ public:
private:
int
blockSize
;
float
voxelSizeX
,
voxelSizeY
;
float
minx
,
maxx
,
miny
,
maxy
;
int
nx
,
ny
;
const
float
*
periodicBoxSize
;
float
voxelSizeY
,
voxelSizeZ
;
float
miny
,
maxy
,
minz
,
maxz
;
int
ny
,
nz
;
float
periodicBoxSize
[
3
],
recipBoxSize
[
3
];
bool
triclinic
;
const
RealVec
*
periodicBoxVectors
;
const
bool
usePeriodic
;
vector
<
vector
<
vector
<
pair
<
float
,
int
>
>
>
>
bins
;
};
...
...
@@ -330,17 +390,20 @@ CpuNeighborList::CpuNeighborList(int blockSize) : blockSize(blockSize) {
}
void
CpuNeighborList
::
computeNeighborList
(
int
numAtoms
,
const
AlignedArray
<
float
>&
atomLocations
,
const
vector
<
set
<
int
>
>&
exclusions
,
const
float
*
periodicBox
Size
,
bool
usePeriodic
,
float
maxDistance
,
ThreadPool
&
threads
)
{
const
RealVec
*
periodicBox
Vectors
,
bool
usePeriodic
,
float
maxDistance
,
ThreadPool
&
threads
)
{
int
numBlocks
=
(
numAtoms
+
blockSize
-
1
)
/
blockSize
;
blockNeighbors
.
resize
(
numBlocks
);
blockExclusions
.
resize
(
numBlocks
);
sortedAtoms
.
resize
(
numAtoms
);
sortedPositions
.
resize
(
4
*
numAtoms
);
// Record the parameters for the threads.
this
->
exclusions
=
&
exclusions
;
this
->
atomLocations
=
&
atomLocations
[
0
];
this
->
periodicBoxSize
=
periodicBoxSize
;
this
->
periodicBoxVectors
[
0
]
=
periodicBoxVectors
[
0
];
this
->
periodicBoxVectors
[
1
]
=
periodicBoxVectors
[
1
];
this
->
periodicBoxVectors
[
2
]
=
periodicBoxVectors
[
2
];
this
->
numAtoms
=
numAtoms
;
this
->
usePeriodic
=
usePeriodic
;
this
->
maxDistance
=
maxDistance
;
...
...
@@ -371,17 +434,19 @@ void CpuNeighborList::computeNeighborList(int numAtoms, const AlignedArray<float
// Build the voxel hash.
float
edgeSize
X
,
edgeSize
Y
;
float
edgeSize
Y
,
edgeSize
Z
;
if
(
!
usePeriodic
)
edgeSize
X
=
edgeSize
Y
=
maxDistance
;
// TODO - adjust this as needed
edgeSize
Y
=
edgeSize
Z
=
maxDistance
;
// TODO - adjust this as needed
else
{
edgeSize
X
=
0.6
f
*
periodicBox
Size
[
0
]
/
floorf
(
periodicBox
Size
[
0
]
/
maxDistance
);
edgeSize
Y
=
0.6
f
*
periodicBox
Size
[
1
]
/
floorf
(
periodicBox
Size
[
1
]
/
maxDistance
);
edgeSize
Y
=
0.6
f
*
periodicBox
Vectors
[
1
][
1
]
/
floorf
(
periodicBox
Vectors
[
1
][
1
]
/
maxDistance
);
edgeSize
Z
=
0.6
f
*
periodicBox
Vectors
[
2
][
2
]
/
floorf
(
periodicBox
Vectors
[
2
][
2
]
/
maxDistance
);
}
Voxels
voxels
(
blockSize
,
edgeSize
X
,
edgeSize
Y
,
min
x
,
max
x
,
min
y
,
max
y
,
periodicBox
Size
,
usePeriodic
);
Voxels
voxels
(
blockSize
,
edgeSize
Y
,
edgeSize
Z
,
min
y
,
max
y
,
min
z
,
max
z
,
periodicBox
Vectors
,
usePeriodic
);
for
(
int
i
=
0
;
i
<
numAtoms
;
i
++
)
{
int
atomIndex
=
atomBins
[
i
].
second
;
sortedAtoms
[
i
]
=
atomIndex
;
fvec4
atomPos
(
&
atomLocations
[
4
*
atomIndex
]);
atomPos
.
store
(
&
sortedPositions
[
4
*
i
]);
voxels
.
insert
(
i
,
&
atomLocations
[
4
*
atomIndex
]);
}
voxels
.
sortItems
();
...
...
@@ -443,6 +508,7 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
int
numBlocks
=
blockNeighbors
.
size
();
vector
<
int
>
blockAtoms
;
vector
<
float
>
blockAtomX
(
blockSize
),
blockAtomY
(
blockSize
),
blockAtomZ
(
blockSize
);
vector
<
VoxelIndex
>
atomVoxelIndex
;
for
(
int
i
=
threadIndex
;
i
<
numBlocks
;
i
+=
numThreads
)
{
// Find the atoms in this block and compute their bounding box.
...
...
@@ -455,14 +521,24 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
blockAtoms
[
j
]
=
sortedAtoms
[
firstIndex
+
j
];
atomVoxelIndex
[
j
]
=
voxels
->
getVoxelIndex
(
&
atomLocations
[
4
*
blockAtoms
[
j
]]);
}
fvec4
minPos
(
&
atomLocations
[
4
*
sortedAtoms
[
firstIndex
]
]
);
fvec4
minPos
(
&
sortedPositions
[
4
*
firstIndex
]);
fvec4
maxPos
=
minPos
;
for
(
int
j
=
1
;
j
<
atomsInBlock
;
j
++
)
{
fvec4
pos
(
&
atomLocations
[
4
*
sortedAtoms
[
firstIndex
+
j
]
]);
fvec4
pos
(
&
sortedPositions
[
4
*
(
firstIndex
+
j
)
]);
minPos
=
min
(
minPos
,
pos
);
maxPos
=
max
(
maxPos
,
pos
);
}
voxels
->
getNeighbors
(
blockNeighbors
[
i
],
i
,
(
maxPos
+
minPos
)
*
0.5
f
,
(
maxPos
-
minPos
)
*
0.5
f
,
sortedAtoms
,
blockExclusions
[
i
],
maxDistance
,
blockAtoms
,
atomLocations
,
atomVoxelIndex
);
for
(
int
j
=
0
;
j
<
atomsInBlock
;
j
++
)
{
blockAtomX
[
j
]
=
sortedPositions
[
4
*
(
firstIndex
+
j
)];
blockAtomY
[
j
]
=
sortedPositions
[
4
*
(
firstIndex
+
j
)
+
1
];
blockAtomZ
[
j
]
=
sortedPositions
[
4
*
(
firstIndex
+
j
)
+
2
];
}
for
(
int
j
=
atomsInBlock
;
j
<
blockSize
;
j
++
)
{
blockAtomX
[
j
]
=
1e10
;
blockAtomY
[
j
]
=
1e10
;
blockAtomZ
[
j
]
=
1e10
;
}
voxels
->
getNeighbors
(
blockNeighbors
[
i
],
i
,
(
maxPos
+
minPos
)
*
0.5
f
,
(
maxPos
-
minPos
)
*
0.5
f
,
sortedAtoms
,
blockExclusions
[
i
],
maxDistance
,
blockAtoms
,
blockAtomX
,
blockAtomY
,
blockAtomZ
,
sortedPositions
,
atomVoxelIndex
);
// Record the exclusions for this block.
...
...
platforms/cpu/src/CpuNonbondedForce.cpp
View file @
61d5cc0f
...
...
@@ -24,7 +24,6 @@
#include <complex>
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMUtilities.h"
#include "CpuNonbondedForce.h"
#include "ReferenceForce.h"
...
...
@@ -103,20 +102,30 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
also been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
@param
boxSize the X, Y, and Z widths of
the periodic box
@param
periodicBoxVectors the vectors defining
the periodic box
--------------------------------------------------------------------------------------- */
void
CpuNonbondedForce
::
setPeriodic
(
float
*
periodicBox
Size
)
{
void
CpuNonbondedForce
::
setPeriodic
(
RealVec
*
periodicBox
Vectors
)
{
assert
(
cutoff
);
assert
(
periodicBox
Size
[
0
]
>=
2
*
cutoffDistance
);
assert
(
periodicBox
Size
[
1
]
>=
2
*
cutoffDistance
);
assert
(
periodicBox
Size
[
2
]
>=
2
*
cutoffDistance
);
assert
(
periodicBox
Vectors
[
0
]
[
0
]
>=
2
.0
*
cutoffDistance
);
assert
(
periodicBox
Vectors
[
1
]
[
1
]
>=
2
.0
*
cutoffDistance
);
assert
(
periodicBox
Vectors
[
2
]
[
2
]
>=
2
.0
*
cutoffDistance
);
periodic
=
true
;
this
->
periodicBoxSize
[
0
]
=
periodicBoxSize
[
0
];
this
->
periodicBoxSize
[
1
]
=
periodicBoxSize
[
1
];
this
->
periodicBoxSize
[
2
]
=
periodicBoxSize
[
2
];
this
->
periodicBoxVectors
[
0
]
=
periodicBoxVectors
[
0
];
this
->
periodicBoxVectors
[
1
]
=
periodicBoxVectors
[
1
];
this
->
periodicBoxVectors
[
2
]
=
periodicBoxVectors
[
2
];
recipBoxSize
[
0
]
=
(
float
)
(
1.0
/
periodicBoxVectors
[
0
][
0
]);
recipBoxSize
[
1
]
=
(
float
)
(
1.0
/
periodicBoxVectors
[
1
][
1
]);
recipBoxSize
[
2
]
=
(
float
)
(
1.0
/
periodicBoxVectors
[
2
][
2
]);
periodicBoxVec4
.
resize
(
3
);
periodicBoxVec4
[
0
]
=
fvec4
(
periodicBoxVectors
[
0
][
0
],
periodicBoxVectors
[
0
][
1
],
periodicBoxVectors
[
0
][
2
],
0
);
periodicBoxVec4
[
1
]
=
fvec4
(
periodicBoxVectors
[
1
][
0
],
periodicBoxVectors
[
1
][
1
],
periodicBoxVectors
[
1
][
2
],
0
);
periodicBoxVec4
[
2
]
=
fvec4
(
periodicBoxVectors
[
2
][
0
],
periodicBoxVectors
[
2
][
1
],
periodicBoxVectors
[
2
][
2
],
0
);
triclinic
=
(
periodicBoxVectors
[
0
][
1
]
!=
0.0
||
periodicBoxVectors
[
0
][
2
]
!=
0.0
||
periodicBoxVectors
[
1
][
0
]
!=
0.0
||
periodicBoxVectors
[
1
][
2
]
!=
0.0
||
periodicBoxVectors
[
2
][
0
]
!=
0.0
||
periodicBoxVectors
[
2
][
1
]
!=
0.0
);
}
/**---------------------------------------------------------------------------------------
...
...
@@ -186,18 +195,16 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
int
kmax
=
(
ewald
?
max
(
numRx
,
max
(
numRy
,
numRz
))
:
0
);
float
factorEwald
=
-
1
/
(
4
*
alphaEwald
*
alphaEwald
);
float
TWO_PI
=
2.0
*
PI_M
;
float
recipCoeff
=
(
float
)(
ONE_4PI_EPS0
*
4
*
PI_M
/
(
periodicBox
Size
[
0
]
*
periodicBox
Size
[
1
]
*
periodicBox
Size
[
2
])
/
epsilon
);
float
recipCoeff
=
(
float
)(
ONE_4PI_EPS0
*
4
*
PI_M
/
(
periodicBox
Vectors
[
0
]
[
0
]
*
periodicBox
Vectors
[
1
]
[
1
]
*
periodicBox
Vectors
[
2
]
[
2
])
/
epsilon
);
if
(
pme
)
{
pme_t
pmedata
;
RealOpenMM
virial
[
3
][
3
];
pme_init
(
&
pmedata
,
alphaEwald
,
numberOfAtoms
,
meshDim
,
5
,
1
);
vector
<
RealOpenMM
>
charges
(
numberOfAtoms
);
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
)
charges
[
i
]
=
posq
[
4
*
i
+
3
];
RealOpenMM
boxSize
[
3
]
=
{
periodicBoxSize
[
0
],
periodicBoxSize
[
1
],
periodicBoxSize
[
2
]};
RealOpenMM
recipEnergy
=
0.0
;
pme_exec
(
pmedata
,
atomCoordinates
,
forces
,
charges
,
boxSize
,
&
recipEnergy
,
virial
);
pme_exec
(
pmedata
,
atomCoordinates
,
forces
,
charges
,
periodicBoxVectors
,
&
recipEnergy
);
if
(
totalEnergy
)
*
totalEnergy
+=
recipEnergy
;
pme_destroy
(
pmedata
);
...
...
@@ -209,7 +216,7 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
// setup reciprocal box
float
recipBoxSize
[
3
]
=
{
TWO_PI
/
periodicBox
Size
[
0
],
TWO_PI
/
periodicBox
Size
[
1
],
TWO_PI
/
periodicBox
Size
[
2
]
};
float
recipBoxSize
[
3
]
=
{
(
float
)
(
TWO_PI
/
periodicBox
Vectors
[
0
][
0
]),
(
float
)
(
TWO_PI
/
periodicBox
Vectors
[
1
][
1
]),
(
float
)
(
TWO_PI
/
periodicBox
Vectors
[
2
][
2
])
};
// setup K-vectors
...
...
@@ -330,8 +337,8 @@ void CpuNonbondedForce::threadComputeDirect(ThreadPool& threads, int threadIndex
threadEnergy
[
threadIndex
]
=
0
;
double
*
energyPtr
=
(
includeEnergy
?
&
threadEnergy
[
threadIndex
]
:
NULL
);
float
*
forces
=
&
(
*
threadForce
)[
threadIndex
][
0
];
fvec4
boxSize
(
periodicBox
Size
[
0
],
periodicBox
Size
[
1
],
periodicBox
Size
[
2
],
0
);
fvec4
invBoxSize
(
(
1
/
periodic
BoxSize
[
0
]
)
,
(
1
/
periodic
BoxSize
[
1
]
)
,
(
1
/
periodic
BoxSize
[
2
]
)
,
0
);
fvec4
boxSize
(
periodicBox
Vectors
[
0
]
[
0
],
periodicBox
Vectors
[
1
]
[
1
],
periodicBox
Vectors
[
2
]
[
2
],
0
);
fvec4
invBoxSize
(
recip
BoxSize
[
0
],
recip
BoxSize
[
1
],
recip
BoxSize
[
2
],
0
);
if
(
ewald
||
pme
)
{
// Compute the interactions from the neighbor list.
...
...
@@ -344,8 +351,6 @@ void CpuNonbondedForce::threadComputeDirect(ThreadPool& threads, int threadIndex
// Now subtract off the exclusions, since they were implicitly included in the reciprocal space sum.
fvec4
boxSize
(
periodicBoxSize
[
0
],
periodicBoxSize
[
1
],
periodicBoxSize
[
2
],
0
);
fvec4
invBoxSize
((
1
/
periodicBoxSize
[
0
]),
(
1
/
periodicBoxSize
[
1
]),
(
1
/
periodicBoxSize
[
2
]),
0
);
for
(
int
i
=
threadIndex
;
i
<
numberOfAtoms
;
i
+=
numThreads
)
{
fvec4
posI
((
float
)
atomCoordinates
[
i
][
0
],
(
float
)
atomCoordinates
[
i
][
1
],
(
float
)
atomCoordinates
[
i
][
2
],
0.0
f
);
for
(
set
<
int
>::
const_iterator
iter
=
exclusions
[
i
].
begin
();
iter
!=
exclusions
[
i
].
end
();
++
iter
)
{
...
...
@@ -454,9 +459,16 @@ void CpuNonbondedForce::calculateOneIxn(int ii, int jj, float* forces, double* t
void
CpuNonbondedForce
::
getDeltaR
(
const
fvec4
&
posI
,
const
fvec4
&
posJ
,
fvec4
&
deltaR
,
float
&
r2
,
bool
periodic
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
{
deltaR
=
posJ
-
posI
;
if
(
periodic
)
{
if
(
triclinic
)
{
deltaR
-=
periodicBoxVec4
[
2
]
*
floorf
(
deltaR
[
2
]
*
recipBoxSize
[
2
]
+
0.5
f
);
deltaR
-=
periodicBoxVec4
[
1
]
*
floorf
(
deltaR
[
1
]
*
recipBoxSize
[
1
]
+
0.5
f
);
deltaR
-=
periodicBoxVec4
[
0
]
*
floorf
(
deltaR
[
0
]
*
recipBoxSize
[
0
]
+
0.5
f
);
}
else
{
fvec4
base
=
round
(
deltaR
*
invBoxSize
)
*
boxSize
;
deltaR
=
deltaR
-
base
;
}
}
r2
=
dot3
(
deltaR
,
deltaR
);
}
...
...
platforms/cpu/src/CpuNonbondedForceVec4.cpp
View file @
61d5cc0f
/* Portions copyright (c) 2006-201
3
Stanford University and Simbios.
/* Portions copyright (c) 2006-201
4
Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
...
...
@@ -22,7 +22,6 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMUtilities.h"
#include "CpuNonbondedForceVec4.h"
...
...
@@ -45,15 +44,68 @@ CpuNonbondedForce* createCpuNonbondedForceVec4() {
CpuNonbondedForceVec4
::
CpuNonbondedForceVec4
()
{
}
enum
PeriodicType
{
NoPeriodic
,
PeriodicPerAtom
,
PeriodicPerInteraction
,
PeriodicTriclinic
};
void
CpuNonbondedForceVec4
::
calculateBlockIxn
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
// Determine whether we need to apply periodic boundary conditions.
PeriodicType
periodicType
;
fvec4
blockCenter
;
if
(
!
periodic
)
{
periodicType
=
NoPeriodic
;
blockCenter
=
0.0
f
;
}
else
{
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
];
float
minx
,
maxx
,
miny
,
maxy
,
minz
,
maxz
;
minx
=
maxx
=
posq
[
4
*
blockAtom
[
0
]];
miny
=
maxy
=
posq
[
4
*
blockAtom
[
0
]
+
1
];
minz
=
maxz
=
posq
[
4
*
blockAtom
[
0
]
+
2
];
for
(
int
i
=
1
;
i
<
4
;
i
++
)
{
minx
=
min
(
minx
,
posq
[
4
*
blockAtom
[
i
]]);
maxx
=
max
(
maxx
,
posq
[
4
*
blockAtom
[
i
]]);
miny
=
min
(
miny
,
posq
[
4
*
blockAtom
[
i
]
+
1
]);
maxy
=
max
(
maxy
,
posq
[
4
*
blockAtom
[
i
]
+
1
]);
minz
=
min
(
minz
,
posq
[
4
*
blockAtom
[
i
]
+
2
]);
maxz
=
max
(
maxz
,
posq
[
4
*
blockAtom
[
i
]
+
2
]);
}
blockCenter
=
fvec4
(
0.5
f
*
(
minx
+
maxx
),
0.5
f
*
(
miny
+
maxy
),
0.5
f
*
(
minz
+
maxz
),
0.0
f
);
if
(
!
(
minx
<
cutoffDistance
||
miny
<
cutoffDistance
||
minz
<
cutoffDistance
||
maxx
>
boxSize
[
0
]
-
cutoffDistance
||
maxy
>
boxSize
[
1
]
-
cutoffDistance
||
maxz
>
boxSize
[
2
]
-
cutoffDistance
))
periodicType
=
NoPeriodic
;
else
if
(
triclinic
)
periodicType
=
PeriodicTriclinic
;
else
if
(
0.5
f
*
(
boxSize
[
0
]
-
(
maxx
-
minx
))
>=
cutoffDistance
&&
0.5
f
*
(
boxSize
[
1
]
-
(
maxy
-
miny
))
>=
cutoffDistance
&&
0.5
f
*
(
boxSize
[
2
]
-
(
maxz
-
minz
))
>=
cutoffDistance
)
periodicType
=
PeriodicPerAtom
;
else
periodicType
=
PeriodicPerInteraction
;
}
// Call the appropriate version depending on what calculation is required for periodic boundary conditions.
if
(
periodicType
==
NoPeriodic
)
calculateBlockIxnImpl
<
NoPeriodic
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicPerAtom
)
calculateBlockIxnImpl
<
PeriodicPerAtom
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicPerInteraction
)
calculateBlockIxnImpl
<
PeriodicPerInteraction
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicTriclinic
)
calculateBlockIxnImpl
<
PeriodicTriclinic
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
}
template
<
int
PERIODIC_TYPE
>
void
CpuNonbondedForceVec4
::
calculateBlockIxnImpl
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
,
const
fvec4
&
blockCenter
)
{
// Load the positions and parameters of the atoms in the block.
int
blockAtom
[
4
];
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
];
fvec4
blockAtomPosq
[
4
];
fvec4
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
blockAtom
[
i
]
=
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
+
i
];
blockAtomPosq
[
i
]
=
fvec4
(
posq
+
4
*
blockAtom
[
i
]);
if
(
PERIODIC_TYPE
==
PeriodicPerAtom
)
blockAtomPosq
[
i
]
-=
floor
((
blockAtomPosq
[
i
]
-
blockCenter
)
*
invBoxSize
+
0.5
f
)
*
boxSize
;
}
fvec4
blockAtomX
=
fvec4
(
blockAtomPosq
[
0
][
0
],
blockAtomPosq
[
1
][
0
],
blockAtomPosq
[
2
][
0
],
blockAtomPosq
[
3
][
0
]);
fvec4
blockAtomY
=
fvec4
(
blockAtomPosq
[
0
][
1
],
blockAtomPosq
[
1
][
1
],
blockAtomPosq
[
2
][
1
],
blockAtomPosq
[
3
][
1
]);
...
...
@@ -61,8 +113,7 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
fvec4
blockAtomCharge
=
fvec4
(
ONE_4PI_EPS0
)
*
fvec4
(
blockAtomPosq
[
0
][
3
],
blockAtomPosq
[
1
][
3
],
blockAtomPosq
[
2
][
3
],
blockAtomPosq
[
3
][
3
]);
fvec4
blockAtomSigma
(
atomParameters
[
blockAtom
[
0
]].
first
,
atomParameters
[
blockAtom
[
1
]].
first
,
atomParameters
[
blockAtom
[
2
]].
first
,
atomParameters
[
blockAtom
[
3
]].
first
);
fvec4
blockAtomEpsilon
(
atomParameters
[
blockAtom
[
0
]].
second
,
atomParameters
[
blockAtom
[
1
]].
second
,
atomParameters
[
blockAtom
[
2
]].
second
,
atomParameters
[
blockAtom
[
3
]].
second
);
bool
needPeriodic
=
(
periodic
&&
(
any
(
blockAtomX
<
cutoffDistance
)
||
any
(
blockAtomY
<
cutoffDistance
)
||
any
(
blockAtomZ
<
cutoffDistance
)
||
any
(
blockAtomX
>
boxSize
[
0
]
-
cutoffDistance
)
||
any
(
blockAtomY
>
boxSize
[
1
]
-
cutoffDistance
)
||
any
(
blockAtomZ
>
boxSize
[
2
]
-
cutoffDistance
)));
const
bool
needPeriodic
=
(
PERIODIC_TYPE
==
PeriodicPerInteraction
||
PERIODIC_TYPE
==
PeriodicTriclinic
);
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
// Loop over neighbors for this block.
...
...
@@ -77,7 +128,10 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
// Compute the distances to the block atoms.
fvec4
dx
,
dy
,
dz
,
r2
;
getDeltaR
(
posq
+
4
*
atom
,
blockAtomX
,
blockAtomY
,
blockAtomZ
,
dx
,
dy
,
dz
,
r2
,
needPeriodic
,
boxSize
,
invBoxSize
);
fvec4
atomPos
(
posq
+
4
*
atom
);
if
(
PERIODIC_TYPE
==
PeriodicPerAtom
)
atomPos
-=
floor
((
atomPos
-
blockCenter
)
*
invBoxSize
+
0.5
f
)
*
boxSize
;
getDeltaR
<
PERIODIC_TYPE
>
(
atomPos
,
blockAtomX
,
blockAtomY
,
blockAtomZ
,
dx
,
dy
,
dz
,
r2
,
needPeriodic
,
boxSize
,
invBoxSize
);
ivec4
include
;
char
excl
=
exclusions
[
i
];
if
(
excl
==
0
)
...
...
@@ -90,8 +144,7 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
// Compute the interactions.
fvec4
r
=
sqrt
(
r2
);
fvec4
inverseR
=
fvec4
(
1.0
f
)
/
r
;
fvec4
inverseR
=
rsqrt
(
r2
);
fvec4
energy
,
dEdR
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
if
(
atomEpsilon
!=
0.0
f
)
{
...
...
@@ -103,6 +156,7 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
dEdR
=
epsSig6
*
(
12.0
f
*
sig6
-
6.0
f
);
energy
=
epsSig6
*
(
sig6
-
1.0
f
);
if
(
useSwitch
)
{
fvec4
r
=
r2
*
inverseR
;
fvec4
t
=
blend
(
0.0
f
,
(
r
-
switchingDistance
)
*
invSwitchingInterval
,
r
>
switchingDistance
);
fvec4
switchValue
=
1
+
t
*
t
*
t
*
(
-
10.0
f
+
t
*
(
15.0
f
-
t
*
6.0
f
));
fvec4
switchDeriv
=
t
*
t
*
(
-
30.0
f
+
t
*
(
60.0
f
-
t
*
30.0
f
))
*
invSwitchingInterval
;
...
...
@@ -157,14 +211,65 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
}
void
CpuNonbondedForceVec4
::
calculateBlockEwaldIxn
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
// Determine whether we need to apply periodic boundary conditions.
PeriodicType
periodicType
;
fvec4
blockCenter
;
if
(
!
periodic
)
{
periodicType
=
NoPeriodic
;
blockCenter
=
0.0
f
;
}
else
{
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
];
float
minx
,
maxx
,
miny
,
maxy
,
minz
,
maxz
;
minx
=
maxx
=
posq
[
4
*
blockAtom
[
0
]];
miny
=
maxy
=
posq
[
4
*
blockAtom
[
0
]
+
1
];
minz
=
maxz
=
posq
[
4
*
blockAtom
[
0
]
+
2
];
for
(
int
i
=
1
;
i
<
4
;
i
++
)
{
minx
=
min
(
minx
,
posq
[
4
*
blockAtom
[
i
]]);
maxx
=
max
(
maxx
,
posq
[
4
*
blockAtom
[
i
]]);
miny
=
min
(
miny
,
posq
[
4
*
blockAtom
[
i
]
+
1
]);
maxy
=
max
(
maxy
,
posq
[
4
*
blockAtom
[
i
]
+
1
]);
minz
=
min
(
minz
,
posq
[
4
*
blockAtom
[
i
]
+
2
]);
maxz
=
max
(
maxz
,
posq
[
4
*
blockAtom
[
i
]
+
2
]);
}
blockCenter
=
fvec4
(
0.5
f
*
(
minx
+
maxx
),
0.5
f
*
(
miny
+
maxy
),
0.5
f
*
(
minz
+
maxz
),
0.0
f
);
if
(
!
(
minx
<
cutoffDistance
||
miny
<
cutoffDistance
||
minz
<
cutoffDistance
||
maxx
>
boxSize
[
0
]
-
cutoffDistance
||
maxy
>
boxSize
[
1
]
-
cutoffDistance
||
maxz
>
boxSize
[
2
]
-
cutoffDistance
))
periodicType
=
NoPeriodic
;
else
if
(
triclinic
)
periodicType
=
PeriodicTriclinic
;
else
if
(
0.5
f
*
(
boxSize
[
0
]
-
(
maxx
-
minx
))
>=
cutoffDistance
&&
0.5
f
*
(
boxSize
[
1
]
-
(
maxy
-
miny
))
>=
cutoffDistance
&&
0.5
f
*
(
boxSize
[
2
]
-
(
maxz
-
minz
))
>=
cutoffDistance
)
periodicType
=
PeriodicPerAtom
;
else
periodicType
=
PeriodicPerInteraction
;
}
// Call the appropriate version depending on what calculation is required for periodic boundary conditions.
if
(
periodicType
==
NoPeriodic
)
calculateBlockEwaldIxnImpl
<
NoPeriodic
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicPerAtom
)
calculateBlockEwaldIxnImpl
<
PeriodicPerAtom
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicPerInteraction
)
calculateBlockEwaldIxnImpl
<
PeriodicPerInteraction
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicTriclinic
)
calculateBlockEwaldIxnImpl
<
PeriodicTriclinic
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
}
template
<
int
PERIODIC_TYPE
>
void
CpuNonbondedForceVec4
::
calculateBlockEwaldIxnImpl
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
,
const
fvec4
&
blockCenter
)
{
// Load the positions and parameters of the atoms in the block.
int
blockAtom
[
4
];
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
];
fvec4
blockAtomPosq
[
4
];
fvec4
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
blockAtom
[
i
]
=
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
+
i
];
blockAtomPosq
[
i
]
=
fvec4
(
posq
+
4
*
blockAtom
[
i
]);
if
(
PERIODIC_TYPE
==
PeriodicPerAtom
)
blockAtomPosq
[
i
]
-=
floor
((
blockAtomPosq
[
i
]
-
blockCenter
)
*
invBoxSize
+
0.5
f
)
*
boxSize
;
}
fvec4
blockAtomX
=
fvec4
(
blockAtomPosq
[
0
][
0
],
blockAtomPosq
[
1
][
0
],
blockAtomPosq
[
2
][
0
],
blockAtomPosq
[
3
][
0
]);
fvec4
blockAtomY
=
fvec4
(
blockAtomPosq
[
0
][
1
],
blockAtomPosq
[
1
][
1
],
blockAtomPosq
[
2
][
1
],
blockAtomPosq
[
3
][
1
]);
...
...
@@ -172,8 +277,7 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
fvec4
blockAtomCharge
=
fvec4
(
ONE_4PI_EPS0
)
*
fvec4
(
blockAtomPosq
[
0
][
3
],
blockAtomPosq
[
1
][
3
],
blockAtomPosq
[
2
][
3
],
blockAtomPosq
[
3
][
3
]);
fvec4
blockAtomSigma
(
atomParameters
[
blockAtom
[
0
]].
first
,
atomParameters
[
blockAtom
[
1
]].
first
,
atomParameters
[
blockAtom
[
2
]].
first
,
atomParameters
[
blockAtom
[
3
]].
first
);
fvec4
blockAtomEpsilon
(
atomParameters
[
blockAtom
[
0
]].
second
,
atomParameters
[
blockAtom
[
1
]].
second
,
atomParameters
[
blockAtom
[
2
]].
second
,
atomParameters
[
blockAtom
[
3
]].
second
);
bool
needPeriodic
=
(
periodic
&&
(
any
(
blockAtomX
<
cutoffDistance
)
||
any
(
blockAtomY
<
cutoffDistance
)
||
any
(
blockAtomZ
<
cutoffDistance
)
||
any
(
blockAtomX
>
boxSize
[
0
]
-
cutoffDistance
)
||
any
(
blockAtomY
>
boxSize
[
1
]
-
cutoffDistance
)
||
any
(
blockAtomZ
>
boxSize
[
2
]
-
cutoffDistance
)));
const
bool
needPeriodic
=
(
PERIODIC_TYPE
==
PeriodicPerInteraction
||
PERIODIC_TYPE
==
PeriodicTriclinic
);
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
// Loop over neighbors for this block.
...
...
@@ -188,7 +292,10 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
// Compute the distances to the block atoms.
fvec4
dx
,
dy
,
dz
,
r2
;
getDeltaR
(
posq
+
4
*
atom
,
blockAtomX
,
blockAtomY
,
blockAtomZ
,
dx
,
dy
,
dz
,
r2
,
needPeriodic
,
boxSize
,
invBoxSize
);
fvec4
atomPos
(
posq
+
4
*
atom
);
if
(
PERIODIC_TYPE
==
PeriodicPerAtom
)
atomPos
-=
floor
((
atomPos
-
blockCenter
)
*
invBoxSize
+
0.5
f
)
*
boxSize
;
getDeltaR
<
PERIODIC_TYPE
>
(
atomPos
,
blockAtomX
,
blockAtomY
,
blockAtomZ
,
dx
,
dy
,
dz
,
r2
,
needPeriodic
,
boxSize
,
invBoxSize
);
ivec4
include
;
char
excl
=
exclusions
[
i
];
if
(
excl
==
0
)
...
...
@@ -201,8 +308,8 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
// Compute the interactions.
fvec4
r
=
sqrt
(
r2
);
fvec4
inverseR
=
fvec4
(
1.0
f
)
/
r
;
fvec4
inverseR
=
r
sqrt
(
r2
);
fvec4
r
=
r2
*
inverseR
;
fvec4
energy
,
dEdR
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
if
(
atomEpsilon
!=
0.0
f
)
{
...
...
@@ -261,11 +368,23 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
(
fvec4
(
forces
+
4
*
blockAtom
[
j
])
+
f
[
j
]).
store
(
forces
+
4
*
blockAtom
[
j
]);
}
void
CpuNonbondedForceVec4
::
getDeltaR
(
const
float
*
posI
,
const
fvec4
&
x
,
const
fvec4
&
y
,
const
fvec4
&
z
,
fvec4
&
dx
,
fvec4
&
dy
,
fvec4
&
dz
,
fvec4
&
r2
,
bool
periodic
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
{
template
<
int
PERIODIC_TYPE
>
void
CpuNonbondedForceVec4
::
getDeltaR
(
const
fvec4
&
posI
,
const
fvec4
&
x
,
const
fvec4
&
y
,
const
fvec4
&
z
,
fvec4
&
dx
,
fvec4
&
dy
,
fvec4
&
dz
,
fvec4
&
r2
,
bool
periodic
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
{
dx
=
x
-
posI
[
0
];
dy
=
y
-
posI
[
1
];
dz
=
z
-
posI
[
2
];
if
(
periodic
)
{
if
(
PERIODIC_TYPE
==
PeriodicTriclinic
)
{
fvec4
scale3
=
floor
(
dz
*
recipBoxSize
[
2
]
+
0.5
f
);
dx
-=
scale3
*
periodicBoxVectors
[
2
][
0
];
dy
-=
scale3
*
periodicBoxVectors
[
2
][
1
];
dz
-=
scale3
*
periodicBoxVectors
[
2
][
2
];
fvec4
scale2
=
floor
(
dy
*
recipBoxSize
[
1
]
+
0.5
f
);
dx
-=
scale2
*
periodicBoxVectors
[
1
][
0
];
dy
-=
scale2
*
periodicBoxVectors
[
1
][
1
];
fvec4
scale1
=
floor
(
dx
*
recipBoxSize
[
0
]
+
0.5
f
);
dx
-=
scale1
*
periodicBoxVectors
[
0
][
0
];
}
else
if
(
PERIODIC_TYPE
==
PeriodicPerInteraction
)
{
dx
-=
round
(
dx
*
invBoxSize
[
0
])
*
boxSize
[
0
];
dy
-=
round
(
dy
*
invBoxSize
[
1
])
*
boxSize
[
1
];
dz
-=
round
(
dz
*
invBoxSize
[
2
])
*
boxSize
[
2
];
...
...
platforms/cpu/src/CpuNonbondedForceVec8.cpp
View file @
61d5cc0f
/* Portions copyright (c) 2006-201
3
Stanford University and Simbios.
/* Portions copyright (c) 2006-201
4
Stanford University and Simbios.
* Contributors: Pande Group
*
* Permission is hereby granted, free of charge, to any person obtaining
...
...
@@ -22,7 +22,6 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMUtilities.h"
#include "CpuNonbondedForceVec8.h"
#include "openmm/OpenMMException.h"
...
...
@@ -31,6 +30,12 @@
using
namespace
std
;
using
namespace
OpenMM
;
#ifdef _MSC_VER
// Workaround for a compiler bug in Visual Studio 10. Hopefully we can remove this
// once we move to a later version.
#undef __AVX__
#endif
#ifndef __AVX__
bool
isVec8Supported
()
{
return
false
;
...
...
@@ -71,23 +76,75 @@ CpuNonbondedForce* createCpuNonbondedForceVec8() {
CpuNonbondedForceVec8
::
CpuNonbondedForceVec8
()
{
}
enum
PeriodicType
{
NoPeriodic
,
PeriodicPerAtom
,
PeriodicPerInteraction
,
PeriodicTriclinic
};
void
CpuNonbondedForceVec8
::
calculateBlockIxn
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
// Determine whether we need to apply periodic boundary conditions.
PeriodicType
periodicType
;
fvec4
blockCenter
;
if
(
!
periodic
)
{
periodicType
=
NoPeriodic
;
blockCenter
=
0.0
f
;
}
else
{
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
8
*
blockIndex
];
float
minx
,
maxx
,
miny
,
maxy
,
minz
,
maxz
;
minx
=
maxx
=
posq
[
4
*
blockAtom
[
0
]];
miny
=
maxy
=
posq
[
4
*
blockAtom
[
0
]
+
1
];
minz
=
maxz
=
posq
[
4
*
blockAtom
[
0
]
+
2
];
for
(
int
i
=
1
;
i
<
8
;
i
++
)
{
minx
=
min
(
minx
,
posq
[
4
*
blockAtom
[
i
]]);
maxx
=
max
(
maxx
,
posq
[
4
*
blockAtom
[
i
]]);
miny
=
min
(
miny
,
posq
[
4
*
blockAtom
[
i
]
+
1
]);
maxy
=
max
(
maxy
,
posq
[
4
*
blockAtom
[
i
]
+
1
]);
minz
=
min
(
minz
,
posq
[
4
*
blockAtom
[
i
]
+
2
]);
maxz
=
max
(
maxz
,
posq
[
4
*
blockAtom
[
i
]
+
2
]);
}
blockCenter
=
fvec4
(
0.5
f
*
(
minx
+
maxx
),
0.5
f
*
(
miny
+
maxy
),
0.5
f
*
(
minz
+
maxz
),
0.0
f
);
if
(
!
(
minx
<
cutoffDistance
||
miny
<
cutoffDistance
||
minz
<
cutoffDistance
||
maxx
>
boxSize
[
0
]
-
cutoffDistance
||
maxy
>
boxSize
[
1
]
-
cutoffDistance
||
maxz
>
boxSize
[
2
]
-
cutoffDistance
))
periodicType
=
NoPeriodic
;
else
if
(
triclinic
)
periodicType
=
PeriodicTriclinic
;
else
if
(
0.5
f
*
(
boxSize
[
0
]
-
(
maxx
-
minx
))
>=
cutoffDistance
&&
0.5
f
*
(
boxSize
[
1
]
-
(
maxy
-
miny
))
>=
cutoffDistance
&&
0.5
f
*
(
boxSize
[
2
]
-
(
maxz
-
minz
))
>=
cutoffDistance
)
periodicType
=
PeriodicPerAtom
;
else
periodicType
=
PeriodicPerInteraction
;
}
// Call the appropriate version depending on what calculation is required for periodic boundary conditions.
if
(
periodicType
==
NoPeriodic
)
calculateBlockIxnImpl
<
NoPeriodic
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicPerAtom
)
calculateBlockIxnImpl
<
PeriodicPerAtom
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicPerInteraction
)
calculateBlockIxnImpl
<
PeriodicPerInteraction
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicTriclinic
)
calculateBlockIxnImpl
<
PeriodicTriclinic
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
}
template
<
int
PERIODIC_TYPE
>
void
CpuNonbondedForceVec8
::
calculateBlockIxnImpl
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
,
const
fvec4
&
blockCenter
)
{
// Load the positions and parameters of the atoms in the block.
int
blockAtom
[
8
];
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
8
*
blockIndex
];
fvec4
blockAtomPosq
[
8
];
fvec8
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
fvec8
blockAtomX
,
blockAtomY
,
blockAtomZ
,
blockAtomCharge
;
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
blockAtom
[
i
]
=
neighborList
->
getSortedAtoms
()[
8
*
blockIndex
+
i
];
blockAtomPosq
[
i
]
=
fvec4
(
posq
+
4
*
blockAtom
[
i
]);
if
(
PERIODIC_TYPE
==
PeriodicPerAtom
)
blockAtomPosq
[
i
]
-=
floor
((
blockAtomPosq
[
i
]
-
blockCenter
)
*
invBoxSize
+
0.5
f
)
*
boxSize
;
}
transpose
(
blockAtomPosq
[
0
],
blockAtomPosq
[
1
],
blockAtomPosq
[
2
],
blockAtomPosq
[
3
],
blockAtomPosq
[
4
],
blockAtomPosq
[
5
],
blockAtomPosq
[
6
],
blockAtomPosq
[
7
],
blockAtomX
,
blockAtomY
,
blockAtomZ
,
blockAtomCharge
);
blockAtomCharge
*=
ONE_4PI_EPS0
;
fvec8
blockAtomSigma
(
atomParameters
[
blockAtom
[
0
]].
first
,
atomParameters
[
blockAtom
[
1
]].
first
,
atomParameters
[
blockAtom
[
2
]].
first
,
atomParameters
[
blockAtom
[
3
]].
first
,
atomParameters
[
blockAtom
[
4
]].
first
,
atomParameters
[
blockAtom
[
5
]].
first
,
atomParameters
[
blockAtom
[
6
]].
first
,
atomParameters
[
blockAtom
[
7
]].
first
);
fvec8
blockAtomEpsilon
(
atomParameters
[
blockAtom
[
0
]].
second
,
atomParameters
[
blockAtom
[
1
]].
second
,
atomParameters
[
blockAtom
[
2
]].
second
,
atomParameters
[
blockAtom
[
3
]].
second
,
atomParameters
[
blockAtom
[
4
]].
second
,
atomParameters
[
blockAtom
[
5
]].
second
,
atomParameters
[
blockAtom
[
6
]].
second
,
atomParameters
[
blockAtom
[
7
]].
second
);
bool
needPeriodic
=
(
periodic
&&
(
any
(
blockAtomX
<
cutoffDistance
)
||
any
(
blockAtomY
<
cutoffDistance
)
||
any
(
blockAtomZ
<
cutoffDistance
)
||
any
(
blockAtomX
>
boxSize
[
0
]
-
cutoffDistance
)
||
any
(
blockAtomY
>
boxSize
[
1
]
-
cutoffDistance
)
||
any
(
blockAtomZ
>
boxSize
[
2
]
-
cutoffDistance
)));
const
bool
needPeriodic
=
(
PERIODIC_TYPE
==
PeriodicPerInteraction
||
PERIODIC_TYPE
==
PeriodicTriclinic
);
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
// Loop over neighbors for this block.
...
...
@@ -102,7 +159,10 @@ void CpuNonbondedForceVec8::calculateBlockIxn(int blockIndex, float* forces, dou
// Compute the distances to the block atoms.
fvec8
dx
,
dy
,
dz
,
r2
;
getDeltaR
(
&
posq
[
4
*
atom
],
blockAtomX
,
blockAtomY
,
blockAtomZ
,
dx
,
dy
,
dz
,
r2
,
needPeriodic
,
boxSize
,
invBoxSize
);
fvec4
atomPos
(
posq
+
4
*
atom
);
if
(
PERIODIC_TYPE
==
PeriodicPerAtom
)
atomPos
-=
floor
((
atomPos
-
blockCenter
)
*
invBoxSize
+
0.5
f
)
*
boxSize
;
getDeltaR
<
PERIODIC_TYPE
>
(
atomPos
,
blockAtomX
,
blockAtomY
,
blockAtomZ
,
dx
,
dy
,
dz
,
r2
,
needPeriodic
,
boxSize
,
invBoxSize
);
ivec8
include
;
char
excl
=
exclusions
[
i
];
if
(
excl
==
0
)
...
...
@@ -115,8 +175,7 @@ void CpuNonbondedForceVec8::calculateBlockIxn(int blockIndex, float* forces, dou
// Compute the interactions.
fvec8
r
=
sqrt
(
r2
);
fvec8
inverseR
=
fvec8
(
1.0
f
)
/
r
;
fvec8
inverseR
=
rsqrt
(
r2
);
fvec8
energy
,
dEdR
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
if
(
atomEpsilon
!=
0.0
f
)
{
...
...
@@ -128,6 +187,7 @@ void CpuNonbondedForceVec8::calculateBlockIxn(int blockIndex, float* forces, dou
dEdR
=
epsSig6
*
(
12.0
f
*
sig6
-
6.0
f
);
energy
=
epsSig6
*
(
sig6
-
1.0
f
);
if
(
useSwitch
)
{
fvec8
r
=
r2
*
inverseR
;
fvec8
t
=
(
r
>
switchingDistance
)
&
((
r
-
switchingDistance
)
*
invSwitchingInterval
);
fvec8
switchValue
=
1
+
t
*
t
*
t
*
(
-
10.0
f
+
t
*
(
15.0
f
-
t
*
6.0
f
));
fvec8
switchDeriv
=
t
*
t
*
(
-
30.0
f
+
t
*
(
60.0
f
-
t
*
30.0
f
))
*
invSwitchingInterval
;
...
...
@@ -182,22 +242,72 @@ void CpuNonbondedForceVec8::calculateBlockIxn(int blockIndex, float* forces, dou
}
void
CpuNonbondedForceVec8
::
calculateBlockEwaldIxn
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
// Determine whether we need to apply periodic boundary conditions.
PeriodicType
periodicType
;
fvec4
blockCenter
;
if
(
!
periodic
)
{
periodicType
=
NoPeriodic
;
blockCenter
=
0.0
f
;
}
else
{
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
8
*
blockIndex
];
float
minx
,
maxx
,
miny
,
maxy
,
minz
,
maxz
;
minx
=
maxx
=
posq
[
4
*
blockAtom
[
0
]];
miny
=
maxy
=
posq
[
4
*
blockAtom
[
0
]
+
1
];
minz
=
maxz
=
posq
[
4
*
blockAtom
[
0
]
+
2
];
for
(
int
i
=
1
;
i
<
8
;
i
++
)
{
minx
=
min
(
minx
,
posq
[
4
*
blockAtom
[
i
]]);
maxx
=
max
(
maxx
,
posq
[
4
*
blockAtom
[
i
]]);
miny
=
min
(
miny
,
posq
[
4
*
blockAtom
[
i
]
+
1
]);
maxy
=
max
(
maxy
,
posq
[
4
*
blockAtom
[
i
]
+
1
]);
minz
=
min
(
minz
,
posq
[
4
*
blockAtom
[
i
]
+
2
]);
maxz
=
max
(
maxz
,
posq
[
4
*
blockAtom
[
i
]
+
2
]);
}
blockCenter
=
fvec4
(
0.5
f
*
(
minx
+
maxx
),
0.5
f
*
(
miny
+
maxy
),
0.5
f
*
(
minz
+
maxz
),
0.0
f
);
if
(
!
(
minx
<
cutoffDistance
||
miny
<
cutoffDistance
||
minz
<
cutoffDistance
||
maxx
>
boxSize
[
0
]
-
cutoffDistance
||
maxy
>
boxSize
[
1
]
-
cutoffDistance
||
maxz
>
boxSize
[
2
]
-
cutoffDistance
))
periodicType
=
NoPeriodic
;
else
if
(
triclinic
)
periodicType
=
PeriodicTriclinic
;
else
if
(
0.5
f
*
(
boxSize
[
0
]
-
(
maxx
-
minx
))
>=
cutoffDistance
&&
0.5
f
*
(
boxSize
[
1
]
-
(
maxy
-
miny
))
>=
cutoffDistance
&&
0.5
f
*
(
boxSize
[
2
]
-
(
maxz
-
minz
))
>=
cutoffDistance
)
periodicType
=
PeriodicPerAtom
;
else
periodicType
=
PeriodicPerInteraction
;
}
// Call the appropriate version depending on what calculation is required for periodic boundary conditions.
if
(
periodicType
==
NoPeriodic
)
calculateBlockEwaldIxnImpl
<
NoPeriodic
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicPerAtom
)
calculateBlockEwaldIxnImpl
<
PeriodicPerAtom
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicPerInteraction
)
calculateBlockEwaldIxnImpl
<
PeriodicPerInteraction
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
else
if
(
periodicType
==
PeriodicTriclinic
)
calculateBlockEwaldIxnImpl
<
PeriodicTriclinic
>
(
blockIndex
,
forces
,
totalEnergy
,
boxSize
,
invBoxSize
,
blockCenter
);
}
template
<
int
PERIODIC_TYPE
>
void
CpuNonbondedForceVec8
::
calculateBlockEwaldIxnImpl
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
,
const
fvec4
&
blockCenter
)
{
// Load the positions and parameters of the atoms in the block.
int
blockAtom
[
8
];
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
8
*
blockIndex
];
fvec4
blockAtomPosq
[
8
];
fvec8
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
fvec8
blockAtomX
,
blockAtomY
,
blockAtomZ
,
blockAtomCharge
;
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
blockAtom
[
i
]
=
neighborList
->
getSortedAtoms
()[
8
*
blockIndex
+
i
];
blockAtomPosq
[
i
]
=
fvec4
(
posq
+
4
*
blockAtom
[
i
]);
if
(
PERIODIC_TYPE
==
PeriodicPerAtom
)
blockAtomPosq
[
i
]
-=
floor
((
blockAtomPosq
[
i
]
-
blockCenter
)
*
invBoxSize
+
0.5
f
)
*
boxSize
;
}
transpose
(
blockAtomPosq
[
0
],
blockAtomPosq
[
1
],
blockAtomPosq
[
2
],
blockAtomPosq
[
3
],
blockAtomPosq
[
4
],
blockAtomPosq
[
5
],
blockAtomPosq
[
6
],
blockAtomPosq
[
7
],
blockAtomX
,
blockAtomY
,
blockAtomZ
,
blockAtomCharge
);
blockAtomCharge
*=
ONE_4PI_EPS0
;
fvec8
blockAtomSigma
(
atomParameters
[
blockAtom
[
0
]].
first
,
atomParameters
[
blockAtom
[
1
]].
first
,
atomParameters
[
blockAtom
[
2
]].
first
,
atomParameters
[
blockAtom
[
3
]].
first
,
atomParameters
[
blockAtom
[
4
]].
first
,
atomParameters
[
blockAtom
[
5
]].
first
,
atomParameters
[
blockAtom
[
6
]].
first
,
atomParameters
[
blockAtom
[
7
]].
first
);
fvec8
blockAtomEpsilon
(
atomParameters
[
blockAtom
[
0
]].
second
,
atomParameters
[
blockAtom
[
1
]].
second
,
atomParameters
[
blockAtom
[
2
]].
second
,
atomParameters
[
blockAtom
[
3
]].
second
,
atomParameters
[
blockAtom
[
4
]].
second
,
atomParameters
[
blockAtom
[
5
]].
second
,
atomParameters
[
blockAtom
[
6
]].
second
,
atomParameters
[
blockAtom
[
7
]].
second
);
bool
needPeriodic
=
(
periodic
&&
(
any
(
blockAtomX
<
cutoffDistance
)
||
any
(
blockAtomY
<
cutoffDistance
)
||
any
(
blockAtomZ
<
cutoffDistance
)
||
any
(
blockAtomX
>
boxSize
[
0
]
-
cutoffDistance
)
||
any
(
blockAtomY
>
boxSize
[
1
]
-
cutoffDistance
)
||
any
(
blockAtomZ
>
boxSize
[
2
]
-
cutoffDistance
)));
const
bool
needPeriodic
=
(
PERIODIC_TYPE
==
PeriodicPerInteraction
||
PERIODIC_TYPE
==
PeriodicTriclinic
);
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
// Loop over neighbors for this block.
...
...
@@ -212,7 +322,10 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
// Compute the distances to the block atoms.
fvec8
dx
,
dy
,
dz
,
r2
;
getDeltaR
(
&
posq
[
4
*
atom
],
blockAtomX
,
blockAtomY
,
blockAtomZ
,
dx
,
dy
,
dz
,
r2
,
needPeriodic
,
boxSize
,
invBoxSize
);
fvec4
atomPos
(
posq
+
4
*
atom
);
if
(
PERIODIC_TYPE
==
PeriodicPerAtom
)
atomPos
-=
floor
((
atomPos
-
blockCenter
)
*
invBoxSize
+
0.5
f
)
*
boxSize
;
getDeltaR
<
PERIODIC_TYPE
>
(
atomPos
,
blockAtomX
,
blockAtomY
,
blockAtomZ
,
dx
,
dy
,
dz
,
r2
,
needPeriodic
,
boxSize
,
invBoxSize
);
ivec8
include
;
char
excl
=
exclusions
[
i
];
if
(
excl
==
0
)
...
...
@@ -225,8 +338,8 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
// Compute the interactions.
fvec8
r
=
sqrt
(
r2
);
fvec8
inverseR
=
fvec8
(
1.0
f
)
/
r
;
fvec8
inverseR
=
r
sqrt
(
r2
);
fvec8
r
=
r2
*
inverseR
;
fvec8
energy
,
dEdR
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
if
(
atomEpsilon
!=
0.0
f
)
{
...
...
@@ -285,11 +398,23 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
(
fvec4
(
forces
+
4
*
blockAtom
[
j
])
+
f
[
j
]).
store
(
forces
+
4
*
blockAtom
[
j
]);
}
void
CpuNonbondedForceVec8
::
getDeltaR
(
const
float
*
posI
,
const
fvec8
&
x
,
const
fvec8
&
y
,
const
fvec8
&
z
,
fvec8
&
dx
,
fvec8
&
dy
,
fvec8
&
dz
,
fvec8
&
r2
,
bool
periodic
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
{
template
<
int
PERIODIC_TYPE
>
void
CpuNonbondedForceVec8
::
getDeltaR
(
const
fvec4
&
posI
,
const
fvec8
&
x
,
const
fvec8
&
y
,
const
fvec8
&
z
,
fvec8
&
dx
,
fvec8
&
dy
,
fvec8
&
dz
,
fvec8
&
r2
,
bool
periodic
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
{
dx
=
x
-
posI
[
0
];
dy
=
y
-
posI
[
1
];
dz
=
z
-
posI
[
2
];
if
(
periodic
)
{
if
(
PERIODIC_TYPE
==
PeriodicTriclinic
)
{
fvec8
scale3
=
floor
(
dz
*
recipBoxSize
[
2
]
+
0.5
f
);
dx
-=
scale3
*
periodicBoxVectors
[
2
][
0
];
dy
-=
scale3
*
periodicBoxVectors
[
2
][
1
];
dz
-=
scale3
*
periodicBoxVectors
[
2
][
2
];
fvec8
scale2
=
floor
(
dy
*
recipBoxSize
[
1
]
+
0.5
f
);
dx
-=
scale2
*
periodicBoxVectors
[
1
][
0
];
dy
-=
scale2
*
periodicBoxVectors
[
1
][
1
];
fvec8
scale1
=
floor
(
dx
*
recipBoxSize
[
0
]
+
0.5
f
);
dx
-=
scale1
*
periodicBoxVectors
[
0
][
0
];
}
else
if
(
PERIODIC_TYPE
==
PeriodicPerInteraction
)
{
dx
-=
round
(
dx
*
invBoxSize
[
0
])
*
boxSize
[
0
];
dy
-=
round
(
dy
*
invBoxSize
[
1
])
*
boxSize
[
1
];
dz
-=
round
(
dz
*
invBoxSize
[
2
])
*
boxSize
[
2
];
...
...
platforms/cpu/src/CpuPlatform.cpp
View file @
61d5cc0f
...
...
@@ -67,6 +67,7 @@ CpuPlatform::CpuPlatform() {
registerKernelFactory
(
CalcCustomNonbondedForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomManyParticleForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcGBSAOBCForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomGBForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinStepKernel
::
Name
(),
factory
);
platformProperties
.
push_back
(
CpuThreads
());
int
threads
=
getNumProcessors
();
...
...
platforms/cpu/src/CpuRandom.cpp
View file @
61d5cc0f
...
...
@@ -23,6 +23,7 @@
*/
#include "CpuRandom.h"
#include "openmm/internal/OSRngSeed.h"
#include "openmm/OpenMMException.h"
#include <cmath>
...
...
@@ -49,9 +50,13 @@ void CpuRandom::initialize(int seed, int numThreads) {
nextGaussian
.
resize
(
numThreads
);
nextGaussianIsValid
.
resize
(
numThreads
,
false
);
// Use a quick and dirty RNG to pick seeds for the real random number generator.
/* Use a quick and dirty RNG to pick seeds for the real random number generator.
* A random seed of 0 means pick a unique seed
*/
unsigned
int
r
=
(
unsigned
int
)
seed
;
if
(
r
==
0
)
r
=
(
unsigned
int
)
osrngseed
();
for
(
int
i
=
0
;
i
<
numThreads
;
i
++
)
{
r
=
(
1664525
*
r
+
1013904223
)
&
0xFFFFFFFF
;
threadRandom
[
i
]
=
new
OpenMM_SFMT
::
SFMT
();
...
...
platforms/cpu/tests/TestCpuCustomGBForce.cpp
0 → 100644
View file @
61d5cc0f
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2014 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
/**
* This tests all the different force terms in the reference implementation of CustomGBForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "sfmt/SFMT.h"
#include "openmm/Context.h"
#include "CpuPlatform.h"
#include "openmm/CustomGBForce.h"
#include "openmm/GBSAOBCForce.h"
#include "openmm/GBVIForce.h"
#include "openmm/OpenMMException.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include <iostream>
#include <vector>
#include <algorithm>
using
namespace
OpenMM
;
using
namespace
std
;
const
double
TOL
=
1e-5
;
void
testOBC
(
GBSAOBCForce
::
NonbondedMethod
obcMethod
,
CustomGBForce
::
NonbondedMethod
customMethod
)
{
const
int
numMolecules
=
70
;
const
int
numParticles
=
numMolecules
*
2
;
const
double
boxSize
=
10.0
;
const
double
cutoff
=
2.0
;
CpuPlatform
platform
;
// Create two systems: one with a GBSAOBCForce, and one using a CustomGBForce to implement the same interaction.
System
standardSystem
;
System
customSystem
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
standardSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
}
standardSystem
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0.0
,
0.0
),
Vec3
(
0.0
,
boxSize
,
0.0
),
Vec3
(
0.0
,
0.0
,
boxSize
));
customSystem
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0.0
,
0.0
),
Vec3
(
0.0
,
boxSize
,
0.0
),
Vec3
(
0.0
,
0.0
,
boxSize
));
GBSAOBCForce
*
obc
=
new
GBSAOBCForce
();
CustomGBForce
*
custom
=
new
CustomGBForce
();
obc
->
setCutoffDistance
(
cutoff
);
custom
->
setCutoffDistance
(
cutoff
);
custom
->
addPerParticleParameter
(
"q"
);
custom
->
addPerParticleParameter
(
"radius"
);
custom
->
addPerParticleParameter
(
"scale"
);
custom
->
addGlobalParameter
(
"solventDielectric"
,
obc
->
getSolventDielectric
());
custom
->
addGlobalParameter
(
"soluteDielectric"
,
obc
->
getSoluteDielectric
());
custom
->
addComputedValue
(
"I"
,
"step(r+sr2-or1)*0.5*(1/L-1/U+0.25*(1/U^2-1/L^2)*(r-sr2*sr2/r)+0.5*log(L/U)/r+C);"
"U=r+sr2;"
"C=2*(1/or1-1/L)*step(sr2-r-or1);"
"L=max(or1, D);"
"D=abs(r-sr2);"
"sr2 = scale2*or2;"
"or1 = radius1-0.009; or2 = radius2-0.009"
,
CustomGBForce
::
ParticlePairNoExclusions
);
custom
->
addComputedValue
(
"B"
,
"1/(1/or-tanh(1*psi-0.8*psi^2+4.85*psi^3)/radius);"
"psi=I*or; or=radius-0.009"
,
CustomGBForce
::
SingleParticle
);
custom
->
addEnergyTerm
(
"28.3919551*(radius+0.14)^2*(radius/B)^6-0.5*138.935485*(1/soluteDielectric-1/solventDielectric)*q^2/B"
,
CustomGBForce
::
SingleParticle
);
string
invCutoffString
=
""
;
if
(
obcMethod
!=
GBSAOBCForce
::
NoCutoff
)
{
stringstream
s
;
s
<<
(
1.0
/
cutoff
);
invCutoffString
=
s
.
str
();
}
custom
->
addEnergyTerm
(
"138.935485*(1/soluteDielectric-1/solventDielectric)*q1*q2*("
+
invCutoffString
+
"-1/f);"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))"
,
CustomGBForce
::
ParticlePairNoExclusions
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
double
>
params
(
3
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
if
(
i
<
numMolecules
/
2
)
{
obc
->
addParticle
(
1.0
,
0.2
,
0.5
);
params
[
0
]
=
1.0
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.5
;
custom
->
addParticle
(
params
);
obc
->
addParticle
(
-
1.0
,
0.1
,
0.5
);
params
[
0
]
=
-
1.0
;
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
else
{
obc
->
addParticle
(
1.0
,
0.2
,
0.8
);
params
[
0
]
=
1.0
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.8
;
custom
->
addParticle
(
params
);
obc
->
addParticle
(
-
1.0
,
0.1
,
0.8
);
params
[
0
]
=
-
1.0
;
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
positions
[
2
*
i
]
=
Vec3
(
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
));
positions
[
2
*
i
+
1
]
=
Vec3
(
positions
[
2
*
i
][
0
]
+
1.0
,
positions
[
2
*
i
][
1
],
positions
[
2
*
i
][
2
]);
velocities
[
2
*
i
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
velocities
[
2
*
i
+
1
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
}
obc
->
setNonbondedMethod
(
obcMethod
);
custom
->
setNonbondedMethod
(
customMethod
);
standardSystem
.
addForce
(
obc
);
customSystem
.
addForce
(
custom
);
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
context1
(
standardSystem
,
integrator1
,
platform
);
context1
.
setPositions
(
positions
);
context1
.
setVelocities
(
velocities
);
State
state1
=
context1
.
getState
(
State
::
Forces
|
State
::
Energy
);
Context
context2
(
customSystem
,
integrator2
,
platform
);
context2
.
setPositions
(
positions
);
context2
.
setVelocities
(
velocities
);
State
state2
=
context2
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
state1
.
getPotentialEnergy
(),
state2
.
getPotentialEnergy
(),
1e-4
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state2
.
getForces
()[
i
],
1e-4
);
}
// Try changing the particle parameters and make sure it's still correct.
for
(
int
i
=
0
;
i
<
numMolecules
/
2
;
i
++
)
{
obc
->
setParticleParameters
(
2
*
i
,
1.1
,
0.3
,
0.6
);
params
[
0
]
=
1.1
;
params
[
1
]
=
0.3
;
params
[
2
]
=
0.6
;
custom
->
setParticleParameters
(
2
*
i
,
params
);
obc
->
setParticleParameters
(
2
*
i
+
1
,
-
1.1
,
0.2
,
0.4
);
params
[
0
]
=
-
1.1
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.4
;
custom
->
setParticleParameters
(
2
*
i
+
1
,
params
);
}
obc
->
updateParametersInContext
(
context1
);
custom
->
updateParametersInContext
(
context2
);
state1
=
context1
.
getState
(
State
::
Forces
|
State
::
Energy
);
state2
=
context2
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
state1
.
getPotentialEnergy
(),
state2
.
getPotentialEnergy
(),
1e-4
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state2
.
getForces
()[
i
],
1e-4
);
}
}
void
testMembrane
()
{
const
int
numMolecules
=
70
;
const
int
numParticles
=
numMolecules
*
2
;
const
double
boxSize
=
10.0
;
CpuPlatform
platform
;
// Create a system with an implicit membrane.
System
system
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
}
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0.0
,
0.0
),
Vec3
(
0.0
,
boxSize
,
0.0
),
Vec3
(
0.0
,
0.0
,
boxSize
));
CustomGBForce
*
custom
=
new
CustomGBForce
();
custom
->
setCutoffDistance
(
2.0
);
custom
->
addPerParticleParameter
(
"q"
);
custom
->
addPerParticleParameter
(
"radius"
);
custom
->
addPerParticleParameter
(
"scale"
);
custom
->
addGlobalParameter
(
"thickness"
,
3
);
custom
->
addGlobalParameter
(
"solventDielectric"
,
78.3
);
custom
->
addGlobalParameter
(
"soluteDielectric"
,
1
);
custom
->
addComputedValue
(
"Imol"
,
"step(r+sr2-or1)*0.5*(1/L-1/U+0.25*(1/U^2-1/L^2)*(r-sr2*sr2/r)+0.5*log(L/U)/r+C);"
"U=r+sr2;"
"C=2*(1/or1-1/L)*step(sr2-r-or1);"
"L=max(or1, D);"
"D=abs(r-sr2);"
"sr2 = scale2*or2;"
"or1 = radius1-0.009; or2 = radius2-0.009"
,
CustomGBForce
::
ParticlePairNoExclusions
);
custom
->
addComputedValue
(
"Imem"
,
"(1/radius+2*log(2)/thickness)/(1+exp(7.2*(abs(z)+radius-0.5*thickness)))"
,
CustomGBForce
::
SingleParticle
);
custom
->
addComputedValue
(
"B"
,
"1/(1/or-tanh(1*psi-0.8*psi^2+4.85*psi^3)/radius);"
"psi=max(Imol,Imem)*or; or=radius-0.009"
,
CustomGBForce
::
SingleParticle
);
custom
->
addEnergyTerm
(
"28.3919551*(radius+0.14)^2*(radius/B)^6-0.5*138.935456*(1/soluteDielectric-1/solventDielectric)*q^2/B"
,
CustomGBForce
::
SingleParticle
);
custom
->
addEnergyTerm
(
"-138.935456*(1/soluteDielectric-1/solventDielectric)*q1*q2/f;"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))"
,
CustomGBForce
::
ParticlePairNoExclusions
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
double
>
params
(
3
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
if
(
i
<
numMolecules
/
2
)
{
params
[
0
]
=
1.0
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.5
;
custom
->
addParticle
(
params
);
params
[
0
]
=
-
1.0
;
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
else
{
params
[
0
]
=
1.0
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.8
;
custom
->
addParticle
(
params
);
params
[
0
]
=
-
1.0
;
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
positions
[
2
*
i
]
=
Vec3
(
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
));
positions
[
2
*
i
+
1
]
=
Vec3
(
positions
[
2
*
i
][
0
]
+
1.0
,
positions
[
2
*
i
][
1
],
positions
[
2
*
i
][
2
]);
velocities
[
2
*
i
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
velocities
[
2
*
i
+
1
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
}
system
.
addForce
(
custom
);
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
double
norm
=
0.0
;
for
(
int
i
=
0
;
i
<
(
int
)
forces
.
size
();
++
i
)
norm
+=
forces
[
i
].
dot
(
forces
[
i
]);
norm
=
std
::
sqrt
(
norm
);
const
double
stepSize
=
1e-2
;
double
step
=
0.5
*
stepSize
/
norm
;
vector
<
Vec3
>
positions2
(
numParticles
),
positions3
(
numParticles
);
for
(
int
i
=
0
;
i
<
(
int
)
positions
.
size
();
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
forces
[
i
];
positions2
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
positions3
[
i
]
=
Vec3
(
p
[
0
]
+
f
[
0
]
*
step
,
p
[
1
]
+
f
[
1
]
*
step
,
p
[
2
]
+
f
[
2
]
*
step
);
}
context
.
setPositions
(
positions2
);
State
state2
=
context
.
getState
(
State
::
Energy
);
context
.
setPositions
(
positions3
);
State
state3
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
state2
.
getPotentialEnergy
()
-
state3
.
getPotentialEnergy
())
/
stepSize
,
1e-3
);
}
void
testTabulatedFunction
()
{
CpuPlatform
platform
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomGBForce
*
force
=
new
CustomGBForce
();
force
->
addComputedValue
(
"a"
,
"0"
,
CustomGBForce
::
ParticlePair
);
force
->
addEnergyTerm
(
"fn(r)+1"
,
CustomGBForce
::
ParticlePair
);
force
->
addParticle
(
vector
<
double
>
());
force
->
addParticle
(
vector
<
double
>
());
vector
<
double
>
table
;
for
(
int
i
=
0
;
i
<
21
;
i
++
)
table
.
push_back
(
std
::
sin
(
0.25
*
i
));
force
->
addTabulatedFunction
(
"fn"
,
new
Continuous1DFunction
(
table
,
1.0
,
6.0
));
system
.
addForce
(
force
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
for
(
int
i
=
1
;
i
<
30
;
i
++
)
{
double
x
=
(
7.0
/
30.0
)
*
i
;
positions
[
1
]
=
Vec3
(
x
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
double
force
=
(
x
<
1.0
||
x
>
6.0
?
0.0
:
-
std
::
cos
(
x
-
1.0
));
double
energy
=
(
x
<
1.0
||
x
>
6.0
?
0.0
:
std
::
sin
(
x
-
1.0
))
+
1.0
;
ASSERT_EQUAL_VEC
(
Vec3
(
-
force
,
0
,
0
),
forces
[
0
],
0.1
);
ASSERT_EQUAL_VEC
(
Vec3
(
force
,
0
,
0
),
forces
[
1
],
0.1
);
ASSERT_EQUAL_TOL
(
energy
,
state
.
getPotentialEnergy
(),
0.02
);
}
}
void
testMultipleChainRules
()
{
CpuPlatform
platform
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomGBForce
*
force
=
new
CustomGBForce
();
force
->
addComputedValue
(
"a"
,
"2*r"
,
CustomGBForce
::
ParticlePair
);
force
->
addComputedValue
(
"b"
,
"a+1"
,
CustomGBForce
::
SingleParticle
);
force
->
addComputedValue
(
"c"
,
"2*b+a"
,
CustomGBForce
::
SingleParticle
);
force
->
addEnergyTerm
(
"0.1*a+1*b+10*c"
,
CustomGBForce
::
SingleParticle
);
// 0.1*(2*r) + 2*r+1 + 10*(3*a+2) = 0.2*r + 2*r+1 + 40*r+20+20*r = 62.2*r+21
force
->
addParticle
(
vector
<
double
>
());
force
->
addParticle
(
vector
<
double
>
());
system
.
addForce
(
force
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
for
(
int
i
=
1
;
i
<
5
;
i
++
)
{
positions
[
1
]
=
Vec3
(
i
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
ASSERT_EQUAL_VEC
(
Vec3
(
124.4
,
0
,
0
),
forces
[
0
],
1e-4
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
124.4
,
0
,
0
),
forces
[
1
],
1e-4
);
ASSERT_EQUAL_TOL
(
2
*
(
62.2
*
i
+
21
),
state
.
getPotentialEnergy
(),
0.02
);
}
}
void
testPositionDependence
()
{
CpuPlatform
platform
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomGBForce
*
force
=
new
CustomGBForce
();
force
->
addComputedValue
(
"a"
,
"r"
,
CustomGBForce
::
ParticlePair
);
force
->
addComputedValue
(
"b"
,
"a+x*y"
,
CustomGBForce
::
SingleParticle
);
force
->
addEnergyTerm
(
"b*z"
,
CustomGBForce
::
SingleParticle
);
force
->
addEnergyTerm
(
"b1+b2"
,
CustomGBForce
::
ParticlePair
);
// = 2*r+x1*y1+x2*y2
force
->
addParticle
(
vector
<
double
>
());
force
->
addParticle
(
vector
<
double
>
());
system
.
addForce
(
force
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
vector
<
Vec3
>
forces
(
2
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
positions
[
0
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
positions
[
1
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
Vec3
delta
=
positions
[
0
]
-
positions
[
1
];
double
r
=
sqrt
(
delta
.
dot
(
delta
));
double
energy
=
2
*
r
+
positions
[
0
][
0
]
*
positions
[
0
][
1
]
+
positions
[
1
][
0
]
*
positions
[
1
][
1
];
for
(
int
j
=
0
;
j
<
2
;
j
++
)
energy
+=
positions
[
j
][
2
]
*
(
r
+
positions
[
j
][
0
]
*
positions
[
j
][
1
]);
Vec3
force1
(
-
(
1
+
positions
[
0
][
2
])
*
delta
[
0
]
/
r
-
(
1
+
positions
[
0
][
2
])
*
positions
[
0
][
1
]
-
(
1
+
positions
[
1
][
2
])
*
delta
[
0
]
/
r
,
-
(
1
+
positions
[
0
][
2
])
*
delta
[
1
]
/
r
-
(
1
+
positions
[
0
][
2
])
*
positions
[
0
][
0
]
-
(
1
+
positions
[
1
][
2
])
*
delta
[
1
]
/
r
,
-
(
1
+
positions
[
0
][
2
])
*
delta
[
2
]
/
r
-
(
r
+
positions
[
0
][
0
]
*
positions
[
0
][
1
])
-
(
1
+
positions
[
1
][
2
])
*
delta
[
2
]
/
r
);
Vec3
force2
((
1
+
positions
[
0
][
2
])
*
delta
[
0
]
/
r
+
(
1
+
positions
[
1
][
2
])
*
delta
[
0
]
/
r
-
(
1
+
positions
[
1
][
2
])
*
positions
[
1
][
1
],
(
1
+
positions
[
0
][
2
])
*
delta
[
1
]
/
r
+
(
1
+
positions
[
1
][
2
])
*
delta
[
1
]
/
r
-
(
1
+
positions
[
1
][
2
])
*
positions
[
1
][
0
],
(
1
+
positions
[
0
][
2
])
*
delta
[
2
]
/
r
+
(
1
+
positions
[
1
][
2
])
*
delta
[
2
]
/
r
-
(
r
+
positions
[
1
][
0
]
*
positions
[
1
][
1
]));
ASSERT_EQUAL_VEC
(
force1
,
forces
[
0
],
1e-4
);
ASSERT_EQUAL_VEC
(
force2
,
forces
[
1
],
1e-4
);
ASSERT_EQUAL_TOL
(
energy
,
state
.
getPotentialEnergy
(),
0.02
);
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
double
norm
=
0.0
;
for
(
int
i
=
0
;
i
<
(
int
)
forces
.
size
();
++
i
)
norm
+=
forces
[
i
].
dot
(
forces
[
i
]);
norm
=
std
::
sqrt
(
norm
);
const
double
stepSize
=
1e-3
;
double
step
=
0.5
*
stepSize
/
norm
;
vector
<
Vec3
>
positions2
(
2
),
positions3
(
2
);
for
(
int
i
=
0
;
i
<
(
int
)
positions
.
size
();
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
forces
[
i
];
positions2
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
positions3
[
i
]
=
Vec3
(
p
[
0
]
+
f
[
0
]
*
step
,
p
[
1
]
+
f
[
1
]
*
step
,
p
[
2
]
+
f
[
2
]
*
step
);
}
context
.
setPositions
(
positions2
);
State
state2
=
context
.
getState
(
State
::
Energy
);
context
.
setPositions
(
positions3
);
State
state3
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
state2
.
getPotentialEnergy
()
-
state3
.
getPotentialEnergy
())
/
stepSize
,
1e-3
);
}
}
void
testExclusions
()
{
CpuPlatform
platform
;
for
(
int
i
=
3
;
i
<
4
;
i
++
)
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomGBForce
*
force
=
new
CustomGBForce
();
force
->
addComputedValue
(
"a"
,
"r"
,
i
<
2
?
CustomGBForce
::
ParticlePair
:
CustomGBForce
::
ParticlePairNoExclusions
);
force
->
addEnergyTerm
(
"a"
,
CustomGBForce
::
SingleParticle
);
force
->
addEnergyTerm
(
"(1+a1+a2)*r"
,
i
%
2
==
0
?
CustomGBForce
::
ParticlePair
:
CustomGBForce
::
ParticlePairNoExclusions
);
force
->
addParticle
(
vector
<
double
>
());
force
->
addParticle
(
vector
<
double
>
());
force
->
addExclusion
(
0
,
1
);
system
.
addForce
(
force
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
double
f
,
energy
;
switch
(
i
)
{
case
0
:
// e = 0
f
=
0
;
energy
=
0
;
break
;
case
1
:
// e = r
f
=
1
;
energy
=
1
;
break
;
case
2
:
// e = 2r
f
=
2
;
energy
=
2
;
break
;
case
3
:
// e = 3r + 2r^2
f
=
7
;
energy
=
5
;
break
;
default:
ASSERT
(
false
);
}
ASSERT_EQUAL_VEC
(
Vec3
(
f
,
0
,
0
),
forces
[
0
],
1e-4
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
f
,
0
,
0
),
forces
[
1
],
1e-4
);
ASSERT_EQUAL_TOL
(
energy
,
state
.
getPotentialEnergy
(),
1e-4
);
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
double
norm
=
0.0
;
for
(
int
i
=
0
;
i
<
(
int
)
forces
.
size
();
++
i
)
norm
+=
forces
[
i
].
dot
(
forces
[
i
]);
norm
=
std
::
sqrt
(
norm
);
const
double
stepSize
=
1e-3
;
double
step
=
stepSize
/
norm
;
for
(
int
i
=
0
;
i
<
(
int
)
positions
.
size
();
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
forces
[
i
];
positions
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
}
context
.
setPositions
(
positions
);
State
state2
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
state2
.
getPotentialEnergy
()
-
state
.
getPotentialEnergy
())
/
stepSize
,
1e-3
*
abs
(
state
.
getPotentialEnergy
()));
}
}
int
main
()
{
try
{
if
(
!
CpuPlatform
::
isProcessorSupported
())
{
cout
<<
"CPU is not supported. Exiting."
<<
endl
;
return
0
;
}
testOBC
(
GBSAOBCForce
::
NoCutoff
,
CustomGBForce
::
NoCutoff
);
testOBC
(
GBSAOBCForce
::
CutoffNonPeriodic
,
CustomGBForce
::
CutoffNonPeriodic
);
testOBC
(
GBSAOBCForce
::
CutoffPeriodic
,
CustomGBForce
::
CutoffPeriodic
);
testMembrane
();
testTabulatedFunction
();
testMultipleChainRules
();
testPositionDependence
();
testExclusions
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/cpu/tests/TestCpuCustomManyParticleForce.cpp
View file @
61d5cc0f
...
...
@@ -53,7 +53,17 @@ using namespace std;
const
double
TOL
=
1e-5
;
void
validateAxilrodTeller
(
CustomManyParticleForce
*
force
,
const
vector
<
Vec3
>&
positions
,
const
vector
<
const
int
*>&
expectedSets
,
double
boxSize
)
{
Vec3
computeDelta
(
const
Vec3
&
pos1
,
const
Vec3
&
pos2
,
bool
periodic
,
const
Vec3
*
periodicBoxVectors
)
{
Vec3
diff
=
pos1
-
pos2
;
if
(
periodic
)
{
diff
-=
periodicBoxVectors
[
2
]
*
floor
(
diff
[
2
]
/
periodicBoxVectors
[
2
][
2
]
+
0.5
);
diff
-=
periodicBoxVectors
[
1
]
*
floor
(
diff
[
1
]
/
periodicBoxVectors
[
1
][
1
]
+
0.5
);
diff
-=
periodicBoxVectors
[
0
]
*
floor
(
diff
[
0
]
/
periodicBoxVectors
[
0
][
0
]
+
0.5
);
}
return
diff
;
}
void
validateAxilrodTeller
(
CustomManyParticleForce
*
force
,
const
vector
<
Vec3
>&
positions
,
const
vector
<
const
int
*>&
expectedSets
,
double
boxSize
,
bool
triclinic
)
{
// Create a System and Context.
int
numParticles
=
force
->
getNumParticles
();
...
...
@@ -61,7 +71,18 @@ void validateAxilrodTeller(CustomManyParticleForce* force, const vector<Vec3>& p
System
system
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
system
.
addParticle
(
1.0
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
Vec3
boxVectors
[
3
];
if
(
triclinic
)
{
boxVectors
[
0
]
=
Vec3
(
boxSize
,
0
,
0
);
boxVectors
[
1
]
=
Vec3
(
0.2
*
boxSize
,
boxSize
,
0
);
boxVectors
[
2
]
=
Vec3
(
-
0.3
*
boxSize
,
-
0.1
*
boxSize
,
boxSize
);
}
else
{
boxVectors
[
0
]
=
Vec3
(
boxSize
,
0
,
0
);
boxVectors
[
1
]
=
Vec3
(
0
,
boxSize
,
0
);
boxVectors
[
2
]
=
Vec3
(
0
,
0
,
boxSize
);
}
system
.
setDefaultPeriodicBoxVectors
(
boxVectors
[
0
],
boxVectors
[
1
],
boxVectors
[
2
]);
system
.
addForce
(
force
);
VerletIntegrator
integrator
(
0.001
);
CpuPlatform
platform
;
...
...
@@ -73,20 +94,14 @@ void validateAxilrodTeller(CustomManyParticleForce* force, const vector<Vec3>& p
// See if the energy matches the expected value.
double
expectedEnergy
=
0
;
bool
periodic
=
(
nonbondedMethod
==
CustomManyParticleForce
::
CutoffPeriodic
);
for
(
int
i
=
0
;
i
<
(
int
)
expectedSets
.
size
();
i
++
)
{
int
p1
=
expectedSets
[
i
][
0
];
int
p2
=
expectedSets
[
i
][
1
];
int
p3
=
expectedSets
[
i
][
2
];
Vec3
d12
=
positions
[
p2
]
-
positions
[
p1
];
Vec3
d13
=
positions
[
p3
]
-
positions
[
p1
];
Vec3
d23
=
positions
[
p3
]
-
positions
[
p2
];
if
(
nonbondedMethod
==
CustomManyParticleForce
::
CutoffPeriodic
)
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
d12
[
j
]
-=
floor
(
d12
[
j
]
/
boxSize
+
0.5
f
)
*
boxSize
;
d13
[
j
]
-=
floor
(
d13
[
j
]
/
boxSize
+
0.5
f
)
*
boxSize
;
d23
[
j
]
-=
floor
(
d23
[
j
]
/
boxSize
+
0.5
f
)
*
boxSize
;
}
}
Vec3
d12
=
computeDelta
(
positions
[
p2
],
positions
[
p1
],
periodic
,
boxVectors
);
Vec3
d13
=
computeDelta
(
positions
[
p3
],
positions
[
p1
],
periodic
,
boxVectors
);
Vec3
d23
=
computeDelta
(
positions
[
p3
],
positions
[
p2
],
periodic
,
boxVectors
);
double
r12
=
sqrt
(
d12
.
dot
(
d12
));
double
r13
=
sqrt
(
d13
.
dot
(
d13
));
double
r23
=
sqrt
(
d23
.
dot
(
d23
));
...
...
@@ -210,7 +225,7 @@ void testNoCutoff() {
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
int
sets
[
4
][
3
]
=
{{
0
,
1
,
2
},
{
1
,
2
,
3
},
{
2
,
3
,
0
},
{
3
,
0
,
1
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
4
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
,
false
);
}
void
testCutoff
()
{
...
...
@@ -235,7 +250,7 @@ void testCutoff() {
positions
.
push_back
(
Vec3
(
0.2
,
0.5
,
-
0.1
));
int
sets
[
7
][
3
]
=
{{
0
,
1
,
2
},
{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
2
,
4
},
{
0
,
3
,
4
},
{
1
,
2
,
4
},
{
1
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
7
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
,
false
);
}
void
testPeriodic
()
{
...
...
@@ -261,7 +276,33 @@ void testPeriodic() {
double
boxSize
=
2.1
;
int
sets
[
5
][
3
]
=
{{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
2
,
4
},
{
0
,
3
,
4
},
{
1
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
5
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
boxSize
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
boxSize
,
false
);
}
void
testTriclinic
()
{
CustomManyParticleForce
*
force
=
new
CustomManyParticleForce
(
3
,
"C*(1+3*cos(theta1)*cos(theta2)*cos(theta3))/(r12*r13*r23)^3;"
"theta1=angle(p1,p2,p3); theta2=angle(p2,p3,p1); theta3=angle(p3,p1,p2);"
"r12=distance(p1,p2); r13=distance(p1,p3); r23=distance(p2,p3)"
);
force
->
addGlobalParameter
(
"C"
,
1.5
);
force
->
setNonbondedMethod
(
CustomManyParticleForce
::
CutoffPeriodic
);
force
->
setCutoffDistance
(
1.05
);
vector
<
double
>
params
;
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
force
->
addParticle
(
params
);
vector
<
Vec3
>
positions
;
positions
.
push_back
(
Vec3
(
0
,
0
,
0
));
positions
.
push_back
(
Vec3
(
1
,
0
,
0
));
positions
.
push_back
(
Vec3
(
0
,
1.1
,
0.3
));
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
positions
.
push_back
(
Vec3
(
0.2
,
0.5
,
-
0.1
));
double
boxSize
=
2.1
;
int
sets
[
4
][
3
]
=
{{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
3
,
4
},
{
1
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
4
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
boxSize
,
true
);
}
void
testExclusions
()
{
...
...
@@ -286,7 +327,7 @@ void testExclusions() {
force
->
addExclusion
(
0
,
3
);
int
sets
[
5
][
3
]
=
{{
0
,
1
,
4
},
{
1
,
2
,
3
},
{
1
,
2
,
4
},
{
1
,
3
,
4
},
{
2
,
3
,
4
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
5
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
,
false
);
}
void
testAllTerms
()
{
...
...
@@ -673,9 +714,14 @@ void testCentralParticleModeLargeSystem() {
int
main
()
{
try
{
if
(
!
CpuPlatform
::
isProcessorSupported
())
{
cout
<<
"CPU is not supported. Exiting."
<<
endl
;
return
0
;
}
testNoCutoff
();
testCutoff
();
testPeriodic
();
testTriclinic
();
testExclusions
();
testAllTerms
();
testParameters
();
...
...
platforms/cpu/tests/TestCpuCustomNonbondedForce.cpp
View file @
61d5cc0f
...
...
@@ -224,6 +224,65 @@ void testPeriodic() {
ASSERT_EQUAL_TOL
(
1.9
+
1
+
0.9
,
state
.
getPotentialEnergy
(),
TOL
);
}
void
testTriclinic
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
Vec3
a
(
3.1
,
0
,
0
);
Vec3
b
(
0.4
,
3.5
,
0
);
Vec3
c
(
-
0.1
,
-
0.5
,
4.0
);
system
.
setDefaultPeriodicBoxVectors
(
a
,
b
,
c
);
VerletIntegrator
integrator
(
0.01
);
CustomNonbondedForce
*
nonbonded
=
new
CustomNonbondedForce
(
"r"
);
nonbonded
->
addParticle
(
vector
<
double
>
());
nonbonded
->
addParticle
(
vector
<
double
>
());
nonbonded
->
setNonbondedMethod
(
CustomNonbondedForce
::
CutoffPeriodic
);
const
double
cutoff
=
1.5
;
nonbonded
->
setCutoffDistance
(
cutoff
);
system
.
addForce
(
nonbonded
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
iteration
=
0
;
iteration
<
50
;
iteration
++
)
{
// Generate random positions for the two particles.
positions
[
0
]
=
a
*
genrand_real2
(
sfmt
)
+
b
*
genrand_real2
(
sfmt
)
+
c
*
genrand_real2
(
sfmt
);
positions
[
1
]
=
a
*
genrand_real2
(
sfmt
)
+
b
*
genrand_real2
(
sfmt
)
+
c
*
genrand_real2
(
sfmt
);
context
.
setPositions
(
positions
);
// Loop over all possible periodic copies and find the nearest one.
Vec3
delta
;
double
distance2
=
100.0
;
for
(
int
i
=
-
1
;
i
<
2
;
i
++
)
for
(
int
j
=
-
1
;
j
<
2
;
j
++
)
for
(
int
k
=
-
1
;
k
<
2
;
k
++
)
{
Vec3
d
=
positions
[
1
]
-
positions
[
0
]
+
a
*
i
+
b
*
j
+
c
*
k
;
if
(
d
.
dot
(
d
)
<
distance2
)
{
delta
=
d
;
distance2
=
d
.
dot
(
d
);
}
}
double
distance
=
sqrt
(
distance2
);
// See if the force and energy are correct.
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
if
(
distance
>=
cutoff
)
{
ASSERT_EQUAL
(
0.0
,
state
.
getPotentialEnergy
());
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
state
.
getForces
()[
0
],
0
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
state
.
getForces
()[
1
],
0
);
}
else
{
const
Vec3
force
=
delta
/
sqrt
(
delta
.
dot
(
delta
));
ASSERT_EQUAL_TOL
(
distance
,
state
.
getPotentialEnergy
(),
TOL
);
ASSERT_EQUAL_VEC
(
force
,
state
.
getForces
()[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
-
force
,
state
.
getForces
()[
1
],
TOL
);
}
}
}
void
testContinuous1DFunction
()
{
System
system
;
system
.
addParticle
(
1.0
);
...
...
@@ -852,6 +911,7 @@ int main() {
testExclusions
();
testCutoff
();
testPeriodic
();
testTriclinic
();
testContinuous1DFunction
();
testContinuous2DFunction
();
testContinuous3DFunction
();
...
...
platforms/cpu/tests/TestCpuEwald.cpp
View file @
61d5cc0f
...
...
@@ -201,6 +201,57 @@ void testEwald2Ions() {
ASSERT_EQUAL_TOL
(
-
217.276
,
state
.
getPotentialEnergy
(),
0.01
/*10*TOL*/
);
}
void
testTriclinic
()
{
// Create a triclinic box containing eight particles.
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
2.5
,
0
,
0
),
Vec3
(
0.5
,
3.0
,
0
),
Vec3
(
0.7
,
0.9
,
3.5
));
for
(
int
i
=
0
;
i
<
8
;
i
++
)
system
.
addParticle
(
1.0
);
NonbondedForce
*
force
=
new
NonbondedForce
();
system
.
addForce
(
force
);
force
->
setNonbondedMethod
(
NonbondedForce
::
PME
);
force
->
setCutoffDistance
(
1.0
);
force
->
setPMEParameters
(
3.45891
,
32
,
40
,
48
);
for
(
int
i
=
0
;
i
<
4
;
i
++
)
force
->
addParticle
(
-
1
,
0.440104
,
0.4184
);
// Cl parameters
for
(
int
i
=
0
;
i
<
4
;
i
++
)
force
->
addParticle
(
1
,
0.332840
,
0.0115897
);
// Na parameters
vector
<
Vec3
>
positions
(
8
);
positions
[
0
]
=
Vec3
(
1.744
,
2.788
,
3.162
);
positions
[
1
]
=
Vec3
(
1.048
,
0.762
,
2.340
);
positions
[
2
]
=
Vec3
(
2.489
,
1.570
,
2.817
);
positions
[
3
]
=
Vec3
(
1.027
,
1.893
,
3.271
);
positions
[
4
]
=
Vec3
(
0.937
,
0.825
,
0.009
);
positions
[
5
]
=
Vec3
(
2.290
,
1.887
,
3.352
);
positions
[
6
]
=
Vec3
(
1.266
,
1.111
,
2.894
);
positions
[
7
]
=
Vec3
(
0.933
,
1.862
,
3.490
);
// Compute the forces and energy.
VerletIntegrator
integ
(
0.001
);
Context
context
(
system
,
integ
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
// Compare them to values computed by Gromacs.
double
expectedEnergy
=
-
963.370
;
vector
<
Vec3
>
expectedForce
(
8
);
expectedForce
[
0
]
=
Vec3
(
4.25253e+01
,
-
1.23503e+02
,
1.22139e+02
);
expectedForce
[
1
]
=
Vec3
(
9.74752e+01
,
1.68213e+02
,
1.93169e+02
);
expectedForce
[
2
]
=
Vec3
(
-
1.50348e+02
,
1.29165e+02
,
3.70435e+02
);
expectedForce
[
3
]
=
Vec3
(
9.18644e+02
,
-
3.52571e+00
,
-
1.34772e+03
);
expectedForce
[
4
]
=
Vec3
(
-
1.61193e+02
,
9.01528e+01
,
-
7.12904e+01
);
expectedForce
[
5
]
=
Vec3
(
2.82630e+02
,
2.78029e+01
,
-
3.72864e+02
);
expectedForce
[
6
]
=
Vec3
(
-
1.47454e+02
,
-
2.14448e+02
,
-
3.55789e+02
);
expectedForce
[
7
]
=
Vec3
(
-
8.82195e+02
,
-
7.39132e+01
,
1.46202e+03
);
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
ASSERT_EQUAL_VEC
(
expectedForce
[
i
],
state
.
getForces
()[
i
],
1e-4
);
}
ASSERT_EQUAL_TOL
(
expectedEnergy
,
state
.
getPotentialEnergy
(),
1e-4
);
}
void
testErrorTolerance
(
NonbondedForce
::
NonbondedMethod
method
)
{
// Create a cloud of random point charges.
...
...
@@ -261,6 +312,7 @@ int main(int argc, char* argv[]) {
testEwaldPME
(
false
);
testEwaldPME
(
true
);
// testEwald2Ions();
testTriclinic
();
testErrorTolerance
(
NonbondedForce
::
Ewald
);
testErrorTolerance
(
NonbondedForce
::
PME
);
}
...
...
platforms/cpu/tests/TestCpuGBSAOBCForce.cpp
View file @
61d5cc0f
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
4
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -67,7 +67,7 @@ void testSingleParticle() {
double
eps0
=
EPSILON0
;
double
bornEnergy
=
(
-
0.5
*
0.5
/
(
8
*
PI_M
*
eps0
))
*
(
1.0
/
forceField
->
getSoluteDielectric
()
-
1.0
/
forceField
->
getSolventDielectric
())
/
bornRadius
;
double
extendedRadius
=
0.15
+
0.14
;
// probe radius
double
nonpolarEnergy
=
CAL2JOULE
*
PI_M
*
0.0216
*
(
10
*
extendedRadius
)
*
(
10
*
extendedRadius
)
*
std
::
pow
(
0.15
/
bornRadius
,
6.0
);
// Where did this formula come from? Just copied it from CpuImplicitSolvent.cpp
double
nonpolarEnergy
=
4
*
PI_M
*
2.25936
*
extendedRadius
*
extendedRadius
*
std
::
pow
(
0.15
/
bornRadius
,
6.0
);
ASSERT_EQUAL_TOL
((
bornEnergy
+
nonpolarEnergy
),
state
.
getPotentialEnergy
(),
0.01
);
// Change the parameters and see if it is still correct.
...
...
@@ -77,8 +77,35 @@ void testSingleParticle() {
state
=
context
.
getState
(
State
::
Energy
);
bornRadius
=
0.25
-
0.009
;
// dielectric offset
bornEnergy
=
(
-
0.4
*
0.4
/
(
8
*
PI_M
*
eps0
))
*
(
1.0
/
forceField
->
getSoluteDielectric
()
-
1.0
/
forceField
->
getSolventDielectric
())
/
bornRadius
;
extendedRadius
=
bornRadius
+
0.14
;
nonpolarEnergy
=
CAL2JOULE
*
PI_M
*
0.0216
*
(
10
*
extendedRadius
)
*
(
10
*
extendedRadius
)
*
std
::
pow
(
0.25
/
bornRadius
,
6.0
);
extendedRadius
=
0.25
+
0.14
;
nonpolarEnergy
=
4
*
PI_M
*
2.25936
*
extendedRadius
*
extendedRadius
*
std
::
pow
(
0.25
/
bornRadius
,
6.0
);
ASSERT_EQUAL_TOL
((
bornEnergy
+
nonpolarEnergy
),
state
.
getPotentialEnergy
(),
0.01
);
}
void
testGlobalSettings
()
{
CpuPlatform
platform
;
System
system
;
system
.
addParticle
(
2.0
);
LangevinIntegrator
integrator
(
0
,
0.1
,
0.01
);
GBSAOBCForce
*
forceField
=
new
GBSAOBCForce
();
forceField
->
addParticle
(
0.5
,
0.15
,
1
);
const
double
soluteDielectric
=
2.1
;
const
double
solventDielectric
=
35.0
;
const
double
surfaceAreaEnergy
=
0.75
;
forceField
->
setSoluteDielectric
(
soluteDielectric
);
forceField
->
setSolventDielectric
(
solventDielectric
);
forceField
->
setSurfaceAreaEnergy
(
surfaceAreaEnergy
);
system
.
addForce
(
forceField
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
1
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Energy
);
double
bornRadius
=
0.15
-
0.009
;
// dielectric offset
double
eps0
=
EPSILON0
;
double
bornEnergy
=
(
-
0.5
*
0.5
/
(
8
*
PI_M
*
eps0
))
*
(
1.0
/
soluteDielectric
-
1.0
/
solventDielectric
)
/
bornRadius
;
double
extendedRadius
=
0.15
+
0.14
;
// probe radius
double
nonpolarEnergy
=
4
*
PI_M
*
surfaceAreaEnergy
*
extendedRadius
*
extendedRadius
*
std
::
pow
(
0.15
/
bornRadius
,
6.0
);
ASSERT_EQUAL_TOL
((
bornEnergy
+
nonpolarEnergy
),
state
.
getPotentialEnergy
(),
0.01
);
}
...
...
@@ -228,6 +255,7 @@ int main() {
return
0
;
}
testSingleParticle
();
testGlobalSettings
();
testCutoffAndPeriodic
();
for
(
int
i
=
5
;
i
<
11
;
i
++
)
{
testForce
(
i
*
i
*
i
,
NonbondedForce
::
NoCutoff
,
GBSAOBCForce
::
NoCutoff
);
...
...
platforms/cpu/tests/TestCpuNeighborList.cpp
View file @
61d5cc0f
...
...
@@ -48,10 +48,21 @@
using
namespace
OpenMM
;
using
namespace
std
;
void
testNeighborList
(
bool
periodic
)
{
void
testNeighborList
(
bool
periodic
,
bool
triclinic
)
{
const
int
numParticles
=
500
;
const
float
cutoff
=
2.0
f
;
const
float
boxSize
[
3
]
=
{
20.0
f
,
15.0
f
,
22.0
f
};
RealVec
boxVectors
[
3
];
if
(
triclinic
)
{
boxVectors
[
0
]
=
RealVec
(
20
,
0
,
0
);
boxVectors
[
1
]
=
RealVec
(
5
,
15
,
0
);
boxVectors
[
2
]
=
RealVec
(
-
3
,
-
7
,
22
);
}
else
{
boxVectors
[
0
]
=
RealVec
(
20
,
0
,
0
);
boxVectors
[
1
]
=
RealVec
(
0
,
15
,
0
);
boxVectors
[
2
]
=
RealVec
(
0
,
0
,
22
);
}
const
float
boxSize
[
3
]
=
{(
float
)
boxVectors
[
0
][
0
],
(
float
)
boxVectors
[
1
][
1
],
(
float
)
boxVectors
[
2
][
2
]};
const
int
blockSize
=
8
;
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
...
...
@@ -69,7 +80,7 @@ void testNeighborList(bool periodic) {
}
ThreadPool
threads
;
CpuNeighborList
neighborList
(
blockSize
);
neighborList
.
computeNeighborList
(
numParticles
,
positions
,
exclusions
,
box
Size
,
periodic
,
cutoff
,
threads
);
neighborList
.
computeNeighborList
(
numParticles
,
positions
,
exclusions
,
box
Vectors
,
periodic
,
cutoff
,
threads
);
// Convert the neighbor list to a set for faster lookup.
...
...
@@ -94,15 +105,13 @@ void testNeighborList(bool periodic) {
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
j
=
0
;
j
<=
i
;
j
++
)
{
bool
shouldInclude
=
(
exclusions
[
i
].
find
(
j
)
==
exclusions
[
i
].
end
());
float
dx
=
positions
[
4
*
i
]
-
positions
[
4
*
j
];
float
dy
=
positions
[
4
*
i
+
1
]
-
positions
[
4
*
j
+
1
];
float
dz
=
positions
[
4
*
i
+
2
]
-
positions
[
4
*
j
+
2
];
Vec3
diff
(
positions
[
4
*
i
]
-
positions
[
4
*
j
],
positions
[
4
*
i
+
1
]
-
positions
[
4
*
j
+
1
],
positions
[
4
*
i
+
2
]
-
positions
[
4
*
j
+
2
]);
if
(
periodic
)
{
d
x
-=
floor
(
d
x
/
boxSize
[
0
]
+
0.5
f
)
*
boxSize
[
0
]
;
d
y
-=
floor
(
d
y
/
boxSize
[
1
]
+
0.5
f
)
*
boxSize
[
1
]
;
d
z
-=
floor
(
d
z
/
boxSize
[
2
]
+
0.5
f
)
*
boxSize
[
2
]
;
d
iff
-=
boxVectors
[
2
]
*
floor
(
d
iff
[
2
]
/
boxSize
[
2
]
+
0.5
)
;
d
iff
-=
boxVectors
[
1
]
*
floor
(
d
iff
[
1
]
/
boxSize
[
1
]
+
0.5
)
;
d
iff
-=
boxVectors
[
0
]
*
floor
(
d
iff
[
0
]
/
boxSize
[
0
]
+
0.5
)
;
}
if
(
d
x
*
dx
+
dy
*
dy
+
dz
*
dz
>
cutoff
*
cutoff
)
if
(
d
iff
.
dot
(
diff
)
>
cutoff
*
cutoff
)
shouldInclude
=
false
;
bool
isIncluded
=
(
neighbors
.
find
(
make_pair
(
i
,
j
))
!=
neighbors
.
end
()
||
neighbors
.
find
(
make_pair
(
j
,
i
))
!=
neighbors
.
end
());
if
(
shouldInclude
)
...
...
@@ -116,8 +125,9 @@ int main() {
cout
<<
"CPU is not supported. Exiting."
<<
endl
;
return
0
;
}
testNeighborList
(
false
);
testNeighborList
(
true
);
testNeighborList
(
false
,
false
);
testNeighborList
(
true
,
false
);
testNeighborList
(
true
,
true
);
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
...
...
platforms/cpu/tests/TestCpuNonbondedForce.cpp
View file @
61d5cc0f
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -353,6 +353,67 @@ void testPeriodic() {
ASSERT_EQUAL_TOL
(
2
*
ONE_4PI_EPS0
*
(
1.0
)
*
(
1.0
+
krf
*
1.0
-
crf
),
state
.
getPotentialEnergy
(),
TOL
);
}
void
testTriclinic
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
Vec3
a
(
3.1
,
0
,
0
);
Vec3
b
(
0.4
,
3.5
,
0
);
Vec3
c
(
-
0.1
,
-
0.5
,
4.0
);
system
.
setDefaultPeriodicBoxVectors
(
a
,
b
,
c
);
VerletIntegrator
integrator
(
0.01
);
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
nonbonded
->
addParticle
(
1.0
,
1
,
0
);
nonbonded
->
addParticle
(
1.0
,
1
,
0
);
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
const
double
cutoff
=
1.5
;
nonbonded
->
setCutoffDistance
(
cutoff
);
system
.
addForce
(
nonbonded
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
const
double
eps
=
78.3
;
const
double
krf
=
(
1.0
/
(
cutoff
*
cutoff
*
cutoff
))
*
(
eps
-
1.0
)
/
(
2.0
*
eps
+
1.0
);
const
double
crf
=
(
1.0
/
cutoff
)
*
(
3.0
*
eps
)
/
(
2.0
*
eps
+
1.0
);
for
(
int
iteration
=
0
;
iteration
<
50
;
iteration
++
)
{
// Generate random positions for the two particles.
positions
[
0
]
=
a
*
genrand_real2
(
sfmt
)
+
b
*
genrand_real2
(
sfmt
)
+
c
*
genrand_real2
(
sfmt
);
positions
[
1
]
=
a
*
genrand_real2
(
sfmt
)
+
b
*
genrand_real2
(
sfmt
)
+
c
*
genrand_real2
(
sfmt
);
context
.
setPositions
(
positions
);
// Loop over all possible periodic copies and find the nearest one.
Vec3
delta
;
double
distance2
=
100.0
;
for
(
int
i
=
-
1
;
i
<
2
;
i
++
)
for
(
int
j
=
-
1
;
j
<
2
;
j
++
)
for
(
int
k
=
-
1
;
k
<
2
;
k
++
)
{
Vec3
d
=
positions
[
1
]
-
positions
[
0
]
+
a
*
i
+
b
*
j
+
c
*
k
;
if
(
d
.
dot
(
d
)
<
distance2
)
{
delta
=
d
;
distance2
=
d
.
dot
(
d
);
}
}
double
distance
=
sqrt
(
distance2
);
// See if the force and energy are correct.
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
if
(
distance
>=
cutoff
)
{
ASSERT_EQUAL
(
0.0
,
state
.
getPotentialEnergy
());
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
state
.
getForces
()[
0
],
0
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
state
.
getForces
()[
1
],
0
);
}
else
{
const
Vec3
force
=
delta
*
ONE_4PI_EPS0
*
(
-
1.0
/
(
distance
*
distance
*
distance
)
+
2.0
*
krf
);
ASSERT_EQUAL_TOL
(
ONE_4PI_EPS0
*
(
1.0
/
distance
+
krf
*
distance
*
distance
-
crf
),
state
.
getPotentialEnergy
(),
1e-4
);
ASSERT_EQUAL_VEC
(
force
,
state
.
getForces
()[
0
],
2e-5
);
ASSERT_EQUAL_VEC
(
-
force
,
state
.
getForces
()[
1
],
2e-5
);
}
}
}
void
testLargeSystem
()
{
const
int
numMolecules
=
600
;
...
...
@@ -635,6 +696,7 @@ int main(int argc, char* argv[]) {
testCutoff
();
testCutoff14
();
testPeriodic
();
testTriclinic
();
testLargeSystem
();
testDispersionCorrection
();
testChangingParameters
();
...
...
platforms/cuda/include/CudaContext.h
View file @
61d5cc0f
...
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2009-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2009-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -41,6 +41,7 @@
#include <vector_functions.h>
#include "windowsExportCuda.h"
#include "CudaPlatform.h"
#include "openmm/Kernel.h"
typedef
unsigned
int
tileflags
;
...
...
@@ -133,6 +134,18 @@ public:
int
getContextIndex
()
const
{
return
contextIndex
;
}
/**
* Get the stream currently being used for execution.
*/
CUstream
getCurrentStream
();
/**
* Set the stream to use for execution.
*/
void
setCurrentStream
(
CUstream
stream
);
/**
* Reset the context to using the default stream for execution.
*/
void
restoreDefaultStream
();
/**
* Get the array which contains the position (the xyz components) and charge (the w component) of each atom.
*/
...
...
@@ -340,43 +353,62 @@ public:
/**
* Get whether double precision is being used.
*/
bool
getUseDoublePrecision
()
{
bool
getUseDoublePrecision
()
const
{
return
useDoublePrecision
;
}
/**
* Get whether mixed precision is being used.
*/
bool
getUseMixedPrecision
()
{
bool
getUseMixedPrecision
()
const
{
return
useMixedPrecision
;
}
/**
* Get whether the periodic box is triclinic.
*/
bool
getBoxIsTriclinic
()
const
{
return
boxIsTriclinic
;
}
/**
* Convert a number to a string in a format suitable for including in a kernel.
* This takes into account whether the context uses single or double precision.
*/
std
::
string
doubleToString
(
double
value
);
std
::
string
doubleToString
(
double
value
)
const
;
/**
* Convert a number to a string in a format suitable for including in a kernel.
*/
std
::
string
intToString
(
int
value
);
std
::
string
intToString
(
int
value
)
const
;
/**
* Convert a CUDA result code to the corresponding string description.
*/
static
std
::
string
getErrorString
(
CUresult
result
);
/**
* Get the
size of
the periodic box.
* Get the
vectors defining
the periodic box.
*/
double4
getPeriodicBoxSize
()
const
{
return
periodicBoxSize
;
void
getPeriodicBoxVectors
(
Vec3
&
a
,
Vec3
&
b
,
Vec3
&
c
)
const
{
a
=
Vec3
(
periodicBoxVecX
.
x
,
periodicBoxVecX
.
y
,
periodicBoxVecX
.
z
);
b
=
Vec3
(
periodicBoxVecY
.
x
,
periodicBoxVecY
.
y
,
periodicBoxVecY
.
z
);
c
=
Vec3
(
periodicBoxVecZ
.
x
,
periodicBoxVecZ
.
y
,
periodicBoxVecZ
.
z
);
}
/**
* Set the
size of
the periodic box.
* Set the
vectors defining
the periodic box.
*/
void
setPeriodicBoxSize
(
double
xsize
,
double
ysize
,
double
zsize
)
{
periodicBoxSize
=
make_double4
(
xsize
,
ysize
,
zsize
,
0.0
);
invPeriodicBoxSize
=
make_double4
(
1.0
/
xsize
,
1.0
/
ysize
,
1.0
/
zsize
,
0.0
);
periodicBoxSizeFloat
=
make_float4
((
float
)
xsize
,
(
float
)
ysize
,
(
float
)
zsize
,
0.0
f
);
invPeriodicBoxSizeFloat
=
make_float4
(
1.0
f
/
(
float
)
xsize
,
1.0
f
/
(
float
)
ysize
,
1.0
f
/
(
float
)
zsize
,
0.0
f
);
void
setPeriodicBoxVectors
(
const
Vec3
&
a
,
const
Vec3
&
b
,
const
Vec3
&
c
)
{
periodicBoxVecX
=
make_double4
(
a
[
0
],
a
[
1
],
a
[
2
],
0.0
);
periodicBoxVecY
=
make_double4
(
b
[
0
],
b
[
1
],
b
[
2
],
0.0
);
periodicBoxVecZ
=
make_double4
(
c
[
0
],
c
[
1
],
c
[
2
],
0.0
);
periodicBoxVecXFloat
=
make_float4
((
float
)
a
[
0
],
(
float
)
a
[
1
],
(
float
)
a
[
2
],
0.0
f
);
periodicBoxVecYFloat
=
make_float4
((
float
)
b
[
0
],
(
float
)
b
[
1
],
(
float
)
b
[
2
],
0.0
f
);
periodicBoxVecZFloat
=
make_float4
((
float
)
c
[
0
],
(
float
)
c
[
1
],
(
float
)
c
[
2
],
0.0
f
);
periodicBoxSize
=
make_double4
(
a
[
0
],
b
[
1
],
c
[
2
],
0.0
);
invPeriodicBoxSize
=
make_double4
(
1.0
/
a
[
0
],
1.0
/
b
[
1
],
1.0
/
c
[
2
],
0.0
);
periodicBoxSizeFloat
=
make_float4
((
float
)
a
[
0
],
(
float
)
b
[
1
],
(
float
)
c
[
2
],
0.0
f
);
invPeriodicBoxSizeFloat
=
make_float4
(
1.0
f
/
(
float
)
a
[
0
],
1.0
f
/
(
float
)
b
[
1
],
1.0
f
/
(
float
)
c
[
2
],
0.0
f
);
}
/**
* Get the size of the periodic box.
*/
double4
getPeriodicBoxSize
()
const
{
return
periodicBoxSize
;
}
/**
* Get the inverse of the size of the periodic box.
...
...
@@ -398,6 +430,27 @@ public:
void
*
getInvPeriodicBoxSizePointer
()
{
return
(
useDoublePrecision
?
reinterpret_cast
<
void
*>
(
&
invPeriodicBoxSize
)
:
reinterpret_cast
<
void
*>
(
&
invPeriodicBoxSizeFloat
));
}
/**
* Get a pointer to the first periodic box vector, represented as either a float4 or double4 depending on
* this context's precision. This value is suitable for passing to kernels as an argument.
*/
void
*
getPeriodicBoxVecXPointer
()
{
return
(
useDoublePrecision
?
reinterpret_cast
<
void
*>
(
&
periodicBoxVecX
)
:
reinterpret_cast
<
void
*>
(
&
periodicBoxVecXFloat
));
}
/**
* Get a pointer to the second periodic box vector, represented as either a float4 or double4 depending on
* this context's precision. This value is suitable for passing to kernels as an argument.
*/
void
*
getPeriodicBoxVecYPointer
()
{
return
(
useDoublePrecision
?
reinterpret_cast
<
void
*>
(
&
periodicBoxVecY
)
:
reinterpret_cast
<
void
*>
(
&
periodicBoxVecYFloat
));
}
/**
* Get a pointer to the third periodic box vector, represented as either a float4 or double4 depending on
* this context's precision. This value is suitable for passing to kernels as an argument.
*/
void
*
getPeriodicBoxVecZPointer
()
{
return
(
useDoublePrecision
?
reinterpret_cast
<
void
*>
(
&
periodicBoxVecZ
)
:
reinterpret_cast
<
void
*>
(
&
periodicBoxVecZFloat
));
}
/**
* Get the CudaIntegrationUtilities for this context.
*/
...
...
@@ -513,14 +566,15 @@ private:
int
paddedNumAtoms
;
int
numAtomBlocks
;
int
numThreadBlocks
;
bool
useBlockingSync
,
useDoublePrecision
,
useMixedPrecision
,
contextIsValid
,
atomsWereReordered
;
bool
useBlockingSync
,
useDoublePrecision
,
useMixedPrecision
,
contextIsValid
,
atomsWereReordered
,
boxIsTriclinic
,
hasCompilerKernel
;
std
::
string
compiler
,
tempDir
,
cacheDir
,
gpuArchitecture
;
float4
periodicBoxSizeFloat
,
invPeriodicBoxSizeFloat
;
double4
periodicBoxSize
,
invPeriodicBoxSize
;
float4
periodicBoxVecXFloat
,
periodicBoxVecYFloat
,
periodicBoxVecZFloat
,
periodicBoxSizeFloat
,
invPeriodicBoxSizeFloat
;
double4
periodicBoxVecX
,
periodicBoxVecY
,
periodicBoxVecZ
,
periodicBoxSize
,
invPeriodicBoxSize
;
std
::
string
defaultOptimizationOptions
;
std
::
map
<
std
::
string
,
std
::
string
>
compilationDefines
;
CUcontext
context
;
CUdevice
device
;
CUstream
currentStream
;
CUfunction
clearBufferKernel
;
CUfunction
clearTwoBuffersKernel
;
CUfunction
clearThreeBuffersKernel
;
...
...
@@ -549,6 +603,7 @@ private:
CudaBondedUtilities
*
bonded
;
CudaNonbondedUtilities
*
nonbonded
;
WorkThread
*
thread
;
Kernel
compilerKernel
;
};
struct
CudaContext
::
Molecule
{
...
...
platforms/cuda/include/CudaKernels.h
View file @
61d5cc0f
...
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -38,6 +38,27 @@
namespace
OpenMM
{
/**
* This abstract class defines an interface for code that can compile CUDA kernels. This allows a plugin to take advantage of runtime compilation
* when running on recent versions of CUDA.
*/
class
CudaCompilerKernel
:
public
KernelImpl
{
public:
static
std
::
string
Name
()
{
return
"CudaCompilerKernel"
;
}
CudaCompilerKernel
(
std
::
string
name
,
const
Platform
&
platform
)
:
KernelImpl
(
name
,
platform
)
{
}
/**
* Compile a kernel to PTX.
*
* @param source the source code for the kernel
* @param options the flags to be passed to the compiler
* @param cu the CudaContext for which the kernel is being compiled
*/
virtual
std
::
string
createModule
(
const
std
::
string
&
source
,
const
std
::
string
&
flags
,
CudaContext
&
cu
)
=
0
;
};
/**
* This kernel is invoked at the beginning and end of force and energy computations. It gives the
* Platform a chance to clear buffers and do other initialization at the beginning, and to do any
...
...
@@ -71,11 +92,13 @@ public:
* @param includeForce true if forces should be computed
* @param includeEnergy true if potential energy should be computed
* @param groups a set of bit flags for which force groups to include
* @param valid the method may set this to false to indicate the results are invalid and the force/energy
* calculation should be repeated
* @return the potential energy of the system. This value is added to all values returned by ForceImpls'
* calcForcesAndEnergy() methods. That is, each force kernel may <i>either</i> return its contribution to the
* energy directly, <i>or</i> add it to an internal buffer so that it will be included here.
*/
double
finishComputation
(
ContextImpl
&
context
,
bool
includeForce
,
bool
includeEnergy
,
int
groups
);
double
finishComputation
(
ContextImpl
&
context
,
bool
includeForce
,
bool
includeEnergy
,
int
groups
,
bool
&
valid
);
private:
CudaContext
&
cu
;
};
...
...
@@ -497,11 +520,19 @@ public:
* @return the potential energy due to the force
*/
double
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
);
/**
* Copy changed parameters over to a context.
*
* @param context the context to copy parameters to
* @param force the CMAPTorsionForce to copy the parameters from
*/
void
copyParametersToContext
(
ContextImpl
&
context
,
const
CMAPTorsionForce
&
force
);
private:
int
numTorsions
;
bool
hasInitializedKernel
;
CudaContext
&
cu
;
const
System
&
system
;
std
::
vector
<
int2
>
mapPositionsVec
;
CudaArray
*
coefficients
;
CudaArray
*
mapPositions
;
CudaArray
*
torsionMaps
;
...
...
@@ -591,14 +622,16 @@ private:
int
getKeySize
()
const
{
return
4
;}
const
char
*
getDataType
()
const
{
return
"int2"
;}
const
char
*
getKeyType
()
const
{
return
"int"
;}
const
char
*
getMinKey
()
const
{
return
"
INT_MIN
"
;}
const
char
*
getMaxKey
()
const
{
return
"
INT_MAX
"
;}
const
char
*
getMaxValue
()
const
{
return
"make_int2(
INT_MAX, INT_MAX
)"
;}
const
char
*
getMinKey
()
const
{
return
"
(-2147483647-1)
"
;}
const
char
*
getMaxKey
()
const
{
return
"
2147483647
"
;}
const
char
*
getMaxValue
()
const
{
return
"make_int2(
2147483647, 2147483647
)"
;}
const
char
*
getSortKey
()
const
{
return
"value.y"
;}
};
class
PmeIO
;
class
PmePreComputation
;
class
PmePostComputation
;
class
SyncStreamPreComputation
;
class
SyncStreamPostComputation
;
CudaContext
&
cu
;
bool
hasInitializedFFT
;
CudaArray
*
sigmaEpsilon
;
...
...
@@ -614,6 +647,8 @@ private:
CudaSort
*
sort
;
Kernel
cpuPme
;
PmeIO
*
pmeio
;
CUstream
pmeStream
;
CUevent
pmeSyncEvent
;
cufftHandle
fftForward
;
cufftHandle
fftBackward
;
CUfunction
ewaldSumsKernel
;
...
...
@@ -628,7 +663,7 @@ private:
std
::
vector
<
std
::
pair
<
int
,
int
>
>
exceptionAtoms
;
double
ewaldSelfEnergy
,
dispersionCoefficient
,
alpha
;
int
interpolateForceThreads
;
bool
hasCoulomb
,
hasLJ
;
bool
hasCoulomb
,
hasLJ
,
usePmeStream
;
static
const
int
PmeOrder
=
5
;
};
...
...
@@ -715,7 +750,7 @@ public:
*/
void
copyParametersToContext
(
ContextImpl
&
context
,
const
GBSAOBCForce
&
force
);
private:
double
prefactor
;
double
prefactor
,
surfaceAreaFactor
;
bool
hasCreatedKernels
;
int
maxTiles
;
CudaContext
&
cu
;
...
...
platforms/cuda/include/CudaNonbondedUtilities.h
View file @
61d5cc0f
...
...
@@ -278,7 +278,7 @@ private:
std
::
string
kernelSource
;
std
::
map
<
std
::
string
,
std
::
string
>
kernelDefines
;
double
cutoff
;
bool
useCutoff
,
usePeriodic
,
anyExclusions
,
usePadding
;
bool
useCutoff
,
usePeriodic
,
anyExclusions
,
usePadding
,
forceRebuildNeighborList
;
int
startTileIndex
,
numTiles
,
startBlockIndex
,
numBlocks
,
maxTiles
,
numForceThreadBlocks
,
forceThreadBlockSize
,
nonbondedForceGroup
,
numAtoms
;
};
...
...
platforms/cuda/include/CudaParallelKernels.h
View file @
61d5cc0f
...
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2011-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2011-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -69,11 +69,13 @@ public:
* @param includeForce true if forces should be computed
* @param includeEnergy true if potential energy should be computed
* @param groups a set of bit flags for which force groups to include
* @param valid the method may set this to false to indicate the results are invalid and the force/energy
* calculation should be repeated
* @return the potential energy of the system. This value is added to all values returned by ForceImpls'
* calcForcesAndEnergy() methods. That is, each force kernel may <i>either</i> return its contribution to the
* energy directly, <i>or</i> add it to an internal buffer so that it will be included here.
*/
double
finishComputation
(
ContextImpl
&
context
,
bool
includeForce
,
bool
includeEnergy
,
int
groups
);
double
finishComputation
(
ContextImpl
&
context
,
bool
includeForce
,
bool
includeEnergy
,
int
groups
,
bool
&
valid
);
private:
class
BeginComputationTask
;
class
FinishComputationTask
;
...
...
@@ -81,10 +83,13 @@ private:
std
::
vector
<
Kernel
>
kernels
;
std
::
vector
<
long
long
>
completionTimes
;
std
::
vector
<
double
>
contextNonbondedFractions
;
int
*
tileCounts
;
CudaArray
*
contextForces
;
void
*
pinnedPositionBuffer
;
long
long
*
pinnedForceBuffer
;
CUfunction
sumKernel
;
CUevent
event
;
CUstream
peerCopyStream
;
};
/**
...
...
@@ -340,6 +345,13 @@ public:
* @return the potential energy due to the force
*/
double
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
);
/**
* Copy changed parameters over to a context.
*
* @param context the context to copy parameters to
* @param force the CMAPTorsionForce to copy the parameters from
*/
void
copyParametersToContext
(
ContextImpl
&
context
,
const
CMAPTorsionForce
&
force
);
private:
class
Task
;
CudaPlatform
::
PlatformData
&
data
;
...
...
Prev
1
…
7
8
9
10
11
12
13
Next
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