예제 #1
0
/* If primitive could not be found, primitive->size = 0 is returned. */
static Cell * get_primitive(int * mapping_table,
			    SPGCONST Cell * cell,
			    const VecDBL * pure_trans,
			    const double symprec)
{
  int multi;
  double prim_lattice[3][3];
  Cell * primitive_cell;

  debug_print("get_primitive:\n");

  /* Primitive lattice vectors are searched. */
  /* To be consistent, sometimes tolerance is decreased iteratively. */
  /* The descreased tolerance is stored in 'static double tolerance'. */
  multi = get_primitive_lattice_vectors_iterative(prim_lattice,
						  cell,
						  pure_trans,
						  symprec);
  if (! multi) {
    goto not_found;
  }

  primitive_cell = cel_alloc_cell(cell->size / multi);

  if (! lat_smallest_lattice_vector(primitive_cell->lattice,
				    prim_lattice,
				    symprec)) {
    cel_free_cell(primitive_cell);
    goto not_found;
  }

  /* Fit atoms into new primitive cell */
  if (! trim_cell(primitive_cell, mapping_table, cell, symprec)) {
    cel_free_cell(primitive_cell);
    goto not_found;
  }

  /* found */
  return primitive_cell;

 not_found:
  primitive_cell = cel_alloc_cell(0);
  warning_print("spglib: Primitive cell could not be found ");
  warning_print("(line %d, %s).\n", __LINE__, __FILE__);
  return primitive_cell;
}
예제 #2
0
파일: niggli.c 프로젝트: atztogo/phonopy
static NiggliParams * initialize(const double *lattice_, const double eps_)
{
  NiggliParams * p;

  p = NULL;

  if ((p = (NiggliParams*)malloc(sizeof(NiggliParams))) == NULL) {
    warning_print("niggli: Memory could not be allocated.");
    return NULL;
  }

  p->A = 0;
  p->B = 0;
  p->C = 0;
  p->eta = 0;
  p->xi = 0;
  p->zeta = 0;
  p->eps = 0;
  p->l = 0;
  p->m = 0;
  p->n = 0;
  p->tmat = NULL;
  p->lattice = NULL;

  if ((p->tmat = (double*)malloc(sizeof(double) * 9)) == NULL) {
    warning_print("niggli: Memory could not be allocated.");
    free(p);
    p = NULL;
    return NULL;
  }

  p->eps = eps_;
  if ((p->lattice = (double*)malloc(sizeof(double) * 9)) == NULL) {
    warning_print("niggli: Memory could not be allocated.");
    free(p->tmat);
    p->tmat = NULL;
    free(p);
    p = NULL;
    return NULL;
  }

  memcpy(p->lattice, lattice_, sizeof(double) * 9);

  return p;
}
예제 #3
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;
}
예제 #4
0
/* NULL is returned if failed */
Primitive * spa_get_spacegroup(Spacegroup * spacegroup,
			       SPGCONST Cell * cell,
			       const double symprec)
{
  int attempt;
  double tolerance;
  Primitive *primitive;

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

  primitive = NULL;

  tolerance = symprec;

  for (attempt = 0; attempt < 100; attempt++) {
    if ((primitive = prm_get_primitive(cell, tolerance)) == NULL) {
      goto cont;
    }

    *spacegroup = search_spacegroup(primitive->cell,
				    spacegroup_to_hall_number,
				    230,
				    primitive->tolerance);
    if (spacegroup->number > 0) {
      break;
    } else {
      prm_free_primitive(primitive);
      primitive = NULL;
    }

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

    tolerance *= REDUCE_RATE;
  }

  if (primitive == NULL) {
    warning_print("spglib: Space group could not be found ");
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);
  }

  return primitive;
}
예제 #5
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;
}
예제 #6
0
VecDBL * sym_get_pure_translation(SPGCONST Cell *cell,
				  const double symprec)
{
  int multi;
  VecDBL * pure_trans;

  pure_trans = get_translation(identity, cell, symprec, 1);
  multi = pure_trans->size;
  if ((cell->size / multi) * multi == cell->size) {
    debug_print("sym_get_pure_translation: pure_trans->size = %d\n", multi);
  } else {
    ;
    warning_print("spglib: Finding pure translation failed (line %d, %s).\n", __LINE__, __FILE__);
    warning_print("        cell->size %d, multi %d\n", cell->size, multi);
  }

  return pure_trans;
}
예제 #7
0
/* primitive cell with smallest lattice is returned. */
static Cell * get_primitive_and_mapping_table(int * mapping_table,
					      SPGCONST Cell * cell,
					      const double symprec)
{
  int i, attempt;
  double tolerance;
  Cell *primitive_cell;
  VecDBL *pure_trans;

  tolerance = symprec;
  for (attempt = 0; attempt < 100; attempt++) {
    pure_trans = sym_get_pure_translation(cell, tolerance);
    if (pure_trans->size == 1) {
      primitive_cell = get_cell_with_smallest_lattice(cell, symprec);
      for (i = 0; i < cell->size; i++) {
	mapping_table[i] = i;
      }
      goto ret;
    }
    if (pure_trans->size > 1) {
      primitive_cell = get_primitive(mapping_table, cell, pure_trans, tolerance);
      if (primitive_cell->size > 0) {
	goto ret;
      }
      cel_free_cell(primitive_cell);
    }

    tolerance *= REDUCE_RATE;
    warning_print("spglib: Tolerance is reduced to %f at attempt %d\n", tolerance, attempt);
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);
    mat_free_VecDBL(pure_trans);
  }

  /* not found: I hope this will not happen. */
  warning_print("spglib: Primitive cell could not be found ");
  warning_print("(line %d, %s).\n", __LINE__, __FILE__);
  return cel_alloc_cell(0);

 ret:
  mat_free_VecDBL(pure_trans);
  set_current_tolerance(tolerance);
  return primitive_cell;
}
예제 #8
0
/* Reference can be found in International table A. */
static int get_Delaunay_reduction( double red_lattice[3][3], 
				   SPGCONST double lattice[3][3],
				   const double symprec )
{
  int i, j;
  double volume;
  double basis[4][3];

  get_exteneded_basis(basis, lattice);

  while (1) {
    if (get_Delaunay_reduction_basis(basis, symprec)) {
      break;
    }
  }

  get_Delaunay_shortest_vectors( basis, symprec );

  for ( i = 0; i < 3; i++ ) {
    for ( j = 0; j < 3; j++ ) {
      red_lattice[i][j] = basis[j][i];
    }
  }

  volume = mat_get_determinant_d3( red_lattice );
  if ( mat_Dabs( volume ) < symprec ) {
    warning_print("spglib: Minimum lattice has no volume (line %d, %s).\n", __LINE__, __FILE__);
    goto err;
  }

  if ( volume  < 0 ) {
    /* Flip axes */
    for (i = 0; i < 3; i++) {
      for ( j = 0; j < 3; j++ ) {
	red_lattice[i][j] = -red_lattice[i][j];
      }
    }
  }


#ifdef DEBUG
  debug_print("Delaunay reduction:\n");
  debug_print_matrix_d3(red_lattice);
  double metric[3][3];
  mat_get_metric( metric, red_lattice );
  debug_print("It's metric tensor.\n");
  debug_print_matrix_d3( metric );
#endif

  return 1;

 err:
  return 0;
}
예제 #9
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;
}
예제 #10
0
Spacegroup spa_get_spacegroup(SPGCONST Cell * cell,
                              const double symprec)
{
    double tolerance;
    Cell *primitive;
    Spacegroup spacegroup;

    primitive = prm_get_primitive(cell, symprec);
    tolerance = prm_get_current_tolerance();

    if (primitive->size > 0) {
        spacegroup = get_spacegroup(primitive, tolerance);
    } else {
        spacegroup.number = 0;
        warning_print("spglib: Space group could not be found ");
        warning_print("(line %d, %s).\n", __LINE__, __FILE__);
    }
    cel_free_cell(primitive);

    return spacegroup;
}
예제 #11
0
static Centering get_base_center( SPGCONST int transform_mat[3][3] )
{
  int i;
  Centering centering = NO_CENTER;

  debug_print("lat_get_base_center\n");

  /* C center */
  for (i = 0; i < 3; i++) {
    if ( transform_mat[i][0] == 0 &&
	 transform_mat[i][1] == 0 &&
	 abs( transform_mat[i][2] ) == 1 ) {
      centering = C_FACE;
      goto end;
    }
  }

  /* A center */
  for (i = 0; i < 3; i++) {
    if ( abs( transform_mat[i][0] ) == 1 && 
	 transform_mat[i][1] == 0 &&
	 transform_mat[i][2] == 0 ) {
      centering = A_FACE;
      goto end;
    }
  }

  /* B center */
  for (i = 0; i < 3; i++) {
    if ( transform_mat[i][0] == 0 &&
	 abs( transform_mat[i][1] ) == 1 && 
	 transform_mat[i][2] == 0 ) {
      centering = B_FACE;
      goto end;
    }
  }

  /* body center */
  if ( abs( transform_mat[0][0] ) +
       abs( transform_mat[0][1] ) + 
       abs( transform_mat[0][2] ) == 2 ) {
    centering = BODY;
    goto end;
  }

  /* This should not happen. */
  warning_print("spglib: No centring was found (line %d, %s).\n", __LINE__, __FILE__);
  return NO_CENTER;

 end:
  debug_print("centering: %d\n", centering);
  return centering;
}
예제 #12
0
/* Return 0 if failed */
static int get_exact_positions(VecDBL *positions,
                               int * equiv_atoms,
                               const Cell * conv_prim,
                               const Symmetry * conv_sym,
                               const double symprec)
{
  int i, num_indep_atoms, sum_num_atoms_in_orbits, num_atoms_in_orbits;
  int *indep_atoms;

  debug_print("get_exact_positions\n");

  indep_atoms = NULL;

  if ((indep_atoms = (int*) malloc(sizeof(int) * conv_prim->size)) == NULL) {
    warning_print("spglib: Memory could not be allocated ");
    return 0;
  }

  num_indep_atoms = 0;
  sum_num_atoms_in_orbits = 0;
  for (i = 0; i < conv_prim->size; i++) {
    /* Check if atom_i overlap to an atom already set at the exact position. */
    if (! set_equivalent_atom(positions,
                              equiv_atoms,
                              i,
                              num_indep_atoms,
                              indep_atoms,
                              conv_prim,
                              conv_sym,
                              symprec)) {
      /* No equivalent atom was found. */
      indep_atoms[num_indep_atoms] = i;
      num_indep_atoms++;
      mat_copy_vector_d3(positions->vec[i], conv_prim->position[i]);
      num_atoms_in_orbits = set_exact_location(positions->vec[i],
                                               conv_sym,
                                               conv_prim->lattice,
                                               symprec);
      if (num_atoms_in_orbits) {
        sum_num_atoms_in_orbits += num_atoms_in_orbits;
        equiv_atoms[i] = i;
      } else {
        sum_num_atoms_in_orbits = 0;
        break;
      }
    }
  }

  free(indep_atoms);
  indep_atoms = NULL;

  return sum_num_atoms_in_orbits;
}
예제 #13
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;
}
예제 #14
0
/* Return NULL if failed */
Symmetry * sym_alloc_symmetry(const int size)
{
  Symmetry *symmetry;

  symmetry = NULL;

  if (size < 1) {
    return NULL;
  }

  if ((symmetry = (Symmetry*) malloc(sizeof(Symmetry))) == NULL) {
    warning_print("spglib: Memory could not be allocated ");
    return NULL;
  }

  symmetry->size = size;
  symmetry->rot = NULL;
  symmetry->trans = NULL;

  if ((symmetry->rot =
       (int (*)[3][3]) malloc(sizeof(int[3][3]) * size)) == NULL) {
    warning_print("spglib: Memory could not be allocated ");
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);
    free(symmetry);
    symmetry = NULL;
    return NULL;
  }
  if ((symmetry->trans =
       (double (*)[3]) malloc(sizeof(double[3]) * size)) == NULL) {
    warning_print("spglib: Memory could not be allocated ");
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);
    free(symmetry->rot);
    symmetry->rot = NULL;
    free(symmetry);
    symmetry = NULL;
    return NULL;
  }

  return symmetry;
}
예제 #15
0
파일: cell.c 프로젝트: hautierg/pymatgen
/* NULL is returned if faied */
Cell * cel_alloc_cell(const int size)
{
  Cell *cell;
  int i, j;
  
  cell = NULL;

  if ((cell = (Cell*) malloc(sizeof(Cell))) == NULL) {
    warning_print("spglib: Memory could not be allocated.");
    return NULL;
  }

  for ( i = 0; i < 3; i++ ) {
    for ( j = 0; j < 3; j++ ) {
      cell->lattice[i][j] = 0;
    }
  }
  cell->size = size;
  
  if (size > 0) {
    if ((cell->types = (int *) malloc(sizeof(int) * size)) == NULL) {
      warning_print("spglib: Memory could not be allocated.");
      free(cell);
      cell = NULL;
      return NULL;
    }
    if ((cell->position =
	 (double (*)[3]) malloc(sizeof(double[3]) * size)) == NULL) {
      warning_print("spglib: Memory could not be allocated.");
      free(cell->types);
      cell->types = NULL;
      free(cell);
      cell = NULL;
      return NULL;
    }
  }

  return cell;
}
예제 #16
0
파일: lattice.c 프로젝트: hautierg/pymatgen
/* Return 0 if failed */
static int get_Delaunay_reduction(double red_lattice[3][3], 
				  SPGCONST double lattice[3][3],
				  const double symprec)
{
  int i, j;
  double volume, sum;
  double basis[4][3];

  get_exteneded_basis(basis, lattice);
  
  sum = 0;
  for (i = 0; i < 4; i++) {
    for (j = 0; j < 3; j++) {
      sum += basis[i][j] * basis[i][j];
    }
  }

  while (1) {
    if (get_Delaunay_reduction_basis(basis, symprec)) {
      break;
    }
  }

  get_Delaunay_shortest_vectors(basis, symprec);

  for (i = 0; i < 3; i++) {
    for (j = 0; j < 3; j++) {
      red_lattice[i][j] = basis[j][i];
    }
  }

  volume = mat_get_determinant_d3(red_lattice);
  if (mat_Dabs(volume) < symprec) {
    warning_print("spglib: Minimum lattice has no volume (line %d, %s).\n", __LINE__, __FILE__);
    goto err;
  }

  if (volume  < 0) {
    /* Flip axes */
    for (i = 0; i < 3; i++) {
      for (j = 0; j < 3; j++) {
	red_lattice[i][j] = -red_lattice[i][j];
      }
    }
  }

  return 1;

 err:
  return 0;
}
예제 #17
0
static int get_pointgroup_class_table(int table[10],
				      SPGCONST PointSymmetry * pointsym)
{
  /* Look-up table */
  /* Operation   -6 -4 -3 -2 -1  1  2  3  4  6 */
  /* Trace     -  2 -1  0  1 -3  3 -1  0  1  2 */
  /* Determinant -1 -1 -1 -1 -1  1  1  1  1  1 */

  /* table[0] = -6 axis */
  /* table[1] = -4 axis */
  /* table[2] = -3 axis */
  /* table[3] = -2 axis */
  /* table[4] = -1 axis */
  /* table[5] =  1 axis */
  /* table[6] =  2 axis */
  /* table[7] =  3 axis */
  /* table[8] =  4 axis */
  /* table[9] =  6 axis */

  int i, rot_type;

  for (i = 0; i < 10; i++) { table[i] = 0; }
  for (i = 0; i < pointsym->size; i++) {
    rot_type = get_rotation_type(pointsym->rot[i]);
    if (rot_type == -1) {
      goto err;
    } else {
      table[rot_type]++;
    }
  }
  
  return 1;

 err:
  warning_print("spglib: No point group symbol found ");
  warning_print("(line %d, %s).\n", __LINE__, __FILE__);
  return 0;
}
예제 #18
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;
}
예제 #19
0
파일: spin.c 프로젝트: vanceeasleaf/phonopy
/* Return NULL if failed */
static int * get_mapping_table(SPGCONST Symmetry *symmetry,
			       SPGCONST Cell * cell,
			       const double symprec)
{
  int i, j, k, is_found;
  double pos[3];
  int *mapping_table;
  SPGCONST int I[3][3] = {{ 1, 0, 0},
			  { 0, 1, 0},
			  { 0, 0, 1}};

  mapping_table = NULL;

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

  for (i = 0; i < cell->size; i++) {
    is_found = 0;
    for (j = 0; j < symmetry->size; j++) {
      if (mat_check_identity_matrix_i3(symmetry->rot[j], I)) {
	for (k = 0; k < 3; k++) {
	  pos[k] = cell->position[i][k] + symmetry->trans[j][k];
	}
	for (k = 0; k < cell->size; k++) {
	  if (cel_is_overlap(pos, cell->position[k], cell->lattice, symprec)) {
	    if (k < i) {
	      mapping_table[i] = mapping_table[k];
	      is_found = 1;
	      break;
	    }
	  }
	}
      }
      if (is_found) {
	break;
      }
    }
    if (!is_found) {
      mapping_table[i] = i;
    }
  }

  return mapping_table;
}
예제 #20
0
파일: niggli.c 프로젝트: atztogo/phonopy
static double * get_transpose(const double *M)
{
  int i, j;
  double *M_T;

  M_T = NULL;

  if ((M_T = (double*)malloc(sizeof(double) * 9)) == NULL) {
    warning_print("niggli: Memory could not be allocated.");
    return NULL;
  }

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

  return M_T;
}
예제 #21
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;
}
예제 #22
0
static int get_index_with_least_atoms(const Cell *cell)
{
  int i, j, min, min_index;
  int *mapping;

  mapping = NULL;

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

  for (i = 0; i < cell->size; i++) {
    mapping[i] = 0;
  }

  for (i = 0; i < cell->size; i++) {
    for (j = 0; j < cell->size; j++) {
      if (cell->types[i] == cell->types[j]) {
	mapping[j]++;
	break;
      }
    }
  }

  min = mapping[0];
  min_index = 0;
  for (i = 0; i < cell->size; i++) {
    if (min > mapping[i] && mapping[i] >0) {
      min = mapping[i];
      min_index = i;
    }
  }

  free(mapping);
  mapping = NULL;

  return min_index;
}
예제 #23
0
파일: niggli.c 프로젝트: atztogo/phonopy
static double * multiply_matrices(const double *L, const double *R)
{
  int i, j, k;
  double *M;

  M = NULL;

  if ((M = (double*)malloc(sizeof(double) * 9)) == NULL) {
    warning_print("niggli: Memory could not be allocated.");
    return NULL;
  }

  for (i = 0; i < 3; i++) {
    for (j = 0; j < 3; j++) {
      M[i * 3 + j] = 0;
      for (k = 0; k < 3; k++) {
        M[i * 3 + j] += L[i * 3 + k] * R[k * 3 + j];
      }
    }
  }

  return M;
}
예제 #24
0
static int laue_one_axis(int axes[3],
			 SPGCONST PointSymmetry * pointsym,
			 const int rot_order)
{
  int i, j, num_ortho_axis, det, is_found, tmpval;
  int axis_vec[3], tmp_axes[3];
  int prop_rot[3][3], t_mat[3][3];
  int ortho_axes[NUM_ROT_AXES];

  debug_print("laue_one_axis with rot_order %d\n", rot_order);
  
  for (i = 0; i < pointsym->size; i++) {
    get_proper_rotation(prop_rot, pointsym->rot[i]);

    /* Search foud-fold rotation */
    if (rot_order == 4) {
      if (mat_get_trace_i3(prop_rot) == 1) {
	/* The first axis */
	axes[2] = get_rotation_axis(prop_rot);
	break;
      }
    }

    /* Search three-fold rotation */
    if (rot_order == 3) {
      if (mat_get_trace_i3(prop_rot) == 0) {
	/* The first axis */
	axes[2] = get_rotation_axis(prop_rot);
	break;
      }
    }
  }

  /* Candidates of the second axis */
  num_ortho_axis = get_orthogonal_axis(ortho_axes, prop_rot, rot_order);
  if (! num_ortho_axis) { goto err; }

  tmp_axes[1] = -1;
  tmp_axes[2] = axes[2];
  for (i = 0; i < num_ortho_axis; i++) {
    is_found = 0;
    tmp_axes[0] = ortho_axes[i];
    mat_multiply_matrix_vector_i3(axis_vec,
				  prop_rot,
				  rot_axes[tmp_axes[0]]);
    for (j = 0; j < num_ortho_axis; j++) {
      is_found = is_exist_axis(axis_vec, ortho_axes[j]);
      if (is_found == 1) {
	tmp_axes[1] = ortho_axes[j];
	break;
      }
      if (is_found == -1) {
	tmp_axes[1] = ortho_axes[j] + NUM_ROT_AXES;
	break;
      }
    }

    if (!is_found) { continue; }
    
    set_transformation_matrix(t_mat, tmp_axes);
    det = abs(mat_get_determinant_i3(t_mat));
    if (det < 4) { /* to avoid F-center choice det=4 */
      axes[0] = tmp_axes[0];
      axes[1] = tmp_axes[1];
      goto end;
    }
  }

 err: /* axes are not correctly found. */
  warning_print("spglib: Secondary axis is not found.");
  warning_print("(line %d, %s).\n", __LINE__, __FILE__);
  return 0;

 end:
  set_transformation_matrix(t_mat, axes);
  if (mat_get_determinant_i3(t_mat) < 0) {
    tmpval = axes[0];
    axes[0] = axes[1];
    axes[1] = tmpval;
  }

  debug_print("axes[0] = %d\n", axes[0]);
  debug_print("axes[1] = %d\n", axes[1]);
  debug_print("axes[2] = %d\n", axes[2]);

  return 1;

}
예제 #25
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;
}
예제 #26
0
/* Return NULL if failed */
static MatINT *get_point_group_reciprocal_with_q(const MatINT * rot_reciprocal,
						 const double symprec,
						 const int num_q,
						 SPGCONST double qpoints[][3])
{
  int i, j, k, l, is_all_ok, num_rot;
  int *ir_rot;
  double q_rot[3], diff[3];
  MatINT * rot_reciprocal_q;

  ir_rot = NULL;
  rot_reciprocal_q = NULL;
  is_all_ok = 0;
  num_rot = 0;

  if ((ir_rot = (int*)malloc(sizeof(int) * rot_reciprocal->size)) == NULL) {
    warning_print("spglib: Memory of ir_rot could not be allocated.");
    return NULL;
  }

  for (i = 0; i < rot_reciprocal->size; i++) {
    ir_rot[i] = -1;
  }
  for (i = 0; i < rot_reciprocal->size; i++) {
    for (j = 0; j < num_q; j++) {
      is_all_ok = 0;
      mat_multiply_matrix_vector_id3(q_rot,
				     rot_reciprocal->mat[i],
				     qpoints[j]);

      for (k = 0; k < num_q; k++) {
	for (l = 0; l < 3; l++) {
	  diff[l] = q_rot[l] - qpoints[k][l];
	  diff[l] -= mat_Nint(diff[l]);
	}
	
	if (mat_Dabs(diff[0]) < symprec && 
	    mat_Dabs(diff[1]) < symprec &&
	    mat_Dabs(diff[2]) < symprec) {
	  is_all_ok = 1;
	  break;
	}
      }
      
      if (! is_all_ok) {
	break;
      }
    }

    if (is_all_ok) {
      ir_rot[num_rot] = i;
      num_rot++;
    }
  }

  if ((rot_reciprocal_q = mat_alloc_MatINT(num_rot)) != NULL) {
    for (i = 0; i < num_rot; i++) {
      mat_copy_matrix_i3(rot_reciprocal_q->mat[i],
			 rot_reciprocal->mat[ir_rot[i]]);  
    }
  }

  free(ir_rot);
  ir_rot = NULL;

  return rot_reciprocal_q;
}
예제 #27
0
/* Return NULL if failed */
static MatINT *get_point_group_reciprocal(const MatINT * rotations,
					  const int is_time_reversal)
{
  int i, j, num_rot;
  MatINT *rot_reciprocal, *rot_return;
  int *unique_rot;
  SPGCONST int inversion[3][3] = {
    {-1, 0, 0 },
    { 0,-1, 0 },
    { 0, 0,-1 }
  };

  rot_reciprocal = NULL;
  rot_return = NULL;
  unique_rot = NULL;
  
  if (is_time_reversal) {
    if ((rot_reciprocal = mat_alloc_MatINT(rotations->size * 2)) == NULL) {
      return NULL;
    }
  } else {
    if ((rot_reciprocal = mat_alloc_MatINT(rotations->size)) == NULL) {
      return NULL;
    }
  }

  if ((unique_rot = (int*)malloc(sizeof(int) * rot_reciprocal->size)) == NULL) {
    warning_print("spglib: Memory of unique_rot could not be allocated.");
    mat_free_MatINT(rot_reciprocal);
    return NULL;
  }

  for (i = 0; i < rot_reciprocal->size; i++) {
    unique_rot[i] = -1;
  }

  for (i = 0; i < rotations->size; i++) {
    mat_transpose_matrix_i3(rot_reciprocal->mat[i], rotations->mat[i]);
    
    if (is_time_reversal) {
      mat_multiply_matrix_i3(rot_reciprocal->mat[rotations->size+i],
			     inversion,
			     rot_reciprocal->mat[i]);
    }
  }

  num_rot = 0;
  for (i = 0; i < rot_reciprocal->size; i++) {
    for (j = 0; j < num_rot; j++) {
      if (mat_check_identity_matrix_i3(rot_reciprocal->mat[unique_rot[j]],
				       rot_reciprocal->mat[i])) {
	goto escape;
      }
    }
    unique_rot[num_rot] = i;
    num_rot++;
  escape:
    ;
  }

  if ((rot_return = mat_alloc_MatINT(num_rot)) != NULL) {
    for (i = 0; i < num_rot; i++) {
      mat_copy_matrix_i3(rot_return->mat[i], rot_reciprocal->mat[unique_rot[i]]);
    }
  }

  free(unique_rot);
  unique_rot = NULL;
  mat_free_MatINT(rot_reciprocal);
  rot_reciprocal = NULL;

  return rot_return;
}
예제 #28
0
static PointSymmetry get_lattice_symmetry(SPGCONST double cell_lattice[3][3],
					  const double symprec,
					  const double angle_symprec)
{
  int i, j, k, attempt, num_sym;
  double angle_tol;
  int axes[3][3];
  double lattice[3][3], min_lattice[3][3];
  double metric[3][3], metric_orig[3][3];
  PointSymmetry lattice_sym;

  debug_print("get_lattice_symmetry:\n");

  lattice_sym.size = 0;

  if (! del_delaunay_reduce(min_lattice, cell_lattice, symprec)) {
    goto err;
  }

  mat_get_metric(metric_orig, min_lattice);
  angle_tol = angle_symprec;

  for (attempt = 0; attempt < 100; attempt++) {
    num_sym = 0;
    for (i = 0; i < 26; i++) {
      for (j = 0; j < 26; j++) {
	for (k = 0; k < 26; k++) {
	  set_axes(axes, i, j, k);
	  if (! ((mat_get_determinant_i3(axes) == 1) ||
		 (mat_get_determinant_i3(axes) == -1))) {
	    continue;
	  }
	  mat_multiply_matrix_di3(lattice, min_lattice, axes);
	  mat_get_metric(metric, lattice);

	  if (is_identity_metric(metric, metric_orig, symprec, angle_tol)) {
	    if (num_sym > 47) {
	      angle_tol *= ANGLE_REDUCE_RATE;
	      warning_print("spglib: Too many lattice symmetries was found.\n");
	      warning_print("        Reduce angle tolerance to %f", angle_tol);
	      warning_print(" (line %d, %s).\n", __LINE__, __FILE__);
	      goto next_attempt;
	    }

	    mat_copy_matrix_i3(lattice_sym.rot[num_sym], axes);
	    num_sym++;
	  }
	}
      }
    }

    if (num_sym < 49 || angle_tol < 0) {
      lattice_sym.size = num_sym;
      return transform_pointsymmetry(&lattice_sym, cell_lattice, min_lattice);
    }

  next_attempt:
    ;
  }

 err:
  debug_print("get_lattice_symmetry failed.\n");
  return lattice_sym;
}
예제 #29
0
/* Return NULL if failed */
static Symmetry *
get_space_group_operations(SPGCONST PointSymmetry *lattice_sym,
			   SPGCONST Cell *primitive,
			   const double symprec)
{
  int i, j, num_sym, total_num_sym;
  VecDBL **trans;
  Symmetry *symmetry;

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

  trans = NULL;
  symmetry = NULL;

  if ((trans = (VecDBL**) malloc(sizeof(VecDBL*) * lattice_sym->size))
      == NULL) {
    warning_print("spglib: Memory could not be allocated ");
    return NULL;
  }

  for (i = 0; i < lattice_sym->size; i++) {
    trans[i] = NULL;
  }

  total_num_sym = 0;
  for (i = 0; i < lattice_sym->size; i++) {

    if ((trans[i] = get_translation(lattice_sym->rot[i], primitive, symprec, 0))
	!= NULL) {

      debug_print("  match translation %d/%d; tolerance = %f\n",
		  i + 1, lattice_sym->size, symprec);

      total_num_sym += trans[i]->size;
    }
  }

  if ((symmetry = sym_alloc_symmetry(total_num_sym)) == NULL) {
    goto ret;
  }

  num_sym = 0;
  for (i = 0; i < lattice_sym->size; i++) {
    if (trans[i] == NULL) {
      continue;
    }
    for (j = 0; j < trans[i]->size; j++) {
      mat_copy_vector_d3(symmetry->trans[num_sym + j], trans[i]->vec[j]);
      mat_copy_matrix_i3(symmetry->rot[num_sym + j], lattice_sym->rot[i]);
    }
    num_sym += trans[i]->size;
  }

 ret:
  for (i = 0; i < lattice_sym->size; i++) {
    if (trans[i] != NULL) {
      mat_free_VecDBL(trans[i]);
      trans[i] = NULL;
    }
  }
  free(trans);
  trans = NULL;

  return symmetry;
}
예제 #30
0
/* Return NULL if failed */
static VecDBL * get_translation(SPGCONST int rot[3][3],
				SPGCONST Cell *cell,
				const double symprec,
				const int is_identity)
{
  int i, j, k, min_atom_index, num_trans;
  int *is_found;
  double origin[3];
  VecDBL *trans;

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

  num_trans = 0;
  is_found = NULL;
  trans = NULL;

#ifdef _OPENMP
  int num_min_type_atoms;
  int *min_type_atoms;
  double vec[3];

  min_type_atoms = NULL;
#endif

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

  for (i = 0; i < cell->size; i++) {
    is_found[i] = 0;
  }

  /* Look for the atom index with least number of atoms within same type */
  min_atom_index = get_index_with_least_atoms(cell);
  if (min_atom_index == -1) {
    debug_print("spglib: get_index_with_least_atoms failed.\n");
    goto ret;
  }

  /* Set min_atom_index as the origin to measure the distance between atoms. */
  mat_multiply_matrix_vector_id3(origin, rot, cell->position[min_atom_index]);

#ifdef _OPENMP
  if (cell->size < NUM_ATOMS_CRITERION_FOR_OPENMP) {
    num_trans = search_translation_part(is_found,
					cell,
					rot,
					min_atom_index,
					origin,
					symprec,
					is_identity);
    if (num_trans == 0) {
      goto ret;
    }
  } else {
    /* Collect indices of atoms with the type where the minimum number */
    /* of atoms belong. */
    if ((min_type_atoms = (int*) malloc(sizeof(int)*cell->size)) == NULL) {
      warning_print("spglib: Memory could not be allocated ");
      goto ret;
    }

    num_min_type_atoms = 0;
    for (i = 0; i < cell->size; i++) {
      if (cell->types[i] == cell->types[min_atom_index]) {
	min_type_atoms[num_min_type_atoms] = i;
	num_min_type_atoms++;
      }
    }
#pragma omp parallel for private(j, vec)
    for (i = 0; i < num_min_type_atoms; i++) {
      for (j = 0; j < 3; j++) {
	vec[j] = cell->position[min_type_atoms[i]][j] - origin[j];
      }
      if (is_overlap_all_atoms(vec,
			       rot,
			       cell,
			       symprec,
			       is_identity)) {
	is_found[min_type_atoms[i]] = 1;
      }
    }

    free(min_type_atoms);
    min_type_atoms = NULL;

    for (i = 0; i < cell->size; i++) {
      num_trans += is_found[i];
    }
  }
#else
  num_trans = search_translation_part(is_found,
				      cell,
				      rot,
				      min_atom_index,
				      origin,
				      symprec,
				      is_identity);
  if (num_trans == 0) {
    goto ret;
  }
#endif

  if ((trans = mat_alloc_VecDBL(num_trans)) == NULL) {
    goto ret;
  }

  k = 0;
  for (i = 0; i < cell->size; i++) {
    if (is_found[i]) {
      for (j = 0; j < 3; j++) {
	trans->vec[k][j] = cell->position[i][j] - origin[j];
      }
      k++;
    }
  }

 ret:
  free(is_found);
  is_found = NULL;

  return trans;
}