Пример #1
0
void mat_cast_matrix_3d_to_3i(int m[3][3], const double a[3][3])
{
    m[0][0] = mat_Nint(a[0][0]);
    m[0][1] = mat_Nint(a[0][1]);
    m[0][2] = mat_Nint(a[0][2]);
    m[1][0] = mat_Nint(a[1][0]);
    m[1][1] = mat_Nint(a[1][1]);
    m[1][2] = mat_Nint(a[1][2]);
    m[2][0] = mat_Nint(a[2][0]);
    m[2][1] = mat_Nint(a[2][1]);
    m[2][2] = mat_Nint(a[2][2]);
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
0
/* Acta Cryst. (2002). A58, 60-65 */
static void get_exact_location(double position[3],
			       SPGCONST Symmetry * conv_sym,
			       SPGCONST double bravais_lattice[3][3],
			       const double symprec)
{
  int i, j, k, num_sum;
  double sum_rot[3][3];
  double pos[3], sum_trans[3];

  debug_print("get_exact_location\n");

  num_sum = 0;
  for (i = 0; i < 3; i++) {
    sum_trans[i] = 0.0;
    for (j = 0; j < 3; j++) {
      sum_rot[i][j] = 0;
    }
  }
  
  for (i = 0; i < conv_sym->size; i++) {
    mat_multiply_matrix_vector_id3(pos,
				   conv_sym->rot[i],
				   position);
    for (j = 0; j < 3; j++) {
      pos[j] += conv_sym->trans[i][j];
    }

    if (cel_is_overlap(pos,
		       position,
		       bravais_lattice,
		       symprec)) {
      for (j = 0; j < 3; j++) {
	sum_trans[j] += conv_sym->trans[i][j] - 
	  mat_Nint(pos[j] - position[j]);
	for (k = 0; k < 3; k++) {
	  sum_rot[j][k] += conv_sym->rot[i][j][k];
	}
      }
      num_sum++;
    }
  }

  for (i = 0; i < 3; i++) {
    sum_trans[i] /= num_sum;
    for (j = 0; j < 3; j++) {
      sum_rot[i][j] /= num_sum;
    }
  }

  /* (sum_rot|sum_trans) is the special-position operator. */
  /* Elements of sum_rot can be fractional values. */
  mat_multiply_matrix_vector_d3(position,
				sum_rot,
				position);

  for (i = 0; i < 3; i++) {
    position[i] += sum_trans[i];
  }

}
Пример #6
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;
}
Пример #7
0
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;

  is_all_ok = 0;
  num_rot = 0;
  ir_rot = (int*)malloc(sizeof(int) * rot_reciprocal->size);
  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++;
    }
  }

  rot_reciprocal_q = mat_alloc_MatINT(num_rot);
  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);

  return rot_reciprocal_q;
}
Пример #8
0
static int is_overlap_all_atoms(const double trans[3],
				SPGCONST int rot[3][3],
				SPGCONST Cell * cell,
				const double symprec,
				const int is_identity)
{
  int i, j, k, is_found;
  double symprec2;
  double pos_rot[3], d[3];

  symprec2 = symprec*symprec;
  
  for (i = 0; i < cell->size; i++) {
    if (is_identity) { /* Identity matrix is treated as special for speed. */
      for (j = 0; j < 3; j++) {
	pos_rot[j] = cell->position[i][j] + trans[j];
      }
    } else {
      mat_multiply_matrix_vector_id3(pos_rot,
				     rot,
				     cell->position[i]);
      for (j = 0; j < 3; j++) {
	pos_rot[j] += trans[j];
      }
    }

    is_found = 0;
    for (j = 0; j < cell->size; j++) {
      if (cell->types[i] == cell->types[j]) {
	/* here cel_is_overlap can be used, but for the tuning */
	/* purpose, write it again */
	for (k = 0; k < 3; k++) {
	  d[k] = pos_rot[k] - cell->position[j][k];
	  d[k] -= mat_Nint(d[k]);
	}
	mat_multiply_matrix_vector_d3(d, cell->lattice, d);
	if (d[0]*d[0]+d[1]*d[1]+d[2]*d[2] < symprec2) {
	  is_found = 1;
	  break;
	}
      }
    }

    if (! is_found) {
      goto not_found;
    }
  }

  return 1;  /* found */

 not_found:
  return 0;
}
Пример #9
0
int mat_is_int_matrix(SPGCONST double mat[3][3], const double symprec)
{
  int i,j ;
  for ( i = 0; i < 3; i++ ) {
    for ( j = 0; j < 3; j++ ) {
      if ( mat_Dabs( mat_Nint( mat[i][j] ) - mat[i][j] ) > symprec ) {
	return 0;
      }
    }
  }
  return 1;
}
Пример #10
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;
}
Пример #11
0
void cel_set_cell(Cell * cell,
                  SPGCONST double lattice[3][3],
                  SPGCONST double position[][3],
                  const int types[])
{
  int i, j;
  mat_copy_matrix_d3(cell->lattice, lattice);
  for (i = 0; i < cell->size; i++) {
    for (j = 0; j < 3; j++) {
      cell->position[i][j] = position[i][j] - mat_Nint(position[i][j]);
    }
    cell->types[i] = types[i];
  }
}
Пример #12
0
static PointSymmetry
get_point_group_reciprocal_with_q(SPGCONST PointSymmetry * pointgroup,
				  const double symprec,
				  const int num_q,
				  SPGCONST double qpoints[][3])
{
  int i, j, k, l, is_all_ok=0, num_ptq = 0;
  double q_rot[3], diff[3];
  PointSymmetry pointgroup_q;

  for (i = 0; i < pointgroup->size; i++) {
    for (j = 0; j < num_q; j++) {
      is_all_ok = 0;
      mat_multiply_matrix_vector_id3(q_rot,
				     pointgroup->rot[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) {
      mat_copy_matrix_i3(pointgroup_q.rot[num_ptq], pointgroup->rot[i]);
      num_ptq++;
    }
  }
  pointgroup_q.size = num_ptq;

  return pointgroup_q;
}
Пример #13
0
int cel_is_overlap( const double a[3],
		    const double b[3],
		    SPGCONST double lattice[3][3],
		    const double symprec )
{
  int i;
  double v_diff[3];

  for ( i = 0; i < 3; i++ ) {
    v_diff[i] = a[i] - b[i];
    v_diff[i] -= mat_Nint( v_diff[i] );
  }

  mat_multiply_matrix_vector_d3( v_diff, lattice, v_diff );
  if ( mat_norm_squared_d3( v_diff ) < symprec*symprec ) {
    return 1;
  } else {
    return 0;
  }
}
Пример #14
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_Nint(cell->position[i][j]);
        }
    }

    return smallest_cell;

