Example #1
0
static Symmetry * reduce_operation(SPGCONST Cell * cell,
				   SPGCONST Symmetry * symmetry,
				   const double symprec)
{
  int i, j, num_sym;
  Symmetry * sym_reduced;
  PointSymmetry point_symmetry;
  MatINT *rot;
  VecDBL *trans;

  debug_print("reduce_operation:\n");

  point_symmetry = get_lattice_symmetry(cell, symprec);
  rot = mat_alloc_MatINT(symmetry->size);
  trans = mat_alloc_VecDBL(symmetry->size);

  num_sym = 0;
  for (i = 0; i < point_symmetry.size; i++) {
    for (j = 0; j < symmetry->size; j++) {
      if (mat_check_identity_matrix_i3(point_symmetry.rot[i],
				       symmetry->rot[j])) {
	if (is_overlap_all_atoms(symmetry->trans[j],
				 symmetry->rot[j],
				 cell,
				 symprec,
				 0)) {
	  mat_copy_matrix_i3(rot->mat[num_sym], symmetry->rot[j]);
	  mat_copy_vector_d3(trans->vec[num_sym], symmetry->trans[j]);
	  num_sym++;
	}
      }
    }
  }

  sym_reduced = sym_alloc_symmetry(num_sym);
  for (i = 0; i < num_sym; i++) {
    mat_copy_matrix_i3(sym_reduced->rot[i], rot->mat[i]);
    mat_copy_vector_d3(sym_reduced->trans[i], trans->vec[i]);
  }

  mat_free_MatINT(rot);
  mat_free_VecDBL(trans);

  debug_print("  num_sym %d -> %d\n", symmetry->size, num_sym);

  return sym_reduced;
}
Example #2
0
/* Only the atoms corresponding to those in primitive are returned. */
static Cell * get_bravais_exact_positions_and_lattice(int * wyckoffs,
        int * equiv_atoms,
        SPGCONST Spacegroup *spacegroup,
        SPGCONST Cell * primitive,
        const double symprec)
{
    int i;
    Symmetry *conv_sym;
    Cell *bravais;
    VecDBL *exact_positions;

    /* Positions of primitive atoms are represented wrt Bravais lattice */
    bravais = get_conventional_primitive(spacegroup, primitive);
    /* Symmetries in database (wrt Bravais lattice) */
    conv_sym = get_db_symmetry(spacegroup->hall_number);
    /* Lattice vectors are set. */
    get_conventional_lattice(bravais->lattice,
                             spacegroup->holohedry,
                             spacegroup->bravais_lattice);

    /* Symmetrize atomic positions of conventional unit cell */
    exact_positions = ssm_get_exact_positions(wyckoffs,
                      equiv_atoms,
                      bravais,
                      conv_sym,
                      spacegroup->hall_number,
                      symprec);
    sym_free_symmetry(conv_sym);

    if (exact_positions->size > 0) {
        for (i = 0; i < bravais->size; i++) {
            mat_copy_vector_d3(bravais->position[i], exact_positions->vec[i]);
        }
    } else {
        cel_free_cell(bravais);
        bravais = cel_alloc_cell(0);
    }

    mat_free_VecDBL(exact_positions);

    return bravais;
}
Example #3
0
int spg_find_primitive( double lattice[3][3],
			double position[][3],
			int types[],
			const int num_atom,
			const double symprec )
{
  int i, j, num_prim_atom=0;
  int *mapping_table;
  Cell *cell, *primitive;
  VecDBL *pure_trans;

  cell = cel_alloc_cell( num_atom );
  cel_set_cell( cell, lattice, position, types );
  pure_trans = sym_get_pure_translation( cell, symprec );

  /* find primitive cell */
  if ( pure_trans->size > 1 ) {
    mapping_table = (int*) malloc( sizeof(int) * cell->size );
    primitive = prm_get_primitive( mapping_table, cell, pure_trans, symprec );
    free( mapping_table );
    mapping_table = NULL;
    num_prim_atom = primitive->size;
    if ( num_prim_atom < num_atom && num_prim_atom > 0  ) {
      mat_copy_matrix_d3( lattice, primitive->lattice );
      for ( i = 0; i < primitive->size; i++ ) {
	types[i] = primitive->types[i];
	for (j=0; j<3; j++) {
	  position[i][j] = primitive->position[i][j];
	}
      }
    }
    cel_free_cell( primitive );
  } else {
    num_prim_atom = 0;
  }

  mat_free_VecDBL( pure_trans );
  cel_free_cell( cell );
    
  return num_prim_atom;
}
Example #4
0
static Symmetry *
get_space_group_operations(SPGCONST PointSymmetry *lattice_sym,
			   SPGCONST Cell *cell,
			   const double symprec)
{
  int i, j, num_sym, total_num_sym;
  VecDBL **trans;
  Symmetry *symmetry;

  debug_print("get_space_group_operations:\n");
  
  trans = (VecDBL**) malloc(sizeof(VecDBL*) * lattice_sym->size);
  total_num_sym = 0;
  for (i = 0; i < lattice_sym->size; i++) {
    trans[i] = get_translation(lattice_sym->rot[i], cell, symprec, 0);
    total_num_sym += trans[i]->size;
  }

  symmetry = sym_alloc_symmetry(total_num_sym);
  num_sym = 0;
  for (i = 0; i < lattice_sym->size; i++) {
    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;
  }

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

  return symmetry;
}
Example #5
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 #6
0
/*    was not a primitive cell. */
static int get_operation( int rot[][3][3],
			  double trans[][3],
			  SPGCONST Cell *cell,
			  const double symprec )
{
  int num_sym;
  int multi;
  int *mapping_table;
  PointSymmetry lattice_sym;
  Cell *primitive;
  VecDBL *pure_trans;

  pure_trans = sym_get_pure_translation(cell, symprec);
  multi = pure_trans->size;

  /* Lattice symmetry for input cell*/
  lattice_sym = get_lattice_symmetry( cell, symprec );
  if ( lattice_sym.size == 0 ) {
    goto err;
  }

  /* Obtain primitive cell */
  if( multi > 1 ) {
    mapping_table = (int*) malloc( sizeof(int) * cell->size );
    primitive = prm_get_primitive( mapping_table, cell, pure_trans, symprec );
    free( mapping_table );
    mapping_table = NULL;

    if ( primitive->size < 1 ) { goto err; }

    lattice_sym = transform_pointsymmetry( &lattice_sym,
    					   primitive->lattice,
    					   cell->lattice );
    if ( lattice_sym.size == 0 ) { goto err; }
  } else {
    primitive = cell;
  }

  /* Symmetry operation search for primitive cell */
  num_sym = get_space_group_operation( rot, trans, &lattice_sym,
  				       primitive, symprec );

  /* Recover symmetry operation for the input structure (overwritten) */
  if( multi > 1 ) {
    num_sym = get_operation_supercell( rot,
  				       trans,
  				       num_sym,
  				       pure_trans,
  				       cell,
  				       primitive );
    cel_free_cell( primitive );
    if ( num_sym == 0 ) { goto err; }
  }

  mat_free_VecDBL( pure_trans );
  return num_sym;

 err:
  mat_free_VecDBL( pure_trans );
  return 0;
}
Example #7
0
/* Return NULL if failed */
static Primitive * get_primitive(SPGCONST Cell * cell, const double symprec)
{
    int i, attempt, is_found = 0;
    double tolerance;
    Primitive *primitive;
    VecDBL * pure_trans;

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

    primitive = NULL;
    pure_trans = NULL;

    if ((primitive = prm_alloc_primitive(cell->size)) == NULL) {
        return NULL;
    }

    tolerance = symprec;
    for (attempt = 0; attempt < 100; attempt++) {
        if ((pure_trans = sym_get_pure_translation(cell, tolerance)) == NULL) {
            printf("***** hoge ******\n");
            goto cont;
        }

        if (pure_trans->size == 1) {
            if ((primitive->cell = get_cell_with_smallest_lattice(cell, tolerance))
                    == NULL) {
                mat_free_VecDBL(pure_trans);
                goto cont;
            }

            for (i = 0; i < cell->size; i++) {
                primitive->mapping_table[i] = i;
            }
        } else {
            if ((primitive->cell = get_primitive_cell(primitive->mapping_table,
                                   cell,
                                   pure_trans,
                                   tolerance)) == NULL) {
                mat_free_VecDBL(pure_trans);
                goto cont;
            }
        }

        is_found = 1;
        break;

cont:
        tolerance *= REDUCE_RATE;
        warning_print("spglib: Reduce tolerance to %f ", tolerance);
        warning_print("(line %d, %s).\n", __LINE__, __FILE__);
    }

    mat_free_VecDBL(pure_trans);

    if (is_found) {
        primitive->tolerance = tolerance;
    } else {
        prm_free_primitive(primitive);
    }

    return primitive;
}
Example #8
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;
}
Example #9
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;
}
Example #10
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;
}
Example #11
0
/* Return NULL if failed */
static Symmetry * reduce_operation(SPGCONST Cell * primitive,
				   SPGCONST Symmetry * symmetry,
				   const double symprec,
				   const double angle_symprec)
{
  int i, j, num_sym;
  Symmetry * sym_reduced;
  PointSymmetry point_symmetry;
  MatINT *rot;
  VecDBL *trans;

  debug_print("reduce_operation:\n");

  sym_reduced = NULL;
  rot = NULL;
  trans = NULL;

  point_symmetry = get_lattice_symmetry(primitive->lattice,
					symprec,
					angle_symprec);
  if (point_symmetry.size == 0) {
    return NULL;
  }

  if ((rot = mat_alloc_MatINT(symmetry->size)) == NULL) {
    return NULL;
  }

  if ((trans = mat_alloc_VecDBL(symmetry->size)) == NULL) {
    mat_free_MatINT(rot);
    rot = NULL;
    return NULL;
  }

  num_sym = 0;
  for (i = 0; i < point_symmetry.size; i++) {
    for (j = 0; j < symmetry->size; j++) {
      if (mat_check_identity_matrix_i3(point_symmetry.rot[i],
				       symmetry->rot[j])) {
	if (is_overlap_all_atoms(symmetry->trans[j],
				 symmetry->rot[j],
				 primitive,
				 symprec,
				 0)) {
	  mat_copy_matrix_i3(rot->mat[num_sym], symmetry->rot[j]);
	  mat_copy_vector_d3(trans->vec[num_sym], symmetry->trans[j]);
	  num_sym++;
	}
      }
    }
  }

  if ((sym_reduced = sym_alloc_symmetry(num_sym)) != NULL) {
    for (i = 0; i < num_sym; i++) {
      mat_copy_matrix_i3(sym_reduced->rot[i], rot->mat[i]);
      mat_copy_vector_d3(sym_reduced->trans[i], trans->vec[i]);
    }
  }

  mat_free_MatINT(rot);
  rot = NULL;
  mat_free_VecDBL(trans);
  trans = NULL;

  return sym_reduced;
}
Example #12
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;
}
Example #13
0
SpglibDataset * spg_get_dataset( SPGCONST double lattice[3][3],
				 SPGCONST double position[][3],
				 const int types[],
				 const int num_atom,
				 const double symprec )
{
  int i, j;
  int *mapping_table, *wyckoffs, *equiv_atoms, *equiv_atoms_prim;
  Spacegroup spacegroup;
  SpglibDataset *dataset;
  Cell *cell, *primitive;
  double inv_mat[3][3];
  Symmetry *symmetry;
  VecDBL *pure_trans;

  dataset = (SpglibDataset*) malloc( sizeof( SpglibDataset ) );

  cell = cel_alloc_cell( num_atom );
  cel_set_cell( cell, lattice, position, types );

  pure_trans = sym_get_pure_translation( cell, symprec );
  mapping_table = (int*) malloc( sizeof(int) * cell->size );
  primitive = prm_get_primitive( mapping_table, cell, pure_trans, symprec );
  mat_free_VecDBL( pure_trans );

  spacegroup = spa_get_spacegroup_with_primitive( primitive, symprec );

  /* Spacegroup type, transformation matrix, origin shift */
  if ( spacegroup.number > 0 ) {
    dataset->spacegroup_number = spacegroup.number;
    strcpy( dataset->international_symbol, spacegroup.international_short);
    strcpy( dataset->hall_symbol, spacegroup.hall_symbol);
    mat_inverse_matrix_d3( inv_mat, lattice, symprec );
    mat_multiply_matrix_d3( dataset->transformation_matrix,
			    inv_mat,
			    spacegroup.bravais_lattice );
    mat_copy_vector_d3( dataset->origin_shift, spacegroup.origin_shift );
  }

  /* Wyckoff positions */
  wyckoffs = (int*) malloc( sizeof(int) * primitive->size );
  equiv_atoms_prim = (int*) malloc( sizeof(int) * primitive->size );
  for ( i = 0; i < primitive->size; i++ ) {
    wyckoffs[i] = -1;
    equiv_atoms_prim[i] = -1;
  }
  ref_get_Wyckoff_positions( wyckoffs, 
			     equiv_atoms_prim,
			     primitive,
			     &spacegroup,
			     symprec );
  dataset->n_atoms = cell->size;
  dataset->wyckoffs = (int*) malloc( sizeof(int) * cell->size ); 
  for ( i = 0; i < cell->size; i++ ) {
    dataset->wyckoffs[i] = wyckoffs[ mapping_table[i] ];
  }
  free( wyckoffs );
  wyckoffs = NULL;

  dataset->equivalent_atoms = (int*) malloc( sizeof(int) * cell->size );
  equiv_atoms = (int*) malloc( sizeof(int) * primitive->size );
  for ( i = 0; i < primitive->size; i++ ) {
    for ( j = 0; j < cell->size; j++ ) {
      if ( mapping_table[j] == equiv_atoms_prim[i] ) {
	equiv_atoms[i] = j;
	break;
      }
    }
  }
  for ( i = 0; i < cell->size; i++ ) {
    dataset->equivalent_atoms[i] = equiv_atoms[ mapping_table[i] ];
  }
  free( equiv_atoms );
  equiv_atoms = NULL;
  free( equiv_atoms_prim );
  equiv_atoms_prim = NULL;
  free( mapping_table );
  mapping_table = NULL;

  /* Symmetry operations */
  symmetry = ref_get_refined_symmetry_operations( cell,
						  primitive->lattice,
						  &spacegroup,
						  symprec );
  cel_free_cell( cell );
  cel_free_cell( primitive );

  dataset->rotations = (int (*)[3][3]) malloc(sizeof(int[3][3]) * symmetry->size );
  dataset->translations = (double (*)[3]) malloc(sizeof(double[3]) * symmetry->size );
  dataset->n_operations = symmetry->size;
  for ( i = 0; i < symmetry->size; i++ ) {
    mat_copy_matrix_i3( dataset->rotations[i], symmetry->rot[i] );
    mat_copy_vector_d3( dataset->translations[i], symmetry->trans[i] );
  }

  sym_free_symmetry( symmetry );

  return dataset;
}
Example #14
0
static Symmetry * get_collinear_operations(SPGCONST Symmetry *sym_nonspin,
					   SPGCONST Cell *cell,
					   const double spins[],
					   const double symprec)
{
  Symmetry *symmetry;
  int i, j, k, sign, is_found, num_sym;
  double pos[3];
  MatINT * rot;
  VecDBL * trans;

  rot = mat_alloc_MatINT(sym_nonspin->size);
  trans = mat_alloc_VecDBL(sym_nonspin->size);
  num_sym = 0;
  
  for (i = 0; i < sym_nonspin->size; i++) {
    sign = 0; /* Set sign as undetermined */
    is_found = 1;
    for (j = 0; j < cell->size; j++) {
      mat_multiply_matrix_vector_id3(pos, sym_nonspin->rot[i], cell->position[j]);
      for (k = 0; k < 3; k++) {
	pos[k] += sym_nonspin->trans[i][k];
      }
      for (k = 0; k < cell->size; k++) {
	if (cel_is_overlap(cell->position[k],
			   pos,
			   cell->lattice,
			   symprec)) {
	  if (sign == 0) {
	    if (mat_Dabs(spins[j] - spins[k]) < symprec) {
	      sign = 1;
	      break;
	    }
	    if (mat_Dabs(spins[j] + spins[k]) < symprec) {
	      sign = -1;
	      break;
	    }
	    is_found = 0;
	    break;
	  } else {
	    if (mat_Dabs(spins[j] - spins[k] * sign) < symprec) {
	      break;
	    } else {
	      is_found = 0;
	      break;
	    }
	  }
	}
      }
      if (! is_found) {
	break;
      }
    }
    if (is_found) {
      mat_copy_matrix_i3(rot->mat[num_sym], sym_nonspin->rot[i]);
      mat_copy_vector_d3(trans->vec[num_sym], sym_nonspin->trans[i]);
      num_sym++;
    }
  }

  symmetry = sym_alloc_symmetry(num_sym);
  for (i = 0; i < num_sym; i++) {
    mat_copy_matrix_i3(symmetry->rot[i], rot->mat[ i ]);
    mat_copy_vector_d3(symmetry->trans[i], trans->vec[ i ]);
  }

  mat_free_MatINT(rot);
  mat_free_VecDBL(trans);

  return symmetry;
}
Example #15
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;
}
Example #16
0
/* Return -1 if failed */
static int get_Wyckoff_notation(double position[3],
				SPGCONST Symmetry * conv_sym,
				SPGCONST double bravais_lattice[3][3],
				const int hall_number,
				const double symprec)
{
  int i, j, k, l, at_orbit, num_sitesym, wyckoff_letter;
  int indices_wyc[2];
  int rot[3][3];
  double trans[3], orbit[3];
  VecDBL *pos_rot;

  debug_print("get_Wyckoff_notation\n");

  wyckoff_letter = -1;
  pos_rot = NULL;

  if ((pos_rot = mat_alloc_VecDBL(conv_sym->size)) == NULL) {
    return -1;
  }

  for (i = 0; i < conv_sym->size; i++) {
    mat_multiply_matrix_vector_id3(pos_rot->vec[i], conv_sym->rot[i], position);
    for (j = 0; j < 3; j++) {
      pos_rot->vec[i][j] += conv_sym->trans[i][j];
    }
  }

  ssmdb_get_wyckoff_indices(indices_wyc, hall_number);
  for (i = 0; i < indices_wyc[1]; i++) {
    num_sitesym = ssmdb_get_coordinate(rot, trans, i + indices_wyc[0]);
    for (j = 0; j < pos_rot->size; j++) {
      at_orbit = 0;
      for (k = 0; k < pos_rot->size; k++) {
	if (cel_is_overlap(pos_rot->vec[j],
			   pos_rot->vec[k],
			   bravais_lattice,
			   symprec)) {
	  mat_multiply_matrix_vector_id3(orbit, rot, pos_rot->vec[k]);
	  for (l = 0; l < 3; l++) {
	    orbit[l] += trans[l];
	  }
	  if (cel_is_overlap(pos_rot->vec[k],
			     orbit,
			     bravais_lattice,
			     symprec)) {
	    at_orbit++;
	  }
	}
      }
      if (at_orbit == conv_sym->size / num_sitesym) {
	/* Database is made reversed order, e.g., gfedcba. */
	/* wyckoff is set 0 1 2 3 4... for a b c d e..., respectively. */
	wyckoff_letter = indices_wyc[1] - i - 1;
	goto end;
      }
    }
  }

 end:
  mat_free_VecDBL(pos_rot);
  return wyckoff_letter;
}
Example #17
0
/* Return if failed */
VecDBL * ssm_get_exact_positions(int *wyckoffs,
                                 int *equiv_atoms,
                                 const Cell * conv_prim,
                                 const Symmetry * conv_sym,
                                 const int hall_number,
                                 const double symprec)
{
  int attempt, num_atoms;
  double tolerance;
  VecDBL *positions;

  positions = NULL;

  if ((positions = mat_alloc_VecDBL(conv_prim->size)) == NULL) {
    return NULL;
  }

  tolerance = symprec;
  for (attempt = 0; attempt < NUM_ATTEMPT; attempt++) {
    num_atoms = get_exact_positions(positions,
                                    equiv_atoms,
                                    conv_prim,
                                    conv_sym,
                                    tolerance);
    if (num_atoms == conv_prim->size) {
      goto succeeded;
    }

    if (num_atoms > conv_prim->size || num_atoms == 0) {
      tolerance *= INCREASE_RATE;
      warning_print("spglib: Some site-symmetry is found broken. ");
      warning_print("(%d != %d)\n", num_atoms, conv_prim->size);
      warning_print("        Increase tolerance to %f", tolerance);
      warning_print(" (%d)", attempt);
      warning_print(" (line %d, %s).\n", __LINE__, __FILE__);
    }

    if (num_atoms < conv_prim->size && num_atoms) {
      tolerance *= REDUCE_RATE;
      warning_print("spglib: Some site-symmetry is found broken. ");
      warning_print("(%d != %d)\n", num_atoms, conv_prim->size);
      warning_print("        Reduce tolerance to %f", tolerance);
      warning_print(" (%d)", attempt);
      warning_print(" (line %d, %s).\n", __LINE__, __FILE__);
    }
  }

  mat_free_VecDBL(positions);
  positions = NULL;
  return NULL;

 succeeded:
  if (! set_Wyckoffs_labels(wyckoffs,
                            positions,
                            equiv_atoms,
                            conv_prim,
                            conv_sym,
                            hall_number,
                            symprec)) {
    mat_free_VecDBL(positions);
    positions = NULL;
  }

  return positions;
}
Example #18
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;
}
Example #19
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;
}
Example #20
0
/* Return 0 if failed */
static int get_primitive_lattice_vectors_iterative(double prim_lattice[3][3],
						   SPGCONST Cell * cell,
						   const VecDBL * pure_trans,
						   const double symprec)
{
  int i, multi, attempt;
  double tolerance;
  VecDBL * vectors, * pure_trans_reduced, *tmp_vec;

  vectors = NULL;
  pure_trans_reduced = NULL;
  tmp_vec = NULL;

  tolerance = symprec;

  if ((pure_trans_reduced = mat_alloc_VecDBL(pure_trans->size)) == NULL) {
    goto fail;
  }

  for (i = 0; i < pure_trans->size; i++) {
    mat_copy_vector_d3(pure_trans_reduced->vec[i], pure_trans->vec[i]);
  }
  
  for (attempt = 0; attempt < 100; attempt++) {
    multi = pure_trans_reduced->size;

    if ((vectors = get_translation_candidates(pure_trans_reduced)) == NULL) {
      mat_free_VecDBL(pure_trans_reduced);
      goto fail;
    }

    /* Lattice of primitive cell is found among pure translation vectors */
    if (get_primitive_lattice_vectors(prim_lattice,
				      vectors,
				      cell,
				      tolerance)) {

      mat_free_VecDBL(vectors);
      mat_free_VecDBL(pure_trans_reduced);

      goto found;

    } else {

      if ((tmp_vec = mat_alloc_VecDBL(multi)) == NULL) {
	mat_free_VecDBL(vectors);
	mat_free_VecDBL(pure_trans_reduced);
	goto fail;
      }

      for (i = 0; i < multi; i++) {
	mat_copy_vector_d3(tmp_vec->vec[i], pure_trans_reduced->vec[i]);
      }
      mat_free_VecDBL(pure_trans_reduced);

      pure_trans_reduced = sym_reduce_pure_translation(cell,
						       tmp_vec,
						       tolerance);

      mat_free_VecDBL(tmp_vec);
      mat_free_VecDBL(vectors);

      if (pure_trans_reduced == NULL) {
	goto fail;
      }

      warning_print("Tolerance is reduced to %f (%d), size = %d\n",
		    tolerance, attempt, pure_trans_reduced->size);

      tolerance *= REDUCE_RATE;
    }
  }

  mat_free_VecDBL(pure_trans_reduced);

 fail:
  return 0;

 found:
  return multi;
}
Example #21
0
/* Return NULL if failed */
static Cell *
get_bravais_exact_positions_and_lattice(int * wyckoffs,
					int * equiv_atoms,
					SPGCONST Spacegroup *spacegroup,
					SPGCONST Cell * primitive,
					const double symprec)
{
  int i;
  int *wyckoffs_prim, *equiv_atoms_prim;
  Symmetry *conv_sym;
  Cell *bravais, *conv_prim;
  VecDBL *exact_positions;

  debug_print("get_bravais_exact_positions_and_lattice\n");

  wyckoffs_prim = NULL;
  equiv_atoms_prim = NULL;
  conv_prim = NULL;
  bravais = NULL;
  conv_sym = NULL;
  exact_positions = NULL;

  /* Symmetrize atomic positions of conventional unit cell */
  if ((wyckoffs_prim = (int*)malloc(sizeof(int) * primitive->size)) == NULL) {
    warning_print("spglib: Memory could not be allocated ");
    return NULL;
  }

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

  for (i = 0; i < primitive->size; i++) {
    wyckoffs_prim[i] = -1;
    equiv_atoms_prim[i] = -1;
  }

  /* Positions of primitive atoms are represented wrt Bravais lattice */
  if ((conv_prim = get_conventional_primitive(spacegroup, primitive)) == NULL) {
    free(wyckoffs_prim);
    wyckoffs_prim = NULL;
    free(equiv_atoms_prim);
    equiv_atoms_prim = NULL;
    return NULL;
  }

  /* Symmetries in database (wrt Bravais lattice) */
  if ((conv_sym = spgdb_get_spacegroup_operations(spacegroup->hall_number))
      == NULL) {
    goto err;
  }

  /* Lattice vectors are set. */
  get_conventional_lattice(conv_prim->lattice, spacegroup);

  if ((exact_positions = ssm_get_exact_positions(wyckoffs_prim,
						 equiv_atoms_prim,
						 conv_prim,
						 conv_sym,
						 spacegroup->hall_number,
						 symprec)) == NULL) {
    sym_free_symmetry(conv_sym);
    conv_sym = NULL;
    goto err;
  }

  for (i = 0; i < conv_prim->size; i++) {
    mat_copy_vector_d3(conv_prim->position[i], exact_positions->vec[i]);
  }

  bravais = expand_positions(wyckoffs,
			     equiv_atoms,
			     conv_prim,
			     conv_sym,
			     wyckoffs_prim,
			     equiv_atoms_prim);

  mat_free_VecDBL(exact_positions);
  exact_positions = NULL;
  sym_free_symmetry(conv_sym);
  conv_sym = NULL;
 err:
  free(wyckoffs_prim);
  wyckoffs_prim = NULL;
  free(equiv_atoms_prim);
  equiv_atoms_prim = NULL;
  cel_free_cell(conv_prim);
  conv_prim = NULL;

  return bravais;
}