aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore2
-rw-r--r--tests/centering_check.c296
-rw-r--r--tests/gpu_sim_check.c1
-rw-r--r--tests/pr_gradient_check.c1
-rw-r--r--tests/transformation_check.c176
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;
+}