CASM  1.1.0
A Clusters Approach to Statistical Mechanics
NeighborList.cc
Go to the documentation of this file.
2 
7 #include "casm/misc/CASM_math.hh"
8 #include "casm/misc/algorithm.hh"
9 
10 namespace CASM {
11 
14  return m_W;
15 }
16 
19  expand(uccoord.unitcell());
20 }
21 
24  // save the old range
25  Scalar prev_range = m_range;
26 
27  auto result = m_neighborhood.insert(uc);
28 
29  // if a new UnitCell
30  if (result.second) {
31  // ensure all intermediate UnitCell are included
32  _expand(prev_range);
33  }
34 }
35 
38  return _expand(uccoord.unitcell());
39 }
40 
43  return m_neighborhood.insert(uc).second;
44 }
45 
48 void PrimNeighborList::_expand(Scalar prev_range) {
49  // if some are new, we need to make sure we including all intermediate
50  // UnitCell in our neighborhood get the score of the last element in the set
51  m_range = _dist(*m_neighborhood.rbegin());
52 
53  // count over possible UnitCell, adding to neighborhood if prev_range < dist
54  // <= m_range we're using a std::set for m_neighborhood, so it gets sorted
55 
56  // We want the bounding box that contains the ellipsoid defined by
57  // m_range = (i,j,k).transpose() * W * (i,j,k)
58  // = F.t * U.t * U * F
59  // = F.t * (M.inv).t * (M.inv) * F
60  // 1 = F.t * (sqrt(m_range)*M.inv).t * (sqrt(m_range)*M.inv) * F
61  // has maximum bb_end
62  // bb_end(i) = M.row(i).norm() (from considerations of an affine
63  // transformation M of unit sphere) where M = sqrt(m_range)*U.inv
64  // and minimum
65  // bb_begin = -bb_end
66 
67  Eigen::MatrixXd M = sqrt(1.0 * m_range) * m_Uinv;
68 
69  auto d = [&](int i) { return std::lround(std::ceil(M.row(i).norm())); };
70 
71  VectorXType bb_end(3);
72  bb_end << d(0), d(1), d(2);
73  VectorXType bb_begin = -bb_end;
74  VectorXType bb_incr = VectorXType::Constant(3, 1);
75 
76  typedef Counter<VectorXType, Scalar, Index,
78  VectorXCounter;
79 
80  VectorXCounter counter(bb_begin, bb_end, bb_incr);
81 
82  Scalar dist;
83  for (; counter.valid(); ++counter) {
84  dist = _dist(counter.current());
85  if (prev_range < dist && dist <= m_range) {
86  m_neighborhood.insert(counter.current());
87  }
88  }
89 }
90 
93  return m_neighborhood.size();
94 }
95 
98  return m_neighborhood.cbegin();
99 }
100 
103  return m_neighborhood.cend();
104 }
105 
108  return m_neighborhood.cbegin();
109 }
110 
113  return m_neighborhood.cend();
114 }
115 
118  const {
119  return m_sublat_indices;
120 }
121 
125  UnitCellCoord const &_ucc) {
126  expand(_ucc);
127  return _neighbor_index(_ucc);
128 }
129 
133  UnitCellCoord const &_ucc) const {
134  Scalar uc_ind(find_index(m_neighborhood, _ucc.unitcell()));
135  Scalar sublat_dist(find_index(sublat_indices(), _ucc.sublattice()));
136 
137  return uc_ind * sublat_indices().size() + sublat_dist;
138 }
139 
142  return A.transpose() * m_W * A;
143 }
144 
147  const UnitCell &A) const {
148  VectorXType vec(4);
149  vec(0) = _dist(A);
150  vec.segment(1, 3) = A;
151  return vec;
152 }
153 
156  const UnitCell &B) const {
157  return _compare_vec(_add_dist(A), _add_dist(B));
158 }
159 
162  const VectorXType &B) {
163  return std::lexicographical_compare(A.data(), A.data() + A.size(), B.data(),
164  B.data() + B.size());
165 }
166 
184  const Eigen::Matrix3d lat_column_mat, Index max_element_value, double tol) {
185  Eigen::Matrix3d W = lat_column_mat.transpose() * lat_column_mat;
186 
188  for (int i = 0; i < 3; ++i) {
189  for (int j = 0; j < 3; ++j) {
190  if (!almost_zero(W(i, j), tol) && std::abs(W(i, j)) < std::abs(min)) {
191  min = W(i, j);
192  }
193  }
194  }
195  W /= min;
196 
197  // make positive definite
198  Eigen::LLT<Eigen::MatrixXd> llt(W);
199  if (llt.info() != Eigen::Success) {
200  W = -W;
201  }
202 
203  double n = 1.0;
204  while (!is_integer(n * W, tol) &&
205  ((n + 1.0) * W).cwiseAbs().maxCoeff() < max_element_value) {
206  n += 1.0;
207  }
208  return lround(n * W);
209 }
210 
212 std::unique_ptr<PrimNeighborList> PrimNeighborList::clone() const {
213  return std::unique_ptr<PrimNeighborList>(new PrimNeighborList(*this));
214 }
215 
237  const PrimNeighborList &prim_nlist) {
238  xtal::UnitCellIndexConverter ijk_index_converter{
240  m_prim_grid_size = ijk_index_converter.total_sites();
241  m_site.resize(m_prim_grid_size);
243 
244  // use the PrimNeighborList to generate the UnitCell and Site indices for
245  // the neighbors of each UnitCell in the supercell
246 
247  // for each unit cell in the supercell
248  for (Index i = 0; i < m_prim_grid_size; ++i) {
249  // for each neighbor unitcell
250  for (auto it = prim_nlist.begin(); it != prim_nlist.end(); ++it) {
251  // get the neighbor unitcell's index
252  UnitCell neighbor_unitcell = ijk_index_converter(i) + *it;
253  size_type neighbor_unitcell_index =
254  ijk_index_converter(neighbor_unitcell);
255 
256  // store the unitcell index
257  m_unitcell[i].push_back(neighbor_unitcell_index);
258 
259  // calculate and store the site indices for all sites in the neighbor
260  // unitcell that are requested
261  // - Depends on Configuration sites being stored in blocks by sublattice
262  // and unitcell indices
263  // determined by the UnitCellCoordIndexConverter ordering
264  for (auto b_it = prim_nlist.sublat_indices().begin();
265  b_it != prim_nlist.sublat_indices().end(); ++b_it) {
266  m_site[i].push_back((*b_it) * m_prim_grid_size +
267  neighbor_unitcell_index);
268  }
269  }
270  }
271 }
272 
290  const PrimNeighborList &prim_nlist)
292  prim_nlist) {}
293 
295 const std::vector<SuperNeighborList::size_type> &SuperNeighborList::sites(
296  size_type unitcell_index) const {
297  return m_site[unitcell_index];
298 }
299 
301 const std::vector<SuperNeighborList::size_type> &SuperNeighborList::unitcells(
302  size_type unitcell_index) const {
303  return m_unitcell[unitcell_index];
304 }
305 
311  // there is an overlap if any of the neighboring unitcell indices is repeated
312  // so sort and check if any two neighboring indices are the same
313 
314  std::vector<size_type> nlist = m_unitcell[0];
315  std::sort(nlist.begin(), nlist.end());
316  return std::adjacent_find(nlist.begin(), nlist.end()) != nlist.end();
317 }
318 
320 std::unique_ptr<SuperNeighborList> SuperNeighborList::clone() const {
321  return std::unique_ptr<SuperNeighborList>(new SuperNeighborList(*this));
322 }
323 
324 } // namespace CASM
A Counter allows looping over many incrementing variables in one loop.
Definition: Counter.hh:109
The PrimNeighborList gives the coordinates of UnitCell that are neighbors of the origin UnitCell.
Definition: NeighborList.hh:39
bool _expand(UnitCell const &uc)
Expand the neighbor list to include the given UnitCell, but do not do additional updates returns true...
Definition: NeighborList.cc:42
Scalar m_range
the neighborhood, m_neighborhood, contains all UnitCell with r <= m_range
NeighborSet m_neighborhood
the neighborhood of [i, j, k]
Scalar _neighbor_index(UnitCellCoord const &_ucc) const
Get neighborlist index of UnitCellCoord.
Scalar _dist(const UnitCell &A) const
Calculate A.transpose()*M*A.
Scalar neighbor_index(UnitCellCoord const &_ucc)
Get neighborlist index of UnitCellCoord.
const_iterator cend() const
const_iterator over the neighborhood of unit cells
EIGEN_MAKE_ALIGNED_OPERATOR_NEW typedef Index Scalar
Definition: NeighborList.hh:43
std::unique_ptr< PrimNeighborList > clone() const
Clone.
void expand(UnitCell const &uc)
Expand the neighbor list to include the given UnitCellCoord.
Definition: NeighborList.cc:23
const_iterator cbegin() const
const_iterator over the neighborhood of unit cells
size_type size() const
size of the neighborhood of unit cells
Definition: NeighborList.cc:92
std::set< int > SublatIndices
Definition: NeighborList.hh:50
const_iterator end() const
const_iterator over the neighborhood of unit cells
const_iterator begin() const
const_iterator over the neighborhood of unit cells
Definition: NeighborList.cc:97
NeighborSet::size_type size_type
Definition: NeighborList.hh:48
Eigen::MatrixXd m_Uinv
Cholesky decomposition: W = U.transpose()*U, useful for getting bounding box.
const SublatIndices & sublat_indices() const
pair of const_iterators over a range of indices of sublattices to include
SublatIndices m_sublat_indices
the indices of sublattices that should be included
bool _compare_unitcell(const UnitCell &A, const UnitCell &B) const
Convert [i,j,k] -> [r,i,j,k] and then lexicographically compare.
Matrix3Type m_W
Weighting matrix.
Matrix3Type weight_matrix() const
Return the weighting matrix W used to define the canonical order.
Definition: NeighborList.cc:13
static bool _compare_vec(const VectorXType &A, const VectorXType &B)
Lexicographical comparison.
Eigen::Matrix< long, Eigen::Dynamic, 1 > VectorXType
Definition: NeighborList.hh:45
Eigen::Matrix3l Matrix3Type
Definition: NeighborList.hh:44
NeighborSet::const_iterator const_iterator
Definition: NeighborList.hh:49
static Matrix3Type make_weight_matrix(const Eigen::Matrix3d lat_column_mat, Index max_element_value, double tol)
Returns a NeighborList weighting matrix appropriate for a particular lattice.
VectorXType _add_dist(const UnitCell &A) const
Return [r, i, j, k], where r = _dist(A)
PrimNeighborList(const Matrix3Type &W, SublatIterator begin, SublatIterator end)
Constructor, specifying the weighting matrix to use and the indices of sublattices to include.
size_type unitcell_index(size_type site_index) const
Get unitcell_index from site_index.
std::vector< std::vector< size_type > > m_site
m_site[unitcell_index][neighbor site index]
std::vector< std::vector< size_type > > m_unitcell
m_unitcell[unitcell_index][neighbor unitcell index]
const std::vector< size_type > & unitcells(size_type unitcell_index) const
const Access the list of unitcells neighboring a particular unit cell
bool overlaps() const
Returns true if periodic images of the neighbor list overlap.
std::unique_ptr< SuperNeighborList > clone() const
Clone.
SuperNeighborList(Eigen::Matrix3l const &transformation_matrix_to_super, PrimNeighborList const &prim_nlist)
Constructor.
size_type m_prim_grid_size
store prim grid size for site index -> unitcell index conversion unitcell_index = site_index % m_prim...
const std::vector< size_type > & sites(size_type unitcell_index) const
const Access the list of sites neighboring a particular unit cell
Unit Cell Coordinates.
const UnitCell & unitcell() const
Unit Cell Indices.
Eigen::CwiseUnaryOp< decltype(Local::lround_l< typename Derived::Scalar >), const Derived > lround(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd to Eigen::MatrixXl.
bool is_integer(const Eigen::MatrixBase< Derived > &M, double tol)
Check if Eigen::Matrix is integer.
MatrixXiSupercellSymInfoFormatter transformation_matrix_to_super()
Main CASM namespace.
Definition: APICommand.hh:8
Eigen::MatrixXd MatrixXd
Index find_index(Iterator begin, Iterator end, const T &value)
Equivalent to std::distance(begin, std::find(begin, end, value))
Definition: algorithm.hh:24
Eigen::Matrix3d Matrix3d
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Definition: CASM_math.hh:104
T min(const T &A, const T &B)
Definition: CASM_math.hh:88
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
T max(const T &A, const T &B)
Definition: CASM_math.hh:95
Matrix< long int, 3, 3 > Matrix3l
Definition: eigen.hh:12
Helper Functor for Counter container access using operator()
Definition: CASM_TMP.hh:165