kshakeh.br 8.69 KB
Newer Older
Mark Friedrichs's avatar
Mark Friedrichs committed
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
31
/* -------------------------------------------------------------------------- *
 *                                   OpenMM                                   *
 * -------------------------------------------------------------------------- *
 * This is part of the OpenMM molecular simulation toolkit originating from   *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org.               *
 *                                                                            *
 * Portions copyright (c) 2008 Stanford University and the Authors.           *
 * Authors: Peter Eastman, Mark Friedrichs, Chris Bruns                       *
 * Contributors:                                                              *
 *                                                                            *
 * Permission is hereby granted, free of charge, to any person obtaining a    *
 * copy of this software and associated documentation files (the "Software"), *
 * to deal in the Software without restriction, including without limitation  *
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
 * and/or sell copies of the Software, and to permit persons to whom the      *
 * Software is furnished to do so, subject to the following conditions:       *
 *                                                                            *
 * The above copyright notice and this permission notice shall be included in *
 * all copies or substantial portions of the Software.                        *
 *                                                                            *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
 * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
 * -------------------------------------------------------------------------- */
Mark Friedrichs's avatar
Mark Friedrichs committed
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

/*
 * This kernel constrains bonds involving hydrogen using an unrolled
 * shake implementation. We assume that a heavy atom can have at most 
 * 3 hydrogens attached. The hydrogens are expected to be identical
 *
 * For atoms that have ewer than 3 hydrogens
 *
 * Also we don't check the constraints!
 *  
 * We do a fixed number of iterations without checking for convergence
 * to avoid stalling
 * *************************************************************/

/* Fix for precision of terms first order in dt
 * To be used with corresponding update kernels
 * The input posqp is now changes to posq rather than
 * posq+changes
 * */
