SimTKOpenMMUtilities.cpp 13 KB
Newer Older
1

2
/* Portions copyright (c) 2006-2009 Stanford University and Simbios.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 * Contributors: Pande Group
 *
 * 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.
 */

// class of shared, static utility methods

27
#include "openmm/internal/OSRngSeed.h"
28
#include "SimTKOpenMMUtilities.h"
29
#include "sfmt/SFMT.h"
30
31
32

// fabs(), ...

33
34
#include <cmath>
#include <cstdio>
35
#include <string.h>
Peter Eastman's avatar
Peter Eastman committed
36
#include <iostream>
37

38
39
using namespace OpenMM;

40
41
uint32_t SimTKOpenMMUtilities::_randomNumberSeed = 0;
bool SimTKOpenMMUtilities::_randomInitialized = false;
42
43
bool SimTKOpenMMUtilities::nextGaussianIsValid = false;
RealOpenMM SimTKOpenMMUtilities::nextGaussian = 0;
44
OpenMM_SFMT::SFMT SimTKOpenMMUtilities::sfmt;
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/* ---------------------------------------------------------------------------------------

   Allocate 1D RealOpenMM array (Simbios)

   array[i]

   @param iSize                i-dimension
   @param array1D              array (if null on entry allocated)
   @param initialize           if true, then initialize array
   @param initialValue         intitial value
   @param idString             id string

   @return allocated array

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

62
63
64
RealOpenMM* SimTKOpenMMUtilities::allocateOneDRealOpenMMArray(int iSize, RealOpenMM* array1D, 
                                                              int initialize, RealOpenMM initialValue,
                                                              const std::string& idString) {
65
66
67
68
69
70
71
72
73

   // ---------------------------------------------------------------------------------------

   // static const char* methodName = "\nSimTKOpenMMUtilities::allocate1DRealOpenMMArray";

   static const RealOpenMM zero       =  0.0;

   // ---------------------------------------------------------------------------------------

74
   if (array1D == NULL) {
75

Peter Eastman's avatar
Peter Eastman committed
76
      array1D = new RealOpenMM[iSize];
77
78
79

   }

80
81
82
   if (initialize) {
      if (initialValue == zero) {
         memset(array1D, 0, iSize*sizeof(RealOpenMM));
83
      } else {
84
         for (int ii = 0; ii < iSize; ii++) {
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
            array1D[ii] = initialValue;
         }
      }
   }

   return array1D;
}

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

   Allocate 2D RealOpenMM array (Simbios)

   array[i][j]

   @param iSize                i-dimension
   @param jSize                j-dimension
   @param array2D              array (if null on entry allocated)
   @param initialize           if true, then initialize array
   @param initialValue         intitial value
   @param idString             id string

   @return allocated array

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

110
111
112
RealOpenMM** SimTKOpenMMUtilities::allocateTwoDRealOpenMMArray(int iSize, int jSize, RealOpenMM** array2D, 
                                                               int initialize, RealOpenMM initialValue,
                                                               const std::string& idString) {
113
114
115
116
117
118
119

   // ---------------------------------------------------------------------------------------

   // static const char* methodName = "\nSimTKOpenMMUtilities::allocate2DRealOpenMMArray";

   // ---------------------------------------------------------------------------------------

120
   if (array2D == NULL) {
121

Peter Eastman's avatar
Peter Eastman committed
122
      array2D = new RealOpenMM*[iSize];
123
      std::string blockString = idString;
124
      blockString.append("Block");
125

Peter Eastman's avatar
Peter Eastman committed
126
      RealOpenMM* block = new RealOpenMM[jSize*iSize];
127

128
      for (int ii = 0; ii < iSize; ii++) {
129
130
131
132
133
         array2D[ii]  = block;
         block       += jSize;
      }    
   }

134
135
   if (initialize) {
      initialize2DRealOpenMMArray(iSize, jSize, array2D, initialValue);
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
   }

   return array2D;
}

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

   Free 2D RealOpenMM array (Simbios)

   array[i][j]

   @param array2D              array (if null on entry allocated)
   @param idString             id string

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

152
void SimTKOpenMMUtilities::freeTwoDRealOpenMMArray(RealOpenMM** array2D, const std::string& idString) {
153
154
155
156
157
158
159

   // ---------------------------------------------------------------------------------------

   // static const char* methodName = "\nSimTKOpenMMUtilities::freeTwoDRealOpenMMArray";

   // ---------------------------------------------------------------------------------------

160
   if (array2D != NULL) {
161
162

      std::string blockString = idString;
163
      blockString.append("Block");
164

Peter Eastman's avatar
Peter Eastman committed
165
166
      delete[] array2D[0];
      delete[] array2D;
167
168
169
170
171
172
173
174
175
176
177
178
179
180
   }
}

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

   Free 1D RealOpenMM array (Simbios)

   array[i]

   @param array1D              array (if null on entry allocated)
   @param idString             id string

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

181
void SimTKOpenMMUtilities::freeOneDRealOpenMMArray(RealOpenMM* array1D, const std::string& idString) {
182
183
184
185
186
187
188

   // ---------------------------------------------------------------------------------------

   // static const char* methodName = "\nSimTKOpenMMUtilities::freeOneDRealOpenMMArray";

   // ---------------------------------------------------------------------------------------

189
   if (array1D != NULL) {
Peter Eastman's avatar
Peter Eastman committed
190
      delete[] array1D;
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
   }
}

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

   Initialize 2D RealOpenMM array (Simbios)

   array[i][j]

   @param iSize                i-dimension
   @param jSize                j-dimension
   @param array2D              array (if null on entry allocated)
   @param initialValue         intitial value

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

207
void SimTKOpenMMUtilities::initialize2DRealOpenMMArray(int iSize, int jSize,
208
                                                       RealOpenMM** array2D,
209
                                                       RealOpenMM initialValue) {
210
211
212
213
214
215
216
217
218
219

   // ---------------------------------------------------------------------------------------

   // static const char* methodName = "\nSimTKOpenMMUtilities::initialize2DRealOpenMMArray";

   // ---------------------------------------------------------------------------------------

   bool useMemset;
   bool useMemsetSingleBlock;

220
   if (initialValue == 0.0f) {
221
      useMemset = true;
222
      if (jSize > 1 && (array2D[0] + jSize) == array2D[1]) {  
223
224
225
226
227
228
229
230
231
         useMemsetSingleBlock = true;
      } else {
         useMemsetSingleBlock = false;
      }

   } else {
      useMemset = false;
   }

232
233
234
   if (useMemset) {
      if (useMemsetSingleBlock) {
         memset(array2D[0], 0, iSize*jSize*sizeof(RealOpenMM));
235
      } else {
236
237
         for (int ii = 0; ii < iSize; ii++) {
            memset(array2D[ii], 0, jSize*sizeof(RealOpenMM));
238
239
240
         }
      }
   } else {
241
242
      for (int ii = 0; ii < iSize; ii++) {
         for (int jj = 0; jj < jSize; jj++) {
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
            array2D[ii][jj] = initialValue;
         }
      }
   }
}

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

   Compute cross product of two 3-vectors and place in 3rd vector  -- helper method

   vectorZ = vectorX x vectorY

   @param vectorX             x-vector
   @param vectorY             y-vector
   @param vectorZ             z-vector

   @return vector is vectorZ

   --------------------------------------------------------------------------------------- */
     
