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
232
Hide 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
232 of 232+
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&
...
@@ -53,6 +53,8 @@ KernelImpl* CpuKernelFactory::createKernelImpl(std::string name, const Platform&
return
new
CpuCalcCustomManyParticleForceKernel
(
name
,
platform
,
data
);
return
new
CpuCalcCustomManyParticleForceKernel
(
name
,
platform
,
data
);
if
(
name
==
CalcGBSAOBCForceKernel
::
Name
())
if
(
name
==
CalcGBSAOBCForceKernel
::
Name
())
return
new
CpuCalcGBSAOBCForceKernel
(
name
,
platform
,
data
);
return
new
CpuCalcGBSAOBCForceKernel
(
name
,
platform
,
data
);
if
(
name
==
CalcCustomGBForceKernel
::
Name
())
return
new
CpuCalcCustomGBForceKernel
(
name
,
platform
,
data
);
if
(
name
==
IntegrateLangevinStepKernel
::
Name
())
if
(
name
==
IntegrateLangevinStepKernel
::
Name
())
return
new
CpuIntegrateLangevinStepKernel
(
name
,
platform
,
data
);
return
new
CpuIntegrateLangevinStepKernel
(
name
,
platform
,
data
);
throw
OpenMMException
((
std
::
string
(
"Tried to create kernel with illegal kernel name '"
)
+
name
+
"'"
).
c_str
());
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 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2013-201
4
Stanford University and the Authors. *
* Portions copyright (c) 2013-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -73,6 +73,11 @@ static RealVec& extractBoxSize(ContextImpl& context) {
...
@@ -73,6 +73,11 @@ static RealVec& extractBoxSize(ContextImpl& context) {
return
*
(
RealVec
*
)
data
->
periodicBoxSize
;
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
)
{
static
ReferenceConstraints
&
extractConstraints
(
ContextImpl
&
context
)
{
ReferencePlatform
::
PlatformData
*
data
=
reinterpret_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
ReferencePlatform
::
PlatformData
*
data
=
reinterpret_cast
<
ReferencePlatform
::
PlatformData
*>
(
context
.
getPlatformData
());
return
*
(
ReferenceConstraints
*
)
data
->
constraints
;
return
*
(
ReferenceConstraints
*
)
data
->
constraints
;
...
@@ -140,32 +145,55 @@ public:
...
@@ -140,32 +145,55 @@ public:
class
CpuCalcForcesAndEnergyKernel
::
InitForceTask
:
public
ThreadPool
::
Task
{
class
CpuCalcForcesAndEnergyKernel
::
InitForceTask
:
public
ThreadPool
::
Task
{
public:
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
)
{
void
execute
(
ThreadPool
&
threads
,
int
threadIndex
)
{
// Convert the positions to single precision and apply periodic boundary conditions
// Convert the positions to single precision and apply periodic boundary conditions
AlignedArray
<
float
>&
posq
=
data
.
posq
;
AlignedArray
<
float
>&
posq
=
data
.
posq
;
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
RealVec
boxSize
=
extractBoxSize
(
context
);
RealVec
*
boxVectors
=
extractBoxVectors
(
context
);
double
invBoxSize
[
3
]
=
{
1
/
boxSize
[
0
],
1
/
boxSize
[
1
],
1
/
boxSize
[
2
]};
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
numParticles
=
context
.
getSystem
().
getNumParticles
();
int
numThreads
=
threads
.
getNumThreads
();
int
numThreads
=
threads
.
getNumThreads
();
int
start
=
threadIndex
*
numParticles
/
numThreads
;
int
start
=
threadIndex
*
numParticles
/
numThreads
;
int
end
=
(
threadIndex
+
1
)
*
numParticles
/
numThreads
;
int
end
=
(
threadIndex
+
1
)
*
numParticles
/
numThreads
;
if
(
data
.
isPeriodic
)
if
(
data
.
isPeriodic
)
{
for
(
int
i
=
start
;
i
<
end
;
i
++
)
if
(
triclinic
)
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
for
(
int
i
=
start
;
i
<
end
;
i
++
)
{
RealOpenMM
x
=
posData
[
i
][
j
];
RealVec
pos
=
posData
[
i
];
double
base
=
floor
(
x
*
invBoxSize
[
j
])
*
boxSize
[
j
];
pos
-=
boxVectors
[
2
]
*
floor
(
pos
[
2
]
*
invBoxSize
[
2
]);
posq
[
4
*
i
+
j
]
=
(
float
)
(
x
-
base
);
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
else
for
(
int
i
=
start
;
i
<
end
;
i
++
)
{
for
(
int
i
=
start
;
i
<
end
;
i
++
)
{
posq
[
4
*
i
]
=
(
float
)
posData
[
i
][
0
];
posq
[
4
*
i
]
=
(
float
)
posData
[
i
][
0
];
posq
[
4
*
i
+
1
]
=
(
float
)
posData
[
i
][
1
];
posq
[
4
*
i
+
1
]
=
(
float
)
posData
[
i
][
1
];
posq
[
4
*
i
+
2
]
=
(
float
)
posData
[
i
][
2
];
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.
// Clear the forces.
...
@@ -174,6 +202,7 @@ public:
...
@@ -174,6 +202,7 @@ public:
zero
.
store
(
&
data
.
threadForce
[
threadIndex
][
j
*
4
]);
zero
.
store
(
&
data
.
threadForce
[
threadIndex
][
j
*
4
]);
}
}
int
numParticles
;
int
numParticles
;
bool
positionsValid
;
ContextImpl
&
context
;
ContextImpl
&
context
;
CpuPlatform
::
PlatformData
&
data
;
CpuPlatform
::
PlatformData
&
data
;
};
};
...
@@ -194,19 +223,21 @@ void CpuCalcForcesAndEnergyKernel::beginComputation(ContextImpl& context, bool i
...
@@ -194,19 +223,21 @@ void CpuCalcForcesAndEnergyKernel::beginComputation(ContextImpl& context, bool i
referenceKernel
.
getAs
<
ReferenceCalcForcesAndEnergyKernel
>
().
beginComputation
(
context
,
includeForce
,
includeEnergy
,
groups
);
referenceKernel
.
getAs
<
ReferenceCalcForcesAndEnergyKernel
>
().
beginComputation
(
context
,
includeForce
,
includeEnergy
,
groups
);
// Convert positions to single precision and clear the forces.
// Convert positions to single precision and clear the forces.
InitForceTask
task
(
context
.
getSystem
().
getNumParticles
(),
context
,
data
);
InitForceTask
task
(
context
.
getSystem
().
getNumParticles
(),
context
,
data
);
data
.
threads
.
execute
(
task
);
data
.
threads
.
execute
(
task
);
data
.
threads
.
waitForThreads
();
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.
// Sum the forces from all the threads.
SumForceTask
task
(
context
.
getSystem
().
getNumParticles
(),
extractForces
(
context
),
data
);
SumForceTask
task
(
context
.
getSystem
().
getNumParticles
(),
extractForces
(
context
),
data
);
data
.
threads
.
execute
(
task
);
data
.
threads
.
execute
(
task
);
data
.
threads
.
waitForThreads
();
data
.
threads
.
waitForThreads
();
return
referenceKernel
.
getAs
<
ReferenceCalcForcesAndEnergyKernel
>
().
finishComputation
(
context
,
includeForce
,
includeEnergy
,
groups
);
return
referenceKernel
.
getAs
<
ReferenceCalcForcesAndEnergyKernel
>
().
finishComputation
(
context
,
includeForce
,
includeEnergy
,
groups
,
valid
);
}
}
CpuCalcPeriodicTorsionForceKernel
::~
CpuCalcPeriodicTorsionForceKernel
()
{
CpuCalcPeriodicTorsionForceKernel
::~
CpuCalcPeriodicTorsionForceKernel
()
{
...
@@ -477,21 +508,19 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
...
@@ -477,21 +508,19 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
if
(
nonbondedMethod
==
PME
)
{
if
(
nonbondedMethod
==
PME
)
{
// If available, use the optimized PME implementation.
// 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
=
getPlatform
().
createKernel
(
CalcPmeReciprocalForceKernel
::
Name
(),
context
);
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
initialize
(
gridSize
[
0
],
gridSize
[
1
],
gridSize
[
2
],
numParticles
,
ewaldAlpha
);
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
;
AlignedArray
<
float
>&
posq
=
data
.
posq
;
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
RealVec
boxSize
=
extractBoxSize
(
context
);
RealVec
*
boxVectors
=
extractBoxVectors
(
context
);
float
floatBoxSize
[
3
]
=
{(
float
)
boxSize
[
0
],
(
float
)
boxSize
[
1
],
(
float
)
boxSize
[
2
]};
double
energy
=
(
includeReciprocal
?
ewaldSelfEnergy
:
0.0
);
double
energy
=
(
includeReciprocal
?
ewaldSelfEnergy
:
0.0
);
bool
ewald
=
(
nonbondedMethod
==
Ewald
);
bool
ewald
=
(
nonbondedMethod
==
Ewald
);
bool
pme
=
(
nonbondedMethod
==
PME
);
bool
pme
=
(
nonbondedMethod
==
PME
);
...
@@ -537,16 +566,17 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
...
@@ -537,16 +566,17 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
}
}
}
}
if
(
needRecompute
)
{
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
;
lastPositions
=
posData
;
}
}
nonbonded
->
setUseCutoff
(
nonbondedCutoff
,
*
neighborList
,
rfDielectric
);
nonbonded
->
setUseCutoff
(
nonbondedCutoff
,
*
neighborList
,
rfDielectric
);
}
}
if
(
data
.
isPeriodic
)
{
if
(
data
.
isPeriodic
)
{
RealVec
*
boxVectors
=
extractBoxVectors
(
context
);
double
minAllowedSize
=
1.999999
*
nonbondedCutoff
;
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."
);
throw
OpenMMException
(
"The periodic box size has decreased to less than twice the nonbonded cutoff."
);
nonbonded
->
setPeriodic
(
floatBoxSize
);
nonbonded
->
setPeriodic
(
boxVectors
);
}
}
if
(
ewald
)
if
(
ewald
)
nonbonded
->
setUseEwald
(
ewaldAlpha
,
kmax
[
0
],
kmax
[
1
],
kmax
[
2
]);
nonbonded
->
setUseEwald
(
ewaldAlpha
,
kmax
[
0
],
kmax
[
1
],
kmax
[
2
]);
...
@@ -560,8 +590,8 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
...
@@ -560,8 +590,8 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
if
(
includeReciprocal
)
{
if
(
includeReciprocal
)
{
if
(
useOptimizedPme
)
{
if
(
useOptimizedPme
)
{
PmeIO
io
(
&
posq
[
0
],
&
data
.
threadForce
[
0
][
0
],
numParticles
);
PmeIO
io
(
&
posq
[
0
],
&
data
.
threadForce
[
0
][
0
],
numParticles
);
Vec3
periodicBox
Size
(
boxSize
[
0
],
box
Size
[
1
],
box
Size
[
2
]
)
;
Vec3
periodicBox
Vectors
[
3
]
=
{
boxVectors
[
0
],
box
Vectors
[
1
],
box
Vectors
[
2
]
}
;
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
beginComputation
(
io
,
periodicBox
Size
,
includeEnergy
);
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
beginComputation
(
io
,
periodicBox
Vectors
,
includeEnergy
);
nonbondedEnergy
+=
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
finishComputation
(
io
);
nonbondedEnergy
+=
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
finishComputation
(
io
);
}
}
else
else
...
@@ -573,7 +603,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
...
@@ -573,7 +603,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
ReferenceLJCoulomb14
nonbonded14
;
ReferenceLJCoulomb14
nonbonded14
;
refBondForce
.
calculateForce
(
num14
,
bonded14IndexArray
,
posData
,
bonded14ParamArray
,
forceData
,
includeEnergy
?
&
energy
:
NULL
,
nonbonded14
);
refBondForce
.
calculateForce
(
num14
,
bonded14IndexArray
,
posData
,
bonded14ParamArray
,
forceData
,
includeEnergy
?
&
energy
:
NULL
,
nonbonded14
);
if
(
data
.
isPeriodic
)
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
;
return
energy
;
}
}
...
@@ -727,19 +757,18 @@ void CpuCalcCustomNonbondedForceKernel::initialize(const System& system, const C
...
@@ -727,19 +757,18 @@ void CpuCalcCustomNonbondedForceKernel::initialize(const System& system, const C
double
CpuCalcCustomNonbondedForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
double
CpuCalcCustomNonbondedForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
RealVec
&
box
=
extractBoxSize
(
context
);
RealVec
*
boxVectors
=
extractBoxVectors
(
context
);
float
floatBoxSize
[
3
]
=
{(
float
)
box
[
0
],
(
float
)
box
[
1
],
(
float
)
box
[
2
]};
double
energy
=
0
;
double
energy
=
0
;
bool
periodic
=
(
nonbondedMethod
==
CutoffPeriodic
);
bool
periodic
=
(
nonbondedMethod
==
CutoffPeriodic
);
if
(
nonbondedMethod
!=
NoCutoff
)
{
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
);
nonbonded
->
setUseCutoff
(
nonbondedCutoff
,
*
neighborList
);
}
}
if
(
periodic
)
{
if
(
periodic
)
{
double
minAllowedSize
=
2
*
nonbondedCutoff
;
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."
);
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
;
bool
globalParamsChanged
=
false
;
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
{
...
@@ -758,7 +787,7 @@ double CpuCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool inc
...
@@ -758,7 +787,7 @@ double CpuCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool inc
longRangeCoefficient
=
CustomNonbondedForceImpl
::
calcLongRangeCorrection
(
*
forceCopy
,
context
.
getOwner
());
longRangeCoefficient
=
CustomNonbondedForceImpl
::
calcLongRangeCorrection
(
*
forceCopy
,
context
.
getOwner
());
hasInitializedLongRangeCorrection
=
true
;
hasInitializedLongRangeCorrection
=
true
;
}
}
energy
+=
longRangeCoefficient
/
(
box
[
0
]
*
box
[
1
]
*
box
[
2
]);
energy
+=
longRangeCoefficient
/
(
box
Vectors
[
0
][
0
]
*
boxVectors
[
1
][
1
]
*
boxVectors
[
2
]
[
2
]);
return
energy
;
return
energy
;
}
}
...
@@ -802,6 +831,7 @@ void CpuCalcGBSAOBCForceKernel::initialize(const System& system, const GBSAOBCFo
...
@@ -802,6 +831,7 @@ void CpuCalcGBSAOBCForceKernel::initialize(const System& system, const GBSAOBCFo
obc
.
setParticleParameters
(
particleParams
);
obc
.
setParticleParameters
(
particleParams
);
obc
.
setSolventDielectric
((
float
)
force
.
getSolventDielectric
());
obc
.
setSolventDielectric
((
float
)
force
.
getSolventDielectric
());
obc
.
setSoluteDielectric
((
float
)
force
.
getSoluteDielectric
());
obc
.
setSoluteDielectric
((
float
)
force
.
getSoluteDielectric
());
obc
.
setSurfaceAreaEnergy
((
float
)
force
.
getSurfaceAreaEnergy
());
if
(
force
.
getNonbondedMethod
()
!=
GBSAOBCForce
::
NoCutoff
)
if
(
force
.
getNonbondedMethod
()
!=
GBSAOBCForce
::
NoCutoff
)
obc
.
setUseCutoff
((
float
)
force
.
getCutoffDistance
());
obc
.
setUseCutoff
((
float
)
force
.
getCutoffDistance
());
data
.
isPeriodic
=
(
force
.
getNonbondedMethod
()
==
GBSAOBCForce
::
CutoffPeriodic
);
data
.
isPeriodic
=
(
force
.
getNonbondedMethod
()
==
GBSAOBCForce
::
CutoffPeriodic
);
...
@@ -835,6 +865,167 @@ void CpuCalcGBSAOBCForceKernel::copyParametersToContext(ContextImpl& context, co
...
@@ -835,6 +865,167 @@ void CpuCalcGBSAOBCForceKernel::copyParametersToContext(ContextImpl& context, co
obc
.
setParticleParameters
(
particleParams
);
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
()
{
CpuCalcCustomManyParticleForceKernel
::~
CpuCalcCustomManyParticleForceKernel
()
{
if
(
particleParamArray
!=
NULL
)
{
if
(
particleParamArray
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
...
@@ -866,6 +1057,7 @@ void CpuCalcCustomManyParticleForceKernel::initialize(const System& system, cons
...
@@ -866,6 +1057,7 @@ void CpuCalcCustomManyParticleForceKernel::initialize(const System& system, cons
ixn
=
new
CpuCustomManyParticleForce
(
force
,
data
.
threads
);
ixn
=
new
CpuCustomManyParticleForce
(
force
,
data
.
threads
);
nonbondedMethod
=
CalcCustomManyParticleForceKernel
::
NonbondedMethod
(
force
.
getNonbondedMethod
());
nonbondedMethod
=
CalcCustomManyParticleForceKernel
::
NonbondedMethod
(
force
.
getNonbondedMethod
());
cutoffDistance
=
force
.
getCutoffDistance
();
cutoffDistance
=
force
.
getCutoffDistance
();
data
.
isPeriodic
=
(
nonbondedMethod
==
CutoffPeriodic
);
}
}
double
CpuCalcCustomManyParticleForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
double
CpuCalcCustomManyParticleForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
...
@@ -873,11 +1065,11 @@ double CpuCalcCustomManyParticleForceKernel::execute(ContextImpl& context, bool
...
@@ -873,11 +1065,11 @@ double CpuCalcCustomManyParticleForceKernel::execute(ContextImpl& context, bool
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
globalParameters
[
globalParameterNames
[
i
]]
=
context
.
getParameter
(
globalParameterNames
[
i
]);
globalParameters
[
globalParameterNames
[
i
]]
=
context
.
getParameter
(
globalParameterNames
[
i
]);
if
(
nonbondedMethod
==
CutoffPeriodic
)
{
if
(
nonbondedMethod
==
CutoffPeriodic
)
{
RealVec
&
box
=
extractBox
Size
(
context
);
RealVec
*
box
Vectors
=
extractBox
Vectors
(
context
);
double
minAllowedSize
=
2
*
cutoffDistance
;
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."
);
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
;
double
energy
=
0
;
ixn
->
calculateIxn
(
data
.
posq
,
particleParamArray
,
globalParameters
,
data
.
threadForce
,
includeForces
,
includeEnergy
,
energy
);
ixn
->
calculateIxn
(
data
.
posq
,
particleParamArray
,
globalParameters
,
data
.
threadForce
,
includeForces
,
includeEnergy
,
energy
);
...
...
platforms/cpu/src/CpuLangevinDynamics.cpp
View file @
61d5cc0f
...
@@ -23,8 +23,6 @@
...
@@ -23,8 +23,6 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMLog.h"
#include "SimTKOpenMMUtilities.h"
#include "SimTKOpenMMUtilities.h"
#include "CpuLangevinDynamics.h"
#include "CpuLangevinDynamics.h"
...
...
platforms/cpu/src/CpuNeighborList.cpp
View file @
61d5cc0f
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2013 Stanford University and the Authors.
*
* Portions copyright (c) 2013
-2015
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -45,12 +45,12 @@ namespace OpenMM {
...
@@ -45,12 +45,12 @@ namespace OpenMM {
class
VoxelIndex
class
VoxelIndex
{
{
public:
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
y
;
int
z
;
};
};
/**
/**
...
@@ -59,26 +59,35 @@ public:
...
@@ -59,26 +59,35 @@ public:
*/
*/
class
CpuNeighborList
::
Voxels
{
class
CpuNeighborList
::
Voxels
{
public:
public:
Voxels
(
int
blockSize
,
float
vsx
,
float
vsy
,
float
minx
,
float
maxx
,
float
miny
,
float
maxy
,
const
float
*
periodicBoxSize
,
bool
usePeriodic
)
:
Voxels
(
int
blockSize
,
float
vsy
,
float
vsz
,
float
miny
,
float
maxy
,
float
minz
,
float
maxz
,
const
RealVec
*
periodicBoxVectors
,
bool
usePeriodic
)
:
blockSize
(
blockSize
),
voxelSizeX
(
vsx
),
voxelSizeY
(
vsy
),
minx
(
minx
),
maxx
(
maxx
),
miny
(
miny
),
maxy
(
maxy
),
periodicBoxSize
(
periodicBoxSize
),
usePeriodic
(
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
)
{
if
(
usePeriodic
)
{
n
x
=
(
int
)
floorf
(
periodicBox
Size
[
0
]
/
voxelSize
X
+
0.5
f
);
n
y
=
(
int
)
floorf
(
periodicBox
Vectors
[
1
][
1
]
/
voxelSize
Y
+
0.5
f
);
n
y
=
(
int
)
floorf
(
periodicBox
Size
[
1
]
/
voxelSize
Y
+
0.5
f
);
n
z
=
(
int
)
floorf
(
periodicBox
Vectors
[
2
][
2
]
/
voxelSize
Z
+
0.5
f
);
voxelSize
X
=
periodicBox
Size
[
0
]
/
n
x
;
voxelSize
Y
=
periodicBox
Vectors
[
1
][
1
]
/
n
y
;
voxelSize
Y
=
periodicBox
Size
[
1
]
/
n
y
;
voxelSize
Z
=
periodicBox
Vectors
[
2
][
2
]
/
n
z
;
}
}
else
{
else
{
nx
=
max
(
1
,
(
int
)
floorf
((
maxx
-
minx
)
/
voxelSizeX
+
0.5
f
));
ny
=
max
(
1
,
(
int
)
floorf
((
maxy
-
miny
)
/
voxelSizeY
+
0.5
f
));
ny
=
max
(
1
,
(
int
)
floorf
((
maxy
-
miny
)
/
voxelSizeY
+
0.5
f
));
if
(
maxx
>
minx
)
nz
=
max
(
1
,
(
int
)
floorf
((
maxz
-
minz
)
/
voxelSizeZ
+
0.5
f
));
voxelSizeX
=
(
maxx
-
minx
)
/
nx
;
if
(
maxy
>
miny
)
if
(
maxy
>
miny
)
voxelSizeY
=
(
maxy
-
miny
)
/
ny
;
voxelSizeY
=
(
maxy
-
miny
)
/
ny
;
if
(
maxz
>
minz
)
voxelSizeZ
=
(
maxz
-
minz
)
/
nz
;
}
}
bins
.
resize
(
n
x
);
bins
.
resize
(
n
y
);
for
(
int
i
=
0
;
i
<
n
x
;
i
++
)
{
for
(
int
i
=
0
;
i
<
n
y
;
i
++
)
{
bins
[
i
].
resize
(
n
y
);
bins
[
i
].
resize
(
n
z
);
for
(
int
j
=
0
;
j
<
n
y
;
j
++
)
for
(
int
j
=
0
;
j
<
n
z
;
j
++
)
bins
[
i
][
j
].
resize
(
0
);
bins
[
i
][
j
].
resize
(
0
);
}
}
}
}
...
@@ -88,28 +97,28 @@ public:
...
@@ -88,28 +97,28 @@ public:
*/
*/
void
insert
(
const
int
&
atom
,
const
float
*
location
)
{
void
insert
(
const
int
&
atom
,
const
float
*
location
)
{
VoxelIndex
voxelIndex
=
getVoxelIndex
(
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
()
{
void
sortItems
()
{
for
(
int
i
=
0
;
i
<
n
x
;
i
++
)
for
(
int
i
=
0
;
i
<
n
y
;
i
++
)
for
(
int
j
=
0
;
j
<
n
y
;
j
++
)
for
(
int
j
=
0
;
j
<
n
z
;
j
++
)
sort
(
bins
[
i
][
j
].
begin
(),
bins
[
i
][
j
].
end
());
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
{
int
findLowerBound
(
int
y
,
int
z
,
double
x
)
const
{
const
vector
<
pair
<
float
,
int
>
>&
bin
=
bins
[
x
][
y
];
const
vector
<
pair
<
float
,
int
>
>&
bin
=
bins
[
y
][
z
];
int
lower
=
0
;
int
lower
=
0
;
int
upper
=
bin
.
size
();
int
upper
=
bin
.
size
();
while
(
lower
<
upper
)
{
while
(
lower
<
upper
)
{
int
middle
=
(
lower
+
upper
)
/
2
;
int
middle
=
(
lower
+
upper
)
/
2
;
if
(
bin
[
middle
].
first
<
z
)
if
(
bin
[
middle
].
first
<
x
)
lower
=
middle
+
1
;
lower
=
middle
+
1
;
else
else
upper
=
middle
;
upper
=
middle
;
...
@@ -118,15 +127,15 @@ public:
...
@@ -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
{
int
findUpperBound
(
int
y
,
int
z
,
double
x
)
const
{
const
vector
<
pair
<
float
,
int
>
>&
bin
=
bins
[
x
][
y
];
const
vector
<
pair
<
float
,
int
>
>&
bin
=
bins
[
y
][
z
];
int
lower
=
0
;
int
lower
=
0
;
int
upper
=
bin
.
size
();
int
upper
=
bin
.
size
();
while
(
lower
<
upper
)
{
while
(
lower
<
upper
)
{
int
middle
=
(
lower
+
upper
)
/
2
;
int
middle
=
(
lower
+
upper
)
/
2
;
if
(
bin
[
middle
].
first
>
z
)
if
(
bin
[
middle
].
first
>
x
)
upper
=
middle
;
upper
=
middle
;
else
else
lower
=
middle
+
1
;
lower
=
middle
+
1
;
...
@@ -138,131 +147,167 @@ public:
...
@@ -138,131 +147,167 @@ public:
* Get the voxel index containing a particular location.
* Get the voxel index containing a particular location.
*/
*/
VoxelIndex
getVoxelIndex
(
const
float
*
location
)
const
{
VoxelIndex
getVoxelIndex
(
const
float
*
location
)
const
{
float
x
periodic
,
y
periodic
;
float
y
periodic
,
z
periodic
;
if
(
!
usePeriodic
)
{
if
(
!
usePeriodic
)
{
xperiodic
=
location
[
0
]
-
minx
;
yperiodic
=
location
[
1
]
-
miny
;
yperiodic
=
location
[
1
]
-
miny
;
zperiodic
=
location
[
2
]
-
minz
;
}
}
else
{
else
{
xperiodic
=
location
[
0
]
-
periodicBoxSize
[
0
]
*
floorf
(
location
[
0
]
/
periodicBoxSize
[
0
]);
float
scale2
=
floorf
(
location
[
2
]
*
recipBoxSize
[
2
]);
yperiodic
=
location
[
1
]
-
periodicBoxSize
[
1
]
*
floorf
(
location
[
1
]
/
periodicBoxSize
[
1
]);
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
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
);
neighbors
.
resize
(
0
);
exclusions
.
resize
(
0
);
exclusions
.
resize
(
0
);
fvec4
boxSize
(
periodicBoxSize
[
0
],
periodicBoxSize
[
1
],
periodicBoxSize
[
2
],
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
maxDistanceSquared
=
maxDistance
*
maxDistance
;
float
refineCutoff
=
maxDistance
-
max
(
max
(
blockWidth
[
0
],
blockWidth
[
1
]),
blockWidth
[
2
]);
float
refineCutoff
=
maxDistance
-
max
(
max
(
blockWidth
[
0
],
blockWidth
[
1
]),
blockWidth
[
2
]);
float
refineCutoffSquared
=
refineCutoff
*
refineCutoff
;
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
;
// How may voxels away do we have to look?
int
dIndex
Y
=
int
((
maxDistance
+
blockWidth
[
1
])
/
voxelSize
Y
)
+
1
;
int
dIndex
Z
=
int
((
maxDistance
+
blockWidth
[
2
])
/
voxelSize
Z
)
+
1
;
if
(
usePeriodic
)
{
if
(
usePeriodic
)
{
dIndexX
=
min
(
nx
/
2
,
dIndexX
);
dIndexY
=
min
(
ny
/
2
,
dIndexY
);
dIndexY
=
min
(
ny
/
2
,
dIndexY
);
dIndexZ
=
min
(
nz
/
2
,
dIndexZ
);
}
}
float
centerPos
[
4
];
float
centerPos
[
4
];
blockCenter
.
store
(
centerPos
);
blockCenter
.
store
(
centerPos
);
VoxelIndex
centerVoxelIndex
=
getVoxelIndex
(
centerPos
);
VoxelIndex
centerVoxelIndex
=
getVoxelIndex
(
centerPos
);
int
startx
=
centerVoxelIndex
.
x
-
dIndexX
;
int
starty
=
centerVoxelIndex
.
y
-
dIndexY
;
// Loop over voxels along the z axis.
int
endx
=
centerVoxelIndex
.
x
+
dIndexX
;
int
endy
=
centerVoxelIndex
.
y
+
dIndexY
;
int
startz
=
centerVoxelIndex
.
z
-
dIndexZ
;
int
numRanges
;
int
endz
=
centerVoxelIndex
.
z
+
dIndexZ
;
if
(
usePeriodic
)
{
if
(
usePeriodic
)
endx
=
min
(
endx
,
centerVoxelIndex
.
x
-
dIndexX
+
nx
-
1
);
endz
=
min
(
endz
,
startz
+
nz
-
1
);
endy
=
min
(
endy
,
centerVoxelIndex
.
y
-
dIndexY
+
ny
-
1
);
}
else
{
else
{
startx
=
max
(
startx
,
0
);
startz
=
max
(
startz
,
0
);
starty
=
max
(
starty
,
0
);
endz
=
min
(
endz
,
nz
-
1
);
endx
=
min
(
endx
,
nx
-
1
);
endy
=
min
(
endy
,
ny
-
1
);
}
}
int
lastSortedIndex
=
blockSize
*
(
blockIndex
+
1
);
int
lastSortedIndex
=
blockSize
*
(
blockIndex
+
1
);
VoxelIndex
voxelIndex
(
0
,
0
);
VoxelIndex
voxelIndex
(
0
,
0
);
for
(
int
x
=
start
x
;
x
<=
end
x
;
++
x
)
{
for
(
int
z
=
start
z
;
z
<=
end
z
;
++
z
)
{
voxelIndex
.
x
=
x
;
voxelIndex
.
z
=
z
;
if
(
usePeriodic
)
if
(
usePeriodic
)
voxelIndex
.
x
=
(
x
<
0
?
x
+
nx
:
(
x
>=
nx
?
x
-
nx
:
x
));
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
endy
=
centerVoxelIndex
.
y
+
dIndexY
;
float
yoffset
=
(
float
)
(
usePeriodic
?
boxz
*
periodicBoxVectors
[
2
][
1
]
:
0
);
if
(
usePeriodic
)
{
starty
-=
(
int
)
ceil
(
yoffset
/
voxelSizeY
);
endy
-=
(
int
)
floor
(
yoffset
/
voxelSizeY
);
endy
=
min
(
endy
,
starty
+
ny
-
1
);
}
else
{
starty
=
max
(
starty
,
0
);
endy
=
min
(
endy
,
ny
-
1
);
}
for
(
int
y
=
starty
;
y
<=
endy
;
++
y
)
{
for
(
int
y
=
starty
;
y
<=
endy
;
++
y
)
{
voxelIndex
.
y
=
y
;
voxelIndex
.
y
=
y
;
if
(
usePeriodic
)
if
(
usePeriodic
)
voxelIndex
.
y
=
(
y
<
0
?
y
+
ny
:
(
y
>=
ny
?
y
-
ny
:
y
));
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
// Identify the range of atoms within this bin we need to search. When using periodic boundary
// conditions, there may be two separate ranges.
// conditions, there may be two separate ranges.
float
minz
=
centerPos
[
2
];
float
minx
=
centerPos
[
0
];
float
maxz
=
centerPos
[
2
];
float
maxx
=
centerPos
[
0
];
fvec4
offset
(
voxelSizeX
*
x
+
(
usePeriodic
?
0.0
f
:
minx
),
voxelSizeY
*
y
+
(
usePeriodic
?
0.0
f
:
miny
),
0
,
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
++
)
{
for
(
int
k
=
0
;
k
<
(
int
)
blockAtoms
.
size
();
k
+=
4
)
{
const
float
*
atomPos
=
&
atomLocations
[
4
*
blockAtoms
[
k
]];
fvec4
dist2
=
maxDistanceSquared
;
fvec4
posVec
(
atomPos
);
if
(
y
!=
atomVoxelIndex
[
k
].
y
)
{
fvec4
delta1
=
offset
-
posVec
;
fvec4
dy1
=
offset
[
1
]
-
fvec4
(
&
blockAtomY
[
k
]);
fvec4
delta2
=
delta1
+
fvec4
(
voxelSizeX
,
voxelSizeY
,
0
,
0
);
fvec4
dy2
=
dy1
+
voxelSizeY
;
if
(
usePeriodic
)
{
if
(
usePeriodic
)
{
delta1
-=
round
(
delta1
*
invBoxSize
)
*
boxSize
;
dy1
-=
round
(
dy1
*
invBoxSize
[
1
])
*
boxSize
[
1
];
delta2
-=
round
(
delta2
*
invBoxSize
)
*
boxSize
;
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
)
{
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
));
fvec4
dist
=
sqrt
(
dist2
);
float
dx
=
(
x
==
atomVoxelIndex
[
k
].
x
?
0.0
f
:
delta
[
0
]);
int
numToCheck
=
min
(
4
,
(
int
)
(
blockAtoms
.
size
()
-
k
));
float
dy
=
(
y
==
atomVoxelIndex
[
k
].
y
?
0.0
f
:
delta
[
1
]);
for
(
int
m
=
0
;
m
<
numToCheck
;
m
++
)
{
float
dist2
=
maxDistanceSquared
-
dx
*
dx
-
dy
*
dy
;
minx
=
min
(
minx
,
blockAtomX
[
k
+
m
]
-
dist
[
m
]
-
xoffset
);
if
(
dist2
>
0
)
{
maxx
=
max
(
maxx
,
blockAtomX
[
k
+
m
]
+
dist
[
m
]
-
xoffset
);
float
dist
=
sqrtf
(
dist2
);
minz
=
min
(
minz
,
atomPos
[
2
]
-
dist
);
maxz
=
max
(
maxz
,
atomPos
[
2
]
+
dist
);
}
}
}
}
if
(
min
z
==
max
z
)
if
(
min
x
==
max
x
)
continue
;
continue
;
bool
needPeriodic
=
(
centerPos
[
0
]
-
blockWidth
[
0
]
<
maxDistance
||
centerPos
[
0
]
+
blockWidth
[
0
]
>
periodicBoxSize
[
0
]
-
maxDistance
||
bool
needPeriodic
=
(
centerPos
[
1
]
-
blockWidth
[
1
]
<
maxDistance
||
centerPos
[
1
]
+
blockWidth
[
1
]
>
periodicBoxSize
[
1
]
-
maxDistance
||
centerPos
[
1
]
-
blockWidth
[
1
]
<
maxDistance
||
centerPos
[
1
]
+
blockWidth
[
1
]
>
periodicBoxSize
[
1
]
-
maxDistance
||
centerPos
[
2
]
-
blockWidth
[
2
]
<
maxDistance
||
centerPos
[
2
]
+
blockWidth
[
2
]
>
periodicBoxSize
[
2
]
-
maxDistance
||
minz
<
0.0
f
||
maxz
>
periodicBoxSize
[
2
]);
minx
<
0.0
f
||
maxx
>
periodicBoxVectors
[
0
][
0
]);
int
numRanges
;
int
rangeStart
[
2
];
int
rangeStart
[
2
];
int
rangeEnd
[
2
];
int
rangeEnd
[
2
];
rangeStart
[
0
]
=
findLowerBound
(
voxelIndex
.
x
,
voxelIndex
.
y
,
min
z
);
rangeStart
[
0
]
=
findLowerBound
(
voxelIndex
.
y
,
voxelIndex
.
z
,
min
x
);
if
(
needPeriodic
)
{
if
(
needPeriodic
)
{
numRanges
=
2
;
numRanges
=
2
;
rangeEnd
[
0
]
=
findUpperBound
(
voxelIndex
.
x
,
voxelIndex
.
y
,
max
z
);
rangeEnd
[
0
]
=
findUpperBound
(
voxelIndex
.
y
,
voxelIndex
.
z
,
max
x
);
if
(
rangeStart
[
0
]
>
0
)
{
if
(
rangeStart
[
0
]
>
0
)
{
rangeStart
[
1
]
=
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
{
else
{
rangeStart
[
1
]
=
max
(
findLowerBound
(
voxelIndex
.
x
,
voxelIndex
.
y
,
min
z
+
periodicBoxSize
[
2
]),
rangeEnd
[
0
]);
rangeStart
[
1
]
=
max
(
findLowerBound
(
voxelIndex
.
y
,
voxelIndex
.
z
,
min
x
+
periodicBoxSize
[
0
]),
rangeEnd
[
0
]);
rangeEnd
[
1
]
=
bins
[
voxelIndex
.
x
][
voxelIndex
.
y
].
size
();
rangeEnd
[
1
]
=
bins
[
voxelIndex
.
y
][
voxelIndex
.
z
].
size
();
}
}
}
}
else
{
else
{
numRanges
=
1
;
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.
// Loop over atoms and check to see if they are neighbors of this block.
for
(
int
range
=
0
;
range
<
numRanges
;
range
++
)
{
for
(
int
range
=
0
;
range
<
numRanges
;
range
++
)
{
for
(
int
item
=
rangeStart
[
range
];
item
<
rangeEnd
[
range
];
item
++
)
{
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.
// Avoid duplicate entries.
if
(
sortedIndex
>=
lastSortedIndex
)
if
(
sortedIndex
>=
lastSortedIndex
)
continue
;
continue
;
fvec4
atomPos
(
atomLocations
+
4
*
sortedAtoms
[
sortedIndex
]);
fvec4
atomPos
(
&
sortedPositions
[
4
*
sortedIndex
]);
fvec4
delta
=
atomPos
-
centerPos
;
fvec4
delta
=
atomPos
-
centerPos
;
if
(
needPeriodic
)
{
if
(
periodicRectangular
)
fvec4
base
=
round
(
delta
*
invBoxSize
)
*
boxSize
;
delta
-=
round
(
delta
*
invBoxSize
)
*
boxSize
;
delta
=
delta
-
base
;
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
);
delta
=
max
(
0.0
f
,
abs
(
delta
)
-
blockWidth
);
float
dSquared
=
dot3
(
delta
,
delta
);
float
dSquared
=
dot3
(
delta
,
delta
);
...
@@ -273,21 +318,34 @@ public:
...
@@ -273,21 +318,34 @@ public:
// The distance is large enough that there might not be any actual interactions.
// The distance is large enough that there might not be any actual interactions.
// Check individual atom pairs to be sure.
// Check individual atom pairs to be sure.
bool
any
=
false
;
bool
anyInteraction
=
false
;
for
(
int
k
=
0
;
k
<
(
int
)
blockAtoms
.
size
();
k
++
)
{
for
(
int
k
=
0
;
k
<
(
int
)
blockAtoms
.
size
();
k
+=
4
)
{
fvec4
pos1
(
&
atomLocations
[
4
*
blockAtoms
[
k
]]);
fvec4
dx
=
fvec4
(
&
blockAtomX
[
k
])
-
atomPos
[
0
];
delta
=
atomPos
-
pos1
;
fvec4
dy
=
fvec4
(
&
blockAtomY
[
k
])
-
atomPos
[
1
];
if
(
needPeriodic
)
{
fvec4
dz
=
fvec4
(
&
blockAtomZ
[
k
])
-
atomPos
[
2
];
fvec4
base
=
round
(
delta
*
invBoxSize
)
*
boxSize
;
if
(
periodicRectangular
)
{
delta
=
delta
-
base
;
dx
-=
round
(
dx
*
invBoxSize
[
0
])
*
boxSize
[
0
];
dy
-=
round
(
dy
*
invBoxSize
[
1
])
*
boxSize
[
1
];
dz
-=
round
(
dz
*
invBoxSize
[
2
])
*
boxSize
[
2
];
}
}
float
r2
=
dot3
(
delta
,
delta
);
else
if
(
needPeriodic
)
{
if
(
r2
<
maxDistanceSquared
)
{
fvec4
scale3
=
floor
(
dz
*
recipBoxSize
[
2
]
+
0.5
f
);
any
=
true
;
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
;
break
;
}
}
}
}
if
(
!
any
)
if
(
!
any
Interaction
)
continue
;
continue
;
}
}
...
@@ -308,10 +366,12 @@ public:
...
@@ -308,10 +366,12 @@ public:
private:
private:
int
blockSize
;
int
blockSize
;
float
voxelSizeX
,
voxelSizeY
;
float
voxelSizeY
,
voxelSizeZ
;
float
minx
,
maxx
,
miny
,
maxy
;
float
miny
,
maxy
,
minz
,
maxz
;
int
nx
,
ny
;
int
ny
,
nz
;
const
float
*
periodicBoxSize
;
float
periodicBoxSize
[
3
],
recipBoxSize
[
3
];
bool
triclinic
;
const
RealVec
*
periodicBoxVectors
;
const
bool
usePeriodic
;
const
bool
usePeriodic
;
vector
<
vector
<
vector
<
pair
<
float
,
int
>
>
>
>
bins
;
vector
<
vector
<
vector
<
pair
<
float
,
int
>
>
>
>
bins
;
};
};
...
@@ -330,17 +390,20 @@ CpuNeighborList::CpuNeighborList(int blockSize) : blockSize(blockSize) {
...
@@ -330,17 +390,20 @@ CpuNeighborList::CpuNeighborList(int blockSize) : blockSize(blockSize) {
}
}
void
CpuNeighborList
::
computeNeighborList
(
int
numAtoms
,
const
AlignedArray
<
float
>&
atomLocations
,
const
vector
<
set
<
int
>
>&
exclusions
,
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
;
int
numBlocks
=
(
numAtoms
+
blockSize
-
1
)
/
blockSize
;
blockNeighbors
.
resize
(
numBlocks
);
blockNeighbors
.
resize
(
numBlocks
);
blockExclusions
.
resize
(
numBlocks
);
blockExclusions
.
resize
(
numBlocks
);
sortedAtoms
.
resize
(
numAtoms
);
sortedAtoms
.
resize
(
numAtoms
);
sortedPositions
.
resize
(
4
*
numAtoms
);
// Record the parameters for the threads.
// Record the parameters for the threads.
this
->
exclusions
=
&
exclusions
;
this
->
exclusions
=
&
exclusions
;
this
->
atomLocations
=
&
atomLocations
[
0
];
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
->
numAtoms
=
numAtoms
;
this
->
usePeriodic
=
usePeriodic
;
this
->
usePeriodic
=
usePeriodic
;
this
->
maxDistance
=
maxDistance
;
this
->
maxDistance
=
maxDistance
;
...
@@ -370,23 +433,25 @@ void CpuNeighborList::computeNeighborList(int numAtoms, const AlignedArray<float
...
@@ -370,23 +433,25 @@ void CpuNeighborList::computeNeighborList(int numAtoms, const AlignedArray<float
sort
(
atomBins
.
begin
(),
atomBins
.
end
());
sort
(
atomBins
.
begin
(),
atomBins
.
end
());
// Build the voxel hash.
// Build the voxel hash.
float
edgeSize
X
,
edgeSize
Y
;
float
edgeSize
Y
,
edgeSize
Z
;
if
(
!
usePeriodic
)
if
(
!
usePeriodic
)
edgeSize
X
=
edgeSize
Y
=
maxDistance
;
// TODO - adjust this as needed
edgeSize
Y
=
edgeSize
Z
=
maxDistance
;
// TODO - adjust this as needed
else
{
else
{
edgeSize
X
=
0.6
f
*
periodicBox
Size
[
0
]
/
floorf
(
periodicBox
Size
[
0
]
/
maxDistance
);
edgeSize
Y
=
0.6
f
*
periodicBox
Vectors
[
1
][
1
]
/
floorf
(
periodicBox
Vectors
[
1
][
1
]
/
maxDistance
);
edgeSize
Y
=
0.6
f
*
periodicBox
Size
[
1
]
/
floorf
(
periodicBox
Size
[
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
++
)
{
for
(
int
i
=
0
;
i
<
numAtoms
;
i
++
)
{
int
atomIndex
=
atomBins
[
i
].
second
;
int
atomIndex
=
atomBins
[
i
].
second
;
sortedAtoms
[
i
]
=
atomIndex
;
sortedAtoms
[
i
]
=
atomIndex
;
fvec4
atomPos
(
&
atomLocations
[
4
*
atomIndex
]);
atomPos
.
store
(
&
sortedPositions
[
4
*
i
]);
voxels
.
insert
(
i
,
&
atomLocations
[
4
*
atomIndex
]);
voxels
.
insert
(
i
,
&
atomLocations
[
4
*
atomIndex
]);
}
}
voxels
.
sortItems
();
voxels
.
sortItems
();
this
->
voxels
=
&
voxels
;
this
->
voxels
=
&
voxels
;
// Signal the threads to start running and wait for them to finish.
// Signal the threads to start running and wait for them to finish.
threads
.
resumeThreads
();
threads
.
resumeThreads
();
...
@@ -443,6 +508,7 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
...
@@ -443,6 +508,7 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
int
numBlocks
=
blockNeighbors
.
size
();
int
numBlocks
=
blockNeighbors
.
size
();
vector
<
int
>
blockAtoms
;
vector
<
int
>
blockAtoms
;
vector
<
float
>
blockAtomX
(
blockSize
),
blockAtomY
(
blockSize
),
blockAtomZ
(
blockSize
);
vector
<
VoxelIndex
>
atomVoxelIndex
;
vector
<
VoxelIndex
>
atomVoxelIndex
;
for
(
int
i
=
threadIndex
;
i
<
numBlocks
;
i
+=
numThreads
)
{
for
(
int
i
=
threadIndex
;
i
<
numBlocks
;
i
+=
numThreads
)
{
// Find the atoms in this block and compute their bounding box.
// Find the atoms in this block and compute their bounding box.
...
@@ -455,14 +521,24 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
...
@@ -455,14 +521,24 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
blockAtoms
[
j
]
=
sortedAtoms
[
firstIndex
+
j
];
blockAtoms
[
j
]
=
sortedAtoms
[
firstIndex
+
j
];
atomVoxelIndex
[
j
]
=
voxels
->
getVoxelIndex
(
&
atomLocations
[
4
*
blockAtoms
[
j
]]);
atomVoxelIndex
[
j
]
=
voxels
->
getVoxelIndex
(
&
atomLocations
[
4
*
blockAtoms
[
j
]]);
}
}
fvec4
minPos
(
&
atomLocations
[
4
*
sortedAtoms
[
firstIndex
]
]
);
fvec4
minPos
(
&
sortedPositions
[
4
*
firstIndex
]);
fvec4
maxPos
=
minPos
;
fvec4
maxPos
=
minPos
;
for
(
int
j
=
1
;
j
<
atomsInBlock
;
j
++
)
{
for
(
int
j
=
1
;
j
<
atomsInBlock
;
j
++
)
{
fvec4
pos
(
&
atomLocations
[
4
*
sortedAtoms
[
firstIndex
+
j
]
]);
fvec4
pos
(
&
sortedPositions
[
4
*
(
firstIndex
+
j
)
]);
minPos
=
min
(
minPos
,
pos
);
minPos
=
min
(
minPos
,
pos
);
maxPos
=
max
(
maxPos
,
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.
// Record the exclusions for this block.
...
...
platforms/cpu/src/CpuNonbondedForce.cpp
View file @
61d5cc0f
...
@@ -24,7 +24,6 @@
...
@@ -24,7 +24,6 @@
#include <complex>
#include <complex>
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMUtilities.h"
#include "SimTKOpenMMUtilities.h"
#include "CpuNonbondedForce.h"
#include "CpuNonbondedForce.h"
#include "ReferenceForce.h"
#include "ReferenceForce.h"
...
@@ -103,20 +102,30 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
...
@@ -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
also been set, and the smallest side of the periodic box is at least twice the cutoff
distance.
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
(
cutoff
);
assert
(
periodicBox
Size
[
0
]
>=
2
*
cutoffDistance
);
assert
(
periodicBox
Vectors
[
0
]
[
0
]
>=
2
.0
*
cutoffDistance
);
assert
(
periodicBox
Size
[
1
]
>=
2
*
cutoffDistance
);
assert
(
periodicBox
Vectors
[
1
]
[
1
]
>=
2
.0
*
cutoffDistance
);
assert
(
periodicBox
Size
[
2
]
>=
2
*
cutoffDistance
);
assert
(
periodicBox
Vectors
[
2
]
[
2
]
>=
2
.0
*
cutoffDistance
);
periodic
=
true
;
periodic
=
true
;
this
->
periodicBoxSize
[
0
]
=
periodicBoxSize
[
0
];
this
->
periodicBoxVectors
[
0
]
=
periodicBoxVectors
[
0
];
this
->
periodicBoxSize
[
1
]
=
periodicBoxSize
[
1
];
this
->
periodicBoxVectors
[
1
]
=
periodicBoxVectors
[
1
];
this
->
periodicBoxSize
[
2
]
=
periodicBoxSize
[
2
];
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
...
@@ -186,18 +195,16 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
int
kmax
=
(
ewald
?
max
(
numRx
,
max
(
numRy
,
numRz
))
:
0
);
int
kmax
=
(
ewald
?
max
(
numRx
,
max
(
numRy
,
numRz
))
:
0
);
float
factorEwald
=
-
1
/
(
4
*
alphaEwald
*
alphaEwald
);
float
factorEwald
=
-
1
/
(
4
*
alphaEwald
*
alphaEwald
);
float
TWO_PI
=
2.0
*
PI_M
;
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
)
{
if
(
pme
)
{
pme_t
pmedata
;
pme_t
pmedata
;
RealOpenMM
virial
[
3
][
3
];
pme_init
(
&
pmedata
,
alphaEwald
,
numberOfAtoms
,
meshDim
,
5
,
1
);
pme_init
(
&
pmedata
,
alphaEwald
,
numberOfAtoms
,
meshDim
,
5
,
1
);
vector
<
RealOpenMM
>
charges
(
numberOfAtoms
);
vector
<
RealOpenMM
>
charges
(
numberOfAtoms
);
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
)
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
)
charges
[
i
]
=
posq
[
4
*
i
+
3
];
charges
[
i
]
=
posq
[
4
*
i
+
3
];
RealOpenMM
boxSize
[
3
]
=
{
periodicBoxSize
[
0
],
periodicBoxSize
[
1
],
periodicBoxSize
[
2
]};
RealOpenMM
recipEnergy
=
0.0
;
RealOpenMM
recipEnergy
=
0.0
;
pme_exec
(
pmedata
,
atomCoordinates
,
forces
,
charges
,
boxSize
,
&
recipEnergy
,
virial
);
pme_exec
(
pmedata
,
atomCoordinates
,
forces
,
charges
,
periodicBoxVectors
,
&
recipEnergy
);
if
(
totalEnergy
)
if
(
totalEnergy
)
*
totalEnergy
+=
recipEnergy
;
*
totalEnergy
+=
recipEnergy
;
pme_destroy
(
pmedata
);
pme_destroy
(
pmedata
);
...
@@ -209,7 +216,7 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
...
@@ -209,7 +216,7 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
// setup reciprocal box
// 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
// setup K-vectors
...
@@ -330,8 +337,8 @@ void CpuNonbondedForce::threadComputeDirect(ThreadPool& threads, int threadIndex
...
@@ -330,8 +337,8 @@ void CpuNonbondedForce::threadComputeDirect(ThreadPool& threads, int threadIndex
threadEnergy
[
threadIndex
]
=
0
;
threadEnergy
[
threadIndex
]
=
0
;
double
*
energyPtr
=
(
includeEnergy
?
&
threadEnergy
[
threadIndex
]
:
NULL
);
double
*
energyPtr
=
(
includeEnergy
?
&
threadEnergy
[
threadIndex
]
:
NULL
);
float
*
forces
=
&
(
*
threadForce
)[
threadIndex
][
0
];
float
*
forces
=
&
(
*
threadForce
)[
threadIndex
][
0
];
fvec4
boxSize
(
periodicBox
Size
[
0
],
periodicBox
Size
[
1
],
periodicBox
Size
[
2
],
0
);
fvec4
boxSize
(
periodicBox
Vectors
[
0
]
[
0
],
periodicBox
Vectors
[
1
]
[
1
],
periodicBox
Vectors
[
2
]
[
2
],
0
);
fvec4
invBoxSize
(
(
1
/
periodic
BoxSize
[
0
]
)
,
(
1
/
periodic
BoxSize
[
1
]
)
,
(
1
/
periodic
BoxSize
[
2
]
)
,
0
);
fvec4
invBoxSize
(
recip
BoxSize
[
0
],
recip
BoxSize
[
1
],
recip
BoxSize
[
2
],
0
);
if
(
ewald
||
pme
)
{
if
(
ewald
||
pme
)
{
// Compute the interactions from the neighbor list.
// Compute the interactions from the neighbor list.
...
@@ -344,8 +351,6 @@ void CpuNonbondedForce::threadComputeDirect(ThreadPool& threads, int threadIndex
...
@@ -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.
// 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
)
{
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
);
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
)
{
for
(
set
<
int
>::
const_iterator
iter
=
exclusions
[
i
].
begin
();
iter
!=
exclusions
[
i
].
end
();
++
iter
)
{
...
@@ -454,8 +459,15 @@ void CpuNonbondedForce::calculateOneIxn(int ii, int jj, float* forces, double* t
...
@@ -454,8 +459,15 @@ 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
{
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
;
deltaR
=
posJ
-
posI
;
if
(
periodic
)
{
if
(
periodic
)
{
fvec4
base
=
round
(
deltaR
*
invBoxSize
)
*
boxSize
;
if
(
triclinic
)
{
deltaR
=
deltaR
-
base
;
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
);
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
* Contributors: Pande Group
*
*
* Permission is hereby granted, free of charge, to any person obtaining
* Permission is hereby granted, free of charge, to any person obtaining
...
@@ -22,7 +22,6 @@
...
@@ -22,7 +22,6 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMUtilities.h"
#include "SimTKOpenMMUtilities.h"
#include "CpuNonbondedForceVec4.h"
#include "CpuNonbondedForceVec4.h"
...
@@ -45,15 +44,68 @@ CpuNonbondedForce* createCpuNonbondedForceVec4() {
...
@@ -45,15 +44,68 @@ CpuNonbondedForce* createCpuNonbondedForceVec4() {
CpuNonbondedForceVec4
::
CpuNonbondedForceVec4
()
{
CpuNonbondedForceVec4
::
CpuNonbondedForceVec4
()
{
}
}
enum
PeriodicType
{
NoPeriodic
,
PeriodicPerAtom
,
PeriodicPerInteraction
,
PeriodicTriclinic
};
void
CpuNonbondedForceVec4
::
calculateBlockIxn
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
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.
// 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
blockAtomPosq
[
4
];
fvec4
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
fvec4
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
blockAtom
[
i
]
=
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
+
i
];
blockAtomPosq
[
i
]
=
fvec4
(
posq
+
4
*
blockAtom
[
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
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
]);
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
...
@@ -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
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
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
);
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
)
||
const
bool
needPeriodic
=
(
PERIODIC_TYPE
==
PeriodicPerInteraction
||
PERIODIC_TYPE
==
PeriodicTriclinic
);
any
(
blockAtomX
>
boxSize
[
0
]
-
cutoffDistance
)
||
any
(
blockAtomY
>
boxSize
[
1
]
-
cutoffDistance
)
||
any
(
blockAtomZ
>
boxSize
[
2
]
-
cutoffDistance
)));
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
// Loop over neighbors for this block.
// Loop over neighbors for this block.
...
@@ -77,7 +128,10 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
...
@@ -77,7 +128,10 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
// Compute the distances to the block atoms.
// Compute the distances to the block atoms.
fvec4
dx
,
dy
,
dz
,
r2
;
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
;
ivec4
include
;
char
excl
=
exclusions
[
i
];
char
excl
=
exclusions
[
i
];
if
(
excl
==
0
)
if
(
excl
==
0
)
...
@@ -90,8 +144,7 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
...
@@ -90,8 +144,7 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
// Compute the interactions.
// Compute the interactions.
fvec4
r
=
sqrt
(
r2
);
fvec4
inverseR
=
rsqrt
(
r2
);
fvec4
inverseR
=
fvec4
(
1.0
f
)
/
r
;
fvec4
energy
,
dEdR
;
fvec4
energy
,
dEdR
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
if
(
atomEpsilon
!=
0.0
f
)
{
if
(
atomEpsilon
!=
0.0
f
)
{
...
@@ -103,6 +156,7 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
...
@@ -103,6 +156,7 @@ void CpuNonbondedForceVec4::calculateBlockIxn(int blockIndex, float* forces, dou
dEdR
=
epsSig6
*
(
12.0
f
*
sig6
-
6.0
f
);
dEdR
=
epsSig6
*
(
12.0
f
*
sig6
-
6.0
f
);
energy
=
epsSig6
*
(
sig6
-
1.0
f
);
energy
=
epsSig6
*
(
sig6
-
1.0
f
);
if
(
useSwitch
)
{
if
(
useSwitch
)
{
fvec4
r
=
r2
*
inverseR
;
fvec4
t
=
blend
(
0.0
f
,
(
r
-
switchingDistance
)
*
invSwitchingInterval
,
r
>
switchingDistance
);
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
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
;
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
...
@@ -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
)
{
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.
// 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
blockAtomPosq
[
4
];
fvec4
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
fvec4
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
blockAtom
[
i
]
=
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
+
i
];
blockAtomPosq
[
i
]
=
fvec4
(
posq
+
4
*
blockAtom
[
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
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
]);
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
...
@@ -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
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
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
);
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
)
||
const
bool
needPeriodic
=
(
PERIODIC_TYPE
==
PeriodicPerInteraction
||
PERIODIC_TYPE
==
PeriodicTriclinic
);
any
(
blockAtomX
>
boxSize
[
0
]
-
cutoffDistance
)
||
any
(
blockAtomY
>
boxSize
[
1
]
-
cutoffDistance
)
||
any
(
blockAtomZ
>
boxSize
[
2
]
-
cutoffDistance
)));
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
// Loop over neighbors for this block.
// Loop over neighbors for this block.
...
@@ -188,7 +292,10 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
...
@@ -188,7 +292,10 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
// Compute the distances to the block atoms.
// Compute the distances to the block atoms.
fvec4
dx
,
dy
,
dz
,
r2
;
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
;
ivec4
include
;
char
excl
=
exclusions
[
i
];
char
excl
=
exclusions
[
i
];
if
(
excl
==
0
)
if
(
excl
==
0
)
...
@@ -201,8 +308,8 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
...
@@ -201,8 +308,8 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
// Compute the interactions.
// Compute the interactions.
fvec4
r
=
sqrt
(
r2
);
fvec4
inverseR
=
r
sqrt
(
r2
);
fvec4
inverseR
=
fvec4
(
1.0
f
)
/
r
;
fvec4
r
=
r2
*
inverseR
;
fvec4
energy
,
dEdR
;
fvec4
energy
,
dEdR
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
if
(
atomEpsilon
!=
0.0
f
)
{
if
(
atomEpsilon
!=
0.0
f
)
{
...
@@ -261,11 +368,23 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
...
@@ -261,11 +368,23 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
(
fvec4
(
forces
+
4
*
blockAtom
[
j
])
+
f
[
j
]).
store
(
forces
+
4
*
blockAtom
[
j
]);
(
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
];
dx
=
x
-
posI
[
0
];
dy
=
y
-
posI
[
1
];
dy
=
y
-
posI
[
1
];
dz
=
z
-
posI
[
2
];
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
];
dx
-=
round
(
dx
*
invBoxSize
[
0
])
*
boxSize
[
0
];
dy
-=
round
(
dy
*
invBoxSize
[
1
])
*
boxSize
[
1
];
dy
-=
round
(
dy
*
invBoxSize
[
1
])
*
boxSize
[
1
];
dz
-=
round
(
dz
*
invBoxSize
[
2
])
*
boxSize
[
2
];
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
* Contributors: Pande Group
*
*
* Permission is hereby granted, free of charge, to any person obtaining
* Permission is hereby granted, free of charge, to any person obtaining
...
@@ -22,7 +22,6 @@
...
@@ -22,7 +22,6 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMUtilities.h"
#include "SimTKOpenMMUtilities.h"
#include "CpuNonbondedForceVec8.h"
#include "CpuNonbondedForceVec8.h"
#include "openmm/OpenMMException.h"
#include "openmm/OpenMMException.h"
...
@@ -31,6 +30,12 @@
...
@@ -31,6 +30,12 @@
using
namespace
std
;
using
namespace
std
;
using
namespace
OpenMM
;
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__
#ifndef __AVX__
bool
isVec8Supported
()
{
bool
isVec8Supported
()
{
return
false
;
return
false
;
...
@@ -45,7 +50,7 @@ CpuNonbondedForce* createCpuNonbondedForceVec8() {
...
@@ -45,7 +50,7 @@ CpuNonbondedForce* createCpuNonbondedForceVec8() {
*/
*/
bool
isVec8Supported
()
{
bool
isVec8Supported
()
{
// Make sure the CPU supports AVX.
// Make sure the CPU supports AVX.
int
cpuInfo
[
4
];
int
cpuInfo
[
4
];
cpuid
(
cpuInfo
,
0
);
cpuid
(
cpuInfo
,
0
);
if
(
cpuInfo
[
0
]
>=
1
)
{
if
(
cpuInfo
[
0
]
>=
1
)
{
...
@@ -71,23 +76,75 @@ CpuNonbondedForce* createCpuNonbondedForceVec8() {
...
@@ -71,23 +76,75 @@ CpuNonbondedForce* createCpuNonbondedForceVec8() {
CpuNonbondedForceVec8
::
CpuNonbondedForceVec8
()
{
CpuNonbondedForceVec8
::
CpuNonbondedForceVec8
()
{
}
}
enum
PeriodicType
{
NoPeriodic
,
PeriodicPerAtom
,
PeriodicPerInteraction
,
PeriodicTriclinic
};
void
CpuNonbondedForceVec8
::
calculateBlockIxn
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
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.
// Load the positions and parameters of the atoms in the block.
int
blockAtom
[
8
];
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
8
*
blockIndex
];
fvec4
blockAtomPosq
[
8
];
fvec4
blockAtomPosq
[
8
];
fvec8
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
fvec8
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
fvec8
blockAtomX
,
blockAtomY
,
blockAtomZ
,
blockAtomCharge
;
fvec8
blockAtomX
,
blockAtomY
,
blockAtomZ
,
blockAtomCharge
;
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
blockAtom
[
i
]
=
neighborList
->
getSortedAtoms
()[
8
*
blockIndex
+
i
];
blockAtomPosq
[
i
]
=
fvec4
(
posq
+
4
*
blockAtom
[
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
);
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
;
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
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
);
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
)
||
const
bool
needPeriodic
=
(
PERIODIC_TYPE
==
PeriodicPerInteraction
||
PERIODIC_TYPE
==
PeriodicTriclinic
);
any
(
blockAtomX
>
boxSize
[
0
]
-
cutoffDistance
)
||
any
(
blockAtomY
>
boxSize
[
1
]
-
cutoffDistance
)
||
any
(
blockAtomZ
>
boxSize
[
2
]
-
cutoffDistance
)));
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
// Loop over neighbors for this block.
// Loop over neighbors for this block.
...
@@ -102,7 +159,10 @@ void CpuNonbondedForceVec8::calculateBlockIxn(int blockIndex, float* forces, dou
...
@@ -102,7 +159,10 @@ void CpuNonbondedForceVec8::calculateBlockIxn(int blockIndex, float* forces, dou
// Compute the distances to the block atoms.
// Compute the distances to the block atoms.
fvec8
dx
,
dy
,
dz
,
r2
;
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
;
ivec8
include
;
char
excl
=
exclusions
[
i
];
char
excl
=
exclusions
[
i
];
if
(
excl
==
0
)
if
(
excl
==
0
)
...
@@ -115,8 +175,7 @@ void CpuNonbondedForceVec8::calculateBlockIxn(int blockIndex, float* forces, dou
...
@@ -115,8 +175,7 @@ void CpuNonbondedForceVec8::calculateBlockIxn(int blockIndex, float* forces, dou
// Compute the interactions.
// Compute the interactions.
fvec8
r
=
sqrt
(
r2
);
fvec8
inverseR
=
rsqrt
(
r2
);
fvec8
inverseR
=
fvec8
(
1.0
f
)
/
r
;
fvec8
energy
,
dEdR
;
fvec8
energy
,
dEdR
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
if
(
atomEpsilon
!=
0.0
f
)
{
if
(
atomEpsilon
!=
0.0
f
)
{
...
@@ -128,6 +187,7 @@ void CpuNonbondedForceVec8::calculateBlockIxn(int blockIndex, float* forces, dou
...
@@ -128,6 +187,7 @@ void CpuNonbondedForceVec8::calculateBlockIxn(int blockIndex, float* forces, dou
dEdR
=
epsSig6
*
(
12.0
f
*
sig6
-
6.0
f
);
dEdR
=
epsSig6
*
(
12.0
f
*
sig6
-
6.0
f
);
energy
=
epsSig6
*
(
sig6
-
1.0
f
);
energy
=
epsSig6
*
(
sig6
-
1.0
f
);
if
(
useSwitch
)
{
if
(
useSwitch
)
{
fvec8
r
=
r2
*
inverseR
;
fvec8
t
=
(
r
>
switchingDistance
)
&
((
r
-
switchingDistance
)
*
invSwitchingInterval
);
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
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
;
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
...
@@ -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
)
{
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.
// Load the positions and parameters of the atoms in the block.
int
blockAtom
[
8
];
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
8
*
blockIndex
];
fvec4
blockAtomPosq
[
8
];
fvec4
blockAtomPosq
[
8
];
fvec8
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
fvec8
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
fvec8
blockAtomX
,
blockAtomY
,
blockAtomZ
,
blockAtomCharge
;
fvec8
blockAtomX
,
blockAtomY
,
blockAtomZ
,
blockAtomCharge
;
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
blockAtom
[
i
]
=
neighborList
->
getSortedAtoms
()[
8
*
blockIndex
+
i
];
blockAtomPosq
[
i
]
=
fvec4
(
posq
+
4
*
blockAtom
[
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
);
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
;
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
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
);
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
)
||
const
bool
needPeriodic
=
(
PERIODIC_TYPE
==
PeriodicPerInteraction
||
PERIODIC_TYPE
==
PeriodicTriclinic
);
any
(
blockAtomX
>
boxSize
[
0
]
-
cutoffDistance
)
||
any
(
blockAtomY
>
boxSize
[
1
]
-
cutoffDistance
)
||
any
(
blockAtomZ
>
boxSize
[
2
]
-
cutoffDistance
)));
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
// Loop over neighbors for this block.
// Loop over neighbors for this block.
...
@@ -212,7 +322,10 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
...
@@ -212,7 +322,10 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
// Compute the distances to the block atoms.
// Compute the distances to the block atoms.
fvec8
dx
,
dy
,
dz
,
r2
;
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
;
ivec8
include
;
char
excl
=
exclusions
[
i
];
char
excl
=
exclusions
[
i
];
if
(
excl
==
0
)
if
(
excl
==
0
)
...
@@ -225,8 +338,8 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
...
@@ -225,8 +338,8 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
// Compute the interactions.
// Compute the interactions.
fvec8
r
=
sqrt
(
r2
);
fvec8
inverseR
=
r
sqrt
(
r2
);
fvec8
inverseR
=
fvec8
(
1.0
f
)
/
r
;
fvec8
r
=
r2
*
inverseR
;
fvec8
energy
,
dEdR
;
fvec8
energy
,
dEdR
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
float
atomEpsilon
=
atomParameters
[
atom
].
second
;
if
(
atomEpsilon
!=
0.0
f
)
{
if
(
atomEpsilon
!=
0.0
f
)
{
...
@@ -251,7 +364,7 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
...
@@ -251,7 +364,7 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
}
}
fvec8
chargeProd
=
blockAtomCharge
*
posq
[
4
*
atom
+
3
];
fvec8
chargeProd
=
blockAtomCharge
*
posq
[
4
*
atom
+
3
];
dEdR
+=
chargeProd
*
inverseR
*
ewaldScaleFunction
(
r
);
dEdR
+=
chargeProd
*
inverseR
*
ewaldScaleFunction
(
r
);
dEdR
*=
inverseR
*
inverseR
;
dEdR
*=
inverseR
*
inverseR
;
// Accumulate energies.
// Accumulate energies.
...
@@ -285,11 +398,23 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
...
@@ -285,11 +398,23 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxn(int blockIndex, float* forces
(
fvec4
(
forces
+
4
*
blockAtom
[
j
])
+
f
[
j
]).
store
(
forces
+
4
*
blockAtom
[
j
]);
(
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
];
dx
=
x
-
posI
[
0
];
dy
=
y
-
posI
[
1
];
dy
=
y
-
posI
[
1
];
dz
=
z
-
posI
[
2
];
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
];
dx
-=
round
(
dx
*
invBoxSize
[
0
])
*
boxSize
[
0
];
dy
-=
round
(
dy
*
invBoxSize
[
1
])
*
boxSize
[
1
];
dy
-=
round
(
dy
*
invBoxSize
[
1
])
*
boxSize
[
1
];
dz
-=
round
(
dz
*
invBoxSize
[
2
])
*
boxSize
[
2
];
dz
-=
round
(
dz
*
invBoxSize
[
2
])
*
boxSize
[
2
];
...
...
platforms/cpu/src/CpuPlatform.cpp
View file @
61d5cc0f
...
@@ -67,6 +67,7 @@ CpuPlatform::CpuPlatform() {
...
@@ -67,6 +67,7 @@ CpuPlatform::CpuPlatform() {
registerKernelFactory
(
CalcCustomNonbondedForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomNonbondedForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomManyParticleForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomManyParticleForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcGBSAOBCForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcGBSAOBCForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomGBForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateLangevinStepKernel
::
Name
(),
factory
);
platformProperties
.
push_back
(
CpuThreads
());
platformProperties
.
push_back
(
CpuThreads
());
int
threads
=
getNumProcessors
();
int
threads
=
getNumProcessors
();
...
...
platforms/cpu/src/CpuRandom.cpp
View file @
61d5cc0f
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
*/
*/
#include "CpuRandom.h"
#include "CpuRandom.h"
#include "openmm/internal/OSRngSeed.h"
#include "openmm/OpenMMException.h"
#include "openmm/OpenMMException.h"
#include <cmath>
#include <cmath>
...
@@ -49,9 +50,13 @@ void CpuRandom::initialize(int seed, int numThreads) {
...
@@ -49,9 +50,13 @@ void CpuRandom::initialize(int seed, int numThreads) {
nextGaussian
.
resize
(
numThreads
);
nextGaussian
.
resize
(
numThreads
);
nextGaussianIsValid
.
resize
(
numThreads
,
false
);
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
;
unsigned
int
r
=
(
unsigned
int
)
seed
;
if
(
r
==
0
)
r
=
(
unsigned
int
)
osrngseed
();
for
(
int
i
=
0
;
i
<
numThreads
;
i
++
)
{
for
(
int
i
=
0
;
i
<
numThreads
;
i
++
)
{
r
=
(
1664525
*
r
+
1013904223
)
&
0xFFFFFFFF
;
r
=
(
1664525
*
r
+
1013904223
)
&
0xFFFFFFFF
;
threadRandom
[
i
]
=
new
OpenMM_SFMT
::
SFMT
();
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,15 +53,36 @@ using namespace std;
...
@@ -53,15 +53,36 @@ using namespace std;
const
double
TOL
=
1e-5
;
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.
// Create a System and Context.
int
numParticles
=
force
->
getNumParticles
();
int
numParticles
=
force
->
getNumParticles
();
CustomManyParticleForce
::
NonbondedMethod
nonbondedMethod
=
force
->
getNonbondedMethod
();
CustomManyParticleForce
::
NonbondedMethod
nonbondedMethod
=
force
->
getNonbondedMethod
();
System
system
;
System
system
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
system
.
addParticle
(
1.0
);
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
);
system
.
addForce
(
force
);
VerletIntegrator
integrator
(
0.001
);
VerletIntegrator
integrator
(
0.001
);
CpuPlatform
platform
;
CpuPlatform
platform
;
...
@@ -69,24 +90,18 @@ void validateAxilrodTeller(CustomManyParticleForce* force, const vector<Vec3>& p
...
@@ -69,24 +90,18 @@ void validateAxilrodTeller(CustomManyParticleForce* force, const vector<Vec3>& p
context
.
setPositions
(
positions
);
context
.
setPositions
(
positions
);
State
state1
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
state1
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
double
c
=
context
.
getParameter
(
"C"
);
double
c
=
context
.
getParameter
(
"C"
);
// See if the energy matches the expected value.
// See if the energy matches the expected value.
double
expectedEnergy
=
0
;
double
expectedEnergy
=
0
;
bool
periodic
=
(
nonbondedMethod
==
CustomManyParticleForce
::
CutoffPeriodic
);
for
(
int
i
=
0
;
i
<
(
int
)
expectedSets
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
expectedSets
.
size
();
i
++
)
{
int
p1
=
expectedSets
[
i
][
0
];
int
p1
=
expectedSets
[
i
][
0
];
int
p2
=
expectedSets
[
i
][
1
];
int
p2
=
expectedSets
[
i
][
1
];
int
p3
=
expectedSets
[
i
][
2
];
int
p3
=
expectedSets
[
i
][
2
];
Vec3
d12
=
positions
[
p2
]
-
positions
[
p1
];
Vec3
d12
=
computeDelta
(
positions
[
p2
],
positions
[
p1
],
periodic
,
boxVectors
);
Vec3
d13
=
positions
[
p3
]
-
positions
[
p1
];
Vec3
d13
=
computeDelta
(
positions
[
p3
],
positions
[
p1
],
periodic
,
boxVectors
);
Vec3
d23
=
positions
[
p3
]
-
positions
[
p2
];
Vec3
d23
=
computeDelta
(
positions
[
p3
],
positions
[
p2
],
periodic
,
boxVectors
);
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
;
}
}
double
r12
=
sqrt
(
d12
.
dot
(
d12
));
double
r12
=
sqrt
(
d12
.
dot
(
d12
));
double
r13
=
sqrt
(
d13
.
dot
(
d13
));
double
r13
=
sqrt
(
d13
.
dot
(
d13
));
double
r23
=
sqrt
(
d23
.
dot
(
d23
));
double
r23
=
sqrt
(
d23
.
dot
(
d23
));
...
@@ -210,7 +225,7 @@ void testNoCutoff() {
...
@@ -210,7 +225,7 @@ void testNoCutoff() {
positions
.
push_back
(
Vec3
(
0.4
,
0
,
-
0.8
));
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
}};
int
sets
[
4
][
3
]
=
{{
0
,
1
,
2
},
{
1
,
2
,
3
},
{
2
,
3
,
0
},
{
3
,
0
,
1
}};
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
4
]);
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
4
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
,
false
);
}
}
void
testCutoff
()
{
void
testCutoff
()
{
...
@@ -235,7 +250,7 @@ void testCutoff() {
...
@@ -235,7 +250,7 @@ void testCutoff() {
positions
.
push_back
(
Vec3
(
0.2
,
0.5
,
-
0.1
));
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
}};
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
]);
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
7
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
,
false
);
}
}
void
testPeriodic
()
{
void
testPeriodic
()
{
...
@@ -261,7 +276,33 @@ void testPeriodic() {
...
@@ -261,7 +276,33 @@ void testPeriodic() {
double
boxSize
=
2.1
;
double
boxSize
=
2.1
;
int
sets
[
5
][
3
]
=
{{
0
,
1
,
3
},
{
0
,
1
,
4
},
{
0
,
2
,
4
},
{
0
,
3
,
4
},
{
1
,
3
,
4
}};
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
]);
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
()
{
void
testExclusions
()
{
...
@@ -286,7 +327,7 @@ void testExclusions() {
...
@@ -286,7 +327,7 @@ void testExclusions() {
force
->
addExclusion
(
0
,
3
);
force
->
addExclusion
(
0
,
3
);
int
sets
[
5
][
3
]
=
{{
0
,
1
,
4
},
{
1
,
2
,
3
},
{
1
,
2
,
4
},
{
1
,
3
,
4
},
{
2
,
3
,
4
}};
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
]);
vector
<
const
int
*>
expectedSets
(
&
sets
[
0
],
&
sets
[
5
]);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
);
validateAxilrodTeller
(
force
,
positions
,
expectedSets
,
2.0
,
false
);
}
}
void
testAllTerms
()
{
void
testAllTerms
()
{
...
@@ -673,9 +714,14 @@ void testCentralParticleModeLargeSystem() {
...
@@ -673,9 +714,14 @@ void testCentralParticleModeLargeSystem() {
int
main
()
{
int
main
()
{
try
{
try
{
if
(
!
CpuPlatform
::
isProcessorSupported
())
{
cout
<<
"CPU is not supported. Exiting."
<<
endl
;
return
0
;
}
testNoCutoff
();
testNoCutoff
();
testCutoff
();
testCutoff
();
testPeriodic
();
testPeriodic
();
testTriclinic
();
testExclusions
();
testExclusions
();
testAllTerms
();
testAllTerms
();
testParameters
();
testParameters
();
...
...
platforms/cpu/tests/TestCpuCustomNonbondedForce.cpp
View file @
61d5cc0f
...
@@ -224,6 +224,65 @@ void testPeriodic() {
...
@@ -224,6 +224,65 @@ void testPeriodic() {
ASSERT_EQUAL_TOL
(
1.9
+
1
+
0.9
,
state
.
getPotentialEnergy
(),
TOL
);
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
()
{
void
testContinuous1DFunction
()
{
System
system
;
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
...
@@ -852,6 +911,7 @@ int main() {
...
@@ -852,6 +911,7 @@ int main() {
testExclusions
();
testExclusions
();
testCutoff
();
testCutoff
();
testPeriodic
();
testPeriodic
();
testTriclinic
();
testContinuous1DFunction
();
testContinuous1DFunction
();
testContinuous2DFunction
();
testContinuous2DFunction
();
testContinuous3DFunction
();
testContinuous3DFunction
();
...
...
platforms/cpu/tests/TestCpuEwald.cpp
View file @
61d5cc0f
...
@@ -201,6 +201,57 @@ void testEwald2Ions() {
...
@@ -201,6 +201,57 @@ void testEwald2Ions() {
ASSERT_EQUAL_TOL
(
-
217.276
,
state
.
getPotentialEnergy
(),
0.01
/*10*TOL*/
);
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
)
{
void
testErrorTolerance
(
NonbondedForce
::
NonbondedMethod
method
)
{
// Create a cloud of random point charges.
// Create a cloud of random point charges.
...
@@ -261,6 +312,7 @@ int main(int argc, char* argv[]) {
...
@@ -261,6 +312,7 @@ int main(int argc, char* argv[]) {
testEwaldPME
(
false
);
testEwaldPME
(
false
);
testEwaldPME
(
true
);
testEwaldPME
(
true
);
// testEwald2Ions();
// testEwald2Ions();
testTriclinic
();
testErrorTolerance
(
NonbondedForce
::
Ewald
);
testErrorTolerance
(
NonbondedForce
::
Ewald
);
testErrorTolerance
(
NonbondedForce
::
PME
);
testErrorTolerance
(
NonbondedForce
::
PME
);
}
}
...
...
platforms/cpu/tests/TestCpuGBSAOBCForce.cpp
View file @
61d5cc0f
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
4
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -67,7 +67,7 @@ void testSingleParticle() {
...
@@ -67,7 +67,7 @@ void testSingleParticle() {
double
eps0
=
EPSILON0
;
double
eps0
=
EPSILON0
;
double
bornEnergy
=
(
-
0.5
*
0.5
/
(
8
*
PI_M
*
eps0
))
*
(
1.0
/
forceField
->
getSoluteDielectric
()
-
1.0
/
forceField
->
getSolventDielectric
())
/
bornRadius
;
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
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
);
ASSERT_EQUAL_TOL
((
bornEnergy
+
nonpolarEnergy
),
state
.
getPotentialEnergy
(),
0.01
);
// Change the parameters and see if it is still correct.
// Change the parameters and see if it is still correct.
...
@@ -77,8 +77,35 @@ void testSingleParticle() {
...
@@ -77,8 +77,35 @@ void testSingleParticle() {
state
=
context
.
getState
(
State
::
Energy
);
state
=
context
.
getState
(
State
::
Energy
);
bornRadius
=
0.25
-
0.009
;
// dielectric offset
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
;
bornEnergy
=
(
-
0.4
*
0.4
/
(
8
*
PI_M
*
eps0
))
*
(
1.0
/
forceField
->
getSoluteDielectric
()
-
1.0
/
forceField
->
getSolventDielectric
())
/
bornRadius
;
extendedRadius
=
bornRadius
+
0.14
;
extendedRadius
=
0.25
+
0.14
;
nonpolarEnergy
=
CAL2JOULE
*
PI_M
*
0.0216
*
(
10
*
extendedRadius
)
*
(
10
*
extendedRadius
)
*
std
::
pow
(
0.25
/
bornRadius
,
6.0
);
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
);
ASSERT_EQUAL_TOL
((
bornEnergy
+
nonpolarEnergy
),
state
.
getPotentialEnergy
(),
0.01
);
}
}
...
@@ -228,6 +255,7 @@ int main() {
...
@@ -228,6 +255,7 @@ int main() {
return
0
;
return
0
;
}
}
testSingleParticle
();
testSingleParticle
();
testGlobalSettings
();
testCutoffAndPeriodic
();
testCutoffAndPeriodic
();
for
(
int
i
=
5
;
i
<
11
;
i
++
)
{
for
(
int
i
=
5
;
i
<
11
;
i
++
)
{
testForce
(
i
*
i
*
i
,
NonbondedForce
::
NoCutoff
,
GBSAOBCForce
::
NoCutoff
);
testForce
(
i
*
i
*
i
,
NonbondedForce
::
NoCutoff
,
GBSAOBCForce
::
NoCutoff
);
...
...
platforms/cpu/tests/TestCpuNeighborList.cpp
View file @
61d5cc0f
...
@@ -48,10 +48,21 @@
...
@@ -48,10 +48,21 @@
using
namespace
OpenMM
;
using
namespace
OpenMM
;
using
namespace
std
;
using
namespace
std
;
void
testNeighborList
(
bool
periodic
)
{
void
testNeighborList
(
bool
periodic
,
bool
triclinic
)
{
const
int
numParticles
=
500
;
const
int
numParticles
=
500
;
const
float
cutoff
=
2.0
f
;
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
;
const
int
blockSize
=
8
;
OpenMM_SFMT
::
SFMT
sfmt
;
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
init_gen_rand
(
0
,
sfmt
);
...
@@ -69,7 +80,7 @@ void testNeighborList(bool periodic) {
...
@@ -69,7 +80,7 @@ void testNeighborList(bool periodic) {
}
}
ThreadPool
threads
;
ThreadPool
threads
;
CpuNeighborList
neighborList
(
blockSize
);
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.
// Convert the neighbor list to a set for faster lookup.
...
@@ -90,19 +101,17 @@ void testNeighborList(bool periodic) {
...
@@ -90,19 +101,17 @@ void testNeighborList(bool periodic) {
}
}
// Check each particle pair and figure out whether they should be in the neighbor list.
// Check each particle pair and figure out whether they should be in the neighbor list.
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
j
=
0
;
j
<=
i
;
j
++
)
{
for
(
int
j
=
0
;
j
<=
i
;
j
++
)
{
bool
shouldInclude
=
(
exclusions
[
i
].
find
(
j
)
==
exclusions
[
i
].
end
());
bool
shouldInclude
=
(
exclusions
[
i
].
find
(
j
)
==
exclusions
[
i
].
end
());
float
dx
=
positions
[
4
*
i
]
-
positions
[
4
*
j
];
Vec3
diff
(
positions
[
4
*
i
]
-
positions
[
4
*
j
],
positions
[
4
*
i
+
1
]
-
positions
[
4
*
j
+
1
],
positions
[
4
*
i
+
2
]
-
positions
[
4
*
j
+
2
]);
float
dy
=
positions
[
4
*
i
+
1
]
-
positions
[
4
*
j
+
1
];
float
dz
=
positions
[
4
*
i
+
2
]
-
positions
[
4
*
j
+
2
];
if
(
periodic
)
{
if
(
periodic
)
{
d
x
-=
floor
(
d
x
/
boxSize
[
0
]
+
0.5
f
)
*
boxSize
[
0
]
;
d
iff
-=
boxVectors
[
2
]
*
floor
(
d
iff
[
2
]
/
boxSize
[
2
]
+
0.5
)
;
d
y
-=
floor
(
d
y
/
boxSize
[
1
]
+
0.5
f
)
*
boxSize
[
1
]
;
d
iff
-=
boxVectors
[
1
]
*
floor
(
d
iff
[
1
]
/
boxSize
[
1
]
+
0.5
)
;
d
z
-=
floor
(
d
z
/
boxSize
[
2
]
+
0.5
f
)
*
boxSize
[
2
]
;
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
;
shouldInclude
=
false
;
bool
isIncluded
=
(
neighbors
.
find
(
make_pair
(
i
,
j
))
!=
neighbors
.
end
()
||
neighbors
.
find
(
make_pair
(
j
,
i
))
!=
neighbors
.
end
());
bool
isIncluded
=
(
neighbors
.
find
(
make_pair
(
i
,
j
))
!=
neighbors
.
end
()
||
neighbors
.
find
(
make_pair
(
j
,
i
))
!=
neighbors
.
end
());
if
(
shouldInclude
)
if
(
shouldInclude
)
...
@@ -116,8 +125,9 @@ int main() {
...
@@ -116,8 +125,9 @@ int main() {
cout
<<
"CPU is not supported. Exiting."
<<
endl
;
cout
<<
"CPU is not supported. Exiting."
<<
endl
;
return
0
;
return
0
;
}
}
testNeighborList
(
false
);
testNeighborList
(
false
,
false
);
testNeighborList
(
true
);
testNeighborList
(
true
,
false
);
testNeighborList
(
true
,
true
);
}
}
catch
(
const
exception
&
e
)
{
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
...
...
platforms/cpu/tests/TestCpuNonbondedForce.cpp
View file @
61d5cc0f
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -353,6 +353,67 @@ void testPeriodic() {
...
@@ -353,6 +353,67 @@ void testPeriodic() {
ASSERT_EQUAL_TOL
(
2
*
ONE_4PI_EPS0
*
(
1.0
)
*
(
1.0
+
krf
*
1.0
-
crf
),
state
.
getPotentialEnergy
(),
TOL
);
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
()
{
void
testLargeSystem
()
{
const
int
numMolecules
=
600
;
const
int
numMolecules
=
600
;
...
@@ -635,6 +696,7 @@ int main(int argc, char* argv[]) {
...
@@ -635,6 +696,7 @@ int main(int argc, char* argv[]) {
testCutoff
();
testCutoff
();
testCutoff14
();
testCutoff14
();
testPeriodic
();
testPeriodic
();
testTriclinic
();
testLargeSystem
();
testLargeSystem
();
testDispersionCorrection
();
testDispersionCorrection
();
testChangingParameters
();
testChangingParameters
();
...
...
platforms/cuda/include/CudaContext.h
View file @
61d5cc0f
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2009-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2009-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -41,6 +41,7 @@
...
@@ -41,6 +41,7 @@
#include <vector_functions.h>
#include <vector_functions.h>
#include "windowsExportCuda.h"
#include "windowsExportCuda.h"
#include "CudaPlatform.h"
#include "CudaPlatform.h"
#include "openmm/Kernel.h"
typedef
unsigned
int
tileflags
;
typedef
unsigned
int
tileflags
;
...
@@ -133,6 +134,18 @@ public:
...
@@ -133,6 +134,18 @@ public:
int
getContextIndex
()
const
{
int
getContextIndex
()
const
{
return
contextIndex
;
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.
* Get the array which contains the position (the xyz components) and charge (the w component) of each atom.
*/
*/
...
@@ -340,43 +353,62 @@ public:
...
@@ -340,43 +353,62 @@ public:
/**
/**
* Get whether double precision is being used.
* Get whether double precision is being used.
*/
*/
bool
getUseDoublePrecision
()
{
bool
getUseDoublePrecision
()
const
{
return
useDoublePrecision
;
return
useDoublePrecision
;
}
}
/**
/**
* Get whether mixed precision is being used.
* Get whether mixed precision is being used.
*/
*/
bool
getUseMixedPrecision
()
{
bool
getUseMixedPrecision
()
const
{
return
useMixedPrecision
;
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.
* 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.
* 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.
* 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.
* Convert a CUDA result code to the corresponding string description.
*/
*/
static
std
::
string
getErrorString
(
CUresult
result
);
static
std
::
string
getErrorString
(
CUresult
result
);
/**
/**
* Get the
size of
the periodic box.
* Get the
vectors defining
the periodic box.
*/
*/
double4
getPeriodicBoxSize
()
const
{
void
getPeriodicBoxVectors
(
Vec3
&
a
,
Vec3
&
b
,
Vec3
&
c
)
const
{
return
periodicBoxSize
;
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 vectors defining the periodic box.
*/
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
);
}
}
/**
/**
*
S
et the size of the periodic box.
*
G
et the size of the periodic box.
*/
*/
void
setPeriodicBoxSize
(
double
xsize
,
double
ysize
,
double
zsize
)
{
double4
getPeriodicBoxSize
()
const
{
periodicBoxSize
=
make_double4
(
xsize
,
ysize
,
zsize
,
0.0
);
return
periodicBoxSize
;
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
);
}
}
/**
/**
* Get the inverse of the size of the periodic box.
* Get the inverse of the size of the periodic box.
...
@@ -398,6 +430,27 @@ public:
...
@@ -398,6 +430,27 @@ public:
void
*
getInvPeriodicBoxSizePointer
()
{
void
*
getInvPeriodicBoxSizePointer
()
{
return
(
useDoublePrecision
?
reinterpret_cast
<
void
*>
(
&
invPeriodicBoxSize
)
:
reinterpret_cast
<
void
*>
(
&
invPeriodicBoxSizeFloat
));
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.
* Get the CudaIntegrationUtilities for this context.
*/
*/
...
@@ -513,14 +566,15 @@ private:
...
@@ -513,14 +566,15 @@ private:
int
paddedNumAtoms
;
int
paddedNumAtoms
;
int
numAtomBlocks
;
int
numAtomBlocks
;
int
numThreadBlocks
;
int
numThreadBlocks
;
bool
useBlockingSync
,
useDoublePrecision
,
useMixedPrecision
,
contextIsValid
,
atomsWereReordered
;
bool
useBlockingSync
,
useDoublePrecision
,
useMixedPrecision
,
contextIsValid
,
atomsWereReordered
,
boxIsTriclinic
,
hasCompilerKernel
;
std
::
string
compiler
,
tempDir
,
cacheDir
,
gpuArchitecture
;
std
::
string
compiler
,
tempDir
,
cacheDir
,
gpuArchitecture
;
float4
periodicBoxSizeFloat
,
invPeriodicBoxSizeFloat
;
float4
periodicBoxVecXFloat
,
periodicBoxVecYFloat
,
periodicBoxVecZFloat
,
periodicBoxSizeFloat
,
invPeriodicBoxSizeFloat
;
double4
periodicBoxSize
,
invPeriodicBoxSize
;
double4
periodicBoxVecX
,
periodicBoxVecY
,
periodicBoxVecZ
,
periodicBoxSize
,
invPeriodicBoxSize
;
std
::
string
defaultOptimizationOptions
;
std
::
string
defaultOptimizationOptions
;
std
::
map
<
std
::
string
,
std
::
string
>
compilationDefines
;
std
::
map
<
std
::
string
,
std
::
string
>
compilationDefines
;
CUcontext
context
;
CUcontext
context
;
CUdevice
device
;
CUdevice
device
;
CUstream
currentStream
;
CUfunction
clearBufferKernel
;
CUfunction
clearBufferKernel
;
CUfunction
clearTwoBuffersKernel
;
CUfunction
clearTwoBuffersKernel
;
CUfunction
clearThreeBuffersKernel
;
CUfunction
clearThreeBuffersKernel
;
...
@@ -549,6 +603,7 @@ private:
...
@@ -549,6 +603,7 @@ private:
CudaBondedUtilities
*
bonded
;
CudaBondedUtilities
*
bonded
;
CudaNonbondedUtilities
*
nonbonded
;
CudaNonbondedUtilities
*
nonbonded
;
WorkThread
*
thread
;
WorkThread
*
thread
;
Kernel
compilerKernel
;
};
};
struct
CudaContext
::
Molecule
{
struct
CudaContext
::
Molecule
{
...
...
platforms/cuda/include/CudaKernels.h
View file @
61d5cc0f
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -38,6 +38,27 @@
...
@@ -38,6 +38,27 @@
namespace
OpenMM
{
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
* 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
* Platform a chance to clear buffers and do other initialization at the beginning, and to do any
...
@@ -71,11 +92,13 @@ public:
...
@@ -71,11 +92,13 @@ public:
* @param includeForce true if forces should be computed
* @param includeForce true if forces should be computed
* @param includeEnergy true if potential energy 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 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'
* @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
* 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.
* 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:
private:
CudaContext
&
cu
;
CudaContext
&
cu
;
};
};
...
@@ -497,11 +520,19 @@ public:
...
@@ -497,11 +520,19 @@ public:
* @return the potential energy due to the force
* @return the potential energy due to the force
*/
*/
double
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
);
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:
private:
int
numTorsions
;
int
numTorsions
;
bool
hasInitializedKernel
;
bool
hasInitializedKernel
;
CudaContext
&
cu
;
CudaContext
&
cu
;
const
System
&
system
;
const
System
&
system
;
std
::
vector
<
int2
>
mapPositionsVec
;
CudaArray
*
coefficients
;
CudaArray
*
coefficients
;
CudaArray
*
mapPositions
;
CudaArray
*
mapPositions
;
CudaArray
*
torsionMaps
;
CudaArray
*
torsionMaps
;
...
@@ -591,14 +622,16 @@ private:
...
@@ -591,14 +622,16 @@ private:
int
getKeySize
()
const
{
return
4
;}
int
getKeySize
()
const
{
return
4
;}
const
char
*
getDataType
()
const
{
return
"int2"
;}
const
char
*
getDataType
()
const
{
return
"int2"
;}
const
char
*
getKeyType
()
const
{
return
"int"
;}
const
char
*
getKeyType
()
const
{
return
"int"
;}
const
char
*
getMinKey
()
const
{
return
"
INT_MIN
"
;}
const
char
*
getMinKey
()
const
{
return
"
(-2147483647-1)
"
;}
const
char
*
getMaxKey
()
const
{
return
"
INT_MAX
"
;}
const
char
*
getMaxKey
()
const
{
return
"
2147483647
"
;}
const
char
*
getMaxValue
()
const
{
return
"make_int2(
INT_MAX, INT_MAX
)"
;}
const
char
*
getMaxValue
()
const
{
return
"make_int2(
2147483647, 2147483647
)"
;}
const
char
*
getSortKey
()
const
{
return
"value.y"
;}
const
char
*
getSortKey
()
const
{
return
"value.y"
;}
};
};
class
PmeIO
;
class
PmeIO
;
class
PmePreComputation
;
class
PmePreComputation
;
class
PmePostComputation
;
class
PmePostComputation
;
class
SyncStreamPreComputation
;
class
SyncStreamPostComputation
;
CudaContext
&
cu
;
CudaContext
&
cu
;
bool
hasInitializedFFT
;
bool
hasInitializedFFT
;
CudaArray
*
sigmaEpsilon
;
CudaArray
*
sigmaEpsilon
;
...
@@ -614,6 +647,8 @@ private:
...
@@ -614,6 +647,8 @@ private:
CudaSort
*
sort
;
CudaSort
*
sort
;
Kernel
cpuPme
;
Kernel
cpuPme
;
PmeIO
*
pmeio
;
PmeIO
*
pmeio
;
CUstream
pmeStream
;
CUevent
pmeSyncEvent
;
cufftHandle
fftForward
;
cufftHandle
fftForward
;
cufftHandle
fftBackward
;
cufftHandle
fftBackward
;
CUfunction
ewaldSumsKernel
;
CUfunction
ewaldSumsKernel
;
...
@@ -628,7 +663,7 @@ private:
...
@@ -628,7 +663,7 @@ private:
std
::
vector
<
std
::
pair
<
int
,
int
>
>
exceptionAtoms
;
std
::
vector
<
std
::
pair
<
int
,
int
>
>
exceptionAtoms
;
double
ewaldSelfEnergy
,
dispersionCoefficient
,
alpha
;
double
ewaldSelfEnergy
,
dispersionCoefficient
,
alpha
;
int
interpolateForceThreads
;
int
interpolateForceThreads
;
bool
hasCoulomb
,
hasLJ
;
bool
hasCoulomb
,
hasLJ
,
usePmeStream
;
static
const
int
PmeOrder
=
5
;
static
const
int
PmeOrder
=
5
;
};
};
...
@@ -715,7 +750,7 @@ public:
...
@@ -715,7 +750,7 @@ public:
*/
*/
void
copyParametersToContext
(
ContextImpl
&
context
,
const
GBSAOBCForce
&
force
);
void
copyParametersToContext
(
ContextImpl
&
context
,
const
GBSAOBCForce
&
force
);
private:
private:
double
prefactor
;
double
prefactor
,
surfaceAreaFactor
;
bool
hasCreatedKernels
;
bool
hasCreatedKernels
;
int
maxTiles
;
int
maxTiles
;
CudaContext
&
cu
;
CudaContext
&
cu
;
...
...
platforms/cuda/include/CudaNonbondedUtilities.h
View file @
61d5cc0f
...
@@ -278,7 +278,7 @@ private:
...
@@ -278,7 +278,7 @@ private:
std
::
string
kernelSource
;
std
::
string
kernelSource
;
std
::
map
<
std
::
string
,
std
::
string
>
kernelDefines
;
std
::
map
<
std
::
string
,
std
::
string
>
kernelDefines
;
double
cutoff
;
double
cutoff
;
bool
useCutoff
,
usePeriodic
,
anyExclusions
,
usePadding
;
bool
useCutoff
,
usePeriodic
,
anyExclusions
,
usePadding
,
forceRebuildNeighborList
;
int
startTileIndex
,
numTiles
,
startBlockIndex
,
numBlocks
,
maxTiles
,
numForceThreadBlocks
,
forceThreadBlockSize
,
nonbondedForceGroup
,
numAtoms
;
int
startTileIndex
,
numTiles
,
startBlockIndex
,
numBlocks
,
maxTiles
,
numForceThreadBlocks
,
forceThreadBlockSize
,
nonbondedForceGroup
,
numAtoms
;
};
};
...
...
platforms/cuda/include/CudaParallelKernels.h
View file @
61d5cc0f
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2011-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2011-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -69,11 +69,13 @@ public:
...
@@ -69,11 +69,13 @@ public:
* @param includeForce true if forces should be computed
* @param includeForce true if forces should be computed
* @param includeEnergy true if potential energy 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 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'
* @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
* 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.
* 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:
private:
class
BeginComputationTask
;
class
BeginComputationTask
;
class
FinishComputationTask
;
class
FinishComputationTask
;
...
@@ -81,10 +83,13 @@ private:
...
@@ -81,10 +83,13 @@ private:
std
::
vector
<
Kernel
>
kernels
;
std
::
vector
<
Kernel
>
kernels
;
std
::
vector
<
long
long
>
completionTimes
;
std
::
vector
<
long
long
>
completionTimes
;
std
::
vector
<
double
>
contextNonbondedFractions
;
std
::
vector
<
double
>
contextNonbondedFractions
;
int
*
tileCounts
;
CudaArray
*
contextForces
;
CudaArray
*
contextForces
;
void
*
pinnedPositionBuffer
;
void
*
pinnedPositionBuffer
;
long
long
*
pinnedForceBuffer
;
long
long
*
pinnedForceBuffer
;
CUfunction
sumKernel
;
CUfunction
sumKernel
;
CUevent
event
;
CUstream
peerCopyStream
;
};
};
/**
/**
...
@@ -340,6 +345,13 @@ public:
...
@@ -340,6 +345,13 @@ public:
* @return the potential energy due to the force
* @return the potential energy due to the force
*/
*/
double
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
);
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:
private:
class
Task
;
class
Task
;
CudaPlatform
::
PlatformData
&
data
;
CudaPlatform
::
PlatformData
&
data
;
...
...
Prev
1
…
7
8
9
10
11
12
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