Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2020 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : plumed is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 : #include "NeighborList.h"
23 : #include "Vector.h"
24 : #include "Pbc.h"
25 : #include "AtomNumber.h"
26 : #include "Tools.h"
27 : #include <vector>
28 : #include <algorithm>
29 :
30 : namespace PLMD {
31 : using namespace std;
32 :
33 207 : NeighborList::NeighborList(const vector<AtomNumber>& list0, const vector<AtomNumber>& list1,
34 : const bool& do_pair, const bool& do_pbc, const Pbc& pbc,
35 207 : const double& distance, const unsigned& stride): reduced(false),
36 414 : do_pair_(do_pair), do_pbc_(do_pbc), pbc_(&pbc),
37 828 : distance_(distance), stride_(stride)
38 : {
39 : // store full list of atoms needed
40 207 : fullatomlist_=list0;
41 207 : fullatomlist_.insert(fullatomlist_.end(),list1.begin(),list1.end());
42 207 : nlist0_=list0.size();
43 207 : nlist1_=list1.size();
44 207 : twolists_=true;
45 207 : if(!do_pair) {
46 184 : nallpairs_=nlist0_*nlist1_;
47 : } else {
48 23 : plumed_assert(nlist0_==nlist1_) << "when using PAIR option, the two groups should have the same number of elements\n"
49 0 : << "the groups you specified have size "<<nlist0_<<" and "<<nlist1_;
50 23 : nallpairs_=nlist0_;
51 : }
52 207 : initialize();
53 207 : lastupdate_=0;
54 207 : }
55 :
56 39 : NeighborList::NeighborList(const vector<AtomNumber>& list0, const bool& do_pbc,
57 : const Pbc& pbc, const double& distance,
58 39 : const unsigned& stride): reduced(false),
59 39 : do_pbc_(do_pbc), pbc_(&pbc),
60 117 : distance_(distance), stride_(stride) {
61 39 : fullatomlist_=list0;
62 39 : nlist0_=list0.size();
63 39 : twolists_=false;
64 39 : nallpairs_=nlist0_*(nlist0_-1)/2;
65 39 : initialize();
66 39 : lastupdate_=0;
67 39 : }
68 :
69 246 : void NeighborList::initialize() {
70 246 : neighbors_.clear();
71 85457990 : for(unsigned int i=0; i<nallpairs_; ++i) {
72 85457744 : neighbors_.push_back(getIndexPair(i));
73 : }
74 246 : }
75 :
76 69887 : vector<AtomNumber>& NeighborList::getFullAtomList() {
77 69887 : return fullatomlist_;
78 : }
79 :
80 48534103 : pair<unsigned,unsigned> NeighborList::getIndexPair(unsigned ipair) {
81 : pair<unsigned,unsigned> index;
82 48534103 : if(twolists_ && do_pair_) {
83 634 : index=pair<unsigned,unsigned>(ipair,ipair+nlist0_);
84 48533469 : } else if (twolists_ && !do_pair_) {
85 8209023 : index=pair<unsigned,unsigned>(ipair/nlist1_,ipair%nlist1_+nlist0_);
86 40324446 : } else if (!twolists_) {
87 40324446 : unsigned ii = nallpairs_-1-ipair;
88 40324446 : unsigned K = unsigned(floor((sqrt(double(8*ii+1))+1)/2));
89 40324446 : unsigned jj = ii-K*(K-1)/2;
90 40324446 : index=pair<unsigned,unsigned>(nlist0_-1-K,nlist0_-1-jj);
91 : }
92 48534103 : return index;
93 : }
94 :
95 137 : void NeighborList::update(const vector<Vector>& positions) {
96 137 : neighbors_.clear();
97 137 : const double d2=distance_*distance_;
98 : // check if positions array has the correct length
99 137 : plumed_assert(positions.size()==fullatomlist_.size());
100 11610599 : for(unsigned int i=0; i<nallpairs_; ++i) {
101 5805231 : pair<unsigned,unsigned> index=getIndexPair(i);
102 5805231 : unsigned index0=index.first;
103 5805231 : unsigned index1=index.second;
104 5805231 : Vector distance;
105 5805231 : if(do_pbc_) {
106 17415693 : distance=pbc_->distance(positions[index0],positions[index1]);
107 : } else {
108 0 : distance=delta(positions[index0],positions[index1]);
109 : }
110 5805231 : double value=modulo2(distance);
111 5805231 : if(value<=d2) {neighbors_.push_back(index);}
112 : }
113 137 : setRequestList();
114 137 : }
115 :
116 137 : void NeighborList::setRequestList() {
117 137 : requestlist_.clear();
118 11518377 : for(unsigned int i=0; i<size(); ++i) {
119 17277360 : requestlist_.push_back(fullatomlist_[neighbors_[i].first]);
120 11518240 : requestlist_.push_back(fullatomlist_[neighbors_[i].second]);
121 : }
122 137 : Tools::removeDuplicates(requestlist_);
123 137 : reduced=false;
124 137 : }
125 :
126 19 : vector<AtomNumber>& NeighborList::getReducedAtomList() {
127 638 : if(!reduced)for(unsigned int i=0; i<size(); ++i) {
128 : unsigned newindex0=0,newindex1=0;
129 1857 : AtomNumber index0=fullatomlist_[neighbors_[i].first];
130 1238 : AtomNumber index1=fullatomlist_[neighbors_[i].second];
131 : // I exploit the fact that requestlist_ is an ordered vector
132 1857 : auto p = std::find(requestlist_.begin(), requestlist_.end(), index0); plumed_assert(p!=requestlist_.end()); newindex0=p-requestlist_.begin();
133 1857 : p = std::find(requestlist_.begin(), requestlist_.end(), index1); plumed_assert(p!=requestlist_.end()); newindex1=p-requestlist_.begin();
134 : neighbors_[i]=pair<unsigned,unsigned>(newindex0,newindex1);
135 : }
136 19 : reduced=true;
137 19 : return requestlist_;
138 : }
139 :
140 6153 : unsigned NeighborList::getStride() const {
141 6153 : return stride_;
142 : }
143 :
144 0 : unsigned NeighborList::getLastUpdate() const {
145 0 : return lastupdate_;
146 : }
147 :
148 0 : void NeighborList::setLastUpdate(unsigned step) {
149 0 : lastupdate_=step;
150 0 : }
151 :
152 23186435 : unsigned NeighborList::size() const {
153 23186435 : return neighbors_.size();
154 : }
155 :
156 31055812 : pair<unsigned,unsigned> NeighborList::getClosePair(unsigned i) const {
157 62111624 : return neighbors_[i];
158 : }
159 :
160 34665936 : pair<AtomNumber,AtomNumber> NeighborList::getClosePairAtomNumber(unsigned i) const {
161 : pair<AtomNumber,AtomNumber> Aneigh;
162 103997808 : Aneigh=pair<AtomNumber,AtomNumber>(fullatomlist_[neighbors_[i].first],fullatomlist_[neighbors_[i].second]);
163 34665936 : return Aneigh;
164 : }
165 :
166 0 : vector<unsigned> NeighborList::getNeighbors(unsigned index) {
167 : vector<unsigned> neighbors;
168 0 : for(unsigned int i=0; i<size(); ++i) {
169 0 : if(neighbors_[i].first==index) neighbors.push_back(neighbors_[i].second);
170 0 : if(neighbors_[i].second==index) neighbors.push_back(neighbors_[i].first);
171 : }
172 0 : return neighbors;
173 : }
174 :
175 : }
|