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
cecc774a
Commit
cecc774a
authored
Oct 05, 2015
by
Peter Eastman
Browse files
Merge branch 'master' into hardwall
parents
1dfa0e59
a20944f6
Changes
230
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
352 additions
and
49 deletions
+352
-49
openmmapi/include/openmm/internal/gmx_atomic.h
openmmapi/include/openmm/internal/gmx_atomic.h
+0
-0
openmmapi/include/openmm/internal/vectorize_neon.h
openmmapi/include/openmm/internal/vectorize_neon.h
+12
-0
openmmapi/include/openmm/internal/vectorize_pnacl.h
openmmapi/include/openmm/internal/vectorize_pnacl.h
+8
-0
openmmapi/include/openmm/internal/vectorize_sse.h
openmmapi/include/openmm/internal/vectorize_sse.h
+12
-0
openmmapi/src/CustomCentroidBondForceImpl.cpp
openmmapi/src/CustomCentroidBondForceImpl.cpp
+17
-4
openmmapi/src/CustomCompoundBondForceImpl.cpp
openmmapi/src/CustomCompoundBondForceImpl.cpp
+17
-4
openmmapi/src/CustomExternalForce.cpp
openmmapi/src/CustomExternalForce.cpp
+4
-0
openmmapi/src/CustomHbondForceImpl.cpp
openmmapi/src/CustomHbondForceImpl.cpp
+13
-4
openmmapi/src/CustomManyParticleForceImpl.cpp
openmmapi/src/CustomManyParticleForceImpl.cpp
+20
-4
platforms/cpu/include/CpuKernels.h
platforms/cpu/include/CpuKernels.h
+41
-0
platforms/cpu/include/CpuLangevinDynamics.h
platforms/cpu/include/CpuLangevinDynamics.h
+14
-1
platforms/cpu/include/CpuNeighborList.h
platforms/cpu/include/CpuNeighborList.h
+2
-0
platforms/cpu/src/CpuCustomGBForce.cpp
platforms/cpu/src/CpuCustomGBForce.cpp
+1
-1
platforms/cpu/src/CpuCustomManyParticleForce.cpp
platforms/cpu/src/CpuCustomManyParticleForce.cpp
+1
-1
platforms/cpu/src/CpuCustomNonbondedForce.cpp
platforms/cpu/src/CpuCustomNonbondedForce.cpp
+1
-1
platforms/cpu/src/CpuGBSAOBCForce.cpp
platforms/cpu/src/CpuGBSAOBCForce.cpp
+2
-2
platforms/cpu/src/CpuKernelFactory.cpp
platforms/cpu/src/CpuKernelFactory.cpp
+2
-0
platforms/cpu/src/CpuKernels.cpp
platforms/cpu/src/CpuKernels.cpp
+103
-4
platforms/cpu/src/CpuLangevinDynamics.cpp
platforms/cpu/src/CpuLangevinDynamics.cpp
+41
-1
platforms/cpu/src/CpuNeighborList.cpp
platforms/cpu/src/CpuNeighborList.cpp
+41
-22
No files found.
platforms/cpu/src
/gmx_atomic.h
→
openmmapi/include/openmm/internal
/gmx_atomic.h
View file @
cecc774a
File moved
openmmapi/include/openmm/internal/vectorize_neon.h
View file @
cecc774a
...
@@ -40,6 +40,10 @@ typedef int int32_t;
...
@@ -40,6 +40,10 @@ typedef int int32_t;
// This file defines classes and functions to simplify vectorizing code with NEON.
// This file defines classes and functions to simplify vectorizing code with NEON.
// These two functions are defined in the vecmath library, which is linked into OpenMM.
float32x4_t
exp_ps
(
float32x4_t
);
float32x4_t
log_ps
(
float32x4_t
);
/**
/**
* Determine whether ivec4 and fvec4 are supported on this processor.
* Determine whether ivec4 and fvec4 are supported on this processor.
*/
*/
...
@@ -262,6 +266,14 @@ static inline fvec4 sqrt(const fvec4& v) {
...
@@ -262,6 +266,14 @@ static inline fvec4 sqrt(const fvec4& v) {
return
rsqrt
(
v
)
*
v
;
return
rsqrt
(
v
)
*
v
;
}
}
static
inline
fvec4
exp
(
const
fvec4
&
v
)
{
return
fvec4
(
exp_ps
(
v
.
val
));
}
static
inline
fvec4
log
(
const
fvec4
&
v
)
{
return
fvec4
(
log_ps
(
v
.
val
));
}
static
inline
float
dot3
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
static
inline
float
dot3
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
fvec4
result
=
v1
*
v2
;
fvec4
result
=
v1
*
v2
;
return
vgetq_lane_f32
(
result
,
0
)
+
vgetq_lane_f32
(
result
,
1
)
+
vgetq_lane_f32
(
result
,
2
);
return
vgetq_lane_f32
(
result
,
0
)
+
vgetq_lane_f32
(
result
,
1
)
+
vgetq_lane_f32
(
result
,
2
);
...
...
openmmapi/include/openmm/internal/vectorize_pnacl.h
View file @
cecc774a
...
@@ -233,6 +233,14 @@ static inline fvec4 abs(const fvec4& v) {
...
@@ -233,6 +233,14 @@ static inline fvec4 abs(const fvec4& v) {
return
v
&
(
__m128
)
ivec4
(
0x7FFFFFFF
);
return
v
&
(
__m128
)
ivec4
(
0x7FFFFFFF
);
}
}
static
inline
fvec4
exp
(
const
fvec4
&
v
)
{
return
fvec4
(
expf
(
v
[
0
]),
expf
(
v
[
1
]),
expf
(
v
[
2
]),
expf
(
v
[
3
]));
}
static
inline
fvec4
log
(
const
fvec4
&
v
)
{
return
fvec4
(
logf
(
v
[
0
]),
logf
(
v
[
1
]),
logf
(
v
[
2
]),
logf
(
v
[
3
]));
}
static
inline
float
dot3
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
static
inline
float
dot3
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
fvec4
r
=
v1
*
v2
;
fvec4
r
=
v1
*
v2
;
return
r
[
0
]
+
r
[
1
]
+
r
[
2
];
return
r
[
0
]
+
r
[
1
]
+
r
[
2
];
...
...
openmmapi/include/openmm/internal/vectorize_sse.h
View file @
cecc774a
...
@@ -37,6 +37,10 @@
...
@@ -37,6 +37,10 @@
// This file defines classes and functions to simplify vectorizing code with SSE.
// This file defines classes and functions to simplify vectorizing code with SSE.
// These two functions are defined in the vecmath library, which is linked into OpenMM.
__m128
exp_ps
(
__m128
);
__m128
log_ps
(
__m128
);
/**
/**
* Determine whether ivec4 and fvec4 are supported on this processor.
* Determine whether ivec4 and fvec4 are supported on this processor.
*/
*/
...
@@ -253,6 +257,14 @@ static inline fvec4 rsqrt(const fvec4& v) {
...
@@ -253,6 +257,14 @@ static inline fvec4 rsqrt(const fvec4& v) {
return
y
;
return
y
;
}
}
static
inline
fvec4
exp
(
const
fvec4
&
v
)
{
return
fvec4
(
exp_ps
(
v
.
val
));
}
static
inline
fvec4
log
(
const
fvec4
&
v
)
{
return
fvec4
(
log_ps
(
v
.
val
));
}
static
inline
float
dot3
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
static
inline
float
dot3
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
return
_mm_cvtss_f32
(
_mm_dp_ps
(
v1
,
v2
,
0x71
));
return
_mm_cvtss_f32
(
_mm_dp_ps
(
v1
,
v2
,
0x71
));
}
}
...
...
openmmapi/src/CustomCentroidBondForceImpl.cpp
View file @
cecc774a
...
@@ -150,24 +150,37 @@ ParsedExpression CustomCentroidBondForceImpl::prepareExpression(const CustomCent
...
@@ -150,24 +150,37 @@ ParsedExpression CustomCentroidBondForceImpl::prepareExpression(const CustomCent
functions
[
"dihedral"
]
=
&
dihedral
;
functions
[
"dihedral"
]
=
&
dihedral
;
ParsedExpression
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
(),
functions
);
ParsedExpression
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
(),
functions
);
map
<
string
,
int
>
groups
;
map
<
string
,
int
>
groups
;
set
<
string
>
variables
;
for
(
int
i
=
0
;
i
<
force
.
getNumGroupsPerBond
();
i
++
)
{
for
(
int
i
=
0
;
i
<
force
.
getNumGroupsPerBond
();
i
++
)
{
stringstream
name
;
stringstream
name
,
x
,
y
,
z
;
name
<<
'g'
<<
(
i
+
1
);
name
<<
'g'
<<
(
i
+
1
);
x
<<
'x'
<<
(
i
+
1
);
y
<<
'y'
<<
(
i
+
1
);
z
<<
'z'
<<
(
i
+
1
);
groups
[
name
.
str
()]
=
i
;
groups
[
name
.
str
()]
=
i
;
variables
.
insert
(
x
.
str
());
variables
.
insert
(
y
.
str
());
variables
.
insert
(
z
.
str
());
}
}
return
ParsedExpression
(
replaceFunctions
(
expression
.
getRootNode
(),
groups
,
distances
,
angles
,
dihedrals
)).
optimize
();
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
variables
.
insert
(
force
.
getGlobalParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumPerBondParameters
();
i
++
)
variables
.
insert
(
force
.
getPerBondParameterName
(
i
));
return
ParsedExpression
(
replaceFunctions
(
expression
.
getRootNode
(),
groups
,
distances
,
angles
,
dihedrals
,
variables
)).
optimize
();
}
}
ExpressionTreeNode
CustomCentroidBondForceImpl
::
replaceFunctions
(
const
ExpressionTreeNode
&
node
,
map
<
string
,
int
>
groups
,
ExpressionTreeNode
CustomCentroidBondForceImpl
::
replaceFunctions
(
const
ExpressionTreeNode
&
node
,
map
<
string
,
int
>
groups
,
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
)
{
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
,
set
<
string
>&
variables
)
{
const
Operation
&
op
=
node
.
getOperation
();
const
Operation
&
op
=
node
.
getOperation
();
if
(
op
.
getId
()
==
Operation
::
VARIABLE
&&
variables
.
find
(
op
.
getName
())
==
variables
.
end
())
throw
OpenMMException
(
"CustomCentroidBondForce: Unknown variable '"
+
op
.
getName
()
+
"'"
);
if
(
op
.
getId
()
!=
Operation
::
CUSTOM
||
(
op
.
getName
()
!=
"distance"
&&
op
.
getName
()
!=
"angle"
&&
op
.
getName
()
!=
"dihedral"
))
if
(
op
.
getId
()
!=
Operation
::
CUSTOM
||
(
op
.
getName
()
!=
"distance"
&&
op
.
getName
()
!=
"angle"
&&
op
.
getName
()
!=
"dihedral"
))
{
{
// This is not an angle or dihedral, so process its children.
// This is not an angle or dihedral, so process its children.
vector
<
ExpressionTreeNode
>
children
;
vector
<
ExpressionTreeNode
>
children
;
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
children
.
push_back
(
replaceFunctions
(
node
.
getChildren
()[
i
],
groups
,
distances
,
angles
,
dihedrals
));
children
.
push_back
(
replaceFunctions
(
node
.
getChildren
()[
i
],
groups
,
distances
,
angles
,
dihedrals
,
variables
));
return
ExpressionTreeNode
(
op
.
clone
(),
children
);
return
ExpressionTreeNode
(
op
.
clone
(),
children
);
}
}
const
Operation
::
Custom
&
custom
=
static_cast
<
const
Operation
::
Custom
&>
(
op
);
const
Operation
::
Custom
&
custom
=
static_cast
<
const
Operation
::
Custom
&>
(
op
);
...
...
openmmapi/src/CustomCompoundBondForceImpl.cpp
View file @
cecc774a
...
@@ -136,24 +136,37 @@ ParsedExpression CustomCompoundBondForceImpl::prepareExpression(const CustomComp
...
@@ -136,24 +136,37 @@ ParsedExpression CustomCompoundBondForceImpl::prepareExpression(const CustomComp
functions
[
"dihedral"
]
=
&
dihedral
;
functions
[
"dihedral"
]
=
&
dihedral
;
ParsedExpression
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
(),
functions
);
ParsedExpression
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
(),
functions
);
map
<
string
,
int
>
atoms
;
map
<
string
,
int
>
atoms
;
set
<
string
>
variables
;
for
(
int
i
=
0
;
i
<
force
.
getNumParticlesPerBond
();
i
++
)
{
for
(
int
i
=
0
;
i
<
force
.
getNumParticlesPerBond
();
i
++
)
{
stringstream
name
;
stringstream
name
,
x
,
y
,
z
;
name
<<
'p'
<<
(
i
+
1
);
name
<<
'p'
<<
(
i
+
1
);
x
<<
'x'
<<
(
i
+
1
);
y
<<
'y'
<<
(
i
+
1
);
z
<<
'z'
<<
(
i
+
1
);
atoms
[
name
.
str
()]
=
i
;
atoms
[
name
.
str
()]
=
i
;
variables
.
insert
(
x
.
str
());
variables
.
insert
(
y
.
str
());
variables
.
insert
(
z
.
str
());
}
}
return
ParsedExpression
(
replaceFunctions
(
expression
.
getRootNode
(),
atoms
,
distances
,
angles
,
dihedrals
)).
optimize
();
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
variables
.
insert
(
force
.
getGlobalParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumPerBondParameters
();
i
++
)
variables
.
insert
(
force
.
getPerBondParameterName
(
i
));
return
ParsedExpression
(
replaceFunctions
(
expression
.
getRootNode
(),
atoms
,
distances
,
angles
,
dihedrals
,
variables
)).
optimize
();
}
}
ExpressionTreeNode
CustomCompoundBondForceImpl
::
replaceFunctions
(
const
ExpressionTreeNode
&
node
,
map
<
string
,
int
>
atoms
,
ExpressionTreeNode
CustomCompoundBondForceImpl
::
replaceFunctions
(
const
ExpressionTreeNode
&
node
,
map
<
string
,
int
>
atoms
,
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
)
{
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
,
set
<
string
>&
variables
)
{
const
Operation
&
op
=
node
.
getOperation
();
const
Operation
&
op
=
node
.
getOperation
();
if
(
op
.
getId
()
==
Operation
::
VARIABLE
&&
variables
.
find
(
op
.
getName
())
==
variables
.
end
())
throw
OpenMMException
(
"CustomCompoundBondForce: Unknown variable '"
+
op
.
getName
()
+
"'"
);
if
(
op
.
getId
()
!=
Operation
::
CUSTOM
||
(
op
.
getName
()
!=
"distance"
&&
op
.
getName
()
!=
"angle"
&&
op
.
getName
()
!=
"dihedral"
))
if
(
op
.
getId
()
!=
Operation
::
CUSTOM
||
(
op
.
getName
()
!=
"distance"
&&
op
.
getName
()
!=
"angle"
&&
op
.
getName
()
!=
"dihedral"
))
{
{
// This is not an angle or dihedral, so process its children.
// This is not an angle or dihedral, so process its children.
vector
<
ExpressionTreeNode
>
children
;
vector
<
ExpressionTreeNode
>
children
;
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
children
.
push_back
(
replaceFunctions
(
node
.
getChildren
()[
i
],
atoms
,
distances
,
angles
,
dihedrals
));
children
.
push_back
(
replaceFunctions
(
node
.
getChildren
()[
i
],
atoms
,
distances
,
angles
,
dihedrals
,
variables
));
return
ExpressionTreeNode
(
op
.
clone
(),
children
);
return
ExpressionTreeNode
(
op
.
clone
(),
children
);
}
}
const
Operation
::
Custom
&
custom
=
static_cast
<
const
Operation
::
Custom
&>
(
op
);
const
Operation
::
Custom
&
custom
=
static_cast
<
const
Operation
::
Custom
&>
(
op
);
...
...
openmmapi/src/CustomExternalForce.cpp
View file @
cecc774a
...
@@ -119,3 +119,7 @@ ForceImpl* CustomExternalForce::createImpl() const {
...
@@ -119,3 +119,7 @@ ForceImpl* CustomExternalForce::createImpl() const {
void
CustomExternalForce
::
updateParametersInContext
(
Context
&
context
)
{
void
CustomExternalForce
::
updateParametersInContext
(
Context
&
context
)
{
dynamic_cast
<
CustomExternalForceImpl
&>
(
getImplInContext
(
context
)).
updateParametersInContext
(
getContextImpl
(
context
));
dynamic_cast
<
CustomExternalForceImpl
&>
(
getImplInContext
(
context
)).
updateParametersInContext
(
getContextImpl
(
context
));
}
}
bool
CustomExternalForce
::
usesPeriodicBoundaryConditions
()
const
{
return
(
energyExpression
.
find
(
"periodicdistance"
)
!=
string
::
npos
);
}
openmmapi/src/CustomHbondForceImpl.cpp
View file @
cecc774a
...
@@ -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
2
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -215,19 +215,28 @@ ParsedExpression CustomHbondForceImpl::prepareExpression(const CustomHbondForce&
...
@@ -215,19 +215,28 @@ ParsedExpression CustomHbondForceImpl::prepareExpression(const CustomHbondForce&
atoms
[
"d1"
]
=
3
;
atoms
[
"d1"
]
=
3
;
atoms
[
"d2"
]
=
4
;
atoms
[
"d2"
]
=
4
;
atoms
[
"d3"
]
=
5
;
atoms
[
"d3"
]
=
5
;
return
ParsedExpression
(
replaceFunctions
(
expression
.
getRootNode
(),
atoms
,
distances
,
angles
,
dihedrals
)).
optimize
();
set
<
string
>
variables
;
for
(
int
i
=
0
;
i
<
force
.
getNumPerDonorParameters
();
i
++
)
variables
.
insert
(
force
.
getPerDonorParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumPerAcceptorParameters
();
i
++
)
variables
.
insert
(
force
.
getPerAcceptorParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
variables
.
insert
(
force
.
getGlobalParameterName
(
i
));
return
ParsedExpression
(
replaceFunctions
(
expression
.
getRootNode
(),
atoms
,
distances
,
angles
,
dihedrals
,
variables
)).
optimize
();
}
}
ExpressionTreeNode
CustomHbondForceImpl
::
replaceFunctions
(
const
ExpressionTreeNode
&
node
,
map
<
string
,
int
>
atoms
,
ExpressionTreeNode
CustomHbondForceImpl
::
replaceFunctions
(
const
ExpressionTreeNode
&
node
,
map
<
string
,
int
>
atoms
,
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
)
{
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
,
set
<
string
>&
variables
)
{
const
Operation
&
op
=
node
.
getOperation
();
const
Operation
&
op
=
node
.
getOperation
();
if
(
op
.
getId
()
==
Operation
::
VARIABLE
&&
variables
.
find
(
op
.
getName
())
==
variables
.
end
())
throw
OpenMMException
(
"CustomHBondForce: Unknown variable '"
+
op
.
getName
()
+
"'"
);
if
(
op
.
getId
()
!=
Operation
::
CUSTOM
||
op
.
getNumArguments
()
<
2
)
if
(
op
.
getId
()
!=
Operation
::
CUSTOM
||
op
.
getNumArguments
()
<
2
)
{
{
// This is not an angle or dihedral, so process its children.
// This is not an angle or dihedral, so process its children.
vector
<
ExpressionTreeNode
>
children
;
vector
<
ExpressionTreeNode
>
children
;
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
children
.
push_back
(
replaceFunctions
(
node
.
getChildren
()[
i
],
atoms
,
distances
,
angles
,
dihedrals
));
children
.
push_back
(
replaceFunctions
(
node
.
getChildren
()[
i
],
atoms
,
distances
,
angles
,
dihedrals
,
variables
));
return
ExpressionTreeNode
(
op
.
clone
(),
children
);
return
ExpressionTreeNode
(
op
.
clone
(),
children
);
}
}
const
Operation
::
Custom
&
custom
=
static_cast
<
const
Operation
::
Custom
&>
(
op
);
const
Operation
::
Custom
&
custom
=
static_cast
<
const
Operation
::
Custom
&>
(
op
);
...
...
openmmapi/src/CustomManyParticleForceImpl.cpp
View file @
cecc774a
...
@@ -165,24 +165,40 @@ ParsedExpression CustomManyParticleForceImpl::prepareExpression(const CustomMany
...
@@ -165,24 +165,40 @@ ParsedExpression CustomManyParticleForceImpl::prepareExpression(const CustomMany
functions
[
"dihedral"
]
=
&
dihedral
;
functions
[
"dihedral"
]
=
&
dihedral
;
ParsedExpression
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
(),
functions
);
ParsedExpression
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
(),
functions
);
map
<
string
,
int
>
atoms
;
map
<
string
,
int
>
atoms
;
set
<
string
>
variables
;
for
(
int
i
=
0
;
i
<
force
.
getNumParticlesPerSet
();
i
++
)
{
for
(
int
i
=
0
;
i
<
force
.
getNumParticlesPerSet
();
i
++
)
{
stringstream
name
;
stringstream
name
,
x
,
y
,
z
;
name
<<
'p'
<<
(
i
+
1
);
name
<<
'p'
<<
(
i
+
1
);
x
<<
'x'
<<
(
i
+
1
);
y
<<
'y'
<<
(
i
+
1
);
z
<<
'z'
<<
(
i
+
1
);
atoms
[
name
.
str
()]
=
i
;
atoms
[
name
.
str
()]
=
i
;
variables
.
insert
(
x
.
str
());
variables
.
insert
(
y
.
str
());
variables
.
insert
(
z
.
str
());
for
(
int
j
=
0
;
j
<
force
.
getNumPerParticleParameters
();
j
++
)
{
stringstream
param
;
param
<<
force
.
getPerParticleParameterName
(
j
)
<<
(
i
+
1
);
variables
.
insert
(
param
.
str
());
}
}
return
ParsedExpression
(
replaceFunctions
(
expression
.
getRootNode
(),
atoms
,
distances
,
angles
,
dihedrals
)).
optimize
();
}
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
variables
.
insert
(
force
.
getGlobalParameterName
(
i
));
return
ParsedExpression
(
replaceFunctions
(
expression
.
getRootNode
(),
atoms
,
distances
,
angles
,
dihedrals
,
variables
)).
optimize
();
}
}
ExpressionTreeNode
CustomManyParticleForceImpl
::
replaceFunctions
(
const
ExpressionTreeNode
&
node
,
map
<
string
,
int
>
atoms
,
ExpressionTreeNode
CustomManyParticleForceImpl
::
replaceFunctions
(
const
ExpressionTreeNode
&
node
,
map
<
string
,
int
>
atoms
,
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
)
{
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
,
set
<
string
>&
variables
)
{
const
Operation
&
op
=
node
.
getOperation
();
const
Operation
&
op
=
node
.
getOperation
();
if
(
op
.
getId
()
==
Operation
::
VARIABLE
&&
variables
.
find
(
op
.
getName
())
==
variables
.
end
())
throw
OpenMMException
(
"CustomManyParticleForce: Unknown variable '"
+
op
.
getName
()
+
"'"
);
if
(
op
.
getId
()
!=
Operation
::
CUSTOM
||
(
op
.
getName
()
!=
"distance"
&&
op
.
getName
()
!=
"angle"
&&
op
.
getName
()
!=
"dihedral"
))
if
(
op
.
getId
()
!=
Operation
::
CUSTOM
||
(
op
.
getName
()
!=
"distance"
&&
op
.
getName
()
!=
"angle"
&&
op
.
getName
()
!=
"dihedral"
))
{
{
// This is not an angle or dihedral, so process its children.
// This is not an angle or dihedral, so process its children.
vector
<
ExpressionTreeNode
>
children
;
vector
<
ExpressionTreeNode
>
children
;
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
children
.
push_back
(
replaceFunctions
(
node
.
getChildren
()[
i
],
atoms
,
distances
,
angles
,
dihedrals
));
children
.
push_back
(
replaceFunctions
(
node
.
getChildren
()[
i
],
atoms
,
distances
,
angles
,
dihedrals
,
variables
));
return
ExpressionTreeNode
(
op
.
clone
(),
children
);
return
ExpressionTreeNode
(
op
.
clone
(),
children
);
}
}
const
Operation
::
Custom
&
custom
=
static_cast
<
const
Operation
::
Custom
&>
(
op
);
const
Operation
::
Custom
&
custom
=
static_cast
<
const
Operation
::
Custom
&>
(
op
);
...
...
platforms/cpu/include/CpuKernels.h
View file @
cecc774a
...
@@ -92,6 +92,46 @@ private:
...
@@ -92,6 +92,46 @@ private:
Kernel
referenceKernel
;
Kernel
referenceKernel
;
};
};
/**
* This kernel is invoked by HarmonicAngleForce to calculate the forces acting on the system and the energy of the system.
*/
class
CpuCalcHarmonicAngleForceKernel
:
public
CalcHarmonicAngleForceKernel
{
public:
CpuCalcHarmonicAngleForceKernel
(
std
::
string
name
,
const
Platform
&
platform
,
CpuPlatform
::
PlatformData
&
data
)
:
CalcHarmonicAngleForceKernel
(
name
,
platform
),
data
(
data
),
angleIndexArray
(
NULL
),
angleParamArray
(
NULL
)
{
}
~
CpuCalcHarmonicAngleForceKernel
();
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the HarmonicAngleForce this kernel will be used for
*/
void
initialize
(
const
System
&
system
,
const
HarmonicAngleForce
&
force
);
/**
* Execute the kernel to calculate the forces and/or energy.
*
* @param context the context in which to execute this kernel
* @param includeForces true if forces should be calculated
* @param includeEnergy true if the energy should be calculated
* @return the potential energy due to the force
*/
double
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
);
/**
* Copy changed parameters over to a context.
*
* @param context the context to copy parameters to
* @param force the HarmonicAngleForce to copy the parameters from
*/
void
copyParametersToContext
(
ContextImpl
&
context
,
const
HarmonicAngleForce
&
force
);
private:
CpuPlatform
::
PlatformData
&
data
;
int
numAngles
;
int
**
angleIndexArray
;
RealOpenMM
**
angleParamArray
;
CpuBondForce
bondForce
;
};
/**
/**
* This kernel is invoked by PeriodicTorsionForce to calculate the forces acting on the system and the energy of the system.
* This kernel is invoked by PeriodicTorsionForce to calculate the forces acting on the system and the energy of the system.
*/
*/
...
@@ -229,6 +269,7 @@ private:
...
@@ -229,6 +269,7 @@ private:
CpuNeighborList
*
neighborList
;
CpuNeighborList
*
neighborList
;
CpuNonbondedForce
*
nonbonded
;
CpuNonbondedForce
*
nonbonded
;
Kernel
optimizedPme
;
Kernel
optimizedPme
;
CpuBondForce
bondForce
;
};
};
/**
/**
...
...
platforms/cpu/include/CpuLangevinDynamics.h
View file @
cecc774a
/* Portions copyright (c) 2013 Stanford University and Simbios.
/* Portions copyright (c) 2013
-2015
Stanford University and Simbios.
* Authors: Peter Eastman
* Authors: Peter Eastman
* Contributors:
* Contributors:
*
*
...
@@ -37,6 +37,7 @@ class CpuLangevinDynamics : public ReferenceStochasticDynamics {
...
@@ -37,6 +37,7 @@ class CpuLangevinDynamics : public ReferenceStochasticDynamics {
public:
public:
class
Update1Task
;
class
Update1Task
;
class
Update2Task
;
class
Update2Task
;
class
Update3Task
;
/**
/**
* Constructor.
* Constructor.
*
*
...
@@ -80,9 +81,21 @@ public:
...
@@ -80,9 +81,21 @@ public:
void
updatePart2
(
int
numberOfAtoms
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
RealVec
>&
velocities
,
void
updatePart2
(
int
numberOfAtoms
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
RealVec
>&
velocities
,
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
std
::
vector
<
RealOpenMM
>&
inverseMasses
,
std
::
vector
<
OpenMM
::
RealVec
>&
xPrime
);
std
::
vector
<
OpenMM
::
RealVec
>&
forces
,
std
::
vector
<
RealOpenMM
>&
inverseMasses
,
std
::
vector
<
OpenMM
::
RealVec
>&
xPrime
);
/**
* Third update
*
* @param numberOfAtoms number of atoms
* @param atomCoordinates atom coordinates
* @param velocities velocities
* @param inverseMasses inverse atom masses
*/
void
updatePart3
(
int
numberOfAtoms
,
std
::
vector
<
OpenMM
::
RealVec
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
RealVec
>&
velocities
,
std
::
vector
<
RealOpenMM
>&
inverseMasses
,
std
::
vector
<
OpenMM
::
RealVec
>&
xPrime
);
private:
private:
void
threadUpdate1
(
int
threadIndex
);
void
threadUpdate1
(
int
threadIndex
);
void
threadUpdate2
(
int
threadIndex
);
void
threadUpdate2
(
int
threadIndex
);
void
threadUpdate3
(
int
threadIndex
);
OpenMM
::
ThreadPool
&
threads
;
OpenMM
::
ThreadPool
&
threads
;
OpenMM
::
CpuRandom
&
random
;
OpenMM
::
CpuRandom
&
random
;
std
::
vector
<
OpenMM_SFMT
::
SFMT
>
threadRandom
;
std
::
vector
<
OpenMM_SFMT
::
SFMT
>
threadRandom
;
...
...
platforms/cpu/include/CpuNeighborList.h
View file @
cecc774a
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
#include "AlignedArray.h"
#include "AlignedArray.h"
#include "RealVec.h"
#include "RealVec.h"
#include "windowsExportCpu.h"
#include "windowsExportCpu.h"
#include "openmm/internal/gmx_atomic.h"
#include "openmm/internal/ThreadPool.h"
#include "openmm/internal/ThreadPool.h"
#include <set>
#include <set>
#include <utility>
#include <utility>
...
@@ -74,6 +75,7 @@ private:
...
@@ -74,6 +75,7 @@ private:
int
numAtoms
;
int
numAtoms
;
bool
usePeriodic
;
bool
usePeriodic
;
float
maxDistance
;
float
maxDistance
;
gmx_atomic_t
atomicCounter
;
};
};
}
// namespace OpenMM
}
// namespace OpenMM
...
...
platforms/cpu/src/CpuCustomGBForce.cpp
View file @
cecc774a
...
@@ -28,7 +28,7 @@
...
@@ -28,7 +28,7 @@
#include "SimTKOpenMMUtilities.h"
#include "SimTKOpenMMUtilities.h"
#include "ReferenceForce.h"
#include "ReferenceForce.h"
#include "CpuCustomGBForce.h"
#include "CpuCustomGBForce.h"
#include "gmx_atomic.h"
#include "
openmm/internal/
gmx_atomic.h"
using
namespace
OpenMM
;
using
namespace
OpenMM
;
using
namespace
std
;
using
namespace
std
;
...
...
platforms/cpu/src/CpuCustomManyParticleForce.cpp
View file @
cecc774a
...
@@ -32,7 +32,7 @@
...
@@ -32,7 +32,7 @@
#include "ReferenceTabulatedFunction.h"
#include "ReferenceTabulatedFunction.h"
#include "openmm/internal/CustomManyParticleForceImpl.h"
#include "openmm/internal/CustomManyParticleForceImpl.h"
#include "lepton/CustomFunction.h"
#include "lepton/CustomFunction.h"
#include "gmx_atomic.h"
#include "
openmm/internal/
gmx_atomic.h"
using
namespace
OpenMM
;
using
namespace
OpenMM
;
using
namespace
std
;
using
namespace
std
;
...
...
platforms/cpu/src/CpuCustomNonbondedForce.cpp
View file @
cecc774a
...
@@ -28,7 +28,7 @@
...
@@ -28,7 +28,7 @@
#include "SimTKOpenMMUtilities.h"
#include "SimTKOpenMMUtilities.h"
#include "ReferenceForce.h"
#include "ReferenceForce.h"
#include "CpuCustomNonbondedForce.h"
#include "CpuCustomNonbondedForce.h"
#include "gmx_atomic.h"
#include "
openmm/internal/
gmx_atomic.h"
using
namespace
OpenMM
;
using
namespace
OpenMM
;
using
namespace
std
;
using
namespace
std
;
...
...
platforms/cpu/src/CpuGBSAOBCForce.cpp
View file @
cecc774a
...
@@ -25,7 +25,7 @@
...
@@ -25,7 +25,7 @@
#include "CpuGBSAOBCForce.h"
#include "CpuGBSAOBCForce.h"
#include "SimTKOpenMMRealType.h"
#include "SimTKOpenMMRealType.h"
#include "openmm/internal/vectorize.h"
#include "openmm/internal/vectorize.h"
#include "gmx_atomic.h"
#include "
openmm/internal/
gmx_atomic.h"
#include <algorithm>
#include <algorithm>
#include <cmath>
#include <cmath>
#include <cstdlib>
#include <cstdlib>
...
@@ -279,7 +279,7 @@ void CpuGBSAOBCForce::threadComputeForce(ThreadPool& threads, int threadIndex) {
...
@@ -279,7 +279,7 @@ void CpuGBSAOBCForce::threadComputeForce(ThreadPool& threads, int threadIndex) {
fvec4
r
=
sqrt
(
r2
);
fvec4
r
=
sqrt
(
r2
);
fvec4
alpha2_ij
=
radii
*
bornRadii
[
atomJ
];
fvec4
alpha2_ij
=
radii
*
bornRadii
[
atomJ
];
fvec4
D_ij
=
r2
/
(
4.0
f
*
alpha2_ij
);
fvec4
D_ij
=
r2
/
(
4.0
f
*
alpha2_ij
);
fvec4
expTerm
(
expf
(
-
D_ij
[
0
]),
expf
(
-
D_ij
[
1
]),
exp
f
(
-
D_ij
[
2
]),
expf
(
-
D_ij
[
3
])
);
fvec4
expTerm
=
exp
(
-
D_ij
);
fvec4
denominator2
=
r2
+
alpha2_ij
*
expTerm
;
fvec4
denominator2
=
r2
+
alpha2_ij
*
expTerm
;
fvec4
denominator
=
sqrt
(
denominator2
);
fvec4
denominator
=
sqrt
(
denominator2
);
fvec4
Gpol
=
(
partialChargeI
*
posJ
[
3
])
/
denominator
;
fvec4
Gpol
=
(
partialChargeI
*
posJ
[
3
])
/
denominator
;
...
...
platforms/cpu/src/CpuKernelFactory.cpp
View file @
cecc774a
...
@@ -41,6 +41,8 @@ KernelImpl* CpuKernelFactory::createKernelImpl(std::string name, const Platform&
...
@@ -41,6 +41,8 @@ KernelImpl* CpuKernelFactory::createKernelImpl(std::string name, const Platform&
CpuPlatform
::
PlatformData
&
data
=
CpuPlatform
::
getPlatformData
(
context
);
CpuPlatform
::
PlatformData
&
data
=
CpuPlatform
::
getPlatformData
(
context
);
if
(
name
==
CalcForcesAndEnergyKernel
::
Name
())
if
(
name
==
CalcForcesAndEnergyKernel
::
Name
())
return
new
CpuCalcForcesAndEnergyKernel
(
name
,
platform
,
data
,
context
);
return
new
CpuCalcForcesAndEnergyKernel
(
name
,
platform
,
data
,
context
);
if
(
name
==
CalcHarmonicAngleForceKernel
::
Name
())
return
new
CpuCalcHarmonicAngleForceKernel
(
name
,
platform
,
data
);
if
(
name
==
CalcPeriodicTorsionForceKernel
::
Name
())
if
(
name
==
CalcPeriodicTorsionForceKernel
::
Name
())
return
new
CpuCalcPeriodicTorsionForceKernel
(
name
,
platform
,
data
);
return
new
CpuCalcPeriodicTorsionForceKernel
(
name
,
platform
,
data
);
if
(
name
==
CalcRBTorsionForceKernel
::
Name
())
if
(
name
==
CalcRBTorsionForceKernel
::
Name
())
...
...
platforms/cpu/src/CpuKernels.cpp
View file @
cecc774a
...
@@ -30,6 +30,7 @@
...
@@ -30,6 +30,7 @@
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
#include "CpuKernels.h"
#include "CpuKernels.h"
#include "ReferenceAngleBondIxn.h"
#include "ReferenceBondForce.h"
#include "ReferenceBondForce.h"
#include "ReferenceConstraints.h"
#include "ReferenceConstraints.h"
#include "ReferenceKernelFactory.h"
#include "ReferenceKernelFactory.h"
...
@@ -47,6 +48,7 @@
...
@@ -47,6 +48,7 @@
#include "RealVec.h"
#include "RealVec.h"
#include "lepton/CompiledExpression.h"
#include "lepton/CompiledExpression.h"
#include "lepton/CustomFunction.h"
#include "lepton/CustomFunction.h"
#include "lepton/Operation.h"
#include "lepton/Parser.h"
#include "lepton/Parser.h"
#include "lepton/ParsedExpression.h"
#include "lepton/ParsedExpression.h"
...
@@ -83,6 +85,17 @@ static ReferenceConstraints& extractConstraints(ContextImpl& context) {
...
@@ -83,6 +85,17 @@ static ReferenceConstraints& extractConstraints(ContextImpl& context) {
return
*
(
ReferenceConstraints
*
)
data
->
constraints
;
return
*
(
ReferenceConstraints
*
)
data
->
constraints
;
}
}
/**
* Make sure an expression doesn't use any undefined variables.
*/
static
void
validateVariables
(
const
Lepton
::
ExpressionTreeNode
&
node
,
const
set
<
string
>&
variables
)
{
const
Lepton
::
Operation
&
op
=
node
.
getOperation
();
if
(
op
.
getId
()
==
Lepton
::
Operation
::
VARIABLE
&&
variables
.
find
(
op
.
getName
())
==
variables
.
end
())
throw
OpenMMException
(
"Unknown variable in expression: "
+
op
.
getName
());
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
validateVariables
(
node
.
getChildren
()[
i
],
variables
);
}
/**
/**
* Compute the kinetic energy of the system, possibly shifting the velocities in time to account
* Compute the kinetic energy of the system, possibly shifting the velocities in time to account
* for a leapfrog integrator.
* for a leapfrog integrator.
...
@@ -240,6 +253,64 @@ double CpuCalcForcesAndEnergyKernel::finishComputation(ContextImpl& context, boo
...
@@ -240,6 +253,64 @@ double CpuCalcForcesAndEnergyKernel::finishComputation(ContextImpl& context, boo
return
referenceKernel
.
getAs
<
ReferenceCalcForcesAndEnergyKernel
>
().
finishComputation
(
context
,
includeForce
,
includeEnergy
,
groups
,
valid
);
return
referenceKernel
.
getAs
<
ReferenceCalcForcesAndEnergyKernel
>
().
finishComputation
(
context
,
includeForce
,
includeEnergy
,
groups
,
valid
);
}
}
CpuCalcHarmonicAngleForceKernel
::~
CpuCalcHarmonicAngleForceKernel
()
{
if
(
angleIndexArray
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
numAngles
;
i
++
)
{
delete
[]
angleIndexArray
[
i
];
delete
[]
angleParamArray
[
i
];
}
delete
[]
angleIndexArray
;
delete
[]
angleParamArray
;
}
}
void
CpuCalcHarmonicAngleForceKernel
::
initialize
(
const
System
&
system
,
const
HarmonicAngleForce
&
force
)
{
numAngles
=
force
.
getNumAngles
();
angleIndexArray
=
new
int
*
[
numAngles
];
for
(
int
i
=
0
;
i
<
numAngles
;
i
++
)
angleIndexArray
[
i
]
=
new
int
[
3
];
angleParamArray
=
new
RealOpenMM
*
[
numAngles
];
for
(
int
i
=
0
;
i
<
numAngles
;
i
++
)
angleParamArray
[
i
]
=
new
RealOpenMM
[
2
];
for
(
int
i
=
0
;
i
<
numAngles
;
++
i
)
{
int
particle1
,
particle2
,
particle3
;
double
angle
,
k
;
force
.
getAngleParameters
(
i
,
particle1
,
particle2
,
particle3
,
angle
,
k
);
angleIndexArray
[
i
][
0
]
=
particle1
;
angleIndexArray
[
i
][
1
]
=
particle2
;
angleIndexArray
[
i
][
2
]
=
particle3
;
angleParamArray
[
i
][
0
]
=
(
RealOpenMM
)
angle
;
angleParamArray
[
i
][
1
]
=
(
RealOpenMM
)
k
;
}
bondForce
.
initialize
(
system
.
getNumParticles
(),
numAngles
,
3
,
angleIndexArray
,
data
.
threads
);
}
double
CpuCalcHarmonicAngleForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
RealOpenMM
energy
=
0
;
ReferenceAngleBondIxn
angleBond
;
bondForce
.
calculateForce
(
posData
,
angleParamArray
,
forceData
,
includeEnergy
?
&
energy
:
NULL
,
angleBond
);
return
energy
;
}
void
CpuCalcHarmonicAngleForceKernel
::
copyParametersToContext
(
ContextImpl
&
context
,
const
HarmonicAngleForce
&
force
)
{
if
(
numAngles
!=
force
.
getNumAngles
())
throw
OpenMMException
(
"updateParametersInContext: The number of angles has changed"
);
// Record the values.
for
(
int
i
=
0
;
i
<
numAngles
;
++
i
)
{
int
particle1
,
particle2
,
particle3
;
double
angle
,
k
;
force
.
getAngleParameters
(
i
,
particle1
,
particle2
,
particle3
,
angle
,
k
);
if
(
particle1
!=
angleIndexArray
[
i
][
0
]
||
particle2
!=
angleIndexArray
[
i
][
1
]
||
particle3
!=
angleIndexArray
[
i
][
2
])
throw
OpenMMException
(
"updateParametersInContext: The set of particles in an angle has changed"
);
angleParamArray
[
i
][
0
]
=
(
RealOpenMM
)
angle
;
angleParamArray
[
i
][
1
]
=
(
RealOpenMM
)
k
;
}
}
CpuCalcPeriodicTorsionForceKernel
::~
CpuCalcPeriodicTorsionForceKernel
()
{
CpuCalcPeriodicTorsionForceKernel
::~
CpuCalcPeriodicTorsionForceKernel
()
{
if
(
torsionIndexArray
!=
NULL
)
{
if
(
torsionIndexArray
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
numTorsions
;
i
++
)
{
for
(
int
i
=
0
;
i
<
numTorsions
;
i
++
)
{
...
@@ -467,6 +538,7 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
...
@@ -467,6 +538,7 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
bonded14ParamArray
[
i
][
1
]
=
static_cast
<
RealOpenMM
>
(
4.0
*
depth
);
bonded14ParamArray
[
i
][
1
]
=
static_cast
<
RealOpenMM
>
(
4.0
*
depth
);
bonded14ParamArray
[
i
][
2
]
=
static_cast
<
RealOpenMM
>
(
charge
);
bonded14ParamArray
[
i
][
2
]
=
static_cast
<
RealOpenMM
>
(
charge
);
}
}
bondForce
.
initialize
(
system
.
getNumParticles
(),
num14
,
2
,
bonded14IndexArray
,
data
.
threads
);
// Record other parameters.
// Record other parameters.
...
@@ -527,7 +599,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
...
@@ -527,7 +599,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
if
(
nonbondedMethod
!=
NoCutoff
)
{
if
(
nonbondedMethod
!=
NoCutoff
)
{
// Determine whether we need to recompute the neighbor list.
// Determine whether we need to recompute the neighbor list.
double
padding
=
0.
1
5
*
nonbondedCutoff
;
double
padding
=
0.
2
5
*
nonbondedCutoff
;
bool
needRecompute
=
false
;
bool
needRecompute
=
false
;
double
closeCutoff2
=
0.25
*
padding
*
padding
;
double
closeCutoff2
=
0.25
*
padding
*
padding
;
double
farCutoff2
=
0.5
*
padding
*
padding
;
double
farCutoff2
=
0.5
*
padding
*
padding
;
...
@@ -599,9 +671,8 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
...
@@ -599,9 +671,8 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
}
}
energy
+=
nonbondedEnergy
;
energy
+=
nonbondedEnergy
;
if
(
includeDirect
)
{
if
(
includeDirect
)
{
ReferenceBondForce
refBondForce
;
ReferenceLJCoulomb14
nonbonded14
;
ReferenceLJCoulomb14
nonbonded14
;
refB
ondForce
.
calculateForce
(
num14
,
bonded14IndexArray
,
posData
,
bonded14ParamArray
,
forceData
,
includeEnergy
?
&
energy
:
NULL
,
nonbonded14
);
b
ondForce
.
calculateForce
(
posData
,
bonded14ParamArray
,
forceData
,
includeEnergy
?
&
energy
:
NULL
,
nonbonded14
);
if
(
data
.
isPeriodic
)
if
(
data
.
isPeriodic
)
energy
+=
dispersionCoefficient
/
(
boxVectors
[
0
][
0
]
*
boxVectors
[
1
][
1
]
*
boxVectors
[
2
][
2
]);
energy
+=
dispersionCoefficient
/
(
boxVectors
[
0
][
0
]
*
boxVectors
[
1
][
1
]
*
boxVectors
[
2
][
2
]);
}
}
...
@@ -737,6 +808,14 @@ void CpuCalcCustomNonbondedForceKernel::initialize(const System& system, const C
...
@@ -737,6 +808,14 @@ void CpuCalcCustomNonbondedForceKernel::initialize(const System& system, const C
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
globalParamValues
[
force
.
getGlobalParameterName
(
i
)]
=
force
.
getGlobalParameterDefaultValue
(
i
);
globalParamValues
[
force
.
getGlobalParameterName
(
i
)]
=
force
.
getGlobalParameterDefaultValue
(
i
);
}
}
set
<
string
>
variables
;
variables
.
insert
(
"r"
);
for
(
int
i
=
0
;
i
<
numParameters
;
i
++
)
{
variables
.
insert
(
parameterNames
[
i
]
+
"1"
);
variables
.
insert
(
parameterNames
[
i
]
+
"2"
);
}
variables
.
insert
(
globalParameterNames
.
begin
(),
globalParameterNames
.
end
());
validateVariables
(
expression
.
getRootNode
(),
variables
);
// Delete the custom functions.
// Delete the custom functions.
...
@@ -950,6 +1029,18 @@ void CpuCalcCustomGBForceKernel::initialize(const System& system, const CustomGB
...
@@ -950,6 +1029,18 @@ void CpuCalcCustomGBForceKernel::initialize(const System& system, const CustomGB
vector
<
vector
<
Lepton
::
CompiledExpression
>
>
valueGradientExpressions
(
force
.
getNumComputedValues
());
vector
<
vector
<
Lepton
::
CompiledExpression
>
>
valueGradientExpressions
(
force
.
getNumComputedValues
());
vector
<
Lepton
::
CompiledExpression
>
valueExpressions
;
vector
<
Lepton
::
CompiledExpression
>
valueExpressions
;
vector
<
Lepton
::
CompiledExpression
>
energyExpressions
;
vector
<
Lepton
::
CompiledExpression
>
energyExpressions
;
set
<
string
>
particleVariables
,
pairVariables
;
pairVariables
.
insert
(
"r"
);
particleVariables
.
insert
(
"x"
);
particleVariables
.
insert
(
"y"
);
particleVariables
.
insert
(
"z"
);
for
(
int
i
=
0
;
i
<
numPerParticleParameters
;
i
++
)
{
particleVariables
.
insert
(
particleParameterNames
[
i
]);
pairVariables
.
insert
(
particleParameterNames
[
i
]
+
"1"
);
pairVariables
.
insert
(
particleParameterNames
[
i
]
+
"2"
);
}
particleVariables
.
insert
(
globalParameterNames
.
begin
(),
globalParameterNames
.
end
());
pairVariables
.
insert
(
globalParameterNames
.
begin
(),
globalParameterNames
.
end
());
for
(
int
i
=
0
;
i
<
force
.
getNumComputedValues
();
i
++
)
{
for
(
int
i
=
0
;
i
<
force
.
getNumComputedValues
();
i
++
)
{
string
name
,
expression
;
string
name
,
expression
;
CustomGBForce
::
ComputationType
type
;
CustomGBForce
::
ComputationType
type
;
...
@@ -958,15 +1049,21 @@ void CpuCalcCustomGBForceKernel::initialize(const System& system, const CustomGB
...
@@ -958,15 +1049,21 @@ void CpuCalcCustomGBForceKernel::initialize(const System& system, const CustomGB
valueExpressions
.
push_back
(
ex
.
createCompiledExpression
());
valueExpressions
.
push_back
(
ex
.
createCompiledExpression
());
valueTypes
.
push_back
(
type
);
valueTypes
.
push_back
(
type
);
valueNames
.
push_back
(
name
);
valueNames
.
push_back
(
name
);
if
(
i
==
0
)
if
(
i
==
0
)
{
valueDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"r"
).
createCompiledExpression
());
valueDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"r"
).
createCompiledExpression
());
validateVariables
(
ex
.
getRootNode
(),
pairVariables
);
}
else
{
else
{
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"x"
).
createCompiledExpression
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"x"
).
createCompiledExpression
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"y"
).
createCompiledExpression
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"y"
).
createCompiledExpression
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"z"
).
createCompiledExpression
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"z"
).
createCompiledExpression
());
for
(
int
j
=
0
;
j
<
i
;
j
++
)
for
(
int
j
=
0
;
j
<
i
;
j
++
)
valueDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]).
createCompiledExpression
());
valueDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]).
createCompiledExpression
());
validateVariables
(
ex
.
getRootNode
(),
particleVariables
);
}
}
particleVariables
.
insert
(
name
);
pairVariables
.
insert
(
name
+
"1"
);
pairVariables
.
insert
(
name
+
"2"
);
}
}
// Parse the expressions for energy terms.
// Parse the expressions for energy terms.
...
@@ -988,10 +1085,12 @@ void CpuCalcCustomGBForceKernel::initialize(const System& system, const CustomGB
...
@@ -988,10 +1085,12 @@ void CpuCalcCustomGBForceKernel::initialize(const System& system, const CustomGB
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"x"
).
createCompiledExpression
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"x"
).
createCompiledExpression
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"y"
).
createCompiledExpression
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"y"
).
createCompiledExpression
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"z"
).
createCompiledExpression
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"z"
).
createCompiledExpression
());
validateVariables
(
ex
.
getRootNode
(),
particleVariables
);
}
}
else
{
else
{
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]
+
"1"
).
createCompiledExpression
());
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]
+
"1"
).
createCompiledExpression
());
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]
+
"2"
).
createCompiledExpression
());
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]
+
"2"
).
createCompiledExpression
());
validateVariables
(
ex
.
getRootNode
(),
pairVariables
);
}
}
}
}
}
}
...
...
platforms/cpu/src/CpuLangevinDynamics.cpp
View file @
cecc774a
/* Portions copyright (c) 2006-201
3
Stanford University and Simbios.
/* Portions copyright (c) 2006-201
5
Stanford University and Simbios.
* Authors: Peter Eastman
* Authors: Peter Eastman
* Contributors:
* Contributors:
*
*
...
@@ -49,6 +49,16 @@ public:
...
@@ -49,6 +49,16 @@ public:
CpuLangevinDynamics
&
owner
;
CpuLangevinDynamics
&
owner
;
};
};
class
CpuLangevinDynamics
::
Update3Task
:
public
ThreadPool
::
Task
{
public:
Update3Task
(
CpuLangevinDynamics
&
owner
)
:
owner
(
owner
)
{
}
void
execute
(
ThreadPool
&
threads
,
int
threadIndex
)
{
owner
.
threadUpdate3
(
threadIndex
);
}
CpuLangevinDynamics
&
owner
;
};
CpuLangevinDynamics
::
CpuLangevinDynamics
(
int
numberOfAtoms
,
RealOpenMM
deltaT
,
RealOpenMM
tau
,
RealOpenMM
temperature
,
ThreadPool
&
threads
,
CpuRandom
&
random
)
:
CpuLangevinDynamics
::
CpuLangevinDynamics
(
int
numberOfAtoms
,
RealOpenMM
deltaT
,
RealOpenMM
tau
,
RealOpenMM
temperature
,
ThreadPool
&
threads
,
CpuRandom
&
random
)
:
ReferenceStochasticDynamics
(
numberOfAtoms
,
deltaT
,
tau
,
temperature
),
threads
(
threads
),
random
(
random
)
{
ReferenceStochasticDynamics
(
numberOfAtoms
,
deltaT
,
tau
,
temperature
),
threads
(
threads
),
random
(
random
)
{
}
}
...
@@ -92,6 +102,23 @@ void CpuLangevinDynamics::updatePart2(int numberOfAtoms, vector<RealVec>& atomCo
...
@@ -92,6 +102,23 @@ void CpuLangevinDynamics::updatePart2(int numberOfAtoms, vector<RealVec>& atomCo
threads
.
waitForThreads
();
threads
.
waitForThreads
();
}
}
void
CpuLangevinDynamics
::
updatePart3
(
int
numberOfAtoms
,
vector
<
RealVec
>&
atomCoordinates
,
vector
<
RealVec
>&
velocities
,
vector
<
RealOpenMM
>&
inverseMasses
,
vector
<
RealVec
>&
xPrime
)
{
// Record the parameters for the threads.
this
->
numberOfAtoms
=
numberOfAtoms
;
this
->
atomCoordinates
=
&
atomCoordinates
[
0
];
this
->
velocities
=
&
velocities
[
0
];
this
->
inverseMasses
=
&
inverseMasses
[
0
];
this
->
xPrime
=
&
xPrime
[
0
];
// Signal the threads to start running and wait for them to finish.
Update3Task
task
(
*
this
);
threads
.
execute
(
task
);
threads
.
waitForThreads
();
}
void
CpuLangevinDynamics
::
threadUpdate1
(
int
threadIndex
)
{
void
CpuLangevinDynamics
::
threadUpdate1
(
int
threadIndex
)
{
const
RealOpenMM
tau
=
getTau
();
const
RealOpenMM
tau
=
getTau
();
const
RealOpenMM
vscale
=
EXP
(
-
getDeltaT
()
/
tau
);
const
RealOpenMM
vscale
=
EXP
(
-
getDeltaT
()
/
tau
);
...
@@ -122,3 +149,16 @@ void CpuLangevinDynamics::threadUpdate2(int threadIndex) {
...
@@ -122,3 +149,16 @@ void CpuLangevinDynamics::threadUpdate2(int threadIndex) {
}
}
}
}
}
}
void
CpuLangevinDynamics
::
threadUpdate3
(
int
threadIndex
)
{
const
RealOpenMM
invStepSize
=
1.0
/
getDeltaT
();
int
start
=
threadIndex
*
numberOfAtoms
/
threads
.
getNumThreads
();
int
end
=
(
threadIndex
+
1
)
*
numberOfAtoms
/
threads
.
getNumThreads
();
for
(
int
i
=
start
;
i
<
end
;
++
i
)
if
(
inverseMasses
[
i
]
!=
0.0
)
{
velocities
[
i
]
=
(
xPrime
[
i
]
-
atomCoordinates
[
i
])
*
invStepSize
;
atomCoordinates
[
i
]
=
xPrime
[
i
];
}
}
platforms/cpu/src/CpuNeighborList.cpp
View file @
cecc774a
...
@@ -59,22 +59,25 @@ public:
...
@@ -59,22 +59,25 @@ public:
*/
*/
class
CpuNeighborList
::
Voxels
{
class
CpuNeighborList
::
Voxels
{
public:
public:
Voxels
(
int
blockSize
,
float
vsy
,
float
vsz
,
float
miny
,
float
maxy
,
float
minz
,
float
maxz
,
const
RealVec
*
periodicBoxVectors
,
bool
usePeriodic
)
:
Voxels
(
int
blockSize
,
float
vsy
,
float
vsz
,
float
miny
,
float
maxy
,
float
minz
,
float
maxz
,
const
RealVec
*
boxVectors
,
bool
usePeriodic
)
:
blockSize
(
blockSize
),
voxelSizeY
(
vsy
),
voxelSizeZ
(
vsz
),
miny
(
miny
),
maxy
(
maxy
),
minz
(
minz
),
maxz
(
maxz
),
periodicBoxVectors
(
periodicBoxVectors
),
usePeriodic
(
usePeriodic
)
{
blockSize
(
blockSize
),
voxelSizeY
(
vsy
),
voxelSizeZ
(
vsz
),
miny
(
miny
),
maxy
(
maxy
),
minz
(
minz
),
maxz
(
maxz
),
usePeriodic
(
usePeriodic
)
{
periodicBoxSize
[
0
]
=
(
float
)
periodicBoxVectors
[
0
][
0
];
for
(
int
i
=
0
;
i
<
3
;
i
++
)
periodicBoxSize
[
1
]
=
(
float
)
periodicBoxVectors
[
1
][
1
];
for
(
int
j
=
0
;
j
<
3
;
j
++
)
periodicBoxSize
[
2
]
=
(
float
)
periodicBoxVectors
[
2
][
2
];
periodicBoxVectors
[
i
][
j
]
=
(
float
)
boxVectors
[
i
][
j
];
recipBoxSize
[
0
]
=
(
float
)
(
1
/
periodicBoxVectors
[
0
][
0
]);
periodicBoxSize
[
0
]
=
(
float
)
boxVectors
[
0
][
0
];
recipBoxSize
[
1
]
=
(
float
)
(
1
/
periodicBoxVectors
[
1
][
1
]);
periodicBoxSize
[
1
]
=
(
float
)
boxVectors
[
1
][
1
];
recipBoxSize
[
2
]
=
(
float
)
(
1
/
periodicBoxVectors
[
2
][
2
]);
periodicBoxSize
[
2
]
=
(
float
)
boxVectors
[
2
][
2
];
triclinic
=
(
periodicBoxVectors
[
0
][
1
]
!=
0.0
||
periodicBoxVectors
[
0
][
2
]
!=
0.0
||
recipBoxSize
[
0
]
=
(
float
)
(
1
/
boxVectors
[
0
][
0
]);
periodicBoxVectors
[
1
][
0
]
!=
0.0
||
periodicBoxVectors
[
1
][
2
]
!=
0.0
||
recipBoxSize
[
1
]
=
(
float
)
(
1
/
boxVectors
[
1
][
1
]);
periodicBoxVectors
[
2
][
0
]
!=
0.0
||
periodicBoxVectors
[
2
][
1
]
!=
0.0
);
recipBoxSize
[
2
]
=
(
float
)
(
1
/
boxVectors
[
2
][
2
]);
triclinic
=
(
boxVectors
[
0
][
1
]
!=
0.0
||
boxVectors
[
0
][
2
]
!=
0.0
||
boxVectors
[
1
][
0
]
!=
0.0
||
boxVectors
[
1
][
2
]
!=
0.0
||
boxVectors
[
2
][
0
]
!=
0.0
||
boxVectors
[
2
][
1
]
!=
0.0
);
if
(
usePeriodic
)
{
if
(
usePeriodic
)
{
ny
=
(
int
)
floorf
(
periodicB
oxVectors
[
1
][
1
]
/
voxelSizeY
+
0.5
f
);
ny
=
(
int
)
floorf
(
b
oxVectors
[
1
][
1
]
/
voxelSizeY
+
0.5
f
);
nz
=
(
int
)
floorf
(
periodicB
oxVectors
[
2
][
2
]
/
voxelSizeZ
+
0.5
f
);
nz
=
(
int
)
floorf
(
b
oxVectors
[
2
][
2
]
/
voxelSizeZ
+
0.5
f
);
voxelSizeY
=
periodicB
oxVectors
[
1
][
1
]
/
ny
;
voxelSizeY
=
b
oxVectors
[
1
][
1
]
/
ny
;
voxelSizeZ
=
periodicB
oxVectors
[
2
][
2
]
/
nz
;
voxelSizeZ
=
b
oxVectors
[
2
][
2
]
/
nz
;
}
}
else
{
else
{
ny
=
max
(
1
,
(
int
)
floorf
((
maxy
-
miny
)
/
voxelSizeY
+
0.5
f
));
ny
=
max
(
1
,
(
int
)
floorf
((
maxy
-
miny
)
/
voxelSizeY
+
0.5
f
));
...
@@ -282,9 +285,10 @@ public:
...
@@ -282,9 +285,10 @@ public:
// 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.
const
vector
<
pair
<
float
,
int
>
>&
voxelBins
=
bins
[
voxelIndex
.
y
][
voxelIndex
.
z
];
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
.
y
][
voxelIndex
.
z
]
[
item
].
second
;
const
int
sortedIndex
=
voxelBins
[
item
].
second
;
// Avoid duplicate entries.
// Avoid duplicate entries.
if
(
sortedIndex
>=
lastSortedIndex
)
if
(
sortedIndex
>=
lastSortedIndex
)
...
@@ -361,7 +365,7 @@ private:
...
@@ -361,7 +365,7 @@ private:
int
ny
,
nz
;
int
ny
,
nz
;
float
periodicBoxSize
[
3
],
recipBoxSize
[
3
];
float
periodicBoxSize
[
3
],
recipBoxSize
[
3
];
bool
triclinic
;
bool
triclinic
;
const
RealVec
*
periodicBoxVectors
;
float
periodicBoxVectors
[
3
][
3
]
;
const
bool
usePeriodic
;
const
bool
usePeriodic
;
vector
<
vector
<
vector
<
pair
<
float
,
int
>
>
>
>
bins
;
vector
<
vector
<
vector
<
pair
<
float
,
int
>
>
>
>
bins
;
};
};
...
@@ -444,6 +448,7 @@ void CpuNeighborList::computeNeighborList(int numAtoms, const AlignedArray<float
...
@@ -444,6 +448,7 @@ void CpuNeighborList::computeNeighborList(int numAtoms, const AlignedArray<float
// Signal the threads to start running and wait for them to finish.
// Signal the threads to start running and wait for them to finish.
gmx_atomic_set
(
&
atomicCounter
,
0
);
threads
.
resumeThreads
();
threads
.
resumeThreads
();
threads
.
waitForThreads
();
threads
.
waitForThreads
();
...
@@ -500,7 +505,11 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
...
@@ -500,7 +505,11 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
vector
<
int
>
blockAtoms
;
vector
<
int
>
blockAtoms
;
vector
<
float
>
blockAtomX
(
blockSize
),
blockAtomY
(
blockSize
),
blockAtomZ
(
blockSize
);
vector
<
float
>
blockAtomX
(
blockSize
),
blockAtomY
(
blockSize
),
blockAtomZ
(
blockSize
);
vector
<
VoxelIndex
>
atomVoxelIndex
;
vector
<
VoxelIndex
>
atomVoxelIndex
;
for
(
int
i
=
threadIndex
;
i
<
numBlocks
;
i
+=
numThreads
)
{
while
(
true
)
{
int
i
=
gmx_atomic_fetch_add
(
&
atomicCounter
,
1
);
if
(
i
>=
numBlocks
)
break
;
// Find the atoms in this block and compute their bounding box.
// Find the atoms in this block and compute their bounding box.
int
firstIndex
=
blockSize
*
i
;
int
firstIndex
=
blockSize
*
i
;
...
@@ -532,14 +541,24 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
...
@@ -532,14 +541,24 @@ void CpuNeighborList::threadComputeNeighborList(ThreadPool& threads, int threadI
// Record the exclusions for this block.
// Record the exclusions for this block.
map
<
int
,
char
>
atomFlags
;
for
(
int
j
=
0
;
j
<
atomsInBlock
;
j
++
)
{
for
(
int
j
=
0
;
j
<
atomsInBlock
;
j
++
)
{
const
set
<
int
>&
atomExclusions
=
(
*
exclusions
)[
sortedAtoms
[
firstIndex
+
j
]];
const
set
<
int
>&
atomExclusions
=
(
*
exclusions
)[
sortedAtoms
[
firstIndex
+
j
]];
char
mask
=
1
<<
j
;
char
mask
=
1
<<
j
;
for
(
int
k
=
0
;
k
<
(
int
)
blockNeighbors
[
i
].
size
();
k
++
)
{
for
(
set
<
int
>::
const_iterator
iter
=
atomExclusions
.
begin
();
iter
!=
atomExclusions
.
end
();
++
iter
)
{
int
atomIndex
=
blockNeighbors
[
i
][
k
];
map
<
int
,
char
>::
iterator
thisAtomFlags
=
atomFlags
.
find
(
*
iter
);
if
(
atomExclusions
.
find
(
atomIndex
)
!=
atomExclusions
.
end
())
if
(
thisAtomFlags
==
atomFlags
.
end
())
blockExclusions
[
i
][
k
]
|=
mask
;
atomFlags
[
*
iter
]
=
mask
;
else
thisAtomFlags
->
second
|=
mask
;
}
}
}
int
numNeighbors
=
blockNeighbors
[
i
].
size
();
for
(
int
k
=
0
;
k
<
numNeighbors
;
k
++
)
{
int
atomIndex
=
blockNeighbors
[
i
][
k
];
map
<
int
,
char
>::
iterator
thisAtomFlags
=
atomFlags
.
find
(
atomIndex
);
if
(
thisAtomFlags
!=
atomFlags
.
end
())
blockExclusions
[
i
][
k
]
|=
thisAtomFlags
->
second
;
}
}
}
}
}
}
...
...
Prev
1
2
3
4
5
6
…
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