Example #1
0
static Symmetry * get_refined_symmetry_operations(SPGCONST Cell * cell,
        SPGCONST Cell * primitive,
        SPGCONST Spacegroup * spacegroup,
        const double symprec)
{
    int t_mat_int[3][3];
    int frame[3];
    double inv_mat[3][3], t_mat[3][3];
    Symmetry *conv_sym, *prim_sym, *symmetry;

    /* Primitive symmetry from database */
    conv_sym = get_db_symmetry(spacegroup->hall_number);
    set_translation_with_origin_shift(conv_sym, spacegroup->origin_shift);
    mat_inverse_matrix_d3(inv_mat, primitive->lattice, symprec);
    mat_multiply_matrix_d3(t_mat, inv_mat, spacegroup->bravais_lattice);
    prim_sym = get_primitive_db_symmetry(t_mat, conv_sym, symprec);

    /* Input cell symmetry from primitive symmetry */
    mat_inverse_matrix_d3(inv_mat, primitive->lattice, symprec);
    mat_multiply_matrix_d3(t_mat, inv_mat, cell->lattice);
    mat_cast_matrix_3d_to_3i(t_mat_int, t_mat);
    get_surrounding_frame(frame, t_mat_int);
    symmetry = reduce_symmetry_in_frame(frame,
                                        prim_sym,
                                        t_mat_int,
                                        cell->lattice,
                                        cell->size / primitive->size,
                                        symprec);

    /* sym_free_symmetry(f_sym); */
    sym_free_symmetry(prim_sym);
    sym_free_symmetry(conv_sym);

    return symmetry;
}
Example #2
0
VecDBL * sym_reduce_pure_translation(SPGCONST Cell * cell,
				     const VecDBL * pure_trans,
				     const double symprec)
{
  int i, multi;
  Symmetry *symmetry, *symmetry_reduced;
  VecDBL * pure_trans_reduced;
  
  multi = pure_trans->size;
  symmetry = sym_alloc_symmetry(multi);
  for (i = 0; i < multi; i++) {
    mat_copy_matrix_i3(symmetry->rot[i], identity);
    mat_copy_vector_d3(symmetry->trans[i], pure_trans->vec[i]);
  }

  symmetry_reduced = reduce_operation(cell, symmetry, symprec);
  sym_free_symmetry(symmetry);

  multi = symmetry_reduced->size;
  pure_trans_reduced = mat_alloc_VecDBL(multi);
  
  for (i = 0; i < multi; i++) {
    mat_copy_vector_d3(pure_trans_reduced->vec[i], symmetry_reduced->trans[i]);
  }
  sym_free_symmetry(symmetry_reduced);
  
  return pure_trans_reduced;
}
Example #3
0
static int get_hall_number( double origin_shift[3],
			    double conv_lattice[3][3],
			    Centering * centering,
			    SPGCONST Cell * primitive,
			    SPGCONST Symmetry * symmetry,
			    const double symprec )
{
  int pg_num, attempt, hall_number=0;
  double tolerance;
  Symmetry * sym_reduced;

  tolerance = symprec;
  pg_num = ptg_get_pointgroup_number( symmetry );
  if ( pg_num > -1 ) {
    hall_number = get_hall_number_local( origin_shift,
					 conv_lattice,
					 centering,
					 primitive,
					 symmetry,
					 symprec );
    if ( hall_number > 0 ) { goto ret; }
  }

  /* Reduce tolerance and search hall symbol again when hall symbol */
  /* could not be found by the given tolerance. */
  /* The situation this happens is that symmetry operations found */
  /* don't match any of hall symbol database due to tricky */
  /* displacements of atoms from the exact points. */
  for ( attempt = 0; attempt < 100; attempt++ ) {
    tolerance *= REDUCE_RATE;
    sym_reduced = sym_reduce_operation( primitive, symmetry, tolerance );
    pg_num = ptg_get_pointgroup_number( sym_reduced );
    if ( pg_num > -1 ) {
      hall_number = get_hall_number_local( origin_shift,
					   conv_lattice,
					   centering,
					   primitive,
					   sym_reduced,
					   symprec );
      if ( hall_number > 0 ) {
	sym_free_symmetry( sym_reduced );
	warning_print("spglib: Tolerance to find Hall symbol was changed to %f\n", tolerance);
	goto ret;
      }
    }
    sym_free_symmetry( sym_reduced );
  }

  warning_print("spglib: Iterative attempt to find Hall symbol was failed.");

 ret:
  return hall_number;
}
Example #4
0
static int get_hall_number_local( double origin_shift[3],
				  double conv_lattice[3][3],
				  Centering * centering,
				  SPGCONST Cell * primitive,
				  SPGCONST Symmetry * symmetry,
				  const double symprec )
{
  int hall_number;
  double trans_mat[3][3];
  Symmetry * conv_symmetry;

  *centering = get_transformation_matrix( trans_mat, symmetry );
  mat_multiply_matrix_d3( conv_lattice,
			  primitive->lattice,
			  trans_mat );
  conv_symmetry = get_conventional_symmetry( trans_mat,
					     *centering,
					     symmetry );

  hall_number = hal_get_hall_symbol( origin_shift,
				     *centering,
				     conv_lattice,
				     conv_symmetry,
				     symprec );
  sym_free_symmetry( conv_symmetry );

  return hall_number;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
/* Return NULL if failed */
Symmetry * spn_get_collinear_operations(int equiv_atoms[],
					SPGCONST Symmetry *sym_nonspin,
					SPGCONST Cell *cell,
					const double spins[],
					const double symprec)
{
  Symmetry *symmetry;

  symmetry = NULL;

  if ((symmetry = get_collinear_operations(sym_nonspin,
					   cell,
					   spins,
					   symprec)) == NULL) {
    return NULL;
  }

  if ((set_equivalent_atoms(equiv_atoms,
			    symmetry,
			    cell,
			    symprec)) == 0) {
    sym_free_symmetry(symmetry);
    symmetry = NULL;
  }

  return symmetry;
}
Example #8
0
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;
}
Example #9
0
/* Return spacegroup.number = 0 if failed */
static Spacegroup search_spacegroup(SPGCONST Cell * primitive,
				    const int candidates[],
				    const int num_candidates,
				    const double symprec)
{
  int hall_number;
  double conv_lattice[3][3];
  double origin_shift[3];
  Spacegroup spacegroup;
  Symmetry *symmetry;
  PointSymmetry pointsym;

  debug_print("search_spacegroup (tolerance = %f):\n", symprec);

  symmetry = NULL;
  hall_number = 0;
  spacegroup.number = 0;

  if ((symmetry = sym_get_operation(primitive, symprec)) == NULL) {
    goto ret;
  }

  pointsym = ptg_get_pointsymmetry(symmetry->rot, symmetry->size);
  if (pointsym.size < symmetry->size) {
    warning_print("spglib: Point symmetry of primitive cell is broken. ");
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);
    sym_free_symmetry(symmetry);
    symmetry = NULL;
    goto ret;
  }

  hall_number = iterative_search_hall_number(origin_shift,
					     conv_lattice,
					     candidates,
					     num_candidates,
					     primitive,
					     symmetry,
					     symprec);
  sym_free_symmetry(symmetry);
  symmetry = NULL;
  spacegroup = get_spacegroup(hall_number, origin_shift, conv_lattice);

 ret:
  return spacegroup;
}
Example #10
0
static Symmetry *
recover_symmetry_in_original_cell(const int frame[3],
				  SPGCONST Symmetry *prim_sym,
				  SPGCONST int t_mat[3][3],
				  SPGCONST double lattice[3][3],
				  const int multiplicity,
				  const double symprec)
{
  Symmetry *symmetry, *t_sym;
  double inv_tmat[3][3], tmp_mat[3][3];
  VecDBL *pure_trans, *lattice_trans;

  symmetry = NULL;
  t_sym = NULL;
  pure_trans = NULL;
  lattice_trans = NULL;

  mat_cast_matrix_3i_to_3d(tmp_mat, t_mat);
  mat_inverse_matrix_d3(inv_tmat, tmp_mat, 0);

  if ((lattice_trans = get_lattice_translations(frame, inv_tmat)) == NULL) {
    return NULL;
  }

  if ((pure_trans = remove_overlapping_lattice_points(lattice,
						      lattice_trans,
						      symprec)) == NULL) {
    mat_free_VecDBL(lattice_trans);
    lattice_trans = NULL;
    return NULL;
  }

  if ((t_sym = get_symmetry_in_original_cell(t_mat,
					     inv_tmat,
					     lattice,
					     prim_sym,
					     symprec)) == NULL) {
    mat_free_VecDBL(pure_trans);
    pure_trans = NULL;
    mat_free_VecDBL(lattice_trans);
    lattice_trans = NULL;
    return NULL;
  }

  if (pure_trans->size == multiplicity) {
    symmetry = copy_symmetry_upon_lattice_points(pure_trans, t_sym);
  }

  mat_free_VecDBL(lattice_trans);
  lattice_trans = NULL;
  mat_free_VecDBL(pure_trans);
  pure_trans = NULL;
  sym_free_symmetry(t_sym);
  t_sym = NULL;

  return symmetry;
}
Example #11
0
/* Return 0 if failed */
static int iterative_search_hall_number(double origin_shift[3],
					double conv_lattice[3][3],
					const int candidates[],
					const int num_candidates,
					SPGCONST Cell * primitive,
					SPGCONST Symmetry * symmetry,
					const double symprec)
{
  int attempt, hall_number;
  double tolerance;
  Symmetry * sym_reduced;

  debug_print("iterative_search_hall_number:\n");

  hall_number = 0;
  sym_reduced = NULL;

  hall_number = search_hall_number(origin_shift,
				   conv_lattice,
				   candidates,
				   num_candidates,
				   primitive->lattice,
				   symmetry,
				   symprec);

  if (hall_number > 0) {
    goto ret;
  }

  tolerance = symprec;
  for (attempt = 0; attempt < 100; attempt++) {

    warning_print("spglib: Attempt %d tolerance = %f failed",
		  attempt, tolerance);
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);

    tolerance *= REDUCE_RATE;
    sym_reduced = sym_reduce_operation(primitive, symmetry, tolerance);
    hall_number = search_hall_number(origin_shift,
				     conv_lattice,
				     candidates,
				     num_candidates,
				     primitive->lattice,
				     sym_reduced,
				     symprec);
    sym_free_symmetry(sym_reduced);
    sym_reduced = NULL;
    if (hall_number > 0) {
      break;
    }
  }

 ret:
  return hall_number;
}
Example #12
0
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);
}
Example #13
0
static int get_hall_number_local_iteration(double origin_shift[3],
        double conv_lattice[3][3],
        SPGCONST Cell * primitive,
        SPGCONST Symmetry * symmetry,
        const double symprec)
{
    int attempt, pg_num, hall_number=0;
    double tolerance;
    Symmetry * sym_reduced;

    debug_print("get_hall_number_local_iteration:\n");

    tolerance = symprec;
    for (attempt = 0; attempt < 100; attempt++) {
        tolerance *= REDUCE_RATE;
        debug_print("  Attempt %d tolerance = %f\n", attempt, tolerance);
        sym_reduced = sym_reduce_operation(primitive, symmetry, tolerance);
        pg_num = ptg_get_pointgroup_number(sym_reduced);

        if (pg_num > -1) {
            hall_number = get_hall_number_local(origin_shift,
                                                conv_lattice,
                                                primitive,
                                                sym_reduced,
                                                symprec);
            if (hall_number > 0) {
                sym_free_symmetry(sym_reduced);
                break;
            }
        }
        sym_free_symmetry(sym_reduced);
    }

#ifdef SPGWARNING
    if (hall_number == 0) {
        warning_print("spglib: Iterative attempt with sym_reduce_operation to find Hall symbol failed.\n");
    }
#endif

    return hall_number;
}
Example #14
0
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;
}
Example #15
0
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;
}
Example #16
0
static Symmetry * recover_operations_original(SPGCONST Symmetry *symmetry,
					      const VecDBL * pure_trans,
					      SPGCONST Cell *cell,
					      SPGCONST Cell *primitive)
{
  int i, j, k, multi;
  double inv_prim_lat[3][3], drot[3][3], trans_mat[3][3], trans_mat_inv[3][3];
  Symmetry *symmetry_orig, *sym_tmp;

  debug_print("recover_operations_original:\n");

  multi = pure_trans->size;
  sym_tmp = sym_alloc_symmetry(symmetry->size);
  symmetry_orig = sym_alloc_symmetry(symmetry->size * multi);

  mat_inverse_matrix_d3(inv_prim_lat, primitive->lattice, 0);
  mat_multiply_matrix_d3(trans_mat, inv_prim_lat, cell->lattice);
  mat_inverse_matrix_d3(trans_mat_inv, trans_mat, 0);

  for(i = 0; i < symmetry->size; i++) {
    mat_copy_matrix_i3(sym_tmp->rot[i], symmetry->rot[i]);
    mat_copy_vector_d3(sym_tmp->trans[i], symmetry->trans[i]);
  }

  for(i = 0; i < symmetry->size; i++) {
    mat_cast_matrix_3i_to_3d(drot, sym_tmp->rot[i]);
    mat_get_similar_matrix_d3(drot, drot, trans_mat, 0);
    mat_cast_matrix_3d_to_3i(sym_tmp->rot[i], drot);

    mat_multiply_matrix_vector_d3(sym_tmp->trans[i],
				  trans_mat_inv,
				  sym_tmp->trans[i]);
  }


  for(i = 0; i < symmetry->size; i++) {
    for(j = 0; j < multi; j++) {
      mat_copy_matrix_i3(symmetry_orig->rot[i * multi + j], sym_tmp->rot[i]);
      for (k = 0; k < 3; k++) {
	symmetry_orig->trans[i * multi + j][k] =
	  sym_tmp->trans[i][k] + pure_trans->vec[j][k];
      }
    }
  }

  sym_free_symmetry(sym_tmp);

  return symmetry_orig;
}
Example #17
0
File: spglib.c Project: nfh/phonopy
/* 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;
}
Example #18
0
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;
}
Example #19
0
/* 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;
}
Example #20
0
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;
}
Example #21
0
/* Return 0 if failed */
int spg_get_symmetry_from_database(int rotations[192][3][3],
				   double translations[192][3],
				   const int hall_number)
{
  int i, size;
  Symmetry *symmetry;

  symmetry = NULL;

  if ((symmetry = spgdb_get_spacegroup_operations(hall_number)) == NULL) {
    return 0;
  }

  for (i = 0; i < symmetry->size; i++) {
    mat_copy_matrix_i3(rotations[i], symmetry->rot[i]);
    mat_copy_vector_d3(translations[i], symmetry->trans[i]);
  }
  size = symmetry->size;

  sym_free_symmetry(symmetry);

  return size;
}
Example #22
0
/* Return NULL if failed */
static Cell *
get_bravais_exact_positions_and_lattice(int * wyckoffs,
					int * equiv_atoms,
					SPGCONST Spacegroup *spacegroup,
					SPGCONST Cell * primitive,
					const double symprec)
{
  int i;
  int *wyckoffs_prim, *equiv_atoms_prim;
  Symmetry *conv_sym;
  Cell *bravais, *conv_prim;
  VecDBL *exact_positions;

  debug_print("get_bravais_exact_positions_and_lattice\n");

  wyckoffs_prim = NULL;
  equiv_atoms_prim = NULL;
  conv_prim = NULL;
  bravais = NULL;
  conv_sym = NULL;
  exact_positions = NULL;

  /* Symmetrize atomic positions of conventional unit cell */
  if ((wyckoffs_prim = (int*)malloc(sizeof(int) * primitive->size)) == NULL) {
    warning_print("spglib: Memory could not be allocated ");
    return NULL;
  }

  if ((equiv_atoms_prim = (int*)malloc(sizeof(int) * primitive->size)) == NULL) {
    warning_print("spglib: Memory could not be allocated ");
    free(wyckoffs_prim);
    wyckoffs_prim = NULL;
    return NULL;
  }

  for (i = 0; i < primitive->size; i++) {
    wyckoffs_prim[i] = -1;
    equiv_atoms_prim[i] = -1;
  }

  /* Positions of primitive atoms are represented wrt Bravais lattice */
  if ((conv_prim = get_conventional_primitive(spacegroup, primitive)) == NULL) {
    free(wyckoffs_prim);
    wyckoffs_prim = NULL;
    free(equiv_atoms_prim);
    equiv_atoms_prim = NULL;
    return NULL;
  }

  /* Symmetries in database (wrt Bravais lattice) */
  if ((conv_sym = spgdb_get_spacegroup_operations(spacegroup->hall_number))
      == NULL) {
    goto err;
  }

  /* Lattice vectors are set. */
  get_conventional_lattice(conv_prim->lattice, spacegroup);

  if ((exact_positions = ssm_get_exact_positions(wyckoffs_prim,
						 equiv_atoms_prim,
						 conv_prim,
						 conv_sym,
						 spacegroup->hall_number,
						 symprec)) == NULL) {
    sym_free_symmetry(conv_sym);
    conv_sym = NULL;
    goto err;
  }

  for (i = 0; i < conv_prim->size; i++) {
    mat_copy_vector_d3(conv_prim->position[i], exact_positions->vec[i]);
  }

  bravais = expand_positions(wyckoffs,
			     equiv_atoms,
			     conv_prim,
			     conv_sym,
			     wyckoffs_prim,
			     equiv_atoms_prim);

  mat_free_VecDBL(exact_positions);
  exact_positions = NULL;
  sym_free_symmetry(conv_sym);
  conv_sym = NULL;
 err:
  free(wyckoffs_prim);
  wyckoffs_prim = NULL;
  free(equiv_atoms_prim);
  equiv_atoms_prim = NULL;
  cel_free_cell(conv_prim);
  conv_prim = NULL;

  return bravais;
}
Example #23
0
/*    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;
}
Example #24
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;
}
Example #25
0
/* Return NULL if failed */
static Symmetry *
get_symmetry_in_original_cell(SPGCONST int t_mat[3][3],
			      SPGCONST double inv_tmat[3][3],
			      SPGCONST double lattice[3][3],
			      SPGCONST Symmetry *prim_sym,
			      const double symprec)
{
  int i, size_sym_orig;
  double tmp_rot_d[3][3], tmp_lat_d[3][3], tmp_lat_i[3][3], tmp_mat[3][3];
  int tmp_rot_i[3][3];
  Symmetry *t_sym, *t_red_sym;

  t_sym = NULL;
  t_red_sym = NULL;

  if ((t_sym = sym_alloc_symmetry(prim_sym->size)) == NULL) {
    return NULL;
  }

  /* transform symmetry operations of primitive cell to those of original */
  size_sym_orig = 0;
  for (i = 0; i < prim_sym->size; i++) {
    /* R' = T^-1*R*T */
    mat_multiply_matrix_di3(tmp_mat, inv_tmat, prim_sym->rot[i]);
    mat_multiply_matrix_di3(tmp_rot_d, tmp_mat, t_mat);

    /* In spglib, symmetry of supercell is defined by the set of symmetry */
    /* operations that are searched among supercell lattice point group */
    /* operations. The supercell lattice may be made by breaking the */
    /* unit cell lattice symmetry. In this case, a part of symmetry */
    /* operations is discarded. */
    mat_cast_matrix_3d_to_3i(tmp_rot_i, tmp_rot_d);
    mat_multiply_matrix_di3(tmp_lat_i, lattice, tmp_rot_i);
    mat_multiply_matrix_d3(tmp_lat_d, lattice, tmp_rot_d);
    if (mat_check_identity_matrix_d3(tmp_lat_i, tmp_lat_d, symprec)) {
      mat_copy_matrix_i3(t_sym->rot[size_sym_orig], tmp_rot_i);
      /* t' = T^-1*t */
      mat_multiply_matrix_vector_d3(t_sym->trans[size_sym_orig],
				    inv_tmat,
				    prim_sym->trans[i]);
      size_sym_orig++;
    }
  }

  /* Broken symmetry due to supercell multiplicity */
  if (size_sym_orig != prim_sym->size) {

    if ((t_red_sym = sym_alloc_symmetry(size_sym_orig)) == NULL) {
      sym_free_symmetry(t_sym);
      t_sym = NULL;
      return NULL;
    }

    for (i = 0; i < size_sym_orig; i++) {
      mat_copy_matrix_i3(t_red_sym->rot[i], t_sym->rot[i]);
      mat_copy_vector_d3(t_red_sym->trans[i], t_sym->trans[i]);
    }

    sym_free_symmetry(t_sym);
    t_sym = NULL;

    t_sym = t_red_sym;
    t_red_sym = NULL;
  }

  return t_sym;
}
Example #26
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;
}
Example #27
0
static Symmetry * reduce_symmetry_in_frame(const int frame[3],
        SPGCONST Symmetry *prim_sym,
        SPGCONST int t_mat[3][3],
        SPGCONST double lattice[3][3],
        const int multiplicity,
        const double symprec)
{
    int i, j, k, l, num_trans, size_sym_orig;
    Symmetry *symmetry, *t_sym;
    double inv_tmat[3][3], tmp_mat[3][3], tmp_rot_d[3][3], tmp_lat_d[3][3], tmp_lat_i[3][3];
    int tmp_rot_i[3][3];
    VecDBL *pure_trans, *lattice_trans;

    mat_cast_matrix_3i_to_3d(tmp_mat, t_mat);
    mat_inverse_matrix_d3(inv_tmat, tmp_mat, symprec);

    /* transformed lattice points */
    lattice_trans = mat_alloc_VecDBL(frame[0]*frame[1]*frame[2]);
    num_trans = 0;
    for (i = 0; i < frame[0]; i++) {
        for (j = 0; j < frame[1]; j++) {
            for (k = 0; k < frame[2]; k++) {
                lattice_trans->vec[num_trans][0] = i;
                lattice_trans->vec[num_trans][1] = j;
                lattice_trans->vec[num_trans][2] = k;

                mat_multiply_matrix_vector_d3(lattice_trans->vec[num_trans],
                                              inv_tmat,
                                              lattice_trans->vec[num_trans]);
                for (l = 0; l < 3; l++) {
                    /* t' = T^-1*t */
                    lattice_trans->vec[num_trans][l] = \
                                                       mat_Dmod1(lattice_trans->vec[num_trans][l]);
                }
                num_trans++;
            }
        }
    }

    /* transformed symmetry operations of primitive cell */
    t_sym = sym_alloc_symmetry(prim_sym->size);
    size_sym_orig = 0;
    for (i = 0; i < prim_sym->size; i++) {
        /* R' = T^-1*R*T */
        mat_multiply_matrix_di3(tmp_mat, inv_tmat, prim_sym->rot[i]);
        mat_multiply_matrix_di3(tmp_rot_d, tmp_mat, t_mat);
        mat_cast_matrix_3d_to_3i(tmp_rot_i, tmp_rot_d);
        mat_multiply_matrix_di3(tmp_lat_i, lattice, tmp_rot_i);
        mat_multiply_matrix_d3(tmp_lat_d, lattice, tmp_rot_d);
        if (mat_check_identity_matrix_d3(tmp_lat_i, tmp_lat_d, symprec)) {
            mat_copy_matrix_i3(t_sym->rot[size_sym_orig], tmp_rot_i);
            /* t' = T^-1*t */
            mat_multiply_matrix_vector_d3(t_sym->trans[size_sym_orig],
                                          inv_tmat, prim_sym->trans[i]);
            size_sym_orig++;
        }
    }

    /* reduce lattice points */
    pure_trans = reduce_lattice_points(lattice,
                                       lattice_trans,
                                       symprec);

    if (! (pure_trans->size == multiplicity)) {
        symmetry = sym_alloc_symmetry(0);
        goto ret;
    }

    /* copy symmetry operations upon lattice points */
    symmetry = sym_alloc_symmetry(pure_trans->size * size_sym_orig);
    for (i = 0; i < pure_trans->size; i++) {
        for (j = 0; j < size_sym_orig; j++) {
            mat_copy_matrix_i3(symmetry->rot[size_sym_orig * i + j],
                               t_sym->rot[j]);
            mat_copy_vector_d3(symmetry->trans[size_sym_orig * i + j],
                               t_sym->trans[j]);
            for (k = 0; k < 3; k++) {
                symmetry->trans[size_sym_orig * i + j][k] += pure_trans->vec[i][k];
                symmetry->trans[size_sym_orig * i + j][k] = \
                        mat_Dmod1(symmetry->trans[size_sym_orig * i + j][k]);
            }
        }
    }


ret:
    mat_free_VecDBL(lattice_trans);
    mat_free_VecDBL(pure_trans);
    sym_free_symmetry(t_sym);

    return symmetry;
}
Example #28
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;
}
Example #29
0
static Symmetry * reduce_symmetry_in_frame( const int frame[3],
					    SPGCONST Symmetry *prim_sym,
					    SPGCONST int t_mat[3][3],
					    SPGCONST double lattice[3][3],
					    const double symprec )
{
  int i, j, k, l, n, num_op, is_found;
  Symmetry *symmetry, *t_sym;
  double inv_mat[3][3], tmp_mat[3][3];
  VecDBL *t, *lattice_trans;

  mat_cast_matrix_3i_to_3d( tmp_mat, t_mat );
  mat_inverse_matrix_d3( inv_mat, tmp_mat, symprec );

  /* transformed lattice points */
  lattice_trans = mat_alloc_VecDBL( frame[0]*frame[1]*frame[2] );
  n = 0;
  for ( i = 0; i < frame[0]; i++ ) {
    for ( j = 0; j < frame[1]; j++ ) {
      for ( k = 0; k < frame[2]; k++ ) {
	lattice_trans->vec[n][0] = i;
	lattice_trans->vec[n][1] = j;
	lattice_trans->vec[n][2] = k;

	mat_multiply_matrix_vector_d3( lattice_trans->vec[n],
				       inv_mat,
				       lattice_trans->vec[n] );
	for ( l = 0; l < 3; l++ ) {
	  /* t' = T^-1*t */
	  lattice_trans->vec[n][l] = mat_Dmod1( lattice_trans->vec[n][l] ); 
	}
	n++;
      }
    }
  }

  /* transformed symmetry operations of primitive cell */
  t_sym = sym_alloc_symmetry( prim_sym->size );
  for ( i = 0; i < prim_sym->size; i++ ) {
    /* R' = T^-1*R*T */
    mat_multiply_matrix_di3( tmp_mat, inv_mat, prim_sym->rot[i] );
    mat_multiply_matrix_di3( tmp_mat, tmp_mat, t_mat );
    mat_cast_matrix_3d_to_3i( t_sym->rot[i], tmp_mat );
    /* t' = T^-1*t */
    mat_multiply_matrix_vector_d3( t_sym->trans[i], inv_mat, prim_sym->trans[ i ] );
  }

  /* reduce lattice points */
  num_op = 0;
  t = mat_alloc_VecDBL( lattice_trans->size );
  for ( i = 0; i < lattice_trans->size; i++ ) {
    is_found = 0;
    for ( j = 0; j < num_op; j++ ) {
      if ( cel_is_overlap( lattice_trans->vec[i], t->vec[j], lattice, symprec ) ) {
	is_found = 1;
	break;
      }
    }
    if ( ! is_found ) {
      mat_copy_vector_d3( t->vec[num_op], lattice_trans->vec[i] );
      num_op++;
    }
  }

  /* copy symmetry operations upon lattice points */
  symmetry = sym_alloc_symmetry( num_op * t_sym->size );
  for ( i = 0; i < num_op; i++ ) {
    for ( j = 0; j < t_sym->size; j++ ) {
      mat_copy_matrix_i3( symmetry->rot[ t_sym->size * i + j ], t_sym->rot[j] );
      mat_copy_vector_d3( symmetry->trans[ t_sym->size * i + j ], t_sym->trans[j] );
      for ( k = 0; k < 3; k++ ) {
	symmetry->trans[ t_sym->size * i + j ][k] += t->vec[i][k];
	symmetry->trans[ t_sym->size * i + j ][k] = \
	  mat_Dmod1( symmetry->trans[ t_sym->size * i + j ][k] );
      }
    }
  }
  
  mat_free_VecDBL( t );
  sym_free_symmetry( t_sym );

  return symmetry;
}
Example #30
0
/* 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;
}