Example #1
0
static Centering get_centering(double correction_mat[3][3],
			       SPGCONST int transform_mat[3][3],
			       const Laue laue)
{
  int det;
  double trans_corr_mat[3][3];
  Centering centering;

  mat_copy_matrix_d3(correction_mat, identity);
  det = abs(mat_get_determinant_i3(transform_mat));
  debug_print("laue class: %d\n", laue);
  debug_print("multiplicity: %d\n", det);

  if (det == 1) { centering = NO_CENTER; }
  if (det == 2) { centering = get_base_center(transform_mat);
    if (centering == A_FACE) {
      if (laue == LAUE2M) {
	debug_print("Monocli A to C\n");
	mat_copy_matrix_d3(correction_mat, monocli_a2c);
      } else {
	mat_copy_matrix_d3(correction_mat, a2c);
      }
      centering = C_FACE;
    }
    if (centering == B_FACE) {
      mat_copy_matrix_d3(correction_mat, b2c);
      centering = C_FACE;
    }
    if (laue == LAUE2M && centering == BODY) {
      debug_print("Monocli I to C\n");
      mat_copy_matrix_d3(correction_mat, monocli_i2c);
      centering = C_FACE;
    }
  }
  if (det == 3) {
    centering = NO_CENTER;
    mat_multiply_matrix_id3(trans_corr_mat,
			    transform_mat, rhombo_obverse);
    if (mat_is_int_matrix(trans_corr_mat, INT_PREC)) {
      mat_copy_matrix_d3(correction_mat, rhombo_obverse);
      debug_print("R-center observe setting\n");
      debug_print_matrix_d3(trans_corr_mat);
    }
    mat_multiply_matrix_id3(trans_corr_mat,
			    transform_mat, rhomb_reverse);
    if (mat_is_int_matrix(trans_corr_mat, INT_PREC)) {
      mat_copy_matrix_d3(correction_mat, rhomb_reverse);
      debug_print("R-center reverse setting\n");
      debug_print_matrix_d3(trans_corr_mat);
    }
  }
  if (det == 4) { centering = FACE; }

  return centering;
}
Example #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;
}
Example #3
0
/* If primitive could not be found, primitive->size = -1 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;

  /* 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 = cel_alloc_cell( cell->size / multi );

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

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

  debug_print("Original cell lattice.\n");
  debug_print_matrix_d3(cell->lattice);
  debug_print("Found primitive lattice after choosing least axes.\n");
  debug_print_matrix_d3(primitive->lattice);
  debug_print("Number of atoms in primitive cell: %d\n", primitive->size);
  debug_print("Volume: original %f --> primitive %f\n",
	      mat_get_determinant_d3(cell->lattice),
	      mat_get_determinant_d3(primitive->lattice));

  /* found */
  return primitive;

 not_found:
  primitive = cel_alloc_cell( -1 );
  warning_print("spglib: Primitive cell could not found ");
  warning_print("(line %d, %s).\n", __LINE__, __FILE__);
  return primitive;
}
Example #4
0
static Cell * refine_cell(SPGCONST Cell * cell,
                          const double symprec)
{
    int *wyckoffs, *equiv_atoms;
    double tolerance;
    Cell *primitive, *bravais, *conv_prim;
    Symmetry *conv_sym;
    Spacegroup spacegroup;

    debug_print("refine_cell:\n");

    primitive = prm_get_primitive(cell, symprec);

    if (primitive->size == 0) {
        cel_free_cell(primitive);
        bravais = cel_alloc_cell(0);
        goto end;
    }

    tolerance = prm_get_current_tolerance();
    spacegroup = spa_get_spacegroup_with_primitive(primitive, tolerance);

    wyckoffs = (int*)malloc(sizeof(int) * primitive->size);
    equiv_atoms = (int*)malloc(sizeof(int) * primitive->size);
    conv_prim = get_bravais_exact_positions_and_lattice(wyckoffs,
                equiv_atoms,
                &spacegroup,
                primitive,
                tolerance);
    free(equiv_atoms);
    equiv_atoms = NULL;
    free(wyckoffs);
    wyckoffs = NULL;

    conv_sym = get_db_symmetry(spacegroup.hall_number);
    bravais = expand_positions(conv_prim, conv_sym);

    debug_print("primitive cell in refine_cell:\n");
    debug_print_matrix_d3(primitive->lattice);
    debug_print("conventional lattice in refine_cell:\n");
    debug_print_matrix_d3(conv_prim->lattice);
    debug_print("bravais lattice in refine_cell:\n");
    debug_print_matrix_d3(bravais->lattice);

    cel_free_cell(conv_prim);
    sym_free_symmetry(conv_sym);
    cel_free_cell(primitive);

end:  /* Return bravais->size = 0, if the bravais could not be found. */
    return bravais;
}
Example #5
0
static Centering get_transformation_matrix( double trans_mat[3][3],
					    SPGCONST Symmetry * symmetry )
{
  int pg_num;
  double correction_mat[3][3];
  Centering centering;
  Pointgroup pointgroup;

  pg_num = ptg_get_pointgroup_number( symmetry );
  pointgroup = ptg_get_pointgroup( pg_num );
  ptg_get_transformation_matrix( &pointgroup, symmetry );

  /* Centering is not determined only from symmetry operations */
  /* sometimes. Therefore centering and transformation matrix are */
  /* related. */
  centering = lat_get_centering( correction_mat,
				 pointgroup.transform_mat,
				 pointgroup.laue );
  mat_multiply_matrix_id3( trans_mat,
			   pointgroup.transform_mat,
			   correction_mat );

  debug_print("correction matrix\n");
  debug_print_matrix_d3( correction_mat );

  return centering;
}
Example #6
0
static void set_monocli(double lattice[3][3],
                        SPGCONST double metric[3][3])
{
    /* Lattice is expected to be C centring */
    double a, b, c, beta;

    debug_print("set_monocli:\n");
    debug_print_matrix_d3(metric);

    a = sqrt(metric[0][0]);
    b = sqrt(metric[1][1]);
    c = sqrt(metric[2][2]);
    lattice[1][1] = b;
    lattice[2][2] = c;
    beta = acos(metric[0][2] / a / c);
    lattice[2][0] = a * cos(beta);
    lattice[0][0] = a * sin(beta);

    debug_print("beta %f\n", beta);
    debug_print_matrix_d3(lattice);
}
Example #7
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;
  }
}
Example #8
0
Symmetry * sym_get_operation( SPGCONST Cell *cell,
			      const double symprec ) {
  int i, j, num_sym;
  MatINT *rot;
  VecDBL *trans;
  Symmetry *symmetry;
  
  rot = mat_alloc_MatINT( cell->size * 48 );
  trans = mat_alloc_VecDBL( cell->size * 48 );

  num_sym = get_operation( rot->mat, trans->vec, cell, symprec );

#ifdef DEBUG
  debug_print("*** get_symmetry (found symmetry operations) *** \n");
  debug_print("Lattice \n");
  debug_print_matrix_d3(cell->lattice);
  for ( i = 0; i < num_sym; i++ ) {
    debug_print("--- %d ---\n", i + 1);
    debug_print_matrix_i3(rot->mat[i]);
    debug_print("%f %f %f\n",
  		trans->vec[i][0], trans->vec[i][1], trans->vec[i][2]);
  }
#endif
  
  symmetry = sym_alloc_symmetry( num_sym );
  for ( i = 0; i < num_sym; i++ ) {
    mat_copy_matrix_i3(symmetry->rot[i], rot->mat[i]);
    for (j = 0; j < 3; j++)
      symmetry->trans[i][j] = trans->vec[i][j];
  }

  mat_free_MatINT( rot );
  mat_free_VecDBL( trans );

  return symmetry;
}
Example #9
0
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));
  debug_print("initial volume: %f\n", initial_volume);

  /* 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 ) {
	  debug_print("temporary volume of primitive cell: %f\n", volume );
	  debug_print("volume of original cell: %f\n", initial_volume );
	  debug_print("multi and calculated multi: %d, %d\n", size-2, mat_Nint( initial_volume / volume ) );
	  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 );

  debug_print("Oritinal relative_lattice\n");
  debug_print_matrix_d3( relative_lattice );
  debug_print("Cleaned relative_lattice\n");
  debug_print_matrix_d3( relative_lattice );
  debug_print("Primitive lattice\n");
  debug_print_matrix_d3( prim_lattice );

  return 1;  
}
Example #10
0
/* Return CENTERING_ERROR if failed */
static Centering get_centering(double correction_mat[3][3],
			       SPGCONST int transform_mat[3][3],
			       const Laue laue)
{
  int det;
  double trans_corr_mat[3][3];
  Centering centering;

  mat_copy_matrix_d3(correction_mat, identity);
  det = abs(mat_get_determinant_i3(transform_mat));
  debug_print("laue class: %d\n", laue);
  debug_print("multiplicity: %d\n", det);

  switch (det) {

  case 1:
    centering = PRIMITIVE;
    break;

  case 2:
    centering = get_base_center(transform_mat);
    if (centering == A_FACE) {
      if (laue == LAUE2M) {
	debug_print("Monocli A to C\n");
	mat_copy_matrix_d3(correction_mat, monocli_a2c);
      } else {
	mat_copy_matrix_d3(correction_mat, a2c);
      }
      centering = C_FACE;
    }
    if (centering == B_FACE) {
      mat_copy_matrix_d3(correction_mat, b2c);
      centering = C_FACE;
    }
    if (laue == LAUE2M && centering == BODY) {
      debug_print("Monocli I to C\n");
      mat_copy_matrix_d3(correction_mat, monocli_i2c);
      centering = C_FACE;
    }
    break;

  case 3:
    /* hP (a=b) but not hR (a=b=c) */
    centering = R_CENTER;
    mat_multiply_matrix_id3(trans_corr_mat, transform_mat, rhombo_obverse);
    if (mat_is_int_matrix(trans_corr_mat, INT_PREC)) {
      mat_copy_matrix_d3(correction_mat, rhombo_obverse);
      debug_print("R-center observe setting\n");
      debug_print_matrix_d3(trans_corr_mat);
    }
    mat_multiply_matrix_id3(trans_corr_mat, transform_mat, rhomb_reverse);
    if (mat_is_int_matrix(trans_corr_mat, INT_PREC)) {
      mat_copy_matrix_d3(correction_mat, rhomb_reverse);
      debug_print("R-center reverse setting\n");
      debug_print_matrix_d3(trans_corr_mat);
    }
    break;

  case 4:
    centering = FACE;
    break;

  default:
    centering = CENTERING_ERROR;
    break;
  }

  return centering;
}