コード例 #1
0
ファイル: site_symmetry.c プロジェクト: ATNDiaye/pymatgen
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=-1;
  int indices_wyc[2];
  int rot[3][3];
  double trans[3], orbit[3];
  VecDBL *pos_rot;

  pos_rot = mat_alloc_VecDBL(conv_sym->size);
  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;
}
コード例 #2
0
ファイル: site_symmetry.c プロジェクト: hautierg/pymatgen
/* 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];
  }

}
コード例 #3
0
ファイル: refinement.c プロジェクト: etp12/avogadro
static VecDBL * reduce_lattice_points(SPGCONST double lattice[3][3],
                                      const VecDBL *lattice_trans,
                                      const double symprec)
{
    int i, j, is_found, num_pure_trans;
    VecDBL *pure_trans, *t;

    num_pure_trans = 0;
    t = mat_alloc_VecDBL(lattice_trans->size);
    for (i = 0; i < lattice_trans->size; i++) {
        is_found = 0;
        for (j = 0; j < num_pure_trans; 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_pure_trans], lattice_trans->vec[i]);
            num_pure_trans++;
        }
    }

    pure_trans = mat_alloc_VecDBL(num_pure_trans);
    for (i = 0; i < num_pure_trans; i++) {
        mat_copy_vector_d3(pure_trans->vec[i], t->vec[i]);
    }
    mat_free_VecDBL(t);

    return pure_trans;
}
コード例 #4
0
ファイル: primitive.c プロジェクト: vanceeasleaf/phonopy
/* Return 0 if failed */
static int get_overlap_table(int **overlap_table,
                             SPGCONST Cell *primitive_cell,
                             const VecDBL * position,
                             const int *types,
                             const double symprec)
{
    int i, j, attempt, num_overlap, ratio, cell_size;
    double trim_tolerance;

    cell_size = position->size;
    ratio = cell_size / primitive_cell->size;
    trim_tolerance = symprec;

    for (attempt = 0; attempt < 100; attempt++) {
        /* Each value of -1 has to be overwritten by 0 or positive numbers. */
        for (i = 0; i < cell_size; i++) {
            for (j = 0; j < cell_size; j++) {
                overlap_table[i][j] = -1;
            }
        }

        for (i = 0; i < cell_size; i++) {
            num_overlap = 0;
            for (j = 0; j < cell_size; j++) {
                if (types[i] == types[j]) {
                    if (cel_is_overlap(position->vec[i],
                                       position->vec[j],
                                       primitive_cell->lattice,
                                       trim_tolerance)) {
                        overlap_table[i][num_overlap] = j;
                        num_overlap++;
                    }
                }
            }
        }

        if (check_overlap_table(overlap_table, cell_size, ratio)) {
            goto found;
        }

        if (num_overlap < ratio) {
            trim_tolerance *= INCREASE_RATE;
            warning_print("spglib: Increase tolerance to %f ", trim_tolerance);
        } else {
            trim_tolerance *= REDUCE_RATE;
            warning_print("spglib: Reduce tolerance to %f ", trim_tolerance);
        }
        warning_print("(line %d, %s).\n", __LINE__, __FILE__);
    }

    warning_print("spglib: Could not trim cell into primitive ");
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);
    return 0;

