10 namespace ConfigMapping {
28 const std::vector<Lattice> &from_range,
32 double best_cost = 10e10;
35 for(
auto it = from_range.cbegin(); it != from_range.cend(); ++it) {
37 LatticeMap strainmap(*it, relaxed_lat, 1, _tol, 1);
39 trans_mat = strainmap.
matrixN();
40 deformation = strainmap.
matrixF();
61 max_vol = ceil(std::abs(relaxed_lat.
vol()) / std::abs(prim_lat.
vol()));
63 double best_cost = 10e10;
68 for(
auto it = enumerator.
begin(); it != enumerator.
end(); ++it) {
73 LatticeMap strainmap(tlat, relaxed_lat, 1, _tol, 1);
75 trans_mat = strainmap.
matrixN();
76 deformation = strainmap.
matrixF();
92 double _lattice_weight,
93 double _max_volume_change,
97 m_lattice_weight(_lattice_weight),
98 m_max_volume_change(_max_volume_change),
101 m_robust_flag(options & robust),
102 m_strict_flag(options & strict),
103 m_rotate_flag(options & rotate),
104 m_tol(
max(1e-9, _tol)) {
115 std::string &imported_name,
117 std::vector<Index> &best_assignment,
124 relaxation_properties,
128 catch(
const std::exception &ex) {
129 throw std::runtime_error(std::string(
"Could not successfully import structure ") + pos_path.string() +
":\n" + ex.what());
138 std::string &imported_name,
140 std::vector<Index> &best_assignment,
142 bool update_struc)
const {
146 relaxation_properties,
156 std::string &imported_name,
158 std::vector<Index> &best_assignment,
160 bool update_struc)
const {
163 ConfigDoF tconfigdof, suggested_configdof;
165 bool is_new_config(
true);
166 double bc(1e20), sc(1e20), hint_cost = 1e20;
168 relaxation_properties.
put_obj();
171 if(hint_ptr !=
nullptr) {
178 mapped_lat = (hint_ptr->
get_supercell()).get_real_super_lattice();
181 relaxation_properties[
"suggested_mapping"][
"basis_deformation"] = bc;
182 relaxation_properties[
"suggested_mapping"][
"lattice_deformation"] = sc;
183 relaxation_properties[
"suggested_mapping"][
"volume_relaxation"] = suggested_configdof.
deformation().determinant();
200 relaxation_properties[
"best_mapping"][
"basis_deformation"] = bc;
201 relaxation_properties[
"best_mapping"][
"lattice_deformation"] = sc;
202 relaxation_properties[
"best_mapping"][
"volume_relaxation"] = tconfigdof.
deformation().determinant();
207 throw std::runtime_error(
"Structure is incompatible with PRIM.");
209 swap(tconfigdof, suggested_configdof);
210 relaxation_properties[
"best_mapping"] = relaxation_properties[
"suggested_mapping"];
219 if(hint_ptr !=
nullptr) {
224 imported_name = hint_ptr->
name();
225 is_new_config =
false;
232 it_canon = ideal_rev_it_canon * relaxed_it_canon;
236 imported_name = hint_ptr->
name();
237 is_new_config =
false;
263 relaxation_properties[
"best_mapping"][
"relaxation_deformation"] = trans_configdof.
deformation();
264 relaxation_properties[
"best_mapping"][
"relaxation_displacement"] = trans_configdof.
displacement().transpose();
272 best_assignment.resize(_struc.
basis.
size());
274 std::copy_if(tperm.cbegin(), tperm.cend(),
275 best_assignment.begin(),
276 [num_atoms](
Index i) {
277 return i < num_atoms;
284 return is_new_config;
290 std::string &imported_name,
292 std::vector<Index> &best_assignment,
298 relaxation_properties,
302 catch(
const std::exception &ex) {
303 throw std::runtime_error(std::string(
"Could not successfully import structure ") + pos_path.string() +
":\n" + ex.what());
311 std::string &imported_name,
313 std::vector<Index> &best_assignment,
321 bool new_config_flag;
328 throw std::runtime_error(
"Structure is incompatible with PRIM.");
332 relaxation_properties[
"best_mapping"][
"volume_change"] = tconfigdof.
deformation().determinant();
357 best_assignment.resize(_struc.
basis.
size());
359 std::copy_if(tperm.cbegin(), tperm.cend(),
360 best_assignment.begin(),
361 [num_atoms](
Index i) {
362 return i < num_atoms;
364 return new_config_flag;
372 std::vector<Index> t_assign;
380 std::vector<Index> &best_assignment,
382 double best_cost )
const {
384 bool valid_mapping(
false);
405 return valid_mapping;
423 std::vector<Index> &best_assignment,
449 cart_op = Eigen::Matrix3d::Identity(3, 3);
481 std::vector<Index> &best_assignment,
483 double best_cost )
const {
487 double bw = 1.0 - lw;
490 std::vector<Index> assignment;
494 double num_atoms = double(struc.
basis.
size());
495 int min_vol, max_vol;
497 mapped_configdof.
clear();
502 if(struc.
basis[i].occ_name() == tcompon)
514 double max_va_frac_limit = double(max_n_va) / double(
primclex().get_prim().basis.size());
519 min_vol = ceil((num_atoms / (
double(
primclex().get_prim().basis.size())) * 1. - t_min_va_frac) -
m_tol);
522 max_vol = ceil(num_atoms / (
double(
primclex().get_prim().basis.size()) * (1.0 - t_max_va_frac)) -
m_tol);
524 if(t_max_va_frac >
TOL) {
529 max_vol = new_max_vol;
530 min_vol = new_min_vol;
534 min_vol =
max(min_vol, 1);
535 max_vol =
max(max_vol, 1);
546 for(
Index i_vol = min_vol; i_vol <= max_vol; i_vol++) {
556 if(best_cost < strain_cost) {
582 if(tot_cost < best_cost) {
583 best_cost = tot_cost -
m_tol;
584 swap(best_assignment, assignment);
586 cart_op = rotF * tF.inverse();
588 swap(mapped_configdof, tdof);
596 for(
Index i_vol = min_vol; i_vol <= max_vol; i_vol++) {
600 for(
auto it = lat_vec.cbegin(); it != lat_vec.cend(); ++it) {
613 if(best_cost > 1e9) {
620 return mapped_configdof.
size() > 0;
629 std::vector<Index> &best_assignment,
635 std::vector<Index> assignment;
639 double bw = 1.0 - lw;
640 double num_atoms = double(struc.
basis.
size());
649 if(strain_cost < best_cost) {
671 if(tot_cost < best_cost) {
672 best_cost = tot_cost -
m_tol;
675 swap(best_assignment, assignment);
676 cart_op = rotF * tF.inverse();
679 swap(mapped_configdof, tdof);
680 mapped_lat = imposed_lat;
688 if(best_cost < strain_cost)
689 strain_cost = lw * strainmap.next_mapping_better_than(best_cost).strain_cost();
691 while(strain_cost < best_cost) {
698 tF = strainmap.matrixF();
722 if(tot_cost < best_cost) {
724 best_cost = tot_cost -
m_tol;
725 swap(best_assignment, assignment);
728 cart_op = rotF * tF.inverse();
731 swap(mapped_configdof, tdof);
732 mapped_lat = imposed_lat;
737 strain_cost = lw * strainmap.next_mapping_better_than(best_cost).strain_cost();
745 throw std::runtime_error(
"Cannot enumerate lattice of volume " +
std::to_string(prim_vol) +
", which is out of bounds.\n");
751 std::vector<Lattice> lat_vec;
758 for(
auto it = enumerator.begin(); it != enumerator.end(); ++it) {
769 namespace ConfigMap_impl {
798 current_relaxed_coord.
cart() += trans.
cart();
806 cost_matrix(i, j) = scel.
coord(i).
min_dist2(current_relaxed_coord, metric);
810 cost_matrix(i, j) = inf;
827 cost_matrix(i, j) = 0;
830 cost_matrix(i, j) = inf;
858 cost_matrix = Eigen::MatrixXd::Constant(scel.num_sites(), scel.num_sites(), inf);
862 for(j = 0; j < rstruc.
basis.
size(); j++) {
863 Coordinate current_relaxed_coord(rstruc.
basis[j].frac(), scel.get_real_super_lattice(),
FRAC);
864 current_relaxed_coord.
cart() += trans.
cart();
867 for(
Index i = 0; i < scel.num_sites(); i++) {
872 cost_matrix(i, j) = scel.coord(i).min_dist2(current_relaxed_coord, metric);
876 cost_matrix(i, j) = inf;
880 if(inf_counter == scel.num_sites()) {
887 for(; j < scel.num_sites(); j++) {
889 for(
Index i = 0; i < scel.num_sites(); i++) {
893 cost_matrix(i, j) = 0;
896 cost_matrix(i, j) = inf;
900 if(inf_counter == scel.num_sites()) {
923 std::vector<Index> &best_assignments,
924 const bool translate_flag,
942 std::vector<Index> &best_assignments,
943 const bool translate_flag,
963 std::vector<Index> &best_assignments,
964 const bool translate_flag,
977 std::vector<Index> optimal_assignments;
980 double min_mean = 10E10;
987 Index num_translations(1);
993 for(
Index n = 0; n < num_translations; n++) {
1008 translation.
cart() = scel.
coord((n - 1) * scel.
volume()).const_cart() - rstruc.
basis[0].const_cart();
1009 translation.voronoi_within();
1022 if(optimal_assignments.size() < rstruc.
basis.
size()) {
1028 mean += _tol * translation.const_cart().norm() / 10.0;
1030 if(mean < min_mean) {
1034 swap(best_assignments, optimal_assignments);
1037 best_trans.cart() = translation.cart();
1047 Eigen::Vector3d zero_vector(0.0, 0.0, 0.0);
1052 Eigen::Vector3d avg_disp(0, 0, 0);
1058 for(
Index i = 0; i < best_assignments.size(); i++) {
1070 if(best_assignments[i] < rstruc.
basis.
size()) {
1074 (rstruc.
basis[best_assignments[i]] + best_trans).min_dist(ideal_coord, disp_coord);
1077 config_dof.
disp(i) = disp_coord.const_cart();
1079 avg_disp += config_dof.
disp(i);
1093 std::string rel_basis_atom;
1094 for(
Index i = 0; i < best_assignments.size(); i++) {
1096 if(best_assignments[i] < rstruc.
basis.
size()) {
1097 config_dof.
disp(i) -= avg_disp;
1099 for(
Index j = 0; j < 3; j++) {
1101 config_dof.
disp(i)[j] = 0;
1105 rel_basis_atom = rstruc.
basis[best_assignments[i]].occ_name();
1111 rel_basis_atom =
"Va";
1143 std::vector<Index> &best_assignments,
1144 const bool translate_flag,
1145 const double _tol) {
1157 std::vector<Index> optimal_assignments;
1161 double min_mean = 10E10;
1168 Index num_translations(1);
1170 num_translations += rstruc.
basis.
size();
1174 for(
Index n = 0; n < num_translations; n++) {
1180 Coordinate translation(scel.get_real_super_lattice());
1185 translation.
cart() = scel.coord(0).const_cart() - rstruc.
basis[n - 1].const_cart();
1186 translation.voronoi_within();
1201 if(optimal_assignments.size() < rstruc.
basis.
size()) {
1207 mean += _tol * translation.const_cart().norm() / 10.0;
1208 if(mean < min_mean) {
1212 swap(best_assignments, optimal_assignments);
1215 best_trans = translation;
1225 Eigen::Vector3d zero_vector(0.0, 0.0, 0.0);
1228 config_dof.
set_displacement(ConfigDoF::displacement_matrix_t::Zero(3, scel.num_sites()));
1230 Eigen::Vector3d avg_disp(0, 0, 0);
1236 for(
Index i = 0; i < best_assignments.size(); i++) {
1248 if(best_assignments[i] < rstruc.
basis.
size()) {
1252 (rstruc.
basis[best_assignments[i]] + best_trans).min_dist(ideal_coord, disp_coord);
1255 config_dof.
disp(i) = disp_coord.const_cart();
1257 avg_disp += config_dof.
disp(i);
1271 std::string rel_basis_atom;
1272 for(
Index i = 0; i < best_assignments.size(); i++) {
1277 if(best_assignments[i] < rstruc.
basis.
size()) {
1278 config_dof.
disp(i) -= avg_disp;
1280 for(
Index j = 0; j < 3; j++) {
1282 config_dof.
disp(i)[j] = 0;
1285 config_dof.
occ(i) = config.
occ(i);
const Configuration & get_config(Index i) const
bool deformed_struc_to_configdof_of_lattice(const BasicStructure< Site > &struc, const Lattice &imposed_lat, double &best_cost, ConfigDoF &mapped_configdof, Lattice &mapped_lat, std::vector< Index > &best_assignment, Eigen::Matrix3d &cart_op) const
Low-level routine to map a structure onto a ConfigDof assuming a specific Lattice, without assuming structure is ideal Will only identify mappings better than best_cost, and best_cost is updated to reflect cost of best mapping identified.
Coordinate coord(const UnitCellCoord &bijk) const
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
ConfigMapper(NullInitializer)
Default construction not allowed – this constructor provides an override.
bool contains(const T &test_elem) const
void set_displacement(const displacement_matrix_t &_displacement)
const int & occ(Index site_l) const
Occupant variable on site l.
Coordinate_impl::CartCoordinate cart()
Set Cartesian coordinate vector and update fractional coordinate vector.
const Molecule & get_mol(Index site_l) const
Molecule on site l.
const SymGroup & point_group() const
const Structure & get_prim() const
bool struc_to_configdof(const BasicStructure< Site > &_struc, ConfigDoF &mapped_configdof, Lattice &mapped_lat) const
Low-level routine to map a structure onto a ConfigDof.
bool is_equivalent(const Lattice &RHS, double tol) const
Are two lattices the same, even if they have different lattice vectors.
Data structure for holding supercell enumeration properties.
double max_va_frac() const
Object copy_apply(const Transform &f, Object obj, Args &&...args)
bool preconditioned_struc_to_configdof(const Supercell &scel, const BasicStructure< Site > &rstruc, const Eigen::Matrix3d &deformation, ConfigDoF &config_dof, std::vector< Index > &best_assignment, const bool translate_flag, const double _tol)
Same as struc_to_configdof, except 'rstruc' is de-rotated and de-strained. Any deformation is instead...
double hungarian_method(const Eigen::MatrixXd &cost_matrix, std::vector< Index > &optimal_assignments, const double _tol)
const std::vector< Lattice > & _lattices_of_vol(Index prim_vol) const
ReturnArray< T > permute(const Array< T > &before_array) const
Generate permuted copy of type-T Array.
const ConfigDoF & configdof() const
const Access the DoF
const_iterator end() const
A const iterator to the past-the-last volume.
const Lattice & get_real_super_lattice() const
bool import_structure(const fs::path &pos_path, std::string &imported_name, jsonParser &relaxation_properties, std::vector< Index > &best_assignment, Eigen::Matrix3d &cart_op) const
imports structure specified by 'pos_path' into primclex() by finding optimal mapping unlike import_st...
PermuteIterator inverse() const
A fake container of supercell matrices.
bool deformed_struc_to_configdof(const BasicStructure< Site > &_struc, ConfigDoF &mapped_config_dof, Lattice &mapped_lat, std::vector< Index > &best_assignment, Eigen::Matrix3d &cart_op, double best_cost=1e20) const
Low-level routine to map a structure onto a ConfigDof. Does not assume structure is ideal...
std::string to_string(ENUM val)
Return string representation of enum class.
const Lattice & lattice() const
Represents a supercell of the primitive parent crystal structure.
const Eigen::Matrix3d & lat_column_mat() const
3x3 matrix with lattice vectors as its columne
void set_lattice(const Lattice &lattice, COORD_TYPE mode)
bool ideal_struc_to_configdof(const BasicStructure< Site > &struc, ConfigDoF &mapped_config_dof, Lattice &mapped_lat, std::vector< Index > &best_assignment, Eigen::Matrix3d &cart_op) const
Low-level routine to map a structure onto a ConfigDof if it is known to be ideal. ...
Index size() const
*** ACCESSORS ***
const Eigen::Matrix3d & deformation() const
PrimClex & primclex() const
void swap(ConfigDoF &A, ConfigDoF &B)
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
const matrix_type & matrix() const
Const access of entire cartesian symmetry matrix.
const Eigen::Matrix3d & inv_lat_column_mat() const
Inverse of Lattice::lat_column_mat() It is the transformation matrix 'C2F', such that f = C2F * c whe...
double strain_cost() const
const_iterator begin() const
A const iterator to the beginning volume, specify here how the iterator should jump through the enume...
permute_const_iterator permute_begin() const
const LatticeMap & best_strain_mapping() const
Represents cartesian and fractional coordinates.
EigenIndex Index
For long integer indexing:
Index volume() const
Return number of primitive cells that fit inside of *this.
std::map< Index, std::vector< Lattice > > m_superlat_map
A container class for the different degrees of freedom a Configuration might have.
Lattice canonical_equivalent_lattice(const Lattice &in_lat, const SymGroup &point_grp, double compare_tol)
Find the niggli, most standard oriented version of the given orbit (defined by the given SymGroup) of...
const DMatType & matrixF() const
Array< CoordType > basis
Lattice vectors that specifies periodicity of the crystal.
bool add_canon_config(const Configuration &config, Index &index)
Index max_possible_vacancies() const
Counts sites that allow vacancies.
bool add_config(const Configuration &config)
PrimClex is the top-level data structure for a CASM project.
bool is_supercell_of(const Lattice &tile, Eigen::Matrix3d &multimat, double _tol=TOL) const
Matrix that relates two lattices (e.g., strain or slat)
T max(const T &A, const T &B)
T min(const T &A, const T &B)
std::string name() const
SCELV_A_B_C_D_E_F/i.
void set_deformation(const Eigen::Matrix3d &_deformation)
set_deformation sets ConfigDoF::has_deformation() to true
double vol() const
Return signed volume of this lattice.
Index add_supercell(const Lattice &superlat)
const DMatType & matrixN() const
PermuteIterator to_canonical() const
Returns the operation that applied to *this returns the canonical form.
jsonParser & put_obj()
Puts new empty JSON object.
const Supercell & get_supercell(Index i) const
const Access supercell by index
bool calc_cost_matrix(const Supercell &scel, const BasicStructure< Site > &rstruc, const Coordinate &trans, const Eigen::Matrix3d &metric, Eigen::MatrixXd &cost_matrix)
static double calc_strain_cost(const Eigen::Matrix3d &F, double relaxed_atomic_vol)
const displacement_matrix_t & displacement() const
const Array< int > & occupation() const
Coordinate_impl::FracCoordinate frac()
Set the fractional coordinate vector.
bool struc_to_configdof(const Supercell &scel, BasicStructure< Site > rstruc, ConfigDoF &config_dof, std::vector< Index > &best_assignment, const bool translate_flag, const double _tol)
double basis_cost(const ConfigDoF &_dof, Index Nsites)
Calculate the basis cost function of a ConfigDoF as the mean-square displacement of its atoms...
double min_va_frac() const
Lattice find_nearest_super_lattice(const Lattice &prim_lat, const Lattice &relaxed_lat, const SymGroup &sym_group, Eigen::Matrix3d &trans_mat, Eigen::Matrix3d &deformation, double &best_cost, Index min_vol, Index max_vol, double _tol)
std::vector< std::pair< std::string, Index > > m_fixed_components
double m_max_volume_change
Supercell & get_supercell() const
Get the Supercell for this Configuration.
displacement_t disp(Index i)
Index get_b(Index i) const
static Matrix3d right_stretch_tensor(Matrix3d &C, Eigen::Vector3d &eigenvalues, Matrix3d &eigenvectors, const Matrix3d &F)
double min_dist2(const Coordinate &neighbor, const Eigen::Ref< const Eigen::Matrix3d > &metric) const
Finds same shift as min_dist but returns shift(CART).transpose()*metric*shift(CART) ...
PermuteIterator from_canonical() const
Returns the operation that applied to the the canonical form returns *this.
void set_occupation(const Array< int > &_occupation)
A Configuration represents the values of all degrees of freedom in a Supercell.
const Structure & get_prim() const
const Access to primitive Structure
Permutation combined_permute() const
Returns the combination of factor_group permutation and translation permutation.
bool valid_index(Index i)
bool import_structure_occupation(const fs::path &pos_path, std::string &imported_name, jsonParser &relaxation_properties, std::vector< Index > &best_assignment, Eigen::Matrix3d &cart_op) const
imports structure specified by 'pos_path' into primclex() by finding optimal mapping and then setting...
double strain_cost(const Lattice &relaxed_lat, const ConfigDoF &_dof, Index Nsites)
Calculate the strain cost function of a ConfigDoF using LatticeMap::calc_strain_cost() ...