示例#1
0
static PointSymmetry get_lattice_symmetry(SPGCONST Cell *cell,
					  const double symprec)
{
  int i, j, k, num_sym;
  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");

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

  mat_get_metric(metric_orig, min_lattice);

  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)) {
	  mat_copy_matrix_i3(lattice_sym.rot[num_sym], axes);
	  num_sym++;
	}
	  
	if (num_sym > 48) {
	  warning_print("spglib: Too many lattice symmetries was found.\n");
	  warning_print("        Tolerance may be too large ");
	  warning_print("(line %d, %s).\n", __LINE__, __FILE__);
	  goto err;
	}
      }
    }
  }

  lattice_sym.size = num_sym;
  return transform_pointsymmetry(&lattice_sym,
				 cell->lattice,
				 min_lattice);
  
 err:
  lattice_sym.size = 0;
  return lattice_sym;
}
示例#2
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;
}
示例#3
0
static void get_conventional_lattice(double lattice[3][3],
				     SPGCONST Spacegroup *spacegroup)
{
  int i, j;
  double metric[3][3];
  Pointgroup pointgroup;

  pointgroup = ptg_get_pointgroup(spacegroup->pointgroup_number);

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

  mat_get_metric(metric, spacegroup->bravais_lattice);

  debug_print("bravais lattice\n");
  debug_print_matrix_d3(spacegroup->bravais_lattice);
  debug_print("%s\n", spacegroup->setting);

  switch (pointgroup.holohedry) {
  case TRICLI:
    set_tricli(lattice, metric);
    break;
  case MONOCLI: /* b-axis is the unique axis. */
    set_monocli(lattice, metric);
    break;
  case ORTHO:
    set_ortho(lattice, metric);
    break;
  case TETRA:
    set_tetra(lattice, metric);
    break;
  case TRIGO:
    if (spacegroup->setting[0] == 'R') {
      set_rhomb(lattice, metric);
    } else {
      set_trigo(lattice, metric);
    }
    break;
  case HEXA:
    set_trigo(lattice, metric);
    break;
  case CUBIC:
    set_cubic(lattice, metric);
    break;
  case HOLOHEDRY_NONE:
    break;
  }
}
示例#4
0
static int get_conventional_lattice(double lattice[3][3],
                                    const Holohedry holohedry,
                                    SPGCONST double bravais_lattice[3][3])
{
    int i, j;
    double metric[3][3];

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

    mat_get_metric(metric, bravais_lattice);

    switch (holohedry) {
    case TRICLI:
        mat_copy_matrix_d3(lattice, bravais_lattice);
        break;
    case MONOCLI: /* b-axis is the unique axis. */
        set_monocli(lattice, metric);
        break;
    case ORTHO:
        set_ortho(lattice, metric);
        break;
    case TETRA:
        set_tetra(lattice, metric);
        break;
    case RHOMB:
        set_rhomb(lattice, metric);
        break;
    case TRIGO:
        set_trigo(lattice, metric);
        break;
    case HEXA:
        set_trigo(lattice, metric);
        break;
    case CUBIC:
        set_cubic(lattice, metric);
        break;
    case NONE:
        break;
    }

    return 1;
}
示例#5
0
static void set_rhomb(double lattice[3][3],
                      SPGCONST double metric[3][3])
{
    double a, b, c, angle, ahex, chex;


    a = sqrt(metric[0][0]);
    b = sqrt(metric[1][1]);
    c = sqrt(metric[2][2]);
    angle = acos((metric[0][1] / a / b +
                  metric[0][2] / a / c +
                  metric[1][2] / b / c) / 3);

    /* Reference, http://cst-www.nrl.navy.mil/lattice/struk/rgr.html */
    ahex = 2 * (a+b+c)/3 * sin(angle / 2);
    chex = (a+b+c)/3 * sqrt(3 * (1 + 2 * cos(angle))) ;
    lattice[0][0] = ahex / 2;
    lattice[1][0] = -ahex / (2 * sqrt(3));
    lattice[2][0] = chex / 3;
    lattice[1][1] = ahex / sqrt(3);
    lattice[2][1] = chex / 3;
    lattice[0][2] = -ahex / 2;
    lattice[1][2] = -ahex / (2 * sqrt(3));
    lattice[2][2] = chex / 3;


#ifdef DEBUG
    debug_print("Rhombo lattice: %f %f %f %f %f %f\n", a, b, c,
                acos(metric[0][1] / a / b) / 3.14 * 180,
                acos(metric[0][2] / a / c) / 3.14 * 180,
                acos(metric[1][2] / b / c) / 3.14 * 180);
    double dmetric[3][3];
    mat_get_metric(dmetric, lattice);
    a = sqrt(dmetric[0][0]);
    b = sqrt(dmetric[1][1]);
    c = sqrt(dmetric[2][2]);
    debug_print("Rhombo lattice symmetrized: %f %f %f %f %f %f\n",
                a, b, c,
                acos(dmetric[0][1] / a / b) / 3.14 * 180,
                acos(dmetric[0][2] / a / c) / 3.14 * 180,
                acos(dmetric[1][2] / b / c) / 3.14 * 180);
#endif
}
示例#6
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;
}