/** * this is a little library for performing crystallographic cell transformations * for SICS. Some of the actual code was lifted from the Risoe program tascom. * * copyright: see file COPYRIGHT * * Mark Koennecke, March 2005 */ #include #include #include #include "trigd.h" #include "cell.h" /* define constants */ #ifndef PI #define PI (3.1415926536) /* pi */ #endif #define TWOPI (2*PI) /* 2*pi */ /***************************************************************************** * default value for a cell ****************************************************************************/ void defaultCell(plattice cell){ cell->a = 1.; cell->b = 1.; cell->c = 1.; cell->alpha = 90.; cell->beta = 90.; cell->gamma = 90.; } /******************************************************************************* * Transform direct lattice to reciprocal lattice. *******************************************************************************/ int directToReciprocalLattice(lattice direct, plattice reciprocal) { double alfa, beta, gamma; double cos_alfa, cos_beta, cos_gamma; double sin_alfa, sin_beta, sin_gamma; double ad, bd, cd; double arg, vol; alfa = direct.alpha; beta = direct.beta; gamma = direct.gamma; cos_alfa = Cosd (alfa); cos_beta = Cosd (beta); cos_gamma = Cosd (gamma); sin_alfa = Sind (alfa); sin_beta = Sind (beta); sin_gamma = Sind (gamma); reciprocal->alpha = Acosd ((cos_beta*cos_gamma - cos_alfa)/sin_beta/sin_gamma); reciprocal->beta =Acosd ((cos_alfa*cos_gamma - cos_beta)/sin_alfa/sin_gamma); reciprocal->gamma = Acosd ((cos_alfa*cos_beta - cos_gamma)/sin_alfa/sin_beta); ad = direct.a; bd = direct.b; cd = direct.c; arg = 1 + 2*cos_alfa*cos_beta*cos_gamma - cos_alfa*cos_alfa - cos_beta*cos_beta - cos_gamma*cos_gamma; if (arg < 0.0) { return REC_NO_VOLUME; } vol = ad*bd*cd*sqrt (arg); reciprocal->a = bd*cd*sin_alfa/vol; reciprocal->b = ad*cd*sin_beta/vol; reciprocal->c = bd*ad*sin_gamma/vol; return (0); } /******************************************************************************* * Transform reciprocal lattice to direct lattice. *******************************************************************************/ int reciprocalToDirectLattice(lattice reciprocal, plattice direct) { double alfa, beta, gamma; double cos_alfa, cos_beta, cos_gamma; double sin_alfa, sin_beta, sin_gamma; double ar, br, cr; double arg, vol; alfa = reciprocal.alpha; beta = reciprocal.beta; gamma = reciprocal.gamma; cos_alfa = Cosd (alfa); cos_beta = Cosd (beta); cos_gamma = Cosd (gamma); sin_alfa = Sind (alfa); sin_beta = Sind (beta); sin_gamma = Sind (gamma); direct->alpha = Acosd ((cos_beta*cos_gamma - cos_alfa)/sin_beta/sin_gamma); direct->beta = Acosd ((cos_alfa*cos_gamma - cos_beta)/sin_alfa/sin_gamma); direct->gamma = Acosd ((cos_alfa*cos_beta - cos_gamma)/sin_alfa/sin_beta); ar = reciprocal.a; br = reciprocal.b; cr = reciprocal.c; arg = 1 + 2*cos_alfa*cos_beta*cos_gamma - cos_alfa*cos_alfa - cos_beta*cos_beta - cos_gamma*cos_gamma; if (arg < 0.0) { return REC_NO_VOLUME; } vol = ar*br*cr*sqrt (arg); direct->a = br*cr*sin_alfa/vol; direct->b = ar*cr*sin_beta/vol; direct->c = br*ar*sin_gamma/vol; return (0); } /*************************************************************************************** * Build a B matrix ***************************************************************************************/ int calculateBMatrix(lattice direct, MATRIX B) { lattice reciprocal; int status; assert(MatRow(B) == 3); assert(MatCol(B) == 3); status = directToReciprocalLattice(direct,&reciprocal); if(status < 0) { return status; } mat_fill(B,ZERO_MATRIX); /* top row */ B[0][0] = reciprocal.a; B[0][1] = reciprocal.b*Cosd(reciprocal.gamma); B[0][2] = reciprocal.c*Cosd(reciprocal.beta); /* middle row */ B[1][1] = reciprocal.b*Sind(reciprocal.gamma); B[1][2] = -reciprocal.c*Sind(reciprocal.beta)*Cosd(direct.alpha); /* bottom row */ B[2][2] = 1./direct.c; return 1; } /*--------------------------------------------------------------------------*/ int cellFromUB(MATRIX UB, plattice direct){ MATRIX UBTRANS, GINV, G; UBTRANS = mat_tran(UB); if(UBTRANS == NULL){ return CELLNOMEMORY; } GINV = mat_mul(UBTRANS,UB); if(GINV == NULL){ mat_free(UBTRANS); return CELLNOMEMORY; } G = mat_inv(GINV); if(G == NULL){ mat_free(UBTRANS); mat_free(GINV); return CELLNOMEMORY; } direct->a = sqrt(G[0][0]); direct->b = sqrt(G[1][1]); direct->c = sqrt(G[2][2]); direct->alpha = Acosd(G[1][2]/(direct->b * direct->c)); direct->beta = Acosd(G[2][0]/(direct->a * direct->c)); direct->gamma = Acosd(G[0][1]/(direct->a * direct->c)); return 1; }