--- trunk/mdtools/md_code/Thermo.cpp 2002/09/24 22:10:55 117 +++ trunk/mdtools/md_code/Thermo.cpp 2003/02/03 21:15:59 261 @@ -1,11 +1,30 @@ #include +#include +using namespace std; +#ifdef IS_MPI +#include +#include +#endif //is_mpi + #include "Thermo.hpp" #include "SRI.hpp" #include "LRI.hpp" #include "Integrator.hpp" +#define BASE_SEED 123456789 +Thermo::Thermo( SimInfo* the_entry_plug ) { + entry_plug = the_entry_plug; + int baseSeed = BASE_SEED; + + gaussStream = new gaussianSPRNG( baseSeed ); +} + +Thermo::~Thermo(){ + delete gaussStream; +} + double Thermo::getKinetic(){ const double e_convert = 4.184E-4; // convert kcal/mol -> (amu A^2)/fs^2 @@ -17,12 +36,15 @@ double Thermo::getKinetic(){ DirectionalAtom *dAtom; int n_atoms; + double kinetic_global; Atom** atoms; + n_atoms = entry_plug->n_atoms; atoms = entry_plug->atoms; kinetic = 0.0; + kinetic_global = 0.0; for( kl=0; kl < n_atoms; kl++ ){ vx2 = atoms[kl]->get_vx() * atoms[kl]->get_vx(); @@ -44,7 +66,11 @@ double Thermo::getKinetic(){ + (jz2 / dAtom->getIzz()); } } - +#ifdef IS_MPI + MPI::COMM_WORLD.Allreduce(&kinetic,&kinetic_global,1,MPI_DOUBLE,MPI_SUM); + kinetic = kinetic_global; +#endif //is_mpi + kinetic = kinetic * 0.5 / e_convert; return kinetic; @@ -53,6 +79,7 @@ double Thermo::getPotential(){ double Thermo::getPotential(){ double potential; + double potential_global; int el, nSRI; SRI** sris; @@ -60,16 +87,21 @@ double Thermo::getPotential(){ nSRI = entry_plug->n_SRI; potential = 0.0; + potential_global = 0.0; + potential += entry_plug->lrPot; - potential += entry_plug->longRange->get_potential();; - // std::cerr << "long range potential: " << potential << "\n"; - for( el=0; elget_potential(); } + // Get total potential for entire system from MPI. +#ifdef IS_MPI + MPI::COMM_WORLD.Allreduce(&potential,&potential_global,1,MPI_DOUBLE,MPI_SUM); + potential = potential_global; +#endif // is_mpi + return potential; } @@ -145,7 +177,21 @@ void Thermo::velocitize() { // picks random velocities from a gaussian distribution // centered on vbar - +#ifndef USE_SPRNG + /* If we are using mpi, we need to use the SPRNG random + generator. The non drand48 generator will just repeat + the same numbers for every node creating a non-gaussian + distribution for the simulation. drand48 is fine for the + single processor version of the code, but SPRNG should + still be preferred for consistency. + */ + +#ifdef IS_MPI +#error "SPRNG random number generator must be used for MPI" +#else + // warning "Using drand48 for random number generation" +#endif // is_mpi + x = drand48(); y = drand48(); vx = vbar * sqrt( -2.0 * log(x)) * cos(2 * M_PI * y); @@ -157,7 +203,15 @@ void Thermo::velocitize() { x = drand48(); y = drand48(); vz = vbar * sqrt( -2.0 * log(x)) * cos(2 * M_PI * y); - + +#endif // use_spring + +#ifdef USE_SPRNG + vx = vbar * gaussStream->getGaussian(); + vy = vbar * gaussStream->getGaussian(); + vz = vbar * gaussStream->getGaussian(); +#endif // use_spring + atoms[vr]->set_vx( vx ); atoms[vr]->set_vy( vy ); atoms[vr]->set_vz( vz ); @@ -205,6 +259,14 @@ void Thermo::velocitize() { if( atoms[i]->isDirectional() ){ dAtom = (DirectionalAtom *)atoms[i]; + +#ifndef USE_SPRNG + +#ifdef IS_MPI +#error "SPRNG random number generator must be used for MPI" +#else // is_mpi + //warning "Using drand48 for random number generation" +#endif // is_MPI vbar = sqrt( 2.0 * kebar * dAtom->getIxx() ); x = drand48(); @@ -220,6 +282,18 @@ void Thermo::velocitize() { x = drand48(); y = drand48(); jz = vbar * sqrt( -2.0 * log(x)) * cos(2 * M_PI * y); + +#else //use_sprng + + vbar = sqrt( 2.0 * kebar * dAtom->getIxx() ); + jx = vbar * gaussStream->getGaussian(); + + vbar = sqrt( 2.0 * kebar * dAtom->getIyy() ); + jy = vbar * gaussStream->getGaussian(); + + vbar = sqrt( 2.0 * kebar * dAtom->getIzz() ); + jz = vbar * gaussStream->getGaussian(); +#endif //use_sprng dAtom->setJx( jx ); dAtom->setJy( jy );