1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/*
* cell.c
*
* Unit Cell Calculations
*
* (c) 2007-2009 Thomas White <thomas.white@desy.de>
*
* template_index - Indexing diffraction patterns by template matching
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "cell.h"
#include "utils.h"
/* Update the cartesian representation from the crystallographic one */
static void cell_update_cartesian(UnitCell *cell)
{
double tmp, V, cosalphastar, cstar;
if ( !cell ) return;
/* a in terms of x, y and z
* +a (cryst) is defined to lie along +x (cart) */
cell->ax = cell->a;
cell->ay = 0.0;
cell->az = 0.0;
/* b in terms of x, y and z
* b (cryst) is defined to lie in the xy (cart) plane */
cell->bx = cell->b*cos(cell->gamma);
cell->by = cell->b*sin(cell->gamma);
cell->bz = 0.0;
tmp = cos(cell->alpha)*cos(cell->alpha)
- cos(cell->beta)*cos(cell->beta)
- cos(cell->gamma)*cos(cell->gamma)
+ 2.0*cos(cell->alpha)*cos(cell->beta)*cos(cell->gamma);
V = cell->a * cell->b * cell->c * sqrt(1.0 - tmp);
cosalphastar = cos(cell->beta)*cos(cell->gamma) - cos(cell->alpha);
cosalphastar /= sin(cell->beta)*sin(cell->gamma);
cstar = (cell->a * cell->b * sin(cell->gamma))/V;
/* c in terms of x, y and z */
cell->cx = cell->c*cos(cell->beta);
cell->cy = -cell->c*sin(cell->beta)*cosalphastar;
cell->cz = 1.0/cstar;
}
/* Update the crystallographic representation from the cartesian one */
static void cell_update_crystallographic(UnitCell *cell)
{
if ( !cell ) return;
cell->a = modulus(cell->ax, cell->ay, cell->az);
cell->b = modulus(cell->bx, cell->by, cell->bz);
cell->c = modulus(cell->cx, cell->cy, cell->cz);
cell->alpha = angle_between(cell->bx, cell->by, cell->bz,
cell->cx, cell->cy, cell->cz);
cell->beta = angle_between(cell->ax, cell->ay, cell->az,
cell->cx, cell->cy, cell->cz);
cell->gamma = angle_between(cell->ax, cell->ay, cell->az,
cell->bx, cell->by, cell->bz);
printf("a=%f nm\n", cell->a);
printf("b=%f nm\n", cell->b);
printf("c=%f nm\n", cell->c);
printf("alpha = %f deg\n", rad2deg(cell->alpha));
printf(" beta = %f deg\n", rad2deg(cell->beta));
printf("gamma = %f deg\n", rad2deg(cell->gamma));
}
UnitCell *cell_new()
{
UnitCell *cell;
cell = malloc(sizeof(UnitCell));
if ( !cell ) return NULL;
cell->a = 1.0;
cell->b = 1.0;
cell->c = 1.0;
cell->alpha = M_PI_2;
cell->beta = M_PI_2;
cell->gamma = M_PI_2;
cell_update_cartesian(cell);
return cell;
}
void cell_set_parameters(UnitCell *cell, double a, double b, double c,
double alpha, double beta, double gamma)
{
if ( !cell ) return;
cell->a = a;
cell->b = b;
cell->c = c;
cell->alpha = alpha;
cell->beta = beta;
cell->gamma = gamma;
cell_update_cartesian(cell);
}
void cell_set_cartesian(UnitCell *cell,
double ax, double ay, double az,
double bx, double by, double bz,
double cx, double cy, double cz)
{
if ( !cell ) return;
cell->ax = ax; cell->ay = ay; cell->az = az;
cell->bx = bx; cell->by = by; cell->bz = bz;
cell->cx = cx; cell->cy = cy; cell->cz = cz;
cell_update_crystallographic(cell);
}
UnitCell *cell_new_from_parameters(double a, double b, double c,
double alpha, double beta, double gamma)
{
UnitCell *cell;
cell = cell_new();
if ( !cell ) return NULL;
cell_set_parameters(cell, a, b, c, alpha, beta, gamma);
return cell;
}
|