- Added brute force indexing support to ubcalc

- Added calculation of UB from 3 reflections to ubcalc
- Added calculation of lattice constants from UB to ubcalc
- Some fixes in stdscan in order to make the scripted scan work
This commit is contained in:
koennecke
2005-04-01 13:48:25 +00:00
parent 152bc961ec
commit 5c30a7ea7b
10 changed files with 637 additions and 45 deletions

238
ubfour.c
View File

@ -1,11 +1,12 @@
/**
* This is a library for calculating UB matrices for four circle diffraction.
* The algorithm and setting definitions is from:
* The algorithm and settings definition is from:
*
* Busing & Levy, Acta Cryst. (1967), 22, 457ff
*
* Implemented:
* - UB from cell cell constants and two reflections.
* - Brute force index search
*
* Mark Koennecke, March 2005
*/
@ -13,6 +14,9 @@
#include <assert.h>
#include "vector.h"
#include "trigd.h"
#include "fourlib.h"
#include "lld.h"
#define ABS(x) (x < 0 ? -(x) : (x))
/*--------------------------------------------------------------------------------------*/
static MATRIX calcUVectorFromAngles(reflection r){
MATRIX u;
@ -50,6 +54,7 @@ MATRIX calcUBFromCellAndReflections(lattice direct, reflection r1,
MATRIX u1, u2, h1, h2;
double ud[3];
int status;
reflection r;
*errCode = 1;
@ -134,3 +139,234 @@ MATRIX calcUBFromCellAndReflections(lattice direct, reflection r1,
return UB;
}
/*-----------------------------------------------------------------------------------*/
static void storeReflection(reflection r, double two_theta_obs,
double two_theta_calc, int list){
refIndex ri, test;
int count = 0, status, pos = 0;
ri.h = r.h;
ri.k = r.k;
ri.l = r.l;
ri.t2obs = two_theta_obs;
ri.t2calc = two_theta_calc;
ri.t2diff = ABS(two_theta_obs - two_theta_calc);
/*
locate the last entry bigger then us
*/
status = LLDnodePtr2First(list);
while(status == 1){
LLDnodeDataTo(list,&test);
count++;
if(test.t2diff == ri.t2diff){
LLDnodeDataFrom(list,&ri);
return;
}
if(test.t2diff > ri.t2diff){
break;
}
status = LLDnodePtr2Next(list);
}
/*
special case: empty list
*/
if(count == 0){
LLDnodeAppendFrom(list,&ri);
return;
}
/*
special case: append after last
*/
LLDnodePtr2Last(list);
LLDnodeDataTo(list,&test);
if(ri.t2diff > test.t2diff){
LLDnodeAppendFrom(list,&ri);
return;
}
status = LLDnodePtr2First(list);
pos = 0;
while(status == 1){
LLDnodeDataTo(list,&test);
pos++;
if(pos == count){
LLDnodeInsertFrom(list,&ri);
return;
}
status = LLDnodePtr2Next(list);
}
}
/*----------------------------------------------------------------------------
u_transform(i) = u(i)*(2*sin(theta)/lambda)
-----------------------------------------------------------------------------*/
static void uToScatteringVector(MATRIX u, double theta, double lambda){
double scale;
int i;
scale = (2. * Sind(theta))/lambda;
for(i = 0; i < 3; i++){
u[i][0] *= scale;
}
}
/*----------------------------------------------------------------------------*/
static MATRIX buildHCHIMatrix(MATRIX u1, MATRIX u2, MATRIX u3){
int i;
MATRIX HCHI;
HCHI = mat_creat(3,3,ZERO_MATRIX);
if(HCHI == NULL){
return NULL;
}
for(i = 0; i < 3; i++){
HCHI[i][0] = u1[i][0];
HCHI[i][1] = u2[i][0];
HCHI[i][2] = u3[i][0];
}
return HCHI;
}
/*----------------------------------------------------------------------------*/
static MATRIX buildIndexMatrix(reflection r1, reflection r2, reflection r3){
MATRIX HI;
int i;
HI = mat_creat(3,3,ZERO_MATRIX);
if(HI == NULL){
return NULL;
}
HI[0][0] = r1.h;
HI[1][0] = r1.k;
HI[2][0] = r1.l;
HI[0][1] = r2.h;
HI[1][1] = r2.k;
HI[2][1] = r2.l;
HI[0][2] = r3.h;
HI[1][2] = r3.k;
HI[2][2] = r3.l;
return HI;
}
/*-----------------------------------------------------------------------------*/
MATRIX calcUBFromThreeReflections(reflection r1, reflection r2, reflection r3,
double lambda, int *errCode){
MATRIX u1, u2, u3, HCHI, HI, HIINV, UB;
double det;
if(lambda <= .1){
*errCode = INVALID_LAMBDA;
return NULL;
}
*errCode = 1;
u1 = calcUVectorFromAngles(r1);
u2 = calcUVectorFromAngles(r2);
u3 = calcUVectorFromAngles(r3);
uToScatteringVector(u1,r1.s2t/2.,lambda);
uToScatteringVector(u2,r2.s2t/2.,lambda);
uToScatteringVector(u3,r3.s2t/2.,lambda);
HCHI = buildHCHIMatrix(u1,u2,u3);
HI = buildIndexMatrix(r1,r2,r3);
if(HCHI == NULL || HI == NULL){
*errCode = UBNOMEMORY;
killVector(u1);
killVector(u2);
killVector(u3);
return NULL;
}
HIINV = mat_inv(HI);
if(HIINV == NULL){
*errCode = UBNOMEMORY;
killVector(u1);
killVector(u2);
killVector(u3);
mat_free(HI);
mat_free(HCHI);
return NULL;
}
UB = mat_mul(HCHI,HIINV);
det = mat_det(UB);
if(det < .0){
mat_free(UB);
UB = NULL;
*errCode = NOTRIGHTHANDED;
}
killVector(u1);
killVector(u2);
killVector(u3);
mat_free(HI);
mat_free(HCHI);
mat_free(HIINV);
return UB;
}
/*---------------------------------------------------------------------------------*/
static int copyReflections(int list, refIndex index[], int maxIndex){
int count = 0, status;
refIndex ri;
status = LLDnodePtr2First(list);
while(status == 1 && count < maxIndex){
LLDnodeDataTo(list,&ri);
index[count] = ri;
status = LLDnodePtr2Next(list);
count++;
}
return count;
}
/*-----------------------------------------------------------------------------------
- matching reflections will be entered in to a list in a sorted way. This list
is copied into the index array.
- There is some waste here in allocating and deallocating the HC vector in the
inner loop. I'am to lazy to resolve this.... May be I'am spared.....
-----------------------------------------------------------------------------------*/
int searchIndex(lattice direct, double lambda, double two_theta, double max_deviation,
int limit, refIndex index[], int maxIndex){
int status, i, j, k, list;
MATRIX B, HC;
double theta, d;
reflection r;
B = mat_creat(3,3,UNIT_MATRIX);
if(B == NULL) {
return UBNOMEMORY;
}
status = calculateBMatrix(direct,B);
if(status < 0) {
return status;
}
list = LLDcreate(sizeof(refIndex));
if(list <0) {
return UBNOMEMORY;
}
for(i = -limit; i < limit; i++){
r.h = (double)i;
for(j = -limit; j < limit; j++){
r.k = (double)j;
for(k = -limit; k < limit; k++){
r.l = (double)k;
HC = reflectionToHC(r,B);
status = calcTheta(lambda, HC, &d, &theta);
if(status == 1){
if(ABS(two_theta - 2. * theta) <= max_deviation){
storeReflection(r,two_theta, theta * 2., list);
}
}
killVector(HC);
}
}
}
mat_free(B);
status = copyReflections(list,index,maxIndex);
LLDdelete(list);
return status;
}