forked from lijiext/lammps
293 lines
9.3 KiB
C++
293 lines
9.3 KiB
C++
// ATC_Method headers
|
|
#include "MoleculeSet.h"
|
|
#include "ATC_Method.h"
|
|
#include "LammpsInterface.h"
|
|
#include "ATC_Error.h"
|
|
#include <queue>
|
|
#include <utility>
|
|
#include <sstream>
|
|
|
|
using std::multimap;
|
|
using std::map;
|
|
using std::pair;
|
|
using std::set;
|
|
using std::stringstream;
|
|
|
|
namespace ATC {
|
|
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
// Class MoleculeSet
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------
|
|
MoleculeSet::MoleculeSet(ATC_Method * atc, int groupBit) :
|
|
atc_(atc),
|
|
groupBit_(groupBit),
|
|
lammps_(atc->lammps_interface())
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// Destructor
|
|
//--------------------------------------------------------
|
|
MoleculeSet::~MoleculeSet()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// clear
|
|
//--------------------------------------------------------
|
|
void MoleculeSet::clear()
|
|
{
|
|
moleculeToAtoms_.clear();
|
|
localMoleculeToAtoms_.clear();
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// initialize
|
|
//--------------------------------------------------------
|
|
void MoleculeSet::initialize(map<int,double> * globalAtomsPerMolecule)
|
|
{
|
|
// determine the total number of molecules in this group
|
|
// essentially ripped Compute::molecules_in_group from lammps
|
|
|
|
// find lo/hi molecule ID for any atom in group
|
|
int i;
|
|
int *molecule = lammps_->atom_to_molecule();
|
|
const int *mask = lammps_->atom_mask();
|
|
int nlocal = lammps_->nlocal();
|
|
|
|
int lo = lammps_->natoms();
|
|
int hi = -1;
|
|
int flag = 0;
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (mask[i] & groupBit_) {
|
|
if (molecule[i] == 0) flag = 1;
|
|
lo = MIN(lo,molecule[i]);
|
|
hi = MAX(hi,molecule[i]);
|
|
}
|
|
}
|
|
|
|
int flagall;
|
|
lammps_->int_allsum(&flag,&flagall);
|
|
if (flagall) throw ATC_Error("Atom with molecule ID = 0 included in atc molecule group");
|
|
|
|
int globalLo, globalHi;
|
|
lammps_->int_allmin(&lo,&globalLo);
|
|
lammps_->int_allmax(&hi,&globalHi);
|
|
if (globalLo == lammps_->natoms()) throw ATC_Error("MoleculeSet:initialize - no molecules correspond to the group");
|
|
|
|
// molmap = vector of length nlen
|
|
// set to 1 for IDs that appear in group across all procs, else 0
|
|
|
|
int nlen = globalHi-globalLo+1;
|
|
int * localCount = new int[nlen];
|
|
for (i = 0; i < nlen; i++) localCount[i] = 0;
|
|
|
|
for (i = 0; i < nlocal; i++)
|
|
if (mask[i] & groupBit_)
|
|
localCount[molecule[i]-globalLo]++;
|
|
|
|
int * globalCount = new int[nlen];
|
|
lammps_->int_allsum(localCount,globalCount,nlen);
|
|
|
|
// nmolecules = # of non-zero IDs in molmap
|
|
// molmap[i] = index of molecule, skipping molecules not in group with -1
|
|
|
|
nMoleculesTotal_ = 0;
|
|
for (i = 0; i < nlen; i++)
|
|
if (globalCount[i]) nMoleculesTotal_++;
|
|
|
|
if (globalAtomsPerMolecule) {
|
|
for (i = 0; i < nlen; i++)
|
|
if (globalCount[i]) globalAtomsPerMolecule->insert(pair<int,double>(i+globalLo,double(globalCount[i])));
|
|
}
|
|
|
|
// deallocate storage
|
|
delete [] localCount;
|
|
delete [] globalCount;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// atoms_by_global_molecule
|
|
//--------------------------------------------------------
|
|
set<int> MoleculeSet::atoms_by_global_molecule(int id) const
|
|
{
|
|
if (need_reset()) reset();
|
|
typedef multimap<int, set<int> >::const_iterator MMIT;
|
|
typedef set<int>::const_iterator SIT;
|
|
pair<MMIT,MMIT> mol = moleculeToAtoms_.equal_range(id);
|
|
|
|
set<int> realAtoms;
|
|
const set<int> * myAtoms;
|
|
for (MMIT molIt = mol.first; molIt != mol.second; molIt++) {
|
|
myAtoms = &(molIt->second);
|
|
for (SIT atomIt = myAtoms->begin(); atomIt != myAtoms->end(); atomIt++)
|
|
realAtoms.insert(*atomIt);
|
|
}
|
|
return realAtoms;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// atoms_by_local_molecule
|
|
//--------------------------------------------------------
|
|
const set<int> & MoleculeSet::atoms_by_local_molecule(int id) const
|
|
{
|
|
if (need_reset()) reset();
|
|
return localMoleculeToAtoms_[id]->second;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// set_local_molecules_to_atoms
|
|
//--------------------------------------------------------
|
|
void MoleculeSet::set_local_molecules_to_atoms() const
|
|
{
|
|
localMoleculeToAtoms_.clear();
|
|
localMoleculeToAtoms_.reserve(moleculeToAtoms_.size());
|
|
multimap<int, set<int> >::const_iterator molecule;
|
|
for (molecule = moleculeToAtoms_.begin(); molecule != moleculeToAtoms_.end(); molecule++)
|
|
localMoleculeToAtoms_.push_back(molecule);
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
// Class SmallMoleculeSet
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------
|
|
SmallMoleculeSet::SmallMoleculeSet(ATC_Method * atc, int groupBit,
|
|
PerAtomQuantity<int> * bondList, PerAtomQuantity<int> * numBond) :
|
|
MoleculeSet(atc,groupBit),
|
|
bondList_(bondList)
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// Destructor
|
|
//--------------------------------------------------------
|
|
SmallMoleculeSet::~SmallMoleculeSet()
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// clear
|
|
//--------------------------------------------------------
|
|
void SmallMoleculeSet::clear()
|
|
{
|
|
MoleculeSet::clear();
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// initialize
|
|
//--------------------------------------------------------
|
|
void SmallMoleculeSet::initialize(std::map<int, double> * globalAtomsPerMolecule)
|
|
{
|
|
// make sure newton_bond is off, otherwise use large molecule set
|
|
if (lammps_->newton_bond())
|
|
throw ATC_Error("Cannot use newton_bond with small molecules");
|
|
|
|
MoleculeSet::initialize(globalAtomsPerMolecule);
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// reset
|
|
//--------------------------------------------------------
|
|
void SmallMoleculeSet::reset() const
|
|
{
|
|
stringstream message;
|
|
using std::queue;
|
|
moleculeToAtoms_.clear();
|
|
lammps_->forward_comm_fix();
|
|
int * numBond = lammps_->num_bond();
|
|
int ** bondAtom = lammps_->bond_atom();
|
|
|
|
// add in real atoms for molecules
|
|
int *molecule = lammps_->atom_to_molecule();
|
|
const int *mask = lammps_->atom_mask();
|
|
int nlocal = lammps_->nlocal();
|
|
_atomFound_.resize(atc_->nproc_ghost());
|
|
_atomFound_ = false;
|
|
int nmol = 0;
|
|
|
|
for (int i = 0; i < nlocal; i++) {
|
|
queue<int> myQueue;
|
|
if ((mask[i] & groupBit_) && !_atomFound_(i)) {
|
|
set<int> myAtoms;
|
|
myAtoms.insert(i);
|
|
_atomFound_(i) = true;
|
|
for (int j = 0; j < numBond[i]; j++) {
|
|
int localIdx = lammps_->local_to_global_map(bondAtom[i][j]);
|
|
if (!_atomFound_(localIdx)) {
|
|
myQueue.push(localIdx);
|
|
_atomFound_(localIdx) = true;
|
|
}
|
|
}
|
|
while (!myQueue.empty()) {
|
|
int myIdx = myQueue.front();
|
|
myQueue.pop();
|
|
myAtoms.insert(myIdx);
|
|
for (int j = 0; j < numBond[myIdx]; j++) {
|
|
int localIdx = lammps_->local_to_global_map(bondAtom[myIdx][j]);
|
|
if (!_atomFound_(localIdx)) {
|
|
myQueue.push(localIdx);
|
|
_atomFound_(localIdx) = true;
|
|
}
|
|
}
|
|
}
|
|
nmol++;
|
|
moleculeToAtoms_.insert(pair<int,set<int> >(molecule[i],myAtoms));
|
|
}
|
|
}
|
|
// set local molecule order
|
|
MoleculeSet::set_local_molecules_to_atoms();
|
|
needReset_ = false;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// atoms_by_global_molecule
|
|
//--------------------------------------------------------
|
|
set<int> SmallMoleculeSet::atoms_by_global_molecule(int id) const
|
|
{
|
|
// take all atoms and prune out ghosts
|
|
set<int> realAtoms = MoleculeSet::atoms_by_global_molecule(id);
|
|
remove_proc_ghosts(realAtoms);
|
|
return realAtoms;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// local_fraction
|
|
//--------------------------------------------------------
|
|
double SmallMoleculeSet::local_fraction(int id) const
|
|
{
|
|
if (need_reset()) reset();
|
|
set<int> realAtoms = (localMoleculeToAtoms_[id])->second;
|
|
int totalAtoms = realAtoms.size();
|
|
remove_proc_ghosts(realAtoms);
|
|
return double(realAtoms.size())/double(totalAtoms);
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// remove_proc_ghosts
|
|
//--------------------------------------------------------
|
|
void SmallMoleculeSet::remove_proc_ghosts(set<int> & atomSet) const
|
|
{
|
|
int nlocalIdx = lammps_->nlocal() - 1;
|
|
set<int>::const_iterator atomIt;
|
|
for (atomIt = atomSet.begin(); atomIt != atomSet.end(); atomIt++) {
|
|
if (*atomIt > nlocalIdx)
|
|
atomSet.erase(atomIt);
|
|
}
|
|
}
|
|
|
|
|
|
};
|