kernel void
kshakeh_fix1(
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
53
		float maxIterations,      //number of iterations
Mark Friedrichs's avatar
Mark Friedrichs committed
54
55
		float strwidth, //stream width of posq
		float invmH,    //inverse mass of hydrogen
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
56
		float inputTolerance,    //tolerance
Mark Friedrichs's avatar
Mark Friedrichs committed
57
		float4 atoms<>, //heavy0, h1, h2, h3
58
59
		float3 posq[][], //positions before update
		float3 posqp[][], //changes to positions
Mark Friedrichs's avatar
Mark Friedrichs committed
60
		float4 params<>, // (1/m0, mu/2, blensq, 0.0f )
61
62
63
64
		out float3 cposq0<>, //constrained position for heavy atom
		out float3 cposq1<>, //ditto for h1
		out float3 cposq2<>, //ditto for h2
		out float3 cposq3<> //ditto for h3
Mark Friedrichs's avatar
Mark Friedrichs committed
65
66
67
68
69
70
		) {
	float2 ai, aj1, aj2, aj3; //2d indices, can be precalc.
	float i; //iteration count
	float3 xi, xj1, xj2, xj3; //coordinates
	float3 xpi, xpj1, xpj2, xpj3; //coordinates
	float3 rij1, rij2, rij3, rpij, dr;
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
71
	float rpsqij, rrpr, acor, tolerance, converged;
Mark Friedrichs's avatar
Mark Friedrichs committed
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
	float mask2, mask3;
	float diff;
	float rij1sq, rij2sq, rij3sq;
	float ld1, ld2, ld3;
	
	// ai.y  = floor( atoms.x / strwidth );
   ai.y  = round( (atoms.x - fmod( atoms.x, strwidth ))/strwidth );
	ai.x  = atoms.x - ai.y * strwidth;

	// aj1.y = floor( atoms.y / strwidth );
   aj1.y  = round( (atoms.y - fmod( atoms.y, strwidth ))/strwidth );
	aj1.x = atoms.y - aj1.y * strwidth;

	//If further hydrogens are absent,
	//just set to the coordinates of the first
	//so we don't have any junk memory accesses
	//or nans/infs in the calcs.	
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
89
90

	if( atoms.z > -0.5f ){
Mark Friedrichs's avatar
Mark Friedrichs committed
91
92
93
94
		// aj2.y = floor( atoms.z / strwidth );
		aj2.y = round( (atoms.z - fmod( atoms.z, strwidth ))/strwidth );
		aj2.x = atoms.z - aj2.y * strwidth;
		mask2 = 1.0f;
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
95
	} else {
Mark Friedrichs's avatar
Mark Friedrichs committed
96
97
98
99
		aj2 = aj1; 
		mask2 = 0.0f;
	}

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
100
	if( atoms.w > -0.5f ){	
Mark Friedrichs's avatar
Mark Friedrichs committed
101
102
103
104
		// aj3.y = floor( atoms.w / strwidth );
		aj3.y = round( (atoms.w - fmod( atoms.w, strwidth ))/strwidth );
		aj3.x = atoms.w - aj3.y * strwidth;
		mask3 = 1.0f;
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
105
	} else {
Mark Friedrichs's avatar
Mark Friedrichs committed
106
107
108
109
		aj3 = aj1;
		mask3 = 0.0f;
	}

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
110
111
112
113
	cposq0       = posq[ai];
	cposq1       = posq[aj1];
	cposq2       = posq[aj2];
	cposq3       = posq[aj3];
Mark Friedrichs's avatar
Mark Friedrichs committed
114
	
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
115
116
117
118
	xi           = cposq0;
	xj1          = cposq1;
	xj2          = cposq2;
	xj3          = cposq3;
Mark Friedrichs's avatar
Mark Friedrichs committed
119
	
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
120
121
122
	rij1         = xi - xj1;
	rij2         = xi - xj2;
	rij3         = xi - xj3;
Mark Friedrichs's avatar
Mark Friedrichs committed
123

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
124
125
126
	rij1sq       = dot( rij1, rij1 );
	rij2sq       = dot( rij2, rij2 );
	rij3sq       = dot( rij3, rij3 );
Mark Friedrichs's avatar
Mark Friedrichs committed
127

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
128
129
130
	ld1          = params.z - rij1sq;
	ld2          = params.z - rij2sq;
	ld3          = params.z - rij3sq;
Mark Friedrichs's avatar
Mark Friedrichs committed
131

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
132
133
134
135
	xpi          = posqp[ai]   - xi;
	xpj1         = posqp[aj1]  - xj1;
	xpj2         = posqp[aj2]  - xj2;
	xpj3         = posqp[aj3]  - xj3;
Mark Friedrichs's avatar
Mark Friedrichs committed
136
137


Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
138
139
140
141
	i           = 0.0f;
   converged   = 1.0f;
   tolerance   = 2.0f*inputTolerance;
	while( i < maxIterations && converged > 0.0f ){
Mark Friedrichs's avatar
Mark Friedrichs committed
142
143
144

		//First hydrogen

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
145
146
147
148
149
150
151
		rpij       = xpi - xpj1; //This is really rpij - rij
		rpsqij     = dot( rpij, rpij ); //This is really deltar ^ 2
		rrpr       = dot( rij1, rpij ); //This is r.deltar
      acor       = ( ld1 - 2 * rrpr - rpsqij ) * params.y / ( rrpr + rij1sq ) ; 
      diff       = abs( ld1 - 2 * rrpr - rpsqij ) / (params.z * tolerance );
      acor       = (diff < 1.0f) ? 0.0f : acor;
      converged  = acor;
Mark Friedrichs's avatar
Mark Friedrichs committed
152

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
153
154
155
		dr         = rij1 * acor;
		xpi       += dr * params.x;
		xpj1      -= dr * invmH;
Mark Friedrichs's avatar
Mark Friedrichs committed
156

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
157
		//Second hydrogen
Mark Friedrichs's avatar
Mark Friedrichs committed
158

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
159
160
161
		rpij       = xpi - xpj2;
		rpsqij     = dot( rpij, rpij );
		rrpr       = dot( rij2, rpij );
Mark Friedrichs's avatar
Mark Friedrichs committed
162

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
163
164
165
166
      diff       = abs( ld2 - 2.0f * rrpr - rpsqij ) / (params.z * tolerance );
      acor       = mask2 * ( ld2 - 2.0f * rrpr - rpsqij ) * params.y / ( rrpr + rij2sq ) ; 
      acor       = (diff < 1.0f) ? 0.0f : acor;
      converged += acor;
Mark Friedrichs's avatar
Mark Friedrichs committed
167

Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
168
169
170
		dr         = rij2 * acor;
		xpi       += dr * params.x;
		xpj2      -= dr * invmH;
Mark Friedrichs's avatar
Mark Friedrichs committed
171
172

		//Third hydrogen
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
173
174
175
176
177
178
179
180
181
182
183
184

		rpij       = xpi - xpj3;
		rpsqij     = dot( rpij, rpij );
		rrpr       = dot( rij3, rpij );
      diff       = abs( ld3 - 2.0f * rrpr - rpsqij ) / (params.z * tolerance );
      acor       = mask3 * ( ld3 - 2.0f * rrpr - rpsqij ) * params.y / ( rrpr + rij3sq ) ;
      acor       = (diff < 1.0f) ? 0.0f : acor;
      converged += acor;

		dr         = rij3 * acor;
		xpi       += dr * params.x;
		xpj3      -= dr * invmH;
Mark Friedrichs's avatar
Mark Friedrichs committed
185
186
187
188
189
		
		i += 1.0f;
	}

	//Output modified delta's
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
190

191
192
193
194
	cposq0 = xpi;
	cposq1 = xpj1;
	cposq2 = xpj2;
	cposq3 = xpj3;
Mark Friedrichs's avatar
Mark Friedrichs committed
195
196
197
198
199
200

}

