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; }
/* If primitive could not be found, primitive->size = -1 is returned. */ static Cell * get_primitive( int * mapping_table, SPGCONST Cell * cell, const VecDBL * pure_trans, const double symprec ) { int multi; double prim_lattice[3][3]; Cell * primitive; /* Primitive lattice vectors are searched. */ /* To be consistent, sometimes tolerance is decreased iteratively. */ /* The descreased tolerance is stored in 'static double tolerance'. */ multi = get_primitive_lattice_vectors_iterative( prim_lattice, cell, pure_trans, symprec ); if ( ! multi ) { goto not_found; } primitive = cel_alloc_cell( cell->size / multi ); if ( ! lat_smallest_lattice_vector( primitive->lattice, prim_lattice, symprec ) ) { cel_free_cell( primitive ); goto not_found; } /* Fit atoms into new primitive cell */ if ( ! trim_cell( primitive, mapping_table, cell, symprec ) ) { cel_free_cell( primitive ); goto not_found; } debug_print("Original cell lattice.\n"); debug_print_matrix_d3(cell->lattice); debug_print("Found primitive lattice after choosing least axes.\n"); debug_print_matrix_d3(primitive->lattice); debug_print("Number of atoms in primitive cell: %d\n", primitive->size); debug_print("Volume: original %f --> primitive %f\n", mat_get_determinant_d3(cell->lattice), mat_get_determinant_d3(primitive->lattice)); /* found */ return primitive; not_found: primitive = cel_alloc_cell( -1 ); warning_print("spglib: Primitive cell could not found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); return primitive; }
int spg_get_ir_kpoints( int map[], SPGCONST double kpoints[][3], const int num_kpoint, SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const int is_time_reversal, const double symprec ) { Symmetry *symmetry; Cell *cell; int num_ir_kpoint; cell = cel_alloc_cell( num_atom ); cel_set_cell( cell, lattice, position, types ); symmetry = sym_get_operation( cell, symprec ); num_ir_kpoint = kpt_get_irreducible_kpoints( map, kpoints, num_kpoint, lattice, symmetry, is_time_reversal, symprec ); cel_free_cell( cell ); sym_free_symmetry( symmetry ); return num_ir_kpoint; }
int spg_get_ir_reciprocal_mesh( int grid_point[][3], int map[], const int mesh[3], const int is_shift[3], const int is_time_reversal, SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const double symprec ) { Symmetry *symmetry; Cell *cell; int num_ir; cell = cel_alloc_cell( num_atom ); cel_set_cell( cell, lattice, position, types ); symmetry = sym_get_operation( cell, symprec ); num_ir = kpt_get_irreducible_reciprocal_mesh( grid_point, map, mesh, is_shift, is_time_reversal, lattice, symmetry, symprec ); cel_free_cell( cell ); sym_free_symmetry( symmetry ); return num_ir; }
static int get_schoenflies(char symbol[10], SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const double symprec) { Cell *cell; Primitive *primitive; Spacegroup spacegroup; cell = NULL; primitive = NULL; spacegroup.number = 0; cell = cel_alloc_cell(num_atom); cel_set_cell(cell, lattice, position, types); if ((primitive = spa_get_spacegroup(&spacegroup, cell, symprec)) != NULL) { prm_free_primitive(primitive); if (spacegroup.number > 0) { strcpy(symbol, spacegroup.schoenflies); } } cel_free_cell(cell); return spacegroup.number; }
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 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; }
static Cell * get_conventional_primitive(SPGCONST Spacegroup * spacegroup, SPGCONST Cell * primitive) { int i, j; double inv_brv[3][3], trans_mat[3][3]; Cell * conv_prim; conv_prim = cel_alloc_cell(primitive->size); mat_inverse_matrix_d3(inv_brv, spacegroup->bravais_lattice, 0); mat_multiply_matrix_d3(trans_mat, inv_brv, primitive->lattice); for (i = 0; i < primitive->size; i++) { conv_prim->types[i] = primitive->types[i]; mat_multiply_matrix_vector_d3(conv_prim->position[i], trans_mat, primitive->position[i]); for (j = 0; j < 3; j++) { conv_prim->position[i][j] -= spacegroup->origin_shift[j]; conv_prim->position[i][j] -= mat_Nint(conv_prim->position[i][j]); } } return conv_prim; }
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; }
/* If primitive could not be found, primitive->size = 0 is returned. */ static Cell * get_primitive(int * mapping_table, SPGCONST Cell * cell, const VecDBL * pure_trans, const double symprec) { int multi; double prim_lattice[3][3]; Cell * primitive_cell; debug_print("get_primitive:\n"); /* Primitive lattice vectors are searched. */ /* To be consistent, sometimes tolerance is decreased iteratively. */ /* The descreased tolerance is stored in 'static double tolerance'. */ multi = get_primitive_lattice_vectors_iterative(prim_lattice, cell, pure_trans, symprec); if (! multi) { goto not_found; } primitive_cell = cel_alloc_cell(cell->size / multi); if (! lat_smallest_lattice_vector(primitive_cell->lattice, prim_lattice, symprec)) { cel_free_cell(primitive_cell); goto not_found; } /* Fit atoms into new primitive cell */ if (! trim_cell(primitive_cell, mapping_table, cell, symprec)) { cel_free_cell(primitive_cell); goto not_found; } /* found */ return primitive_cell; not_found: primitive_cell = cel_alloc_cell(0); warning_print("spglib: Primitive cell could not be found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); return primitive_cell; }
Cell * cel_copy_cell( SPGCONST Cell * cell ) { Cell * cell_new; cell_new = cel_alloc_cell( cell->size ); cel_set_cell( cell_new, cell->lattice, cell->position, cell->types ); return cell_new; }
static Cell * refine_cell(SPGCONST Cell * cell, const double symprec) { int *wyckoffs, *equiv_atoms; double tolerance; Cell *primitive, *bravais, *conv_prim; Symmetry *conv_sym; Spacegroup spacegroup; debug_print("refine_cell:\n"); primitive = prm_get_primitive(cell, symprec); if (primitive->size == 0) { cel_free_cell(primitive); bravais = cel_alloc_cell(0); goto end; } tolerance = prm_get_current_tolerance(); spacegroup = spa_get_spacegroup_with_primitive(primitive, tolerance); wyckoffs = (int*)malloc(sizeof(int) * primitive->size); equiv_atoms = (int*)malloc(sizeof(int) * primitive->size); conv_prim = get_bravais_exact_positions_and_lattice(wyckoffs, equiv_atoms, &spacegroup, primitive, tolerance); free(equiv_atoms); equiv_atoms = NULL; free(wyckoffs); wyckoffs = NULL; conv_sym = get_db_symmetry(spacegroup.hall_number); bravais = expand_positions(conv_prim, conv_sym); debug_print("primitive cell in refine_cell:\n"); debug_print_matrix_d3(primitive->lattice); debug_print("conventional lattice in refine_cell:\n"); debug_print_matrix_d3(conv_prim->lattice); debug_print("bravais lattice in refine_cell:\n"); debug_print_matrix_d3(bravais->lattice); cel_free_cell(conv_prim); sym_free_symmetry(conv_sym); cel_free_cell(primitive); end: /* Return bravais->size = 0, if the bravais could not be found. */ return bravais; }
/* primitive cell with smallest lattice is returned. */ static Primitive get_primitive_and_pure_translation(SPGCONST Cell * cell, const double symprec) { int attempt, is_found = 0; double tolerance; int *mapping_table; Primitive primitive; tolerance = symprec; for (attempt = 0; attempt < 100; attempt++) { primitive.pure_trans = sym_get_pure_translation(cell, tolerance); if (primitive.pure_trans->size == 0) { mat_free_VecDBL(primitive.pure_trans); continue; } if (primitive.pure_trans->size == 1) { primitive.cell = get_cell_with_smallest_lattice(cell, tolerance); } else { mapping_table = (int*) malloc(sizeof(int) * cell->size); primitive.cell = get_primitive(mapping_table, cell, primitive.pure_trans, tolerance); free(mapping_table); } if (primitive.cell->size > 0) { is_found = 1; break; } cel_free_cell(primitive.cell); mat_free_VecDBL(primitive.pure_trans); tolerance *= REDUCE_RATE; warning_print("spglib: Reduce tolerance to %f ", tolerance); warning_print("(line %d, %s).\n", __LINE__, __FILE__); } if (! is_found) { primitive.cell = cel_alloc_cell(0); primitive.pure_trans = mat_alloc_VecDBL(0); } return primitive; }
/* Return 0 if failed */ static int get_symmetry_numerical(int rotation[][3][3], double translation[][3], const int max_size, SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const double symprec) { int i, size; Cell *cell; Symmetry *symmetry; size = 0; cell = NULL; symmetry = NULL; if ((cell = cel_alloc_cell(num_atom)) == NULL) { return 0; } cel_set_cell(cell, lattice, position, types); if ((symmetry = sym_get_operation(cell, symprec)) == NULL) { cel_free_cell(cell); return 0; } if (symmetry->size > max_size) { fprintf(stderr, "spglib: Indicated max size(=%d) is less than number ", max_size); fprintf(stderr, "spglib: of symmetry operations(=%d).\n", symmetry->size); goto ret; } for (i = 0; i < symmetry->size; i++) { mat_copy_matrix_i3(rotation[i], symmetry->rot[i]); mat_copy_vector_d3(translation[i], symmetry->trans[i]); } size = symmetry->size; ret: sym_free_symmetry(symmetry); cel_free_cell(cell); return size; }
static Cell * refine_cell( SPGCONST Cell * cell, const double symprec ) { int *mapping_table, *wyckoffs, *equiv_atoms; Cell *primitive, *bravais, *conv_prim; Symmetry *conv_sym; VecDBL *pure_trans; Spacegroup spacegroup; pure_trans = sym_get_pure_translation( cell, symprec ); mapping_table = (int*) malloc( sizeof(int) * cell->size ); primitive = prm_get_primitive( mapping_table, cell, pure_trans, symprec ); free( mapping_table ); mapping_table = NULL; if ( primitive->size == -1 ) { cel_free_cell( primitive ); bravais = cel_alloc_cell( -1 ); goto ret; } spacegroup = spa_get_spacegroup_with_primitive( primitive, symprec ); wyckoffs = (int*)malloc( sizeof( int ) * primitive->size ); equiv_atoms = (int*)malloc( sizeof( int ) * primitive->size ); conv_prim = get_bravais_exact_positions_and_lattice( wyckoffs, equiv_atoms, &spacegroup, primitive, symprec ); free( equiv_atoms ); equiv_atoms = NULL; free( wyckoffs ); wyckoffs = NULL; conv_sym = get_db_symmetry( spacegroup.hall_number ); bravais = expand_positions( conv_prim, conv_sym ); cel_free_cell( conv_prim ); sym_free_symmetry( conv_sym ); cel_free_cell( primitive ); ret: /* Return bravais->size = -1, if the bravais could not be found. */ return bravais; }
Cell * cel_copy_cell(const Cell * cell) { Cell * cell_new; cell_new = NULL; if ((cell_new = cel_alloc_cell(cell->size)) == NULL) { return NULL; } cel_set_cell(cell_new, cell->lattice, cell->position, cell->types); return cell_new; }
int spg_get_max_multiplicity( SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const double symprec ) { Cell *cell; int num_max_multi; cell = cel_alloc_cell( num_atom ); cel_set_cell( cell, lattice, position, types ); /* 48 is the magic number, which is the number of rotations */ /* in the highest point symmetry Oh. */ num_max_multi = sym_get_multiplicity( cell, symprec ) * 48; cel_free_cell( cell ); return num_max_multi; }
/* primitive cell with smallest lattice is returned. */ static Cell * get_primitive_and_mapping_table(int * mapping_table, SPGCONST Cell * cell, const double symprec) { int i, attempt; double tolerance; Cell *primitive_cell; VecDBL *pure_trans; tolerance = symprec; for (attempt = 0; attempt < 100; attempt++) { pure_trans = sym_get_pure_translation(cell, tolerance); if (pure_trans->size == 1) { primitive_cell = get_cell_with_smallest_lattice(cell, symprec); for (i = 0; i < cell->size; i++) { mapping_table[i] = i; } goto ret; } if (pure_trans->size > 1) { primitive_cell = get_primitive(mapping_table, cell, pure_trans, tolerance); if (primitive_cell->size > 0) { goto ret; } cel_free_cell(primitive_cell); } tolerance *= REDUCE_RATE; warning_print("spglib: Tolerance is reduced to %f at attempt %d\n", tolerance, attempt); warning_print("(line %d, %s).\n", __LINE__, __FILE__); mat_free_VecDBL(pure_trans); } /* not found: I hope this will not happen. */ warning_print("spglib: Primitive cell could not be found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); return cel_alloc_cell(0); ret: mat_free_VecDBL(pure_trans); set_current_tolerance(tolerance); return primitive_cell; }
/* Only the atoms corresponding to those in primitive are returned. */ static Cell * get_bravais_exact_positions_and_lattice(int * wyckoffs, int * equiv_atoms, SPGCONST Spacegroup *spacegroup, SPGCONST Cell * primitive, const double symprec) { int i; Symmetry *conv_sym; Cell *bravais; VecDBL *exact_positions; /* Positions of primitive atoms are represented wrt Bravais lattice */ bravais = get_conventional_primitive(spacegroup, primitive); /* Symmetries in database (wrt Bravais lattice) */ conv_sym = get_db_symmetry(spacegroup->hall_number); /* Lattice vectors are set. */ get_conventional_lattice(bravais->lattice, spacegroup->holohedry, spacegroup->bravais_lattice); /* Symmetrize atomic positions of conventional unit cell */ exact_positions = ssm_get_exact_positions(wyckoffs, equiv_atoms, bravais, conv_sym, spacegroup->hall_number, symprec); sym_free_symmetry(conv_sym); if (exact_positions->size > 0) { for (i = 0; i < bravais->size; i++) { mat_copy_vector_d3(bravais->position[i], exact_positions->vec[i]); } } else { cel_free_cell(bravais); bravais = cel_alloc_cell(0); } mat_free_VecDBL(exact_positions); return bravais; }
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; }
int spg_get_multiplicity( SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const double symprec ) { Symmetry *symmetry; Cell *cell; int size; cell = cel_alloc_cell( num_atom ); cel_set_cell( cell, lattice, position, types ); symmetry = sym_get_operation( cell, symprec ); size = symmetry->size; cel_free_cell( cell ); sym_free_symmetry( symmetry ); return size; }
int spg_get_schoenflies( char symbol[10], SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const double symprec ) { Cell *cell; Spacegroup spacegroup; cell = cel_alloc_cell( num_atom ); cel_set_cell( cell, lattice, position, types ); spacegroup = spa_get_spacegroup( cell, symprec ); if ( spacegroup.number > 0 ) { strcpy(symbol, spacegroup.schoenflies); } cel_free_cell( cell ); return spacegroup.number; }
/* 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; }
static int get_symmetry_with_collinear_spin(int rotation[][3][3], double translation[][3], const int max_size, SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const double spins[], const int num_atom, const double symprec) { int i, j, size; Symmetry *symmetry; Cell *cell; cell = cel_alloc_cell(num_atom); cel_set_cell(cell, lattice, position, types); symmetry = spn_get_collinear_operation(cell, spins, symprec); if (symmetry->size > max_size) { fprintf(stderr, "spglib: Indicated max size(=%d) is less than number ", max_size); fprintf(stderr, "spglib: of symmetry operations(=%d).\n", symmetry->size); sym_free_symmetry(symmetry); return 0; } for (i = 0; i < symmetry->size; i++) { mat_copy_matrix_i3(rotation[i], symmetry->rot[i]); for (j = 0; j < 3; j++) { translation[i][j] = symmetry->trans[i][j]; } } size = symmetry->size; cel_free_cell(cell); sym_free_symmetry(symmetry); return size; }
/* Return NULL if failed */ static SpglibDataset * get_dataset(SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const int hall_number, const double symprec) { Spacegroup spacegroup; SpacegroupType spacegroup_type; SpglibDataset *dataset; Cell *cell; Primitive *primitive; spacegroup.number = 0; dataset = NULL; cell = NULL; primitive = NULL; if ((dataset = (SpglibDataset*) malloc(sizeof(SpglibDataset))) == NULL) { warning_print("spglib: Memory could not be allocated."); return NULL; } dataset->spacegroup_number = 0; strcpy(dataset->international_symbol, ""); strcpy(dataset->hall_symbol, ""); strcpy(dataset->setting, ""); dataset->origin_shift[0] = 0; dataset->origin_shift[1] = 0; dataset->origin_shift[2] = 0; dataset->n_atoms = 0; dataset->wyckoffs = NULL; dataset->equivalent_atoms = NULL; dataset->n_operations = 0; dataset->rotations = NULL; dataset->translations = NULL; dataset->n_brv_atoms = 0; dataset->brv_positions = NULL; dataset->brv_types = NULL; if ((cell = cel_alloc_cell(num_atom)) == NULL) { free(dataset); dataset = NULL; return NULL; } cel_set_cell(cell, lattice, position, types); primitive = spa_get_spacegroup(&spacegroup, cell, symprec); if ((spacegroup.number > 0) && (primitive != NULL)) { /* With hall_number > 0, specific choice is searched. */ if (hall_number > 0) { spacegroup_type = spgdb_get_spacegroup_type(hall_number); if (spacegroup.number == spacegroup_type.number) { spacegroup = spa_get_spacegroup_with_hall_number(primitive, hall_number); } else { goto err; } if (spacegroup.number == 0) { goto err; } } if (spacegroup.number > 0) { if ((set_dataset(dataset, cell, primitive->cell, &spacegroup, primitive->mapping_table, primitive->tolerance)) == 0) { goto err; } } } cel_free_cell(cell); prm_free_primitive(primitive); return dataset; err: cel_free_cell(cell); prm_free_primitive(primitive); free(dataset); dataset = NULL; return NULL; }
SpglibDataset * spg_get_dataset( SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const double symprec ) { int i, j; int *mapping_table, *wyckoffs, *equiv_atoms, *equiv_atoms_prim; Spacegroup spacegroup; SpglibDataset *dataset; Cell *cell, *primitive; double inv_mat[3][3]; Symmetry *symmetry; VecDBL *pure_trans; dataset = (SpglibDataset*) malloc( sizeof( SpglibDataset ) ); cell = cel_alloc_cell( num_atom ); cel_set_cell( cell, lattice, position, types ); pure_trans = sym_get_pure_translation( cell, symprec ); mapping_table = (int*) malloc( sizeof(int) * cell->size ); primitive = prm_get_primitive( mapping_table, cell, pure_trans, symprec ); mat_free_VecDBL( pure_trans ); spacegroup = spa_get_spacegroup_with_primitive( primitive, symprec ); /* Spacegroup type, transformation matrix, origin shift */ if ( spacegroup.number > 0 ) { dataset->spacegroup_number = spacegroup.number; strcpy( dataset->international_symbol, spacegroup.international_short); strcpy( dataset->hall_symbol, spacegroup.hall_symbol); mat_inverse_matrix_d3( inv_mat, lattice, symprec ); mat_multiply_matrix_d3( dataset->transformation_matrix, inv_mat, spacegroup.bravais_lattice ); mat_copy_vector_d3( dataset->origin_shift, spacegroup.origin_shift ); } /* Wyckoff positions */ wyckoffs = (int*) malloc( sizeof(int) * primitive->size ); equiv_atoms_prim = (int*) malloc( sizeof(int) * primitive->size ); for ( i = 0; i < primitive->size; i++ ) { wyckoffs[i] = -1; equiv_atoms_prim[i] = -1; } ref_get_Wyckoff_positions( wyckoffs, equiv_atoms_prim, primitive, &spacegroup, symprec ); dataset->n_atoms = cell->size; dataset->wyckoffs = (int*) malloc( sizeof(int) * cell->size ); for ( i = 0; i < cell->size; i++ ) { dataset->wyckoffs[i] = wyckoffs[ mapping_table[i] ]; } free( wyckoffs ); wyckoffs = NULL; dataset->equivalent_atoms = (int*) malloc( sizeof(int) * cell->size ); equiv_atoms = (int*) malloc( sizeof(int) * primitive->size ); for ( i = 0; i < primitive->size; i++ ) { for ( j = 0; j < cell->size; j++ ) { if ( mapping_table[j] == equiv_atoms_prim[i] ) { equiv_atoms[i] = j; break; } } } for ( i = 0; i < cell->size; i++ ) { dataset->equivalent_atoms[i] = equiv_atoms[ mapping_table[i] ]; } free( equiv_atoms ); equiv_atoms = NULL; free( equiv_atoms_prim ); equiv_atoms_prim = NULL; free( mapping_table ); mapping_table = NULL; /* Symmetry operations */ symmetry = ref_get_refined_symmetry_operations( cell, primitive->lattice, &spacegroup, symprec ); cel_free_cell( cell ); cel_free_cell( primitive ); dataset->rotations = (int (*)[3][3]) malloc(sizeof(int[3][3]) * symmetry->size ); dataset->translations = (double (*)[3]) malloc(sizeof(double[3]) * symmetry->size ); dataset->n_operations = symmetry->size; 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] ); } sym_free_symmetry( symmetry ); return dataset; }
/* Return 0 if failed */ static int get_symmetry_with_collinear_spin(int rotation[][3][3], double translation[][3], int equivalent_atoms[], const int max_size, SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const double spins[], const int num_atom, const double symprec) { int i, size; Symmetry *symmetry, *sym_nonspin; Cell *cell; SpglibDataset *dataset; size = 0; symmetry = NULL; sym_nonspin = NULL; cell = NULL; dataset = NULL; if ((cell = cel_alloc_cell(num_atom)) == NULL) { goto err; } cel_set_cell(cell, lattice, position, types); if ((dataset = get_dataset(lattice, position, types, num_atom, 0, symprec)) == NULL) { cel_free_cell(cell); goto err; } if ((sym_nonspin = sym_alloc_symmetry(dataset->n_operations)) == NULL) { spg_free_dataset(dataset); cel_free_cell(cell); goto err; } for (i = 0; i < dataset->n_operations; i++) { mat_copy_matrix_i3(sym_nonspin->rot[i], dataset->rotations[i]); mat_copy_vector_d3(sym_nonspin->trans[i], dataset->translations[i]); } spg_free_dataset(dataset); if ((symmetry = spn_get_collinear_operations(equivalent_atoms, sym_nonspin, cell, spins, symprec)) == NULL) { sym_free_symmetry(sym_nonspin); cel_free_cell(cell); goto err; } sym_free_symmetry(sym_nonspin); if (symmetry->size > max_size) { fprintf(stderr, "spglib: Indicated max size(=%d) is less than number ", max_size); fprintf(stderr, "spglib: of symmetry operations(=%d).\n", symmetry->size); sym_free_symmetry(symmetry); goto err; } for (i = 0; i < symmetry->size; i++) { mat_copy_matrix_i3(rotation[i], symmetry->rot[i]); mat_copy_vector_d3(translation[i], symmetry->trans[i]); } size = symmetry->size; cel_free_cell(cell); sym_free_symmetry(symmetry); return size; err: return 0; }
static int get_standardized_cell(double lattice[3][3], double position[][3], int types[], const int num_atom, const int to_primitive, const double symprec) { int num_std_atom; SpglibDataset *dataset; Cell *std_cell, *cell; Centering centering; num_std_atom = 0; dataset = NULL; std_cell = NULL; cell = NULL; if ((dataset = get_dataset(lattice, position, types, num_atom, 0, symprec)) == NULL) { goto err; } if (to_primitive) { if ((centering = get_centering(dataset->hall_number)) == CENTERING_ERROR) { goto err; } if (dataset->hall_number == 433 || dataset->hall_number == 436 || dataset->hall_number == 444 || dataset->hall_number == 450 || dataset->hall_number == 452 || dataset->hall_number == 458 || dataset->hall_number == 460) { centering = R_CENTER; } } else { centering = PRIMITIVE; } if ((cell = cel_alloc_cell(num_atom)) == NULL) { spg_free_dataset(dataset); goto err; } cel_set_cell(cell, lattice, position, types); std_cell = spa_transform_to_primitive(cell, dataset->transformation_matrix, centering, symprec); spg_free_dataset(dataset); cel_free_cell(cell); if (std_cell == NULL) { goto err; } set_cell(lattice, position, types, std_cell); num_std_atom = std_cell->size; cel_free_cell(std_cell); return num_std_atom; 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; }