Beispiel #1
0
static void set_positions(Cell * trimmed_cell,
                          const VecDBL * position,
                          const int * mapping_table,
                          const int * overlap_table)
{
  int i, j, k, l, multi;

  for (i = 0; i < trimmed_cell->size; i++) {
    for (j = 0; j < 3; j++) {
      trimmed_cell->position[i][j] = 0;
    }
  }

  /* Positions of overlapped atoms are averaged. */
  for (i = 0; i < position->size; i++) {
    j = mapping_table[i];
    k = overlap_table[i];
    for (l = 0; l < 3; l++) {
      /* boundary treatment */
      /* One is at right and one is at left or vice versa. */
      if (mat_Dabs(position->vec[k][l] - position->vec[i][l]) > 0.5) {
        if (position->vec[i][l] < position->vec[k][l]) {
          trimmed_cell->position[j][l] += position->vec[i][l] + 1;
        } else {
          trimmed_cell->position[j][l] += position->vec[i][l] - 1;
        }
      } else {
        trimmed_cell->position[j][l] += position->vec[i][l];
      }
    }

  }

  multi = position->size / trimmed_cell->size;
  for (i = 0; i < trimmed_cell->size; i++) {
    for (j = 0; j < 3; j++) {
      trimmed_cell->position[i][j] /= multi;
      trimmed_cell->position[i][j] = mat_Dmod1(trimmed_cell->position[i][j]);
    }
  }
}
Beispiel #2
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;
}
Beispiel #3
0
static int set_equivalent_atom(VecDBL *positions,
                               int * equiv_atoms,
                               const int i,
                               const int num_indep_atoms,
                               const int *indep_atoms,
                               const Cell * conv_prim,
                               const Symmetry * conv_sym,
                               const double symprec)
{
  int j, k, l;
  double pos[3];

  for (j = 0; j < num_indep_atoms; j++) {
    for (k = 0; k < conv_sym->size; k++) {
      mat_multiply_matrix_vector_id3(pos,
                                     conv_sym->rot[k],
                                     positions->vec[indep_atoms[j]]);
      for (l = 0; l < 3; l++) {
        pos[l] += conv_sym->trans[k][l];
      }
      if (cel_is_overlap_with_same_type(pos,
                                        conv_prim->position[i],
                                        conv_prim->types[indep_atoms[j]],
                                        conv_prim->types[i],
                                        conv_prim->lattice,
                                        symprec)) {
        for (l = 0; l < 3; l++) {
          positions->vec[i][l] = mat_Dmod1(pos[l]);
        }
        equiv_atoms[i] = indep_atoms[j];
        return 1;
      }
    }
  }

  return 0;
}
Beispiel #4
0
/* Return NULL if failed */
static VecDBL * get_lattice_translations(const int frame[3],
					 SPGCONST double inv_tmat[3][3])
{
  int i, j, k, l, num_trans;
  VecDBL * lattice_trans;

  lattice_trans = NULL;

  if ((lattice_trans = mat_alloc_VecDBL(frame[0] * frame[1] * frame[2]))
      == NULL) {
    return NULL;
  }

  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;

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

  return lattice_trans;
}
Beispiel #5
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;
}
Beispiel #6
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;
}
Beispiel #7
0
/* Return NULL if failed */
static VecDBL * get_exact_positions(int * wyckoffs,
				    int * equiv_atoms,
				    SPGCONST Cell * bravais,
				    SPGCONST Symmetry * conv_sym,
				    const int hall_number,
				    const double symprec)
{
  int i, j, k, l, num_indep_atoms;
  double pos[3];
  int *indep_atoms;
  VecDBL *positions;

  debug_print("get_exact_positions\n");

  indep_atoms = NULL;
  positions = NULL;

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

  if ((positions = mat_alloc_VecDBL(bravais->size)) == NULL) {
    free(indep_atoms);
    indep_atoms = NULL;
    return NULL;
  }

  num_indep_atoms = 0;

  for (i = 0; i < bravais->size; i++) {
    /* Check if atom_i overlap to an atom already set at the exact position. */
    for (j = 0; j < num_indep_atoms; j++) {
      for (k = 0; k < conv_sym->size; k++) {
	mat_multiply_matrix_vector_id3(pos,
				       conv_sym->rot[k],
				       positions->vec[indep_atoms[j]]);
	for (l = 0; l < 3; l++) {
	  pos[l] += conv_sym->trans[k][l];
	}
	if (cel_is_overlap(pos,
			   bravais->position[i],
			   bravais->lattice,
			   symprec)) {
	  /* Equivalent atom was found. */
	  for (l = 0; l < 3; l++) {
	    positions->vec[i][l] = mat_Dmod1(pos[l]);
	  }
	  wyckoffs[i] = wyckoffs[indep_atoms[j]];
	  equiv_atoms[i] = indep_atoms[j];
	  goto escape;
	}
      }
    }
    
    /* No equivalent atom was found. */
    indep_atoms[num_indep_atoms] = i;
    num_indep_atoms++;
    mat_copy_vector_d3(positions->vec[i], bravais->position[i]);
    get_exact_location(positions->vec[i],
		       conv_sym,
		       bravais->lattice,
		       symprec);
    wyckoffs[i] = get_Wyckoff_notation(positions->vec[i],
				       conv_sym,
				       bravais->lattice,
				       hall_number,
				       symprec);
    equiv_atoms[i] = i;
  escape:
    ;
  }

  free(indep_atoms);
  indep_atoms = NULL;

  for (i = 0; i < bravais->size; i++) {
    if (wyckoffs[i] == -1) {
      mat_free_VecDBL(positions);
      positions = NULL;
      break;
    }
  }

  return positions;
}
Beispiel #8
0
static Symmetry * get_primitive_db_symmetry(SPGCONST double t_mat[3][3],
					    const Symmetry *conv_sym)
{
  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 = NULL;
  t_prim = NULL;
  prim_sym = NULL;

  if ((r_prim = mat_alloc_MatINT(conv_sym->size)) == NULL) {
    return NULL;
  }

  if ((t_prim = mat_alloc_VecDBL(conv_sym->size)) == NULL) {
    mat_free_MatINT(r_prim);
    r_prim = NULL;
    return NULL;
  }

  mat_inverse_matrix_d3(inv_mat, t_mat, 0);

  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:
    ;
  }

  if ((prim_sym = sym_alloc_symmetry(num_op)) == NULL) {
    goto ret;
  }

  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] = mat_Dmod1(t_prim->vec[i][j]);
    }
  }

 ret:
  mat_free_MatINT(r_prim);
  r_prim = NULL;
  mat_free_VecDBL(t_prim);
  t_prim = NULL;

  return prim_sym;
}
Beispiel #9
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;
}