/*---------------------------------------------------------------------------
                             C r y s t

  This is a library of crystallographic utility routines for four
  circle diffractometers. It deals with all sorts of rotations and
  stuff. This is based on code originally developed by John Allibon 
  at ILL and reimplemented in C using a matrix-library.

  Mark Koennecke, July 2000
----------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include "matrix/matrix.h"
#include "cryst.h"

#define PIR 57.30

/*-------------------------------------------------------------------------
    chimat, calculate chi rotation matrix. The input angle is in degrees.
    The setting is Busing & Levy.
--------------------------------------------------------------------------*/

MATRIX chimat(double dAngle)
{
   MATRIX res;
   double dChi;

   res = mat_creat(3,3,ZERO_MATRIX);
   dChi = dAngle/PIR;
 
   res[0][0] = cos(dChi);
   res[0][2] = sin(dChi);
   res[1][1] = 1.;
   res[2][0] = -res[0][2];
   res[2][2] = res[0][0];

   return res;
}


/*-------------------------------------------------------------------------
    phimat, calculate phi rotation matrix. The input angle is in degrees.
    The setting is Busing & Levy.
--------------------------------------------------------------------------*/

MATRIX phimat(double dAngle)
{
   MATRIX res;
   double dPhi;

   res = mat_creat(3,3,ZERO_MATRIX);
   dPhi = dAngle/PIR;
 
   res[0][0] = cos(dPhi);
   res[0][1] = sin(dChi);
   res[2][2] = 1.;
   res[1][0] = -res[0][1];
   res[1][1] = res[0][0];

   return res;
}
/*-------------------------------------------------------------------------
    psimat, calculate psi rotation matrix. The input angle is in degrees.
    The setting is Busing & Levy.
--------------------------------------------------------------------------*/

MATRIX psimat(double dAngle)
{
   MATRIX res;
   double dPsi;

   res = mat_creat(3,3,ZERO_MATRIX);
   dPsi = dAngle/PIR;
 
   res[0][0] = 1.;
   res[1][1] = cos(dPsi);
   res[1][2] = -sin(dPsi);
   res[2][1] = -res[1][2];
   res[2][2] = res[1][1];

   return res;
}

/*-------------------------------------------------------------------------
  diffFromAngles calculates the diffraction vector from two theta, omega
  chi and phi. The angled need not be bissecting but it is assumed that
  the diffraction vector is in the equatorial plane.
--------------------------------------------------------------------------*/
 
MATRIX diffFromAngles(double wave, double tth, double om, 
                        double chi, double phi)
{
   MATRIX res, rot, dum, z;
   double dTh;

   dTh = (tth/2.)/PIR;
   res = mat_creat(3,1,ZERO_MATRIX);
   res[0][0] = (2.*sin(dTh)*cos(dTh))/wave;
   res[1][0] = (-2. *sin(dTh)*sin(dTh))/wave;

   /* undo omega rotation */
   rot = phimat(om);
   dum = mat_tran(rot);
   mat_free(rot);
   z = mat_mul(dum,res);
   mat_free(dum);
   mat_free(res);

   /* result is now z */
   
}

