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; }
/* 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; }
/* Return NULL if failed */ static Cell * get_primitive_cell(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_cell = NULL; /* 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; } if ((primitive_cell = cel_alloc_cell(cell->size / multi)) == NULL) { goto not_found; } if (! lat_smallest_lattice_vector(primitive_cell->lattice, prim_lattice, symprec)) { cel_free_cell(primitive_cell); primitive_cell = NULL; goto not_found; } /* Fit atoms into new primitive cell */ if (! trim_cell(primitive_cell, mapping_table, cell, symprec)) { cel_free_cell(primitive_cell); primitive_cell = NULL; goto not_found; } /* found */ return primitive_cell; not_found: warning_print("spglib: Primitive cell could not be found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); return NULL; }
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; }
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; }
Spacegroup spa_get_spacegroup( SPGCONST Cell * cell, const double symprec ) { Cell *primitive; int *mapping_table; Spacegroup spacegroup; VecDBL *pure_trans; 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 > 0 ) { spacegroup = get_spacegroup( primitive, symprec ); } else { spacegroup.number = 0; warning_print("spglib: Space group could not be found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); } cel_free_cell( primitive ); return spacegroup; }
Spacegroup spa_get_spacegroup( SPGCONST Cell * cell, const double symprec ) { Cell *primitive; int *mapping_table; Spacegroup spacegroup; VecDBL *pure_trans; double tolerance; 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; /* In some case, tolerance (symprec) to find primitive lattice is reduced. */ /* The reduced tolerance should be used to find symmetry operations. */ tolerance = prm_get_tolerance(); if ( primitive->size > -1 ) { spacegroup = get_spacegroup( primitive, tolerance ); } else { spacegroup.number = 0; warning_print("spglib: Space group could not be found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); } cel_free_cell( primitive ); return spacegroup; }
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_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; }
/* 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; }
static void 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; /* 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 */ symmetry = ref_get_refined_symmetry_operations(cell, primitive, spacegroup, tolerance); 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]); } /* Wyckoff positions */ dataset->wyckoffs = (int*) malloc(sizeof(int) * cell->size); dataset->equivalent_atoms = (int*) malloc(sizeof(int) * cell->size); bravais = ref_get_Wyckoff_positions(dataset->wyckoffs, dataset->equivalent_atoms, primitive, cell, spacegroup, symmetry, mapping_table, tolerance); cel_free_cell(bravais); sym_free_symmetry(symmetry); }
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; }
void prm_free_primitive(Primitive * primitive) { if (primitive != NULL) { if (primitive->mapping_table != NULL) { free(primitive->mapping_table); primitive->mapping_table = NULL; } if (primitive->cell != NULL) { cel_free_cell(primitive->cell); } free(primitive); primitive = NULL; } }
void ref_get_Wyckoff_positions(int * wyckoffs, int * equiv_atoms, SPGCONST Cell * primitive, SPGCONST Spacegroup * spacegroup, const double symprec) { Cell *conv_prim; conv_prim = get_bravais_exact_positions_and_lattice(wyckoffs, equiv_atoms, spacegroup, primitive, symprec); cel_free_cell(conv_prim); }
/* 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; }
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_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; }
Spacegroup spa_get_spacegroup(SPGCONST Cell * cell, const double symprec) { double tolerance; Cell *primitive; Spacegroup spacegroup; primitive = prm_get_primitive(cell, symprec); tolerance = prm_get_current_tolerance(); if (primitive->size > 0) { spacegroup = get_spacegroup(primitive, tolerance); } else { spacegroup.number = 0; warning_print("spglib: Space group could not be found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); } cel_free_cell(primitive); return spacegroup; }
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; }
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; }
/* was not a primitive cell. */ static Symmetry * get_operations(SPGCONST Cell *cell, const double symprec) { int i, j, attempt; double tolerance; PointSymmetry lattice_sym; Symmetry *symmetry, *symmetry_orig, *symmetry_reduced; Primitive primitive; debug_print("get_operations:\n"); symmetry_orig = NULL; lattice_sym = get_lattice_symmetry(cell, symprec); if (lattice_sym.size == 0) { debug_print("get_lattice_symmetry failed.\n"); goto end; } primitive = prm_get_primitive_and_pure_translations(cell, symprec); if (primitive.cell->size == 0) { goto deallocate_and_end; } lattice_sym = transform_pointsymmetry(&lattice_sym, primitive.cell->lattice, cell->lattice); if (lattice_sym.size == 0) { goto deallocate_and_end; } symmetry = get_space_group_operations(&lattice_sym, primitive.cell, symprec); if (symmetry->size > 48) { tolerance = symprec; for (attempt = 0; attempt < 100; attempt++) { tolerance *= REDUCE_RATE; warning_print("spglib: number of symmetry operations for primitive cell > 48 was found. (line %d, %s).\n", __LINE__, __FILE__); warning_print("tolerance is reduced to %f\n", tolerance); symmetry_reduced = reduce_operation(primitive.cell, symmetry, tolerance); sym_free_symmetry(symmetry); symmetry = symmetry_reduced; if (symmetry_reduced->size > 48) { ; } else { break; } } } symmetry_orig = recover_operations_original(symmetry, primitive.pure_trans, cell, primitive.cell); sym_free_symmetry(symmetry); for (i = 0; i < symmetry_orig->size; i++) { for (j = 0; j < 3; j++) { symmetry_orig->trans[i][j] -= mat_Nint(symmetry_orig->trans[i][j]); } } deallocate_and_end: cel_free_cell(primitive.cell); mat_free_VecDBL(primitive.pure_trans); end: if (! symmetry_orig) { symmetry_orig = sym_alloc_symmetry(0); } return symmetry_orig; }
/* 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; }
/* 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; }
/* was not a primitive cell. */ static int get_operation( int rot[][3][3], double trans[][3], SPGCONST Cell *cell, const double symprec ) { int num_sym; int multi; int *mapping_table; PointSymmetry lattice_sym; Cell *primitive; VecDBL *pure_trans; pure_trans = sym_get_pure_translation(cell, symprec); multi = pure_trans->size; /* Lattice symmetry for input cell*/ lattice_sym = get_lattice_symmetry( cell, symprec ); if ( lattice_sym.size == 0 ) { goto err; } /* Obtain primitive cell */ if( multi > 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; if ( primitive->size < 1 ) { goto err; } lattice_sym = transform_pointsymmetry( &lattice_sym, primitive->lattice, cell->lattice ); if ( lattice_sym.size == 0 ) { goto err; } } else { primitive = cell; } /* Symmetry operation search for primitive cell */ num_sym = get_space_group_operation( rot, trans, &lattice_sym, primitive, symprec ); /* Recover symmetry operation for the input structure (overwritten) */ if( multi > 1 ) { num_sym = get_operation_supercell( rot, trans, num_sym, pure_trans, cell, primitive ); cel_free_cell( primitive ); if ( num_sym == 0 ) { goto err; } } mat_free_VecDBL( pure_trans ); return num_sym; err: mat_free_VecDBL( pure_trans ); 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; }