3 #include "casm/external/Eigen/CASM_AddOns"
26 m_group_index(RHS.m_group_index),
27 m_coord_rep_ID(RHS.m_coord_rep_ID),
28 m_reg_rep_ID(RHS.m_reg_rep_ID),
29 m_identity_rep_IDs(RHS.m_identity_rep_IDs) {
170 regrep_mat(j, k) = 1.0;
173 regrep_mat(j, k) = 0.0;
200 kroneckerProduct(*(rep1->get_MatrixXd(i)), *(rep2->
get_MatrixXd(i)), tmat);
211 for(
Index i = 0; i < rep_IDs.
size(); i++) {
219 for(
Index i = 0; i < treps.
size(); i++) {
222 if(!(treps[i]->get_MatrixXd(0)))
225 dim += (treps[i]->get_MatrixXd(0))->cols();
232 for(
Index j = 0; j < treps.
size(); j++) {
233 tmat.block(corner, corner, (treps[j]->get_MatrixXd(i))->cols(), (treps[j]->get_MatrixXd(i))->cols()) = *(treps[j]->get_MatrixXd(i));
234 corner += (treps[j]->get_MatrixXd(i))->cols();
260 std::cout <<
"IN IF" << std::endl;
261 coord_rep_mat *= coord_rep_mat.determinant();
265 Eigen::Quaterniond opq(coord_rep_mat);
289 right_q(0, 0) = opq.w();
290 right_q(0, 1) = -opq.x();
291 right_q(0, 2) = -opq.y();
292 right_q(0, 3) = -opq.z();
294 right_q(1, 0) = opq.x();
295 right_q(1, 1) = opq.w();
296 right_q(1, 2) = opq.z();
297 right_q(1, 3) = -opq.y();
299 right_q(2, 0) = opq.y();
300 right_q(2, 1) = -opq.z();
301 right_q(2, 2) = opq.w();
302 right_q(2, 3) = opq.x();
304 right_q(3, 0) = opq.z();
305 right_q(3, 1) = opq.y();
306 right_q(3, 2) = -opq.x();
307 right_q(3, 3) = opq.w();
309 left_q(0, 0) = opq.w();
310 left_q(0, 1) = -opq.x();
311 left_q(0, 2) = -opq.y();
312 left_q(0, 3) = -opq.z();
314 left_q(1, 0) = opq.x();
315 left_q(1, 1) = opq.w();
316 left_q(1, 2) = -opq.z();
317 left_q(1, 3) = opq.y();
319 left_q(2, 0) = opq.y();
320 left_q(2, 1) = opq.z();
321 left_q(2, 2) = opq.w();
322 left_q(2, 3) = -opq.x();
324 left_q(3, 0) = opq.z();
325 left_q(3, 1) = -opq.y();
326 left_q(3, 2) = opq.x();
327 left_q(3, 3) = opq.w();
330 std::cout << right_q << std::endl;
335 for(
Index i = 0 ; i < new_rep->
size() ; i++) {
336 std::cout <<
"Rota Rep final mats " << i <<
"\n" << *(new_rep->
get_MatrixXd(i)) << std::endl;
370 m_rep_array.back()->set_master_group(*
this, new_ID);
397 bool broken_check(
false);
401 if(
at(i).index() != i) {
407 std::cerr <<
"WARNING: Order of symmetry operations has been altered by MasterSymGroup::sort_by_class(). Attempting to repair "
408 <<
m_rep_array.size() <<
" symmetry representations.\n";
426 m_group_periodicity(init_type),
428 for(
Index i = 0; i < from_array.
size(); i++)
521 if(std::abs(180 - info.
angle) <
TOL) {
524 else if(std::abs(120 - info.
angle) <
TOL) {
527 else if(std::abs(90 - info.
angle) <
TOL) {
530 else if(std::abs(60 - info.
angle) <
TOL) {
539 else if(std::abs(120 - info.
angle) <
TOL) {
542 else if(std::abs(90 - info.
angle) <
TOL) {
545 else if(std::abs(60 - info.
angle) <
TOL) {
619 std::cerr <<
"\n Error Cubic case 24 Acentric \n ";
624 std::cerr <<
"\n Error Cubic \n";
651 std::cerr <<
"\n Error Hexagonal case 6 Acentric \n ";
677 else std::cerr <<
"\n Error Hexagonal case 12 Ancentric #6 \n";
686 std::cerr <<
"\n Error Hexagonal case 12 Acentric \n ";
691 std::cerr <<
"\n Error Hexagonal \n";
732 std::cerr <<
"\n Error Trigonal case 6 Acentric \n ";
737 std::cerr <<
"\n Error Trigonal \n";
764 std::cerr <<
"\n Error Tetragonal case 4 Acentric \n ";
790 else std::cerr <<
"\n Error Tetragonal case 8 Ancentric #4 \n";
799 std::cerr <<
"\n Error Tetragonal case 8 Acentric \n ";
804 std::cerr <<
"\n Error Tetragonal \n";
829 std::cerr <<
"\n Error Orthorhombic Acentric \n ";
856 std::cerr <<
"\n Error Monoclinic Acentric \n ";
876 std::cerr <<
"Error foind point group type \n";
892 out <<
" Point Group is " ;
896 else out <<
" Centric ";
908 if(shiftless.
size() != 0) {
909 std::cerr <<
"WARNING in SymGroup::copy_no_trans" << std::endl;
910 std::cerr <<
"The provided SymGroup wasn't empty and it's about to be erased. Say goodbye." << std::endl;
915 SymOp tsymop(
at(i).no_trans());
919 else if(!shiftless.
contains(tsymop)) {
941 assert(
m_lat_ptr &&
"Attempting to access Lattice of a SymGroup, but it has not been initialized!");
952 bool inversion =
false;
953 bool sigma_h =
false;
954 bool sigma_v =
false;
957 bool sym_wrt_paxis =
true;
958 bool sym_wrt_v =
true;
959 bool sym_wrt_C2p =
true;
960 bool sym_wrt_h =
true;
961 bool sym_wrt_inv =
true;
965 bool all_unique =
false;
969 if((
name.find(
"O") != std::string::npos) || (
name.find(
"T") != std::string::npos)) {
990 sym_wrt_paxis =
true;
1010 sym_wrt_paxis =
false;
1015 if(sym_wrt_paxis ==
true) {
1082 if(sym_wrt_v ==
true) {
1097 sym_wrt_C2p =
false;
1101 if(sym_wrt_C2p ==
true) {
1109 else if(((sigma_v ==
true) || (C2p ==
true)) && (!all_unique) && (!cubic)) {
1123 else if(((sigma_v ==
true) || (C2p ==
true)) && (!all_unique) && (cubic)) {
1150 int c2z = 0, c2y = 0, c2x = 0;
1208 sym_wrt_inv =
false;
1212 if(sym_wrt_inv ==
true) {
1258 if(sym_wrt_h ==
true) {
1283 std::cerr <<
"WARNING: Failed to name all irreps uniquely... \n";
1319 std::string symtype;
1330 std::vector<SymInfo>
info;
1357 highsym_axes.
clear();
1362 if(highsym_axes.
contains(info[i].axis.cart())) {
1363 mult[highsym_axes.
find(info[i].axis.cart())]++;
1366 highsym_axes.
push_back(info[i].axis.cart());
1372 Eigen::Vector3d hs_axis;
1373 bool hs_axis_set =
false;
1374 double hangle = 360;
1377 if((info[i].angle < hangle) && (info[i].angle >
TOL)) {
1378 hangle = info[i].angle;
1379 hs_axis = info[i].axis.cart();
1385 int order = mult.
max();
1387 for(
int i = (
int(mult.
size()) - 1); i >= 0; i--) {
1388 if((cubic ==
false) && (mult[i] != order)) {
1392 else if(mult[i] < (order - 1)) {
1403 for(
int i =
int(mult.
size()) - 1; i >= 0; i--) {
1405 throw std::runtime_error(
"Error in _generate_class_names: using hs_axis unitialized");
1416 std::string cprime =
"'";
1417 std::string sprime =
"'";
1418 std::string vprime =
"";
1423 std::ostringstream s;
1425 bool normal =
false;
1426 for(
Index j = 0; j < highsym_axes.
size(); j++) {
1427 dprod = highsym_axes[j].dot(info[i].axis.const_cart());
1428 Eigen::Vector3d xprodvec = highsym_axes[j].cross(info[i].axis.const_cart());
1436 if((info[i].angle < 200) && (info[i].angle > 1)) {
1438 angle = info[i].angle;
1446 angle = info[i].angle;
1463 if((info[i].angle < 200) && (info[i].angle > 1)) {
1465 angle = info[i].angle;
1474 angle = info[i].angle;
1504 std::string one =
"1";
1549 stream.precision(3);
1596 bool all_int =
true;
1612 stream <<
"-------";
1614 stream <<
"\n| Group: " <<
name <<
" (" <<
comment <<
")";
1616 for(
int i = 0; i < space; i++) {
1622 stream <<
"-------";
1624 stream << std::endl;
1629 double leftspace = ceil(whitespace);
1630 double rightspace = floor(whitespace);
1631 for(
int j = 0; j < int(leftspace); j++) {
1635 for(
int j = 0; j < int(rightspace); j++) {
1641 stream << std::endl;
1645 stream <<
"-------";
1647 stream << std::endl;
1652 double leftspace = ceil(whitespace);
1653 double rightspace = floor(whitespace);
1654 for(
int j = 0; j < int(leftspace); j++) {
1658 for(
int j = 0; j < int(rightspace); j++) {
1701 stream <<
"i" <<
" |";
1704 stream <<
"-" <<
"i" <<
" |";
1711 stream << std::endl;
1717 stream <<
"-------";
1719 stream << std::endl;
1726 stream <<
"----------------";
1729 stream <<
"\n| Group: " <<
name <<
" (" <<
comment <<
")";
1731 for(
int i = 0; i < space; i++) {
1738 stream <<
"----------------";
1740 stream << std::endl;
1745 double leftspace = ceil(whitespace);
1746 double rightspace = floor(whitespace);
1747 for(
int j = 0; j < int(leftspace); j++) {
1751 for(
int j = 0; j < int(rightspace); j++) {
1756 stream << std::endl;
1759 stream <<
"----------------";
1761 stream << std::endl;
1766 double leftspace = ceil(whitespace);
1767 double rightspace = floor(whitespace);
1768 for(
int j = 0; j < int(leftspace); j++) {
1772 for(
int j = 0; j < int(rightspace); j++) {
1815 stream <<
"i" <<
" |";
1818 stream <<
"-" <<
"i" <<
" |";
1842 stream <<
"----------------";
1866 bool all_commute =
true;
1879 all_commute =
false;
1891 std::cerr <<
"WARNING: This is an empty group. It has no character.\n";
1896 int sigma_h_ind = 0;
1897 Index d1 = 0, d2 = 0, d3 = 0;
1898 Index order1 = 0, order2 = 0;
1900 bool inversion(
false);
1904 std::vector<SymInfo>
info;
1909 std::cerr <<
"WARNING: This is not a group!!!\n";
1933 for(
Index i = 0; i <= nc; i++) {
1934 for(
Index j = 0; j <= nc; j++) {
1935 for(
Index k = 0; k <= nc; k++) {
1936 if(((1 * i + 4 * j + 9 * k) == h) && ((i + j + k) == nc) && (d1 >= d2) && (d1 >= d3)) {
1951 else if(i >= d1 && i < (d1 + d2)) {
1963 std::complex<double> ortho = 0;
1964 int telem = 0, elem1 = 0, elem2 = 0;
1965 int try1 = 0, try2 = 0;
1967 int try1_ind = 0, try2_ind = 0;
1974 bool satisfy_multi_table =
true;
1978 for(
Index i = 0; i < nc; i++) {
1984 for(
Index i = 0; i < nc && check[i]; i++) {
1985 for(
Index j = 0; j < nc && check[i]; j++) {
1986 telem = (count[i] * count[j]);
2001 if((telem != count[try1_ind]) || (telem != count[try2_ind])) {
2012 for(
Index i = 0; i < nc; i++) {
2015 for(
Index j = 0; j < nc; j++) {
2017 std::complex<double> temp = std::complex<double>(double(count[j] *
conjugacy_classes[j].
size()), 0.0);
2026 for(
Index i = 0; i < ortharray.
size(); i++) {
2028 ortho = std::complex<double>(1, 1);
2033 for(
Index i = 0; i < nc; i++) {
2038 satisfy_multi_table =
true;
2041 satisfy_multi_table =
false;
2044 if((ortho == std::complex<double>(0.0, 0.0)) && (satisfy_multi_table ==
true)) {
2045 for(
Index i = 1; i < nc; i++) {
2104 else if(mir ==
true) {
2123 else if(mir ==
true) {
2210 bool generator_found =
false;
2213 if((info[i].angle < angle) && (info[i].angle >
TOL)) {
2214 angle = info[i].angle;
2216 generator_found =
true;
2219 if(!generator_found) {
2220 throw std::runtime_error(
"Error in _generate_character_table: generator not found");
2228 angle = angle * (M_PI / 180);
2230 std::complex<double> iangle(cos(angle), sin(angle));
2236 tchar[0] = std::complex<double>(1, 0);
2237 tchar[generator] = iangle;
2240 Index ind2 = generator;
2242 while(order1 < nc) {
2243 std::complex<double> tangle = iangle;
2247 ind2 = multi_table[ind2][generator];
2258 for(
Index i = 0; i < tchar.size(); i++) {
2259 tcharconj[i] = conj(tchar[i]);
2262 for(
Index i = 0; i < tchar.size(); i++) {
2263 if(std::abs(tchar[i].real()) <
TOL) {
2264 tchar[i] = std::complex<double>(0, tchar[i].imag());
2265 tcharconj[i] = std::complex<double>(0, tcharconj[i].imag());
2267 if(std::abs(tchar[i].imag()) <
TOL) {
2268 tchar[i] = std::complex<double>(tchar[i].real(), 0);
2269 tcharconj[i] = std::complex<double>(tcharconj[i].real(), 0);
2290 for(
Index g = 0; g <
size() && !inv; g++) {
2316 else if((mirror ==
true) || (inversion ==
true) ) {
2331 if(
at(i).
matrix().determinant() > 0) {
2362 for(
Index i = 0; i < subgroup.
size(); i++) {
2413 if(subgroup.
name ==
"C4") {
2418 else if(subgroup.
name ==
"D2") {
2423 else if(subgroup.
name ==
"T") {
2430 if(subgroup.
name ==
"D3") {
2435 else if(subgroup.
name ==
"C3") {
2446 else if(
almost_equal(subgroup[i].matrix()*
at(sigma_h_ind).matrix(),
at(j).matrix(),
TOL) && mirror && !inversion) {
2474 else if((d3 == 0) && (d2 > 0)) {
2478 for(
Index i = 0; i < d1; i++) {
2485 for(
Index i = 1; i < nc; i++) {
2486 if(abs(centrcheck[i] - centralizers[i]) <
TOL) {
2523 else if(mircount == 2) {
2528 else if(mircount == 4) {
2539 else if((d2 == 2) && !subgroup.
size()) {
2543 for(
Index i = 1; i < nc; i++) {
2544 if(abs(centrcheck[i] - centralizers[i]) <
TOL) {
2545 for(
Index j = 0; j < d2; j++) {
2547 remainder[i] = std::complex<double>(0, 0);
2551 remainder[i] = sqrt(abs(centralizers[i] - centrcheck[i]) / 2);
2564 for(
Index i = 0; i < nc; i++) {
2569 trow[i] = signcount[j] * remainder[i].real();
2576 for(
Index i = 0; i < nc; i++) {
2583 for(
Index i = 0; i < d1; i++) {
2585 for(
Index j = 0; j < nc; j++) {
2594 for(
Index i = 0; i < ortharray.
size(); i++) {
2596 ortho = std::complex<double>(1, 1);
2601 if((sum == 0) && (ortho.real() == 0) && (ortho.imag() == 0)) {
2608 if(tset.
size() == d2) {
2609 for(
Index i = 0; i < d2; i++) {
2650 std::complex<double> omega = std::complex<double>(-0.5, 0.866);
2651 for(
Index j = 1; j < nc; j++) {
2655 m_character_table[3][j] = std::complex<double>(-1, 0);
2666 bool sigma_d =
false;
2674 if(sigma_d ==
true) {
2679 for(
Index j = 1; j < nc; j++) {
2683 m_character_table[3][j] = std::complex<double>(-1, 0);
2684 m_character_table[4][j] = std::complex<double>(-1, 0);
2689 m_character_table[3][j] = std::complex<double>(0, 0);
2690 m_character_table[4][j] = std::complex<double>(0, 0);
2695 m_character_table[3][j] = std::complex<double>(1, 0);
2696 m_character_table[4][j] = std::complex<double>(-1, 0);
2701 m_character_table[3][j] = std::complex<double>(-1, 0);
2702 m_character_table[4][j] = std::complex<double>(1, 0);
2707 else if((sigma_d ==
false) && (nc == 5)) {
2711 for(
Index j = 1; j < nc; j++) {
2715 m_character_table[3][j] = std::complex<double>(-1, 0);
2716 m_character_table[4][j] = std::complex<double>(-1, 0);
2721 m_character_table[3][j] = std::complex<double>(0, 0);
2722 m_character_table[4][j] = std::complex<double>(0, 0);
2727 m_character_table[3][j] = std::complex<double>(-1, 0);
2728 m_character_table[4][j] = std::complex<double>(1, 0);
2733 m_character_table[3][j] = std::complex<double>(1, 0);
2734 m_character_table[4][j] = std::complex<double>(-1, 0);
2781 return small_sgroups;
2800 for(j = 0; j < small_sgroups.
size(); j++) {
2801 for(k = 0; k < small_sgroups[j].
size(); k++) {
2802 if(small_sgroups[j][k].
size() == tgroup.
size() && tgroup.
all_in(small_sgroups[j][k]))
2805 if(k < small_sgroups[j].
size())
2808 if(j < small_sgroups.
size())
2815 small_sgroups.
back().push_back(tgroup);
2816 for(k = 1; k < equiv_map.
size(); k++) {
2817 small_sgroups.
back().push_back(small_sgroups.
back()[0]);
2818 for(l = 0; l < small_sgroups.
back()[0].size(); l++) {
2820 small_sgroups.
back()[k][l] =
ind_prod(equiv_map[k][0], tempind);
2824 return small_sgroups;
2839 Index i, j, k, l, m, jj, iii, jjj;
2846 for(j = 0; j < small_subgroups.
size(); j++) {
2848 for(jj = 0; jj < small_subgroups[j].
size(); jj++) {
2852 for(jjj = 0; jjj < small_subgroups[j][jj].
size(); jjj++) {
2853 if(!tgroup1.
contains(small_subgroups[j][jj][jjj])) {
2854 tgroup1.
push_back(small_subgroups[j][jj][jjj]);
2859 for(iii = 0; iii < tgroup1.
size(); iii++) {
2860 for(jjj = 0; jjj < tgroup1.
size(); jjj++) {
2882 for(m = 0; m < tgroup1.
size(); m++) {
2926 std::cout << sgroup.
name <<
"-" << i <<
" has equivalencies:\n";
2935 std::cout <<
"Subgroup " << sg_names[i] <<
"-" << i <<
" is also a subgroup of ";
2940 std::cout << sg_names[j] <<
"-" << j <<
"-" << jj <<
" ";
2950 for(
int i =
int(
m_subgroups.size()) - 1; i >= 0; i--) {
2951 if(chosen_flag[i])
continue;
2953 for(
int j = 0; j < i; j++) {
2954 if(sg_names[j] == sg_names[i]) {
2955 chosen_flag[j] =
true;
2969 std::vector<SymGroup> unique_sgroups;
2972 if(chosen_flag[i])
continue;
2973 unique_sgroups.push_back(
SymGroup());
2977 unique_sgroups.back().sort();
2978 unique_sgroups.back()._generate_character_table();
2980 std::cout <<
"Added group " << unique_sgroups.back().name <<
" having bit-string " <<
m_subgroups[i][0] << std::endl;
2983 return unique_sgroups;
3007 bool dup_class(
false);
3014 if(dup_class)
continue;
3080 assert((
valid_index(i) && i <
irrep_IDs.size()) &&
"Attempting to set ID for out-of-bounds irrep.");
3099 if(!
size() || !
at(0).has_valid_master()) {
3100 std::cerr <<
"CRITICAL ERROR: In SymGroup::get_coord_rep_ID(), SymGroup is improperly initialized.\n"
3110 if(!
size() || !
at(0).has_valid_master()) {
3111 std::cerr <<
"CRITICAL ERROR: In SymGroup::add_empty_representation(), SymGroup is improperly initialized.\n"
3123 throw std::runtime_error(std::string(
"Cannot find irrep ") +
std::to_string(i) +
" in the current SymGroup\n");
3140 assert(
size() % subgroup_inds.
size() == 0 &&
"In SymGroup::left_cosets(), left cosets must be generated by a subgroup of *this SymGroup.");
3144 tcosets.push_back(subgroup_inds);
3145 if(tcosets.back().size() == 0) {
3146 std::cerr <<
"CRITICAL ERROR: In SymGroup::left_cosets(), could not find subgroup within *this group.\n"
3153 for(j = 0; j < tcosets.size(); j++) {
3157 if(j < tcosets.size())
continue;
3159 for(j = 0; j < subgroup_inds.
size(); j++) {
3160 tcosets.back()[j] =
ind_prod(i, subgroup_inds[j]);
3225 std::cerr <<
"WARNING: In SymGroup::get_name(), unable to get symgroup type.\n";
3226 std::cerr <<
"group size is " <<
size() <<
'\n';
3255 for(i = 0; i <
size(); i++) {
3256 for(j = 0; j <
size(); j++) {
3269 std::cerr <<
"Failed to construc multiplication table! Table in progress:\n";
3334 for(
Index i = 0; i < subgroup.
size(); i++) {
3368 while(new_ops &&
size() < max_size) {
3371 SymOp A_op(
at(i).unregistered_copy());
3373 SymOp B_op(
at(j).unregistered_copy());
3375 SymOp tOp(A_op * B_op);
3392 if(
size() >= max_size - 1) {
3393 std::cerr <<
"In SymGroup::enforce_group() -- you have reached the maximum allowed size you specified for your group (the default is 200). Unless you are generating a factor group in a large supercell, you probably need to adjust your tolerances.\n";
3422 std::ofstream outfile;
3423 outfile.open(filename.c_str());
3424 print(outfile, mode);
3432 out <<
size() <<
" # " <<
COORD_MODE::NAME(mode) <<
" representation of group containing " <<
size() <<
" elements:\n\n";
3450 Eigen::Vector3i max_trans(3, 3, 3);
3452 space_group_cell.
clear();
3454 std::vector<SymInfo> sg_info;
3458 trans.
frac() = lat_comb().cast<
double>();
3461 trans = info.location;
3467 bool new_location =
true;
3468 for(
Index j = 0; j < space_group_cell.
size(); j++) {
3470 if(
almost_equal(new_sym.matrix(), space_group_cell[j].matrix()) &&
almost_equal(info.location.const_cart(), sg_info[j].location.const_cart())) {
3471 new_location =
false;
3478 sg_info.push_back(info);
3491 Eigen::Vector3i min_trans,
3492 Eigen::Vector3i max_trans)
const {
3501 trans.
frac() = lat_comb().cast<
double>();
3505 if(!space_group.
contains(new_sym)) {
3523 stream <<
"Locations for symmetry operations\n";
3531 stream << std::endl;
3532 at(i).
print(stream, Eigen::Matrix3d::Identity());
3533 stream << std::endl;
3535 stream <<
"Location:" << std::endl;
3536 stream <<
"FRAC\t\t\t\t\tCART" << std::endl;
3541 stream << std::endl;
3543 if(i + 1 <
size()) {
3551 stream <<
"----------------------------------------------------------------------------------\n\n";
3582 typedef Eigen::Matrix<double, 9, 1> key_type;
3583 auto make_key = [](
const SymOp & op,
const Lattice & lat) {
3590 vec[offset] = -op.
matrix().determinant();
3593 vec[offset] = -op.
matrix().trace();
3596 vec[offset] = info.
angle;
3609 auto op_compare = [
tol](
const key_type & A,
const key_type & B) {
3613 typedef std::map<key_type, SymOp, std::reference_wrapper<decltype(op_compare)> > map_type;
3616 auto cclass_compare = [
tol](
const map_type & A,
const map_type & B) {
3621 std::vector<map_type> sorter;
3624 for(
int i = 0; i <
size(); ++i) {
3639 sorter.push_back(map_type(op_compare));
3640 auto &cclass = sorter.back();
3644 cclass.insert(std::make_pair(make_key(op,
lattice()), op));
3649 std::sort(sorter.begin(), sorter.end(), cclass_compare);
3654 sorter.push_back(map_type(op_compare));
3655 for(
auto it =
begin(); it !=
end(); ++it) {
3656 sorter.back().insert(std::make_pair(make_key(*it,
lattice()), *it));
3662 for(
int i = 0; i < sorter.size(); ++i) {
3663 for(
auto it = sorter[i].
begin(); it != sorter[i].end(); ++it) {
3723 std::complex<double> temp = std::complex<double>(0, 0);
3745 for(
int i = 0; i < json[
"symop"].
size(); ++i) {
3747 auto &j = json[
"symop"][i];
3771 for(
int i = 0; i < json[
"character_table"].
size(); i++) {
3772 json[
"character_table"][i].set_force_row();
3773 for(
int j = 0; j < json[
"character_table"][i].
size(); j++) {
3774 json[
"character_table"][i][j].set_force_row();
3775 json[
"character_table"][i][j][
"real"].set_remove_trailing_zeros();
3776 json[
"character_table"][i][j][
"imag"].set_remove_trailing_zeros();
3801 json[
"name"] =
name;
3838 for(
int i = 0; i < json[
"symop"].
size(); i++) {
3839 push_back(json[
"symop"][i].get<SymOp>());
3897 for(
int i = 0; i < json[
"rotation_groups"].
size(); i++) {
3899 for(
int j = 0; i < json[
"rotation_groups"][i].
size(); j++) {
3900 group.
push_back(json[
"rotation_groups"][i][j].get<SymOp>());
3945 if(coord_map.empty()) {
3946 std::cerr <<
"SymGroup molecular_point_group found an empty coord_map\n"
3947 <<
"Exiting ... " << std::endl;
3953 int map_size = coord_map.size();
3955 int num_elements = 0;
3956 for(
auto const &map_entry : coord_map) {
3957 num_elements += map_entry.second.size();
3964 Index col_counter = 0;
3965 Eigen::Vector3d center(0., 0., 0.);
3966 Eigen::Vector3d mol_center(0., 0., 0.);
3967 for(
auto map_entry : coord_map) {
3968 for(
Index i = 0; i < map_entry.second.size() ; i++) {
3970 coord_matrix.col(col_counter) = map_entry.second.at(i);
3971 mol_center += map_entry.second.at(i);
3975 mol_center /= num_elements;
3976 std::cout <<
" found center at: " << mol_center << std::endl;
3980 Eigen::Vector3d origin(0., 0., 0.);
3981 for(
auto it = coord_map.begin(); it != coord_map.end();) {
3982 if(it->second.size() == 1 && it->second.at(0) == origin) {
3983 it = coord_map.erase(it);
3994 if(center != mol_center) {
3995 for(
auto &map_entry : coord_map) {
3997 for(
Index i = 0; i < map_entry.second.size() ; i++) {
3999 coord_map[map_entry.first].at(i) -= mol_center;
4013 for(
auto &map_entry : coord_map) {
4014 for(
Index i = 0; i < map_entry.second.size() ; i++) {
4016 coord_matrix.col(col_counter) = map_entry.second.at(i);
4033 bool is_linear =
false;
4034 bool is_planar =
false;
4040 if(coord_matrix.colPivHouseholderQr().rank() == 1) {
4044 else if(coord_matrix.colPivHouseholderQr().rank() == 2) {
4046 std::cout <<
" rank == 2 " << std::endl;
4051 bool is_unique =
false;
4053 if(coord_map.count(map_size - 1) == 0) {
4068 std::vector<Eigen::Matrix3d> sym_ops;
4081 Eigen::Vector3d tmp_coord;
4086 if(is_planar && !is_linear) {
4087 std::cout <<
" In is_planar" << std::endl;
4088 Eigen::Vector3d disp1;
4089 disp1 = (coord_map.at(0).at(0) - coord_map.at(0).at(1));
4090 Eigen::Vector3d disp2;
4091 disp2 = (coord_map.at(0).at(2) - coord_map.at(0).at(1));
4092 Eigen::Vector3d normal_vector;
4093 normal_vector = (disp1.cross(disp2));
4096 std::vector<Eigen::Vector3d> norm_vecs {normal_vector, -normal_vector};
4097 std::cout <<
"Norm vecs 1 " << norm_vecs.at(0) << std::endl;
4098 std::cout <<
"Norm vecs 2 " << norm_vecs.at(1) << std::endl;
4099 coord_map[map_size] = norm_vecs;
4112 std::vector<std::vector<Eigen::Vector3d> > curr_buckets(3);
4117 for(i = 0; i < map_size - 2; i++) {
4118 for(j = i + 1; j < map_size - 1; j++) {
4119 for(k = j + 1; k < map_size; k++) {
4125 for(
Index i = 0; i < 3; ++i) {
4126 for(
Index j = 0; j < 3; ++j) {
4128 if(a(i, j) < b(i, j))
return true;
4129 if(a(i, j) > b(i, j))
return false;
4135 return a.isApprox(b, 0.00001);
4138 curr_buckets[0] = coord_map.at(i);
4139 curr_buckets[1] = coord_map.at(j);
4140 curr_buckets[2] = coord_map.at(k);
4142 for(
Index ii = 0; ii < curr_buckets.at(0).size(); ii++) {
4143 for(
Index jj = 0; jj < curr_buckets.at(1).size(); jj++) {
4144 for(
Index kk = 0; kk < curr_buckets.at(2).size(); kk++) {
4146 tmp_coord = curr_buckets.at(0)[ii];
4147 init_cluster.col(0) = tmp_coord;
4148 tmp_coord = curr_buckets.at(1)[jj];
4149 init_cluster.col(1) = tmp_coord;
4150 tmp_coord = curr_buckets.at(2)[kk];
4151 init_cluster.col(2) = tmp_coord;
4155 std::cout <<
"my init_cluster:\n" << init_cluster << std::endl;
4157 if(init_cluster.colPivHouseholderQr().rank() == 3) {
4158 inv_init = init_cluster.inverse();
4165 for(
Index iii = 0; iii < curr_buckets.at(0).size(); iii++) {
4166 for(
Index jjj = 0; jjj < curr_buckets.at(1).size(); jjj++) {
4167 for(
Index kkk = 0; kkk < curr_buckets.at(2).size(); kkk++) {
4170 tmp_coord = curr_buckets.at(0)[iii];
4171 test_cluster.col(0) = tmp_coord;
4172 tmp_coord = curr_buckets.at(1)[jjj];
4173 test_cluster.col(1) = tmp_coord;
4174 tmp_coord = curr_buckets.at(2)[kkk];
4175 test_cluster.col(2) = tmp_coord;
4180 S = test_cluster * inv_init;
4182 std::cout <<
"my S:\n" << S << std::endl;
4183 if(S.isUnitary(1e-6) && !(S.isIdentity(1e-8))) {
4184 std::cout <<
"keeper:\n" << S << std::endl;
4188 sym_ops.push_back(S);
4211 if(map_size <= 2 && num_elements > 2) {
4214 if(map_size > 1 && coord_map.at(0).size() != 1) {
4215 std::vector<Eigen::Vector3d> &single_atom = coord_map[1];
4216 std::vector<Eigen::Vector3d> &multi_atom = coord_map[0];
4229 for(
Index comb = 0; comb < 4; comb++) {
4231 std::cout <<
"in for" << std::endl;
4235 if(comb == 0 && coord_map.at(0).size() > 2) {
4236 std::cout <<
"in comb 0" << std::endl;
4237 curr_buckets[0] = coord_map.at(0);
4238 curr_buckets[1] = coord_map.at(0);
4239 curr_buckets[2] = coord_map.at(0);
4241 else if(comb == 0) {
4246 if(map_size > 1 && comb == 1 && coord_map.at(1).size() > 2) {
4247 std::cout <<
"in comb 1" << std::endl;
4248 curr_buckets[0] = coord_map.at(1);
4249 curr_buckets[1] = coord_map.at(1);
4250 curr_buckets[2] = coord_map.at(1);
4252 else if(comb == 1)
continue;
4256 if(map_size > 1 && comb == 2 && coord_map.at(0).size() > 1) {
4257 std::cout <<
"in comb 2" << std::endl;
4258 curr_buckets[0] = coord_map.at(0);
4259 curr_buckets[1] = coord_map.at(0);
4260 curr_buckets[2] = coord_map.at(1);
4262 else if(comb == 2)
continue;
4267 if(map_size > 1 && comb == 3 && coord_map.at(1).size() > 1) {
4268 std::cout <<
"in comb 3" << std::endl;
4269 curr_buckets[0] = coord_map.at(1);
4270 curr_buckets[1] = coord_map.at(1);
4271 curr_buckets[2] = coord_map.at(0);
4273 else if(comb == 3)
continue;
4281 for(
Index ii = 0; ii < curr_buckets.at(0).size(); ++ii) {
4291 for(
Index i = 0; i < 3; ++i) {
4292 for(
Index j = 0; j < 3; ++j) {
4294 if(a(i, j) < b(i, j))
return true;
4295 if(a(i, j) > b(i, j))
return false;
4301 return a.isApprox(b, 0.00001);
4305 for(
Index jj = 0; jj < curr_buckets.at(1).size(); ++jj) {
4307 for(
Index kk = 0; kk < curr_buckets.at(2).size(); ++kk) {
4309 tmp_coord = curr_buckets.at(0)[ii];
4310 init_cluster.col(0) = tmp_coord;
4311 tmp_coord = curr_buckets.at(1)[jj];
4312 init_cluster.col(1) = tmp_coord;
4313 tmp_coord = curr_buckets.at(2)[kk];
4314 init_cluster.col(2) = tmp_coord;
4322 if(init_cluster.colPivHouseholderQr().rank() == 3) {
4323 inv_init = init_cluster.inverse();
4329 for(
Index iii = 0; iii < curr_buckets.at(0).size(); ++iii) {
4330 for(
Index jjj = 0; jjj < curr_buckets.at(1).size(); ++jjj) {
4331 for(
Index kkk = 0; kkk < curr_buckets.at(2).size(); ++kkk) {
4334 tmp_coord = curr_buckets.at(0)[iii];
4335 test_cluster.col(0) = tmp_coord;
4336 tmp_coord = curr_buckets.at(1)[jjj];
4337 test_cluster.col(1) = tmp_coord;
4338 tmp_coord = curr_buckets.at(2)[kkk];
4339 test_cluster.col(2) = tmp_coord;
4344 S = test_cluster * inv_init;
4346 if(S.isUnitary(1e-6) && !(S.isIdentity(1e-8))) {
4349 sym_ops.push_back(S);
4464 if(num_elements == 2) {
4466 inv_mat << -1., 0., 0.,
4469 sym_ops.push_back(inv_mat);
4476 for(
Index i = 0; i < 3; ++i) {
4477 for(
Index j = 0; j < 3; ++j) {
4479 if(a(i, j) < b(i, j))
return true;
4480 if(a(i, j) > b(i, j))
return false;
4491 return a.isApprox(b, 0.00001);
4506 std::vector<bool> sym_bools(sym_ops.size(),
true);
4507 std::cout <<
" PRE TEST Sym_ops size() " << sym_ops.size() << std::endl;
4509 for(
Index so = 0; so < sym_ops.size(); so++) {
4513 for(
auto map_entry : coord_map) {
4514 std::vector<Eigen::Vector3d> sym_species_vec;
4516 for(
Index v = 0; v < map_entry.second.size(); v++) {
4518 sym_species_vec.push_back(sym_ops[so] * map_entry.second.at(v));
4520 std::vector<bool> sym_species_bools(sym_species_vec.size(),
false);
4525 for(
Index ov = 0 ; ov < map_entry.second.size(); ov++) {
4528 tmp_coord = map_entry.second.at(ov);
4529 auto found = std::find_if(sym_species_vec.begin(), sym_species_vec.end(), [&tmp_coord](Eigen::Vector3d a) {
4530 return a.isApprox(tmp_coord, 1e-5);
4533 if(found != sym_species_vec.end()) {
4538 sym_bools[so] =
false;
4542 sym_species_vec.clear();
4548 int vec_counter = 0;
4549 std::vector<Eigen::Matrix3d> final_ops;
4550 for(
auto ind : sym_bools) {
4553 final_ops.push_back(sym_ops.at(vec_counter));
4559 for(
Index mat = 0; mat < final_ops.size(); mat++) {
4609 for(
int i = 0; i < json[
"rep_array"].
size(); i++) {
SymGroupRepID add_rotation_rep() const
size_type size() const
Returns array size if *this is a JSON array, object size if *this is a JSON object, 1 otherwise.
PERIODICITY_TYPE m_group_periodicity
Specifies whether to use lattice periodicity when testing for equivalence.
Coordinate location
A Cartesian coordinate that is invariant to the operation (if one exists)
double angle(const Eigen::Ref< const Eigen::Vector3d > &a, const Eigen::Ref< const Eigen::Vector3d > &b)
Get angle, in radians, between two vectors on range [0,pi].
virtual void sort()
Sort SymOp in the SymGroup.
jsonParser & to_json(jsonParser &json) const
Array< Array< Index > > multi_table
multi_table[i][j] gives index of operation that is result of at(i)*at(j)
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Index rep_index() const
Index of SymGroupRep within the master group Used internally to MasterSymGroup to access the correct ...
void calc_space_group_in_cell(SymGroup &space_group, const Lattice &_cell) const
SymInfo info(Index i) const
void _generate_centralizers() const
static SymOp translation(const Eigen::Ref< const vector_type > &_tau)
static method to create operation that describes pure translation
bool contains(const T &test_elem) const
ReturnArray< Array< Index > > left_cosets(const Array< SymOp > &subgroup, double tol=TOL) const
void from_json(ClexDescription &desc, const jsonParser &json)
Array< Array< Index > > alt_multi_table
alt_multi_table[i][j] gives index of operation that is result of at(i).inverse()*at(j) ...
A Counter allows looping over many incrementing variables in one loop.
Coordinate_impl::CartCoordinate cart()
Set Cartesian coordinate vector and update fractional coordinate vector.
Index which_unique_combination(const Array< Index > &input, const Array< Index >::X2 &unique, const Array< Index >::X2 &ind_equiv)
Type-safe ID object for communicating and accessing Symmetry representation info. ...
SymGroup & apply_sym(const SymOp &op)
Calls 'apply_sym' on all SymOps in the group.
bool empty() const
Returns true if SymGroupRepID has not been initialized with valid group_index or rep_index.
void get_rotation_groups() const
Space group (added by Donghee );.
void write(std::string filename, COORD_TYPE mode) const
Write the SymGroup to a file.
bool has_valid_master() const
check if this representation is registered with a MasterSymGroup
SymGroupRepID add_direct_sum_rep(const Array< SymGroupRepID > &rep_IDs) const
void push_back(const T &toPush)
SymGroupRepID add_transformed_rep(SymGroupRepID orig_ID, const Eigen::MatrixXd &trans_mat) const
bool float_lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, double tol)
Floating point lexicographical comparison with tol.
const SymGroup & point_group() const
jsonParser & to_json(const ClexDescription &desc, jsonParser &json)
void set_index(const MasterSymGroup &new_group, Index new_index)
bool is_identity() const
Returns true if SymGroupRepID corresponds to an Identity representation.
SymGroupRepID add_empty_representation() const
Add a new empty representation.
Array< SymGroupRep * > m_rep_array
Index index() const
Index of this operation within the master_group.
SymGroupRepID m_coord_rep_ID
ID of Cartesian representation.
SymGroup molecular_point_group(std::map< int, std::vector< Eigen::Vector3d > > coord_map)
SymGroupRepID add_kronecker_rep(SymGroupRepID ID1, SymGroupRepID ID2) const
Array< std::string > irrep_names
std::string to_string(ENUM val)
Return string representation of enum class.
Array< Array< Index > > elem_order_table
Array< std::string > group_name
SymGroupRepID coord_rep_ID() const
Get symrep ID of the representation that stores the Cartesian symop matrices.
Lattice const * m_lat_ptr
Pointer to a lattice for doing periodic comparisons.
void push_back(const SymOp &op)
Index ind_inverse(Index i) const
Get index of operation that is inverse of operation at(i)
const vector_type & const_cart() const
user override to force const Access the Cartesian coordinate vector
Array & operator=(const Array &RHS)
void print(std::ostream &out, COORD_TYPE mode) const
Print the SymGroup to a stream.
bool is_identity() const
returns true if matrix part of operation is identity
const Array< Index >::X2 & get_multi_table() const
const vector_type & const_frac() const
user override to force const Access the fractional coordinate vector
Array< Index >::X3 _small_subgroups() const
void print_locations(std::ostream &stream) const
print locations of the symmetry-generating element of each SymOp
Index group_index() const
jsonParser & to_json(jsonParser &json) const
Index group_index() const
Index of master group in which the corresponding SymGroupRep is stored Used internally to MasterSymGr...
void swap(ConfigDoF &A, ConfigDoF &B)
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
MasterSymGroup & operator=(const MasterSymGroup &RHS)
bool is_irreducible() const
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...
SymGroupRep const & coord_rep() const
void _generate_subgroups() const
const double & map_error() const
Allows access to the map_error.
SymOp is the Coordinate representation of a symmetry operation it keeps fraction (FRAC) and Cartesian...
SymGroupRep const & get_irrep(Index i) const
Get symrep for a particular irrep.
Represents cartesian and fractional coordinates.
Array< Array< Index > > centralizer_table
Simple struct to be used as return type for SymOp::info().
void _generate_character_table() const
Eigen::MatrixXd const * get_MatrixXd(Index i) const
SymOp within_cell(const SymOp &a, const Lattice &lat, PERIODICITY_TYPE periodicity)
double max_error()
This returns the group's max_error.
EigenIndex Index
For long integer indexing:
SymGroupRepID _add_coord_rep() const
void set_irrep_ID(Index i, SymGroupRepID ID) const
set symrep ID of a particular irrep
const Array< std::complex< double > >::X2 & character_table() const
const Array< Index >::X3 & subgroups() const
Eigen::Matrix< typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime > inverse(const Eigen::MatrixBase< Derived > &M)
Return the integer inverse matrix of an invertible integer matrix.
void add_sym_info(const SymInfo &info, jsonParser &j)
Add to existing JSON object.
Array< Array< Index > > conjugacy_classes
const MasterSymGroup & master_group() const
const access of head group
ReturnArray< Index > get_irrep_decomposition() const
bool is_within() const
Checks to see if coordinate is in the unit cell, but does not translate it.
const Array< Index >::X2 & get_alt_multi_table() const
Array< int > group_number
void invalidate_multi_tables() const
void enforce_group(double tol=TOL, Index max_size=200)
Enforce group property by adding products of operations to the group.
bool contains_periodic(const SymOp &test_op, double tol=TOL) const
Check to see if a SymOp is contained in in SymGroup.
SymOp inverse() const
get the inverse of this SymOp
void _generate_conjugacy_classes() const
void _generate_elem_order_table() const
const Array< Index >::X2 & get_conjugacy_classes() const
SymGroupRepID _add_representation(SymGroupRep *_rep_ptr) const
Array< Array< std::complex< double > > > m_character_table
SymGroupRepID reg_rep_ID() const
Index find_no_trans(const SymOp &test_op) const
Check to see if a SymOp is contained in in SymGroup and return its index.
void _generate_alt_multi_table() const
std::string description(const SymOp &op, const Lattice &lat, COORD_TYPE mode)
Print SymInfo to string.
Index find(const SymOp &test_elem) const
bool is_group(double tol=TOL) const
Check to see if SymGroup satisfies the group property.
void from_json(const jsonParser &json)
MasterSymGroup(PERIODICITY_TYPE init_type=PERIODIC)
std::vector< SymGroup > unique_subgroups() const
SymGroupRepID get_irrep_ID(Index i) const
Get symrep ID of a particular irrep.
const Lattice & lattice() const
Array & append(const Array &new_tail)
Index find_periodic(const SymOp &test_op, double tol=TOL) const
static std::string NAME()
get a string with the name of the active mode
Generalized symmetry matrix representation for arbitrary dimension Can be used to describe applicatio...
bool check(std::string test, const jsonParser &expected, const jsonParser &calculated, fs::path test_cases_path, bool quiet, double tol=0.0)
Check expected JSON vs calculated JSON using BOOST_CHECK_EQUAL.
SymGroup m_point_group
Copy of *this with translations removed.
bool all_in(const Array &superset) const
PERIODICITY_TYPE periodicity() const
SymGroupRep const & reg_rep() const
jsonParser & put_obj()
Puts new empty JSON object.
Array< SymGroupRepID > irrep_IDs
virtual void push_back(const SymOp &new_op)
Array< std::string > class_names
jsonParser & put(const T &value)
Puts data of any type T for which 'jsonParser& to_json( const T &value, jsonParser &json)' is defined (same as 'o...
void reserve(Index new_max)
SymGroupRepID m_reg_rep_ID
ID of 'regular representation', which is (size() X size()) representation constructed from alt_multi_...
void sort(const CompareType &comp)
jsonParser & push_back(const T &value)
Puts new valued element at end of array of any type T for which 'jsonParser& to_json( const T &value...
void copy_no_trans(SymGroup &shiftless, bool keep_repeated=false) const
Fill up a SymGroup with *this minus the shifts.
void print(std::ostream &stream, const Eigen::Ref< const matrix_type > &c2fmat=matrix_type::Identity()) const
SymGroup(PERIODICITY_TYPE init_type=PERIODIC)
Initialize by setting periodicity mode (default mode is PERIODIC)
SymGroupRep coord_transformed_copy(const Eigen::MatrixXd &trans_mat) const
SymGroupRep * _representation_ptr(SymGroupRepID _id) const
Coordinate_impl::FracCoordinate frac()
Set the fractional coordinate vector.
SymOp & apply_sym(const SymOp &op)
const vector_type & tau() const
Const access of the cartesian translation vector, 'tau'.
void set_lattice(const Lattice &new_lat)
SymGroupRepID _add_reg_rep() const
SymGroupRep is an alternative representation of a SymGroup for something other than real space...
const std::string & get_latex_name() const
void print_space_group_info(std::ostream &out) const
SymGroupRepID coord_rep_ID() const
Array< Array< SymOp > > rotation_groups
Space group (added by Donghee );.
Index class_of_op(Index i) const
Get conjugacy class index of operation at(i)
void from_json(const jsonParser &json)
void _generate_class_names() const
void _generate_irrep_names() const
const std::string & get_name() const
const Array< bool > & get_complex_irrep_list() const
Array< Index > index2conjugacy_class
SymGroupRepID identity_rep_ID(Index dim) const
Array< SymGroupRepID > m_identity_rep_IDs
identity representations: m_identity_rep_IDs[dim] refers to the Identity representation of dimention ...
bool _generate_multi_table() const
SymGroupRepID add_representation(const SymGroupRep &new_rep) const
Add a new representation by passing a reference. SymGroup will store a copy.
void print_character_table(std::ostream &stream)
Index ind_prod(Index i, Index j) const
Get index of operation that is result of multiplication of at(i)*at(j)
SymGroupRepID add_empty_representation() const
Add a new empty representation.
SymGroupRep * copy() const
Basic std::vector like container (deprecated)
ReturnArray< Index > find_all_periodic(const Array< SymOp > &subgroup, double tol=TOL) const
jsonParser & put_array()
Puts new empty JSON array.
void calc_space_group_in_range(SymGroup &space_group, const Lattice &_cell, Eigen::Vector3i min_trans, Eigen::Vector3i max_trans) const
std::string crystal_system
void get_point_group_type() const
bool almost_equal(const GenericCluster< CoordType > &LHS, const GenericCluster< CoordType > &RHS, double tol)
SymGroup & operator+=(const Eigen::Ref< const SymOp::vector_type > &shift)
Cartesian translation of SymGroup origin by vector 'shift'.
Array< bool > complex_irrep
Array< Array< Array< Index > > > m_subgroups
static Index GROUP_COUNT
Counts number of instantiated MasterSymGroups, excluding ones created via copy.
bool compare_periodic(const SymOp &a, const SymOp &b, const Lattice &lat, PERIODICITY_TYPE periodicity, double _tol)
SymGroup & operator-=(const Eigen::Ref< const SymOp::vector_type > &shift)
ReturnArray< Index > op_indices() const
bool valid_index(Index i)
SymGroupRep const & representation(SymGroupRepID i) const
Const access of alternate Representations of a SymGroup.
void sort()
Sort SymOp in the SymGroup.
virtual void clear_tables()
void set_rep(const SymOpRepresentation &base_rep, const SymOpRepresentation &new_rep) const