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; }
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 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; }
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; }
/* 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; }
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; }
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; }
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; }
static int standardize_primitive(double lattice[3][3], double position[][3], int types[], const int num_atom, const double symprec) { int num_prim_atom; Centering centering; SpglibDataset *dataset; Cell *primitive, *bravais; double identity[3][3] = {{ 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }}; num_prim_atom = 0; dataset = NULL; primitive = NULL; bravais = NULL; if ((dataset = get_dataset(lattice, position, types, num_atom, 0, symprec)) == NULL) { return 0; } 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; } if ((bravais = cel_alloc_cell(dataset->n_std_atoms)) == NULL) { spg_free_dataset(dataset); return 0; } cel_set_cell(bravais, dataset->std_lattice, dataset->std_positions, dataset->std_types); spg_free_dataset(dataset); primitive = spa_transform_to_primitive(bravais, identity, centering, symprec); cel_free_cell(bravais); if (primitive == NULL) { goto err; } set_cell(lattice, position, types, primitive); num_prim_atom = primitive->size; cel_free_cell(primitive); return num_prim_atom; err: return 0; }
/* 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; }
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 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; }
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; }
/*---------*/ static SpglibDataset * get_dataset(SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const double symprec) { int attempt; int *mapping_table; double tolerance, tolerance_from_prim; Spacegroup spacegroup; SpglibDataset *dataset; Cell *cell, *primitive; dataset = (SpglibDataset*) malloc(sizeof(SpglibDataset)); 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; mapping_table = (int*) malloc(sizeof(int) * num_atom); cell = cel_alloc_cell(num_atom); cel_set_cell(cell, lattice, position, types); tolerance = symprec; for (attempt = 0; attempt < 100; attempt++) { primitive = prm_get_primitive_and_mapping_table(mapping_table, cell, tolerance); if (primitive->size > 0) { tolerance_from_prim = prm_get_current_tolerance(); spacegroup = spa_get_spacegroup_with_primitive(primitive, tolerance_from_prim); if (spacegroup.number > 0) { set_dataset(dataset, cell, primitive, &spacegroup, mapping_table, tolerance_from_prim); cel_free_cell(primitive); break; } } tolerance *= REDUCE_RATE; cel_free_cell(primitive); warning_print(" Attempt %d tolerance = %f failed.", attempt, tolerance); warning_print(" (line %d, %s).\n", __LINE__, __FILE__); } free(mapping_table); mapping_table = NULL; cel_free_cell(cell); return dataset; }