CpuCustomManyParticleForce.h 9.06 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

/* Portions copyright (c) 2009-2014 Stanford University and Simbios.
 * Contributors: Peter Eastman
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject
 * to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef OPENMM_CPU_CUSTOM_MANY_PARTICLE_FORCE_H__
#define OPENMM_CPU_CUSTOM_MANY_PARTICLE_FORCE_H__

#include "ReferenceForce.h"
#include "ReferenceBondIxn.h"
#include "CompiledExpressionSet.h"
31
#include "CpuNeighborList.h"
32
#include "openmm/CustomManyParticleForce.h"
33
#include "openmm/internal/ThreadPool.h"
34
35
36
37
38
#include "openmm/internal/vectorize.h"
#include "lepton/CompiledExpression.h"
#include "lepton/ParsedExpression.h"
#include <map>
#include <set>
39
#include <utility>
40
41
42
43
44
45
46
47
48
49
50
#include <vector>

namespace OpenMM {

class CpuCustomManyParticleForce {
private:

    class ParticleTermInfo;
    class DistanceTermInfo;
    class AngleTermInfo;
    class DihedralTermInfo;
51
52
    class ComputeForceTask;
    class ThreadData;
53
    int numParticles, numParticlesPerSet, numPerParticleParameters, numTypes;
54
55
56
    bool useCutoff, usePeriodic;
    RealOpenMM cutoffDistance;
    RealOpenMM periodicBoxSize[3];
57
58
    CpuNeighborList* neighborList;
    ThreadPool& threads;
59
60
61
62
    std::vector<std::set<int> > exclusions;
    std::vector<int> particleTypes;
    std::vector<int> orderIndex;
    std::vector<std::vector<int> > particleOrder;
63
64
65
66
67
68
69
70
71
72
73
74
75
    std::vector<ThreadData*> threadData;
    // The following variables are used to make information accessible to the individual threads.
    float* posq;
    RealOpenMM** particleParameters;        
    const std::map<std::string, double>* globalParameters;
    std::vector<AlignedArray<float> >* threadForce;
    bool includeForces, includeEnergy;
    void* atomicCounter;

    /**
     * This routine contains the code executed by each thread.
     */
    void threadComputeForce(ThreadPool& threads, int threadIndex);
76

77
78
79
80
    /**
     * This is called recursively to loop over all possible combination of a set of particles and evaluate the
     * interaction for each one.
     */
81
82
    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);
83
84
85
86
87

    /**---------------------------------------------------------------------------------------

       Calculate custom interaction for one set of particles

88
89
90
91
92
       @param particleSet        the indices of the particles
       @param posq               atom coordinates in float format
       @param particleParameters particle parameter values (particleParameters[particleIndex][parameterIndex])
       @param forces             force array (forces added)
       @param totalEnergy        total energy
93
94
95

       --------------------------------------------------------------------------------------- */

96
97
98
99
100
101
102
103
104
105
    /**
     * Calculate the interaction for one set of particles
     * 
     * @param particleSet        the indices of the particles
     * @param particleParameters particle parameter values (particleParameters[particleIndex][parameterIndex])
     * @param data               information and workspace for the current thread
     * @param boxSize            the 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);
106
107
108
109
110

    /**
     * Compute the displacement and squared distance between two points, optionally using
     * periodic boundary conditions.
     */
111
112
113
114
115
    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 getDihedralAngleBetweenThreeVectors(const fvec4& v1, const fvec4& v2, const fvec4& v3, fvec4& cross1, fvec4& cross2, const fvec4& signVector);
116
117

public:
118
119
120
121
122
123
    /**
     * Create a new CpuCustomManyParticleForce.
     *
     * @param force      the CustomManyParticleForce to create it for
     * @param threads    the thread pool to use
     */
124
    CpuCustomManyParticleForce(const OpenMM::CustomManyParticleForce& force, ThreadPool& threads);
