1 #ifndef CASM_ClusterOrbits_impl
2 #define CASM_ClusterOrbits_impl
37 template <
typename OutputIterator>
40 OutputIterator result,
double xtal_tol) {
43 Eigen::Vector3i::Constant(1));
45 const auto &basis = unit.
basis();
48 lat_point.
frac() = grid_count().cast<
double>();
50 for (
auto it = basis.begin(); it != basis.end(); ++it) {
51 if (!site_filter(*it)) {
57 return test.
dist(coord) < max_radius;
59 if (std::any_of(basis.begin(), basis.end(), within_radius)) {
63 }
while (++grid_count);
82 template <
typename OutputIterator>
86 bool include_phenomenal_sites,
87 OutputIterator result,
double xtal_tol) {
88 const auto &prim = phenomenal.
prim();
90 int max_low_shift = 0;
91 int max_high_shift = 0;
92 for (
auto it = phenomenal.
begin(); it != phenomenal.
end(); it++) {
94 if (vec.maxCoeff() > max_high_shift) {
95 max_high_shift = vec.maxCoeff();
97 if (vec.minCoeff() < max_low_shift) {
98 max_low_shift = vec.minCoeff();
104 Eigen::Vector3i ones(1, 1, 1);
106 -dim + (max_low_shift * ones).cast<int>(),
107 dim + (max_high_shift * ones).cast<int>(), Eigen::Vector3i::Constant(1));
112 const auto &basis = prim.basis();
115 lat_point.
frac() = grid_count().cast<
double>();
117 for (
auto it = basis.begin(); it != basis.end(); ++it) {
118 if (!site_filter(*it)) {
124 if (!include_phenomenal_sites) {
126 return test.
dist(uccoord.coordinate(prim)) < xtal_tol;
128 if (std::any_of(phenomenal.
begin(), phenomenal.
end(),
135 return test.dist(uccoord.coordinate(prim)) < cutoff_radius;
137 if (std::any_of(phenomenal.
begin(), phenomenal.
end(), within_radius)) {
141 }
while (++grid_count);
156 template <
typename OrbitType,
typename OutputIterator>
158 OutputIterator result) {
159 for (
const auto &equiv : orbit) {
160 for (
const auto &site : equiv) {
177 template <
typename ClusterOrbitIterator,
typename OutputIterator>
179 ClusterOrbitIterator end,
180 OutputIterator result) {
182 for (
auto it = begin; it != end; ++it) {
194 template <
typename OrbitType>
198 std::set<std::pair<Index, Index>> present;
200 for (
auto const &orbit : local_orbits) {
201 for (
auto const &cluster : orbit) {
202 for (
auto const &uccoord : cluster) {
204 present.emplace(uccoord.sublattice(), convert[uccoord.unitcell()]);
223 template <
typename OrbitType>
225 std::vector<OrbitType> &local_orbits,
226 const std::vector<Eigen::Matrix3i> &transf_mat_options) {
227 std::vector<Eigen::Matrix3i> results;
249 template <
typename OrbitType>
251 typename OrbitType::Element cluster,
253 typedef typename OrbitType::Element cluster_type;
254 typedef OrbitType orbit_type;
267 generators.
elements.insert(canonical_generator(*it++));
281 template <
typename OrbitIterator>
282 std::pair<OrbitIterator, OrbitIterator>
orbit_branch(OrbitIterator begin,
285 auto branch_begin = std::find_if(
286 begin, end, [&](
const typename OrbitIterator::value_type &orbit) {
287 return orbit.prototype().size() == size;
290 auto branch_end = std::find_if(
291 branch_begin, end, [&](
const typename OrbitIterator::value_type &orbit) {
292 return orbit.prototype().size() == size + 1;
295 return std::pair<OrbitIterator, OrbitIterator>(branch_begin, branch_end);
310 template <
typename OrbitType>
311 OrbitGenerators<OrbitType> &_insert_null_cluster_generator(
312 const Structure &prim, OrbitGenerators<OrbitType> &generators) {
313 typedef typename OrbitType::Element cluster_type;
316 cluster_type test(prim);
317 generators.insert(test);
331 template <
typename OrbitType>
332 OrbitGenerators<OrbitType> &_insert_asymmetric_unit_generators(
333 const Structure &prim, OrbitGenerators<OrbitType> &generators) {
334 typedef typename OrbitType::Element cluster_type;
337 for (
int i = 0; i < prim.basis().size(); i++) {
339 cluster_type test(prim);
340 test.elements().emplace_back(i, xtal::UnitCell(0, 0, 0));
341 generators.insert(test);
360 template <
typename OrbitType,
typename OrbitGeneratorIterator>
361 OrbitGenerators<OrbitType> &_insert_next_orbitbranch_generators(
362 OrbitGeneratorIterator begin, OrbitGeneratorIterator end,
363 const OrbitBranchSpecs<OrbitType> &specs,
364 OrbitGenerators<OrbitType> &generators, std::ostream &status) {
365 typedef typename OrbitType::Element cluster_type;
367 const auto &filter = specs.filter();
370 std::string clean(100,
' ');
373 auto candidate_sites = specs.candidate_sites();
376 for (
auto orbit_generator_it = begin; orbit_generator_it != end;
377 ++orbit_generator_it) {
378 Index orig_size = generators.elements.size();
381 status << clean <<
'\r' <<
" Calculating orbit branch "
382 << orbit_generator_it->size() + 1 <<
": Expanding orbit "
383 << std::distance(begin, orbit_generator_it) <<
" / "
384 << std::distance(begin, end) <<
" of branch "
385 << orbit_generator_it->size() <<
"." << std::flush;
388 for (
auto site_it = candidate_sites.first;
389 site_it != candidate_sites.second; ++site_it) {
391 if (
contains(*orbit_generator_it, *site_it)) {
396 cluster_type test(*orbit_generator_it);
399 test.elements().push_back(*site_it);
406 generators.insert(test);
409 status <<
" New orbits: " << generators.elements.size() - orig_size
426 template <
typename OrbitType,
typename OrbitOutputIterator>
429 std::ostream &status) {
434 OrbitType null_cluster_orbit(empty, g, specs.
sym_compare());
437 std::vector<OrbitType> orbits(1, null_cluster_orbit);
451 template <
typename OrbitType,
typename OrbitInputIterator,
452 typename OrbitOutputIterator>
454 OrbitInputIterator begin, OrbitInputIterator end,
456 std::ostream &status) {
478 template <
typename OrbitBranchSpecsIterator,
typename OrbitOutputIterator>
480 OrbitBranchSpecsIterator begin, OrbitBranchSpecsIterator end,
481 const std::vector<IntegralClusterOrbitGenerator> &custom_generators,
482 OrbitOutputIterator result, std::ostream &status) {
485 "Error in make_orbits: No OrbitBranchSpecs (begin==end)");
488 typedef typename OrbitOutputIterator::container_type container_type;
489 typedef typename container_type::value_type orbit_type;
493 std::vector<OrbitGenerators<orbit_type>> generators;
494 generators.reserve(std::distance(begin, end));
498 begin->sym_compare());
503 for (
auto it = branch.elements.begin(); it != branch.elements.end(); ++it) {
508 status <<
" Adding null orbit branch." << std::flush;
510 auto specs_it = begin;
511 if (specs_it != end) {
512 generators.emplace_back(begin->generating_group(), begin->sym_compare());
513 _insert_null_cluster_generator(specs_it->prim(), generators.back());
515 insert_branch(all_generators, generators.back());
517 status <<
" New orbits: 1" << std::endl;
521 std::string clean(100,
' ');
524 auto prev_gen = generators.begin();
525 while (specs_it != end) {
526 generators.emplace_back(specs_it->generating_group(),
527 specs_it->sym_compare());
528 _insert_next_orbitbranch_generators(prev_gen->elements.begin(),
529 prev_gen->elements.end(), *specs_it,
530 generators.back(), status);
533 insert_branch(all_generators, generators.back());
538 for (
int i = 0; i < custom_generators.size(); ++i) {
539 status <<
" Adding custom orbit " << i <<
"/" << custom_generators.size()
540 <<
"." << std::flush;
541 if (custom_generators[i].include_subclusters) {
542 status <<
" Include subclusters." << std::flush;
547 all_generators.
insert(custom_generators[i].prototype);
548 if (custom_generators[i].include_subclusters) {
553 status <<
" New orbits: " << all_generators.
elements.size() - orig_size
583 template <
typename OrbitOutputIterator>
585 std::shared_ptr<Structure const> prim_ptr,
587 OrbitOutputIterator result, std::ostream &status) {
589 typedef typename orbit_type::Element cluster_type;
592 SymGroup const &generating_grp = prim_ptr->factor_group();
594 symcompare_type sym_compare(prim_ptr, xtal_tol);
596 std::vector<xtal::UnitCellCoord> candidate_sites;
597 for (
int i = 0; i < prim_ptr->basis().size(); ++i) {
598 if (site_filter(prim_ptr->basis()[i])) {
599 candidate_sites.emplace_back(i, 0, 0, 0);
604 *prim_ptr, candidate_sites.begin(), candidate_sites.end(), generating_grp,
605 [](cluster_type
const &test) { return true; }, sym_compare);
632 template <
typename OrbitOutputIterator>
634 std::shared_ptr<Structure const> prim_ptr,
635 std::vector<double>
const &max_length,
636 std::vector<IntegralClusterOrbitGenerator>
const &custom_generators,
638 OrbitOutputIterator result, std::ostream &status) {
640 typedef typename orbit_type::Element cluster_type;
643 SymGroup const &generating_grp = prim_ptr->factor_group();
645 symcompare_type sym_compare(prim_ptr, xtal_tol);
648 std::vector<OrbitBranchSpecs<orbit_type>> specs;
651 std::vector<xtal::UnitCellCoord> candidate_sites;
654 if (max_length.size() >= 1) {
656 *prim_ptr, candidate_sites.begin(), candidate_sites.end(),
657 generating_grp, [](cluster_type
const &test) { return true; },
662 if (max_length.size() >= 2) {
663 for (
int i = 0; i < prim_ptr->basis().size(); ++i) {
664 if (site_filter(prim_ptr->basis()[i])) {
665 candidate_sites.emplace_back(i, 0, 0, 0);
669 *prim_ptr, candidate_sites.begin(), candidate_sites.end(),
670 generating_grp, [](cluster_type
const &test) { return true; },
675 for (
auto it = max_length.begin() + 2; it != max_length.end(); ++it) {
677 candidate_sites.clear();
679 std::back_inserter(candidate_sites), xtal_tol);
681 auto max_length_filter = [=](cluster_type
const &test) {
682 return sym_compare.make_invariants(test).displacement().back() < *it;
685 specs.emplace_back(*prim_ptr, candidate_sites.begin(),
686 candidate_sites.end(), generating_grp, max_length_filter,
691 return make_orbits(specs.begin(), specs.end(), custom_generators, result,
708 template <
typename OutputIterator>
711 for (
const auto &equiv : orbit) {
713 std::vector<xtal::UnitCellCoord> coord(equiv.begin(), equiv.end());
717 for (
int ns_i = 0; ns_i < coord.size(); ++ns_i) {
718 for (
int ns_j = 0; ns_j < coord.size(); ++ns_j) {
720 coord[ns_j].sublattice(),
721 coord[ns_j].unitcell() - coord[ns_i].unitcell());
739 template <
typename ClusterOrbitIterator,
typename OutputIterator>
741 ClusterOrbitIterator end,
742 OutputIterator result) {
744 for (
auto it = begin; it != end; ++it) {
763 template <
typename OutputIterator,
typename OrbitType>
765 OutputIterator result) {
767 for (
auto const &equiv : orbit) {
775 if (!ucc_ptr)
return result;
778 orbit.prototype().prim().factor_group().begin(),
779 (orbit.prototype().prim().factor_group().begin()) + 1);
780 OrbitType empty_orbit(
typename OrbitType::Element(orbit.prototype().prim()),
781 identity_group, orbit.sym_compare());
782 typename OrbitType::Element test(empty_orbit.prototype());
783 test.elements().push_back(*ucc_ptr);
786 for (
auto const &equiv : orbit) {
790 test.elements()[0] = ucc;
792 test = orbit.sym_compare().prepare(test);
794 xtal::UnitCell trans = test.element(0).unitcell() - ucc.unitcell();
796 *result++ = (ucc2 + trans);
815 template <
typename ClusterOrbitIterator,
typename OutputIterator>
817 ClusterOrbitIterator end,
818 OutputIterator result) {
820 for (
auto it = begin; it != end; ++it) {
A Counter allows looping over many incrementing variables in one loop.
iterator end()
Iterator to the past-the-last element in the cluster.
iterator begin()
Iterator to first element in the cluster.
OrbitOutputIterator make_prim_periodic_orbits(std::shared_ptr< Structure const > prim_ptr, std::vector< double > const &max_length, std::vector< IntegralClusterOrbitGenerator > const &custom_generators, SiteFilterFunction const &site_filter, double xtal_tol, OrbitOutputIterator result, std::ostream &status)
Generate Orbit<IntegralCluster> by specifying max cluster length for each branch.
OrbitOutputIterator make_prim_periodic_asymmetric_unit(std::shared_ptr< Structure const > prim_ptr, SiteFilterFunction const &site_filter, double xtal_tol, OrbitOutputIterator result, std::ostream &status)
Generate the prim periodic asymmetric unit.
const PrimType & prim() const
OrbitOutputIterator make_asymmetric_unit(const OrbitBranchSpecs< OrbitType > &specs, OrbitOutputIterator result, std::ostream &status)
Generate the asymmetric unit, using OrbitBranchSpecs.
Store data used to generate an orbit branch of IntegralCluster.
const PrimType & prim() const
const SymCompareType & sym_compare() const
const SymGroup & generating_group() const
Structure specifies the lattice and atomic basis of a crystal.
const Lattice & lattice() const
const std::vector< xtal::Site > & basis() const
Generates subclusters of a cluster with an iterator-like interface.
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Represents cartesian and fractional coordinates.
Coordinate_impl::FracCoordinate frac()
Set the fractional coordinate vector.
double dist(const Coordinate &neighbor) const
distance (in Angstr) of neighbor from *this
Eigen::Vector3i enclose_sphere(double radius) const
static UnitCellCoord from_coordinate(const PrimType &, const Coordinate &coord, double tol)
std::pair< OrbitIterator, OrbitIterator > orbit_branch(OrbitIterator begin, OrbitIterator end, Index size)
Returns the first range containing orbits of the requested orbit branch in the given range of Orbit.
OutputIterator neighborhood(Structure const &unit, double max_radius, SiteFilterFunction site_filter, OutputIterator result, double xtal_tol)
Output the neighborhood of UnitCellCoord within max_radius of any sites in unit cell.
OrbitGenerators< OrbitType > & insert_subcluster_generators(typename OrbitType::Element cluster, OrbitGenerators< OrbitType > &generators)
Given a cluster, generate all subcluster generators.
OutputIterator flower_neighborhood(OrbitType const &orbit, OutputIterator result)
Iterate over all sites in an orbit and insert a UnitCellCoord.
OrbitOutputIterator make_next_orbitbranch(OrbitInputIterator begin, OrbitInputIterator end, const OrbitBranchSpecs< OrbitType > &specs, OrbitOutputIterator result, std::ostream &status)
Use orbits of size n to generate orbits of size n+1.
OutputIterator local_orbit_neighborhood(const OrbitType &orbit, OutputIterator result)
Iterate over all sites in an orbit and insert a UnitCellCoord.
OutputIterator prim_periodic_orbit_neighborhood(const PrimPeriodicOrbit< IntegralCluster > &orbit, OutputIterator result)
Iterate over all sites in an orbit and insert a UnitCellCoord.
OutputIterator prim_periodic_neighborhood(ClusterOrbitIterator begin, ClusterOrbitIterator end, OutputIterator result)
Iterate over all sites in all orbits and insert a UnitCellCoord.
OutputIterator local_neighborhood(ClusterOrbitIterator begin, ClusterOrbitIterator end, OutputIterator result)
Iterate over all sites in all orbits and insert a UnitCellCoord.
Eigen::Matrix3l transf_mat(const Lattice &prim_lat, const Lattice &super_lat)
typename _LinearIndexConverter< IntegralCoordinateType >::type LinearIndexConverter
OrbitOutputIterator make_orbits(OrbitBranchSpecsIterator begin, OrbitBranchSpecsIterator end, const std::vector< IntegralClusterOrbitGenerator > &custom_generators, OrbitOutputIterator result, std::ostream &status)
Generate orbits of IntegralCluster using OrbitBranchSpecs.
bool has_local_neighborhood_overlap(std::vector< OrbitType > &local_orbits, const Eigen::Matrix3i &transf_mat)
Check if periodic images of sites in an orbit are overlapping in supercells defined by the given supe...
std::function< bool(xtal::Site)> SiteFilterFunction
std::vector< Eigen::Matrix3i > viable_supercells(std::vector< OrbitType > &local_orbits, const std::vector< Eigen::Matrix3i > &transf_mat)
Return superlattice transf. matrices for which has_local_neighborhood_overlap is false.
bool contains(const Container &container, const T &value)
Equivalent to container.end() != std::find(container.begin(), container.end(), value)
OrbitOutputIterator make_asymmetric_unit(const OrbitBranchSpecs< OrbitType > &specs, OrbitOutputIterator result, std::ostream &status)
Generate the asymmetric unit, using OrbitBranchSpecs.
PrototypeIterator< OrbitIterator > prototype_iterator(OrbitIterator orbit_it)
Convert an Orbit iterator to a prototype iterator.
INDEX_TYPE Index
For long integer indexing:
Matrix< long int, 3, 1 > Vector3l
Functor to find the canonical generating element for an orbit.
Data structure that holds canonical generating elements and can then make sorted orbits.
OrbitGeneratorSet< OrbitType > elements
OrbitOutputIterator make_orbits(OrbitOutputIterator result)
Construct Orbit from all generating elements.
const SymCompareType & sym_compare
std::pair< typename OrbitGeneratorSet< OrbitType >::iterator, bool > insert(const Element &test)
Try inserting an element, after generating the canonical form.