static Cell * get_cell_with_smallest_lattice( SPGCONST Cell * cell, const double symprec ) { int i, j; double min_lat[3][3], trans_mat[3][3], inv_lat[3][3]; Cell * smallest_cell; if ( lat_smallest_lattice_vector( min_lat, cell->lattice, symprec ) ) { mat_inverse_matrix_d3( inv_lat, min_lat, 0 ); mat_multiply_matrix_d3( trans_mat, inv_lat, cell->lattice ); smallest_cell = cel_alloc_cell( cell->size ); mat_copy_matrix_d3( smallest_cell->lattice, min_lat ); for ( i = 0; i < cell->size; i++ ) { smallest_cell->types[i] = cell->types[i]; mat_multiply_matrix_vector_d3( smallest_cell->position[i], trans_mat, cell->position[i] ); for ( j = 0; j < 3; j++ ) { cell->position[i][j] -= mat_Nint( cell->position[i][j] ); } } } else { smallest_cell = cel_alloc_cell( -1 ); } return smallest_cell; }
static int find_primitive(double lattice[3][3], double position[][3], int types[], const int num_atom, const double symprec) { int i, num_prim_atom=0; Cell *cell, *primitive; cell = cel_alloc_cell(num_atom); cel_set_cell(cell, lattice, position, types); /* find primitive cell */ primitive = prm_get_primitive(cell, symprec); if (primitive->size == cell->size) { /* Already primitive */ num_prim_atom = 0; } else { /* Primitive cell was found. */ num_prim_atom = primitive->size; if (num_prim_atom < num_atom && num_prim_atom > 0 ) { mat_copy_matrix_d3(lattice, primitive->lattice); for (i = 0; i < primitive->size; i++) { types[i] = primitive->types[i]; mat_copy_vector_d3(position[i], primitive->position[i]); } } } cel_free_cell(primitive); cel_free_cell(cell); return num_prim_atom; }
int spg_refine_cell( double lattice[3][3], double position[][3], int types[], const int num_atom, const double symprec ) { int i, num_atom_bravais; Cell *cell, *bravais; cell = cel_alloc_cell( num_atom ); cel_set_cell( cell, lattice, position, types ); bravais = ref_refine_cell( cell, symprec ); cel_free_cell( cell ); if ( bravais->size > 0 ) { mat_copy_matrix_d3( lattice, bravais->lattice ); num_atom_bravais = bravais->size; for ( i = 0; i < bravais->size; i++ ) { types[i] = bravais->types[i]; mat_copy_vector_d3( position[i], bravais->position[i] ); } } else { num_atom_bravais = 0; } cel_free_cell( bravais ); return num_atom_bravais; }
static Cell * expand_positions(SPGCONST Cell * conv_prim, SPGCONST Symmetry * conv_sym) { int i, j, k, num_pure_trans; int num_atom; Cell * bravais; num_pure_trans = get_number_of_pure_translation(conv_sym); bravais = cel_alloc_cell(conv_prim->size * num_pure_trans); num_atom = 0; for (i = 0; i < conv_sym->size; i++) { /* Referred atoms in Bravais lattice */ if (mat_check_identity_matrix_i3(identity, conv_sym->rot[i])) { for (j = 0; j < conv_prim->size; j++) { bravais->types[num_atom] = conv_prim->types[j]; mat_copy_vector_d3(bravais->position[ num_atom ], conv_prim->position[j]); for (k = 0; k < 3; k++) { bravais->position[num_atom][k] += conv_sym->trans[i][k]; bravais->position[num_atom][k] = mat_Dmod1(bravais->position[num_atom][k]); } num_atom++; } } } mat_copy_matrix_d3(bravais->lattice, conv_prim->lattice); return bravais; }
static int refine_cell(double lattice[3][3], double position[][3], int types[], const int num_atom, const double symprec) { int i, n_brv_atoms; SpglibDataset *dataset; n_brv_atoms = 0; dataset = NULL; if ((dataset = get_dataset(lattice, position, types, num_atom, 0, symprec)) == NULL) { return 0; } n_brv_atoms = dataset->n_brv_atoms; mat_copy_matrix_d3(lattice, dataset->brv_lattice); for (i = 0; i < dataset->n_brv_atoms; i++) { types[i] = dataset->brv_types[i]; mat_copy_vector_d3(position[i], dataset->brv_positions[i]); } spg_free_dataset(dataset); return n_brv_atoms; }
static Spacegroup get_spacegroup(SPGCONST Cell * primitive, const double symprec) { int hall_number; double conv_lattice[3][3]; double origin_shift[3]; Symmetry *symmetry; Spacegroup spacegroup; SpacegroupType spacegroup_type; symmetry = sym_get_operation(primitive, symprec); if (symmetry->size == 0) { spacegroup.number = 0; warning_print("spglib: Space group could not be found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); goto ret; } hall_number = get_hall_number(origin_shift, conv_lattice, primitive, symmetry, symprec); if (hall_number == 0) { spacegroup.number = 0; warning_print("spglib: Space group could not be found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); goto ret; } spacegroup_type = spgdb_get_spacegroup_type(hall_number); if (spacegroup_type.number > 0) { mat_copy_matrix_d3(spacegroup.bravais_lattice, conv_lattice); mat_copy_vector_d3(spacegroup.origin_shift, origin_shift); spacegroup.number = spacegroup_type.number; spacegroup.hall_number = hall_number; spacegroup.holohedry = spacegroup_type.holohedry; strcpy(spacegroup.schoenflies, spacegroup_type.schoenflies); strcpy(spacegroup.hall_symbol, spacegroup_type.hall_symbol); strcpy(spacegroup.international, spacegroup_type.international); strcpy(spacegroup.international_long, spacegroup_type.international_full); strcpy(spacegroup.international_short, spacegroup_type.international_short); } else { spacegroup.number = 0; warning_print("spglib: Space group could not be found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); } ret: /* spacegroup.number = 0 when space group was not found. */ sym_free_symmetry(symmetry); return spacegroup; }
/* Return spacegroup.number = 0 if failed */ static Spacegroup get_spacegroup(const int hall_number, const double origin_shift[3], SPGCONST double conv_lattice[3][3]) { Spacegroup spacegroup; SpacegroupType spacegroup_type; spacegroup.number = 0; spacegroup_type = spgdb_get_spacegroup_type(hall_number); if (spacegroup_type.number > 0) { mat_copy_matrix_d3(spacegroup.bravais_lattice, conv_lattice); mat_copy_vector_d3(spacegroup.origin_shift, origin_shift); spacegroup.number = spacegroup_type.number; spacegroup.hall_number = hall_number; spacegroup.pointgroup_number = spacegroup_type.pointgroup_number; strcpy(spacegroup.schoenflies, spacegroup_type.schoenflies); strcpy(spacegroup.hall_symbol, spacegroup_type.hall_symbol); strcpy(spacegroup.international, spacegroup_type.international); strcpy(spacegroup.international_long, spacegroup_type.international_full); strcpy(spacegroup.international_short, spacegroup_type.international_short); strcpy(spacegroup.setting, spacegroup_type.setting); } return spacegroup; }
/* }} */ int mat_inverse_matrix_d3(double m[3][3], SPGCONST double a[3][3], const double precision) { double det; double c[3][3]; det = mat_get_determinant_d3(a); if (mat_Dabs(det) < precision) { warning_print("spglib: No inverse matrix (det=%f)\n", det); debug_print("No inverse matrix\n"); return 0; } c[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det; c[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) / det; c[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det; c[0][1] = (a[2][1] * a[0][2] - a[2][2] * a[0][1]) / det; c[1][1] = (a[2][2] * a[0][0] - a[2][0] * a[0][2]) / det; c[2][1] = (a[2][0] * a[0][1] - a[2][1] * a[0][0]) / det; c[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det; c[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) / det; c[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det; mat_copy_matrix_d3(m, c); return 1; }
/* m=axb */ void mat_multiply_matrix_d3(double m[3][3], const double a[3][3], const double b[3][3]) { int i, j; /* a_ij */ double c[3][3]; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j]; } } mat_copy_matrix_d3(m, c); }
/* Return NULL if failed */ Cell * spa_transform_to_primitive(SPGCONST Cell * cell, SPGCONST double trans_mat[3][3], const Centering centering, const double symprec) { int * mapping_table; double tmat[3][3], tmat_inv[3][3], prim_lat[3][3]; Cell * primitive; mapping_table = NULL; primitive = NULL; mat_inverse_matrix_d3(tmat_inv, trans_mat, 0); switch (centering) { case PRIMITIVE: mat_copy_matrix_d3(tmat, tmat_inv); break; case A_FACE: mat_multiply_matrix_d3(tmat, tmat_inv, A_mat); break; case C_FACE: mat_multiply_matrix_d3(tmat, tmat_inv, C_mat); break; case FACE: mat_multiply_matrix_d3(tmat, tmat_inv, F_mat); break; case BODY: mat_multiply_matrix_d3(tmat, tmat_inv, I_mat); break; case R_CENTER: mat_multiply_matrix_d3(tmat, tmat_inv, R_mat); break; default: goto err; } if ((mapping_table = (int*) malloc(sizeof(int) * cell->size)) == NULL) { warning_print("spglib: Memory could not be allocated "); goto err; } mat_multiply_matrix_d3(prim_lat, cell->lattice, tmat); primitive = cel_trim_cell(mapping_table, prim_lat, cell, symprec); free(mapping_table); mapping_table = NULL; return primitive; err: return NULL; }
static Centering get_centering(double correction_mat[3][3], SPGCONST int transform_mat[3][3], const Laue laue) { int det; double trans_corr_mat[3][3]; Centering centering; mat_copy_matrix_d3(correction_mat, identity); det = abs(mat_get_determinant_i3(transform_mat)); debug_print("laue class: %d\n", laue); debug_print("multiplicity: %d\n", det); if (det == 1) { centering = NO_CENTER; } if (det == 2) { centering = get_base_center(transform_mat); if (centering == A_FACE) { if (laue == LAUE2M) { debug_print("Monocli A to C\n"); mat_copy_matrix_d3(correction_mat, monocli_a2c); } else { mat_copy_matrix_d3(correction_mat, a2c); } centering = C_FACE; } if (centering == B_FACE) { mat_copy_matrix_d3(correction_mat, b2c); centering = C_FACE; } if (laue == LAUE2M && centering == BODY) { debug_print("Monocli I to C\n"); mat_copy_matrix_d3(correction_mat, monocli_i2c); centering = C_FACE; } } if (det == 3) { centering = NO_CENTER; mat_multiply_matrix_id3(trans_corr_mat, transform_mat, rhombo_obverse); if (mat_is_int_matrix(trans_corr_mat, INT_PREC)) { mat_copy_matrix_d3(correction_mat, rhombo_obverse); debug_print("R-center observe setting\n"); debug_print_matrix_d3(trans_corr_mat); } mat_multiply_matrix_id3(trans_corr_mat, transform_mat, rhomb_reverse); if (mat_is_int_matrix(trans_corr_mat, INT_PREC)) { mat_copy_matrix_d3(correction_mat, rhomb_reverse); debug_print("R-center reverse setting\n"); debug_print_matrix_d3(trans_corr_mat); } } if (det == 4) { centering = FACE; } return centering; }
static void set_cell(double lattice[3][3], double position[][3], int types[], Cell * cell) { int i; mat_copy_matrix_d3(lattice, cell->lattice); for (i = 0; i < cell->size; i++) { types[i] = cell->types[i]; mat_copy_vector_d3(position[i], cell->position[i]); } }
void cel_set_cell( Cell * cell, SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[] ) { int i, j; mat_copy_matrix_d3(cell->lattice, lattice); for (i = 0; i < cell->size; i++) { for (j = 0; j < 3; j++) { cell->position[i][j] = position[i][j]; } cell->types[i] = types[i]; } }
void mat_transpose_matrix_d3(double a[3][3], const double b[3][3]) { double c[3][3]; c[0][0] = b[0][0]; c[0][1] = b[1][0]; c[0][2] = b[2][0]; c[1][0] = b[0][1]; c[1][1] = b[1][1]; c[1][2] = b[2][1]; c[2][0] = b[0][2]; c[2][1] = b[1][2]; c[2][2] = b[2][2]; mat_copy_matrix_d3(a, c); }
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 int mat_inverse_matrix_d3(double m[3][3], double a[3][3], const double precision) { double det; double c[3][3]; det = mat_get_determinant_d3(a); c[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det; c[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) / det; c[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det; c[0][1] = (a[2][1] * a[0][2] - a[2][2] * a[0][1]) / det; c[1][1] = (a[2][2] * a[0][0] - a[2][0] * a[0][2]) / det; c[2][1] = (a[2][0] * a[0][1] - a[2][1] * a[0][0]) / det; c[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det; c[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) / det; c[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det; mat_copy_matrix_d3(m, c); return 1; }
int spg_find_primitive( double lattice[3][3], double position[][3], int types[], const int num_atom, const double symprec ) { int i, j, num_prim_atom=0; int *mapping_table; Cell *cell, *primitive; VecDBL *pure_trans; cell = cel_alloc_cell( num_atom ); cel_set_cell( cell, lattice, position, types ); pure_trans = sym_get_pure_translation( cell, symprec ); /* find primitive cell */ if ( pure_trans->size > 1 ) { mapping_table = (int*) malloc( sizeof(int) * cell->size ); primitive = prm_get_primitive( mapping_table, cell, pure_trans, symprec ); free( mapping_table ); mapping_table = NULL; num_prim_atom = primitive->size; if ( num_prim_atom < num_atom && num_prim_atom > 0 ) { mat_copy_matrix_d3( lattice, primitive->lattice ); for ( i = 0; i < primitive->size; i++ ) { types[i] = primitive->types[i]; for (j=0; j<3; j++) { position[i][j] = primitive->position[i][j]; } } } cel_free_cell( primitive ); } else { num_prim_atom = 0; } mat_free_VecDBL( pure_trans ); cel_free_cell( cell ); return num_prim_atom; }
/* Return 0 if failed */ static int find_primitive(double lattice[3][3], double position[][3], int types[], const int num_atom, const double symprec) { int i, num_prim_atom; Cell *cell; Primitive *primitive; cell = NULL; primitive = NULL; num_prim_atom = 0; if ((cell = cel_alloc_cell(num_atom)) == NULL) { return 0; } cel_set_cell(cell, lattice, position, types); /* find primitive cell */ if ((primitive = prm_get_primitive(cell, symprec)) == NULL) { cel_free_cell(cell); return 0; } num_prim_atom = primitive->cell->size; if (num_prim_atom < num_atom && num_prim_atom > 0 ) { mat_copy_matrix_d3(lattice, primitive->cell->lattice); for (i = 0; i < primitive->cell->size; i++) { types[i] = primitive->cell->types[i]; mat_copy_vector_d3(position[i], primitive->cell->position[i]); } } prm_free_primitive(primitive); cel_free_cell(cell); return num_prim_atom; }
/* Return NULL if failed */ static Cell * get_cell_with_smallest_lattice(SPGCONST Cell * cell, const double symprec) { int i, j; double min_lat[3][3], trans_mat[3][3], inv_lat[3][3]; Cell * smallest_cell; debug_print("get_cell_with_smallest_lattice:\n"); smallest_cell = NULL; if (!lat_smallest_lattice_vector(min_lat, cell->lattice, symprec)) { goto err; } mat_inverse_matrix_d3(inv_lat, min_lat, 0); mat_multiply_matrix_d3(trans_mat, inv_lat, cell->lattice); if ((smallest_cell = cel_alloc_cell(cell->size)) == NULL) { goto err; } mat_copy_matrix_d3(smallest_cell->lattice, min_lat); for (i = 0; i < cell->size; i++) { smallest_cell->types[i] = cell->types[i]; mat_multiply_matrix_vector_d3(smallest_cell->position[i], trans_mat, cell->position[i]); for (j = 0; j < 3; j++) { cell->position[i][j] = mat_Dmod1(cell->position[i][j]); } } return smallest_cell; err: return NULL; }
/* }} */ int mat_inverse_matrix_d3(double m[3][3], const double a[3][3], const double precision) { double det; double c[3][3]; det = mat_get_determinant_d3(a); if (mat_Dabs(det) < precision) { fprintf(stderr, "spglib: No inverse matrix\n"); return 0; } c[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det; c[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) / det; c[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det; c[0][1] = (a[2][1] * a[0][2] - a[2][2] * a[0][1]) / det; c[1][1] = (a[2][2] * a[0][0] - a[2][0] * a[0][2]) / det; c[2][1] = (a[2][0] * a[0][1] - a[2][1] * a[0][0]) / det; c[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det; c[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) / det; c[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det; mat_copy_matrix_d3(m, c); return 1; }
/* Return 0 if failed */ static int match_hall_symbol_db(double origin_shift[3], double lattice[3][3], const int hall_number, const int pointgroup_number, const Holohedry holohedry, const Centering centering, SPGCONST Symmetry *symmetry, const double symprec) { int is_found, num_hall_types; SpacegroupType spacegroup_type; Symmetry * changed_symmetry; double changed_lattice[3][3], inv_lattice[3][3], transform_mat[3][3]; changed_symmetry = NULL; spacegroup_type = spgdb_get_spacegroup_type(hall_number); num_hall_types = (spacegroup_to_hall_number[spacegroup_type.number] - spacegroup_to_hall_number[spacegroup_type.number - 1]); if (pointgroup_number != spacegroup_type.pointgroup_number) { goto err; } switch (holohedry) { case MONOCLI: if (match_hall_symbol_db_monocli(origin_shift, lattice, hall_number, num_hall_types, centering, symmetry, symprec)) {return 1;} break; case ORTHO: if (spacegroup_type.number == 48 || spacegroup_type.number == 50 || spacegroup_type.number == 59 || spacegroup_type.number == 68 || spacegroup_type.number == 70) { /* uncount origin shift */ num_hall_types /= 2; } if (num_hall_types == 1) { if (match_hall_symbol_db_ortho(origin_shift, lattice, hall_number, centering, symmetry, 6, symprec)) {return 1;} break; } if (num_hall_types == 2) { if (match_hall_symbol_db_ortho(origin_shift, lattice, hall_number, centering, symmetry, 3, symprec)) {return 1;} break; } if (num_hall_types == 3) { mat_copy_matrix_d3(changed_lattice, lattice); if (! match_hall_symbol_db_ortho (origin_shift, changed_lattice, spacegroup_to_hall_number[spacegroup_type.number - 1], centering, symmetry, 0, symprec)) {break;} mat_inverse_matrix_d3(inv_lattice, lattice, 0); mat_multiply_matrix_d3(transform_mat, inv_lattice, changed_lattice); if ((changed_symmetry = get_conventional_symmetry(transform_mat, PRIMITIVE, symmetry)) == NULL) { goto err; } is_found = match_hall_symbol_db_ortho(origin_shift, changed_lattice, hall_number, centering, changed_symmetry, 2, symprec); sym_free_symmetry(changed_symmetry); changed_symmetry = NULL; if (is_found) { mat_copy_matrix_d3(lattice, changed_lattice); return 1; } break; } if (num_hall_types == 6) { if (match_hall_symbol_db_ortho(origin_shift, lattice, hall_number, centering, symmetry, 1, symprec)) {return 1;} break; } break; case CUBIC: if (hal_match_hall_symbol_db(origin_shift, lattice, hall_number, centering, symmetry, symprec)) {return 1;} if (hall_number == 501) { /* Try another basis for No.205 */ mat_multiply_matrix_d3(changed_lattice, lattice, change_of_basis_501); if ((changed_symmetry = get_conventional_symmetry(change_of_basis_501, PRIMITIVE, symmetry)) == NULL) { goto err; } is_found = hal_match_hall_symbol_db(origin_shift, changed_lattice, hall_number, PRIMITIVE, changed_symmetry, symprec); sym_free_symmetry(changed_symmetry); changed_symmetry = NULL; if (is_found) { mat_copy_matrix_d3(lattice, changed_lattice); return 1; } } break; case TRIGO: if (centering == R_CENTER) { if (hall_number == 433 || hall_number == 436 || hall_number == 444 || hall_number == 450 || hall_number == 452 || hall_number == 458 || hall_number == 460) { mat_multiply_matrix_d3(changed_lattice, lattice, hR_to_hP); if ((changed_symmetry = get_conventional_symmetry(hR_to_hP, R_CENTER, symmetry)) == NULL) { goto err; } is_found = hal_match_hall_symbol_db(origin_shift, changed_lattice, hall_number, centering, changed_symmetry, symprec); sym_free_symmetry(changed_symmetry); changed_symmetry = NULL; if (is_found) { mat_copy_matrix_d3(lattice, changed_lattice); return 1; } } } /* Do not break for other trigonal cases */ default: /* HEXA, TETRA, TRICLI and rest of TRIGO */ if (hal_match_hall_symbol_db(origin_shift, lattice, hall_number, centering, symmetry, symprec)) { return 1; } break; } err: return 0; }
/* Return 0 if failed */ static int match_hall_symbol_db_monocli(double origin_shift[3], double lattice[3][3], const int hall_number, const int num_hall_types, const Centering centering, SPGCONST Symmetry *symmetry, const double symprec) { int i, j, k, l, is_found; double vec[3], norms[3]; Centering changed_centering; Symmetry * changed_symmetry; double changed_lattice[3][3]; changed_symmetry = NULL; for (i = 0; i < 18; i++) { if (centering == C_FACE) { changed_centering = change_of_centering_monocli[i]; } else { /* suppose PRIMITIVE */ changed_centering = centering; } mat_multiply_matrix_d3(changed_lattice, lattice, change_of_basis_monocli[i]); /* Choose |a| < |b| < |c| if there are freedom. */ if (num_hall_types == 3) { l = 0; for (j = 0; j < 3; j++) { if (j == change_of_unique_axis_monocli[i]) {continue;} for (k = 0; k < 3; k++) {vec[k] = changed_lattice[k][j];} norms[l] = mat_norm_squared_d3(vec); l++; } if (norms[0] > norms[1]) {continue;} } if ((changed_symmetry = get_conventional_symmetry(change_of_basis_monocli[i], PRIMITIVE, symmetry)) == NULL) { goto err; } is_found = hal_match_hall_symbol_db(origin_shift, changed_lattice, hall_number, changed_centering, changed_symmetry, symprec); sym_free_symmetry(changed_symmetry); changed_symmetry = NULL; if (is_found) { mat_copy_matrix_d3(lattice, changed_lattice); return 1; } } err: return 0; }
/* Return NULL if failed */ static Cell * trim_cell(int * mapping_table, SPGCONST double trimmed_lattice[3][3], const Cell * cell, const double symprec) { int i, index_atom, ratio; Cell *trimmed_cell; VecDBL * position; int *overlap_table; position = NULL; overlap_table = NULL; trimmed_cell = NULL; ratio = abs(mat_Nint(mat_get_determinant_d3(cell->lattice) / mat_get_determinant_d3(trimmed_lattice))); /* Check if cell->size is dividable by ratio */ if ((cell->size / ratio) * ratio != cell->size) { return NULL; } if ((trimmed_cell = cel_alloc_cell(cell->size / ratio)) == NULL) { return NULL; } if ((position = translate_atoms_in_trimmed_lattice(cell, trimmed_lattice)) == NULL) { cel_free_cell(trimmed_cell); trimmed_cell = NULL; goto err; } mat_copy_matrix_d3(trimmed_cell->lattice, trimmed_lattice); if ((overlap_table = get_overlap_table(position, cell->size, cell->types, trimmed_cell, symprec)) == NULL) { mat_free_VecDBL(position); position = NULL; cel_free_cell(trimmed_cell); trimmed_cell = NULL; goto err; } index_atom = 0; for (i = 0; i < cell->size; i++) { if (overlap_table[i] == i) { mapping_table[i] = index_atom; trimmed_cell->types[index_atom] = cell->types[i]; index_atom++; } else { mapping_table[i] = mapping_table[overlap_table[i]]; } } set_positions(trimmed_cell, position, mapping_table, overlap_table); mat_free_VecDBL(position); position = NULL; free(overlap_table); return trimmed_cell; err: return NULL; }
/* Return 0 if failed */ static int set_dataset(SpglibDataset * dataset, SPGCONST Cell * cell, SPGCONST Cell * primitive, SPGCONST Spacegroup * spacegroup, const int * mapping_table, const double tolerance) { int i; double inv_mat[3][3]; Cell *bravais; Symmetry *symmetry; bravais = NULL; symmetry = NULL; /* Spacegroup type, transformation matrix, origin shift */ dataset->n_atoms = cell->size; dataset->spacegroup_number = spacegroup->number; dataset->hall_number = spacegroup->hall_number; strcpy(dataset->international_symbol, spacegroup->international_short); strcpy(dataset->hall_symbol, spacegroup->hall_symbol); strcpy(dataset->setting, spacegroup->setting); mat_inverse_matrix_d3(inv_mat, cell->lattice, tolerance); mat_multiply_matrix_d3(dataset->transformation_matrix, inv_mat, spacegroup->bravais_lattice); mat_copy_vector_d3(dataset->origin_shift, spacegroup->origin_shift); /* Symmetry operations */ if ((symmetry = ref_get_refined_symmetry_operations(cell, primitive, spacegroup, tolerance)) == NULL) { return 0; } dataset->n_operations = symmetry->size; if ((dataset->rotations = (int (*)[3][3]) malloc(sizeof(int[3][3]) * dataset->n_operations)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } if ((dataset->translations = (double (*)[3]) malloc(sizeof(double[3]) * dataset->n_operations)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } for (i = 0; i < symmetry->size; i++) { mat_copy_matrix_i3(dataset->rotations[i], symmetry->rot[i]); mat_copy_vector_d3(dataset->translations[i], symmetry->trans[i]); } /* Wyckoff positions */ if ((dataset->wyckoffs = (int*) malloc(sizeof(int) * dataset->n_atoms)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } if ((dataset->equivalent_atoms = (int*) malloc(sizeof(int) * dataset->n_atoms)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } if ((bravais = ref_get_Wyckoff_positions(dataset->wyckoffs, dataset->equivalent_atoms, primitive, cell, spacegroup, symmetry, mapping_table, tolerance)) == NULL) { goto err; } dataset->n_brv_atoms = bravais->size; mat_copy_matrix_d3(dataset->brv_lattice, bravais->lattice); if ((dataset->brv_positions = (double (*)[3]) malloc(sizeof(double[3]) * dataset->n_brv_atoms)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } if ((dataset->brv_types = (int*) malloc(sizeof(int) * dataset->n_brv_atoms)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } for (i = 0; i < dataset->n_brv_atoms; i++) { mat_copy_vector_d3(dataset->brv_positions[i], bravais->position[i]); dataset->brv_types[i] = bravais->types[i]; } cel_free_cell(bravais); sym_free_symmetry(symmetry); return 1; err: if (dataset->brv_positions != NULL) { free(dataset->brv_positions); dataset->brv_positions = NULL; } if (bravais != NULL) { cel_free_cell(bravais); } if (dataset->equivalent_atoms != NULL) { free(dataset->equivalent_atoms); dataset->equivalent_atoms = NULL; } if (dataset->wyckoffs != NULL) { free(dataset->wyckoffs); dataset->wyckoffs = NULL; } if (dataset->translations != NULL) { free(dataset->translations); dataset->translations = NULL; } if (dataset->rotations != NULL) { free(dataset->rotations); dataset->rotations = NULL; } if (symmetry != NULL) { sym_free_symmetry(symmetry); } return 0; }
/* Return CENTERING_ERROR if failed */ static Centering get_centering(double correction_mat[3][3], SPGCONST int transform_mat[3][3], const Laue laue) { int det; double trans_corr_mat[3][3]; Centering centering; mat_copy_matrix_d3(correction_mat, identity); det = abs(mat_get_determinant_i3(transform_mat)); debug_print("laue class: %d\n", laue); debug_print("multiplicity: %d\n", det); switch (det) { case 1: centering = PRIMITIVE; break; case 2: centering = get_base_center(transform_mat); if (centering == A_FACE) { if (laue == LAUE2M) { debug_print("Monocli A to C\n"); mat_copy_matrix_d3(correction_mat, monocli_a2c); } else { mat_copy_matrix_d3(correction_mat, a2c); } centering = C_FACE; } if (centering == B_FACE) { mat_copy_matrix_d3(correction_mat, b2c); centering = C_FACE; } if (laue == LAUE2M && centering == BODY) { debug_print("Monocli I to C\n"); mat_copy_matrix_d3(correction_mat, monocli_i2c); centering = C_FACE; } break; case 3: /* hP (a=b) but not hR (a=b=c) */ centering = R_CENTER; mat_multiply_matrix_id3(trans_corr_mat, transform_mat, rhombo_obverse); if (mat_is_int_matrix(trans_corr_mat, INT_PREC)) { mat_copy_matrix_d3(correction_mat, rhombo_obverse); debug_print("R-center observe setting\n"); debug_print_matrix_d3(trans_corr_mat); } mat_multiply_matrix_id3(trans_corr_mat, transform_mat, rhomb_reverse); if (mat_is_int_matrix(trans_corr_mat, INT_PREC)) { mat_copy_matrix_d3(correction_mat, rhomb_reverse); debug_print("R-center reverse setting\n"); debug_print_matrix_d3(trans_corr_mat); } break; case 4: centering = FACE; break; default: centering = CENTERING_ERROR; break; } return centering; }
/* 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, sum, red_sum; double basis[4][3]; get_exteneded_basis(basis, lattice); sum = 0; for (i = 0; i < 4; i++) { for (j = 0; j < 3; j++) { sum += basis[i][j] * basis[i][j]; } } while (1) { if (get_Delaunay_reduction_basis(basis, symprec)) { break; } } get_Delaunay_shortest_vectors(basis, symprec); red_sum = 0; for (i = 0; i < 4; i++) { for (j = 0; j < 3; j++) { red_sum += basis[i][j] * basis[i][j]; } } if (sum - red_sum > symprec * symprec) { for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { red_lattice[i][j] = basis[j][i]; } } } else { mat_copy_matrix_d3(red_lattice, lattice); } 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]; } } } return 1; err: return 0; }