Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests for noncollinear case and spg_get_symmetry_with_site_tensors of fortran interface #342

Merged
merged 5 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
54 changes: 53 additions & 1 deletion test/functional/c/test_magnetic_symmetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ TEST(MagneticSymmetry, test_spgms_get_magnetic_dataset_high_mag_symprec) {
double mag_symprec = 1e-1; // with high mag_symprec

int size;
int equivalent_atoms[3];
int equivalent_atoms[6];
LecrisUT marked this conversation as resolved.
Show resolved Hide resolved
double primitive_lattice[3][3];
int(*rotations)[3][3];
double(*translations)[3];
Expand Down Expand Up @@ -421,6 +421,58 @@ TEST(MagneticSymmetry, test_spgms_get_magnetic_dataset_high_mag_symprec) {
if (dataset != NULL) spg_free_magnetic_dataset(dataset);
}

TEST(MagneticSymmetry, test_spg_get_magnetic_dataset_non_collinear) {
double lattice[3][3] = {{10, 0, 0}, {0, 10, 0}, {0, 0, 10}};
double position[][3] = {
{0, 0, 0},
};
int types[] = {1};
double spins[3] = {1, 0, 0};
int num_atom = 1;
SpglibMagneticDataset *dataset;
dataset = spg_get_magnetic_dataset(lattice, position, types, spins, 1,
num_atom, 1, 1e-5);

ASSERT_TRUE(dataset->n_operations == 16);
show_spg_magnetic_dataset(dataset);
spg_free_magnetic_dataset(dataset);
atztogo marked this conversation as resolved.
Show resolved Hide resolved
}

TEST(MagneticSymmetry, test_spg_get_symmetry_with_site_tensors_non_collinear) {
double lattice[3][3] = {{10, 0, 0}, {0, 10, 0}, {0, 0, 10}};
double position[][3] = {
{0, 0, 0},
};
int types[] = {1};
double tensors[3] = {1, 0, 0};
int num_atoms = 1;
int max_size = num_atoms * 96;
LecrisUT marked this conversation as resolved.
Show resolved Hide resolved

int size;
int equivalent_atoms[1];
double primitive_lattice[3][3];
int(*rotations)[3][3];
double(*translations)[3];
int *spin_flips;
int *time_reversals;

rotations = (int(*)[3][3])malloc(sizeof(int[3][3]) * max_size);
translations = (double(*)[3])malloc(sizeof(double[3]) * max_size);
spin_flips = (int *)malloc(sizeof(int *) * max_size);
time_reversals = (int *)malloc(sizeof(int *) * max_size);

size = spg_get_symmetry_with_site_tensors(
rotations, translations, equivalent_atoms, primitive_lattice,
spin_flips, max_size, lattice, position, types, tensors, 1, num_atoms,
1 /* with_time_reversal */, 1 /* is_axial */, 1e-5);

ASSERT_TRUE(size == 16);
free(rotations);
free(translations);
free(spin_flips);
free(time_reversals);
}

TEST(MagneticSymmetry, test_with_broken_symmetry) {
// https://github.com/spglib/spglib/issues/194
// Part of "mp-806965" in the Materials Project database
Expand Down
7 changes: 7 additions & 0 deletions test/functional/fortran/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@ set(SubTests_test_fortran_spg_get_spacegroup_type
set(SubTests_test_fortran_spg_get_magnetic_dataset
test_rutile_type_III
test_Cr_type_IV
test_magnetic_dataset_non_collinear
)
set(SubTests_test_fortran_spg_get_magnetic_spacegroup_type
test_magnetic_spacegroup_type_Cr
)
set(SubTests_test_fortran_spg_get_symmetry_with_site_tensors
test_site_tensors_rutile_type_III
test_site_tensors_Cr_type_IV
test_site_tensors_non_collinear
)

# Add fortran tests here
create_test_sourcelist(FortranTests_Files
Expand All @@ -32,6 +38,7 @@ create_test_sourcelist(FortranTests_Files
test_fortran_spg_get_dataset.F90
test_fortran_spg_get_magnetic_spacegroup_type.F90
test_fortran_spg_get_magnetic_dataset.F90
test_fortran_spg_get_symmetry_with_site_tensors.F90
test_fortran_spg_get_symmetry.F90
test_fortran_spg_refine_cell.F90)
# Define any subtests (would be nice to auto-detect them like Catch2)
Expand Down
38 changes: 33 additions & 5 deletions test/functional/fortran/test_fortran_spg_get_magnetic_dataset.F90
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ function test_fortran_spg_get_magnetic_dataset(argc, argv) bind(C) result(ret)
call test_rutile_type_III()
write (output_unit, *) "test_Cr_type_IV"
call test_Cr_type_IV()
write (output_unit, *) "test_magnetic_dataset_non_collinear"
call test_magnetic_dataset_non_collinear()
else
len = c_strlen(argv(2))
allocate (character(len=len) :: str)
Expand All @@ -28,6 +30,8 @@ function test_fortran_spg_get_magnetic_dataset(argc, argv) bind(C) result(ret)
call test_rutile_type_III()
case ("test_Cr_type_IV")
call test_Cr_type_IV()
case ("test_magnetic_dataset_non_collinear")
call test_magnetic_dataset_non_collinear()
case default
write (error_unit, *) "No known sub-test passed"
ret = 1
Expand Down Expand Up @@ -89,7 +93,7 @@ subroutine test_Cr_type_IV() bind(C)
integer(c_int) :: types(2)
integer(c_int) :: tensor_rank, is_axial

integer :: i, j, num_atom, num_timerev
integer :: i, num_atom, num_timerev
real :: origin_shift(3)
real(c_double) :: symprec
type(SpglibMagneticDataset) :: dataset
Expand All @@ -99,10 +103,7 @@ subroutine test_Cr_type_IV() bind(C)
is_axial = 0

lattice(:, :) = reshape([4, 0, 0, 0, 4, 0, 0, 0, 4], [3, 3])
position(:, :) = reshape( &
[ &
0.0, 0.0, 0.0, 0.5, 0.5, 0.5 &
], [3, 2])
position(:, :) = reshape([0.0, 0.0, 0.0, 0.5, 0.5, 0.5], [3, 2])
types(:) = [1, 1]
origin_shift(:) = [0.1, 0.1, 0.0]
tensors(:) = [1, -1]
Expand All @@ -122,4 +123,31 @@ subroutine test_Cr_type_IV() bind(C)
call assert(dataset%n_operations, 96)
call assert(num_timerev, 48)
end subroutine test_Cr_type_IV

subroutine test_magnetic_dataset_non_collinear() bind(C)
real(c_double) :: lattice(3, 3)
real(c_double) :: position(3, 1)
real(c_double) :: tensors(3)
integer(c_int) :: types(1)
integer(c_int) :: tensor_rank, is_axial

integer :: i, j, num_atom
real(c_double) :: symprec
type(SpglibMagneticDataset) :: dataset

num_atom = 1
tensor_rank = 1
is_axial = 1

lattice(:, :) = reshape([10, 0, 0, 0, 10, 0, 0, 0, 10], [3, 3])
position(:, :) = reshape([0.0, 0.0, 0.0], [3, 1])
types(:) = [1]
tensors(:) = [1, 0, 0]
symprec = 1e-5

dataset = spg_get_magnetic_dataset(lattice, position, types, tensors, tensor_rank, &
num_atom, is_axial, symprec)

call assert(dataset%n_operations, 16)
end subroutine test_magnetic_dataset_non_collinear
end module test_spg_get_magnetic_dataset
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
module test_spg_get_symmetry_with_site_tensors
use spglib_f08, only: spg_get_symmetry_with_site_tensors
use test_utils
use C_interface_module
use, intrinsic :: iso_fortran_env
implicit none
contains
function test_fortran_spg_get_symmetry_with_site_tensors(argc, argv) bind(C) result(ret)
use, intrinsic :: iso_c_binding
integer(c_int), value, intent(in) :: argc
type(c_ptr), intent(in) :: argv(argc)
integer(c_int) :: ret

integer :: len
character(len=:), allocatable :: str

if (argc < 2) then
write (output_unit, *) "test_site_tensors_rutile_type_III"
call test_site_tensors_rutile_type_III()
write (output_unit, *) "test_site_tensors_Cr_type_IV"
call test_site_tensors_Cr_type_IV()
write (output_unit, *) "test_magnetic_dataset_non_collinear"
call test_site_tensors_non_collinear()
else
len = c_strlen(argv(2))
allocate (character(len=len) :: str)
call C_F_string(argv(2), str)
select case (str)
case ("test_site_tensors_rutile_type_III")
call test_site_tensors_rutile_type_III()
case ("test_site_tensors_Cr_type_IV")
call test_site_tensors_Cr_type_IV()
case ("test_site_tensors_non_collinear")
call test_site_tensors_non_collinear()
case default
write (error_unit, *) "No known sub-test passed"
ret = 1
return
end select
deallocate (str)
end if

ret = 0
end function test_fortran_spg_get_symmetry_with_site_tensors

subroutine test_site_tensors_rutile_type_III() bind(C)
real(c_double) :: lattice(3, 3)
real(c_double) :: positions(3, 6)
real(c_double) :: tensors(6)
real(c_double) :: translations(3, 6*96)
real(c_double) :: primitive_lattice(3, 3)
real(c_double) :: symprec = 1e-5
integer(c_int) :: types(6)
integer(c_int) :: n_operations
integer(c_int) :: num_atom = 6
integer(c_int) :: with_time_reversal = 1
integer(c_int) :: tensor_rank = 0
integer(c_int) :: is_axial = 0
integer(c_int) :: max_size = 96*6
integer(c_int) :: rotations(3, 3, 96*6)
integer(c_int) :: equivalent_atoms(6)
integer(c_int) :: spin_flips(96*6)

integer :: i, num_timerev
real :: origin_shift(3)

lattice(:, :) = reshape([4, 0, 0, 0, 4, 0, 0, 0, 3], [3, 3])
positions(:, :) = reshape( &
[ &
0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.3, 0.3, 0.0, 0.7, 0.7, 0.0, &
0.2, 0.8, 0.5, 0.8, 0.2, 0.5 &
], [3, 6])
types(:) = [1, 1, 2, 2, 2, 2]
origin_shift(:) = [0.1, 0.1, 0.0]
tensors(:) = [1, -1, 0, 0, 0, 0]

do i = 1, num_atom
positions(:, i) = positions(:, i) + origin_shift(:)
end do

n_operations = spg_get_symmetry_with_site_tensors( &
rotations, translations, equivalent_atoms, &
primitive_lattice, spin_flips, max_size, &
lattice, positions, types, tensors, tensor_rank, &
num_atom, with_time_reversal, is_axial, symprec)

num_timerev = 0
do i = 1, n_operations
num_timerev = num_timerev - (spin_flips(i) - 1)/2
end do

call assert(n_operations, 16)
call assert(num_timerev, 8)
end subroutine test_site_tensors_rutile_type_III

subroutine test_site_tensors_Cr_type_IV() bind(C)
real(c_double) :: lattice(3, 3)
real(c_double) :: positions(3, 2)
real(c_double) :: tensors(2)
real(c_double) :: translations(3, 2*96)
real(c_double) :: primitive_lattice(3, 3)
real(c_double) :: symprec = 1e-5
integer(c_int) :: types(2)
integer(c_int) :: n_operations
integer(c_int) :: num_atom = 2
integer(c_int) :: with_time_reversal = 1
integer(c_int) :: tensor_rank = 0
integer(c_int) :: is_axial = 0
integer(c_int) :: max_size = 96*2
integer(c_int) :: rotations(3, 3, 96*2)
integer(c_int) :: equivalent_atoms(2)
integer(c_int) :: spin_flips(96*2)

integer :: i, num_timerev
real :: origin_shift(3)

lattice(:, :) = reshape([4, 0, 0, 0, 4, 0, 0, 0, 4], [3, 3])
positions(:, :) = reshape([0.0, 0.0, 0.0, 0.5, 0.5, 0.5], [3, 2])
types(:) = [1, 1]
origin_shift(:) = [0.1, 0.1, 0.0]
tensors(:) = [1, -1]

do i = 1, num_atom
positions(:, i) = positions(:, i) + origin_shift(:)
end do

n_operations = spg_get_symmetry_with_site_tensors( &
rotations, translations, equivalent_atoms, &
primitive_lattice, spin_flips, max_size, &
lattice, positions, types, tensors, tensor_rank, &
num_atom, with_time_reversal, is_axial, symprec)

num_timerev = 0
do i = 1, n_operations
num_timerev = num_timerev - (spin_flips(i) - 1)/2
end do

call assert(n_operations, 96)
call assert(num_timerev, 48)
end subroutine test_site_tensors_Cr_type_IV

subroutine test_site_tensors_non_collinear() bind(C)
real(c_double) :: lattice(3, 3)
real(c_double) :: positions(3, 1)
real(c_double) :: tensors(3)
real(c_double) :: translations(3, 96)
real(c_double) :: primitive_lattice(3, 3)
real(c_double) :: symprec = 1e-5
integer(c_int) :: types(1)
integer(c_int) :: n_operations
integer(c_int) :: num_atom = 1
integer(c_int) :: with_time_reversal = 1
integer(c_int) :: tensor_rank = 1
integer(c_int) :: is_axial = 1
integer(c_int) :: max_size = 96
integer(c_int) :: rotations(3, 3, 96)
integer(c_int) :: equivalent_atoms(1)
integer(c_int) :: spin_flips(96)

lattice(:, :) = reshape([10, 0, 0, 0, 10, 0, 0, 0, 10], [3, 3])
positions(:, :) = reshape([0.0, 0.0, 0.0], [3, 1])
types(:) = [1]
tensors(:) = [1, 0, 0]

n_operations = spg_get_symmetry_with_site_tensors( &
rotations, translations, equivalent_atoms, &
primitive_lattice, spin_flips, max_size, &
lattice, positions, types, tensors, tensor_rank, &
num_atom, with_time_reversal, is_axial, symprec)

call assert(n_operations, 16)
end subroutine test_site_tensors_non_collinear
end module test_spg_get_symmetry_with_site_tensors