ParM  parm
A molecular dynamics library
constraints.hpp
Go to the documentation of this file.
1 #include "interaction.hpp"
2 
3 #ifndef CONSTRAINTS_H
4 #define CONSTRAINTS_H
5 
6 #include <vector>
7 #include <list>
8 #include <set>
9 #include <map>
10 #include <queue>
11 #include <complex>
12 
13 using namespace std;
14 
15 class Constraint {
16  public:
17  virtual void apply_positions(Box &box) = 0;
18  virtual void apply_velocities(Box &box) = 0;
19  virtual void apply_forces(Box &box) = 0;
20  virtual int constrained_dof() = 0;
21  virtual ~Constraint(){};
22 };
23 
24 class CoordConstraint : public Constraint {
25  private:
26  Atom* a;
27  bool fixed[3];
28  Vec loc;
29  public:
30  CoordConstraint(Atom* atm, bool fixx, bool fixy, bool fixz, Vec loc) :
31  a(atm), loc(loc) {fixed[0] = fixx; fixed[1] = fixy; fixed[2] = fixz;};
32  CoordConstraint(Atom* atm, bool fixx, bool fixy, bool fixz) :
33  a(atm), loc(a->x) {fixed[0] = fixx; fixed[1] = fixy; fixed[2] = fixz;};
35  a(atm), loc(a->x) {fixed[0] = fixed[1] = fixed[2] = true;};
36  int constrained_dof(){return (int)fixed[0] + (int)fixed[1] + (int)fixed[2];};
37  void apply_positions(Box &box){
38  for(uint i=0; i<3; i++){
39  if(not fixed[i]) continue;
40  a->x[i] = loc[i];
41  }
42  }
43  void apply_velocities(Box &box){
44  for(uint i=0; i<3; i++){
45  if(not fixed[i]) continue;
46  a->v[i] = 0;
47  }
48  }
49  void apply_forces(Box &box){
50  for(uint i=0; i<3; i++){
51  if(not fixed[i]) continue;
52  a->f[i] = 0;
53  }
54  }
55 };
56 
58  private:
59  sptr<AtomGroup> a;
60  bool fixed[3];
61  Vec loc;
62  public:
63  CoordCOMConstraint(sptr<AtomGroup> atm, bool fixx, bool fixy, bool fixz, Vec loc) :
64  a(atm), loc(loc) {fixed[0] = fixx; fixed[1] = fixy; fixed[2] = fixz;};
65  CoordCOMConstraint(sptr<AtomGroup> atm, bool fixx, bool fixy, bool fixz) :
66  a(atm), loc(a->com()) {fixed[0] = fixx; fixed[1] = fixy; fixed[2] = fixz;};
67  CoordCOMConstraint(sptr<AtomGroup> atm) :
68  a(atm), loc(a->com()) {fixed[0] = fixed[1] = fixed[2] = true;};
69  int constrained_dof(){return (int)fixed[0] + (int)fixed[1] + (int)fixed[2];};
70  void apply_positions(Box &box);
71  void apply_velocities(Box &box);
72  void apply_forces(Box &box);
73 };
74 
76  private:
77  Atom *a1, *a2;
78  bool fixed[3];
79  Vec loc;
80  public:
81  RelativeConstraint(Atom* atm1, Atom* atm2, bool fixx, bool fixy, bool fixz, Vec loc) :
82  a1(atm1), a2(atm2), loc(loc) {
83  fixed[0] = fixx; fixed[1] = fixy; fixed[2] = fixz;};
84  RelativeConstraint(Atom* atm1, Atom* atm2, bool fixx, bool fixy, bool fixz) :
85  a1(atm1), a2(atm2), loc(a2->x - a1->x) {
86  fixed[0] = fixx; fixed[1] = fixy; fixed[2] = fixz;};
87  RelativeConstraint(Atom* atm1, Atom* atm2) :
88  a1(atm1), a2(atm2), loc(a2->x - a1->x) {
89  fixed[0] = fixed[1] = fixed[2] = true;};
90  int constrained_dof(){return (int)fixed[0] + (int)fixed[1] + (int)fixed[2];};
91 
92  void apply_positions(Box &box);
93  void apply_velocities(Box &box);
94  void apply_forces(Box &box);
95 };
96 
97 class DistConstraint : public Constraint {
98  private:
99  AtomID a1, a2;
100  flt dist;
101  public:
102  DistConstraint(AtomID atm1, AtomID atm2, flt dist) :
103  a1(atm1), a2(atm2), dist(dist) {};
105  a1(atm1), a2(atm2), dist((a1->x - a2->x).norm()){};
106  int constrained_dof(){return 1;};
107  void apply_positions(Box &box);
108  void apply_velocities(Box &box);
109  void apply_forces(Box &box);
110 };
111 
112 
113 class LinearConstraint : public Constraint {
114  private:
115  sptr<AtomGroup> atms;
116  flt dist;
117  flt lincom, I, M;
118  Vec lvec, com;
119 
120  void set_lvec_com();
121  public:
122  LinearConstraint(sptr<AtomGroup> atms, flt dist) :
123  atms(atms), dist(dist), lincom(0), I(0), M(0), lvec(Vec::Zero()), com(Vec::Zero()) {
124  for(uint i = 0; i < atms->size(); i++){
125  M += (*atms)[i].m;
126  lincom += (dist*i)*(*atms)[i].m;
127  }
128  lincom /= M;
129 
130  for(uint i = 0; i < atms->size(); i++){
131  flt dx = (dist*i - lincom);
132  I += (*atms)[i].m * dx * dx;
133  }
134 
135  set_lvec_com();
136  };
137  int constrained_dof(){return (int)atms->size()-1;};
138  void apply_positions(Box &box);
139  void apply_velocities(Box &box);
140  void apply_forces(Box &box);
141 };
142 
143 #ifdef VEC3D
144 class RigidConstraint : public Constraint {
146  private:
147  sptr<AtomGroup> atms;
148  flt M;
149 
150  // moment of inertia matrix
151  Matrix MoI;
152  // moment of inertia matrix inverse
153  Eigen::JacobiSVD<Matrix> MoI_solver;
154  // locations relative to center of mass, no rotation
155  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> expected;
156 
157  // updated at every apply_positions()
158  // Curent rotation matrix
159  Matrix rot;
160  // center of mass
161  Vec com;
162  // Angular velocity, acceleration
163  Vec omega, alpha;
164 
165  public:
166  RigidConstraint(sptr<Box> box, sptr<AtomGroup> atms);
167 
168  //TODO: should probably handle cases with atms.size() < 3
169  int constrained_dof(){return (int)atms->size() * NDIM-6;};
170 
171  void apply_positions(Box &box);
172  void apply_velocities(Box &box);
173  void apply_forces(Box &box);
174  Matrix get_rotation();
175  Matrix get_MoI(){return MoI;};
176 };
177 #endif
178 
180  protected:
181  sptr<AtomGroup> atoms;
182  vector<flt> dists;
183  vector<vector<bool> > contacts;
184 
185  unsigned long long breaks;
186  unsigned long long formations;
187  unsigned long long incontact;
188  public:
189  ContactTracker(sptr<Box> box, sptr<AtomGroup> atoms, vector<flt> dists);
190  void update(Box &box);
191 
192  void reset(){
193  breaks=0;
194  formations=0;
195  incontact=0;
196  uint N = atoms->size();
197  contacts.resize(N);
198  for(uint i=0; i<N; ++i){
199  contacts[i].assign(i, false);
200  }
201  };
202  unsigned long long broken(){return breaks;};
203  unsigned long long formed(){return formations;};
204  unsigned long long number(){return incontact;};
205 };
206 
207 inline ContactTracker* ContactTrackerD(sptr<Box> box, sptr<AtomGroup> atoms, vector<double> dists){
208  vector<flt> newdists = vector<flt>();
209  for(uint i=0; i<dists.size(); i++){
210  newdists.push_back(dists[i]);
211  }
212  return new ContactTracker(box, atoms, newdists);
213 }
214 
216  protected:
217  sptr<AtomGroup> atoms;
218  vector<sptr<Interaction> > interactions;
219 
221  uint n_skip, n_skipped;
223  flt Es, Us, Ks;
224  flt Esq, Usq, Ksq;
225  public:
226  EnergyTracker(sptr<AtomGroup> atoms,
227  vector<sptr<Interaction> > interactions, uint n_skip=1)
228  : atoms(atoms),
229  interactions(interactions), N(0), n_skip(max(n_skip,1u)), n_skipped(0),
230  U0(0),Es(0),Us(0),Ks(0), Esq(0), Usq(0), Ksq(0){};
231  void update(Box &box);
232  void reset(){
233  n_skipped=0;
234  N=0; Es=0; Us=0; Ks=0;
235  Esq=0; Usq=0; Ksq=0;
236  };
237  void set_U0(flt newU0){
238  U0 = newU0;
239  reset();
240  };
241  void set_U0(Box &box);
242  flt get_U0(){return U0;};
243 
244  flt E(){return Es/((flt) N);};
245  flt U(){return Us/((flt) N);};
246  flt K(){return Ks/((flt) N);};
247  flt E_std(){return sqrt(Esq/N -Es*Es/N/N);};
248  flt K_std(){return sqrt(Ksq/N -Ks*Ks/N/N);};
249  flt U_std(){return sqrt(Usq/N -Us*Us/N/N);};
250  flt E_squared_mean(){return Esq/N;};
251  flt K_squared_mean(){return Ksq/N;};
252  flt U_squared_mean(){return Usq/N;};
253  //~ flt U_std(){return sqrt((Usq -(U*U)) / ((flt) N));};
254  //~ flt K_std(){return sqrt((Ksq -(K*K)) / ((flt) N));};
255  uint n(){return N;};
256 };
257 
258 class RsqTracker1 {
259  // Tracks only a single dt (skip)
260  public:
261  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> pastlocs;
262  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> xyz2sums;
263  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> xyz4sums;
264  vector<flt> r4sums;
265  unsigned long skip, count;
266 
267  public:
268  RsqTracker1(AtomGroup& atoms, unsigned long skip, Vec com);
269 
270  void reset(AtomGroup& atoms, Vec com);
271 
272  bool update(Box& box, AtomGroup& atoms, unsigned long t, Vec com); // updates if necessary.
273  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> xyz2();
274  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> xyz4();
275  vector<flt> r4();
276 
277  unsigned long get_skip(){return skip;};
278  unsigned long get_count(){return count;};
279 };
280 
281 class RsqTracker : public StateTracker {
282  public:
283  sptr<AtomGroup> atoms;
284  vector<RsqTracker1> singles;
285  unsigned long curt;
286  bool usecom;
287 
288  public:
289  RsqTracker(sptr<AtomGroup> atoms, vector<unsigned long> ns, bool usecom=true);
290 
291  void reset();
292  void update(Box &box);
293 
294  vector<Eigen::Matrix<flt, Eigen::Dynamic, NDIM> > xyz2();
295  vector<vector<flt> > r2();
296  vector<Eigen::Matrix<flt, Eigen::Dynamic, NDIM> > xyz4();
297  vector<vector<flt> > r4();
298  vector<flt> counts();
299 };
300 
302 // ISF tracking
303 // code is similar to Rsqtracker.
304 // It tracks ISF(k, Δt) with one ISFTracker1 per Δt.
305 // k is of type 'flt', representing a length; it will average over
306 // k(x hat), k(y hat), k(z hat).
307 
308 class ISFTracker1 {
309  // Tracks only a single dt (skip)
310  public:
311  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> pastlocs;
312  vector<vector<array<cmplx, NDIM> > > ISFsums; // (number of ks x number of particles x number of dimensions)
313  vector<flt> ks;
314  unsigned long skip, count;
315 
316  public:
317  ISFTracker1(AtomGroup& atoms, unsigned long skip, vector<flt> ks, Vec com);
318 
319  void reset(AtomGroup& atoms, Vec com);
320 
321  bool update(Box& box, AtomGroup& atoms, unsigned long t, Vec com); // updates if necessary.
322  vector<vector<cmplx> > ISFs();
323  vector<vector<array<cmplx, NDIM> > > ISFxyz();
324 
325  unsigned long get_skip(){return skip;};
326  unsigned long get_count(){return count;};
327 };
328 
329 class ISFTracker : public StateTracker {
330  public:
331  sptr<AtomGroup> atoms;
332  vector<ISFTracker1> singles;
333  unsigned long curt;
334  bool usecom;
335 
336  public:
337  ISFTracker(sptr<AtomGroup> atoms, vector<flt> ks,
338  vector<unsigned long> ns, bool usecom=false);
339 
340  void reset();
341  void update(Box &box);
342 
343  vector<vector<vector<array<cmplx, NDIM> > > > ISFxyz();
344  vector<vector<vector<cmplx> > > ISFs();
345  vector<flt> counts();
346 };
347 
349 // Get the "smoothed" version of each particles location, "smoothed" over windows of a given size
350 
351 class SmoothLocs : public StateTracker {
352  public:
353  sptr<AtomGroup> atoms;
354  uint smoothn; // number of skipns to "smooth" over
355  uint skipn; // number of dts to skip
356  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> curlocs;
358  vector<Eigen::Matrix<flt, Eigen::Dynamic, NDIM> > locs;
359  unsigned long curt;
360  bool usecom;
361 
362  public:
363  SmoothLocs(sptr<AtomGroup> atoms, Box &box, uint smoothn, uint skipn=1, bool usecom=false);
364 
365  void reset();
366  void update(Box &box);
367 
368  vector<Eigen::Matrix<flt, Eigen::Dynamic, NDIM> > smooth_locs(){return locs;};
369 };
370 
372 class RDiffs : public StateTracker {
373  // Tracks only a single dt (skip)
374  public:
375  sptr<AtomGroup> atoms;
376  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> pastlocs;
377  vector<vector<flt> > dists;
378  unsigned long skip;
379  unsigned long curt;
380  bool usecom;
381  public:
382  RDiffs(sptr<AtomGroup> atoms, unsigned long skip, bool usecom=false);
383 
384  void reset();
385 
386  void update(Box& box); // updates if necessary.
387  vector<vector<flt> > rdiffs(){return dists;};
388 
389  unsigned long get_skip(){return skip;};
390 };
391 
393 // For comparing two jammed structures
394 
395 /* We have two packings, A and B, and want to know the sequence {A1, A2, A3...}
396  * such that particle A1 of packing 1 matches particle 1 of packing B.
397  * A JammingList is a partial list; it has a list {A1 .. An}, with n / N
398  * particles assigned, with a total distance² of distance_squared.
399 */
400 class JammingList {
401  public:
402  vector<uint> assigned;
404 
405  JammingList() : assigned(), distance_squared(0){};
406  JammingList(const JammingList& other)
407  : assigned(other.assigned), distance_squared(other.distance_squared){};
408  JammingList(const JammingList& other, uint expand, flt addeddist)
409  : assigned(other.size() + 1, 0), distance_squared(other.distance_squared + addeddist){
410  for(uint i=0; i < other.size(); i++){
411  assigned[i] = other.assigned[i];
412  }
413  assigned[assigned.size()-1] = expand;
414  }
415  inline uint size() const {return (uint) assigned.size();};
416 
417  bool operator<(const JammingList& other) const;
418 };
419 
424 class JammingTree {
425  private:
426  sptr<Box> box;
427  list<JammingList> jlists;
428  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> A;
429  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> B;
430  public:
431  JammingTree(sptr<Box> box, Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& A, Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& B)
432  : box(box), jlists(), A(A), B(B) {
433  jlists.push_back(JammingList());
434  assert(A.size() <= B.size());
435  };
436 
437  bool expand(){
438  JammingList curjlist = jlists.front();
439  vector<uint>& curlist = curjlist.assigned;
440  if(curlist.size() >= (uint) A.rows()){
441  //~ cout << "List already too big\n";
442  return false;
443  }
444 
445  list<JammingList> newlists = list<JammingList>();
446  for(uint i=0; i < B.size(); i++){
447  vector<uint>::iterator found = find(curlist.begin(), curlist.end(), i);
448  //if (find(curlist.begin(), curlist.end(), i) != curlist.end()){
449  if (found != curlist.end()){
450  //~ cout << "Found " << i << "\n";
451  //cout << found << '\n';
452  continue;
453  }
454  flt newdist = box->diff(A.row(curlist.size()), B.row(i)).squaredNorm();
455  JammingList newjlist = JammingList(curjlist, i, newdist);
456  newlists.push_back(newjlist);
457  //~ cout << "Made " << i << "\n";
458  }
459 
460  if(newlists.empty()){
461  //~ cout << "No lists made\n";
462  return false;
463  }
464  //~ cout << "Have " << newlists.size() << "\n";
465  newlists.sort();
466  //~ cout << "Sorted.\n";
467  jlists.pop_front();
468  //~ cout << "Popped.\n";
469  jlists.merge(newlists);
470  //~ cout << "Merged to size " << jlists.size() << "best dist now " << jlists.front().distance_squared << "\n";
471  return true;
472  }
473  bool expand(uint n){
474  bool retval=false;
475  for(uint i=0; i<n; i++){
476  retval = expand();
477  }
478  return retval;
479  }
480  list<JammingList> &my_list(){return jlists;};
481  list<JammingList> copy_list(){return jlists;};
482 
484  JammingList j = JammingList(jlists.front());
485  //~ cout << "Best size: " << j.size() << " dist: " << j.distance_squared;
486  //~ if(j.size() > 0) cout << " Elements: [" << j.assigned[0] << ", " << j.assigned[j.size()-1] << "]";
487  //~ cout << '\n';
488  return j;
489  //return JammingList(jlists.front());
490  };
491  uint size(){return (uint) jlists.size();};
492 };
493 
494 class JammingListRot : public JammingList {
495  public:
497 
498  JammingListRot() : JammingList(), rotation(0){};
499  JammingListRot(uint rot) : JammingList(), rotation(rot){};
501  : JammingList(other), rotation(other.rotation){};
502  JammingListRot(const JammingListRot& other, uint expand, flt addeddist)
503  : JammingList(other, expand, addeddist), rotation(other.rotation){};
504 
505  bool operator<(const JammingListRot& other) const;
506 };
507 
508 // Includes rotations, flips, and translations.
510  protected:
511  sptr<Box> box;
512  list<JammingListRot> jlists;
513  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> A;
514  vector<Eigen::Matrix<flt, Eigen::Dynamic, NDIM> > Bs;
515  public:
516  // make all 8 possible rotations / flips
517  // then subtract off all possible COMVs
518  JammingTreeRot(sptr<Box>box, Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& A, Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& B, bool use_rotations=true, bool use_inversions=true);
519  flt distance(JammingListRot& jlist);
520  list<JammingListRot> expand(JammingListRot curjlist);
521 
522  virtual bool expand();
523 
524  bool expand(uint n){
525  bool retval=false;
526  for(uint i=0; i<n; i++){
527  retval = expand();
528  if(!retval) break;
529  }
530  return retval;
531  }
532  bool expand_to(flt maxdistsq){
533  bool retval = true;
534  while((maxdistsq <= 0 or jlists.front().distance_squared < maxdistsq) and retval){
535  retval = expand();
536  };
537  return retval;
538  }
539  static Vec straight_diff(Box &bx, Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& A, Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& B);
540  static flt straight_distsq(Box &bx, Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& A, Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& B);
541 
542  list<JammingListRot> &my_list(){return jlists;};
543  list<JammingListRot> copy_list(){return jlists;};
544  list<JammingListRot> copy_list(uint n){
545  list<JammingListRot>::iterator last = jlists.begin();
546  advance(last, n);
547  return list<JammingListRot>(jlists.begin(), last);
548  };
549 
550 
552  if(jlists.empty()){
553  JammingListRot bad_list = JammingListRot();
554  bad_list.distance_squared = -1;
555  return bad_list;
556  }
557  JammingListRot j = JammingListRot(jlists.front());
558  //~ cout << "Best size: " << j.size() << " dist: " << j.distance_squared;
559  //~ if(j.size() > 0) cout << " Elements: [" << j.assigned[0] << ", " << j.assigned[j.size()-1] << "]";
560  //~ cout << '\n';
561  return j;
562  //return JammingList(jlists.front());
563  };
564 
565  //JammingListRot operator[](uint i){
566  // assert(i < jlists.size());
567  // return JammingListRot(jlists[i]);
568  //};
569 
570  uint size(){return (uint) jlists.size();};
571 
572  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> locations_B(JammingListRot jlist);
573  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> locations_B(){return locations_B(current_best());};
574  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> locations_A(JammingListRot jlist);
575  Eigen::Matrix<flt, Eigen::Dynamic, NDIM> locations_A(){return locations_A(current_best());};
576  virtual ~JammingTreeRot(){};
577 };
578 
579 
581  /* For a bi-disperse packing.
582  * 'cutoff' is the number of particles of the first kind; i.e., the
583  * A vector should have A[0]..A[cutoff-1] be of particle type 1,
584  * and A[cutoff]..A[N-1] of particle type 2.
585  * This does much the same as JammingTree2, but doesn't check any
586  * reordering in which particles of one type are relabeled as another.
587  * For exampe, with 2+2 particles (cutoff 2), we check
588  * [0123],[1023],[0132],[1032]
589  * But not
590  * [0213],[0231],[0312],[0321],[1203],[1230],[1302],[1320],...
591  * This means at most (cutoff! (N-cutoff)!) combinations are checked,
592  * and not all N!, which can save a lot of time (as well as
593  * rejecting false combinations).
594  */
595  protected:
596  uint cutoff1,cutoff2;
597  public:
599  sptr<Box>box,
600  Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& A,
601  Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& B,
602  uint cutoff,
603  bool use_rotations=true,
604  bool use_inversions=true
605  ) : JammingTreeRot(box, A, B, use_rotations, use_inversions),
606  cutoff1(cutoff), cutoff2(cutoff){};
608  sptr<Box>box,
609  Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& A,
610  Eigen::Matrix<flt, Eigen::Dynamic, NDIM>& B,
611  uint cutoffA,
612  uint cutoffB,
613  bool use_rotations=true,
614  bool use_inversions=true);// :
615  //JammingTree2(box, A, B), cutoff1(cutoffA), cutoff2(cutoffB){};
616 
617  list<JammingListRot> expand(JammingListRot curjlist);
618  bool expand();
619  bool expand(uint n){return JammingTreeRot::expand(n);};
620 };
621 
623 /* Finding Percolation
624  *
625  * Plan:
626  * struct Node {
627  * uint n;
628  * Vec x;
629  * }
630  *
631  * struct Connectivity {
632  * sptr<OriginBox>;
633  * vector<Node> nodes;
634  * set<Node, vector<Node> > neighbors; # with both directions in
635  * }
636  *
637  * make_connectivity(sptr<OriginBox>, NListed<A,P>) {
638  * # for each pair, if energy != 0, add it to the Connectivity
639  * }
640  *
641  * or
642  *
643  * make_connectivity(sptr<OriginBox>, NeighborList, ... sigmas) {
644  * # for each pair, if box.diff(a1.x, a2.x) < (sigma1 < sigma2)/2, add it to the list
645  * }
646  *
647  * struct Path {
648  * Vec<uint> distance # Euclidean distance from first node to last. Note this is not
649  * # the same as box.diff(last - first), because it might go
650  * # a longer way around the box
651  * vector<uint> nodes # nodes visited
652  * }
653  *
654  * Maybe implement <, ==, > by using length of nodes first and what the nodes are second
655  *
656  * Implement ... circular_from(uint n, check_all=true):
657  * - Do a breadth-first search starting from n, including only nodes > n.
658  * - While searching, build map<node, path>, which is the Euclidean distance from the start node
659  * to the current node via the path traveled
660  * - If you get to an already visited node, compare the current Vec path to the previous one. If
661  * the same:
662  * - either replace the old path (if new_path < old_path) or don't
663  * - Do not follow connections
664  * If different, we've found a percolation:
665  * - Mark percolations with "map<uint, path> cycles"; the key is the dimension, and
666  * the value (vector<uint>) is the path.
667  * - If(check_all && cycles.size() >= 1) return cycles
668  * - else if cycles.size() >= NDIM return cycles
669  * - If you finish without finding any (or enough), return cycles
670  *
671  * Implement ... find_percolation(...):
672  * - for each n, run circular_from(uint n, false)
673  * - if any have a cycle, return it!
674  *
675  * Implement ... find_percolations(...):
676  * - for each n, run circular_from(uint n, true)
677  * - keep merging results
678  * - if cycles.size() >= NDIM return cycles
679  * - if you get to the end, return cycles
680  */
681 
682 class CNode {
683  public:
684  int n;
686 
687  CNode() : n(-1){};
688  CNode(int n, Vec x) : n(n), x(x){};
689 
690  bool operator!=(const CNode& other) const { return n != other.n;};
691  bool operator==(const CNode& other) const { return n == other.n;};
692  bool operator<(const CNode& other) const { return n < other.n;};
693  bool operator>(const CNode& other) const { return n > other.n;};
694 };
695 
696 class CNodePath {
697  public:
699  vector<CNode> nodes;
700 
701  public:
703  CNodePath(CNode node){nodes.push_back(node);};
704  CNodePath(CNodePath other, CNode node, OriginBox& box) :
705  distance(other.distance), nodes(other.nodes){add(node, box);};
706  void add(CNode node, OriginBox& box);
707  uint size(){return (uint) nodes.size();};
708 };
709 
710 // The class that actually finds percolation.
711 
712 // TODO:
713 /*
714  * add a way to work with a NeighborList for initial construction
715  */
717  public:
718  sptr<OriginBox> box;
719  set<CNode> nodes;
720  map<int, vector<CNode> > neighbors;
721 
722  array<bool, NDIM> nonzero(Vec diff_vec); // is it nonzero. Specifically, is any dimension > L/2?
723  CNodePath make_cycle(CNodePath forward, CNodePath backward);
724 
725  map<uint, CNodePath> circular_from(CNode node, set<uint>& visited, bool check_all);
726 
727  public:
728  Connectivity(sptr<OriginBox> box) : box(box){};
729  void add_edge(CNode node1, CNode node2);
730 
731  // assumes diameters are additive
732  // Note that "diameter" should generally be the attractive diameter
733  void add(Eigen::Matrix<flt, Eigen::Dynamic, NDIM> locs, vector<flt> diameters);
734 
735  map<uint, CNodePath> find_percolation(bool check_all_dims=true);
736 };
737 
738 #endif
flt Usq
Definition: constraints.hpp:224
vector< CNode > nodes
Definition: constraints.hpp:699
virtual bool expand()
Definition: constraints.cpp:879
void apply_forces(Box &box)
Definition: constraints.hpp:49
list< JammingListRot > jlists
Definition: constraints.hpp:512
JammingList current_best()
Definition: constraints.hpp:483
The basic class for representing each particle.
Definition: box.hpp:229
unsigned long long formations
Definition: constraints.hpp:186
list< JammingList > & my_list()
Definition: constraints.hpp:480
Connectivity(sptr< OriginBox > box)
Definition: constraints.hpp:728
uint size()
Definition: constraints.hpp:570
int constrained_dof()
Definition: constraints.hpp:137
vector< vector< flt > > dists
Definition: constraints.hpp:377
uint n_skipped
Definition: constraints.hpp:221
a group of atoms, such as all of them (AtomVec), or a smaller group such as a molecule, sidebranch, etc.
Definition: box.hpp:312
JammingListRot(const JammingListRot &other)
Definition: constraints.hpp:500
flt E_squared_mean()
Definition: constraints.hpp:250
virtual ~Constraint()
Definition: constraints.hpp:21
unsigned long curt
Definition: constraints.hpp:285
vector< vector< flt > > rdiffs()
Definition: constraints.hpp:387
flt K()
Definition: constraints.hpp:246
int constrained_dof()
Definition: constraints.hpp:36
vector< Eigen::Matrix< flt, Eigen::Dynamic, NDIM > > locs
Definition: constraints.hpp:358
unsigned int uint
Definition: vec.hpp:20
unsigned long long formed()
Definition: constraints.hpp:203
EnergyTracker(sptr< AtomGroup > atoms, vector< sptr< Interaction > > interactions, uint n_skip=1)
Definition: constraints.hpp:226
Vec x
location.
Definition: box.hpp:231
CoordCOMConstraint(sptr< AtomGroup > atm, bool fixx, bool fixy, bool fixz)
Definition: constraints.hpp:65
CNode()
Definition: constraints.hpp:687
vector< Eigen::Matrix< flt, Eigen::Dynamic, NDIM > > smooth_locs()
Definition: constraints.hpp:368
double flt
The basic floating point type used in the simulations.
Definition: vecrand.hpp:45
JammingListRot current_best()
Definition: constraints.hpp:551
flt distance_squared
Definition: constraints.hpp:403
bool expand()
Definition: constraints.hpp:437
bool expand_to(flt maxdistsq)
Definition: constraints.hpp:532
uint size()
Definition: constraints.hpp:707
Vec v
velocity
Definition: box.hpp:234
bool operator<(const CNode &other) const
Definition: constraints.hpp:692
vector< ISFTracker1 > singles
Definition: constraints.hpp:332
LinearConstraint(sptr< AtomGroup > atms, flt dist)
Definition: constraints.hpp:122
Vec x
Definition: constraints.hpp:685
list< JammingList > copy_list()
Definition: constraints.hpp:481
Definition: constraints.hpp:215
uint size()
Definition: constraints.hpp:491
uint smoothn
Definition: constraints.hpp:354
JammingListRot(const JammingListRot &other, uint expand, flt addeddist)
Definition: constraints.hpp:502
sptr< AtomGroup > atoms
Definition: constraints.hpp:217
A rectilinear Box, with periodic boundary conditions.
Definition: box.hpp:98
unsigned long curt
Definition: constraints.hpp:379
unsigned long get_skip()
Definition: constraints.hpp:325
void apply_velocities(Box &box)
Definition: constraints.hpp:43
vector< RsqTracker1 > singles
Definition: constraints.hpp:284
vector< flt > dists
Definition: constraints.hpp:182
Eigen::Matrix< flt, Eigen::Dynamic, NDIM > locations_B()
Definition: constraints.hpp:573
sptr< AtomGroup > atoms
Definition: constraints.hpp:353
JammingTreeBD(sptr< Box >box, Eigen::Matrix< flt, Eigen::Dynamic, NDIM > &A, Eigen::Matrix< flt, Eigen::Dynamic, NDIM > &B, uint cutoff, bool use_rotations=true, bool use_inversions=true)
Definition: constraints.hpp:598
uint skipn
Definition: constraints.hpp:355
unsigned long get_skip()
Definition: constraints.hpp:277
A pointer to an Atom, that also knows its own index in an AtomVec.
Definition: box.hpp:270
uint cutoff2
Definition: constraints.hpp:596
flt get_U0()
Definition: constraints.hpp:242
A class that enforces rigid-body dynamics.
Definition: constraints.hpp:145
flt K_std()
Definition: constraints.hpp:248
Matrix get_MoI()
Definition: constraints.hpp:175
flt Us
Definition: constraints.hpp:223
bool operator==(const CNode &other) const
Definition: constraints.hpp:691
uint n()
Definition: constraints.hpp:255
Eigen::Matrix< flt, Eigen::Dynamic, NDIM > xyz2sums
Definition: constraints.hpp:262
vector< sptr< Interaction > > interactions
Definition: constraints.hpp:218
CNodePath(CNode node)
Definition: constraints.hpp:703
Definition: constraints.hpp:351
unsigned long skip
Definition: constraints.hpp:378
uint size() const
Definition: constraints.hpp:415
sptr< AtomGroup > atoms
Definition: constraints.hpp:331
bool expand(uint n)
Definition: constraints.hpp:473
CoordCOMConstraint(sptr< AtomGroup > atm, bool fixx, bool fixy, bool fixz, Vec loc)
Definition: constraints.hpp:63
flt E_std()
Definition: constraints.hpp:247
list< JammingListRot > copy_list(uint n)
Definition: constraints.hpp:544
bool expand(uint n)
Definition: constraints.hpp:524
CNodePath()
Definition: constraints.hpp:702
Definition: constraints.hpp:372
uint rotation
Definition: constraints.hpp:496
CNodePath(CNodePath other, CNode node, OriginBox &box)
Definition: constraints.hpp:704
int constrained_dof()
Definition: constraints.hpp:106
Definition: constraints.hpp:494
Vec f
forces
Definition: box.hpp:240
unsigned long long number()
Definition: constraints.hpp:204
void reset()
Definition: constraints.hpp:232
Eigen::Matrix< flt, Eigen::Dynamic, NDIM > A
Definition: constraints.hpp:513
vector< uint > assigned
Definition: constraints.hpp:402
Definition: constraints.hpp:509
unsigned long long breaks
Definition: constraints.hpp:185
flt U()
Definition: constraints.hpp:245
DistConstraint(AtomID atm1, AtomID atm2)
Definition: constraints.hpp:104
unsigned long curt
Definition: constraints.hpp:359
JammingListRot(uint rot)
Definition: constraints.hpp:499
uint N
Definition: constraints.hpp:220
unsigned long long broken()
Definition: constraints.hpp:202
Eigen::Matrix< flt, Eigen::Dynamic, NDIM > locations_A()
Definition: constraints.hpp:575
int constrained_dof()
Definition: constraints.hpp:169
Definition: constraints.hpp:75
Definition: constraints.hpp:179
Definition: constraints.hpp:281
int constrained_dof()
Definition: constraints.hpp:90
bool operator!=(const CNode &other) const
Definition: constraints.hpp:690
sptr< AtomGroup > atoms
Definition: constraints.hpp:375
Definition: constraints.hpp:258
JammingList(const JammingList &other)
Definition: constraints.hpp:406
Eigen::Matrix< flt, Eigen::Dynamic, NDIM > pastlocs
Definition: constraints.hpp:311
flt U_std()
Definition: constraints.hpp:249
void set_U0(flt newU0)
Definition: constraints.hpp:237
set< CNode > nodes
Definition: constraints.hpp:719
uint numincur
Definition: constraints.hpp:357
Definition: constraints.hpp:113
bool usecom
Definition: constraints.hpp:334
void reset()
Definition: constraints.hpp:192
list< JammingListRot > copy_list()
Definition: constraints.hpp:543
A 3x3 matrix, with methods for adding, subtracting, dot product, etc.
Definition: vec.hpp:360
flt E()
Definition: constraints.hpp:244
Eigen::Matrix< flt, Eigen::Dynamic, NDIM > pastlocs
Definition: constraints.hpp:261
int n
Definition: constraints.hpp:684
RelativeConstraint(Atom *atm1, Atom *atm2, bool fixx, bool fixy, bool fixz, Vec loc)
Definition: constraints.hpp:81
sptr< OriginBox > box
Definition: constraints.hpp:718
vector< Eigen::Matrix< flt, Eigen::Dynamic, NDIM > > Bs
Definition: constraints.hpp:514
void apply_positions(Box &box)
Definition: constraints.hpp:37
The general interface for a "tracker", a class that needs to be called every timestep.
Definition: trackers.hpp:16
vector< vector< bool > > contacts
Definition: constraints.hpp:183
Definition: constraints.hpp:400
bool expand(uint n)
Definition: constraints.hpp:619
unsigned long curt
Definition: constraints.hpp:333
JammingTree(sptr< Box > box, Eigen::Matrix< flt, Eigen::Dynamic, NDIM > &A, Eigen::Matrix< flt, Eigen::Dynamic, NDIM > &B)
Definition: constraints.hpp:431
Eigen::Matrix< flt, Eigen::Dynamic, NDIM > pastlocs
Definition: constraints.hpp:376
#define NDIM
Definition: vecrand.hpp:12
Definition: constraints.hpp:329
unsigned long long incontact
Definition: constraints.hpp:187
RelativeConstraint(Atom *atm1, Atom *atm2, bool fixx, bool fixy, bool fixz)
Definition: constraints.hpp:84
virtual ~JammingTreeRot()
Definition: constraints.hpp:576
sptr< Box > box
Definition: constraints.hpp:511
CNode(int n, Vec x)
Definition: constraints.hpp:688
unsigned long get_count()
Definition: constraints.hpp:326
A class for determining if two packings are the same.
Definition: constraints.hpp:424
Definition: constraints.hpp:57
Definition: constraints.hpp:716
Definition: constraints.hpp:308
vector< vector< array< cmplx, NDIM > > > ISFsums
Definition: constraints.hpp:312
flt K_squared_mean()
Definition: constraints.hpp:251
CoordConstraint(Atom *atm, bool fixx, bool fixy, bool fixz, Vec loc)
Definition: constraints.hpp:30
map< int, vector< CNode > > neighbors
Definition: constraints.hpp:720
The virtual interface for the shape of the space and its boundaries.
Definition: box.hpp:50
Definition: constraints.hpp:97
ContactTracker * ContactTrackerD(sptr< Box > box, sptr< AtomGroup > atoms, vector< double > dists)
Definition: constraints.hpp:207
sptr< AtomGroup > atoms
Definition: constraints.hpp:181
Eigen::Matrix< flt, NDIM, 1 > Vec
The basic physics vector.
Definition: vecrand.hpp:53
bool usecom
Definition: constraints.hpp:286
Definition: constraints.hpp:682
JammingList()
Definition: constraints.hpp:405
CoordCOMConstraint(sptr< AtomGroup > atm)
Definition: constraints.hpp:67
unsigned long skip
Definition: constraints.hpp:265
JammingListRot()
Definition: constraints.hpp:498
sptr< AtomGroup > atoms
Definition: constraints.hpp:283
JammingList(const JammingList &other, uint expand, flt addeddist)
Definition: constraints.hpp:408
list< JammingListRot > & my_list()
Definition: constraints.hpp:542
bool operator>(const CNode &other) const
Definition: constraints.hpp:693
int constrained_dof()
Definition: constraints.hpp:69
bool usecom
Definition: constraints.hpp:380
vector< flt > r4sums
Definition: constraints.hpp:264
flt U0
Definition: constraints.hpp:222
RelativeConstraint(Atom *atm1, Atom *atm2)
Definition: constraints.hpp:87
CoordConstraint(Atom *atm)
Definition: constraints.hpp:34
bool usecom
Definition: constraints.hpp:360
DistConstraint(AtomID atm1, AtomID atm2, flt dist)
Definition: constraints.hpp:102
unsigned long get_skip()
Definition: constraints.hpp:389
unsigned long skip
Definition: constraints.hpp:314
Vec distance
Definition: constraints.hpp:698
Definition: constraints.hpp:696
vector< flt > ks
Definition: constraints.hpp:313
unsigned long get_count()
Definition: constraints.hpp:278
Eigen::Matrix< flt, Eigen::Dynamic, NDIM > curlocs
Definition: constraints.hpp:356
Definition: constraints.hpp:15
Definition: constraints.hpp:580
CoordConstraint(Atom *atm, bool fixx, bool fixy, bool fixz)
Definition: constraints.hpp:32
flt U_squared_mean()
Definition: constraints.hpp:252
Definition: constraints.hpp:24
Eigen::Matrix< flt, Eigen::Dynamic, NDIM > xyz4sums
Definition: constraints.hpp:263