125
126
127

    ~CpuCustomManyParticleForce();

128
129
130
131
132
    /**
     * Set the force to use a cutoff.
     * 
     * @param distance   the cutoff distance
     */
133
134
    void setUseCutoff(RealOpenMM distance);

135
136
137
138
139
140
141
    /**
     * 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
     * distance.
     * 
     * @param boxSize    the X, Y, and Z widths of the periodic box
     */
142
143
    void setPeriodic(OpenMM::RealVec& boxSize);

144
145
146
147
148
149
150
151
152
153
154
155
    /**
     * Calculate the interaction.
     * 
     * @param posq               atom coordinates in float format
     * @param particleParameters particle parameter values (particleParameters[particleIndex][parameterIndex])
     * @param globalParameters   the values of global parameters
     * @param threadForce        the collection of arrays for each thread to add forces to
     * @param includeForce       whether to compute forces
     * @param includeEnergy      whether to compute energy
     * @param energy             the total energy is added to this
     */
    void calculateIxn(AlignedArray<float>& posq, RealOpenMM** particleParameters, const std::map<std::string, double>& globalParameters,
156
                      std::vector<AlignedArray<float> >& threadForce, bool includeForces, bool includeEnergy, double& energy);
157
158
159
160
161
162
163
};

class CpuCustomManyParticleForce::ParticleTermInfo {
public:
    std::string name;
    int atom, component, variableIndex;
    Lepton::CompiledExpression forceExpression;
164
    ParticleTermInfo(const std::string& name, int atom, int component, const Lepton::CompiledExpression& forceExpression, ThreadData& data);
165
166
167
168
169
170
171
};

class CpuCustomManyParticleForce::DistanceTermInfo {
public:
    std::string name;
    int p1, p2, variableIndex;
    Lepton::CompiledExpression forceExpression;
172
173
174
    int delta;
    float deltaSign;
    DistanceTermInfo(const std::string& name, const std::vector<int>& atoms, const Lepton::CompiledExpression& forceExpression, ThreadData& data);
175
176
177
178
179
180
181
};

class CpuCustomManyParticleForce::AngleTermInfo {
public:
    std::string name;
    int p1, p2, p3, variableIndex;
    Lepton::CompiledExpression forceExpression;
182
183
184
    int delta1, delta2;
    float delta1Sign, delta2Sign;
    AngleTermInfo(const std::string& name, const std::vector<int>& atoms, const Lepton::CompiledExpression& forceExpression, ThreadData& data);
185
186
187
188
189
190
191
};

class CpuCustomManyParticleForce::DihedralTermInfo {
public:
    std::string name;
    int p1, p2, p3, p4, variableIndex;
    Lepton::CompiledExpression forceExpression;
192
    int delta1, delta2, delta3;
193
    mutable fvec4 cross1, cross2;
194
195
196
197
198
199
200
201
202
203
204
205
206
    DihedralTermInfo(const std::string& name, const std::vector<int>& atoms, const Lepton::CompiledExpression& forceExpression, ThreadData& data);
};

class CpuCustomManyParticleForce::ThreadData {
public:
    CompiledExpressionSet expressionSet;
    Lepton::CompiledExpression energyExpression;
    std::vector<std::vector<int> > particleParamIndices;
    std::vector<std::pair<int, int> > deltaPairs;
    std::vector<ParticleTermInfo> particleTerms;
    std::vector<DistanceTermInfo> distanceTerms;
    std::vector<AngleTermInfo> angleTerms;
    std::vector<DihedralTermInfo> dihedralTerms;
207
208
209
    AlignedArray<fvec4> delta;
    std::vector<float> normDelta;
    std::vector<float> norm2Delta;
210
211
212
213
214
215
216
    double energy;
    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);
    /**
     * 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);
217
218
219
220
221
};

} // namespace OpenMM

#endif // OPENMM_CPU_CUSTOM_MANY_PARTICLE_FORCE_H__