err:
    return NULL;
}
Пример #15
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;
}
Пример #16
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;
}
Пример #17
0
/* Return 0 if failed */
static int set_primitive_positions(Cell * primitive_cell,
                                   const VecDBL * position,
                                   const Cell * cell,
                                   int * const * table)
{
    int i, j, k, ratio, index_prim_atom;
    int *is_equivalent;

    is_equivalent = NULL;

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

    for (i = 0; i < cell->size; i++) {
        is_equivalent[i] = 0;
    }
    ratio = cell->size / primitive_cell->size;

    /* Copy positions. Positions of overlapped atoms are averaged. */
    index_prim_atom = 0;
    for (i = 0; i < cell->size; i++) {

        if (! is_equivalent[i]) {
            primitive_cell->types[index_prim_atom] = cell->types[i];

            for (j = 0; j < 3; j++) {
                primitive_cell->position[index_prim_atom][j] = 0;
            }

            for (j = 0; j < ratio; j++) { /* Loop for averaging positions */
                is_equivalent[table[i][j]] = 1;

                for (k = 0; k < 3; k++) {
                    /* boundary treatment */
                    /* One is at right and one is at left or vice versa. */
                    if (mat_Dabs(position->vec[table[i][0]][k] -
                                 position->vec[table[i][j]][k]) > 0.5) {
                        if (position->vec[table[i][j]][k] < 0) {
                            primitive_cell->position[index_prim_atom][k] =
                                primitive_cell->position[index_prim_atom][k] +
                                position->vec[table[i][j]][k] + 1;
                        } else {
                            primitive_cell->position[index_prim_atom][k] =
                                primitive_cell->position[index_prim_atom][k] +
                                position->vec[table[i][j]][k] - 1;
                        }

                    } else {
                        primitive_cell->position[index_prim_atom][k] =
                            primitive_cell->position[index_prim_atom][k] +
                            position->vec[table[i][j]][k];
                    }
                }

            }

            for (j = 0; j < 3; j++) {	/* take average and reduce */
                primitive_cell->position[index_prim_atom][j] =
                    primitive_cell->position[index_prim_atom][j] / ratio;
                primitive_cell->position[index_prim_atom][j] =
                    primitive_cell->position[index_prim_atom][j] -
                    mat_Nint(primitive_cell->position[index_prim_atom][j]);
            }
            index_prim_atom++;
        }
    }

    free(is_equivalent);
    is_equivalent = NULL;

    if (! (index_prim_atom == primitive_cell->size)) {
        warning_print("spglib: Atomic positions of primitive cell could not be determined ");
        warning_print("(line %d, %s).\n", __LINE__, __FILE__);
        goto err;
    }

    return 1;

err:
    return 0;
}
Пример #18
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;  
}
Пример #19
0
static int get_ir_kpoints(int map[],
			  SPGCONST double kpoints[][3],
			  const int num_kpoint,
			  SPGCONST PointSymmetry * point_symmetry,
			  const double symprec)
{
  int i, j, k, l, num_ir_kpoint = 0, is_found;
  int *ir_map;
  double kpt_rot[3], diff[3];

  ir_map = (int*)malloc(num_kpoint*sizeof(int));

  for (i = 0; i < num_kpoint; i++) {

    map[i] = i;

    is_found = 1;

    for (j = 0; j < point_symmetry->size; j++) {
      mat_multiply_matrix_vector_id3(kpt_rot, point_symmetry->rot[j], kpoints[i]);

      for (k = 0; k < 3; k++) {
	diff[k] = kpt_rot[k] - kpoints[i][k];
	diff[k] = diff[k] - mat_Nint(diff[k]);
      }

      if (mat_Dabs(diff[0]) < symprec && 
	  mat_Dabs(diff[1]) < symprec && 
	  mat_Dabs(diff[2]) < symprec) {
	continue;
      }
      
      for (k = 0; k < num_ir_kpoint; k++) {
	mat_multiply_matrix_vector_id3(kpt_rot, point_symmetry->rot[j], kpoints[i]);

	for (l = 0; l < 3; l++) {
	  diff[l] = kpt_rot[l] - kpoints[ir_map[k]][l];
	  diff[l] = diff[l] - mat_Nint(diff[l]);
	}

	if (mat_Dabs(diff[0]) < symprec && 
	    mat_Dabs(diff[1]) < symprec && 
	    mat_Dabs(diff[2]) < symprec) {
	  is_found = 0;
	  map[i] = ir_map[k];
	  break;
	}
      }

      if (! is_found)
	break;
    }

    if (is_found) {
      ir_map[num_ir_kpoint] = i;
      num_ir_kpoint++;
    }
  }

  free(ir_map);
  ir_map = NULL;

  return num_ir_kpoint;
}
Пример #20
0
/* Acta Cryst. (2002). A58, 60-65 */
static int set_exact_location(double position[3],
                              const Symmetry * conv_sym,
                              SPGCONST double bravais_lattice[3][3],
                              const double symprec)
{
  int i, j, k, num_sum, multi, num_pure_trans;
  double sum_rot[3][3];
  double pos[3], sum_trans[3];

  debug_print("get_exact_location\n");

  num_sum = 0;
  for (i = 0; i < 3; i++) {
    sum_trans[i] = 0.0;
    for (j = 0; j < 3; j++) {
      sum_rot[i][j] = 0;
    }
  }

  num_pure_trans = 0;
  for (i = 0; i < conv_sym->size; i++) {
    if (mat_check_identity_matrix_i3(identity, conv_sym->rot[i])) {
      num_pure_trans++;
      for (j = 0; j < 3; j++) {
        pos[j] = position[j];
      }
    } else {
      mat_multiply_matrix_vector_id3(pos,
                                     conv_sym->rot[i],
                                     position);
    }
    for (j = 0; j < 3; j++) {
      pos[j] += conv_sym->trans[i][j];
    }

    if (cel_is_overlap(pos,
                       position,
                       bravais_lattice,
                       symprec)) {
      for (j = 0; j < 3; j++) {
        for (k = 0; k < 3; k++) {
          sum_rot[j][k] += conv_sym->rot[i][j][k];
        }
        sum_trans[j] +=
          conv_sym->trans[i][j] - mat_Nint(pos[j] - position[j]);
      }
      num_sum++;
    }
  }

  for (i = 0; i < 3; i++) {
    sum_trans[i] /= num_sum;
    for (j = 0; j < 3; j++) {
      sum_rot[i][j] /= num_sum;
    }
  }

  /* (sum_rot|sum_trans) is the special-position operator. */
  /* Elements of sum_rot can be fractional values. */
  mat_multiply_matrix_vector_d3(position,
                                sum_rot,
                                position);

  for (i = 0; i < 3; i++) {
    position[i] += sum_trans[i];
  }

  multi = conv_sym->size / num_pure_trans / num_sum;
  if (multi * num_sum * num_pure_trans == conv_sym->size) {
    return multi;
  } else {
    return 0;
  }
}
Пример #21
0
static int set_primitive_positions( Cell * primitive,
				    const VecDBL * position,
				    const Cell * cell,
				    int * const * table )
{
  int i, j, k, ratio, count;
  int *is_equivalent = (int*)malloc(cell->size * sizeof(int));

  ratio = cell->size / primitive->size;
  for (i = 0; i < cell->size; i++) {
    is_equivalent[i] = 0;
  }

  /* Copy positions. Positions of overlapped atoms are averaged. */
  count = 0;
  for ( i = 0; i < cell->size; i++ )

    if ( ! is_equivalent[i] ) {

      debug_print("Trimming... i=%d count=%d\n", i, count);
      primitive->types[count] = cell->types[i];

      for ( j = 0; j < 3; j++ ) {
	primitive->position[count][j] = 0;
      }

      for ( j = 0; j < ratio; j++ ) {	/* overlap atoms */
        if ( table[i][j] < 0 ) { /* check if table is correctly bulit. */
          break;
	}

	is_equivalent[table[i][j]] = 1;

	for (k = 0; k < 3; k++) {

	  /* boundary treatment */
	  if (mat_Dabs(position->vec[table[i][0]][k] -
		       position->vec[table[i][j]][k]) > 0.5) {

	    if (position->vec[table[i][j]][k] < 0) {
	      primitive->position[count][k]
		= primitive->position[count][k] +
		position->vec[table[i][j]][k] + 1;
	    } else {
	      primitive->position[count][k]
		= primitive->position[count][k] +
		position->vec[table[i][j]][k] - 1;
	    }

	  } else {
	    primitive->position[count][k]
	      = primitive->position[count][k] +
	      position->vec[table[i][j]][k];
	  }
	}
	
      }

      for (j = 0; j < 3; j++) {	/* take average and reduce */

	primitive->position[count][j] =
	  primitive->position[count][j] / ratio;

	primitive->position[count][j] =
	  primitive->position[count][j] -
	  mat_Nint( primitive->position[count][j] );
      }
      count++;
    }

  free(is_equivalent);
  is_equivalent = NULL;

  debug_print("Count: %d Size of cell: %d Size of primitive: %d\n", count, cell->size, primitive->size);
  if ( ! ( count == primitive->size ) ) {
    warning_print("spglib: Atomic positions of primitive cell could not be determined ");
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);
    goto err;
  }

  return 1;

 err:
  return 0;
}
Пример #22
0
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_symmetrized_positions\n");

  indep_atoms = (int*) malloc(sizeof(int) * bravais->size);
  positions = mat_alloc_VecDBL(bravais->size);
  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++) {
	    pos[l] -= mat_Nint(pos[l]);
	  }
	  mat_copy_vector_d3(positions->vec[i], pos);
	  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;

  return positions;
}
Пример #23
0
/* Return NULL if failed */
static Cell * trim_cell(int * mapping_table,
                        SPGCONST double trimmed_lattice[3][3],
                        const Cell * cell,
                        const double symprec)
{
  int i, index_atom, ratio;
  Cell *trimmed_cell;
  VecDBL * position;
  int *overlap_table;

  position = NULL;
  overlap_table = NULL;
  trimmed_cell = NULL;

  ratio = abs(mat_Nint(mat_get_determinant_d3(cell->lattice) /
                       mat_get_determinant_d3(trimmed_lattice)));

  /* Check if cell->size is dividable by ratio */
  if ((cell->size / ratio) * ratio != cell->size) {
    return NULL;
  }

  if ((trimmed_cell = cel_alloc_cell(cell->size / ratio)) == NULL) {
    return NULL;
  }

  if ((position = translate_atoms_in_trimmed_lattice(cell,
                                                     trimmed_lattice))
      == NULL) {
    cel_free_cell(trimmed_cell);
    trimmed_cell = NULL;
    goto err;
  }

  mat_copy_matrix_d3(trimmed_cell->lattice, trimmed_lattice);

  if ((overlap_table = get_overlap_table(position,
                                         cell->size,
                                         cell->types,
                                         trimmed_cell,
                                         symprec)) == NULL) {
    mat_free_VecDBL(position);
    position = NULL;
    cel_free_cell(trimmed_cell);
    trimmed_cell = NULL;
    goto err;
  }

  index_atom = 0;
  for (i = 0; i < cell->size; i++) {
    if (overlap_table[i] == i) {
      mapping_table[i] = index_atom;
      trimmed_cell->types[index_atom] = cell->types[i];
      index_atom++;
    } else {
      mapping_table[i] = mapping_table[overlap_table[i]];
    }
  }

  set_positions(trimmed_cell,
                position,
                mapping_table,
                overlap_table);

  mat_free_VecDBL(position);
  position = NULL;
  free(overlap_table);

  return trimmed_cell;

 err:
  return NULL;
}