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
c66766a8
Commit
c66766a8
authored
Sep 03, 2014
by
peastman
Browse files
Fixed errors on Windows
parent
6f7dee30
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1049 additions
and
1045 deletions
+1049
-1045
openmmapi/include/openmm/internal/vectorize_sse.h
openmmapi/include/openmm/internal/vectorize_sse.h
+305
-305
platforms/cpu/include/CpuCustomManyParticleForce.h
platforms/cpu/include/CpuCustomManyParticleForce.h
+223
-224
platforms/cpu/src/CpuCustomManyParticleForce.cpp
platforms/cpu/src/CpuCustomManyParticleForce.cpp
+521
-516
No files found.
openmmapi/include/openmm/internal/vectorize_sse.h
View file @
c66766a8
#ifndef OPENMM_VECTORIZE_SSE_H_
#ifndef OPENMM_VECTORIZE_SSE_H_
#define OPENMM_VECTORIZE_SSE_H_
#define OPENMM_VECTORIZE_SSE_H_
/* -------------------------------------------------------------------------- *
/* -------------------------------------------------------------------------- *
* OpenMM *
* OpenMM *
* -------------------------------------------------------------------------- *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* 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 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* 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: *
* Software is furnished to do so, subject to the following conditions: *
* *
* *
* The above copyright notice and this permission notice shall be included in *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* all copies or substantial portions of the Software. *
* *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* 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 *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
#include <smmintrin.h>
#include <smmintrin.h>
#include "hardware.h"
#include "hardware.h"
// This file defines classes and functions to simplify vectorizing code with SSE.
// This file defines classes and functions to simplify vectorizing code with SSE.
/**
/**
* Determine whether ivec4 and fvec4 are supported on this processor.
* Determine whether ivec4 and fvec4 are supported on this processor.
*/
*/
static
bool
isVec4Supported
()
{
static
bool
isVec4Supported
()
{
int
cpuInfo
[
4
];
int
cpuInfo
[
4
];
cpuid
(
cpuInfo
,
0
);
cpuid
(
cpuInfo
,
0
);
if
(
cpuInfo
[
0
]
>=
1
)
{
if
(
cpuInfo
[
0
]
>=
1
)
{
cpuid
(
cpuInfo
,
1
);
cpuid
(
cpuInfo
,
1
);
return
((
cpuInfo
[
2
]
&
((
int
)
1
<<
19
))
!=
0
);
return
((
cpuInfo
[
2
]
&
((
int
)
1
<<
19
))
!=
0
);
}
}
return
false
;
return
false
;
}
}
class
ivec4
;
class
ivec4
;
/**
/**
* A four element vector of floats.
* A four element vector of floats.
*/
*/
class
fvec4
{
class
fvec4
{
public:
public:
__m128
val
;
__m128
val
;
fvec4
()
{}
fvec4
()
{}
fvec4
(
float
v
)
:
val
(
_mm_set1_ps
(
v
))
{}
fvec4
(
float
v
)
:
val
(
_mm_set1_ps
(
v
))
{}
fvec4
(
float
v1
,
float
v2
,
float
v3
,
float
v4
)
:
val
(
_mm_set_ps
(
v4
,
v3
,
v2
,
v1
))
{}
fvec4
(
float
v1
,
float
v2
,
float
v3
,
float
v4
)
:
val
(
_mm_set_ps
(
v4
,
v3
,
v2
,
v1
))
{}
fvec4
(
__m128
v
)
:
val
(
v
)
{}
fvec4
(
__m128
v
)
:
val
(
v
)
{}
fvec4
(
const
float
*
v
)
:
val
(
_mm_loadu_ps
(
v
))
{}
fvec4
(
const
float
*
v
)
:
val
(
_mm_loadu_ps
(
v
))
{}
operator
__m128
()
const
{
operator
__m128
()
const
{
return
val
;
return
val
;
}
}
float
operator
[](
int
i
)
const
{
float
operator
[](
int
i
)
const
{
float
result
[
4
];
float
result
[
4
];
store
(
result
);
store
(
result
);
return
result
[
i
];
return
result
[
i
];
}
}
void
store
(
float
*
v
)
const
{
void
store
(
float
*
v
)
const
{
_mm_storeu_ps
(
v
,
val
);
_mm_storeu_ps
(
v
,
val
);
}
}
fvec4
operator
+
(
const
fvec4
&
other
)
const
{
fvec4
operator
+
(
const
fvec4
&
other
)
const
{
return
_mm_add_ps
(
val
,
other
);
return
_mm_add_ps
(
val
,
other
);
}
}
fvec4
operator
-
(
const
fvec4
&
other
)
const
{
fvec4
operator
-
(
const
fvec4
&
other
)
const
{
return
_mm_sub_ps
(
val
,
other
);
return
_mm_sub_ps
(
val
,
other
);
}
}
fvec4
operator
*
(
const
fvec4
&
other
)
const
{
fvec4
operator
*
(
const
fvec4
&
other
)
const
{
return
_mm_mul_ps
(
val
,
other
);
return
_mm_mul_ps
(
val
,
other
);
}
}
fvec4
operator
/
(
const
fvec4
&
other
)
const
{
fvec4
operator
/
(
const
fvec4
&
other
)
const
{
return
_mm_div_ps
(
val
,
other
);
return
_mm_div_ps
(
val
,
other
);
}
}
void
operator
+=
(
const
fvec4
&
other
)
{
void
operator
+=
(
const
fvec4
&
other
)
{
val
=
_mm_add_ps
(
val
,
other
);
val
=
_mm_add_ps
(
val
,
other
);
}
}
void
operator
-=
(
const
fvec4
&
other
)
{
void
operator
-=
(
const
fvec4
&
other
)
{
val
=
_mm_sub_ps
(
val
,
other
);
val
=
_mm_sub_ps
(
val
,
other
);
}
}
void
operator
*=
(
const
fvec4
&
other
)
{
void
operator
*=
(
const
fvec4
&
other
)
{
val
=
_mm_mul_ps
(
val
,
other
);
val
=
_mm_mul_ps
(
val
,
other
);
}
}
void
operator
/=
(
const
fvec4
&
other
)
{
void
operator
/=
(
const
fvec4
&
other
)
{
val
=
_mm_div_ps
(
val
,
other
);
val
=
_mm_div_ps
(
val
,
other
);
}
}
fvec4
operator
-
()
const
{
fvec4
operator
-
()
const
{
return
_mm_sub_ps
(
_mm_set1_ps
(
0.0
f
),
val
);
return
_mm_sub_ps
(
_mm_set1_ps
(
0.0
f
),
val
);
}
}
fvec4
operator
&
(
const
fvec4
&
other
)
const
{
fvec4
operator
&
(
const
fvec4
&
other
)
const
{
return
_mm_and_ps
(
val
,
other
);
return
_mm_and_ps
(
val
,
other
);
}
}
fvec4
operator
|
(
const
fvec4
&
other
)
const
{
fvec4
operator
|
(
const
fvec4
&
other
)
const
{
return
_mm_or_ps
(
val
,
other
);
return
_mm_or_ps
(
val
,
other
);
}
}
fvec4
operator
==
(
const
fvec4
&
other
)
const
{
fvec4
operator
==
(
const
fvec4
&
other
)
const
{
return
_mm_cmpeq_ps
(
val
,
other
);
return
_mm_cmpeq_ps
(
val
,
other
);
}
}
fvec4
operator
!=
(
const
fvec4
&
other
)
const
{
fvec4
operator
!=
(
const
fvec4
&
other
)
const
{
return
_mm_cmpneq_ps
(
val
,
other
);
return
_mm_cmpneq_ps
(
val
,
other
);
}
}
fvec4
operator
>
(
const
fvec4
&
other
)
const
{
fvec4
operator
>
(
const
fvec4
&
other
)
const
{
return
_mm_cmpgt_ps
(
val
,
other
);
return
_mm_cmpgt_ps
(
val
,
other
);
}
}
fvec4
operator
<
(
const
fvec4
&
other
)
const
{
fvec4
operator
<
(
const
fvec4
&
other
)
const
{
return
_mm_cmplt_ps
(
val
,
other
);
return
_mm_cmplt_ps
(
val
,
other
);
}
}
fvec4
operator
>=
(
const
fvec4
&
other
)
const
{
fvec4
operator
>=
(
const
fvec4
&
other
)
const
{
return
_mm_cmpge_ps
(
val
,
other
);
return
_mm_cmpge_ps
(
val
,
other
);
}
}
fvec4
operator
<=
(
const
fvec4
&
other
)
const
{
fvec4
operator
<=
(
const
fvec4
&
other
)
const
{
return
_mm_cmple_ps
(
val
,
other
);
return
_mm_cmple_ps
(
val
,
other
);
}
}
operator
ivec4
()
const
;
operator
ivec4
()
const
;
};
};
/**
/**
* A four element vector of ints.
* A four element vector of ints.
*/
*/
class
ivec4
{
class
ivec4
{
public:
public:
__m128i
val
;
__m128i
val
;
ivec4
()
{}
ivec4
()
{}
ivec4
(
int
v
)
:
val
(
_mm_set1_epi32
(
v
))
{}
ivec4
(
int
v
)
:
val
(
_mm_set1_epi32
(
v
))
{}
ivec4
(
int
v1
,
int
v2
,
int
v3
,
int
v4
)
:
val
(
_mm_set_epi32
(
v4
,
v3
,
v2
,
v1
))
{}
ivec4
(
int
v1
,
int
v2
,
int
v3
,
int
v4
)
:
val
(
_mm_set_epi32
(
v4
,
v3
,
v2
,
v1
))
{}
ivec4
(
__m128i
v
)
:
val
(
v
)
{}
ivec4
(
__m128i
v
)
:
val
(
v
)
{}
ivec4
(
const
int
*
v
)
:
val
(
_mm_loadu_si128
((
const
__m128i
*
)
v
))
{}
ivec4
(
const
int
*
v
)
:
val
(
_mm_loadu_si128
((
const
__m128i
*
)
v
))
{}
operator
__m128i
()
const
{
operator
__m128i
()
const
{
return
val
;
return
val
;
}
}
int
operator
[](
int
i
)
const
{
int
operator
[](
int
i
)
const
{
int
result
[
4
];
int
result
[
4
];
store
(
result
);
store
(
result
);
return
result
[
i
];
return
result
[
i
];
}
}
void
store
(
int
*
v
)
const
{
void
store
(
int
*
v
)
const
{
_mm_storeu_si128
((
__m128i
*
)
v
,
val
);
_mm_storeu_si128
((
__m128i
*
)
v
,
val
);
}
}
ivec4
operator
+
(
const
ivec4
&
other
)
const
{
ivec4
operator
+
(
const
ivec4
&
other
)
const
{
return
_mm_add_epi32
(
val
,
other
);
return
_mm_add_epi32
(
val
,
other
);
}
}
ivec4
operator
-
(
const
ivec4
&
other
)
const
{
ivec4
operator
-
(
const
ivec4
&
other
)
const
{
return
_mm_sub_epi32
(
val
,
other
);
return
_mm_sub_epi32
(
val
,
other
);
}
}
ivec4
operator
*
(
const
ivec4
&
other
)
const
{
ivec4
operator
*
(
const
ivec4
&
other
)
const
{
return
_mm_mullo_epi32
(
val
,
other
);
return
_mm_mullo_epi32
(
val
,
other
);
}
}
void
operator
+=
(
const
ivec4
&
other
)
{
void
operator
+=
(
const
ivec4
&
other
)
{
val
=
_mm_add_epi32
(
val
,
other
);
val
=
_mm_add_epi32
(
val
,
other
);
}
}
void
operator
-=
(
const
ivec4
&
other
)
{
void
operator
-=
(
const
ivec4
&
other
)
{
val
=
_mm_sub_epi32
(
val
,
other
);
val
=
_mm_sub_epi32
(
val
,
other
);
}
}
void
operator
*=
(
const
ivec4
&
other
)
{
void
operator
*=
(
const
ivec4
&
other
)
{
val
=
_mm_mullo_epi32
(
val
,
other
);
val
=
_mm_mullo_epi32
(
val
,
other
);
}
}
ivec4
operator
-
()
const
{
ivec4
operator
-
()
const
{
return
_mm_sub_epi32
(
_mm_set1_epi32
(
0
),
val
);
return
_mm_sub_epi32
(
_mm_set1_epi32
(
0
),
val
);
}
}
ivec4
operator
&
(
const
ivec4
&
other
)
const
{
ivec4
operator
&
(
const
ivec4
&
other
)
const
{
return
_mm_and_si128
(
val
,
other
);
return
_mm_and_si128
(
val
,
other
);
}
}
ivec4
operator
|
(
const
ivec4
&
other
)
const
{
ivec4
operator
|
(
const
ivec4
&
other
)
const
{
return
_mm_or_si128
(
val
,
other
);
return
_mm_or_si128
(
val
,
other
);
}
}
ivec4
operator
==
(
const
ivec4
&
other
)
const
{
ivec4
operator
==
(
const
ivec4
&
other
)
const
{
return
_mm_cmpeq_epi32
(
val
,
other
);
return
_mm_cmpeq_epi32
(
val
,
other
);
}
}
ivec4
operator
!=
(
const
ivec4
&
other
)
const
{
ivec4
operator
!=
(
const
ivec4
&
other
)
const
{
return
_mm_xor_si128
(
*
this
==
other
,
_mm_set1_epi32
(
0xFFFFFFFF
));
return
_mm_xor_si128
(
*
this
==
other
,
_mm_set1_epi32
(
0xFFFFFFFF
));
}
}
ivec4
operator
>
(
const
ivec4
&
other
)
const
{
ivec4
operator
>
(
const
ivec4
&
other
)
const
{
return
_mm_cmpgt_epi32
(
val
,
other
);
return
_mm_cmpgt_epi32
(
val
,
other
);
}
}
ivec4
operator
<
(
const
ivec4
&
other
)
const
{
ivec4
operator
<
(
const
ivec4
&
other
)
const
{
return
_mm_cmplt_epi32
(
val
,
other
);
return
_mm_cmplt_epi32
(
val
,
other
);
}
}
ivec4
operator
>=
(
const
ivec4
&
other
)
const
{
ivec4
operator
>=
(
const
ivec4
&
other
)
const
{
return
_mm_xor_si128
(
_mm_cmplt_epi32
(
val
,
other
),
_mm_set1_epi32
(
0xFFFFFFFF
));
return
_mm_xor_si128
(
_mm_cmplt_epi32
(
val
,
other
),
_mm_set1_epi32
(
0xFFFFFFFF
));
}
}
ivec4
operator
<=
(
const
ivec4
&
other
)
const
{
ivec4
operator
<=
(
const
ivec4
&
other
)
const
{
return
_mm_xor_si128
(
_mm_cmpgt_epi32
(
val
,
other
),
_mm_set1_epi32
(
0xFFFFFFFF
));
return
_mm_xor_si128
(
_mm_cmpgt_epi32
(
val
,
other
),
_mm_set1_epi32
(
0xFFFFFFFF
));
}
}
operator
fvec4
()
const
;
operator
fvec4
()
const
;
};
};
// Conversion operators.
// Conversion operators.
inline
fvec4
::
operator
ivec4
()
const
{
inline
fvec4
::
operator
ivec4
()
const
{
return
_mm_cvttps_epi32
(
val
);
return
_mm_cvttps_epi32
(
val
);
}
}
inline
ivec4
::
operator
fvec4
()
const
{
inline
ivec4
::
operator
fvec4
()
const
{
return
_mm_cvtepi32_ps
(
val
);
return
_mm_cvtepi32_ps
(
val
);
}
}
// Functions that operate on fvec4s.
// Functions that operate on fvec4s.
static
inline
fvec4
floor
(
const
fvec4
&
v
)
{
static
inline
fvec4
floor
(
const
fvec4
&
v
)
{
return
fvec4
(
_mm_floor_ps
(
v
.
val
));
return
fvec4
(
_mm_floor_ps
(
v
.
val
));
}
}
static
inline
fvec4
ceil
(
const
fvec4
&
v
)
{
static
inline
fvec4
ceil
(
const
fvec4
&
v
)
{
return
fvec4
(
_mm_ceil_ps
(
v
.
val
));
return
fvec4
(
_mm_ceil_ps
(
v
.
val
));
}
}
static
inline
fvec4
round
(
const
fvec4
&
v
)
{
static
inline
fvec4
round
(
const
fvec4
&
v
)
{
return
fvec4
(
_mm_round_ps
(
v
.
val
,
_MM_FROUND_TO_NEAREST_INT
));
return
fvec4
(
_mm_round_ps
(
v
.
val
,
_MM_FROUND_TO_NEAREST_INT
));
}
}
static
inline
fvec4
min
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
static
inline
fvec4
min
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
return
fvec4
(
_mm_min_ps
(
v1
.
val
,
v2
.
val
));
return
fvec4
(
_mm_min_ps
(
v1
.
val
,
v2
.
val
));
}
}
static
inline
fvec4
max
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
static
inline
fvec4
max
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
return
fvec4
(
_mm_max_ps
(
v1
.
val
,
v2
.
val
));
return
fvec4
(
_mm_max_ps
(
v1
.
val
,
v2
.
val
));
}
}
static
inline
fvec4
abs
(
const
fvec4
&
v
)
{
static
inline
fvec4
abs
(
const
fvec4
&
v
)
{
static
const
__m128
mask
=
_mm_castsi128_ps
(
_mm_set1_epi32
(
0x7FFFFFFF
));
static
const
__m128
mask
=
_mm_castsi128_ps
(
_mm_set1_epi32
(
0x7FFFFFFF
));
return
fvec4
(
_mm_and_ps
(
v
.
val
,
mask
));
return
fvec4
(
_mm_and_ps
(
v
.
val
,
mask
));
}
}
static
inline
fvec4
sqrt
(
const
fvec4
&
v
)
{
static
inline
fvec4
sqrt
(
const
fvec4
&
v
)
{
return
fvec4
(
_mm_sqrt_ps
(
v
.
val
));
return
fvec4
(
_mm_sqrt_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
));
}
}
static
inline
float
dot4
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
static
inline
float
dot4
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
return
_mm_cvtss_f32
(
_mm_dp_ps
(
v1
,
v2
,
0xF1
));
return
_mm_cvtss_f32
(
_mm_dp_ps
(
v1
,
v2
,
0xF1
));
}
}
static
inline
fvec4
cross
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
static
inline
fvec4
cross
(
const
fvec4
&
v1
,
const
fvec4
&
v2
)
{
fvec4
temp
=
_mm_mul_ps
(
v1
,
_mm_shuffle_ps
(
v2
,
v2
,
_MM_SHUFFLE
(
3
,
0
,
2
,
1
)))
-
fvec4
temp
=
fvec4
(
_mm_mul_ps
(
v1
,
_mm_shuffle_ps
(
v2
,
v2
,
_MM_SHUFFLE
(
3
,
0
,
2
,
1
)))
)
-
_mm_mul_ps
(
v2
,
_mm_shuffle_ps
(
v1
,
v1
,
_MM_SHUFFLE
(
3
,
0
,
2
,
1
)))
;
fvec4
(
_mm_mul_ps
(
v2
,
_mm_shuffle_ps
(
v1
,
v1
,
_MM_SHUFFLE
(
3
,
0
,
2
,
1
)))
);
return
_mm_shuffle_ps
(
temp
,
temp
,
_MM_SHUFFLE
(
3
,
0
,
2
,
1
));
return
_mm_shuffle_ps
(
temp
,
temp
,
_MM_SHUFFLE
(
3
,
0
,
2
,
1
));
}
}
static
inline
void
transpose
(
fvec4
&
v1
,
fvec4
&
v2
,
fvec4
&
v3
,
fvec4
&
v4
)
{
static
inline
void
transpose
(
fvec4
&
v1
,
fvec4
&
v2
,
fvec4
&
v3
,
fvec4
&
v4
)
{
_MM_TRANSPOSE4_PS
(
v1
,
v2
,
v3
,
v4
);
_MM_TRANSPOSE4_PS
(
v1
,
v2
,
v3
,
v4
);
}
}
// Functions that operate on ivec4s.
// Functions that operate on ivec4s.
static
inline
ivec4
min
(
const
ivec4
&
v1
,
const
ivec4
&
v2
)
{
static
inline
ivec4
min
(
const
ivec4
&
v1
,
const
ivec4
&
v2
)
{
return
ivec4
(
_mm_min_epi32
(
v1
.
val
,
v2
.
val
));
return
ivec4
(
_mm_min_epi32
(
v1
.
val
,
v2
.
val
));
}
}
static
inline
ivec4
max
(
const
ivec4
&
v1
,
const
ivec4
&
v2
)
{
static
inline
ivec4
max
(
const
ivec4
&
v1
,
const
ivec4
&
v2
)
{
return
ivec4
(
_mm_max_epi32
(
v1
.
val
,
v2
.
val
));
return
ivec4
(
_mm_max_epi32
(
v1
.
val
,
v2
.
val
));
}
}
static
inline
ivec4
abs
(
const
ivec4
&
v
)
{
static
inline
ivec4
abs
(
const
ivec4
&
v
)
{
return
ivec4
(
_mm_abs_epi32
(
v
.
val
));
return
ivec4
(
_mm_abs_epi32
(
v
.
val
));
}
}
static
inline
bool
any
(
const
ivec4
&
v
)
{
static
inline
bool
any
(
const
ivec4
&
v
)
{
return
!
_mm_test_all_zeros
(
v
,
_mm_set1_epi32
(
0xFFFFFFFF
));
return
!
_mm_test_all_zeros
(
v
,
_mm_set1_epi32
(
0xFFFFFFFF
));
}
}
// Mathematical operators involving a scalar and a vector.
// Mathematical operators involving a scalar and a vector.
static
inline
fvec4
operator
+
(
float
v1
,
const
fvec4
&
v2
)
{
static
inline
fvec4
operator
+
(
float
v1
,
const
fvec4
&
v2
)
{
return
fvec4
(
v1
)
+
v2
;
return
fvec4
(
v1
)
+
v2
;
}
}
static
inline
fvec4
operator
-
(
float
v1
,
const
fvec4
&
v2
)
{
static
inline
fvec4
operator
-
(
float
v1
,
const
fvec4
&
v2
)
{
return
fvec4
(
v1
)
-
v2
;
return
fvec4
(
v1
)
-
v2
;
}
}
static
inline
fvec4
operator
*
(
float
v1
,
const
fvec4
&
v2
)
{
static
inline
fvec4
operator
*
(
float
v1
,
const
fvec4
&
v2
)
{
return
fvec4
(
v1
)
*
v2
;
return
fvec4
(
v1
)
*
v2
;
}
}
static
inline
fvec4
operator
/
(
float
v1
,
const
fvec4
&
v2
)
{
static
inline
fvec4
operator
/
(
float
v1
,
const
fvec4
&
v2
)
{
return
fvec4
(
v1
)
/
v2
;
return
fvec4
(
v1
)
/
v2
;
}
}
// Operations for blending fvec4s based on an ivec4.
// Operations for blending fvec4s based on an ivec4.
static
inline
fvec4
blend
(
const
fvec4
&
v1
,
const
fvec4
&
v2
,
const
ivec4
&
mask
)
{
static
inline
fvec4
blend
(
const
fvec4
&
v1
,
const
fvec4
&
v2
,
const
ivec4
&
mask
)
{
return
fvec4
(
_mm_blendv_ps
(
v1
.
val
,
v2
.
val
,
_mm_castsi128_ps
(
mask
.
val
)));
return
fvec4
(
_mm_blendv_ps
(
v1
.
val
,
v2
.
val
,
_mm_castsi128_ps
(
mask
.
val
)));
}
}
#endif
/*OPENMM_VECTORIZE_SSE_H_*/
#endif
/*OPENMM_VECTORIZE_SSE_H_*/
platforms/cpu/include/CpuCustomManyParticleForce.h
View file @
c66766a8
/* Portions copyright (c) 2009-2014 Stanford University and Simbios.
/* Portions copyright (c) 2009-2014 Stanford University and Simbios.
* Contributors: Peter Eastman
* Contributors: Peter Eastman
*
*
* Permission is hereby granted, free of charge, to any person obtaining
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
* to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
* in all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#ifndef OPENMM_CPU_CUSTOM_MANY_PARTICLE_FORCE_H__
#ifndef OPENMM_CPU_CUSTOM_MANY_PARTICLE_FORCE_H__
#define OPENMM_CPU_CUSTOM_MANY_PARTICLE_FORCE_H__
#define OPENMM_CPU_CUSTOM_MANY_PARTICLE_FORCE_H__
#include "ReferenceForce.h"
#include "ReferenceForce.h"
#include "ReferenceBondIxn.h"
#include "ReferenceBondIxn.h"
#include "CompiledExpressionSet.h"
#include "CompiledExpressionSet.h"
#include "CpuNeighborList.h"
#include "CpuNeighborList.h"
#include "openmm/CustomManyParticleForce.h"
#include "openmm/CustomManyParticleForce.h"
#include "openmm/internal/ThreadPool.h"
#include "openmm/internal/ThreadPool.h"
#include "openmm/internal/vectorize.h"
#include "openmm/internal/vectorize.h"
#include "lepton/CompiledExpression.h"
#include "lepton/CompiledExpression.h"
#include "lepton/ParsedExpression.h"
#include "lepton/ParsedExpression.h"
#include <map>
#include <map>
#include <set>
#include <set>
#include <utility>
#include <utility>
#include <vector>
#include <vector>
namespace
OpenMM
{
namespace
OpenMM
{
class
CpuCustomManyParticleForce
{
class
CpuCustomManyParticleForce
{
private:
private:
class
ParticleTermInfo
;
class
ParticleTermInfo
;
class
DistanceTermInfo
;
class
DistanceTermInfo
;
class
AngleTermInfo
;
class
AngleTermInfo
;
class
DihedralTermInfo
;
class
DihedralTermInfo
;
class
ComputeForceTask
;
class
ComputeForceTask
;
class
ThreadData
;
class
ThreadData
;
int
numParticles
,
numParticlesPerSet
,
numPerParticleParameters
,
numTypes
;
int
numParticles
,
numParticlesPerSet
,
numPerParticleParameters
,
numTypes
;
bool
useCutoff
,
usePeriodic
,
centralParticleMode
;
bool
useCutoff
,
usePeriodic
,
centralParticleMode
;
RealOpenMM
cutoffDistance
;
RealOpenMM
cutoffDistance
;
RealOpenMM
periodicBoxSize
[
3
];
RealOpenMM
periodicBoxSize
[
3
];
CpuNeighborList
*
neighborList
;
CpuNeighborList
*
neighborList
;
ThreadPool
&
threads
;
ThreadPool
&
threads
;
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
std
::
vector
<
int
>
particleTypes
;
std
::
vector
<
int
>
particleTypes
;
std
::
vector
<
int
>
orderIndex
;
std
::
vector
<
int
>
orderIndex
;
std
::
vector
<
std
::
vector
<
int
>
>
particleOrder
;
std
::
vector
<
std
::
vector
<
int
>
>
particleOrder
;
std
::
vector
<
std
::
vector
<
int
>
>
particleNeighbors
;
std
::
vector
<
std
::
vector
<
int
>
>
particleNeighbors
;
std
::
vector
<
ThreadData
*>
threadData
;
std
::
vector
<
ThreadData
*>
threadData
;
// The following variables are used to make information accessible to the individual threads.
// The following variables are used to make information accessible to the individual threads.
float
*
posq
;
float
*
posq
;
RealOpenMM
**
particleParameters
;
RealOpenMM
**
particleParameters
;
const
std
::
map
<
std
::
string
,
double
>*
globalParameters
;
const
std
::
map
<
std
::
string
,
double
>*
globalParameters
;
std
::
vector
<
AlignedArray
<
float
>
>*
threadForce
;
std
::
vector
<
AlignedArray
<
float
>
>*
threadForce
;
bool
includeForces
,
includeEnergy
;
bool
includeForces
,
includeEnergy
;
void
*
atomicCounter
;
void
*
atomicCounter
;
/**
/**
* This routine contains the code executed by each thread.
* This routine contains the code executed by each thread.
*/
*/
void
threadComputeForce
(
ThreadPool
&
threads
,
int
threadIndex
);
void
threadComputeForce
(
ThreadPool
&
threads
,
int
threadIndex
);
/**
/**
* This is called recursively to loop over all possible combination of a set of particles and evaluate the
* This is called recursively to loop over all possible combination of a set of particles and evaluate the
* interaction for each one.
* interaction for each one.
*/
*/
void
loopOverInteractions
(
std
::
vector
<
int
>&
availableParticles
,
std
::
vector
<
int
>&
particleSet
,
int
loopIndex
,
int
startIndex
,
void
loopOverInteractions
(
std
::
vector
<
int
>&
availableParticles
,
std
::
vector
<
int
>&
particleSet
,
int
loopIndex
,
int
startIndex
,
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
);
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
);
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Calculate custom interaction for one set of particles
Calculate custom interaction for one set of particles
@param particleSet the indices of the particles
@param particleSet the indices of the particles
@param posq atom coordinates in float format
@param posq atom coordinates in float format
@param particleParameters particle parameter values (particleParameters[particleIndex][parameterIndex])
@param particleParameters particle parameter values (particleParameters[particleIndex][parameterIndex])
@param forces force array (forces added)
@param forces force array (forces added)
@param totalEnergy total energy
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------------- */
/**
/**
* Calculate the interaction for one set of particles
* Calculate the interaction for one set of particles
*
*
* @param particleSet the indices of the particles
* @param particleSet the indices of the particles
* @param particleParameters particle parameter values (particleParameters[particleIndex][parameterIndex])
* @param particleParameters particle parameter values (particleParameters[particleIndex][parameterIndex])
* @param data information and workspace for the current thread
* @param data information and workspace for the current thread
* @param boxSize the size of the periodic box
* @param boxSize the size of the periodic box
* @param invBoxSize the inverse size of the periodic box
* @param invBoxSize the inverse size of the periodic box
*/
*/
void
calculateOneIxn
(
std
::
vector
<
int
>&
particleSet
,
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
);
void
calculateOneIxn
(
std
::
vector
<
int
>&
particleSet
,
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
);
/**
/**
* Compute the displacement and squared distance between two points, optionally using
* Compute the displacement and squared distance between two points, optionally using
* periodic boundary conditions.
* periodic boundary conditions.
*/
*/
void
computeDelta
(
const
fvec4
&
posI
,
const
fvec4
&
posJ
,
fvec4
&
deltaR
,
float
&
r2
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
;
void
computeDelta
(
const
fvec4
&
posI
,
const
fvec4
&
posJ
,
fvec4
&
deltaR
,
float
&
r2
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
;
static
float
computeAngle
(
const
fvec4
&
vi
,
const
fvec4
&
vj
,
float
v2i
,
float
v2j
,
float
sign
);
static
float
computeAngle
(
const
fvec4
&
vi
,
const
fvec4
&
vj
,
float
v2i
,
float
v2j
,
float
sign
);
static
float
getDihedralAngleBetweenThreeVectors
(
const
fvec4
&
v1
,
const
fvec4
&
v2
,
const
fvec4
&
v3
,
fvec4
&
cross1
,
fvec4
&
cross2
,
const
fvec4
&
signVector
);
static
float
getDihedralAngleBetweenThreeVectors
(
const
fvec4
&
v1
,
const
fvec4
&
v2
,
const
fvec4
&
v3
,
fvec4
&
cross1
,
fvec4
&
cross2
,
const
fvec4
&
signVector
);
public:
public:
/**
/**
* Create a new CpuCustomManyParticleForce.
* Create a new CpuCustomManyParticleForce.
*
*
* @param force the CustomManyParticleForce to create it for
* @param force the CustomManyParticleForce to create it for
* @param threads the thread pool to use
* @param threads the thread pool to use
*/
*/
CpuCustomManyParticleForce
(
const
OpenMM
::
CustomManyParticleForce
&
force
,
ThreadPool
&
threads
);
CpuCustomManyParticleForce
(
const
OpenMM
::
CustomManyParticleForce
&
force
,
ThreadPool
&
threads
);
~
CpuCustomManyParticleForce
();
~
CpuCustomManyParticleForce
();
/**
/**
* Set the force to use a cutoff.
* Set the force to use a cutoff.
*
*
* @param distance the cutoff distance
* @param distance the cutoff distance
*/
*/
void
setUseCutoff
(
RealOpenMM
distance
);
void
setUseCutoff
(
RealOpenMM
distance
);
/**
/**
* Set the force to use periodic boundary conditions. This requires that a cutoff has
* Set the force to use periodic boundary conditions. This requires that a cutoff has
* already been set, and the smallest side of the periodic box is at least twice the cutoff
* already 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 boxSize the X, Y, and Z widths of the periodic box
*/
*/
void
setPeriodic
(
OpenMM
::
RealVec
&
boxSize
);
void
setPeriodic
(
OpenMM
::
RealVec
&
boxSize
);
/**
/**
* Calculate the interaction.
* Calculate the interaction.
*
*
* @param posq atom coordinates in float format
* @param posq atom coordinates in float format
* @param particleParameters particle parameter values (particleParameters[particleIndex][parameterIndex])
* @param particleParameters particle parameter values (particleParameters[particleIndex][parameterIndex])
* @param globalParameters the values of global parameters
* @param globalParameters the values of global parameters
* @param threadForce the collection of arrays for each thread to add forces to
* @param threadForce the collection of arrays for each thread to add forces to
* @param includeForce whether to compute forces
* @param includeForce whether to compute forces
* @param includeEnergy whether to compute energy
* @param includeEnergy whether to compute energy
* @param energy the total energy is added to this
* @param energy the total energy is added to this
*/
*/
void
calculateIxn
(
AlignedArray
<
float
>&
posq
,
RealOpenMM
**
particleParameters
,
const
std
::
map
<
std
::
string
,
double
>&
globalParameters
,
void
calculateIxn
(
AlignedArray
<
float
>&
posq
,
RealOpenMM
**
particleParameters
,
const
std
::
map
<
std
::
string
,
double
>&
globalParameters
,
std
::
vector
<
AlignedArray
<
float
>
>&
threadForce
,
bool
includeForces
,
bool
includeEnergy
,
double
&
energy
);
std
::
vector
<
AlignedArray
<
float
>
>&
threadForce
,
bool
includeForces
,
bool
includeEnergy
,
double
&
energy
);
};
};
class
CpuCustomManyParticleForce
::
ParticleTermInfo
{
class
CpuCustomManyParticleForce
::
ParticleTermInfo
{
public:
public:
std
::
string
name
;
std
::
string
name
;
int
atom
,
component
,
variableIndex
;
int
atom
,
component
,
variableIndex
;
Lepton
::
CompiledExpression
forceExpression
;
Lepton
::
CompiledExpression
forceExpression
;
ParticleTermInfo
(
const
std
::
string
&
name
,
int
atom
,
int
component
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
ParticleTermInfo
(
const
std
::
string
&
name
,
int
atom
,
int
component
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
};
};
class
CpuCustomManyParticleForce
::
DistanceTermInfo
{
class
CpuCustomManyParticleForce
::
DistanceTermInfo
{
public:
public:
std
::
string
name
;
std
::
string
name
;
int
p1
,
p2
,
variableIndex
;
int
p1
,
p2
,
variableIndex
;
Lepton
::
CompiledExpression
forceExpression
;
Lepton
::
CompiledExpression
forceExpression
;
int
delta
;
int
delta
;
float
deltaSign
;
float
deltaSign
;
DistanceTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
DistanceTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
};
};
class
CpuCustomManyParticleForce
::
AngleTermInfo
{
class
CpuCustomManyParticleForce
::
AngleTermInfo
{
public:
public:
std
::
string
name
;
std
::
string
name
;
int
p1
,
p2
,
p3
,
variableIndex
;
int
p1
,
p2
,
p3
,
variableIndex
;
Lepton
::
CompiledExpression
forceExpression
;
Lepton
::
CompiledExpression
forceExpression
;
int
delta1
,
delta2
;
int
delta1
,
delta2
;
float
delta1Sign
,
delta2Sign
;
float
delta1Sign
,
delta2Sign
;
AngleTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
AngleTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
};
};
class
CpuCustomManyParticleForce
::
DihedralTermInfo
{
class
CpuCustomManyParticleForce
::
DihedralTermInfo
{
public:
public:
std
::
string
name
;
std
::
string
name
;
int
p1
,
p2
,
p3
,
p4
,
variableIndex
;
int
p1
,
p2
,
p3
,
p4
,
variableIndex
;
Lepton
::
CompiledExpression
forceExpression
;
Lepton
::
CompiledExpression
forceExpression
;
int
delta1
,
delta2
,
delta3
;
int
delta1
,
delta2
,
delta3
;
mutable
fvec4
cross1
,
cross2
;
DihedralTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
DihedralTermInfo
(
const
std
::
string
&
name
,
const
std
::
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
);
};
};
class
CpuCustomManyParticleForce
::
ThreadData
{
class
CpuCustomManyParticleForce
::
ThreadData
{
public:
public:
CompiledExpressionSet
expressionSet
;
CompiledExpressionSet
expressionSet
;
Lepton
::
CompiledExpression
energyExpression
;
Lepton
::
CompiledExpression
energyExpression
;
std
::
vector
<
std
::
vector
<
int
>
>
particleParamIndices
;
std
::
vector
<
std
::
vector
<
int
>
>
particleParamIndices
;
std
::
vector
<
int
>
permutedParticles
;
std
::
vector
<
int
>
permutedParticles
;
std
::
vector
<
std
::
pair
<
int
,
int
>
>
deltaPairs
;
std
::
vector
<
std
::
pair
<
int
,
int
>
>
deltaPairs
;
std
::
vector
<
ParticleTermInfo
>
particleTerms
;
std
::
vector
<
ParticleTermInfo
>
particleTerms
;
std
::
vector
<
DistanceTermInfo
>
distanceTerms
;
std
::
vector
<
DistanceTermInfo
>
distanceTerms
;
std
::
vector
<
AngleTermInfo
>
angleTerms
;
std
::
vector
<
AngleTermInfo
>
angleTerms
;
std
::
vector
<
DihedralTermInfo
>
dihedralTerms
;
std
::
vector
<
DihedralTermInfo
>
dihedralTerms
;
AlignedArray
<
fvec4
>
delta
,
cross1
,
cross2
;
AlignedArray
<
fvec4
>
delta
;
std
::
vector
<
float
>
normDelta
;
std
::
vector
<
float
>
normDelta
;
std
::
vector
<
float
>
norm2Delta
;
std
::
vector
<
float
>
norm2Delta
;
AlignedArray
<
fvec4
>
f
;
AlignedArray
<
fvec4
>
f
;
double
energy
;
double
energy
;
ThreadData
(
const
CustomManyParticleForce
&
force
,
Lepton
::
ParsedExpression
&
energyExpr
,
ThreadData
(
const
CustomManyParticleForce
&
force
,
Lepton
::
ParsedExpression
&
energyExpr
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
distances
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
angles
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
dihedrals
);
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
distances
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
angles
,
std
::
map
<
std
::
string
,
std
::
vector
<
int
>
>&
dihedrals
);
/**
/**
* Request a pair of particles whose distance or displacement vector is needed in the computation.
* Request a pair of particles whose distance or displacement vector is needed in the computation.
*/
*/
void
requestDeltaPair
(
int
p1
,
int
p2
,
int
&
pairIndex
,
float
&
pairSign
,
bool
allowReversed
);
void
requestDeltaPair
(
int
p1
,
int
p2
,
int
&
pairIndex
,
float
&
pairSign
,
bool
allowReversed
);
};
};
}
// namespace OpenMM
}
// namespace OpenMM
#endif // OPENMM_CPU_CUSTOM_MANY_PARTICLE_FORCE_H__
#endif // OPENMM_CPU_CUSTOM_MANY_PARTICLE_FORCE_H__
platforms/cpu/src/CpuCustomManyParticleForce.cpp
View file @
c66766a8
/* Portions copyright (c) 2009-2014 Stanford University and Simbios.
/* Portions copyright (c) 2009-2014 Stanford University and Simbios.
* Contributors: Peter Eastman
* Contributors: Peter Eastman
*
*
* Permission is hereby granted, free of charge, to any person obtaining
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
* to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
* in all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* 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 <string.h>
#include <string.h>
#include <sstream>
#include <sstream>
#include <utility>
#include <utility>
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMCommon.h"
#include "SimTKOpenMMLog.h"
#include "SimTKOpenMMLog.h"
#include "SimTKOpenMMUtilities.h"
#include "SimTKOpenMMUtilities.h"
#include "ReferenceForce.h"
#include "ReferenceForce.h"
#include "CpuCustomManyParticleForce.h"
#include "CpuCustomManyParticleForce.h"
#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 "gmx_atomic.h"
using
namespace
OpenMM
;
using
namespace
OpenMM
;
using
namespace
std
;
using
namespace
std
;
class
CpuCustomManyParticleForce
::
ComputeForceTask
:
public
ThreadPool
::
Task
{
class
CpuCustomManyParticleForce
::
ComputeForceTask
:
public
ThreadPool
::
Task
{
public:
public:
ComputeForceTask
(
CpuCustomManyParticleForce
&
owner
)
:
owner
(
owner
)
{
ComputeForceTask
(
CpuCustomManyParticleForce
&
owner
)
:
owner
(
owner
)
{
}
}
void
execute
(
ThreadPool
&
threads
,
int
threadIndex
)
{
void
execute
(
ThreadPool
&
threads
,
int
threadIndex
)
{
owner
.
threadComputeForce
(
threads
,
threadIndex
);
owner
.
threadComputeForce
(
threads
,
threadIndex
);
}
}
CpuCustomManyParticleForce
&
owner
;
CpuCustomManyParticleForce
&
owner
;
};
};
CpuCustomManyParticleForce
::
CpuCustomManyParticleForce
(
const
CustomManyParticleForce
&
force
,
ThreadPool
&
threads
)
:
CpuCustomManyParticleForce
::
CpuCustomManyParticleForce
(
const
CustomManyParticleForce
&
force
,
ThreadPool
&
threads
)
:
threads
(
threads
),
useCutoff
(
false
),
usePeriodic
(
false
),
neighborList
(
NULL
)
{
threads
(
threads
),
useCutoff
(
false
),
usePeriodic
(
false
),
neighborList
(
NULL
)
{
numParticles
=
force
.
getNumParticles
();
numParticles
=
force
.
getNumParticles
();
numParticlesPerSet
=
force
.
getNumParticlesPerSet
();
numParticlesPerSet
=
force
.
getNumParticlesPerSet
();
numPerParticleParameters
=
force
.
getNumPerParticleParameters
();
numPerParticleParameters
=
force
.
getNumPerParticleParameters
();
centralParticleMode
=
(
force
.
getPermutationMode
()
==
CustomManyParticleForce
::
UniqueCentralParticle
);
centralParticleMode
=
(
force
.
getPermutationMode
()
==
CustomManyParticleForce
::
UniqueCentralParticle
);
// Create custom functions for the tabulated functions.
// Create custom functions for the tabulated functions.
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
for
(
int
i
=
0
;
i
<
(
int
)
force
.
getNumTabulatedFunctions
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
force
.
getNumTabulatedFunctions
();
i
++
)
functions
[
force
.
getTabulatedFunctionName
(
i
)]
=
createReferenceTabulatedFunction
(
force
.
getTabulatedFunction
(
i
));
functions
[
force
.
getTabulatedFunctionName
(
i
)]
=
createReferenceTabulatedFunction
(
force
.
getTabulatedFunction
(
i
));
// Parse the expression and create the objects used to calculate the interaction.
// Parse the expression and create the objects used to calculate the interaction.
map
<
string
,
vector
<
int
>
>
distances
;
map
<
string
,
vector
<
int
>
>
distances
;
map
<
string
,
vector
<
int
>
>
angles
;
map
<
string
,
vector
<
int
>
>
angles
;
map
<
string
,
vector
<
int
>
>
dihedrals
;
map
<
string
,
vector
<
int
>
>
dihedrals
;
Lepton
::
ParsedExpression
energyExpr
=
CustomManyParticleForceImpl
::
prepareExpression
(
force
,
functions
,
distances
,
angles
,
dihedrals
);
Lepton
::
ParsedExpression
energyExpr
=
CustomManyParticleForceImpl
::
prepareExpression
(
force
,
functions
,
distances
,
angles
,
dihedrals
);
for
(
int
i
=
0
;
i
<
threads
.
getNumThreads
();
i
++
)
for
(
int
i
=
0
;
i
<
threads
.
getNumThreads
();
i
++
)
threadData
.
push_back
(
new
ThreadData
(
force
,
energyExpr
,
distances
,
angles
,
dihedrals
));
threadData
.
push_back
(
new
ThreadData
(
force
,
energyExpr
,
distances
,
angles
,
dihedrals
));
if
(
force
.
getNonbondedMethod
()
!=
CustomManyParticleForce
::
NoCutoff
)
if
(
force
.
getNonbondedMethod
()
!=
CustomManyParticleForce
::
NoCutoff
)
setUseCutoff
(
force
.
getCutoffDistance
());
setUseCutoff
(
force
.
getCutoffDistance
());
// Delete the custom functions.
// Delete the custom functions.
for
(
map
<
string
,
Lepton
::
CustomFunction
*>::
iterator
iter
=
functions
.
begin
();
iter
!=
functions
.
end
();
iter
++
)
for
(
map
<
string
,
Lepton
::
CustomFunction
*>::
iterator
iter
=
functions
.
begin
();
iter
!=
functions
.
end
();
iter
++
)
delete
iter
->
second
;
delete
iter
->
second
;
// Record exclusions.
// Record exclusions.
exclusions
.
resize
(
force
.
getNumParticles
());
exclusions
.
resize
(
force
.
getNumParticles
());
for
(
int
i
=
0
;
i
<
(
int
)
force
.
getNumExclusions
();
i
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
force
.
getNumExclusions
();
i
++
)
{
int
p1
,
p2
;
int
p1
,
p2
;
force
.
getExclusionParticles
(
i
,
p1
,
p2
);
force
.
getExclusionParticles
(
i
,
p1
,
p2
);
exclusions
[
p1
].
insert
(
p2
);
exclusions
[
p1
].
insert
(
p2
);
exclusions
[
p2
].
insert
(
p1
);
exclusions
[
p2
].
insert
(
p1
);
}
}
// Record information about type filters.
// Record information about type filters.
CustomManyParticleForceImpl
::
buildFilterArrays
(
force
,
numTypes
,
particleTypes
,
orderIndex
,
particleOrder
);
CustomManyParticleForceImpl
::
buildFilterArrays
(
force
,
numTypes
,
particleTypes
,
orderIndex
,
particleOrder
);
}
}
CpuCustomManyParticleForce
::~
CpuCustomManyParticleForce
()
{
CpuCustomManyParticleForce
::~
CpuCustomManyParticleForce
()
{
if
(
neighborList
!=
NULL
)
if
(
neighborList
!=
NULL
)
delete
neighborList
;
delete
neighborList
;
for
(
int
i
=
0
;
i
<
(
int
)
threadData
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
threadData
.
size
();
i
++
)
delete
threadData
[
i
];
delete
threadData
[
i
];
}
}
void
CpuCustomManyParticleForce
::
calculateIxn
(
AlignedArray
<
float
>&
posq
,
RealOpenMM
**
particleParameters
,
void
CpuCustomManyParticleForce
::
calculateIxn
(
AlignedArray
<
float
>&
posq
,
RealOpenMM
**
particleParameters
,
const
map
<
string
,
double
>&
globalParameters
,
vector
<
AlignedArray
<
float
>
>&
threadForce
,
const
map
<
string
,
double
>&
globalParameters
,
vector
<
AlignedArray
<
float
>
>&
threadForce
,
bool
includeForces
,
bool
includeEnergy
,
double
&
energy
)
{
bool
includeForces
,
bool
includeEnergy
,
double
&
energy
)
{
// Record the parameters for the threads.
// Record the parameters for the threads.
this
->
posq
=
&
posq
[
0
];
this
->
posq
=
&
posq
[
0
];
this
->
particleParameters
=
particleParameters
;
this
->
particleParameters
=
particleParameters
;
this
->
globalParameters
=
&
globalParameters
;
this
->
globalParameters
=
&
globalParameters
;
this
->
threadForce
=
&
threadForce
;
this
->
threadForce
=
&
threadForce
;
this
->
includeForces
=
includeForces
;
this
->
includeForces
=
includeForces
;
this
->
includeEnergy
=
includeEnergy
;
this
->
includeEnergy
=
includeEnergy
;
gmx_atomic_t
counter
;
gmx_atomic_t
counter
;
gmx_atomic_set
(
&
counter
,
0
);
gmx_atomic_set
(
&
counter
,
0
);
this
->
atomicCounter
=
&
counter
;
this
->
atomicCounter
=
&
counter
;
if
(
useCutoff
)
{
if
(
useCutoff
)
{
// Construct a neighbor list. We use CpuNeighborList to do this, but then copy the result
// Construct a neighbor list. We use CpuNeighborList to do this, but then copy the result
// into a new data structure. This is needed because in UniqueCentralParticle mode, the
// into a new data structure. This is needed because in UniqueCentralParticle mode, the
// the neighbor list needs to include symmetric pairs.
// the neighbor list needs to include symmetric pairs.
particleNeighbors
.
resize
(
numParticles
);
particleNeighbors
.
resize
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
particleNeighbors
[
i
].
clear
();
particleNeighbors
[
i
].
clear
();
float
boxSizeFloat
[]
=
{(
float
)
periodicBoxSize
[
0
],
(
float
)
periodicBoxSize
[
1
],
(
float
)
periodicBoxSize
[
2
]};
float
boxSizeFloat
[]
=
{(
float
)
periodicBoxSize
[
0
],
(
float
)
periodicBoxSize
[
1
],
(
float
)
periodicBoxSize
[
2
]};
neighborList
->
computeNeighborList
(
numParticles
,
posq
,
exclusions
,
boxSizeFloat
,
usePeriodic
,
cutoffDistance
,
threads
);
neighborList
->
computeNeighborList
(
numParticles
,
posq
,
exclusions
,
boxSizeFloat
,
usePeriodic
,
cutoffDistance
,
threads
);
for
(
int
blockIndex
=
0
;
blockIndex
<
neighborList
->
getNumBlocks
();
blockIndex
++
)
{
for
(
int
blockIndex
=
0
;
blockIndex
<
neighborList
->
getNumBlocks
();
blockIndex
++
)
{
const
vector
<
int
>&
neighbors
=
neighborList
->
getBlockNeighbors
(
blockIndex
);
const
vector
<
int
>&
neighbors
=
neighborList
->
getBlockNeighbors
(
blockIndex
);
const
vector
<
char
>&
exclusions
=
neighborList
->
getBlockExclusions
(
blockIndex
);
const
vector
<
char
>&
exclusions
=
neighborList
->
getBlockExclusions
(
blockIndex
);
int
numNeighbors
=
neighbors
.
size
();
int
numNeighbors
=
neighbors
.
size
();
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
int
p1
=
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
+
i
];
int
p1
=
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
+
i
];
for
(
int
j
=
0
;
j
<
numNeighbors
;
j
++
)
{
for
(
int
j
=
0
;
j
<
numNeighbors
;
j
++
)
{
if
((
exclusions
[
j
]
&
(
1
<<
i
))
==
0
)
{
if
((
exclusions
[
j
]
&
(
1
<<
i
))
==
0
)
{
int
p2
=
neighbors
[
j
];
int
p2
=
neighbors
[
j
];
particleNeighbors
[
p1
].
push_back
(
p2
);
particleNeighbors
[
p1
].
push_back
(
p2
);
if
(
centralParticleMode
)
if
(
centralParticleMode
)
particleNeighbors
[
p2
].
push_back
(
p1
);
particleNeighbors
[
p2
].
push_back
(
p1
);
}
}
}
}
}
}
}
}
}
}
// Signal the threads to start running and wait for them to finish.
// Signal the threads to start running and wait for them to finish.
ComputeForceTask
task
(
*
this
);
ComputeForceTask
task
(
*
this
);
threads
.
execute
(
task
);
threads
.
execute
(
task
);
threads
.
waitForThreads
();
threads
.
waitForThreads
();
// Combine the energies from all the threads.
// Combine the energies from all the threads.
if
(
includeEnergy
)
{
if
(
includeEnergy
)
{
int
numThreads
=
threads
.
getNumThreads
();
int
numThreads
=
threads
.
getNumThreads
();
for
(
int
i
=
0
;
i
<
numThreads
;
i
++
)
for
(
int
i
=
0
;
i
<
numThreads
;
i
++
)
energy
+=
threadData
[
i
]
->
energy
;
energy
+=
threadData
[
i
]
->
energy
;
}
}
}
}
void
CpuCustomManyParticleForce
::
threadComputeForce
(
ThreadPool
&
threads
,
int
threadIndex
)
{
void
CpuCustomManyParticleForce
::
threadComputeForce
(
ThreadPool
&
threads
,
int
threadIndex
)
{
vector
<
int
>
particleIndices
(
numParticlesPerSet
);
vector
<
int
>
particleIndices
(
numParticlesPerSet
);
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
((
1
/
periodicBoxSize
[
0
]),
(
1
/
periodicBoxSize
[
1
]),
(
1
/
periodicBoxSize
[
2
]),
0
);
float
*
forces
=
&
(
*
threadForce
)[
threadIndex
][
0
];
float
*
forces
=
&
(
*
threadForce
)[
threadIndex
][
0
];
ThreadData
&
data
=
*
threadData
[
threadIndex
];
ThreadData
&
data
=
*
threadData
[
threadIndex
];
data
.
energy
=
0
;
data
.
energy
=
0
;
for
(
map
<
string
,
double
>::
const_iterator
iter
=
globalParameters
->
begin
();
iter
!=
globalParameters
->
end
();
++
iter
)
for
(
map
<
string
,
double
>::
const_iterator
iter
=
globalParameters
->
begin
();
iter
!=
globalParameters
->
end
();
++
iter
)
data
.
expressionSet
.
setVariable
(
data
.
expressionSet
.
getVariableIndex
(
iter
->
first
),
iter
->
second
);
data
.
expressionSet
.
setVariable
(
data
.
expressionSet
.
getVariableIndex
(
iter
->
first
),
iter
->
second
);
if
(
useCutoff
)
{
if
(
useCutoff
)
{
// Loop over interactions from the neighbor list.
// Loop over interactions from the neighbor list.
while
(
true
)
{
while
(
true
)
{
int
i
=
gmx_atomic_fetch_add
(
reinterpret_cast
<
gmx_atomic_t
*>
(
atomicCounter
),
1
);
int
i
=
gmx_atomic_fetch_add
(
reinterpret_cast
<
gmx_atomic_t
*>
(
atomicCounter
),
1
);
if
(
i
>=
numParticles
)
if
(
i
>=
numParticles
)
break
;
break
;
particleIndices
[
0
]
=
i
;
particleIndices
[
0
]
=
i
;
loopOverInteractions
(
particleNeighbors
[
i
],
particleIndices
,
1
,
0
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
loopOverInteractions
(
particleNeighbors
[
i
],
particleIndices
,
1
,
0
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
}
}
}
}
else
{
else
{
// Loop over all possible sets of particles.
// Loop over all possible sets of particles.
vector
<
int
>
particles
(
numParticles
);
vector
<
int
>
particles
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
particles
[
i
]
=
i
;
particles
[
i
]
=
i
;
while
(
true
)
{
while
(
true
)
{
int
i
=
gmx_atomic_fetch_add
(
reinterpret_cast
<
gmx_atomic_t
*>
(
atomicCounter
),
1
);
int
i
=
gmx_atomic_fetch_add
(
reinterpret_cast
<
gmx_atomic_t
*>
(
atomicCounter
),
1
);
if
(
i
>=
numParticles
)
if
(
i
>=
numParticles
)
break
;
break
;
particleIndices
[
0
]
=
i
;
particleIndices
[
0
]
=
i
;
int
startIndex
=
(
centralParticleMode
?
0
:
i
+
1
);
int
startIndex
=
(
centralParticleMode
?
0
:
i
+
1
);
loopOverInteractions
(
particles
,
particleIndices
,
1
,
startIndex
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
loopOverInteractions
(
particles
,
particleIndices
,
1
,
startIndex
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
}
}
}
}
}
}
void
CpuCustomManyParticleForce
::
setUseCutoff
(
RealOpenMM
distance
)
{
void
CpuCustomManyParticleForce
::
setUseCutoff
(
RealOpenMM
distance
)
{
useCutoff
=
true
;
useCutoff
=
true
;
cutoffDistance
=
distance
;
cutoffDistance
=
distance
;
if
(
neighborList
==
NULL
)
if
(
neighborList
==
NULL
)
neighborList
=
new
CpuNeighborList
(
4
);
neighborList
=
new
CpuNeighborList
(
4
);
}
}
void
CpuCustomManyParticleForce
::
setPeriodic
(
RealVec
&
boxSize
)
{
void
CpuCustomManyParticleForce
::
setPeriodic
(
RealVec
&
boxSize
)
{
assert
(
useCutoff
);
assert
(
useCutoff
);
assert
(
boxSize
[
0
]
>=
2.0
*
cutoffDistance
);
assert
(
boxSize
[
0
]
>=
2.0
*
cutoffDistance
);
assert
(
boxSize
[
1
]
>=
2.0
*
cutoffDistance
);
assert
(
boxSize
[
1
]
>=
2.0
*
cutoffDistance
);
assert
(
boxSize
[
2
]
>=
2.0
*
cutoffDistance
);
assert
(
boxSize
[
2
]
>=
2.0
*
cutoffDistance
);
usePeriodic
=
true
;
usePeriodic
=
true
;
periodicBoxSize
[
0
]
=
boxSize
[
0
];
periodicBoxSize
[
0
]
=
boxSize
[
0
];
periodicBoxSize
[
1
]
=
boxSize
[
1
];
periodicBoxSize
[
1
]
=
boxSize
[
1
];
periodicBoxSize
[
2
]
=
boxSize
[
2
];
periodicBoxSize
[
2
]
=
boxSize
[
2
];
}
}
void
CpuCustomManyParticleForce
::
loopOverInteractions
(
vector
<
int
>&
availableParticles
,
vector
<
int
>&
particleSet
,
int
loopIndex
,
int
startIndex
,
void
CpuCustomManyParticleForce
::
loopOverInteractions
(
vector
<
int
>&
availableParticles
,
vector
<
int
>&
particleSet
,
int
loopIndex
,
int
startIndex
,
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
int
numParticles
=
availableParticles
.
size
();
int
numParticles
=
availableParticles
.
size
();
double
cutoff2
=
cutoffDistance
*
cutoffDistance
;
double
cutoff2
=
cutoffDistance
*
cutoffDistance
;
int
checkRange
=
(
centralParticleMode
?
1
:
loopIndex
);
int
checkRange
=
(
centralParticleMode
?
1
:
loopIndex
);
for
(
int
i
=
startIndex
;
i
<
numParticles
;
i
++
)
{
for
(
int
i
=
startIndex
;
i
<
numParticles
;
i
++
)
{
int
particle
=
availableParticles
[
i
];
int
particle
=
availableParticles
[
i
];
// Check whether this particle can actually participate in interactions with the others found so far.
// Check whether this particle can actually participate in interactions with the others found so far.
bool
include
=
true
;
bool
include
=
true
;
if
(
useCutoff
)
{
if
(
useCutoff
)
{
fvec4
deltaR
;
fvec4
deltaR
;
fvec4
pos1
(
posq
+
4
*
particle
);
fvec4
pos1
(
posq
+
4
*
particle
);
float
r2
;
float
r2
;
for
(
int
j
=
0
;
j
<
checkRange
&&
include
;
j
++
)
{
for
(
int
j
=
0
;
j
<
checkRange
&&
include
;
j
++
)
{
fvec4
pos2
(
posq
+
4
*
particleSet
[
j
]);
fvec4
pos2
(
posq
+
4
*
particleSet
[
j
]);
computeDelta
(
pos1
,
pos2
,
deltaR
,
r2
,
boxSize
,
invBoxSize
);
computeDelta
(
pos1
,
pos2
,
deltaR
,
r2
,
boxSize
,
invBoxSize
);
include
&=
(
r2
<
cutoff2
);
include
&=
(
r2
<
cutoff2
);
}
}
}
}
for
(
int
j
=
0
;
j
<
loopIndex
&&
include
;
j
++
)
for
(
int
j
=
0
;
j
<
loopIndex
&&
include
;
j
++
)
include
&=
(
exclusions
[
particle
].
find
(
particleSet
[
j
])
==
exclusions
[
particle
].
end
());
include
&=
(
exclusions
[
particle
].
find
(
particleSet
[
j
])
==
exclusions
[
particle
].
end
());
if
(
include
)
{
if
(
include
)
{
if
(
loopIndex
>
0
&&
availableParticles
[
i
]
==
particleSet
[
0
])
if
(
loopIndex
>
0
&&
availableParticles
[
i
]
==
particleSet
[
0
])
continue
;
continue
;
particleSet
[
loopIndex
]
=
availableParticles
[
i
];
particleSet
[
loopIndex
]
=
availableParticles
[
i
];
if
(
loopIndex
==
numParticlesPerSet
-
1
)
if
(
loopIndex
==
numParticlesPerSet
-
1
)
calculateOneIxn
(
particleSet
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
calculateOneIxn
(
particleSet
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
else
else
loopOverInteractions
(
availableParticles
,
particleSet
,
loopIndex
+
1
,
i
+
1
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
loopOverInteractions
(
availableParticles
,
particleSet
,
loopIndex
+
1
,
i
+
1
,
particleParameters
,
forces
,
data
,
boxSize
,
invBoxSize
);
}
}
}
}
}
}
void
CpuCustomManyParticleForce
::
calculateOneIxn
(
vector
<
int
>&
particleSet
,
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
void
CpuCustomManyParticleForce
::
calculateOneIxn
(
vector
<
int
>&
particleSet
,
RealOpenMM
**
particleParameters
,
float
*
forces
,
ThreadData
&
data
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
// Select the ordering to use for the particles.
// Select the ordering to use for the particles.
vector
<
int
>&
permutedParticles
=
data
.
permutedParticles
;
vector
<
int
>&
permutedParticles
=
data
.
permutedParticles
;
if
(
particleOrder
.
size
()
==
1
)
{
if
(
particleOrder
.
size
()
==
1
)
{
// There are no filters, so we don't need to worry about ordering.
// There are no filters, so we don't need to worry about ordering.
permutedParticles
=
particleSet
;
permutedParticles
=
particleSet
;
}
}
else
{
else
{
int
index
=
0
;
int
index
=
0
;
for
(
int
i
=
numParticlesPerSet
-
1
;
i
>=
0
;
i
--
)
for
(
int
i
=
numParticlesPerSet
-
1
;
i
>=
0
;
i
--
)
index
=
particleTypes
[
particleSet
[
i
]]
+
numTypes
*
index
;
index
=
particleTypes
[
particleSet
[
i
]]
+
numTypes
*
index
;
int
order
=
orderIndex
[
index
];
int
order
=
orderIndex
[
index
];
if
(
order
==
-
1
)
if
(
order
==
-
1
)
return
;
return
;
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
permutedParticles
[
i
]
=
particleSet
[
particleOrder
[
order
][
i
]];
permutedParticles
[
i
]
=
particleSet
[
particleOrder
[
order
][
i
]];
}
}
// Record per-particle parameters.
// Record per-particle parameters.
CompiledExpressionSet
&
expressionSet
=
data
.
expressionSet
;
CompiledExpressionSet
&
expressionSet
=
data
.
expressionSet
;
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
expressionSet
.
setVariable
(
data
.
particleParamIndices
[
i
][
j
],
particleParameters
[
permutedParticles
[
i
]][
j
]);
expressionSet
.
setVariable
(
data
.
particleParamIndices
[
i
][
j
],
particleParameters
[
permutedParticles
[
i
]][
j
]);
// Compute inter-particle deltas.
// Compute inter-particle deltas.
int
numDeltas
=
data
.
deltaPairs
.
size
();
int
numDeltas
=
data
.
deltaPairs
.
size
();
AlignedArray
<
fvec4
>&
delta
=
data
.
delta
;
AlignedArray
<
fvec4
>&
delta
=
data
.
delta
;
vector
<
float
>&
normDelta
=
data
.
normDelta
;
AlignedArray
<
fvec4
>&
cross1
=
data
.
cross1
;
vector
<
float
>&
norm2Delta
=
data
.
norm2Delta
;
AlignedArray
<
fvec4
>&
cross2
=
data
.
cross2
;
for
(
int
i
=
0
;
i
<
numDeltas
;
i
++
)
{
vector
<
float
>&
normDelta
=
data
.
normDelta
;
int
p1
=
permutedParticles
[
data
.
deltaPairs
[
i
].
first
];
vector
<
float
>&
norm2Delta
=
data
.
norm2Delta
;
int
p2
=
permutedParticles
[
data
.
deltaPairs
[
i
].
second
];
for
(
int
i
=
0
;
i
<
numDeltas
;
i
++
)
{
computeDelta
(
fvec4
(
posq
+
4
*
p1
),
fvec4
(
posq
+
4
*
p2
),
delta
[
i
],
norm2Delta
[
i
],
boxSize
,
invBoxSize
);
int
p1
=
permutedParticles
[
data
.
deltaPairs
[
i
].
first
];
normDelta
[
i
]
=
sqrtf
(
norm2Delta
[
i
]);
int
p2
=
permutedParticles
[
data
.
deltaPairs
[
i
].
second
];
}
computeDelta
(
fvec4
(
posq
+
4
*
p1
),
fvec4
(
posq
+
4
*
p2
),
delta
[
i
],
norm2Delta
[
i
],
boxSize
,
invBoxSize
);
normDelta
[
i
]
=
sqrtf
(
norm2Delta
[
i
]);
// Compute all of the variables the energy can depend on.
}
for
(
int
i
=
0
;
i
<
(
int
)
data
.
particleTerms
.
size
();
i
++
)
{
// Compute all of the variables the energy can depend on.
const
ParticleTermInfo
&
term
=
data
.
particleTerms
[
i
];
expressionSet
.
setVariable
(
term
.
variableIndex
,
posq
[
4
*
permutedParticles
[
term
.
atom
]
+
term
.
component
]);
for
(
int
i
=
0
;
i
<
(
int
)
data
.
particleTerms
.
size
();
i
++
)
{
}
const
ParticleTermInfo
&
term
=
data
.
particleTerms
[
i
];
for
(
int
i
=
0
;
i
<
(
int
)
data
.
distanceTerms
.
size
();
i
++
)
{
expressionSet
.
setVariable
(
term
.
variableIndex
,
posq
[
4
*
permutedParticles
[
term
.
atom
]
+
term
.
component
]);
const
DistanceTermInfo
&
term
=
data
.
distanceTerms
[
i
];
}
expressionSet
.
setVariable
(
term
.
variableIndex
,
normDelta
[
term
.
delta
]);
for
(
int
i
=
0
;
i
<
(
int
)
data
.
distanceTerms
.
size
();
i
++
)
{
}
const
DistanceTermInfo
&
term
=
data
.
distanceTerms
[
i
];
for
(
int
i
=
0
;
i
<
(
int
)
data
.
angleTerms
.
size
();
i
++
)
{
expressionSet
.
setVariable
(
term
.
variableIndex
,
normDelta
[
term
.
delta
]);
const
AngleTermInfo
&
term
=
data
.
angleTerms
[
i
];
}
expressionSet
.
setVariable
(
term
.
variableIndex
,
computeAngle
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
],
norm2Delta
[
term
.
delta1
],
norm2Delta
[
term
.
delta2
],
term
.
delta1Sign
*
term
.
delta2Sign
));
for
(
int
i
=
0
;
i
<
(
int
)
data
.
angleTerms
.
size
();
i
++
)
{
}
const
AngleTermInfo
&
term
=
data
.
angleTerms
[
i
];
for
(
int
i
=
0
;
i
<
(
int
)
data
.
dihedralTerms
.
size
();
i
++
)
{
expressionSet
.
setVariable
(
term
.
variableIndex
,
computeAngle
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
],
norm2Delta
[
term
.
delta1
],
norm2Delta
[
term
.
delta2
],
term
.
delta1Sign
*
term
.
delta2Sign
));
const
DihedralTermInfo
&
term
=
data
.
dihedralTerms
[
i
];
}
expressionSet
.
setVariable
(
term
.
variableIndex
,
getDihedralAngleBetweenThreeVectors
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
],
delta
[
term
.
delta3
],
term
.
cross1
,
term
.
cross2
,
delta
[
term
.
delta1
]));
for
(
int
i
=
0
;
i
<
(
int
)
data
.
dihedralTerms
.
size
();
i
++
)
{
}
const
DihedralTermInfo
&
term
=
data
.
dihedralTerms
[
i
];
expressionSet
.
setVariable
(
term
.
variableIndex
,
getDihedralAngleBetweenThreeVectors
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
],
delta
[
term
.
delta3
],
cross1
[
i
],
cross2
[
i
],
delta
[
term
.
delta1
]));
if
(
includeForces
)
{
}
// Apply forces based on individual particle coordinates.
if
(
includeForces
)
{
AlignedArray
<
fvec4
>&
f
=
data
.
f
;
// Apply forces based on individual particle coordinates.
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
f
[
i
]
=
fvec4
(
0.0
f
);
AlignedArray
<
fvec4
>&
f
=
data
.
f
;
for
(
int
i
=
0
;
i
<
(
int
)
data
.
particleTerms
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
const
ParticleTermInfo
&
term
=
data
.
particleTerms
[
i
];
f
[
i
]
=
fvec4
(
0.0
f
);
float
temp
[
4
];
for
(
int
i
=
0
;
i
<
(
int
)
data
.
particleTerms
.
size
();
i
++
)
{
f
[
term
.
atom
].
store
(
temp
);
const
ParticleTermInfo
&
term
=
data
.
particleTerms
[
i
];
temp
[
term
.
component
]
-=
term
.
forceExpression
.
evaluate
();
float
temp
[
4
];
f
[
term
.
atom
]
=
fvec4
(
temp
);
f
[
term
.
atom
].
store
(
temp
);
}
temp
[
term
.
component
]
-=
term
.
forceExpression
.
evaluate
();
f
[
term
.
atom
]
=
fvec4
(
temp
);
// Apply forces based on distances.
}
for
(
int
i
=
0
;
i
<
(
int
)
data
.
distanceTerms
.
size
();
i
++
)
{
// Apply forces based on distances.
const
DistanceTermInfo
&
term
=
data
.
distanceTerms
[
i
];
float
dEdR
=
(
float
)
(
term
.
forceExpression
.
evaluate
()
*
term
.
deltaSign
/
(
normDelta
[
term
.
delta
]));
for
(
int
i
=
0
;
i
<
(
int
)
data
.
distanceTerms
.
size
();
i
++
)
{
fvec4
force
=
-
dEdR
*
delta
[
term
.
delta
];
const
DistanceTermInfo
&
term
=
data
.
distanceTerms
[
i
];
f
[
term
.
p1
]
-=
force
;
float
dEdR
=
(
float
)
(
term
.
forceExpression
.
evaluate
()
*
term
.
deltaSign
/
(
normDelta
[
term
.
delta
]));
f
[
term
.
p2
]
+=
force
;
fvec4
force
=
-
dEdR
*
delta
[
term
.
delta
];
}
f
[
term
.
p1
]
-=
force
;
f
[
term
.
p2
]
+=
force
;
// Apply forces based on angles.
}
for
(
int
i
=
0
;
i
<
(
int
)
data
.
angleTerms
.
size
();
i
++
)
{
// Apply forces based on angles.
const
AngleTermInfo
&
term
=
data
.
angleTerms
[
i
];
float
dEdTheta
=
(
float
)
term
.
forceExpression
.
evaluate
();
for
(
int
i
=
0
;
i
<
(
int
)
data
.
angleTerms
.
size
();
i
++
)
{
fvec4
thetaCross
=
cross
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
]);
const
AngleTermInfo
&
term
=
data
.
angleTerms
[
i
];
float
lengthThetaCross
=
sqrtf
(
dot3
(
thetaCross
,
thetaCross
));
float
dEdTheta
=
(
float
)
term
.
forceExpression
.
evaluate
();
if
(
lengthThetaCross
<
1.0e-6
f
)
fvec4
thetaCross
=
cross
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
]);
lengthThetaCross
=
1.0e-6
f
;
float
lengthThetaCross
=
sqrtf
(
dot3
(
thetaCross
,
thetaCross
));
float
termA
=
dEdTheta
*
term
.
delta2Sign
/
(
norm2Delta
[
term
.
delta1
]
*
lengthThetaCross
);
if
(
lengthThetaCross
<
1.0e-6
f
)
float
termC
=
-
dEdTheta
*
term
.
delta1Sign
/
(
norm2Delta
[
term
.
delta2
]
*
lengthThetaCross
);
lengthThetaCross
=
1.0e-6
f
;
fvec4
deltaCross1
=
cross
(
delta
[
term
.
delta1
],
thetaCross
);
float
termA
=
dEdTheta
*
term
.
delta2Sign
/
(
norm2Delta
[
term
.
delta1
]
*
lengthThetaCross
);
fvec4
deltaCross2
=
cross
(
delta
[
term
.
delta2
],
thetaCross
);
float
termC
=
-
dEdTheta
*
term
.
delta1Sign
/
(
norm2Delta
[
term
.
delta2
]
*
lengthThetaCross
);
fvec4
force1
=
termA
*
deltaCross1
;
fvec4
deltaCross1
=
cross
(
delta
[
term
.
delta1
],
thetaCross
);
fvec4
force3
=
termC
*
deltaCross2
;
fvec4
deltaCross2
=
cross
(
delta
[
term
.
delta2
],
thetaCross
);
fvec4
force2
=
-
(
force1
+
force3
);
fvec4
force1
=
termA
*
deltaCross1
;
f
[
term
.
p1
]
+=
force1
;
fvec4
force3
=
termC
*
deltaCross2
;
f
[
term
.
p2
]
+=
force2
;
fvec4
force2
=
-
(
force1
+
force3
);
f
[
term
.
p3
]
+=
force3
;
f
[
term
.
p1
]
+=
force1
;
}
f
[
term
.
p2
]
+=
force2
;
f
[
term
.
p3
]
+=
force3
;
// Apply forces based on dihedrals.
}
for
(
int
i
=
0
;
i
<
(
int
)
data
.
dihedralTerms
.
size
();
i
++
)
{
// Apply forces based on dihedrals.
const
DihedralTermInfo
&
term
=
data
.
dihedralTerms
[
i
];
float
dEdTheta
=
(
float
)
term
.
forceExpression
.
evaluate
();
for
(
int
i
=
0
;
i
<
(
int
)
data
.
dihedralTerms
.
size
();
i
++
)
{
float
normCross1
=
dot3
(
term
.
cross1
,
term
.
cross1
);
const
DihedralTermInfo
&
term
=
data
.
dihedralTerms
[
i
];
float
normBC
=
normDelta
[
term
.
delta2
];
float
dEdTheta
=
(
float
)
term
.
forceExpression
.
evaluate
();
float
forceFactors
[
4
];
float
normCross1
=
dot3
(
cross1
[
i
],
cross1
[
i
]);
forceFactors
[
0
]
=
(
-
dEdTheta
*
normBC
)
/
normCross1
;
float
normBC
=
normDelta
[
term
.
delta2
];
float
normCross2
=
dot3
(
term
.
cross2
,
term
.
cross2
);
float
forceFactors
[
4
];
forceFactors
[
3
]
=
(
dEdTheta
*
normBC
)
/
normCross2
;
forceFactors
[
0
]
=
(
-
dEdTheta
*
normBC
)
/
normCross1
;
forceFactors
[
1
]
=
dot3
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
]);
float
normCross2
=
dot3
(
cross2
[
i
],
cross2
[
i
]);
forceFactors
[
1
]
/=
norm2Delta
[
term
.
delta2
];
forceFactors
[
3
]
=
(
dEdTheta
*
normBC
)
/
normCross2
;
forceFactors
[
2
]
=
dot3
(
delta
[
term
.
delta3
],
delta
[
term
.
delta2
]);
forceFactors
[
1
]
=
dot3
(
delta
[
term
.
delta1
],
delta
[
term
.
delta2
]);
forceFactors
[
2
]
/=
norm2Delta
[
term
.
delta2
];
forceFactors
[
1
]
/=
norm2Delta
[
term
.
delta2
];
fvec4
force1
=
forceFactors
[
0
]
*
term
.
cross1
;
forceFactors
[
2
]
=
dot3
(
delta
[
term
.
delta3
],
delta
[
term
.
delta2
]);
fvec4
force4
=
forceFactors
[
3
]
*
term
.
cross2
;
forceFactors
[
2
]
/=
norm2Delta
[
term
.
delta2
];
fvec4
s
=
forceFactors
[
1
]
*
force1
-
forceFactors
[
2
]
*
force4
;
fvec4
force1
=
forceFactors
[
0
]
*
cross1
[
i
];
f
[
term
.
p1
]
+=
force1
;
fvec4
force4
=
forceFactors
[
3
]
*
cross2
[
i
];
f
[
term
.
p2
]
-=
force1
-
s
;
fvec4
s
=
forceFactors
[
1
]
*
force1
-
forceFactors
[
2
]
*
force4
;
f
[
term
.
p3
]
-=
force4
+
s
;
f
[
term
.
p1
]
+=
force1
;
f
[
term
.
p4
]
+=
force4
;
f
[
term
.
p2
]
-=
force1
-
s
;
}
f
[
term
.
p3
]
-=
force4
+
s
;
f
[
term
.
p4
]
+=
force4
;
// Store the forces.
}
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
{
// Store the forces.
int
index
=
permutedParticles
[
i
];
(
fvec4
(
forces
+
4
*
index
)
+
f
[
i
]).
store
(
forces
+
4
*
index
);
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
{
}
int
index
=
permutedParticles
[
i
];
}
(
fvec4
(
forces
+
4
*
index
)
+
f
[
i
]).
store
(
forces
+
4
*
index
);
}
// Add the energy
}
if
(
includeEnergy
)
// Add the energy
data
.
energy
+=
data
.
energyExpression
.
evaluate
();
}
if
(
includeEnergy
)
data
.
energy
+=
data
.
energyExpression
.
evaluate
();
void
CpuCustomManyParticleForce
::
computeDelta
(
const
fvec4
&
posI
,
const
fvec4
&
posJ
,
fvec4
&
deltaR
,
float
&
r2
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
{
}
deltaR
=
posJ
-
posI
;
if
(
usePeriodic
)
{
void
CpuCustomManyParticleForce
::
computeDelta
(
const
fvec4
&
posI
,
const
fvec4
&
posJ
,
fvec4
&
deltaR
,
float
&
r2
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
{
fvec4
base
=
round
(
deltaR
*
invBoxSize
)
*
boxSize
;
deltaR
=
posJ
-
posI
;
deltaR
=
deltaR
-
base
;
if
(
usePeriodic
)
{
}
fvec4
base
=
round
(
deltaR
*
invBoxSize
)
*
boxSize
;
r2
=
dot3
(
deltaR
,
deltaR
);
deltaR
=
deltaR
-
base
;
}
}
r2
=
dot3
(
deltaR
,
deltaR
);
float
CpuCustomManyParticleForce
::
computeAngle
(
const
fvec4
&
vi
,
const
fvec4
&
vj
,
float
v2i
,
float
v2j
,
float
sign
)
{
}
float
dot
=
dot3
(
vi
,
vj
)
*
sign
;
float
cosine
=
dot
/
sqrtf
(
v2i
*
v2j
);
float
CpuCustomManyParticleForce
::
computeAngle
(
const
fvec4
&
vi
,
const
fvec4
&
vj
,
float
v2i
,
float
v2j
,
float
sign
)
{
if
(
cosine
>
0.99
f
||
cosine
<
-
0.99
f
)
{
float
dot
=
dot3
(
vi
,
vj
)
*
sign
;
// We're close to the singularity in acos(), so take the cross product and use asin() instead.
float
cosine
=
dot
/
sqrtf
(
v2i
*
v2j
);
if
(
cosine
>
0.99
f
||
cosine
<
-
0.99
f
)
{
fvec4
cross12
=
cross
(
vi
,
vj
);
// We're close to the singularity in acos(), so take the cross product and use asin() instead.
float
scale
=
v2i
*
v2j
;
float
angle
=
asinf
(
sqrtf
(
dot3
(
cross12
,
cross12
)
/
scale
));
fvec4
cross12
=
cross
(
vi
,
vj
);
if
(
cosine
<
0.0
f
)
float
scale
=
v2i
*
v2j
;
angle
=
(
float
)
(
M_PI
-
angle
);
float
angle
=
asinf
(
sqrtf
(
dot3
(
cross12
,
cross12
)
/
scale
));
return
angle
;
if
(
cosine
<
0.0
f
)
}
angle
=
(
float
)
(
M_PI
-
angle
);
return
acosf
(
cosine
);
return
angle
;
}
}
return
acosf
(
cosine
);
float
CpuCustomManyParticleForce
::
getDihedralAngleBetweenThreeVectors
(
const
fvec4
&
v1
,
const
fvec4
&
v2
,
const
fvec4
&
v3
,
fvec4
&
cross1
,
fvec4
&
cross2
,
const
fvec4
&
signVector
)
{
}
cross1
=
cross
(
v1
,
v2
);
cross2
=
cross
(
v2
,
v3
);
float
CpuCustomManyParticleForce
::
getDihedralAngleBetweenThreeVectors
(
const
fvec4
&
v1
,
const
fvec4
&
v2
,
const
fvec4
&
v3
,
fvec4
&
cross1
,
fvec4
&
cross2
,
const
fvec4
&
signVector
)
{
float
angle
=
computeAngle
(
cross1
,
cross2
,
dot3
(
cross1
,
cross1
),
dot3
(
cross2
,
cross2
),
1.0
f
);
cross1
=
cross
(
v1
,
v2
);
float
dotProduct
=
dot3
(
signVector
,
cross2
);
cross2
=
cross
(
v2
,
v3
);
if
(
dotProduct
<
0
)
float
angle
=
computeAngle
(
cross1
,
cross2
,
dot3
(
cross1
,
cross1
),
dot3
(
cross2
,
cross2
),
1.0
f
);
angle
=
-
angle
;
float
dotProduct
=
dot3
(
signVector
,
cross2
);
return
angle
;
if
(
dotProduct
<
0
)
}
angle
=
-
angle
;
return
angle
;
CpuCustomManyParticleForce
::
ParticleTermInfo
::
ParticleTermInfo
(
const
string
&
name
,
int
atom
,
int
component
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
}
name
(
name
),
atom
(
atom
),
component
(
component
),
forceExpression
(
forceExpression
)
{
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
CpuCustomManyParticleForce
::
ParticleTermInfo
::
ParticleTermInfo
(
const
string
&
name
,
int
atom
,
int
component
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
}
name
(
name
),
atom
(
atom
),
component
(
component
),
forceExpression
(
forceExpression
)
{
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
CpuCustomManyParticleForce
::
DistanceTermInfo
::
DistanceTermInfo
(
const
string
&
name
,
const
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
}
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
forceExpression
(
forceExpression
)
{
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
CpuCustomManyParticleForce
::
DistanceTermInfo
::
DistanceTermInfo
(
const
string
&
name
,
const
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
data
.
requestDeltaPair
(
p1
,
p2
,
delta
,
deltaSign
,
true
);
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
forceExpression
(
forceExpression
)
{
}
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
data
.
requestDeltaPair
(
p1
,
p2
,
delta
,
deltaSign
,
true
);
CpuCustomManyParticleForce
::
AngleTermInfo
::
AngleTermInfo
(
const
string
&
name
,
const
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
}
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
p3
(
atoms
[
2
]),
forceExpression
(
forceExpression
)
{
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
CpuCustomManyParticleForce
::
AngleTermInfo
::
AngleTermInfo
(
const
string
&
name
,
const
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
data
.
requestDeltaPair
(
p1
,
p2
,
delta1
,
delta1Sign
,
true
);
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
p3
(
atoms
[
2
]),
forceExpression
(
forceExpression
)
{
data
.
requestDeltaPair
(
p3
,
p2
,
delta2
,
delta2Sign
,
true
);
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
}
data
.
requestDeltaPair
(
p1
,
p2
,
delta1
,
delta1Sign
,
true
);
data
.
requestDeltaPair
(
p3
,
p2
,
delta2
,
delta2Sign
,
true
);
CpuCustomManyParticleForce
::
DihedralTermInfo
::
DihedralTermInfo
(
const
string
&
name
,
const
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
}
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
p3
(
atoms
[
2
]),
p4
(
atoms
[
3
]),
forceExpression
(
forceExpression
)
{
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
CpuCustomManyParticleForce
::
DihedralTermInfo
::
DihedralTermInfo
(
const
string
&
name
,
const
vector
<
int
>&
atoms
,
const
Lepton
::
CompiledExpression
&
forceExpression
,
ThreadData
&
data
)
:
float
sign
;
name
(
name
),
p1
(
atoms
[
0
]),
p2
(
atoms
[
1
]),
p3
(
atoms
[
2
]),
p4
(
atoms
[
3
]),
forceExpression
(
forceExpression
)
{
data
.
requestDeltaPair
(
p2
,
p1
,
delta1
,
sign
,
false
);
variableIndex
=
data
.
expressionSet
.
getVariableIndex
(
name
);
data
.
requestDeltaPair
(
p2
,
p3
,
delta2
,
sign
,
false
);
float
sign
;
data
.
requestDeltaPair
(
p4
,
p3
,
delta3
,
sign
,
false
);
data
.
requestDeltaPair
(
p2
,
p1
,
delta1
,
sign
,
false
);
}
data
.
requestDeltaPair
(
p2
,
p3
,
delta2
,
sign
,
false
);
data
.
requestDeltaPair
(
p4
,
p3
,
delta3
,
sign
,
false
);
CpuCustomManyParticleForce
::
ThreadData
::
ThreadData
(
const
CustomManyParticleForce
&
force
,
Lepton
::
ParsedExpression
&
energyExpr
,
}
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
)
{
int
numParticlesPerSet
=
force
.
getNumParticlesPerSet
();
CpuCustomManyParticleForce
::
ThreadData
::
ThreadData
(
const
CustomManyParticleForce
&
force
,
Lepton
::
ParsedExpression
&
energyExpr
,
int
numPerParticleParameters
=
force
.
getNumPerParticleParameters
();
map
<
string
,
vector
<
int
>
>&
distances
,
map
<
string
,
vector
<
int
>
>&
angles
,
map
<
string
,
vector
<
int
>
>&
dihedrals
)
{
particleParamIndices
.
resize
(
numParticlesPerSet
);
int
numParticlesPerSet
=
force
.
getNumParticlesPerSet
();
permutedParticles
.
resize
(
numParticlesPerSet
);
int
numPerParticleParameters
=
force
.
getNumPerParticleParameters
();
f
.
resize
(
numParticlesPerSet
);
particleParamIndices
.
resize
(
numParticlesPerSet
);
energyExpression
=
energyExpr
.
createCompiledExpression
();
permutedParticles
.
resize
(
numParticlesPerSet
);
expressionSet
.
registerExpression
(
energyExpression
);
f
.
resize
(
numParticlesPerSet
);
energyExpression
=
energyExpr
.
createCompiledExpression
();
// Differentiate the energy to get expressions for the force.
expressionSet
.
registerExpression
(
energyExpression
);
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
{
// Differentiate the energy to get expressions for the force.
stringstream
xname
,
yname
,
zname
;
xname
<<
'x'
<<
(
i
+
1
);
for
(
int
i
=
0
;
i
<
numParticlesPerSet
;
i
++
)
{
yname
<<
'y'
<<
(
i
+
1
);
stringstream
xname
,
yname
,
zname
;
zname
<<
'z'
<<
(
i
+
1
);
xname
<<
'x'
<<
(
i
+
1
);
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
xname
.
str
(),
i
,
0
,
energyExpr
.
differentiate
(
xname
.
str
()).
optimize
().
createCompiledExpression
(),
*
this
));
yname
<<
'y'
<<
(
i
+
1
);
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
yname
.
str
(),
i
,
1
,
energyExpr
.
differentiate
(
yname
.
str
()).
optimize
().
createCompiledExpression
(),
*
this
));
zname
<<
'z'
<<
(
i
+
1
);
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
zname
.
str
(),
i
,
2
,
energyExpr
.
differentiate
(
zname
.
str
()).
optimize
().
createCompiledExpression
(),
*
this
));
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
xname
.
str
(),
i
,
0
,
energyExpr
.
differentiate
(
xname
.
str
()).
optimize
().
createCompiledExpression
(),
*
this
));
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
{
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
yname
.
str
(),
i
,
1
,
energyExpr
.
differentiate
(
yname
.
str
()).
optimize
().
createCompiledExpression
(),
*
this
));
stringstream
paramname
;
particleTerms
.
push_back
(
CpuCustomManyParticleForce
::
ParticleTermInfo
(
zname
.
str
(),
i
,
2
,
energyExpr
.
differentiate
(
zname
.
str
()).
optimize
().
createCompiledExpression
(),
*
this
));
paramname
<<
force
.
getPerParticleParameterName
(
j
)
<<
(
i
+
1
);
for
(
int
j
=
0
;
j
<
numPerParticleParameters
;
j
++
)
{
particleParamIndices
[
i
].
push_back
(
expressionSet
.
getVariableIndex
(
paramname
.
str
()));
stringstream
paramname
;
}
paramname
<<
force
.
getPerParticleParameterName
(
j
)
<<
(
i
+
1
);
}
particleParamIndices
[
i
].
push_back
(
expressionSet
.
getVariableIndex
(
paramname
.
str
()));
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
dihedrals
.
begin
();
iter
!=
dihedrals
.
end
();
++
iter
)
}
dihedralTerms
.
push_back
(
CpuCustomManyParticleForce
::
DihedralTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
*
this
));
}
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
distances
.
begin
();
iter
!=
distances
.
end
();
++
iter
)
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
dihedrals
.
begin
();
iter
!=
dihedrals
.
end
();
++
iter
)
distanceTerms
.
push_back
(
CpuCustomManyParticleForce
::
DistanceTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
*
this
));
dihedralTerms
.
push_back
(
CpuCustomManyParticleForce
::
DihedralTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
*
this
));
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
angles
.
begin
();
iter
!=
angles
.
end
();
++
iter
)
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
distances
.
begin
();
iter
!=
distances
.
end
();
++
iter
)
angleTerms
.
push_back
(
CpuCustomManyParticleForce
::
AngleTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
*
this
));
distanceTerms
.
push_back
(
CpuCustomManyParticleForce
::
DistanceTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
*
this
));
for
(
int
i
=
0
;
i
<
particleTerms
.
size
();
i
++
)
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
angles
.
begin
();
iter
!=
angles
.
end
();
++
iter
)
expressionSet
.
registerExpression
(
particleTerms
[
i
].
forceExpression
);
angleTerms
.
push_back
(
CpuCustomManyParticleForce
::
AngleTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpr
.
differentiate
(
iter
->
first
).
optimize
().
createCompiledExpression
(),
*
this
));
for
(
int
i
=
0
;
i
<
distanceTerms
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
particleTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
distanceTerms
[
i
].
forceExpression
);
expressionSet
.
registerExpression
(
particleTerms
[
i
].
forceExpression
);
for
(
int
i
=
0
;
i
<
angleTerms
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
distanceTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
angleTerms
[
i
].
forceExpression
);
expressionSet
.
registerExpression
(
distanceTerms
[
i
].
forceExpression
);
for
(
int
i
=
0
;
i
<
dihedralTerms
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
angleTerms
.
size
();
i
++
)
expressionSet
.
registerExpression
(
dihedralTerms
[
i
].
forceExpression
);
expressionSet
.
registerExpression
(
angleTerms
[
i
].
forceExpression
);
int
numDeltas
=
deltaPairs
.
size
();
for
(
int
i
=
0
;
i
<
dihedralTerms
.
size
();
i
++
)
delta
.
resize
(
numDeltas
);
expressionSet
.
registerExpression
(
dihedralTerms
[
i
].
forceExpression
);
normDelta
.
resize
(
numDeltas
);
int
numDeltas
=
deltaPairs
.
size
();
norm2Delta
.
resize
(
numDeltas
);
delta
.
resize
(
numDeltas
);
}
normDelta
.
resize
(
numDeltas
);
norm2Delta
.
resize
(
numDeltas
);
void
CpuCustomManyParticleForce
::
ThreadData
::
requestDeltaPair
(
int
p1
,
int
p2
,
int
&
pairIndex
,
float
&
pairSign
,
bool
allowReversed
)
{
cross1
.
resize
(
numDeltas
);
for
(
int
i
=
0
;
i
<
(
int
)
deltaPairs
.
size
();
i
++
)
{
cross2
.
resize
(
numDeltas
);
if
(
deltaPairs
[
i
].
first
==
p1
&&
deltaPairs
[
i
].
second
==
p2
)
{
pairIndex
=
i
;
}
pairSign
=
1
;
return
;
void
CpuCustomManyParticleForce
::
ThreadData
::
requestDeltaPair
(
int
p1
,
int
p2
,
int
&
pairIndex
,
float
&
pairSign
,
bool
allowReversed
)
{
}
for
(
int
i
=
0
;
i
<
(
int
)
deltaPairs
.
size
();
i
++
)
{
if
(
deltaPairs
[
i
].
first
==
p2
&&
deltaPairs
[
i
].
second
==
p1
&&
allowReversed
)
{
if
(
deltaPairs
[
i
].
first
==
p1
&&
deltaPairs
[
i
].
second
==
p2
)
{
pairIndex
=
i
;
pairIndex
=
i
;
pairSign
=
-
1
;
pairSign
=
1
;
return
;
return
;
}
}
}
if
(
deltaPairs
[
i
].
first
==
p2
&&
deltaPairs
[
i
].
second
==
p1
&&
allowReversed
)
{
pairIndex
=
deltaPairs
.
size
();
pairIndex
=
i
;
pairSign
=
1
;
pairSign
=
-
1
;
deltaPairs
.
push_back
(
make_pair
(
p1
,
p2
));
return
;
}
}
}
pairIndex
=
deltaPairs
.
size
();
pairSign
=
1
;
deltaPairs
.
push_back
(
make_pair
(
p1
,
p2
));
}
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