CudaIntegrationUtilities.cpp 5.96 KB
Newer Older
1
2
3
4
5
6
7
8
/* -------------------------------------------------------------------------- *
 *                                   OpenMM                                   *
 * -------------------------------------------------------------------------- *
 * This is part of the OpenMM molecular simulation toolkit originating from   *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org.               *
 *                                                                            *
9
 * Portions copyright (c) 2009-2019 Stanford University and the Authors.      *
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * Authors: Peter Eastman                                                     *
 * Contributors:                                                              *
 *                                                                            *
 * This program is free software: you can redistribute it and/or modify       *
 * it under the terms of the GNU Lesser General Public License as published   *
 * by the Free Software Foundation, either version 3 of the License, or       *
 * (at your option) any later version.                                        *
 *                                                                            *
 * This program is distributed in the hope that it will be useful,            *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
 * GNU Lesser General Public License for more details.                        *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.      *
 * -------------------------------------------------------------------------- */

#include "CudaIntegrationUtilities.h"
28
#include "CudaContext.h"
29
30
31
32
33
34
35
36

using namespace OpenMM;
using namespace std;

#define CHECK_RESULT(result) CHECK_RESULT2(result, errorMessage);
#define CHECK_RESULT2(result, prefix) \
    if (result != CUDA_SUCCESS) { \
        std::stringstream m; \
37
        m<<prefix<<": "<<dynamic_cast<CudaContext&>(context).getErrorString(result)<<" ("<<result<<")"<<" at "<<__FILE__<<":"<<__LINE__; \
38
39
40
        throw OpenMMException(m.str());\
    }

41
42
43
CudaIntegrationUtilities::CudaIntegrationUtilities(CudaContext& context, const System& system) : IntegrationUtilities(context, system),
        ccmaConvergedMemory(NULL) {
        CHECK_RESULT2(cuEventCreate(&ccmaEvent, CU_EVENT_DISABLE_TIMING), "Error creating event for CCMA");
Peter Eastman's avatar
Peter Eastman committed
44
45
        CHECK_RESULT2(cuMemHostAlloc((void**) &ccmaConvergedMemory, sizeof(int), CU_MEMHOSTALLOC_DEVICEMAP), "Error allocating pinned memory");
        CHECK_RESULT2(cuMemHostGetDevicePointer(&ccmaConvergedDeviceMemory, ccmaConvergedMemory, 0), "Error getting device address for pinned memory");
46
47
48
}

CudaIntegrationUtilities::~CudaIntegrationUtilities() {
49
    context.setAsCurrent();
50
    if (ccmaConvergedMemory != NULL) {
Peter Eastman's avatar
Peter Eastman committed
51
        cuMemFreeHost(ccmaConvergedMemory);
52
        cuEventDestroy(ccmaEvent);
53
54
55
    }
}

56
57
CudaArray& CudaIntegrationUtilities::getPosDelta() {
    return dynamic_cast<CudaContext&>(context).unwrap(posDelta);
58
59
}

60
61
CudaArray& CudaIntegrationUtilities::getRandom() {
    return dynamic_cast<CudaContext&>(context).unwrap(random);
62
63
}

64
65
CudaArray& CudaIntegrationUtilities::getStepSize() {
    return dynamic_cast<CudaContext&>(context).unwrap(stepSize);
66
67
}

68
69
void CudaIntegrationUtilities::applyConstraintsImpl(bool constrainVelocities, double tol) {
    ComputeKernel settleKernel, shakeKernel, ccmaForceKernel;
70
71
72
73
74
75
76
77
78
79
    if (constrainVelocities) {
        settleKernel = settleVelKernel;
        shakeKernel = shakeVelKernel;
        ccmaForceKernel = ccmaVelForceKernel;
    }
    else {
        settleKernel = settlePosKernel;
        shakeKernel = shakePosKernel;
        ccmaForceKernel = ccmaPosForceKernel;
    }
Peter Eastman's avatar
Peter Eastman committed
80
    if (settleAtoms.isInitialized()) {
81
82
83
84
85
        if (context.getUseDoublePrecision() || context.getUseMixedPrecision())
            settleKernel->setArg(1, tol);
        else
            settleKernel->setArg(1, (float) tol);
        settleKernel->execute(settleAtoms.getSize());
86
    }
Peter Eastman's avatar
Peter Eastman committed
87
    if (shakeAtoms.isInitialized()) {
88
89
90
91
92
        if (context.getUseDoublePrecision() || context.getUseMixedPrecision())
            shakeKernel->setArg(1, tol);
        else
            shakeKernel->setArg(1, (float) tol);
        shakeKernel->execute(shakeAtoms.getSize());
93
    }
Peter Eastman's avatar
Peter Eastman committed
94
    if (ccmaAtoms.isInitialized()) {
95
96
97
98
99
100
        ccmaForceKernel->setArg(6, ccmaConvergedDeviceMemory);
        if (context.getUseDoublePrecision() || context.getUseMixedPrecision())
            ccmaForceKernel->setArg(7, tol);
        else
            ccmaForceKernel->setArg(7, (float) tol);
        ccmaDirectionsKernel->execute(ccmaAtoms.getSize());
101
        const int checkInterval = 4;
Peter Eastman's avatar
Peter Eastman committed
102
        ccmaConvergedMemory[0] = 0;
103
104
105
106
        ccmaUpdateKernel->setArg(3, constrainVelocities ? context.getVelm() : posDelta);
        for (int i = 0; i < 150; i++) {
            ccmaForceKernel->setArg(8, i);
            ccmaForceKernel->execute(ccmaAtoms.getSize());
Peter Eastman's avatar
Peter Eastman committed
107
            if ((i+1)%checkInterval == 0)
108
                CHECK_RESULT2(cuEventRecord(ccmaEvent, 0), "Error recording event for CCMA");
109
110
111
112
            ccmaMultiplyKernel->setArg(5, i);
            ccmaMultiplyKernel->execute(ccmaAtoms.getSize());
            ccmaUpdateKernel->setArg(8, i);
            ccmaUpdateKernel->execute(context.getNumAtoms());
113
114
            if ((i+1)%checkInterval == 0) {
                CHECK_RESULT2(cuEventSynchronize(ccmaEvent), "Error synchronizing on event for CCMA");
Peter Eastman's avatar
Peter Eastman committed
115
                if (ccmaConvergedMemory[0])
116
117
118
119
                    break;
            }
        }
    }
120
121
122
}

void CudaIntegrationUtilities::distributeForcesFromVirtualSites() {
123
    if (numVsites > 0) {
124
125
        vsiteForceKernel->setArg(2, context.getLongForceBuffer());
        vsiteForceKernel->execute(numVsites);
126
    }
127
}