diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/.gitignore | 2 | ||||
-rw-r--r-- | tests/centering_check.c | 296 | ||||
-rw-r--r-- | tests/gpu_sim_check.c | 1 | ||||
-rw-r--r-- | tests/pr_gradient_check.c | 1 | ||||
-rw-r--r-- | tests/transformation_check.c | 176 |
5 files changed, 476 insertions, 0 deletions
diff --git a/tests/.gitignore b/tests/.gitignore index c2a45f5a..81fd558f 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -5,4 +5,6 @@ gpu_sim_check integration_check pr_gradient_check symmetry_check +centering_check +transformation_check .dirstamp diff --git a/tests/centering_check.c b/tests/centering_check.c new file mode 100644 index 00000000..e17915d3 --- /dev/null +++ b/tests/centering_check.c @@ -0,0 +1,296 @@ +/* + * centering_check.c + * + * Check that centering of cells works + * + * Copyright © 2012 Thomas White <taw@physics.org> + * + * This file is part of CrystFEL. + * + * CrystFEL is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CrystFEL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <fenv.h> + +#include <cell.h> +#include <cell-utils.h> + + +static int check_cell(UnitCell *cell, const char *text) +{ + int err = 0; + + err = validate_cell(cell); + + if ( err ) { + ERROR("%s cell:\n", text); + cell_print(cell); + } + + return err; +} + + +static int check_centering(double a, double b, double c, + double al, double be, double ga, + LatticeType latt, char cen, char ua) +{ + UnitCell *cell, *cref; + UnitCell *n; + UnitCellTransformation *t; + int fail = 0; + int i; + double asx, asy, asz; + double bsx, bsy, bsz; + double csx, csy, csz; + double ax, ay, az; + double bx, by, bz; + double cx, cy, cz; + + STATUS(" ---------------> " + "Checking %s %c (ua %c) %5.2e %5.2e %5.2e %5.2f %5.2f %5.2f\n", + str_lattice(latt), cen, ua, a, b, c, al, be, ga); + + cref = cell_new_from_parameters(a, b, c, + deg2rad(al), deg2rad(be), deg2rad(ga)); + cell_set_lattice_type(cref, latt); + cell_set_centering(cref, cen); + cell_set_unique_axis(cref, ua); + + cell = cell_rotate(cref, random_quaternion()); + if ( cell == NULL ) return 1; + cell_free(cref); + + check_cell(cell, "Input"); + n = uncenter_cell(cell, &t); + if ( n != NULL ) { + STATUS("Transformation was:\n"); + tfn_print(t); + if ( check_cell(n, "Output") ) fail = 1; + if ( !fail ) cell_print(n); + } else { + fail = 1; + } + + cell_get_reciprocal(cell, &asx, &asy, &asz, + &bsx, &bsy, &bsz, + &csx, &csy, &csz); + cell_get_cartesian(n, &ax, &ay, &az, + &bx, &by, &bz, + &cx, &cy, &cz); + + fesetround(1); /* Round towards nearest */ + for ( i=0; i<100; i++ ) { + + signed int h, k, l; + double x, y, z; + double nh, nk, nl; + double dh, dk, dl; + int f = 0; + + do { + + h = flat_noise(0, 30); + k = flat_noise(0, 30); + l = flat_noise(0, 30); + + } while ( forbidden_reflection(cell, h, k, l) ); + + x = h*asx + k*bsx + l*csx; + y = h*asy + k*bsy + l*csy; + z = h*asz + k*bsz + l*csz; + + nh = x*ax + y*ay + z*az; + nk = x*bx + y*by + z*bz; + nl = x*cx + y*cy + z*cz; + + dh = nh - lrint(nh); + dk = nk - lrint(nk); + dl = nl - lrint(nl); + if ( fabs(dh) > 0.1 ) f++; + if ( fabs(dk) > 0.1 ) f++; + if ( fabs(dl) > 0.1 ) f++; + + if ( f ) { + STATUS("Centered %3i %3i %3i -> " + "Primitive %7.2f %7.2f %7.2f\n", + h, k, l, nh, nk, nl); + fail = 1; + } + + } + + cell_get_reciprocal(n, &asx, &asy, &asz, + &bsx, &bsy, &bsz, + &csx, &csy, &csz); + cell_get_cartesian(cell, &ax, &ay, &az, + &bx, &by, &bz, + &cx, &cy, &cz); + + for ( i=0; i<100; i++ ) { + + signed int h, k, l; + double x, y, z; + double nh, nk, nl; + double dh, dk, dl; + int f = 0; + long int ih, ik, il; + + h = flat_noise(0, 30); + k = flat_noise(0, 30); + l = flat_noise(0, 30); + + x = h*asx + k*bsx + l*csx; + y = h*asy + k*bsy + l*csy; + z = h*asz + k*bsz + l*csz; + + nh = x*ax + y*ay + z*az; + nk = x*bx + y*by + z*bz; + nl = x*cx + y*cy + z*cz; + + dh = nh - lrint(nh); dk = nk - lrint(nk); dl = nl - lrint(nl); + + if ( fabs(dh) > 0.1 ) f++; + if ( fabs(dk) > 0.1 ) f++; + if ( fabs(dl) > 0.1 ) f++; + + ih = lrint(nh); ik = lrint(nk); il = lrint(nl); + if ( forbidden_reflection(cell, ih, ik, il) ) { + STATUS("Primitive %3i %3i %3i -> " + "Centered %3li %3li %3li, " + "which is forbidden\n", + h, k, l, ih, ik, il); + fail = 1; + } + + if ( f ) { + STATUS("Primitive %3i %3i %3i -> " + "Centered %7.2f %7.2f %7.2f\n", + h, k, l, nh, nk, nl); + fail = 1; + } + + } + + return fail; +} + + +int main(int argc, char *argv[]) +{ + int fail = 0; + + /* Triclinic P */ + fail += check_centering(50e-10, 55e-10, 70e-10, 67.0, 70.0, 77.0, + L_TRICLINIC, 'P', '*'); + + /* Monoclinic P */ + fail += check_centering(10e-10, 20e-10, 30e-10, 100.0, 90.0, 90.0, + L_MONOCLINIC, 'P', 'a'); + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 100.0, 90.0, + L_MONOCLINIC, 'P', 'b'); + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 100.0, + L_MONOCLINIC, 'P', 'c'); + + /* Monoclinic A */ + fail += check_centering(10e-10, 20e-10, 30e-10, 100.0, 90.0, 90.0, + L_MONOCLINIC, 'A', 'a'); + + /* Monoclinic B */ + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 100.0, 90.0, + L_MONOCLINIC, 'B', 'b'); + + /* Monoclinic C */ + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 100.0, + L_MONOCLINIC, 'C', 'c'); + + /* Orthorhombic P */ + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_ORTHORHOMBIC, 'P', '*'); + + /* Orthorhombic A */ + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_ORTHORHOMBIC, 'A', 'a'); + + /* Orthorhombic B */ + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_ORTHORHOMBIC, 'B', 'b'); + + /* Orthorhombic C */ + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_ORTHORHOMBIC, 'C', 'c'); + + /* Orthorhombic I */ + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_ORTHORHOMBIC, 'I', '*'); + + /* Orthorhombic F */ + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_ORTHORHOMBIC, 'F', '*'); + + /* Tetragonal P */ + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_TETRAGONAL, 'P', 'a'); + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_TETRAGONAL, 'P', 'b'); + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_TETRAGONAL, 'P', 'c'); + + /* Tetragonal I */ + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_TETRAGONAL, 'I', 'a'); + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_TETRAGONAL, 'I', 'b'); + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 90.0, + L_TETRAGONAL, 'I', 'c'); + + /* Rhombohedral R */ + fail += check_centering(10e-10, 10e-10, 10e-10, 60.0, 60.0, 60.0, + L_RHOMBOHEDRAL, 'R', '*'); + + /* Hexagonal P */ + fail += check_centering(10e-10, 20e-10, 30e-10, 120.0, 90.0, 90.0, + L_HEXAGONAL, 'P', 'a'); + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 120.0, 90.0, + L_HEXAGONAL, 'P', 'b'); + fail += check_centering(10e-10, 20e-10, 30e-10, 90.0, 90.0, 120.0, + L_HEXAGONAL, 'P', 'c'); + + /* Hexagonal H (PDB-speak for rhombohedral) */ + fail += check_centering(20e-10, 20e-10, 40e-10, 90.0, 90.0, 120.0, + L_HEXAGONAL, 'H', 'c'); + + /* Cubic P */ + fail += check_centering(30e-10, 30e-10, 30e-10, 90.0, 90.0, 90.0, + L_CUBIC, 'P', '*'); + + /* Cubic I */ + fail += check_centering(30e-10, 30e-10, 30e-10, 90.0, 90.0, 90.0, + L_CUBIC, 'I', '*'); + + /* Cubic F */ + fail += check_centering(30e-10, 30e-10, 30e-10, 90.0, 90.0, 90.0, + L_CUBIC, 'F', '*'); + + return fail; +} diff --git a/tests/gpu_sim_check.c b/tests/gpu_sim_check.c index 5b6f6da7..5c45ea02 100644 --- a/tests/gpu_sim_check.c +++ b/tests/gpu_sim_check.c @@ -36,6 +36,7 @@ #include <beam-parameters.h> #include <utils.h> #include <symmetry.h> +#include <cell-utils.h> #ifdef HAVE_CLOCK_GETTIME diff --git a/tests/pr_gradient_check.c b/tests/pr_gradient_check.c index 6972b66a..b39dfd05 100644 --- a/tests/pr_gradient_check.c +++ b/tests/pr_gradient_check.c @@ -32,6 +32,7 @@ #include <image.h> #include <cell.h> +#include <cell-utils.h> #include <geometry.h> #include <reflist.h> #include "../src/post-refinement.h" diff --git a/tests/transformation_check.c b/tests/transformation_check.c new file mode 100644 index 00000000..7d25aa04 --- /dev/null +++ b/tests/transformation_check.c @@ -0,0 +1,176 @@ +/* + * transformation_check.c + * + * Check that unit cell transformations work + * + * Copyright © 2012 Thomas White <taw@physics.org> + * + * This file is part of CrystFEL. + * + * CrystFEL is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CrystFEL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> + +#include <cell.h> +#include <cell-utils.h> + + +static int check_transformation(UnitCell *cell, UnitCellTransformation *tfn) +{ + UnitCell *cnew, *cback; + UnitCellTransformation *inv; + double a[9], b[9]; + int i; + int fail = 0; + + cnew = cell_transform(cell, tfn); + + cback = cell_transform_inverse(cnew, tfn); + + cell_get_cartesian(cell, &a[0], &a[1], &a[2], + &a[3], &a[4], &a[5], + &a[6], &a[7], &a[8]); + cell_get_cartesian(cback, &b[0], &b[1], &b[2], + &b[3], &b[4], &b[5], + &b[6], &b[7], &b[8]); + for ( i=0; i<9; i++ ) { + if ( !within_tolerance(a[i], b[i], 0.1) ) { + fail = 1; + STATUS("%e %e\n", a[i], b[i]); + } + } + + if ( fail ) { + ERROR("Original cell not recovered after transformation:\n"); + cell_print(cell); + tfn_print(tfn); + inv = tfn_inverse(tfn); + tfn_print(inv); + cell_print(cback); + } + + return fail; +} + + +static int check_identity(UnitCell *cell, UnitCellTransformation *tfn) +{ + UnitCell *cnew; + double a[9], b[9]; + int i; + int fail = 0; + + cnew = cell_transform(cell, tfn); + + cell_get_cartesian(cell, &a[0], &a[1], &a[2], + &a[3], &a[4], &a[5], + &a[6], &a[7], &a[8]); + cell_get_cartesian(cnew, &b[0], &b[1], &b[2], + &b[3], &b[4], &b[5], + &b[6], &b[7], &b[8]); + for ( i=0; i<9; i++ ) { + if ( !within_tolerance(a[i], b[i], 0.1) ) { + fail = 1; + STATUS("%e %e\n", a[i], b[i]); + } + } + + if ( fail ) { + ERROR("Original cell not recovered after transformation:\n"); + cell_print(cell); + tfn_print(tfn); + cell_print(cnew); + } + + return fail; +} + + +int main(int argc, char *argv[]) +{ + int fail = 0; + UnitCell *cell, *cref; + UnitCellTransformation *tfn; + + cref = cell_new_from_parameters(50e-10, 55e-10, 70e-10, + deg2rad(67.0), + deg2rad(70.0), + deg2rad(77.0)); + if ( cref == NULL ) return 1; + + cell = cell_rotate(cref, random_quaternion()); + if ( cell == NULL ) return 1; + cell_free(cref); + + /* Permutation of axes */ + tfn = tfn_identity(); + if ( tfn == NULL ) return 1; + tfn_combine(tfn, tfn_vector(0,1,0), + tfn_vector(0,0,1), + tfn_vector(1,0,0)); + fail += check_transformation(cell, tfn); + tfn_free(tfn); + + /* Doubling of cell in one direction */ + tfn = tfn_identity(); + if ( tfn == NULL ) return 1; + tfn_combine(tfn, tfn_vector(2,0,0), + tfn_vector(0,1,0), + tfn_vector(0,0,1)); + fail += check_transformation(cell, tfn); + tfn_free(tfn); + + /* Diagonal supercell */ + tfn = tfn_identity(); + if ( tfn == NULL ) return 1; + tfn_combine(tfn, tfn_vector(1,1,0), + tfn_vector(0,1,0), + tfn_vector(0,0,1)); + fail += check_transformation(cell, tfn); + tfn_free(tfn); + + /* Crazy */ + tfn = tfn_identity(); + if ( tfn == NULL ) return 1; + tfn_combine(tfn, tfn_vector(1,1,0), + tfn_vector(0,1,0), + tfn_vector(0,1,1)); + fail += check_transformation(cell, tfn); + tfn_free(tfn); + + /* Identity in two parts */ + tfn = tfn_identity(); + if ( tfn == NULL ) return 1; + tfn_combine(tfn, tfn_vector(0,0,1), + tfn_vector(0,1,0), + tfn_vector(-1,0,0)); + tfn_combine(tfn, tfn_vector(0,0,-1), + tfn_vector(0,1,0), + tfn_vector(1,0,0)); + fail += check_identity(cell, tfn); + tfn_free(tfn); + + cell_free(cell); + + return fail; +} |