kernel void kshakeh_update2_fix1( 
		float strwidth, //width of cposq streams
		float2 invmap<>,    //shakeh inverse map
201
202
203
204
205
206
207
		float3 posq<>,     //old positions
		float3 posqp<>,    //deltas from sd2
		float3 cposq0[][], //constrained delta for heavy atom
		float3 cposq1[][], //ditto for h1
		float3 cposq2[][], //ditto for h2
		float3 cposq3[][], //ditto for h3
		out float3 oposq<> //updated deltas
Mark Friedrichs's avatar
Mark Friedrichs committed
208
209
210
211
212
213
214
215
		){
	float2 atom;
	
	// atom.y = floor( invmap.x / strwidth );
   atom.y  = round( (invmap.x - fmod( invmap.x, strwidth ))/strwidth );
	atom.x = invmap.x - atom.y * strwidth;
	
	if ( invmap.y < 0 ){
216
		oposq = posqp - posq;
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
217
	} else if ( invmap.y < 0.5f ){ 
Mark Friedrichs's avatar
Mark Friedrichs committed
218
		oposq = cposq0[ atom ];
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
219
	} else if ( invmap.y < 1.5f){
Mark Friedrichs's avatar
Mark Friedrichs committed
220
		oposq = cposq1[ atom ];
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
221
	} else if ( invmap.y < 2.5f ){
Mark Friedrichs's avatar
Mark Friedrichs committed
222
		oposq = cposq2[ atom ];
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
223
	} else if ( invmap.y < 3.5f ){
Mark Friedrichs's avatar
Mark Friedrichs committed
224
		oposq = cposq3[ atom ];
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
225
   }
Mark Friedrichs's avatar
Mark Friedrichs committed
226

227
	oposq += posq;
Mark Friedrichs's avatar
Mark Friedrichs committed
228
229
230
231
232
}

kernel void kshakeh_update1_fix1( 
		float strwidth, //width of cposq streams
		float2 invmap<>,    //shakeh inverse map
233
234
235
236
237
238
239
		float3 posq<>,     //old positions
		float3 posqp<>,    //deltas from sd2
		float3 cposq0[][], //constrained delta for heavy atom
		float3 cposq1[][], //ditto for h1
		float3 cposq2[][], //ditto for h2
		float3 cposq3[][], //ditto for h3
		out float3 oposq<> //updated deltas
Mark Friedrichs's avatar
Mark Friedrichs committed
240
241
242
243
244
245
246
247
248
249
		){
	float2 atom;
	
	// atom.y = floor( invmap.x / strwidth );
   atom.y  = round( (invmap.x - fmod( invmap.x, strwidth ))/strwidth );
	atom.x = invmap.x - atom.y * strwidth;
	
	oposq = posq;
	if ( invmap.y < 0 ){
		oposq = posqp;
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
250
	} else if ( invmap.y < 0.5f ){
251
		oposq += cposq0[ atom ];
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
252
	} else if ( invmap.y < 1.5f ){
253
		oposq += cposq1[ atom ];
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
254
	} else if ( invmap.y < 2.5f ){
255
		oposq += cposq2[ atom ];
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
256
	} else if ( invmap.y < 3.5f ){
257
		oposq += cposq3[ atom ];
Mark Friedrichs's avatar
Mods  
Mark Friedrichs committed
258
   }
Mark Friedrichs's avatar
Mark Friedrichs committed
259
260

}