found:
    return 1;

}
コード例 #5
0
ファイル: spin.c プロジェクト: vanceeasleaf/phonopy
/* Return 0 if failed */
static int set_equivalent_atoms(int * equiv_atoms,
				SPGCONST Symmetry *symmetry,
				SPGCONST Cell * cell,
				const double symprec)
{
  int i, j, k, is_found;
  double pos[3];
  int *mapping_table;

  mapping_table = NULL;

  if ((mapping_table = get_mapping_table(symmetry, cell, symprec)) == NULL) {
    return 0;
  }
  
  for (i = 0; i < cell->size; i++) {
    if (mapping_table[i] != i) {
      continue;
    }
    is_found = 0;
    for (j = 0; j < symmetry->size; j++) {
      mat_multiply_matrix_vector_id3(pos,
				     symmetry->rot[j],
				     cell->position[i]);
      for (k = 0; k < 3; k++) {
	pos[k] += symmetry->trans[j][k];
      }
      for (k = 0; k < cell->size; k++) {
	if (cel_is_overlap(pos, cell->position[k], cell->lattice, symprec)) {
	  if (mapping_table[k] < i) {
	    equiv_atoms[i] = equiv_atoms[mapping_table[k]];
	    is_found = 1;
	    break;
	  }
	}
      }
      if (is_found) {
	break;
      }
    }
    if (!is_found) {
      equiv_atoms[i] = i;
    }
  }

  for (i = 0; i < cell->size; i++) {
    if (mapping_table[i] == i) {
      continue;
    }
    equiv_atoms[i] = equiv_atoms[mapping_table[i]];
  }

  free(mapping_table);
  mapping_table = NULL;

  return 1;
}
コード例 #6
0
ファイル: cell.c プロジェクト: dlonie/XtalComp
int cel_is_overlap_with_same_type(const double a[3],
                                  const double b[3],
                                  const int type_a,
                                  const int type_b,
                                  SPGCONST double lattice[3][3],
                                  const double symprec)
{
  if (type_a == type_b) {
    return cel_is_overlap(a, b, lattice, symprec);
  } else {
    return 0;
  }
}
コード例 #7
0
ファイル: cell.c プロジェクト: dlonie/XtalComp
/* 0: No overlap of atoms was found. */
int cel_any_overlap(const Cell * cell,
                    const double symprec) {
  int i, j;

  for (i = 0; i < cell->size; i++) {
    for (j = i + 1; j < cell->size; j++) {
      if (cel_is_overlap(cell->position[i],
                         cell->position[j],
                         cell->lattice,
                         symprec)) {
        return 1;
      }
    }
  }
  return 0;
}
コード例 #8
0
ファイル: spin.c プロジェクト: vanceeasleaf/phonopy
/* Return NULL if failed */
static int * get_mapping_table(SPGCONST Symmetry *symmetry,
			       SPGCONST Cell * cell,
			       const double symprec)
{
  int i, j, k, is_found;
  double pos[3];
  int *mapping_table;
  SPGCONST int I[3][3] = {{ 1, 0, 0},
			  { 0, 1, 0},
			  { 0, 0, 1}};

  mapping_table = NULL;

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

  for (i = 0; i < cell->size; i++) {
    is_found = 0;
    for (j = 0; j < symmetry->size; j++) {
      if (mat_check_identity_matrix_i3(symmetry->rot[j], I)) {
	for (k = 0; k < 3; k++) {
	  pos[k] = cell->position[i][k] + symmetry->trans[j][k];
	}
	for (k = 0; k < cell->size; k++) {
	  if (cel_is_overlap(pos, cell->position[k], cell->lattice, symprec)) {
	    if (k < i) {
	      mapping_table[i] = mapping_table[k];
	      is_found = 1;
	      break;
	    }
	  }
	}
      }
      if (is_found) {
	break;
      }
    }
    if (!is_found) {
      mapping_table[i] = i;
    }
  }

  return mapping_table;
}
コード例 #9
0
ファイル: refinement.c プロジェクト: WeiLiPenguin/pymatgen
static int search_equivalent_atom(const int atom_index,
				  SPGCONST Cell * cell,
				  const Symmetry *symmetry,
				  const double symprec)
{
  int i, j;
  double pos_rot[3];

  for (i = 0; i < symmetry->size; i++) {
    mat_multiply_matrix_vector_id3(pos_rot,
				   symmetry->rot[i],
				   cell->position[atom_index]);
    for (j = 0; j < 3; j++) {
      pos_rot[j] += symmetry->trans[i][j];
    }
    for (j = 0; j < atom_index; j++) {
      if (cel_is_overlap(cell->position[j], pos_rot, cell->lattice, symprec)) {
	return j;
      }
    }
  }
  return atom_index;
}
コード例 #10
0
ファイル: site_symmetry.c プロジェクト: ATNDiaye/pymatgen
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;
}
コード例 #11
0
ファイル: refinement.c プロジェクト: alexurba/cftb
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;
}
コード例 #12
0
ファイル: cell.c プロジェクト: dlonie/XtalComp
/* Return NULL if failed */
static int * get_overlap_table(const VecDBL * position,
                               const int cell_size,
                               const int * cell_types,
                               const Cell * trimmed_cell,
                               const double symprec)
{
  int i, j, attempt, num_overlap, ratio;
  double trim_tolerance;
  int *overlap_table;

  trim_tolerance = symprec;

  ratio = cell_size / trimmed_cell->size;

  if ((overlap_table = (int*)malloc(sizeof(int) * cell_size)) == NULL) {
    return NULL;
  }

  for (attempt = 0; attempt < NUM_ATTEMPT; attempt++) {
    for (i = 0; i < cell_size; i++) {
      overlap_table[i] = i;
      for (j = 0; j < cell_size; j++) {
        if (cell_types[i] == cell_types[j]) {
          if (cel_is_overlap(position->vec[i],
                             position->vec[j],
                             trimmed_cell->lattice,
                             trim_tolerance)) {
            if (overlap_table[j] == j) {
              overlap_table[i] = j;
              break;
            }
          }
        }
      }
    }

    for (i = 0; i < cell_size; i++) {
      if (overlap_table[i] != i) {
        continue;
      }

      num_overlap = 0;
      for (j = 0; j < cell_size; j++) {
        if (i == overlap_table[j]) {
          num_overlap++;
        }
      }

      if (num_overlap == ratio) {
        continue;
      }

      if (num_overlap < ratio) {
        trim_tolerance *= INCREASE_RATE;
        warning_print("spglib: Increase tolerance to %f ", trim_tolerance);
        warning_print("(line %d, %s).\n", __LINE__, __FILE__);
        goto cont;
      }
      if (num_overlap > ratio) {
        trim_tolerance *= REDUCE_RATE;
        warning_print("spglib: Reduce tolerance to %f ", trim_tolerance);
        warning_print("(%d) ", attempt);
        warning_print("(line %d, %s).\n", __LINE__, __FILE__);
        goto cont;
      }
    }

    goto found;

  cont:
    ;
  }

  warning_print("spglib: Could not trim cell well ");
  warning_print("(line %d, %s).\n", __LINE__, __FILE__);
  free(overlap_table);
  overlap_table = NULL;

found:
  return overlap_table;
}
コード例 #13
0
ファイル: primitive.c プロジェクト: alexurba/cftb
static int get_overlap_table( int **overlap_table,
			      const int cell_size,
			      SPGCONST Cell *primitive,
			      const VecDBL * position,
			      const double symprec )
{
  int i, j, is_found, attempt, count, ratio;
  int count_error=0, old_count_error=0;
  double trim_tolerance, tol_adjust;

  ratio = cell_size / primitive->size;
  
  trim_tolerance = symprec;
  tol_adjust = trim_tolerance/2.0;

  is_found = 0;

  /* Break when is_found */
  for ( attempt = 0; attempt < 1000; attempt++ ) {
    is_found = 1;
    debug_print("Trim attempt %d: tolerance=%f\n",attempt+1,trim_tolerance);

    /* Each value of -1 has to be overwritten by 0 or positive numbers. */
    for (i = 0; i < cell_size; i++) {
      for (j = 0; j < cell_size; j++) {
        overlap_table[i][j] = -1;
      }
    }

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

      count = 0;
      for (j = 0; j < cell_size; j++) {
        if ( cel_is_overlap( position->vec[i], position->vec[j],
			     primitive->lattice, trim_tolerance ) ) {
          overlap_table[i][count] = j;
          count++;
        }
      }

      /* Adjust tolerance to avoid too much and too few overlaps */
      if (count != ratio) { /* check overlapping number */
        count_error = count - ratio;

        /* Initialize count error if needed: */
        if (old_count_error == 0) {
          old_count_error = count - ratio;
        }

        /* Adjust the tolerance adjustment if needed */
        if ( ( old_count_error > 0 && count_error < 0 ) ||
             ( old_count_error < 0 && count_error > 0 ) ||
             trim_tolerance - tol_adjust <= 0 ) {
          tol_adjust /= 2.0;
        }
        old_count_error = count_error;

        debug_print("Bad tolerance: count=%d ratio=%d tol_adjust=%f\n",
		    count,ratio,tol_adjust);

        if ( count_error > 0 ) { trim_tolerance -= tol_adjust; }
        else { trim_tolerance += tol_adjust; }          

	is_found = 0;
	break;
      }
    }
    if ( is_found ) { break; }
  }
  
  if ( ! is_found ) {
    warning_print("spglib: Could not trim cell into primitive ");
    warning_print("(line %d, %s).\n", __LINE__, __FILE__);
    goto err;
  }

  return 1;

 err:
  return 0;
}
コード例 #14
0
ファイル: spin.c プロジェクト: vanceeasleaf/phonopy
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;
}
コード例 #15
0
ファイル: site_symmetry.c プロジェクト: dlonie/XtalComp
/* 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;
  }
}