rename HklPseudoAxisEngine -> HklEngine
[hkl.git] / hkl / hkl-pseudoaxis-k6c-hkl.c
blobcff53e29afb77d33ff7db60c63bbde7f38282abd
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-2012 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>
21 * Maria-Teresa Nunez-Pardo-de-Verra <tnunez@mail.desy.de>
22 * Jens Krüger <Jens.Krueger@frm2.tum.de>
24 #include <gsl/gsl_math.h>
25 #include <gsl/gsl_vector.h>
26 #include <gsl/gsl_sf.h>
28 #include <ccan/array_size/array_size.h>
30 #include "hkl-parameter-private.h"
31 #include "hkl-pseudoaxis-auto-private.h"
32 #include "hkl-pseudoaxis-common-hkl-private.h"
34 /***********************/
35 /* numerical functions */
36 /***********************/
38 static int _bissector_h_f1(const gsl_vector *x, void *params, gsl_vector *f)
40 const double mu = x->data[0];
41 const double komega = x->data[1];
42 const double kappa = x->data[2];
43 const double gamma = x->data[4];
44 double omega;
46 CHECK_NAN(x->data, x->size);
48 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
50 RUBh_minus_Q(x->data, params, f->data);
51 f->data[3] = fmod(omega, M_PI);
52 f->data[4] = fmod(gamma - 2 * fmod(mu, M_PI), 2*M_PI);
54 return GSL_SUCCESS;
57 static const HklFunction bissector_h_f1 = {
58 .function = _bissector_h_f1,
59 .size = 5,
62 static int _bissector_h_f2(const gsl_vector *x, void *params, gsl_vector *f)
64 const double mu = x->data[0];
65 const double komega = x->data[1];
66 const double kappa = x->data[2];
67 const double gamma = x->data[4];
68 double omega;
70 CHECK_NAN(x->data, x->size);
72 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) + M_PI_2;
74 RUBh_minus_Q(x->data, params, f->data);
75 f->data[3] = fmod(omega, M_PI);
76 f->data[4] = fmod(gamma - 2 * fmod(mu, M_PI), 2*M_PI);
79 return GSL_SUCCESS;
82 static const HklFunction bissector_h_f2 = {
83 .function = _bissector_h_f2,
84 .size = 5,
87 static int _constant_kphi_h_f1(const gsl_vector *x, void *params, gsl_vector *f)
89 const double komega = x->data[1];
90 const double kappa = x->data[2];
91 double omega;
93 CHECK_NAN(x->data, x->size);
95 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
97 RUBh_minus_Q(x->data, params, f->data);
98 f->data[3] = fmod(omega, M_PI);
100 return GSL_SUCCESS;
103 static const HklFunction constant_kphi_h_f1 = {
104 .function = _constant_kphi_h_f1,
105 .size = 4,
108 static int _constant_kphi_h_f2(const gsl_vector *x, void *params, gsl_vector *f)
110 const double komega = x->data[1];
111 const double kappa = x->data[2];
112 double omega;
114 CHECK_NAN(x->data, x->size);
116 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) + M_PI_2;
118 RUBh_minus_Q(x->data, params, f->data);
119 f->data[3] = fmod(omega, M_PI);
121 return GSL_SUCCESS;
124 static const HklFunction constant_kphi_h_f2 = {
125 .function = _constant_kphi_h_f2,
126 .size = 4,
129 static int _constant_phi_h_f1(const gsl_vector *x, void *params, gsl_vector *f)
131 const double komega = x->data[1];
132 const double kappa = x->data[2];
133 const double kphi = x->data[3];
134 double omega, phi, p;
136 CHECK_NAN(x->data, x->size);
138 p = atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD));
139 omega = komega + p - M_PI_2;
140 phi = kphi + p + M_PI_2;
142 RUBh_minus_Q(x->data, params, f->data);
143 f->data[3] = fmod(omega, M_PI);
144 f->data[4] = phi;
146 return GSL_SUCCESS;
149 static const HklFunction constant_phi_h_f1 = {
150 .function = _constant_phi_h_f1,
151 .size = 5,
154 static int _constant_phi_h_f2(const gsl_vector *x, void *params, gsl_vector *f)
156 const double komega = x->data[1];
157 const double kappa = x->data[2];
158 const double kphi = x->data[3];
159 double omega, phi, p;
161 CHECK_NAN(x->data, x->size);
163 p = atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD));
164 omega = komega + p + M_PI_2;
165 phi = kphi + p - M_PI_2;
167 RUBh_minus_Q(x->data, params, f->data);
168 f->data[3] = fmod(omega, M_PI);
169 f->data[4] = phi;
171 return GSL_SUCCESS;
174 static const HklFunction constant_phi_h_f2 = {
175 .function = _constant_phi_h_f2,
176 .size = 5,
179 static int _bissector_v(const gsl_vector *x, void *params, gsl_vector *f)
181 const double komega = x->data[0];
182 const double kappa = x->data[1];
183 const double delta = x->data[3];
184 double omega;
186 CHECK_NAN(x->data, x->size);
188 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
190 RUBh_minus_Q(x->data, params, f->data);
191 f->data[3] = fmod(delta - 2 * fmod(omega, M_PI), 2*M_PI);
193 return GSL_SUCCESS;
196 static const HklFunction bissector_v = {
197 .function = _bissector_v,
198 .size = 4,
201 static int _constant_omega_v(const gsl_vector *x, void *params, gsl_vector *f)
203 const double komega = x->data[0];
204 const double kappa = x->data[1];
205 double omega;
206 HklEngine *engine = params;
207 double omega0;
208 uint shit;
210 hkl_parameter_list_get_values(&engine->mode->parameters, &omega0, &shit);
212 CHECK_NAN(x->data, x->size);
214 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
216 RUBh_minus_Q(x->data, params, f->data);
217 f->data[3] = omega0 - omega;
219 return GSL_SUCCESS;
222 static const HklFunction constant_omega_v = {
223 .function = _constant_omega_v,
224 .size = 4,
227 static int _constant_chi_v(const gsl_vector *x, void *params, gsl_vector *f)
229 const double kappa = x->data[1];
230 double chi;
231 HklEngine *engine = params;
232 double chi0;
233 uint shit;
235 hkl_parameter_list_get_values(&engine->mode->parameters, &chi0, &shit);
237 CHECK_NAN(x->data, x->size);
239 chi = 2 * asin(sin(kappa/2.) * sin(50 * HKL_DEGTORAD));
241 RUBh_minus_Q(x->data, params, f->data);
242 f->data[3] = chi0 - chi;
244 return GSL_SUCCESS;
247 static const HklFunction constant_chi_v = {
248 .function = _constant_chi_v,
249 .size = 4,
252 static int _constant_phi_v(const gsl_vector *x, void *params, gsl_vector *f)
254 const double kappa = x->data[1];
255 const double kphi = x->data[2];
256 double phi;
257 HklEngine *engine = params;
258 double phi0;
259 uint shit;
261 hkl_parameter_list_get_values(&engine->mode->parameters, &phi0, &shit);
263 CHECK_NAN(x->data, x->size);
265 phi = kphi + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) + M_PI_2;
267 RUBh_minus_Q(x->data, params, f->data);
268 f->data[3] = phi0 - phi;
270 return GSL_SUCCESS;
273 static const HklFunction constant_phi_v = {
274 .function = _constant_phi_v,
275 .size = 4,
278 static int _double_diffraction_h(const gsl_vector *x, void *params, gsl_vector *f)
280 const double komega = x->data[1];
281 const double kappa = x->data[2];
282 double omega;
284 CHECK_NAN(x->data, x->size);
286 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
288 _double_diffraction(x->data, params, f->data);
289 f->data[4] = fmod(omega, M_PI);
291 return GSL_SUCCESS;
294 static const HklFunction double_diffraction_h = {
295 .function = _double_diffraction_h,
296 .size = 5,
299 static int _constant_incidence_func(const gsl_vector *x, void *params, gsl_vector *f)
301 static const HklVector Y = {
302 .data = {0, 1, 0},
304 double incidence;
305 double azimuth;
306 HklEngine *engine = params;
307 double parameters[5];
308 uint shit;
309 HklVector n;
310 double incidence0;
311 double azimuth0;
312 HklVector ki;
314 CHECK_NAN(x->data, x->size);
316 RUBh_minus_Q(x->data, params, f->data);
318 /* get the mode parameters */
319 hkl_parameter_list_get_values(&engine->mode->parameters,
320 parameters, &shit);
321 n.data[0] = parameters[0];
322 n.data[1] = parameters[1];
323 n.data[2] = parameters[2];
324 incidence0 = parameters[3];
325 azimuth0 = parameters[4];
327 /* compute the two angles */
330 /* first check that the mode was already initialized if not
331 * the surface is oriented along the nx, ny, nz axis for all
332 * diffractometer angles equal to zero */
333 if(engine->mode->geometry_init){
334 HklQuaternion q0 = engine->mode->geometry_init->holders[0].q;
336 hkl_quaternion_conjugate(&q0);
337 hkl_vector_rotated_quaternion(&n, &q0);
340 hkl_vector_rotated_quaternion(&n, &engine->geometry->holders[0].q);
342 hkl_source_compute_ki(&engine->geometry->source, &ki);
343 incidence = M_PI_2 - hkl_vector_angle(&n, &ki);
345 hkl_vector_project_on_plan(&n, &ki);
346 azimuth = hkl_vector_angle(&n, &Y);
348 f->data[3] = incidence0 - incidence;
349 f->data[4] = azimuth0 - azimuth;
351 return GSL_SUCCESS;
354 static const HklFunction constant_incidence_func = {
355 .function = _constant_incidence_func,
356 .size = 5,
359 /********/
360 /* mode */
361 /********/
363 static HklMode *bissector_vertical(void)
365 static const char* axes[] = {"komega", "kappa", "kphi", "delta"};
366 static const HklFunction *functions[] = {&bissector_v};
367 static const HklModeAutoInfo info = {
368 INFO_AUTO(__func__, axes, functions),
371 return hkl_mode_auto_new(&info,
372 &hkl_mode_operations);
375 static HklMode *constant_omega_vertical(void)
377 static const char* axes[] = {"komega", "kappa", "kphi", "delta"};
378 static const HklFunction *functions[] = {&constant_omega_v};
379 static const HklParameter parameters[] = {
380 {HKL_PARAMETER_DEFAULTS_ANGLE, .name = "omega"},
382 static const HklModeAutoInfo info = {
383 INFO_AUTO_WITH_PARAMS(__func__, axes, functions, parameters),
386 return hkl_mode_auto_new(&info,
387 &hkl_mode_operations);
390 static HklMode *constant_chi_vertical(void)
392 static const char* axes[] = {"komega", "kappa", "kphi", "delta"};
393 static const HklFunction *functions[] = {&constant_chi_v};
394 static const HklParameter parameters[] = {
395 {HKL_PARAMETER_DEFAULTS_ANGLE, .name = "chi"},
397 static const HklModeAutoInfo info = {
398 INFO_AUTO_WITH_PARAMS(__func__, axes, functions, parameters),
401 return hkl_mode_auto_new(&info,
402 &hkl_mode_operations);
405 static HklMode *constant_phi_vertical(void)
407 static const char* axes[] = {"komega", "kappa", "kphi", "delta"};
408 static const HklFunction *functions[] = {&constant_phi_v};
409 static const HklParameter parameters[] = {
410 {HKL_PARAMETER_DEFAULTS_ANGLE, .name = "phi"},
412 static const HklModeAutoInfo info = {
413 INFO_AUTO_WITH_PARAMS(__func__, axes, functions, parameters),
416 return hkl_mode_auto_new(&info,
417 &hkl_mode_operations);
420 static HklMode *lifting_detector_kphi(void)
422 static const char* axes[] = {"kphi", "gamma", "delta"};
423 static const HklFunction *functions[] = {&RUBh_minus_Q_func};
424 static const HklModeAutoInfo info = {
425 INFO_AUTO(__func__, axes, functions),
428 return hkl_mode_auto_new(&info,
429 &hkl_mode_operations);
432 static HklMode *lifting_detector_komega(void)
434 static const char* axes[] = {"komega", "gamma", "delta"};
435 static const HklFunction *functions[] = {&RUBh_minus_Q_func};
436 static const HklModeAutoInfo info = {
437 INFO_AUTO(__func__, axes, functions),
440 return hkl_mode_auto_new(&info,
441 &hkl_mode_operations);
444 static HklMode *lifting_detector_mu(void)
446 static const char* axes[] = {"mu", "gamma", "delta"};
447 static const HklFunction *functions[] = {&RUBh_minus_Q_func};
448 static const HklModeAutoInfo info = {
449 INFO_AUTO(__func__, axes, functions),
452 return hkl_mode_auto_new(&info,
453 &hkl_mode_operations);
456 static HklMode *double_diffraction_vertical(void)
458 static const char* axes[] = {"komega", "kappa", "kphi", "delta"};
459 static const HklFunction *functions[] = {&double_diffraction_func};
460 static const HklParameter parameters[] = {
461 {HKL_PARAMETER_DEFAULTS, .name = "h2", .range = {.min=-1, .max=1}, ._value = 1,},
462 {HKL_PARAMETER_DEFAULTS, .name = "k2", .range = {.min=-1, .max=1}, ._value = 1,},
463 {HKL_PARAMETER_DEFAULTS, .name = "l2", .range = {.min=-1, .max=1}, ._value = 1,},
465 static const HklModeAutoInfo info = {
466 INFO_AUTO_WITH_PARAMS(__func__, axes, functions, parameters),
469 return hkl_mode_auto_new(&info,
470 &hkl_mode_operations);
473 static HklMode *bissector_horizontal(void)
475 static const char* axes[] = {"mu", "komega", "kappa", "kphi", "gamma"};
476 static const HklFunction *functions[] = {&bissector_h_f1, &bissector_h_f2};
477 static const HklModeAutoInfo info = {
478 INFO_AUTO(__func__, axes, functions),
481 return hkl_mode_auto_new(&info,
482 &hkl_mode_operations);
485 static HklMode *constant_phi_horizontal(void)
487 static const char* axes[] = {"mu", "komega", "kappa", "kphi", "gamma"};
488 static const HklFunction *functions[] = {&constant_phi_h_f1, &constant_phi_h_f2};
489 static const HklParameter parameters[] = {
490 {HKL_PARAMETER_DEFAULTS_ANGLE, .name = "phi",},
492 static const HklModeAutoInfo info = {
493 INFO_AUTO_WITH_PARAMS(__func__, axes, functions, parameters),
496 return hkl_mode_auto_new(&info,
497 &hkl_mode_operations);
500 static HklMode *constant_kphi_horizontal(void)
502 static const char* axes[] = {"mu", "komega", "kappa", "gamma"};
503 static const HklFunction *functions[] = {&constant_kphi_h_f1, &constant_kphi_h_f2};
504 static const HklModeAutoInfo info = {
505 INFO_AUTO(__func__, axes, functions),
508 return hkl_mode_auto_new(&info,
509 &hkl_mode_operations);
512 static HklMode *double_diffraction_horizontal(void)
514 static const char* axes[] = {"mu", "komega", "kappa", "kphi", "gamma"};
515 static const HklFunction *functions[] = {&double_diffraction_h};
516 static const HklParameter parameters[] = {
517 {HKL_PARAMETER_DEFAULTS, .name = "h2", .range = {.min=-1, .max=1}, ._value = 1,},
518 {HKL_PARAMETER_DEFAULTS, .name = "k2", .range = {.min=-1, .max=1}, ._value = 1,},
519 {HKL_PARAMETER_DEFAULTS, .name = "l2", .range = {.min=-1, .max=1}, ._value = 1,},
521 static const HklModeAutoInfo info = {
522 INFO_AUTO_WITH_PARAMS(__func__, axes, functions, parameters),
525 return hkl_mode_auto_new(&info,
526 &hkl_mode_operations);
529 static HklMode *psi_constant_vertical(void)
531 static const char* axes[] = {"komega", "kappa", "kphi", "delta"};
532 static const HklFunction *functions[] = {&psi_constant_vertical_func};
533 static const HklParameter parameters[] = {
534 {HKL_PARAMETER_DEFAULTS, .name = "h2", .range = {.min=-1, .max=1}, ._value = 1,},
535 {HKL_PARAMETER_DEFAULTS, .name = "k2", .range = {.min=-1, .max=1}, ._value = 0,},
536 {HKL_PARAMETER_DEFAULTS, .name = "l2", .range = {.min=-1, .max=1}, ._value = 0,},
537 {HKL_PARAMETER_DEFAULTS_ANGLE, .name = "psi"},
539 static const HklModeAutoInfo info = {
540 INFO_AUTO_WITH_PARAMS(__func__, axes, functions, parameters),
543 return hkl_mode_auto_new(&info,
544 &psi_constant_vertical_mode_operations);
547 static HklMode *constant_incidence(void)
549 static const char* axes[] = {"komega", "kappa", "kphi", "gamma", "delta"};
550 static const HklFunction *functions[] = {&constant_incidence_func};
551 static const HklParameter parameters[] = {
552 {HKL_PARAMETER_DEFAULTS, .name = "x", .range = {.min=-1, .max=1}, ._value = 1,},
553 {HKL_PARAMETER_DEFAULTS, .name = "y", .range = {.min=-1, .max=1}, ._value = 1,},
554 {HKL_PARAMETER_DEFAULTS, .name = "z", .range = {.min=-1, .max=1}, ._value = 1,},
555 {HKL_PARAMETER_DEFAULTS_ANGLE, .name = "incidence"},
556 {HKL_PARAMETER_DEFAULTS_ANGLE, .name = "aximuth", ._value = M_PI_2,},
558 static const HklModeAutoInfo info = {
559 INFO_AUTO_WITH_PARAMS(__func__, axes, functions, parameters),
562 return hkl_mode_auto_new(&info,
563 &hkl_mode_operations);
566 /**********************/
567 /* pseudo axis engine */
568 /**********************/
570 HklEngine *hkl_engine_k6c_hkl_new(void)
572 HklEngine *self;
573 HklMode *default_mode;
575 self = hkl_engine_hkl_new();
577 default_mode = bissector_vertical();
578 hkl_engine_add_mode(self, default_mode);
579 hkl_engine_select_mode(self, default_mode);
581 hkl_engine_add_mode(self, constant_omega_vertical());
582 hkl_engine_add_mode(self, constant_chi_vertical());
583 hkl_engine_add_mode(self, constant_phi_vertical());
584 hkl_engine_add_mode(self, lifting_detector_kphi());
585 hkl_engine_add_mode(self, lifting_detector_komega());
586 hkl_engine_add_mode(self, lifting_detector_mu());
587 hkl_engine_add_mode(self, double_diffraction_vertical());
588 hkl_engine_add_mode(self, bissector_horizontal());
589 hkl_engine_add_mode(self, constant_phi_horizontal());
590 hkl_engine_add_mode(self, constant_kphi_horizontal());
591 hkl_engine_add_mode(self, double_diffraction_horizontal());
592 hkl_engine_add_mode(self, psi_constant_vertical());
593 hkl_engine_add_mode(self, constant_incidence());
595 return self;