static PointSymmetry get_lattice_symmetry(SPGCONST Cell *cell, const double symprec) { int i, j, k, num_sym; int axes[3][3]; double lattice[3][3], min_lattice[3][3]; double metric[3][3], metric_orig[3][3]; PointSymmetry lattice_sym; debug_print("get_lattice_symmetry:\n"); if (! lat_smallest_lattice_vector(min_lattice, cell->lattice, symprec)) { goto err; } mat_get_metric(metric_orig, min_lattice); num_sym = 0; for (i = 0; i < 26; i++) { for (j = 0; j < 26; j++) { for (k = 0; k < 26; k++) { set_axes(axes, i, j, k); if (! ((mat_get_determinant_i3(axes) == 1) || (mat_get_determinant_i3(axes) == -1))) { continue; } mat_multiply_matrix_di3(lattice, min_lattice, axes); mat_get_metric(metric, lattice); if (is_identity_metric(metric, metric_orig, symprec)) { mat_copy_matrix_i3(lattice_sym.rot[num_sym], axes); num_sym++; } if (num_sym > 48) { warning_print("spglib: Too many lattice symmetries was found.\n"); warning_print(" Tolerance may be too large "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); goto err; } } } } lattice_sym.size = num_sym; return transform_pointsymmetry(&lattice_sym, cell->lattice, min_lattice); err: lattice_sym.size = 0; return lattice_sym; }
/* Reference can be found in International table A. */ static int get_Delaunay_reduction( double red_lattice[3][3], SPGCONST double lattice[3][3], const double symprec ) { int i, j; double volume; double basis[4][3]; get_exteneded_basis(basis, lattice); while (1) { if (get_Delaunay_reduction_basis(basis, symprec)) { break; } } get_Delaunay_shortest_vectors( basis, symprec ); for ( i = 0; i < 3; i++ ) { for ( j = 0; j < 3; j++ ) { red_lattice[i][j] = basis[j][i]; } } volume = mat_get_determinant_d3( red_lattice ); if ( mat_Dabs( volume ) < symprec ) { warning_print("spglib: Minimum lattice has no volume (line %d, %s).\n", __LINE__, __FILE__); goto err; } if ( volume < 0 ) { /* Flip axes */ for (i = 0; i < 3; i++) { for ( j = 0; j < 3; j++ ) { red_lattice[i][j] = -red_lattice[i][j]; } } } #ifdef DEBUG debug_print("Delaunay reduction:\n"); debug_print_matrix_d3(red_lattice); double metric[3][3]; mat_get_metric( metric, red_lattice ); debug_print("It's metric tensor.\n"); debug_print_matrix_d3( metric ); #endif return 1; err: return 0; }
static void get_conventional_lattice(double lattice[3][3], SPGCONST Spacegroup *spacegroup) { int i, j; double metric[3][3]; Pointgroup pointgroup; pointgroup = ptg_get_pointgroup(spacegroup->pointgroup_number); for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { lattice[i][j] = 0; } } mat_get_metric(metric, spacegroup->bravais_lattice); debug_print("bravais lattice\n"); debug_print_matrix_d3(spacegroup->bravais_lattice); debug_print("%s\n", spacegroup->setting); switch (pointgroup.holohedry) { case TRICLI: set_tricli(lattice, metric); break; case MONOCLI: /* b-axis is the unique axis. */ set_monocli(lattice, metric); break; case ORTHO: set_ortho(lattice, metric); break; case TETRA: set_tetra(lattice, metric); break; case TRIGO: if (spacegroup->setting[0] == 'R') { set_rhomb(lattice, metric); } else { set_trigo(lattice, metric); } break; case HEXA: set_trigo(lattice, metric); break; case CUBIC: set_cubic(lattice, metric); break; case HOLOHEDRY_NONE: break; } }
static int get_conventional_lattice(double lattice[3][3], const Holohedry holohedry, SPGCONST double bravais_lattice[3][3]) { int i, j; double metric[3][3]; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { lattice[i][j] = 0; } } mat_get_metric(metric, bravais_lattice); switch (holohedry) { case TRICLI: mat_copy_matrix_d3(lattice, bravais_lattice); break; case MONOCLI: /* b-axis is the unique axis. */ set_monocli(lattice, metric); break; case ORTHO: set_ortho(lattice, metric); break; case TETRA: set_tetra(lattice, metric); break; case RHOMB: set_rhomb(lattice, metric); break; case TRIGO: set_trigo(lattice, metric); break; case HEXA: set_trigo(lattice, metric); break; case CUBIC: set_cubic(lattice, metric); break; case NONE: break; } return 1; }
static void set_rhomb(double lattice[3][3], SPGCONST double metric[3][3]) { double a, b, c, angle, ahex, chex; a = sqrt(metric[0][0]); b = sqrt(metric[1][1]); c = sqrt(metric[2][2]); angle = acos((metric[0][1] / a / b + metric[0][2] / a / c + metric[1][2] / b / c) / 3); /* Reference, http://cst-www.nrl.navy.mil/lattice/struk/rgr.html */ ahex = 2 * (a+b+c)/3 * sin(angle / 2); chex = (a+b+c)/3 * sqrt(3 * (1 + 2 * cos(angle))) ; lattice[0][0] = ahex / 2; lattice[1][0] = -ahex / (2 * sqrt(3)); lattice[2][0] = chex / 3; lattice[1][1] = ahex / sqrt(3); lattice[2][1] = chex / 3; lattice[0][2] = -ahex / 2; lattice[1][2] = -ahex / (2 * sqrt(3)); lattice[2][2] = chex / 3; #ifdef DEBUG debug_print("Rhombo lattice: %f %f %f %f %f %f\n", a, b, c, acos(metric[0][1] / a / b) / 3.14 * 180, acos(metric[0][2] / a / c) / 3.14 * 180, acos(metric[1][2] / b / c) / 3.14 * 180); double dmetric[3][3]; mat_get_metric(dmetric, lattice); a = sqrt(dmetric[0][0]); b = sqrt(dmetric[1][1]); c = sqrt(dmetric[2][2]); debug_print("Rhombo lattice symmetrized: %f %f %f %f %f %f\n", a, b, c, acos(dmetric[0][1] / a / b) / 3.14 * 180, acos(dmetric[0][2] / a / c) / 3.14 * 180, acos(dmetric[1][2] / b / c) / 3.14 * 180); #endif }
static PointSymmetry get_lattice_symmetry(SPGCONST double cell_lattice[3][3], const double symprec, const double angle_symprec) { int i, j, k, attempt, num_sym; double angle_tol; int axes[3][3]; double lattice[3][3], min_lattice[3][3]; double metric[3][3], metric_orig[3][3]; PointSymmetry lattice_sym; debug_print("get_lattice_symmetry:\n"); lattice_sym.size = 0; if (! del_delaunay_reduce(min_lattice, cell_lattice, symprec)) { goto err; } mat_get_metric(metric_orig, min_lattice); angle_tol = angle_symprec; for (attempt = 0; attempt < 100; attempt++) { num_sym = 0; for (i = 0; i < 26; i++) { for (j = 0; j < 26; j++) { for (k = 0; k < 26; k++) { set_axes(axes, i, j, k); if (! ((mat_get_determinant_i3(axes) == 1) || (mat_get_determinant_i3(axes) == -1))) { continue; } mat_multiply_matrix_di3(lattice, min_lattice, axes); mat_get_metric(metric, lattice); if (is_identity_metric(metric, metric_orig, symprec, angle_tol)) { if (num_sym > 47) { angle_tol *= ANGLE_REDUCE_RATE; warning_print("spglib: Too many lattice symmetries was found.\n"); warning_print(" Reduce angle tolerance to %f", angle_tol); warning_print(" (line %d, %s).\n", __LINE__, __FILE__); goto next_attempt; } mat_copy_matrix_i3(lattice_sym.rot[num_sym], axes); num_sym++; } } } } if (num_sym < 49 || angle_tol < 0) { lattice_sym.size = num_sym; return transform_pointsymmetry(&lattice_sym, cell_lattice, min_lattice); } next_attempt: ; } err: debug_print("get_lattice_symmetry failed.\n"); return lattice_sym; }