ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/Thermo.cpp
(Generate patch)

Comparing trunk/src/brains/Thermo.cpp (file contents):
Revision 1442 by gezelter, Mon May 10 17:28:26 2010 UTC vs.
Revision 1638 by chuckv, Fri Sep 23 20:52:24 2011 UTC

# Line 237 | Line 237 | namespace OpenMD {
237      stat[Stats::PRESSURE_TENSOR_ZX] = tensor(2, 0);      
238      stat[Stats::PRESSURE_TENSOR_ZY] = tensor(2, 1);      
239      stat[Stats::PRESSURE_TENSOR_ZZ] = tensor(2, 2);      
240 <
240 >    Vector3d GKappa_t = getThermalHelfand();
241 >    stat[Stats::THERMAL_HELFANDMOMENT_X] = GKappa_t.x();
242 >    stat[Stats::THERMAL_HELFANDMOMENT_Y] = GKappa_t.y();
243 >    stat[Stats::THERMAL_HELFANDMOMENT_Z] = GKappa_t.z();
244  
245      Globals* simParams = info_->getSimParams();
246  
# Line 303 | Line 306 | namespace OpenMD {
306      //Conserved Quantity is set by integrator and time is set by setTime
307      
308    }
309 +
310 +
311 +
312 + Vector3d Thermo::getBoxDipole() {
313 +    Snapshot* currSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
314 +    SimInfo::MoleculeIterator miter;
315 +    std::vector<Atom*>::iterator aiter;
316 +    Molecule* mol;
317 +    Atom* atom;
318 +    RealType charge;
319 +    RealType moment(0.0);
320 +    Vector3d ri(0.0);
321 +    Vector3d dipoleVector(0.0);
322 +    Vector3d nPos(0.0);
323 +    Vector3d pPos(0.0);
324 +    RealType nChg(0.0);
325 +    RealType pChg(0.0);
326 +    int nCount = 0;
327 +    int pCount = 0;
328 +
329 +    RealType chargeToC = 1.60217733e-19;
330 +    RealType angstromToM = 1.0e-10;    RealType debyeToCm = 3.33564095198e-30;
331 +
332 +    for (mol = info_->beginMolecule(miter); mol != NULL;
333 +         mol = info_->nextMolecule(miter)) {
334 +
335 +      for (atom = mol->beginAtom(aiter); atom != NULL;
336 +           atom = mol->nextAtom(aiter)) {
337 +
338 +        if (atom->isCharge() ) {
339 +          charge = 0.0;
340 +          GenericData* data = atom->getAtomType()->getPropertyByName("Charge");
341 +          if (data != NULL) {
342 +
343 +            charge = (dynamic_cast<DoubleGenericData*>(data))->getData();
344 +            charge *= chargeToC;
345 +
346 +            ri = atom->getPos();
347 +            currSnapshot->wrapVector(ri);
348 +            ri *= angstromToM;
349 +
350 +            if (charge < 0.0) {
351 +              nPos += ri;
352 +              nChg -= charge;
353 +              nCount++;
354 +            } else if (charge > 0.0) {
355 +              pPos += ri;
356 +              pChg += charge;
357 +              pCount++;
358 +            }
359 +          }
360 +        }
361  
362 +        if (atom->isDipole() ) {
363 +          Vector3d u_i = atom->getElectroFrame().getColumn(2);
364 +          GenericData* data = dynamic_cast<DirectionalAtomType*>(atom->getAtomType())->getPropertyByName("Dipole");
365 +          if (data != NULL) {
366 +            moment = (dynamic_cast<DoubleGenericData*>(data))->getData();
367 +
368 +            moment *= debyeToCm;
369 +            dipoleVector += u_i * moment;
370 +          }
371 +        }
372 +      }
373 +    }
374 +
375 +
376 + #ifdef IS_MPI
377 +    RealType pChg_global, nChg_global;
378 +    int pCount_global, nCount_global;
379 +    Vector3d pPos_global, nPos_global, dipVec_global;
380 +
381 +    MPI_Allreduce(&pChg, &pChg_global, 1, MPI_REALTYPE, MPI_SUM,
382 +                  MPI_COMM_WORLD);
383 +    pChg = pChg_global;
384 +    MPI_Allreduce(&nChg, &nChg_global, 1, MPI_REALTYPE, MPI_SUM,
385 +                  MPI_COMM_WORLD);
386 +    nChg = nChg_global;
387 +    MPI_Allreduce(&pCount, &pCount_global, 1, MPI_INTEGER, MPI_SUM,
388 +                  MPI_COMM_WORLD);
389 +    pCount = pCount_global;
390 +    MPI_Allreduce(&nCount, &nCount_global, 1, MPI_INTEGER, MPI_SUM,
391 +                  MPI_COMM_WORLD);
392 +    nCount = nCount_global;
393 +    MPI_Allreduce(pPos.getArrayPointer(), pPos_global.getArrayPointer(), 3,
394 +                  MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
395 +    pPos = pPos_global;
396 +    MPI_Allreduce(nPos.getArrayPointer(), nPos_global.getArrayPointer(), 3,
397 +                  MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
398 +    nPos = nPos_global;
399 +    MPI_Allreduce(dipoleVector.getArrayPointer(),
400 +                  dipVec_global.getArrayPointer(), 3,
401 +                  MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
402 +    dipoleVector = dipVec_global;
403 + #endif //is_mpi
404 +
405 +    // first load the accumulated dipole moment (if dipoles were present)
406 +    Vector3d boxDipole = dipoleVector;
407 +    // now include the dipole moment due to charges
408 +    // use the lesser of the positive and negative charge totals
409 +    RealType chg_value = nChg <= pChg ? nChg : pChg;
410 +
411 +    // find the average positions
412 +    if (pCount > 0 && nCount > 0 ) {
413 +      pPos /= pCount;
414 +      nPos /= nCount;
415 +    }
416 +
417 +    // dipole is from the negative to the positive (physics notation)
418 +    boxDipole += (pPos - nPos) * chg_value;
419 +
420 +    return boxDipole;
421 +  }
422 +
423 + Vector3d Thermo::getThermalHelfand() {
424 +    Snapshot* currSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
425 +    SimInfo::MoleculeIterator miter;
426 +    std::vector<Atom*>::iterator aiter;
427 +    Molecule* mol;
428 +    Atom* atom;
429 +    RealType mass;
430 +    Vector3d velocity;
431 +    Vector3d x_a;
432 +    RealType kinetic;
433 +    RealType potential;
434 +    RealType eatom;
435 +    RealType AvgE_a_ = 0;
436 +    Vector3d GKappa_t = V3Zero;
437 +    Vector3d ThermalHelfandMoment;
438 +    
439 +    for (mol = info_->beginMolecule(miter); mol != NULL;
440 +         mol = info_->nextMolecule(miter)) {
441 +
442 +      for (atom = mol->beginAtom(aiter); atom != NULL;
443 +           atom = mol->nextAtom(aiter)) {
444 +
445 +        mass = atom->getMass();
446 +        velocity = atom->getVel();
447 +        kinetic = mass * (velocity[0]*velocity[0] + velocity[1]*velocity[1] +
448 +                                   velocity[2]*velocity[2]) / PhysicalConstants::energyConvert;
449 +        potential =  atom->getParticlePot();
450 +        eatom += (kinetic + potential)/2.0;
451 +      }
452 +    }
453 +
454 +   int natoms = info_->getNGlobalAtoms();
455 + #ifdef IS_MPI
456 +    
457 +    MPI_Allreduce(&eatom, &AvgE_a_, 1, MPI_REALTYPE, MPI_SUM,
458 +                  MPI_COMM_WORLD);
459 + #else    
460 +    AvgE_a_ = eatom;
461 + #endif
462 +    AvgE_a_ = AvgE_a_/RealType(natoms);
463 +    
464 +    for (mol = info_->beginMolecule(miter); mol != NULL;
465 +         mol = info_->nextMolecule(miter)) {
466 +      
467 +      for (atom = mol->beginAtom(aiter); atom != NULL;
468 +           atom = mol->nextAtom(aiter)) {
469 +        
470 +        /* We think that x_a is relative to the total box and should be a wrapped coordinate */
471 +        x_a = atom->getPos();
472 +        currSnapshot->wrapVector(x_a);
473 +        potential =  atom->getParticlePot();
474 +
475 +        GKappa_t += x_a*(potential-AvgE_a_);
476 +        }
477 +      }
478 + #ifdef IS_MPI
479 +     MPI_Allreduce(GKappa_t.getArrayPointer(), ThermalHelfandMoment.getArrayPointer(), 3,
480 +                  MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
481 + #else    
482 +     ThermalHelfandMoment = GKappa_t;
483 + #endif  
484 +     return ThermalHelfandMoment;
485 +    
486 + }
487 +
488 +
489 +
490   } //end namespace OpenMD

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines