| 10 |  | #include "SRI.hpp" | 
| 11 |  | #include "Integrator.hpp" | 
| 12 |  | #include "simError.h" | 
| 13 | + | #include "MatVec3.h" | 
| 14 |  |  | 
| 15 |  | #ifdef IS_MPI | 
| 16 |  | #define __C | 
| 17 |  | #include "mpiSimulation.hpp" | 
| 18 |  | #endif // is_mpi | 
| 19 |  |  | 
| 20 | + | inline double roundMe( double x ){ | 
| 21 | + | return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 ); | 
| 22 | + | } | 
| 23 | + |  | 
| 24 |  | Thermo::Thermo( SimInfo* the_info ) { | 
| 25 |  | info = the_info; | 
| 26 |  | int baseSeed = the_info->getSeed(); | 
| 202 |  | double molmass, volume; | 
| 203 |  | double vcom[3]; | 
| 204 |  | double p_local[9], p_global[9]; | 
| 205 | < | int i, j, k, nMols; | 
| 201 | < | Molecule* molecules; | 
| 205 | > | int i, j, k; | 
| 206 |  |  | 
| 203 | – | nMols = info->n_mol; | 
| 204 | – | molecules = info->molecules; | 
| 205 | – | //tau = info->tau; | 
| 206 | – |  | 
| 207 | – | // use velocities of molecular centers of mass and molecular masses: | 
| 207 |  | for (i=0; i < 9; i++) { | 
| 208 |  | p_local[i] = 0.0; | 
| 209 |  | p_global[i] = 0.0; | 
| 210 |  | } | 
| 211 |  |  | 
| 212 | < | for (i=0; i < nMols; i++) { | 
| 214 | < | molmass = molecules[i].getCOMvel(vcom); | 
| 212 | > | // use velocities of integrableObjects and their masses: | 
| 213 |  |  | 
| 214 | + | for (i=0; i < info->integrableObjects.size(); i++) { | 
| 215 | + |  | 
| 216 | + | molmass = info->integrableObjects[i]->getMass(); | 
| 217 | + |  | 
| 218 | + | info->integrableObjects[i]->getVel(vcom); | 
| 219 | + |  | 
| 220 |  | p_local[0] += molmass * (vcom[0] * vcom[0]); | 
| 221 |  | p_local[1] += molmass * (vcom[0] * vcom[1]); | 
| 222 |  | p_local[2] += molmass * (vcom[0] * vcom[2]); | 
| 226 |  | p_local[6] += molmass * (vcom[2] * vcom[0]); | 
| 227 |  | p_local[7] += molmass * (vcom[2] * vcom[1]); | 
| 228 |  | p_local[8] += molmass * (vcom[2] * vcom[2]); | 
| 229 | + |  | 
| 230 |  | } | 
| 231 |  |  | 
| 232 |  | // Get total for entire system from MPI. | 
| 233 | < |  | 
| 233 | > |  | 
| 234 |  | #ifdef IS_MPI | 
| 235 |  | MPI_Allreduce(p_local,p_global,9,MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); | 
| 236 |  | #else | 
| 241 |  |  | 
| 242 |  | volume = this->getVolume(); | 
| 243 |  |  | 
| 244 | + |  | 
| 245 | + |  | 
| 246 |  | for(i = 0; i < 3; i++) { | 
| 247 |  | for (j = 0; j < 3; j++) { | 
| 248 |  | k = 3*i + j; | 
| 249 |  | press[i][j] = (p_global[k] + info->tau[k]*e_convert) / volume; | 
| 243 | – |  | 
| 250 |  | } | 
| 251 |  | } | 
| 252 |  | } | 
| 254 |  | void Thermo::velocitize() { | 
| 255 |  |  | 
| 256 |  | double aVel[3], aJ[3], I[3][3]; | 
| 257 | < | int i, j, vr, vd; // velocity randomizer loop counters | 
| 257 | > | int i, j, l, m, n, vr, vd; // velocity randomizer loop counters | 
| 258 |  | double vdrift[3]; | 
| 259 |  | double vbar; | 
| 260 |  | const double kb = 8.31451e-7; // kb in amu, angstroms, fs, etc. | 
| 261 |  | double av2; | 
| 262 |  | double kebar; | 
| 257 | – | int n_atoms; | 
| 258 | – | Atom** atoms; | 
| 259 | – | DirectionalAtom* dAtom; | 
| 263 |  | double temperature; | 
| 264 | < | int n_oriented; | 
| 262 | < | int n_constraints; | 
| 264 | > | int nobj; | 
| 265 |  |  | 
| 266 | < | atoms         = info->atoms; | 
| 267 | < | n_atoms       = info->n_atoms; | 
| 266 | > | nobj = info->integrableObjects.size(); | 
| 267 | > |  | 
| 268 |  | temperature   = info->target_temp; | 
| 267 | – | n_oriented    = info->n_oriented; | 
| 268 | – | n_constraints = info->n_constraints; | 
| 269 |  |  | 
| 270 |  | kebar = kb * temperature * (double)info->ndfRaw / | 
| 271 |  | ( 2.0 * (double)info->ndf ); | 
| 272 |  |  | 
| 273 | < | for(vr = 0; vr < n_atoms; vr++){ | 
| 273 | > | for(vr = 0; vr < nobj; vr++){ | 
| 274 |  |  | 
| 275 |  | // uses equipartition theory to solve for vbar in angstrom/fs | 
| 276 |  |  | 
| 277 | < | av2 = 2.0 * kebar / atoms[vr]->getMass(); | 
| 277 | > | av2 = 2.0 * kebar / info->integrableObjects[vr]->getMass(); | 
| 278 |  | vbar = sqrt( av2 ); | 
| 279 |  |  | 
| 280 |  | // picks random velocities from a gaussian distribution | 
| 283 |  | for (j=0; j<3; j++) | 
| 284 |  | aVel[j] = vbar * gaussStream->getGaussian(); | 
| 285 |  |  | 
| 286 | < | atoms[vr]->setVel( aVel ); | 
| 286 | > | info->integrableObjects[vr]->setVel( aVel ); | 
| 287 | > |  | 
| 288 | > | if(info->integrableObjects[vr]->isDirectional()){ | 
| 289 |  |  | 
| 290 | + | info->integrableObjects[vr]->getI( I ); | 
| 291 | + |  | 
| 292 | + | if (info->integrableObjects[vr]->isLinear()) { | 
| 293 | + |  | 
| 294 | + | l= info->integrableObjects[vr]->linearAxis(); | 
| 295 | + | m = (l+1)%3; | 
| 296 | + | n = (l+2)%3; | 
| 297 | + |  | 
| 298 | + | aJ[l] = 0.0; | 
| 299 | + | vbar = sqrt( 2.0 * kebar * I[m][m] ); | 
| 300 | + | aJ[m] = vbar * gaussStream->getGaussian(); | 
| 301 | + | vbar = sqrt( 2.0 * kebar * I[n][n] ); | 
| 302 | + | aJ[n] = vbar * gaussStream->getGaussian(); | 
| 303 | + |  | 
| 304 | + | } else { | 
| 305 | + | for (j = 0 ; j < 3; j++) { | 
| 306 | + | vbar = sqrt( 2.0 * kebar * I[j][j] ); | 
| 307 | + | aJ[j] = vbar * gaussStream->getGaussian(); | 
| 308 | + | } | 
| 309 | + | } // else isLinear | 
| 310 | + |  | 
| 311 | + | info->integrableObjects[vr]->setJ( aJ ); | 
| 312 | + |  | 
| 313 | + | }//isDirectional | 
| 314 | + |  | 
| 315 |  | } | 
| 316 |  |  | 
| 317 |  | // Get the Center of Mass drift velocity. | 
| 321 |  | //  Corrects for the center of mass drift. | 
| 322 |  | // sums all the momentum and divides by total mass. | 
| 323 |  |  | 
| 324 | < | for(vd = 0; vd < n_atoms; vd++){ | 
| 324 | > | for(vd = 0; vd < nobj; vd++){ | 
| 325 |  |  | 
| 326 | < | atoms[vd]->getVel(aVel); | 
| 326 | > | info->integrableObjects[vd]->getVel(aVel); | 
| 327 |  |  | 
| 328 |  | for (j=0; j < 3; j++) | 
| 329 |  | aVel[j] -= vdrift[j]; | 
| 330 |  |  | 
| 331 | < | atoms[vd]->setVel( aVel ); | 
| 331 | > | info->integrableObjects[vd]->setVel( aVel ); | 
| 332 |  | } | 
| 306 | – | if( n_oriented ){ | 
| 307 | – |  | 
| 308 | – | for( i=0; i<n_atoms; i++ ){ | 
| 309 | – |  | 
| 310 | – | if( atoms[i]->isDirectional() ){ | 
| 311 | – |  | 
| 312 | – | dAtom = (DirectionalAtom *)atoms[i]; | 
| 313 | – | dAtom->getI( I ); | 
| 314 | – |  | 
| 315 | – | for (j = 0 ; j < 3; j++) { | 
| 333 |  |  | 
| 317 | – | vbar = sqrt( 2.0 * kebar * I[j][j] ); | 
| 318 | – | aJ[j] = vbar * gaussStream->getGaussian(); | 
| 319 | – |  | 
| 320 | – | } | 
| 321 | – |  | 
| 322 | – | dAtom->setJ( aJ ); | 
| 323 | – |  | 
| 324 | – | } | 
| 325 | – | } | 
| 326 | – | } | 
| 334 |  | } | 
| 335 |  |  | 
| 336 |  | void Thermo::getCOMVel(double vdrift[3]){ | 
| 338 |  | double mtot, mtot_local; | 
| 339 |  | double aVel[3], amass; | 
| 340 |  | double vdrift_local[3]; | 
| 341 | < | int vd, n_atoms, j; | 
| 342 | < | Atom** atoms; | 
| 341 | > | int vd, j; | 
| 342 | > | int nobj; | 
| 343 |  |  | 
| 344 | < | // We are very careless here with the distinction between n_atoms and n_local | 
| 338 | < | // We should really fix this before someone pokes an eye out. | 
| 344 | > | nobj   = info->integrableObjects.size(); | 
| 345 |  |  | 
| 340 | – | n_atoms = info->n_atoms; | 
| 341 | – | atoms   = info->atoms; | 
| 342 | – |  | 
| 346 |  | mtot_local = 0.0; | 
| 347 |  | vdrift_local[0] = 0.0; | 
| 348 |  | vdrift_local[1] = 0.0; | 
| 349 |  | vdrift_local[2] = 0.0; | 
| 350 |  |  | 
| 351 | < | for(vd = 0; vd < n_atoms; vd++){ | 
| 351 | > | for(vd = 0; vd < nobj; vd++){ | 
| 352 |  |  | 
| 353 | < | amass = atoms[vd]->getMass(); | 
| 354 | < | atoms[vd]->getVel( aVel ); | 
| 353 | > | amass = info->integrableObjects[vd]->getMass(); | 
| 354 | > | info->integrableObjects[vd]->getVel( aVel ); | 
| 355 |  |  | 
| 356 |  | for(j = 0; j < 3; j++) | 
| 357 |  | vdrift_local[j] += aVel[j] * amass; | 
| 380 |  | double mtot, mtot_local; | 
| 381 |  | double aPos[3], amass; | 
| 382 |  | double COM_local[3]; | 
| 383 | < | int i, n_atoms, j; | 
| 384 | < | Atom** atoms; | 
| 383 | > | int i, j; | 
| 384 | > | int nobj; | 
| 385 |  |  | 
| 383 | – | // We are very careless here with the distinction between n_atoms and n_local | 
| 384 | – | // We should really fix this before someone pokes an eye out. | 
| 385 | – |  | 
| 386 | – | n_atoms = info->n_atoms; | 
| 387 | – | atoms   = info->atoms; | 
| 388 | – |  | 
| 386 |  | mtot_local = 0.0; | 
| 387 |  | COM_local[0] = 0.0; | 
| 388 |  | COM_local[1] = 0.0; | 
| 389 |  | COM_local[2] = 0.0; | 
| 390 | < |  | 
| 391 | < | for(i = 0; i < n_atoms; i++){ | 
| 390 | > |  | 
| 391 | > | nobj = info->integrableObjects.size(); | 
| 392 | > | for(i = 0; i < nobj; i++){ | 
| 393 |  |  | 
| 394 | < | amass = atoms[i]->getMass(); | 
| 395 | < | atoms[i]->getPos( aPos ); | 
| 394 | > | amass = info->integrableObjects[i]->getMass(); | 
| 395 | > | info->integrableObjects[i]->getPos( aPos ); | 
| 396 |  |  | 
| 397 |  | for(j = 0; j < 3; j++) | 
| 398 |  | COM_local[j] += aPos[j] * amass; | 
| 414 |  | COM[i] = COM[i] / mtot; | 
| 415 |  | } | 
| 416 |  | } | 
| 417 | + |  | 
| 418 | + | void Thermo::removeCOMdrift() { | 
| 419 | + | double vdrift[3], aVel[3]; | 
| 420 | + | int vd, j, nobj; | 
| 421 | + |  | 
| 422 | + | nobj = info->integrableObjects.size(); | 
| 423 | + |  | 
| 424 | + | // Get the Center of Mass drift velocity. | 
| 425 | + |  | 
| 426 | + | getCOMVel(vdrift); | 
| 427 | + |  | 
| 428 | + | //  Corrects for the center of mass drift. | 
| 429 | + | // sums all the momentum and divides by total mass. | 
| 430 | + |  | 
| 431 | + | for(vd = 0; vd < nobj; vd++){ | 
| 432 | + |  | 
| 433 | + | info->integrableObjects[vd]->getVel(aVel); | 
| 434 | + |  | 
| 435 | + | for (j=0; j < 3; j++) | 
| 436 | + | aVel[j] -= vdrift[j]; | 
| 437 | + |  | 
| 438 | + | info->integrableObjects[vd]->setVel( aVel ); | 
| 439 | + | } | 
| 440 | + | } |