338 lines
12 KiB
C
338 lines
12 KiB
C
/**
|
|
* This is a library of functions and data structures for performing
|
|
* triple axis spectrometer angle calculations using the UB-matrix
|
|
* formalism as described by Mark Lumsden.
|
|
*
|
|
* copyright: see file COPYRIGHT
|
|
*
|
|
* Mark Koennecke, April 2005
|
|
*/
|
|
#ifndef TASUBLIB
|
|
#define TASUBLIB
|
|
#include "cell.h"
|
|
#include "matrix/matrix.h"
|
|
/*================= error codes =====================================*/
|
|
#define ENERGYTOBIG -700
|
|
#define BADSYNC -701 /* mono/analyzer out of sync: 2*theta != two_theta */
|
|
#define UBNOMEMORY -200
|
|
#define TRIANGLENOTCLOSED -703
|
|
#define BADRMATRIX -704
|
|
#define BADUBORQ -705
|
|
/*========================== defines for tasMode ====================*/
|
|
#define KICONST 1
|
|
#define KFCONST 2
|
|
#define ELASTIC 3
|
|
/*
|
|
* in elastic mode A5, A5 will be disregarded and ki = kf at all times
|
|
*/
|
|
/*=========================== TAS Variables =========================*/
|
|
#define EI 1
|
|
#define KI 2
|
|
#define QH 3
|
|
#define QK 4
|
|
#define QL 5
|
|
#define EF 6
|
|
#define KF 7
|
|
#define EN 8
|
|
#define QM 9
|
|
/*=========================== data structures =======================*/
|
|
/**
|
|
* data structure describing a monochromator or analyzer crystal
|
|
*/
|
|
typedef struct {
|
|
double dd; /* lattice spacing */
|
|
int ss; /* scattering sense */
|
|
double HB1, HB2; /* horizontal curvature parameters */
|
|
double VB1, VB2; /* vertical curvature parameters */
|
|
} maCrystal, *pmaCrystal;
|
|
/**
|
|
* the machine parameters of a triple axis spectrometer
|
|
*/
|
|
typedef struct {
|
|
maCrystal monochromator, analyzer;
|
|
MATRIX UB;
|
|
MATRIX planeNormal;
|
|
int ss_sample; /* scattering sense sample */
|
|
double a3offset;
|
|
} tasMachine, *ptasMachine;
|
|
/**
|
|
* a position in Q - Energy space
|
|
*/
|
|
typedef struct {
|
|
double ki, kf;
|
|
double qh, qk, ql;
|
|
double qm;
|
|
} tasQEPosition, *ptasQEPosition;
|
|
/**
|
|
* A triple axis angle position
|
|
*/
|
|
typedef struct {
|
|
double monochromator_two_theta;
|
|
double a3;
|
|
double sample_two_theta;
|
|
double sgl;
|
|
double sgu;
|
|
double analyzer_two_theta;
|
|
} tasAngles, *ptasAngles;
|
|
/**
|
|
* a full triple axis reflection
|
|
*/
|
|
typedef struct {
|
|
tasQEPosition qe;
|
|
tasAngles angles;
|
|
} tasReflection, *ptasReflection;
|
|
/*================= Monochromator/Analyzer stuff =====================*/
|
|
/**
|
|
* convert an energy in meV to Ki, Kf type values
|
|
* @param input energy
|
|
* @return Ki, or Kf
|
|
*/
|
|
double energyToK(double energy);
|
|
/**
|
|
* convert from Ki, Kf to energy in meV
|
|
* @param input K value
|
|
* @return output energy in meV
|
|
*/
|
|
double KtoEnergy(double k);
|
|
/*----------------------------------------------------------------------*/
|
|
/**
|
|
* calculate two_theta for k
|
|
* @param data The crystals parameter
|
|
* @param k The input K value to calculate
|
|
* @param two_theta The resulting two_theta
|
|
* @return 1 on success, a negative error code on failure
|
|
*/
|
|
int maCalcTwoTheta(maCrystal data, double k, double *two_theta);
|
|
/**
|
|
* calculate the value for the vertical curvature
|
|
* @param data The input crystal parameters
|
|
* @param two_theta The tow theta value for which to calculate the curvature.
|
|
* @return A new value for the curvature.
|
|
*/
|
|
double maCalcVerticalCurvature(maCrystal data, double two_theta);
|
|
/**
|
|
* calculate the value for the horizontal curvature
|
|
* @param data The input crystal parameters
|
|
* @param two_theta The tow theta value for which to calculate the curvature.
|
|
* @return A new value for the curvature.
|
|
*/
|
|
double maCalcHorizontalCurvature(maCrystal data, double two_theta);
|
|
/**
|
|
* calculate the value of the K vector from the angle
|
|
* @param data The crystals constants
|
|
* @param two_theta The two theta read from the motor
|
|
* @return The k value calculated from two_theta and the parameters.
|
|
*/
|
|
double maCalcK(maCrystal data, double two_theta);
|
|
/*======================= reciprocal space =============================*/
|
|
/**
|
|
* make an auxiliary reflection which has the same sgu and sgl as r1, but
|
|
* an omega which is adjusted to the angle difference between r1 and
|
|
* the target. This is useful for generating an auxilairy UB during
|
|
* alignment.
|
|
* @param B The B matrix
|
|
* @param r1 The first reflection
|
|
* @param r2 a pointer to the second reflection, QH, QK, QL initialized
|
|
* @param ss The scattering sense at the sample
|
|
* @return 1 on success, a negative error code on failure.
|
|
*/
|
|
int makeAuxReflection(MATRIX B, tasReflection r1,
|
|
tasReflection * r2, int ss);
|
|
/**
|
|
* calculate the scattering vector
|
|
* @param r The reflection for which to calculate the scattering vector.
|
|
* @return The scattering vector as a matrix
|
|
*/
|
|
MATRIX calcTasUVectorFromAngles(tasReflection r);
|
|
|
|
/**
|
|
* calculate two theta for the reflection ref
|
|
* @param B the metric matrix, or the UB
|
|
* @param ref The reflection for which to calculate two theta
|
|
* @param ss The scattering sense
|
|
* @param twoTheta The new two theta value (output)
|
|
* @return a negative error code on failure, 1 on success
|
|
*/
|
|
int calcTwoTheta(MATRIX B, tasQEPosition ref, int ss, double *twoTheta);
|
|
/**
|
|
* calculate a UB from the cell and values for the displacement of
|
|
* the crystal in om, sgu and sgl. This is for software testing.
|
|
* @param cell The lattice constant of the crystal
|
|
* @param om A theoretical omega
|
|
* @param sgu A theoreticl sgu
|
|
* @param sgl A theoretical sgl
|
|
* @return a UB matix on sucess, or NULL on failure. Failure means out of memory
|
|
* or an invalid cell.
|
|
*/
|
|
MATRIX calcTheoreticalTasUB(lattice cell, double om, double sgu, double sgl);
|
|
/**
|
|
* calculate a UB from two reflections and the cell.
|
|
* @param cell The lattice constant of the crystal
|
|
* @param r1 The first reflection
|
|
* @param r2 The second reflection
|
|
* @param erroroCode An error code which gives more details
|
|
* when an error occurs.
|
|
* @return a UB matix on sucess, or NULL on failure. Then errorCode
|
|
* can be inspected what caused the problem.
|
|
*/
|
|
MATRIX calcTasUBFromTwoReflections(lattice cell, tasReflection r1,
|
|
tasReflection r2, int *errorCode);
|
|
/**
|
|
* calculate a test plane normal
|
|
* @param sgu A theoretical plane tilt on upper
|
|
* @param sgl A theoretical plane tilt on lower
|
|
* @return a normal on sucess, or NULL on failure. This can only happen
|
|
* when out of memory
|
|
*/
|
|
MATRIX calcTestNormal(double sgu, double sgl);
|
|
/**
|
|
* calculate a test UB from angles
|
|
* @param cell The B lattice constants
|
|
* @param om A theoretical om for the crystal
|
|
* @param sgu A theoretical plane tilt on upper
|
|
* @param sgl A theoretical plane tilt on lower
|
|
* @return a UB matrix on sucess, or NULL on failure. This can only happen
|
|
* when out of memory or with a bad cell
|
|
*/
|
|
MATRIX calcTestUB(lattice cell, double om, double sgu, double sgl);
|
|
/**
|
|
* calculate a test UB
|
|
* @param B The B matrix as calculated from the cell constants
|
|
* @param om A theoretical om for the crystal
|
|
* @param sgu A theoretical plane tilt on upper
|
|
* @param sgl A theoretical plane tilt on lower
|
|
* @return a UB matrix on sucess, or NULL on failure. This can only happen
|
|
* when out of memory or with a bad cell
|
|
*/
|
|
MATRIX calcUBFromAngles(MATRIX B, double om, double sgu, double sgl);
|
|
|
|
/**
|
|
* calcluate the normal to the plane describe by the two reflections r1, r2
|
|
* @param r1 first reflection
|
|
* @param r2 second reflection
|
|
* @return a plane normal on success, NULL else
|
|
*/
|
|
|
|
MATRIX calcPlaneNormal(tasReflection r1, tasReflection r2);
|
|
/**
|
|
* calcluate the normal to the plane describe by the two reflections r1, r2
|
|
* This uses a different path in that it calculates the Qv from the UB and
|
|
* the Q values.
|
|
* @param UB The UB to use
|
|
* @param r1 first reflection
|
|
* @param r2 second reflection
|
|
* @return a plane normal on success, NULL else
|
|
*/
|
|
MATRIX calcPlaneNormalQ(MATRIX UB, tasReflection r1, tasReflection r2);
|
|
/**
|
|
* calculate the angles for r. R's h, k, l, ki, kf must be set, the angles
|
|
* will be updated.
|
|
* @param UB The UB matrix to use
|
|
* @param planeNormal The normal to the scattering plane to use
|
|
* @param ss The scattering sense at the sample
|
|
* @param The Mark Laver offset to a3. 0 is always a good value for this
|
|
* @param qe The desired Q Energy position
|
|
* @param angles The resulting angles.
|
|
* @return 1 on success, a negative error code when errors are encountered
|
|
*/
|
|
int calcTasQAngles(MATRIX UB, MATRIX planeNormal,
|
|
int ss, double a3offset,
|
|
tasQEPosition qe, ptasAngles angles);
|
|
/**
|
|
* calculate QH, QK, QL from the angles given
|
|
* @param UB The UB matrix to use
|
|
* @param angles The angles as read from the motors
|
|
* @param qe The resulting Q Energy positions
|
|
* @return 1 on success, a negative error code on failures.
|
|
*/
|
|
int calcTasQH(MATRIX UB, tasAngles angles, ptasQEPosition qe);
|
|
/*======================== pulling it together.. =======================*/
|
|
/**
|
|
* calculate all the tas target angles for a position in Q-Energy space.
|
|
* @param machine The machine description
|
|
* @param qe Input QE position
|
|
* @param angles output angles.
|
|
* @return 1 on success, a negative error code in case of problems
|
|
*/
|
|
int calcAllTasAngles(ptasMachine machine, tasQEPosition qe,
|
|
ptasAngles angles);
|
|
/**
|
|
* calculate the current position of the spectrometer in Q-E space from
|
|
* angles.
|
|
* @param machine The machine parameters
|
|
* @param angles The input angles
|
|
* @param qe The output Q-E position
|
|
* @return 1 on success, a negative error code on errors.
|
|
*/
|
|
int calcTasQEPosition(ptasMachine machine, tasAngles angles,
|
|
ptasQEPosition qe);
|
|
/*======================== POWDER MODE =================================
|
|
Powder mode is driving only QM, A3, SGGU, SGL will not be touched,
|
|
only energy and sample two theta will be driven.
|
|
========================================================================*/
|
|
/**
|
|
* calculate the angles for a specified energy and qm position (in qe).
|
|
* @param machine The machine constants of the spectrometer
|
|
* @param qe The energy, qm position desired.
|
|
* @param angles The angles for this qe position. Please ignore a3, sgu, sgl
|
|
* @return 1 on success, a negative error code else
|
|
*/
|
|
int calcTasPowderAngles(ptasMachine machine, tasQEPosition qe,
|
|
ptasAngles angles);
|
|
/**
|
|
* calculate the current energy qm position from angles.
|
|
* @param machine The spectrometer parameters.
|
|
* @param angles The angles as read from the motors
|
|
* @param qe The resulting qe position
|
|
* @return 1 on success, a negative error code on errors
|
|
*/
|
|
int calcTasPowderPosition(ptasMachine machine, tasAngles angles,
|
|
ptasQEPosition qe);
|
|
/**
|
|
* calculate the misalignment of the crystal towards the goniometers.
|
|
* This is for people who love to manually adjust their crystal
|
|
* until it is paralel with the goniometers which in turn helps them
|
|
* understand what they are doing.
|
|
* @param machine The spectrometer parameters.
|
|
* @param qe The current qe position
|
|
* @param misalign An output parameter which then holds the value
|
|
* of the misalignment.
|
|
* @return 1 on success, a negative error code on errors
|
|
*/
|
|
int calcTasMisalignment(ptasMachine machine, tasQEPosition qe, double *misalign);
|
|
/*======================= TAS Logic =====================================*/
|
|
/**
|
|
* set triple axis parameters, thereby taking the tasMode into account
|
|
* @param qe The Q Energy variable set to update
|
|
* @param tasMode The triple axis mode to apply
|
|
* @param tasVar The TAS variable to handle. This MUST be one of the
|
|
* defines at the top of this file.
|
|
* @param value The value to set for tasPar
|
|
*/
|
|
void setTasPar(ptasQEPosition qe, int tasMode, int tasVar, double value);
|
|
/**
|
|
* calculates the value of a TAS parameter from qe.
|
|
* @param qe The Q Energy psoition to extract data from
|
|
* @parm tasVar The TAS variable to extract. This MUST be one of the
|
|
* defines given at the top of this file.
|
|
* @return The value of the TAS variable.
|
|
*/
|
|
double getTasPar(tasQEPosition qe, int tasVar);
|
|
/**
|
|
* checks if a QE Position is in the scattering plane as defined by the
|
|
* planeNormal
|
|
* @param planeNormal The plane normal of the scattering plane
|
|
* @param qe The QE position to check
|
|
* @return 0 when not in plane,1 when in plane
|
|
*/
|
|
int isInPlane(MATRIX scatteringPlaneNormal, tasQEPosition qe);
|
|
/**
|
|
* calculate the normal of the scattering plane from two reflections
|
|
* @param qe1 QE Position of first reflection in scattering plane
|
|
* @param qe2 QE position of second reflection in scattering plane
|
|
* @return The scattering plane normal
|
|
*/
|
|
MATRIX calcScatteringPlaneNormal(tasQEPosition qe1, tasQEPosition qe2);
|
|
|
|
#endif
|