263
264
265
void SimTKOpenMMUtilities::crossProductVector3(RealOpenMM* vectorX,
                                               RealOpenMM* vectorY,
                                               RealOpenMM* vectorZ) {
266
267
268
269
270
271
272
273
274
275
276
277
278
279

   // ---------------------------------------------------------------------------------------

   // static const char* methodName = "\nSimTKOpenMMUtilities::crossProductVector3";

   // ---------------------------------------------------------------------------------------

   vectorZ[0]  = vectorX[1]*vectorY[2] - vectorX[2]*vectorY[1];
   vectorZ[1]  = vectorX[2]*vectorY[0] - vectorX[0]*vectorY[2];
   vectorZ[2]  = vectorX[0]*vectorY[1] - vectorX[1]*vectorY[0];

   return;
}

280
281
282
283
284
285
286
287
/**---------------------------------------------------------------------------------------

   Get normally distributed random number

   @return random value

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

288
RealOpenMM SimTKOpenMMUtilities::getNormallyDistributedRandomNumber() {
289
290
291
    if (nextGaussianIsValid) {
        nextGaussianIsValid = false;
        return nextGaussian;
292
293
    }
    if (!_randomInitialized) {
294
        init_gen_rand(_randomNumberSeed, sfmt);
295
        _randomInitialized = true;
296
        nextGaussianIsValid = false;
297
298
299
300
301
302
    }
    
    // Use the polar form of the Box-Muller transformation to generate two Gaussian random numbers.
    
    RealOpenMM x, y, r2;
    do {
303
304
        x = static_cast<RealOpenMM>(2.0 * genrand_real2(sfmt) - 1.0);
        y = static_cast<RealOpenMM>(2.0 * genrand_real2(sfmt) - 1.0);
305
306
        r2 = x*x + y*y;
    } while (r2 >= 1.0 || r2 == 0.0);
307
    RealOpenMM multiplier = static_cast<RealOpenMM>(sqrt((-2.0*log(r2))/r2));
308
309
    nextGaussian = y*multiplier;
    nextGaussianIsValid = true;
310
311
312
313
314
315
316
317
318
319
320
    return x*multiplier;
}

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

   Get uniformly distributed random number in the range [0, 1)

   @return random value

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

321
RealOpenMM SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber() {
322
    if (!_randomInitialized) {
323
        init_gen_rand(_randomNumberSeed, sfmt);
324
        _randomInitialized = true;
325
        nextGaussianIsValid = false;
326
    }
327
    RealOpenMM value = static_cast<RealOpenMM>(genrand_real2(sfmt));
328
    return value;
329
330
331
332
333
334
335
336
337
338
}

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

   Get random number seed

   @return random number seed

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

339
uint32_t SimTKOpenMMUtilities::getRandomNumberSeed() {
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357

   // ---------------------------------------------------------------------------------------

   // static const char* methodName  = "\nReferenceDynamics::getRandomNumberSeed";

   // ---------------------------------------------------------------------------------------

   return _randomNumberSeed;
}

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

   Set random number seed

   @param seed    new seed value

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

358
void SimTKOpenMMUtilities::setRandomNumberSeed(uint32_t seed) {
359
360
361
362
363
364
365

   // ---------------------------------------------------------------------------------------

   // static const char* methodName  = "\nReferenceDynamics::setRandomNumberSeed";

   // ---------------------------------------------------------------------------------------

366
    // If the seed is 0, use a unique seed
367
368
369
370
    if (seed == 0)
        _randomNumberSeed = (uint32_t) osrngseed();
    else
        _randomNumberSeed = seed;
371
   _randomInitialized = false;
372
}
Peter Eastman's avatar
Peter Eastman committed
373
374
375
376
377
378
379
380
381
382
383
384
385

void SimTKOpenMMUtilities::createCheckpoint(std::ostream& stream) {
    stream.write((char*) &_randomNumberSeed, sizeof(uint32_t));
    stream.write((char*) &_randomInitialized, sizeof(bool));
    if (_randomInitialized) {
        stream.write((char*) &nextGaussianIsValid, sizeof(bool));
        stream.write((char*) &nextGaussian, sizeof(RealOpenMM));
        sfmt.createCheckpoint(stream);
    }
}

void SimTKOpenMMUtilities::loadCheckpoint(std::istream& stream) {
    stream.read((char*) &_randomNumberSeed, sizeof(uint32_t));
386
    bool prevInitialized = _randomInitialized;
Peter Eastman's avatar
Peter Eastman committed
387
388
    stream.read((char*) &_randomInitialized, sizeof(bool));
    if (_randomInitialized) {
389
390
        if (!prevInitialized)
            init_gen_rand(0, sfmt);
Peter Eastman's avatar
Peter Eastman committed
391
392
393
394
395
        stream.read((char*) &nextGaussianIsValid, sizeof(bool));
        stream.read((char*) &nextGaussian, sizeof(RealOpenMM));
        sfmt.loadCheckpoint(stream);
    }
}