- 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:
238
ubfour.c
238
ubfour.c
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user