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
static int get_operation_supercell( int rot[][3][3],
				    double trans[][3],
				    const int num_sym, 
				    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];
  MatINT *rot_prim;
  VecDBL *trans_prim;

  rot_prim = mat_alloc_MatINT( num_sym );
  trans_prim = mat_alloc_VecDBL( num_sym );
  multi = pure_trans->size;

  debug_print("get_operation_supercell\n");

  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 < num_sym; i++) {

    /* Translations  */
    mat_multiply_matrix_vector_d3( trans[i], trans_mat_inv, trans[i] );

    /* Rotations */
    mat_cast_matrix_3i_to_3d( drot, rot[i] );
    mat_get_similar_matrix_d3( drot, drot, trans_mat, 0 );
    mat_cast_matrix_3d_to_3i( rot[i], drot );
  }

  for( i = 0; i < num_sym; i++ ) {
    mat_copy_matrix_i3( rot_prim->mat[i], rot[i] );
    for( j = 0; j < 3; j++ )
      trans_prim->vec[i][j] = trans[i][j];
  }

  /* Rotations and translations are copied with the set of */
  /* pure translations. */
  for( i = 0; i < num_sym; i++ ) {
    for( j = 0; j < multi; j++ ) {
      mat_copy_matrix_i3( rot[ i * multi + j ], rot_prim->mat[i] );
      for ( k = 0; k < 3; k++ ) {
	trans[i * multi + j][k] =
	  mat_Dmod1( trans_prim->vec[i][k] + pure_trans->vec[j][k] );
      }
    }
  }

  mat_free_MatINT( rot_prim );
  mat_free_VecDBL( trans_prim );

  /* return number of symmetry operation of supercell */
  return num_sym * multi;
}
Example #3
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 #4
0
static Cell * get_cell_with_smallest_lattice( SPGCONST Cell * cell,
					      const double symprec )
{
  int i, j;
  double min_lat[3][3], trans_mat[3][3], inv_lat[3][3];
  Cell * smallest_cell;

  if ( lat_smallest_lattice_vector( min_lat,
				    cell->lattice,
				    symprec ) ) {
    mat_inverse_matrix_d3( inv_lat, min_lat, 0 );
    mat_multiply_matrix_d3( trans_mat, inv_lat, cell->lattice );
    smallest_cell = cel_alloc_cell( cell->size );
    mat_copy_matrix_d3( smallest_cell->lattice, min_lat );
    for ( i = 0; i < cell->size; i++ ) {
      smallest_cell->types[i] = cell->types[i];
      mat_multiply_matrix_vector_d3( smallest_cell->position[i],
				     trans_mat, cell->position[i] );
      for ( j = 0; j < 3; j++ ) {
	cell->position[i][j] -= mat_Nint( cell->position[i][j] );
      }
    }
  } else {
    smallest_cell = cel_alloc_cell( -1 );
  }

  return smallest_cell;
}
Example #5
0
static Cell * get_conventional_primitive(SPGCONST Spacegroup * spacegroup,
        SPGCONST Cell * primitive)
{
    int i, j;
    double inv_brv[3][3], trans_mat[3][3];
    Cell * conv_prim;

    conv_prim = cel_alloc_cell(primitive->size);

    mat_inverse_matrix_d3(inv_brv, spacegroup->bravais_lattice, 0);
    mat_multiply_matrix_d3(trans_mat, inv_brv, primitive->lattice);

    for (i = 0; i < primitive->size; i++) {
        conv_prim->types[i] = primitive->types[i];
        mat_multiply_matrix_vector_d3(conv_prim->position[i],
                                      trans_mat,
                                      primitive->position[i]);
        for (j = 0; j < 3; j++) {
            conv_prim->position[i][j] -= spacegroup->origin_shift[j];
            conv_prim->position[i][j] -= mat_Nint(conv_prim->position[i][j]);
        }
    }

    return conv_prim;
}
Example #6
0
static VecDBL * get_positions_primitive( SPGCONST Cell * cell,
					 SPGCONST double prim_lat[3][3] )
{
  int i, j;
  double tmp_matrix[3][3], axis_inv[3][3];
  VecDBL * position;

  position = mat_alloc_VecDBL( cell->size );

  mat_inverse_matrix_d3(tmp_matrix, prim_lat, 0);
  mat_multiply_matrix_d3(axis_inv, tmp_matrix, cell->lattice);

  /* Send atoms into the primitive cell */
  debug_print("Positions in new axes reduced to primitive cell\n");
  for (i = 0; i < cell->size; i++) {
    mat_multiply_matrix_vector_d3( position->vec[i],
				   axis_inv, cell->position[i] );
    for (j = 0; j < 3; j++) {
      position->vec[i][j] -= mat_Nint( position->vec[i][j] );
    }
    debug_print("%d: %f %f %f\n", i + 1,
		position->vec[i][0], 
		position->vec[i][1],
		position->vec[i][2]);
  }

  return position;
}
Example #7
0
/* Return NULL if failed */
static VecDBL * get_positions_primitive(SPGCONST Cell * cell,
                                        SPGCONST double prim_lat[3][3])
{
    int i, j;
    double tmp_matrix[3][3], axis_inv[3][3];
    VecDBL * position;

    position = NULL;

    if ((position = mat_alloc_VecDBL(cell->size)) == NULL) {
        return NULL;
    }

    mat_inverse_matrix_d3(tmp_matrix, prim_lat, 0);
    mat_multiply_matrix_d3(axis_inv, tmp_matrix, cell->lattice);

    /* Send atoms into the primitive cell */
    for (i = 0; i < cell->size; i++) {
        mat_multiply_matrix_vector_d3(position->vec[i],
                                      axis_inv,
                                      cell->position[i]);
        for (j = 0; j < 3; j++) {
            position->vec[i][j] -= mat_Nint(position->vec[i][j]);
        }
    }

    return position;
}
Example #8
0
/* Return NULL if failed */
static VecDBL *
translate_atoms_in_trimmed_lattice(const Cell * cell,
                                   SPGCONST double trimmed_lattice[3][3])
{
  int i, j;
  double tmp_matrix[3][3], axis_inv[3][3];
  VecDBL * position;

  position = NULL;

  if ((position = mat_alloc_VecDBL(cell->size)) == NULL) {
    return NULL;
  }

  mat_inverse_matrix_d3(tmp_matrix, trimmed_lattice, 0);
  mat_multiply_matrix_d3(axis_inv, tmp_matrix, cell->lattice);

  /* Send atoms into the trimmed cell */
  for (i = 0; i < cell->size; i++) {
    mat_multiply_matrix_vector_d3(position->vec[i],
                                  axis_inv,
                                  cell->position[i]);
    for (j = 0; j < 3; j++) {
      position->vec[i][j] = mat_Dmod1(position->vec[i][j]);
    }
  }

  return position;
}
Example #9
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 #10
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 #11
0
/* m = b^-1 a b */
int mat_get_similar_matrix_d3(double m[3][3], const double a[3][3],
			      const double b[3][3], const double precision)
{
    double c[3][3];
    if (!mat_inverse_matrix_d3(c, b, precision)) {
        fprintf(stderr, "spglib: No similar matrix due to 0 determinant.\n");
        return 0;
    }
    mat_multiply_matrix_d3(m, a, b);
    mat_multiply_matrix_d3(m, c, m);
    return 1;
}
Example #12
0
/* Return NULL if failed */
Cell * spa_transform_to_primitive(SPGCONST Cell * cell,
				  SPGCONST double trans_mat[3][3],
				  const Centering centering,
				  const double symprec)
{
  int * mapping_table;
  double tmat[3][3], tmat_inv[3][3], prim_lat[3][3];
  Cell * primitive;

  mapping_table = NULL;
  primitive = NULL;

  mat_inverse_matrix_d3(tmat_inv, trans_mat, 0);

  switch (centering) {
  case PRIMITIVE:
    mat_copy_matrix_d3(tmat, tmat_inv);
    break;
  case A_FACE:
    mat_multiply_matrix_d3(tmat, tmat_inv, A_mat);
    break;
  case C_FACE:
    mat_multiply_matrix_d3(tmat, tmat_inv, C_mat);
    break;
  case FACE:
    mat_multiply_matrix_d3(tmat, tmat_inv, F_mat);
    break;
  case BODY:
    mat_multiply_matrix_d3(tmat, tmat_inv, I_mat);
    break;
  case R_CENTER:
    mat_multiply_matrix_d3(tmat, tmat_inv, R_mat);
    break;
  default:
    goto err;
  }

  if ((mapping_table = (int*) malloc(sizeof(int) * cell->size)) == NULL) {
    warning_print("spglib: Memory could not be allocated ");
    goto err;
  }

  mat_multiply_matrix_d3(prim_lat, cell->lattice, tmat);
  primitive = cel_trim_cell(mapping_table, prim_lat, cell, symprec);

  free(mapping_table);
  mapping_table = NULL;

  return primitive;

 err:
  return NULL;
}
Example #13
0
static Symmetry * get_primitive_db_symmetry(SPGCONST double t_mat[3][3],
        const Symmetry *conv_sym,
        const double symprec)
{
    int i, j, num_op;
    double inv_mat[3][3], tmp_mat[3][3];
    MatINT *r_prim;
    VecDBL *t_prim;
    Symmetry *prim_sym;

    r_prim = mat_alloc_MatINT(conv_sym->size);
    t_prim = mat_alloc_VecDBL(conv_sym->size);

    mat_inverse_matrix_d3(inv_mat, t_mat, symprec);

    num_op = 0;
    for (i = 0; i < conv_sym->size; i++) {
        for (j = 0; j < i; j++) {
            if (mat_check_identity_matrix_i3(conv_sym->rot[i],
                                             conv_sym->rot[j])) {
                goto pass;
            }
        }

        /* R' = T*R*T^-1 */
        mat_multiply_matrix_di3(tmp_mat, t_mat, conv_sym->rot[i]);
        mat_multiply_matrix_d3(tmp_mat, tmp_mat, inv_mat);
        mat_cast_matrix_3d_to_3i(r_prim->mat[ num_op ], tmp_mat);
        /* t' = T*t */
        mat_multiply_matrix_vector_d3(t_prim->vec[ num_op ],
                                      t_mat,
                                      conv_sym->trans[ i ]);
        num_op++;

pass:
        ;
    }

    prim_sym = sym_alloc_symmetry(num_op);
    for (i = 0; i < num_op; i++) {
        mat_copy_matrix_i3(prim_sym->rot[i], r_prim->mat[i]);
        for (j = 0; j < 3; j++) {
            prim_sym->trans[i][j] = t_prim->vec[i][j] - mat_Nint(t_prim->vec[i][j]);
        }
    }

    mat_free_MatINT(r_prim);
    mat_free_VecDBL(t_prim);

    return prim_sym;
}
Example #14
0
/* m = b^-1 a b */
int mat_get_similar_matrix_d3(double m[3][3],
			      SPGCONST double a[3][3],
			      SPGCONST double b[3][3],
			      const double precision)
{
  double c[3][3];
  if (!mat_inverse_matrix_d3(c, b, precision)) {
    warning_print("spglib: No similar matrix due to 0 determinant.\n");
    debug_print("No similar matrix due to 0 determinant.\n");
    return 0;
  }
  mat_multiply_matrix_d3(m, a, b);
  mat_multiply_matrix_d3(m, c, m);
  return 1;
}
Example #15
0
static PointSymmetry
transform_pointsymmetry(SPGCONST PointSymmetry * lat_sym_orig,
			SPGCONST double new_lattice[3][3],
			SPGCONST double original_lattice[3][3])
{
  int i, size;
  double trans_mat[3][3], inv_mat[3][3], drot[3][3];
  PointSymmetry lat_sym_new;

  lat_sym_new.size = 0;

  mat_inverse_matrix_d3(inv_mat, original_lattice, 0);
  mat_multiply_matrix_d3(trans_mat, inv_mat, new_lattice);

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

    /* new_lattice may have lower point symmetry than original_lattice.*/
    /* The operations that have non-integer elements are not counted. */
    if (mat_is_int_matrix(drot, mat_Dabs(mat_get_determinant_d3(trans_mat)) / 10)) {
      mat_cast_matrix_3d_to_3i(lat_sym_new.rot[size], drot);
      if (abs(mat_get_determinant_i3(lat_sym_new.rot[size])) != 1) {
	warning_print("spglib: A point symmetry operation is not unimodular.");
	warning_print("(line %d, %s).\n", __LINE__, __FILE__);
	goto err;
      }
      size++;
    }
  }

