aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2014-08-14 14:34:40 +0200
committerThomas White <taw@physics.org>2014-09-25 10:53:56 +0200
commita06a3f67f57de0bc85982976b9ea6d598598e014 (patch)
tree6eab60a0a40acacc27f5e07264043bfd617c859f
parent4ad4127092681a2190c682a736d8baecb1554328 (diff)
WIP on gradients for scsphere
-rw-r--r--src/post-refinement.c27
-rw-r--r--tests/pr_p_gradient_check.c20
2 files changed, 33 insertions, 14 deletions
diff --git a/src/post-refinement.c b/src/post-refinement.c
index 99ddf6b1..4c16f2d8 100644
--- a/src/post-refinement.c
+++ b/src/post-refinement.c
@@ -68,9 +68,14 @@ static double dpdq(double r, double profile_radius)
/* Returns dp/dr at "r" */
static double partiality_gradient(double r, double profile_radius,
- PartialityModel pmodel)
+ PartialityModel pmodel,
+ double rlow, double rhigh, double p)
{
- double dqdr; /* dq/dr */
+ double dqdr; /* dq/dr */
+ double dpsphdr; /* dpsph / dr */
+ double A, D;
+
+ D = rlow - rhigh;
switch ( pmodel ) {
@@ -90,6 +95,12 @@ static double partiality_gradient(double r, double profile_radius,
case PMODEL_THIN:
return -(2.0*r)/(profile_radius*profile_radius);
+ case PMODEL_SCSPHERE:
+ dqdr = 1.0 / (2.0*profile_radius);
+ dpsphdr = dpdq(r, profile_radius) * dqdr;
+ A = (dpsphdr/D) - p*pow(rlow-rhigh, -2.0);
+ return 4.0*profile_radius*A/3.0;
+
}
}
@@ -178,12 +189,12 @@ double p_gradient(Crystal *cr, int k, Reflection *refl, PartialityModel pmodel)
/* Calculate the gradient of partiality wrt excitation error. */
if ( clamp_low == 0 ) {
- glow = partiality_gradient(rlow, r, pmodel);
+ glow = partiality_gradient(rlow, r, pmodel, rlow, rhigh, p);
} else {
glow = 0.0;
}
if ( clamp_high == 0 ) {
- ghigh = partiality_gradient(rhigh, r, pmodel);
+ ghigh = partiality_gradient(rhigh, r, pmodel, rlow, rhigh, p);
} else {
ghigh = 0.0;
}
@@ -215,14 +226,15 @@ double p_gradient(Crystal *cr, int k, Reflection *refl, PartialityModel pmodel)
default:
case PMODEL_UNITY:
+ case PMODEL_THIN:
return 0.0;
case PMODEL_GAUSSIAN:
case PMODEL_SPHERE:
return (ds*glow + ds*ghigh) / 2.0;
- case PMODEL_THIN:
- return 0.0;
+ case PMODEL_SCSPHERE:
+ return 0.0; /* FIXME */
}
}
@@ -273,6 +285,9 @@ double l_gradient(Crystal *cr, int k, Reflection *refl, PartialityModel pmodel)
signed int hs, ks, ls;
double L;
+ /* L has a non-zero gradient only for div in sphere or gaussian model */
+ if ( (pmodel != PMODEL_SPHERE)
+ && (pmodel != PMODEL_GAUSSIAN) ) return 0.0;
if ( k != REF_DIV ) return 0.0;
get_symmetric_indices(refl, &hs, &ks, &ls);
diff --git a/tests/pr_p_gradient_check.c b/tests/pr_p_gradient_check.c
index b88380eb..82ed2b02 100644
--- a/tests/pr_p_gradient_check.c
+++ b/tests/pr_p_gradient_check.c
@@ -45,7 +45,8 @@
static void scan_partialities(RefList *reflections, RefList *compare,
- int *valid, long double *vals[3], int idx)
+ int *valid, long double *vals[3], int idx,
+ PartialityModel pmodel)
{
int i;
Reflection *refl;
@@ -70,7 +71,7 @@ static void scan_partialities(RefList *reflections, RefList *compare,
}
get_partial(refl2, &r1, &r2, &p, &clamp_low, &clamp_high);
- if ( clamp_low && clamp_high ) {
+ if ( clamp_low && clamp_high && (pmodel != PMODEL_SCSPHERE) ) {
if ( !within_tolerance(p, 1.0, 0.001) ) {
signed int h, k, l;
@@ -190,7 +191,7 @@ static void calc_either_side(Crystal *cr, double incr_val,
cr_new = new_shifted_crystal(cr, refine, -incr_val);
compare = find_intersections(image, cr_new, pmodel);
scan_partialities(crystal_get_reflections(cr), compare, valid,
- vals, 0);
+ vals, 0, pmodel);
cell_free(crystal_get_cell(cr_new));
crystal_free(cr_new);
reflist_free(compare);
@@ -198,7 +199,7 @@ static void calc_either_side(Crystal *cr, double incr_val,
cr_new = new_shifted_crystal(cr, refine, +incr_val);
compare = find_intersections(image, cr_new, pmodel);
scan_partialities(crystal_get_reflections(cr), compare, valid,
- vals, 2);
+ vals, 2, pmodel);
cell_free(crystal_get_cell(cr_new));
crystal_free(cr_new);
reflist_free(compare);
@@ -212,14 +213,14 @@ static void calc_either_side(Crystal *cr, double incr_val,
shift_parameter(&im_moved, refine, -incr_val);
compare = find_intersections(&im_moved, cr, pmodel);
scan_partialities(crystal_get_reflections(cr), compare,
- valid, vals, 0);
+ valid, vals, 0, pmodel);
reflist_free(compare);
im_moved = *image;
shift_parameter(&im_moved, refine, +incr_val);
compare = find_intersections(&im_moved, cr, pmodel);
scan_partialities(crystal_get_reflections(cr), compare,
- valid, vals, 2);
+ valid, vals, 2, pmodel);
reflist_free(compare);
}
@@ -271,7 +272,7 @@ static double test_gradients(Crystal *cr, double incr_val, int refine,
}
for ( i=0; i<nref; i++ ) valid[i] = 1;
- scan_partialities(reflections, reflections, valid, vals, 1);
+ scan_partialities(reflections, reflections, valid, vals, 1, pmodel);
calc_either_side(cr, incr_val, valid, vals, refine, pmodel);
@@ -450,7 +451,7 @@ int main(int argc, char *argv[])
rng = gsl_rng_alloc(gsl_rng_mt19937);
- for ( i=0; i<3; i++ ) {
+ for ( i=0; i<4; i++ ) {
UnitCell *rot;
double val;
@@ -467,6 +468,9 @@ int main(int argc, char *argv[])
} else if ( i == 2 ) {
pmodel = PMODEL_THIN;
STATUS("Testing Thin Ewald Sphere model:\n");
+ } else if ( i == 3 ) {
+ pmodel = PMODEL_SCSPHERE;
+ STATUS("Testing SCSphere model:\n");
} else {
ERROR("WTF?\n");
return 1;