1 /* This file is part of the hkl library.
3 * The hkl library is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * The hkl library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with the hkl library. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright (C) 2003-2010 Synchrotron SOLEIL
17 * L'Orme des Merisiers Saint-Aubin
18 * BP 48 91192 GIF-sur-YVETTE CEDEX
20 * Authors: Picca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>
25 #include "hkl/hkl-lattice.h"
26 #include "hkl/hkl-unit.h"
30 static int check_lattice_param(double a
, double b
, double c
,
31 double alpha
, double beta
, double gamma
)
33 double D
= 1. - cos(alpha
)*cos(alpha
) - cos(beta
)*cos(beta
)
34 - cos(gamma
)*cos(gamma
) + 2. * cos(alpha
)*cos(beta
)*cos(gamma
);
44 HklLattice
*hkl_lattice_new(double a
, double b
, double c
,
45 double alpha
, double beta
, double gamma
)
47 HklLattice
*self
= NULL
;
48 if(!check_lattice_param(a
, b
, c
, alpha
, beta
, gamma
)) {
49 self
= HKL_MALLOC(HklLattice
);
51 self
->a
= hkl_parameter_new("a", 0, a
, a
+10,
55 self
->b
= hkl_parameter_new("b", 0, b
, b
+10,
59 self
->c
= hkl_parameter_new("c", 0, c
, c
+10,
63 self
->alpha
= hkl_parameter_new("alpha", -M_PI
, alpha
, M_PI
,
67 self
->beta
= hkl_parameter_new("beta", -M_PI
, beta
, M_PI
,
71 self
->gamma
= hkl_parameter_new("gamma", -M_PI
, gamma
, M_PI
,
80 HklLattice
*hkl_lattice_new_copy(HklLattice
const *self
)
82 HklLattice
*copy
= NULL
;
84 copy
= HKL_MALLOC(HklLattice
);
86 copy
->a
= hkl_parameter_new_copy(self
->a
);
87 copy
->b
= hkl_parameter_new_copy(self
->b
);
88 copy
->c
= hkl_parameter_new_copy(self
->c
);
89 copy
->alpha
= hkl_parameter_new_copy(self
->alpha
);
90 copy
->beta
= hkl_parameter_new_copy(self
->beta
);
91 copy
->gamma
= hkl_parameter_new_copy(self
->gamma
);
96 HklLattice
* hkl_lattice_new_default(void)
98 return hkl_lattice_new(1.54, 1.54, 1.54,
99 90*HKL_DEGTORAD
, 90*HKL_DEGTORAD
, 90*HKL_DEGTORAD
);
102 void hkl_lattice_free(HklLattice
*self
)
104 hkl_parameter_free(self
->a
);
105 hkl_parameter_free(self
->b
);
106 hkl_parameter_free(self
->c
);
107 hkl_parameter_free(self
->alpha
);
108 hkl_parameter_free(self
->beta
);
109 hkl_parameter_free(self
->gamma
);
113 int hkl_lattice_set(HklLattice
*self
,
114 double a
, double b
, double c
,
115 double alpha
, double beta
, double gamma
)
119 if(!check_lattice_param(a
, b
, c
, alpha
, beta
, gamma
)) {
123 self
->alpha
->value
= alpha
;
124 self
->beta
->value
= beta
;
125 self
->gamma
->value
= gamma
;
132 * Get the B matrix from the l parameters
134 int hkl_lattice_get_B(HklLattice
const *self
, HklMatrix
*B
)
137 double c_alpha
, s_alpha
;
138 double c_beta
, s_beta
;
139 double c_gamma
, s_gamma
;
140 double b11
, b22
, tmp
;
142 c_alpha
= cos(self
->alpha
->value
);
143 c_beta
= cos(self
->beta
->value
);
144 c_gamma
= cos(self
->gamma
->value
);
145 D
= 1 - c_alpha
*c_alpha
- c_beta
*c_beta
- c_gamma
*c_gamma
146 + 2*c_alpha
*c_beta
*c_gamma
;
153 s_alpha
= sin(self
->alpha
->value
);
154 s_beta
= sin(self
->beta
->value
);
155 s_gamma
= sin(self
->gamma
->value
);
157 b11
= HKL_TAU
/ (self
->b
->value
* s_alpha
);
158 b22
= HKL_TAU
/ self
->c
->value
;
161 B
->data
[0][0] = HKL_TAU
* s_alpha
/ (self
->a
->value
* D
);
162 B
->data
[0][1] = b11
/ D
* (c_alpha
*c_beta
- c_gamma
);
163 B
->data
[0][2] = tmp
/ D
* (c_gamma
*c_alpha
- c_beta
);
167 B
->data
[1][2] = tmp
/ (s_beta
*s_gamma
) * (c_beta
*c_gamma
- c_alpha
);
177 * hkl_lattice_get_1_B:
178 * @self: the @HklLattice
179 * @B: the @HklMatrix returned
181 * Compute the invert of B (needed by the hkl_sample_set_UB method)
182 * should be optimized
184 * Returns: HKL_SUCCESS or HKL_FAIL depending of the success of the
187 int hkl_lattice_get_1_B(const HklLattice
*self
, HklMatrix
*B
)
201 * first compute the B matrix
206 hkl_lattice_get_B(self
, &tmp
);
209 * now invert this triangular matrix
218 B
->data
[0][0] = 1 / a
;
219 B
->data
[0][1] = -b
/ a
/ d
;
220 B
->data
[0][2] = (b
* e
- d
* c
) / a
/ d
/ f
;
223 B
->data
[1][1] = 1 / d
;
224 B
->data
[1][2] = -e
/ d
/ f
;
228 B
->data
[2][2] = 1 / f
;
233 int hkl_lattice_reciprocal(HklLattice
const *self
, HklLattice
*reciprocal
)
235 double c_alpha
, c_beta
, c_gamma
;
236 double s_alpha
, s_beta
, s_gamma
;
237 double c_beta1
, c_beta2
, c_beta3
;
238 double s_beta1
, s_beta2
, s_beta3
;
239 double s_beta_s_gamma
, s_gamma_s_alpha
, s_alpha_s_beta
;
242 c_alpha
= cos(self
->alpha
->value
);
243 c_beta
= cos(self
->beta
->value
);
244 c_gamma
= cos(self
->gamma
->value
);
245 D
= 1 - c_alpha
*c_alpha
- c_beta
*c_beta
- c_gamma
*c_gamma
246 + 2*c_alpha
*c_beta
*c_gamma
;
253 s_alpha
= sin(self
->alpha
->value
);
254 s_beta
= sin(self
->beta
->value
);
255 s_gamma
= sin(self
->gamma
->value
);
257 s_beta_s_gamma
= s_beta
* s_gamma
;
258 s_gamma_s_alpha
= s_gamma
* s_alpha
;
259 s_alpha_s_beta
= s_alpha
* s_beta
;
261 c_beta1
= (c_beta
* c_gamma
- c_alpha
) / s_beta_s_gamma
;
262 c_beta2
= (c_gamma
* c_alpha
- c_beta
) / s_gamma_s_alpha
;
263 c_beta3
= (c_alpha
* c_beta
- c_gamma
) / s_alpha_s_beta
;
264 s_beta1
= D
/ s_beta_s_gamma
;
265 s_beta2
= D
/ s_gamma_s_alpha
;
266 s_beta3
= D
/ s_alpha_s_beta
;
268 reciprocal
->a
->value
= HKL_TAU
* s_alpha
/ (self
->a
->value
* D
);
269 reciprocal
->b
->value
= HKL_TAU
* s_beta
/ (self
->b
->value
* D
);
270 reciprocal
->c
->value
= HKL_TAU
* s_gamma
/ (self
->c
->value
* D
);
271 reciprocal
->alpha
->value
= atan2(s_beta1
, c_beta1
);
272 reciprocal
->beta
->value
= atan2(s_beta2
, c_beta2
);
273 reciprocal
->gamma
->value
= atan2(s_beta3
, c_beta3
);
278 void hkl_lattice_randomize(HklLattice
*self
)
280 static HklVector vector_x
= {{1, 0, 0}};
283 unsigned int angles_to_randomize
;
285 /* La valeur des angles alpha, beta et gamma ne sont pas indépendant. */
286 /* Il faut donc gérer les différents cas. */
287 hkl_parameter_randomize(self
->a
);
288 hkl_parameter_randomize(self
->b
);
289 hkl_parameter_randomize(self
->c
);
291 angles_to_randomize
= self
->alpha
->fit
294 switch (angles_to_randomize
) {
298 if (self
->alpha
->fit
) {
300 a
= b
= c
= vector_x
;
303 hkl_vector_randomize_vector(&axe
, &a
);
304 hkl_vector_rotated_around_vector(&b
, &axe
, self
->gamma
->value
);
307 hkl_vector_randomize_vector(&axe
, &a
);
308 hkl_vector_rotated_around_vector(&c
, &axe
, self
->beta
->value
);
310 /* compute the alpha angle. */
311 self
->alpha
->value
= hkl_vector_angle(&b
, &c
);
312 } else if (self
->beta
->fit
) {
317 hkl_vector_randomize_vector(&axe
, &a
);
318 hkl_vector_rotated_around_vector(&b
, &axe
, self
->gamma
->value
);
322 hkl_vector_randomize_vector(&axe
, &b
);
323 hkl_vector_rotated_around_vector(&c
, &axe
, self
->alpha
->value
);
326 self
->beta
->value
= hkl_vector_angle(&a
, &c
);
332 hkl_vector_randomize_vector(&axe
, &a
);
333 hkl_vector_rotated_around_vector(&c
, &axe
, self
->beta
->value
);
337 hkl_vector_randomize_vector(&axe
, &c
);
338 hkl_vector_rotated_around_vector(&b
, &axe
, self
->alpha
->value
);
341 self
->gamma
->value
= hkl_vector_angle(&a
, &b
);
345 if (self
->alpha
->fit
) {
346 if (self
->beta
->fit
) {
351 hkl_vector_randomize_vector(&axe
, &a
);
352 hkl_vector_rotated_around_vector(&b
, &axe
, self
->gamma
->value
);
355 hkl_vector_randomize_vector_vector(&c
, &a
, &b
);
357 self
->alpha
->value
= hkl_vector_angle(&b
, &c
);
358 self
->beta
->value
= hkl_vector_angle(&a
, &c
);
364 hkl_vector_randomize_vector(&axe
, &a
);
365 hkl_vector_rotated_around_vector(&c
, &axe
, self
->beta
->value
);
368 hkl_vector_randomize_vector_vector(&b
, &a
, &c
);
370 self
->alpha
->value
= hkl_vector_angle(&b
, &c
);
371 self
->gamma
->value
= hkl_vector_angle(&a
, &b
);
378 hkl_vector_randomize_vector(&axe
, &b
);
379 hkl_vector_rotated_around_vector(&c
, &axe
, self
->alpha
->value
);
382 hkl_vector_randomize_vector_vector(&a
, &b
, &c
);
384 self
->beta
->value
= hkl_vector_angle(&a
, &c
);
385 self
->gamma
->value
= hkl_vector_angle(&a
, &b
);
389 hkl_vector_randomize(&a
);
390 hkl_vector_randomize_vector(&b
, &a
);
391 hkl_vector_randomize_vector_vector(&c
, &b
, &a
);
393 self
->alpha
->value
= hkl_vector_angle(&b
, &c
);
394 self
->beta
->value
= hkl_vector_angle(&a
, &c
);
395 self
->gamma
->value
= hkl_vector_angle(&a
, &b
);
400 void hkl_lattice_fprintf(FILE *f
, HklLattice
const *self
)
403 hkl_parameter_fprintf(f
, self
->a
);
405 hkl_parameter_fprintf(f
, self
->b
);
407 hkl_parameter_fprintf(f
, self
->c
);
409 hkl_parameter_fprintf(f
, self
->alpha
);
411 hkl_parameter_fprintf(f
, self
->beta
);
413 hkl_parameter_fprintf(f
, self
->gamma
);