#ifdef SPGWARNING
  if (! (lat_sym_orig->size == size)) {
    warning_print("spglib: Some of point symmetry operations were dropped.");
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);
  }
#endif

  lat_sym_new.size = size;
  return lat_sym_new;

 err:
  return lat_sym_new;
}
Example #16
0
/* Return 0 if failed */
static int change_basis_monocli(int int_transform_mat[3][3],
				SPGCONST double conv_lattice[3][3],
				SPGCONST double primitive_lattice[3][3],
				const double symprec)
{
  double smallest_lattice[3][3], inv_lattice[3][3], transform_mat[3][3];

  if (! del_delaunay_reduce_2D(smallest_lattice,
			       conv_lattice,
			       1, /* unique axis of b */
			       symprec)) {
    return 0;
  }

  mat_inverse_matrix_d3(inv_lattice, primitive_lattice, 0);
  mat_multiply_matrix_d3(transform_mat, inv_lattice, smallest_lattice);
  mat_cast_matrix_3d_to_3i(int_transform_mat, transform_mat);
  return 1;
}
Example #17
0
/* Return NULL if failed */
static Cell * get_cell_with_smallest_lattice(SPGCONST Cell * cell,
					     const double symprec)
{
  int i, j;
  double min_lat[3][3], trans_mat[3][3], inv_lat[3][3];
  Cell * smallest_cell;

  debug_print("get_cell_with_smallest_lattice:\n");
  
  smallest_cell = NULL;

  if (!lat_smallest_lattice_vector(min_lat,
				   cell->lattice,
				   symprec)) {
    goto err;
  }

  mat_inverse_matrix_d3(inv_lat, min_lat, 0);
  mat_multiply_matrix_d3(trans_mat, inv_lat, cell->lattice);

  if ((smallest_cell = cel_alloc_cell(cell->size)) == NULL) {
    goto err;
  }

  mat_copy_matrix_d3(smallest_cell->lattice, min_lat);
  for (i = 0; i < cell->size; i++) {
    smallest_cell->types[i] = cell->types[i];
    mat_multiply_matrix_vector_d3(smallest_cell->position[i],
				  trans_mat, cell->position[i]);
    for (j = 0; j < 3; j++) {
      cell->position[i][j] = mat_Dmod1(cell->position[i][j]);
    }
  }

  return smallest_cell;

 err:
  return NULL;
}
Example #18
0
/* Return 0 if failed */
static int change_basis_tricli(int int_transform_mat[3][3],
			       SPGCONST double conv_lattice[3][3],
			       SPGCONST double primitive_lattice[3][3],
			       const double symprec)
{
  int i, j;
  double niggli_cell[9];
  double smallest_lattice[3][3], inv_lattice[3][3], transform_mat[3][3];

  for (i = 0; i < 3; i++) {
    for (j = 0; j < 3; j++) {
      niggli_cell[i * 3 + j] = conv_lattice[i][j];
    }
  }

  if (! niggli_reduce(niggli_cell, symprec * symprec)) {
    return 0;
  }

  for (i = 0; i < 3; i++) {
    for (j = 0; j < 3; j++) {
      smallest_lattice[i][j] = niggli_cell[i * 3 + j];
    }
  }
  if (mat_get_determinant_d3(smallest_lattice) < 0) {
    for (i = 0; i < 3; i++) {
      for (j = 0; j < 3; j++) {
	smallest_lattice[i][j] = -smallest_lattice[i][j];
      }
    }
  }
  mat_inverse_matrix_d3(inv_lattice, primitive_lattice, 0);
  mat_multiply_matrix_d3(transform_mat, inv_lattice, smallest_lattice);
  mat_cast_matrix_3d_to_3i(int_transform_mat, transform_mat);

  return 1;
}
Example #19
0
static Symmetry * get_conventional_symmetry(SPGCONST double transform_mat[3][3],
        const Centering centering,
        const Symmetry *primitive_sym)
{
    int i, j, k, multi, size;
    double tmp_trans;
    double tmp_matrix_d3[3][3], shift[4][3];
    double symmetry_rot_d3[3][3], primitive_sym_rot_d3[3][3];
    Symmetry *symmetry;

    size = primitive_sym->size;

    if (centering == FACE) {
        symmetry = sym_alloc_symmetry(size * 4);
    }
    else {
        if (centering) {
            symmetry = sym_alloc_symmetry(size * 2);
        } else {
            symmetry = sym_alloc_symmetry(size);
        }
    }

    for (i = 0; i < size; i++) {
        mat_cast_matrix_3i_to_3d(primitive_sym_rot_d3, primitive_sym->rot[i]);

        /* C*S*C^-1: recover conventional cell symmetry operation */
        mat_get_similar_matrix_d3(symmetry_rot_d3,
                                  primitive_sym_rot_d3,
                                  transform_mat,
                                  0);
        mat_cast_matrix_3d_to_3i(symmetry->rot[i], symmetry_rot_d3);

        /* translation in conventional cell: C = B^-1*P */
        mat_inverse_matrix_d3(tmp_matrix_d3,
                              transform_mat,
                              0);
        mat_multiply_matrix_vector_d3(symmetry->trans[i],
                                      tmp_matrix_d3,
                                      primitive_sym->trans[i]);
    }

    multi = 1;

    if (centering) {
        if (! (centering == FACE)) {
            for (i = 0; i < 3; i++) {
                shift[0][i] = 0.5;
            }
            if (centering == A_FACE) {
                shift[0][0] = 0;
            }
            if (centering == B_FACE) {
                shift[0][1] = 0;
            }
            if (centering == C_FACE) {
                shift[0][2] = 0;
            }

            multi = 2;
        }

        if (centering == FACE) {
            shift[0][0] = 0;
            shift[0][1] = 0.5;
            shift[0][2] = 0.5;
            shift[1][0] = 0.5;
            shift[1][1] = 0;
            shift[1][2] = 0.5;
            shift[2][0] = 0.5;
            shift[2][1] = 0.5;
            shift[2][2] = 0;

            multi = 4;
        }

        for (i = 0; i < multi - 1; i++) {
            for (j = 0; j < size; j++) {
                mat_copy_matrix_i3(symmetry->rot[(i+1) * size + j],
                                   symmetry->rot[j]);
                for (k = 0; k < 3; k++) {
                    tmp_trans = symmetry->trans[j][k] + shift[i][k];
                    symmetry->trans[(i+1) * size + j][k] = tmp_trans;
                }
            }
        }
    }


    /* Reduce translations into -0 < trans < 1.0 */
    for (i = 0; i < multi; i++) {
        for (j = 0; j < size; j++) {
            for (k = 0; k < 3; k++) {
                tmp_trans = symmetry->trans[i * size + j][k];
                tmp_trans -= mat_Nint(tmp_trans);
                if (tmp_trans < 0) {
                    tmp_trans += 1.0;
                }
                symmetry->trans[i * size + j][k] = tmp_trans;
            }
        }
    }

    return symmetry;
}
Example #20
0
/* (http://phonopy.sf.net/) */
static void test_tetrahedron_method(void)
{
  printf("*** Example of tetrahedron method of NaCl to calculate DOS ***:\n");
  printf("Read data from frequency.dat and write DOS to dos.dat.\n");

  int i, j, k, l, q, r;

  /* NaCl 20x20x20 mesh */
  double lattice[3][3] = {
    {0.000000000000000, 2.845150738087836, 2.845150738087836},
    {2.845150738087836, 0.000000000000000, 2.845150738087836},
    {2.845150738087836, 2.845150738087836, 0.000000000000000}
  };
  double position[][3] =
    {{0, 0, 0},
     {0.5, 0.5, 0.5}};
  int types[] = {1, 2};
  int num_atom = 2;
  int m = 20;
  int mesh[] = {m, m, m};
  int num_gp = mesh[0] * mesh[1] * mesh[2];
  int is_shift[] = {0, 0, 0};
  int grid_address[num_gp][3];
  int grid_mapping_table[num_gp];
  int weights[num_gp];
  int num_ir = spg_get_ir_reciprocal_mesh(grid_address,
					  grid_mapping_table,
					  mesh,
					  is_shift,
					  1,
					  lattice,
					  position,
					  types,
					  num_atom,
					  1e-5);
  int ir_gp[num_ir];
  int ir_weights[num_ir];
  int gp_ir_index[num_gp];
  int relative_grid_address[24][4][3];
  double rec_lat[3][3];
  FILE *fp;
  char * line = NULL;
  size_t len = 0;
  ssize_t read;
  double frequency[num_ir * num_atom * 3];
  double max_f, min_f;
  double t_omegas[24][4];
  int g_addr[3];
  int gp;
  int num_freqs = 201;
  double dos[num_freqs];
  double integral_dos[num_freqs];
  double omegas[num_freqs];
  double iw;
  
  for (i = 0; i < num_gp; i++) {
    weights[i] = 0;
  }

  for (i = 0; i < num_gp; i++) {
    weights[grid_mapping_table[i]]++;
  }

  j = 0;
  for (i = 0; i < num_gp; i++) {
    if (weights[i] != 0) {
      ir_gp[j] = i;
      ir_weights[j] = weights[i];
      gp_ir_index[i] = j;
      j++;
    } else {
      gp_ir_index[i] = gp_ir_index[grid_mapping_table[i]];
    }
  }

  printf("Number of irreducible k-points: %d\n", num_ir);
  
  mat_inverse_matrix_d3(rec_lat, lattice, 1e-5);
  thm_get_relative_grid_address(relative_grid_address, rec_lat);

  /* for (i = 0; i < 24; i++) { */
  /*   for (j = 0; j < 4; j++) { */
  /*     printf("[%2d %2d %2d] ", */
  /* 	     relative_grid_address[i][j][0], */
  /* 	     relative_grid_address[i][j][1], */
  /* 	     relative_grid_address[i][j][2]); */
  /*   } */
  /*   printf("\n"); */
  /* } */

  fp = fopen("frequency.dat", "r");

  for (i = 0; i < num_ir * num_atom * 3; i++) {
    read = getline(&line, &len, fp);
    if (read == -1) {
      break;
    }
    frequency[i] = strtod(line, NULL);
  }

  fclose(fp);

  max_f = frequency[0];
  min_f = frequency[0];
  for (i = 0; i < num_ir * num_atom * 3; i++) {
    if (max_f < frequency[i]) {
      max_f = frequency[i];
    }
    if (min_f > frequency[i]) {
      min_f = frequency[i];
    }
  }
  
  printf("Number of frequencies: %d\n", i);
  

#pragma omp parallel for private(j, k, l, q, r, g_addr, gp, t_omegas, iw)
  for (i = 0; i < num_freqs; i++) {
    dos[i] = 0;
    integral_dos[i] = 0;
    omegas[i] = min_f + (max_f - min_f) / (num_freqs - 1) * i;
    for (j = 0; j < num_ir;  j++) {
      for (k = 0; k < num_atom * 3; k++) {
	for (l = 0; l < 24; l++) {
	  for (q = 0; q < 4; q++) {
	    for (r = 0; r < 3; r++) {
	      g_addr[r] = grid_address[ir_gp[j]][r] +
		relative_grid_address[l][q][r];
	    }
	    gp = spg_get_grid_point_from_address(g_addr, mesh);
	    t_omegas[l][q] = frequency[gp_ir_index[gp] * num_atom * 3 + k];
	  }
	}
	iw = thm_get_integration_weight(omegas[i], t_omegas, 'J');
	dos[i] += iw * ir_weights[j];
	iw = thm_get_integration_weight(omegas[i], t_omegas, 'I');
	integral_dos[i] += iw * ir_weights[j];
      }
    }
  }

  fp = fopen("dos.dat", "w");

  for (i = 0; i < num_freqs; i++) {
    fprintf(fp, "%f %f\n", omegas[i], dos[i] / num_gp);
  }

  fprintf(fp, "\n\n");
  
  for (i = 0; i < num_freqs; i++) {
    fprintf(fp, "%f %f\n", omegas[i], integral_dos[i] / num_gp);
  }
    
  fclose(fp);
}
Example #21
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 #22
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 #23
0
/* Return NULL if failed */
static Symmetry * get_conventional_symmetry(SPGCONST double transform_mat[3][3],
					    const Centering centering,
					    const Symmetry *primitive_sym)
{
  int i, j, k, multi, size;
  double inv_tmat[3][3], shift[4][3];
  double symmetry_rot_d3[3][3], primitive_sym_rot_d3[3][3];
  Symmetry *symmetry;

  symmetry = NULL;

  size = primitive_sym->size;

  switch (centering) {
  case FACE:
    if ((symmetry = sym_alloc_symmetry(size * 4)) == NULL) {
      return NULL;
    }
    break;
  case R_CENTER:
    if ((symmetry = sym_alloc_symmetry(size * 3)) == NULL) {
      return NULL;
    }
    break;
  case BODY:
  case A_FACE:
  case B_FACE:
  case C_FACE:
    if ((symmetry = sym_alloc_symmetry(size * 2)) == NULL) {
      return NULL;
    }
    break;
  default:
    if ((symmetry = sym_alloc_symmetry(size)) == NULL) {
      return NULL;
    }
    break;
  }

  for (i = 0; i < size; i++) {
    mat_cast_matrix_3i_to_3d(primitive_sym_rot_d3, primitive_sym->rot[i]);

    /* C*S*C^-1: recover conventional cell symmetry operation */
    mat_get_similar_matrix_d3(symmetry_rot_d3,
			      primitive_sym_rot_d3,
			      transform_mat,
			      0);
    mat_cast_matrix_3d_to_3i(symmetry->rot[i], symmetry_rot_d3);

    /* translation in conventional cell: C = B^-1*P */
    mat_inverse_matrix_d3(inv_tmat, transform_mat, 0);
    mat_multiply_matrix_vector_d3(symmetry->trans[i],
				  inv_tmat,
				  primitive_sym->trans[i]);
  }

  multi = 1;

  if (centering != PRIMITIVE) {
    if (centering != FACE && centering != R_CENTER) {
      for (i = 0; i < 3; i++) {	shift[0][i] = 0.5; } /* BASE */
      if (centering == A_FACE) { shift[0][0] = 0; }
      if (centering == B_FACE) { shift[0][1] = 0; }
      if (centering == C_FACE) { shift[0][2] = 0; }
      multi = 2;
    }

    if (centering == R_CENTER) {
      shift[0][0] = 2. / 3;
      shift[0][1] = 1. / 3;
      shift[0][2] = 1. / 3;
      shift[1][0] = 1. / 3;
      shift[1][1] = 2. / 3;
      shift[1][2] = 2. / 3;
      multi = 3;
    }

    if (centering == FACE) {
      shift[0][0] = 0;
      shift[0][1] = 0.5;
      shift[0][2] = 0.5;
      shift[1][0] = 0.5;
      shift[1][1] = 0;
      shift[1][2] = 0.5;
      shift[2][0] = 0.5;
      shift[2][1] = 0.5;
      shift[2][2] = 0;
      multi = 4;
    }

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

  for (i = 0; i < multi; i++) {
    for (j = 0; j < size; j++) {
      for (k = 0; k < 3; k++) {
  	symmetry->trans[i * size + j][k] =
	  mat_Dmod1(symmetry->trans[i * size + j][k]);
      }
    }
  }

  return symmetry;
}
Example #24
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 #25
0
/* Return 0 if failed */
static int get_primitive_lattice_vectors(double prim_lattice[3][3],
					 const VecDBL * vectors,
					 SPGCONST Cell * cell,
					 const double symprec)
{
  int i, j, k, size;
  double initial_volume, volume;
  double relative_lattice[3][3], min_vectors[3][3], tmp_lattice[3][3];
  double inv_mat_dbl[3][3];
  int inv_mat_int[3][3];

  debug_print("get_primitive_lattice_vectors:\n");

  size = vectors->size;
  initial_volume = mat_Dabs(mat_get_determinant_d3(cell->lattice));

  /* check volumes of all possible lattices, find smallest volume */
  for (i = 0; i < size; i++) {
    for (j = i + 1; j < size; j++) {
      for (k = j + 1; k < size; k++) {
	mat_multiply_matrix_vector_d3(tmp_lattice[0],
				      cell->lattice,
				      vectors->vec[i]);
	mat_multiply_matrix_vector_d3(tmp_lattice[1],
				      cell->lattice,
				      vectors->vec[j]);
	mat_multiply_matrix_vector_d3(tmp_lattice[2],
				      cell->lattice,
				      vectors->vec[k]);
	volume = mat_Dabs(mat_get_determinant_d3(tmp_lattice));
	if (volume > symprec) {
	  if (mat_Nint(initial_volume / volume) == size-2) {
	    mat_copy_vector_d3(min_vectors[0], vectors->vec[i]);
	    mat_copy_vector_d3(min_vectors[1], vectors->vec[j]);
	    mat_copy_vector_d3(min_vectors[2], vectors->vec[k]);
	    goto ret;
	  }
	}
      }
    }
  }

  /* Not found */
  warning_print("spglib: Primitive lattice vectors cound not be found ");
  warning_print("(line %d, %s).\n", __LINE__, __FILE__);
  return 0;

  /* Found */
 ret:
  for (i = 0; i < 3; i++) {
    for (j = 0; j < 3; j++) {
      relative_lattice[j][i] = min_vectors[i][j];
    }
  }

  mat_inverse_matrix_d3(inv_mat_dbl, relative_lattice, 0);
  mat_cast_matrix_3d_to_3i(inv_mat_int, inv_mat_dbl);
  if (abs(mat_get_determinant_i3(inv_mat_int)) == size-2) {
    mat_cast_matrix_3i_to_3d(inv_mat_dbl, inv_mat_int);
    mat_inverse_matrix_d3(relative_lattice, inv_mat_dbl, 0);
  } else {
    warning_print("spglib: Primitive lattice cleaning is incomplete ");
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);
  }
  mat_multiply_matrix_d3(prim_lattice, cell->lattice, relative_lattice);

  return 1;  
}
Example #26
0
/* Return 0 if failed */
static int match_hall_symbol_db(double origin_shift[3],
				double lattice[3][3],
				const int hall_number,
				const int pointgroup_number,
				const Holohedry holohedry,
				const Centering centering,
				SPGCONST Symmetry *symmetry,
				const double symprec)
{
  int is_found, num_hall_types;
  SpacegroupType spacegroup_type;
  Symmetry * changed_symmetry;
  double changed_lattice[3][3], inv_lattice[3][3], transform_mat[3][3];

  changed_symmetry = NULL;

  spacegroup_type = spgdb_get_spacegroup_type(hall_number);
  num_hall_types = (spacegroup_to_hall_number[spacegroup_type.number] -
		    spacegroup_to_hall_number[spacegroup_type.number - 1]);

  if (pointgroup_number != spacegroup_type.pointgroup_number) {
    goto err;
  }

  switch (holohedry) {
  case MONOCLI:
    if (match_hall_symbol_db_monocli(origin_shift,
				     lattice,
				     hall_number,
				     num_hall_types,
				     centering,
				     symmetry,
				     symprec)) {return 1;}
    break;

  case ORTHO:
    if (spacegroup_type.number == 48 ||
	spacegroup_type.number == 50 ||
	spacegroup_type.number == 59 ||
	spacegroup_type.number == 68 ||
	spacegroup_type.number == 70) { /* uncount origin shift */
      num_hall_types /= 2;
    }

    if (num_hall_types == 1) {
      if (match_hall_symbol_db_ortho(origin_shift,
				     lattice,
				     hall_number,
				     centering,
				     symmetry,
				     6,
				     symprec)) {return 1;}
      break;
    }

    if (num_hall_types == 2) {
      if (match_hall_symbol_db_ortho(origin_shift,
				     lattice,
				     hall_number,
				     centering,
				     symmetry,
				     3,
				     symprec)) {return 1;}
      break;
    }

    if (num_hall_types == 3) {
      mat_copy_matrix_d3(changed_lattice, lattice);
      if (! match_hall_symbol_db_ortho
	  (origin_shift,
	   changed_lattice,
	   spacegroup_to_hall_number[spacegroup_type.number - 1],
	   centering,
	   symmetry,
	   0,
	   symprec)) {break;}
      mat_inverse_matrix_d3(inv_lattice, lattice, 0);
      mat_multiply_matrix_d3(transform_mat, inv_lattice, changed_lattice);

      if ((changed_symmetry = get_conventional_symmetry(transform_mat,
							PRIMITIVE,
							symmetry)) == NULL) {
	goto err;
      }

      is_found = match_hall_symbol_db_ortho(origin_shift,
					    changed_lattice,
					    hall_number,
					    centering,
					    changed_symmetry,
					    2,
					    symprec);
      sym_free_symmetry(changed_symmetry);
      changed_symmetry = NULL;
      if (is_found) {
	mat_copy_matrix_d3(lattice, changed_lattice);
	return 1;
      }
      break;
    }

    if (num_hall_types == 6) {
      if (match_hall_symbol_db_ortho(origin_shift,
				     lattice,
				     hall_number,
				     centering,
				     symmetry,
				     1,
				     symprec)) {return 1;}
      break;
    }

    break;

  case CUBIC:
    if (hal_match_hall_symbol_db(origin_shift,
				 lattice,
				 hall_number,
				 centering,
				 symmetry,
				 symprec)) {return 1;}

    if (hall_number == 501) { /* Try another basis for No.205 */
      mat_multiply_matrix_d3(changed_lattice,
			     lattice,
			     change_of_basis_501);
      if ((changed_symmetry = get_conventional_symmetry(change_of_basis_501,
							PRIMITIVE,
							symmetry)) == NULL) {
	goto err;
      }

      is_found = hal_match_hall_symbol_db(origin_shift,
					  changed_lattice,
					  hall_number,
					  PRIMITIVE,
					  changed_symmetry,
					  symprec);
      sym_free_symmetry(changed_symmetry);
      changed_symmetry = NULL;
      if (is_found) {
	mat_copy_matrix_d3(lattice, changed_lattice);
	return 1;
      }
    }
    break;

  case TRIGO:
    if (centering == R_CENTER) {
      if (hall_number == 433 ||
	  hall_number == 436 ||
	  hall_number == 444 ||
	  hall_number == 450 ||
	  hall_number == 452 ||
	  hall_number == 458 ||
	  hall_number == 460) {
	mat_multiply_matrix_d3(changed_lattice,
			       lattice,
			       hR_to_hP);
	if ((changed_symmetry = get_conventional_symmetry(hR_to_hP,
							  R_CENTER,
							  symmetry)) == NULL) {
	  goto err;
	}

	is_found = hal_match_hall_symbol_db(origin_shift,
					    changed_lattice,
					    hall_number,
					    centering,
					    changed_symmetry,
					    symprec);
	sym_free_symmetry(changed_symmetry);
	changed_symmetry = NULL;
	if (is_found) {
	  mat_copy_matrix_d3(lattice, changed_lattice);
	  return 1;
	}
      }
    }
    /* Do not break for other trigonal cases */
  default: /* HEXA, TETRA, TRICLI and rest of TRIGO */
    if (hal_match_hall_symbol_db(origin_shift,
				 lattice,
				 hall_number,
				 centering,
				 symmetry,
				 symprec)) {
      return 1;
    }
    break;
  }

 err:
  return 0;
}
Example #27
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;
}