Esempio n. 1
0
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;
}
Esempio n. 2
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];
  }

}
Esempio n. 3
0
/* This function is heaviest in this code. */
static VecDBL * get_translation( SPGCONST int rot[3][3],
				 SPGCONST Cell *cell,
				 const double symprec,
				 const int is_identity )
{
  int i, j, min_atom_index, num_trans = 0;
  int *is_found;
  double origin[3];
  VecDBL *tmp_trans, *trans;

  tmp_trans = mat_alloc_VecDBL( cell->size );
  is_found = (int*) malloc( sizeof(int)*cell->size);
  for ( i = 0; i < cell->size; i++ ) {
    is_found[i] = 0;
  }

  /* Look for the atom index with least number of atoms within same type */
  min_atom_index = get_index_with_least_atoms( cell );

  /* Set min_atom_index as the origin to measure the distance between atoms. */
  mat_multiply_matrix_vector_id3(origin, rot, cell->position[min_atom_index]);

  
#pragma omp parallel for private( j )
  for (i = 0; i < cell->size; i++) {	/* test translation */
    if (cell->types[i] != cell->types[min_atom_index]) {
      continue;
    }

    for (j = 0; j < 3; j++) {
      tmp_trans->vec[i][j] = cell->position[i][j] - origin[j];
    }
    if ( is_overlap_all_atoms( tmp_trans->vec[i],
			       rot,
			       cell,
			       symprec,
			       is_identity ) ) {
      is_found[i] = 1;
    }
  }

  for ( i = 0; i < cell->size; i++ ) {
    num_trans += is_found[i];
  }
  trans = mat_alloc_VecDBL( num_trans );
  num_trans = 0;
  for ( i = 0; i < cell->size; i++ ) {
    if ( is_found[i] ) {
      mat_copy_vector_d3( trans->vec[num_trans], tmp_trans->vec[i] );
      num_trans++;
    }
  }

  mat_free_VecDBL( tmp_trans );
  free( is_found );
  is_found = NULL;
  
  return trans;
}
Esempio n. 4
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;
}
Esempio n. 5
0
/* 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;
}
Esempio n. 6
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;
}
Esempio n. 7
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;
}
Esempio n. 8
0
static void set_translation_with_origin_shift(Symmetry *conv_sym,
        const double origin_shift[3])
{
    int i, j;
    double tmp_vec[3];
    int tmp_mat[3][3];

    /* t' = t - (R-E)w, w is the origin shift */
    for (i = 0; i < conv_sym->size; i++) {
        mat_copy_matrix_i3(tmp_mat, conv_sym->rot[i]);
        tmp_mat[0][0]--;
        tmp_mat[1][1]--;
        tmp_mat[2][2]--;
        mat_multiply_matrix_vector_id3(tmp_vec, tmp_mat, origin_shift);
        for (j = 0; j < 3; j++) {
            conv_sym->trans[i][j] -= tmp_vec[j];
        }
    }
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
static int set_equivalent_atom(VecDBL *positions,
                               int * equiv_atoms,
                               const int i,
                               const int num_indep_atoms,
                               const int *indep_atoms,
                               const Cell * conv_prim,
                               const Symmetry * conv_sym,
                               const double symprec)
{
  int j, k, l;
  double pos[3];

  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_with_same_type(pos,
                                        conv_prim->position[i],
                                        conv_prim->types[indep_atoms[j]],
                                        conv_prim->types[i],
                                        conv_prim->lattice,
                                        symprec)) {
        for (l = 0; l < 3; l++) {
          positions->vec[i][l] = mat_Dmod1(pos[l]);
        }
        equiv_atoms[i] = indep_atoms[j];
        return 1;
      }
    }
  }

  return 0;
}
Esempio n. 11
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;
}
Esempio n. 12
0
/* This function is heaviest in this code. */
static VecDBL * get_translation(SPGCONST int rot[3][3],
				SPGCONST Cell *cell,
				const double symprec,
				const int is_identity)
{
  int i, j, min_atom_index, num_trans = 0;
  int *is_found;
  double origin[3];
  VecDBL *trans;

#ifdef _OPENMP
  int num_min_type_atoms;
  int *min_type_atoms;
  double vec[3];
#endif

  is_found = (int*) malloc(sizeof(int)*cell->size);
  for (i = 0; i < cell->size; i++) {
    is_found[i] = 0;
  }

  /* Look for the atom index with least number of atoms within same type */
  min_atom_index = get_index_with_least_atoms(cell);

  /* Set min_atom_index as the origin to measure the distance between atoms. */
  mat_multiply_matrix_vector_id3(origin, rot, cell->position[min_atom_index]);

#ifdef _OPENMP
  if (cell->size < NUM_ATOMS_CRITERION_FOR_OPENMP) {
    search_translation_part(is_found,
			    cell,
			    rot,
			    min_atom_index,
			    origin,
			    symprec,
			    is_identity);
  } else {
    /* Collect indices of atoms with the type where the minimum number */
    /* of atoms belong. */
    min_type_atoms = (int*) malloc(sizeof(int)*cell->size);
    num_min_type_atoms = 0;
    for (i = 0; i < cell->size; i++) {
      if (cell->types[i] == cell->types[min_atom_index]) {
	min_type_atoms[num_min_type_atoms] = i;
	num_min_type_atoms++;
      }
    }
#pragma omp parallel for private(j, vec)
    for (i = 0; i < num_min_type_atoms; i++) {
      for (j = 0; j < 3; j++) {
	vec[j] = cell->position[min_type_atoms[i]][j] - origin[j];
      }
      if (is_overlap_all_atoms(vec,
			       rot,
			       cell,
			       symprec,
			       is_identity)) {
	is_found[min_type_atoms[i]] = 1;
      }
    }

    free(min_type_atoms);
  }
#else
  search_translation_part(is_found,
			  cell,
			  rot,
			  min_atom_index,
			  origin,
			  symprec,
			  is_identity);
#endif

  
  for (i = 0; i < cell->size; i++) {
    num_trans += is_found[i];
  }
  trans = mat_alloc_VecDBL(num_trans);
  num_trans = 0;
  for (i = 0; i < cell->size; i++) {
    if (is_found[i]) {
      for (j = 0; j < 3; j++) {
	trans->vec[num_trans][j] = cell->position[i][j] - origin[j];
      }
      num_trans++;
    }
  }

  free(is_found);
  is_found = NULL;
  
  return trans;
}
Esempio n. 13
0
/* Return NULL if failed */
static VecDBL * get_translation(SPGCONST int rot[3][3],
				SPGCONST Cell *cell,
				const double symprec,
				const int is_identity)
{
  int i, j, k, min_atom_index, num_trans;
  int *is_found;
  double origin[3];
  VecDBL *trans;

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

  num_trans = 0;
  is_found = NULL;
  trans = NULL;

#ifdef _OPENMP
  int num_min_type_atoms;
  int *min_type_atoms;
  double vec[3];

  min_type_atoms = NULL;
#endif

  if ((is_found = (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[i] = 0;
  }

  /* Look for the atom index with least number of atoms within same type */
  min_atom_index = get_index_with_least_atoms(cell);
  if (min_atom_index == -1) {
    debug_print("spglib: get_index_with_least_atoms failed.\n");
    goto ret;
  }

  /* Set min_atom_index as the origin to measure the distance between atoms. */
  mat_multiply_matrix_vector_id3(origin, rot, cell->position[min_atom_index]);

#ifdef _OPENMP
  if (cell->size < NUM_ATOMS_CRITERION_FOR_OPENMP) {
    num_trans = search_translation_part(is_found,
					cell,
					rot,
					min_atom_index,
					origin,
					symprec,
					is_identity);
    if (num_trans == 0) {
      goto ret;
    }
  } else {
    /* Collect indices of atoms with the type where the minimum number */
    /* of atoms belong. */
    if ((min_type_atoms = (int*) malloc(sizeof(int)*cell->size)) == NULL) {
      warning_print("spglib: Memory could not be allocated ");
      goto ret;
    }

    num_min_type_atoms = 0;
    for (i = 0; i < cell->size; i++) {
      if (cell->types[i] == cell->types[min_atom_index]) {
	min_type_atoms[num_min_type_atoms] = i;
	num_min_type_atoms++;
      }
    }
#pragma omp parallel for private(j, vec)
    for (i = 0; i < num_min_type_atoms; i++) {
      for (j = 0; j < 3; j++) {
	vec[j] = cell->position[min_type_atoms[i]][j] - origin[j];
      }
      if (is_overlap_all_atoms(vec,
			       rot,
			       cell,
			       symprec,
			       is_identity)) {
	is_found[min_type_atoms[i]] = 1;
      }
    }

    free(min_type_atoms);
    min_type_atoms = NULL;

    for (i = 0; i < cell->size; i++) {
      num_trans += is_found[i];
    }
  }
#else
  num_trans = search_translation_part(is_found,
				      cell,
				      rot,
				      min_atom_index,
				      origin,
				      symprec,
				      is_identity);
  if (num_trans == 0) {
    goto ret;
  }
#endif

  if ((trans = mat_alloc_VecDBL(num_trans)) == NULL) {
    goto ret;
  }

  k = 0;
  for (i = 0; i < cell->size; i++) {
    if (is_found[i]) {
      for (j = 0; j < 3; j++) {
	trans->vec[k][j] = cell->position[i][j] - origin[j];
      }
      k++;
    }
  }

 ret:
  free(is_found);
  is_found = NULL;

  return trans;
}
Esempio n. 14
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;
}
Esempio n. 15
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;
}
Esempio n. 16
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;
  }
}