upgrading copyright year from 2015 to 2016
[hkl.git] / hkl / hkl-engine-k4c.c
blob714e6f32a0a583c169bf29fa0cccff9f5ea8f923
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-2016 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>
22 #include <gsl/gsl_sys.h> // for gsl_isnan
23 #include "hkl-factory-private.h" // for autodata_factories_, etc
24 #include "hkl-pseudoaxis-common-eulerians-private.h"
25 #include "hkl-pseudoaxis-common-q-private.h" // for hkl_engine_q2_new, etc
26 #include "hkl-pseudoaxis-common-hkl-private.h" // for RUBh_minus_Q, etc
27 #include "hkl-pseudoaxis-common-psi-private.h" // for hkl_engine_psi_new, etc
28 #include "hkl-pseudoaxis-common-readonly-private.h"
30 #define KOMEGA "komega"
31 #define KAPPA "kappa"
32 #define KPHI "kphi"
33 #define TTH "tth"
35 static void hkl_geometry_list_multiply_k4c_real(HklGeometryList *self,
36 HklGeometryListItem *item)
38 HklGeometry *geometry;
39 HklGeometry *copy;
40 double komega, komegap;
41 double kappa, kappap;
42 double kphi, kphip;
44 geometry = item->geometry;
45 komega = hkl_parameter_value_get(darray_item(geometry->axes, 0), HKL_UNIT_DEFAULT);
46 kappa = hkl_parameter_value_get(darray_item(geometry->axes, 1), HKL_UNIT_DEFAULT);
47 kphi = hkl_parameter_value_get(darray_item(geometry->axes, 2), HKL_UNIT_DEFAULT);
49 kappa_2_kappap(komega, kappa, kphi, 50 * HKL_DEGTORAD, &komegap, &kappap, &kphip);
51 copy = hkl_geometry_new_copy(geometry);
52 /* TODO parameter list for the geometry */
53 hkl_parameter_value_set(darray_item(copy->axes, 0), komegap, HKL_UNIT_DEFAULT, NULL);
54 hkl_parameter_value_set(darray_item(copy->axes, 1), kappap, HKL_UNIT_DEFAULT, NULL);
55 hkl_parameter_value_set(darray_item(copy->axes, 2), kphip, HKL_UNIT_DEFAULT, NULL);
57 hkl_geometry_update(copy);
58 hkl_geometry_list_add(self, copy);
59 hkl_geometry_free(copy);
62 /************/
63 /* hkl mode */
64 /************/
66 /* bissector */
68 static int _bissector_f1(const gsl_vector *x, void *params, gsl_vector *f)
70 const double komega = x->data[0];
71 const double kappa = x->data[1];
72 const double tth = x->data[3];
73 double omega;
75 CHECK_NAN(x->data, x->size);
77 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) + M_PI_2;
79 RUBh_minus_Q(x->data, params, f->data);
80 f->data[3] = fmod(tth - 2 * fmod(omega, M_PI), 2*M_PI);
82 return GSL_SUCCESS;
85 static const HklFunction bissector_f1 = {
86 .function = _bissector_f1,
87 .size = 4,
90 static int _bissector_f2(const gsl_vector *x, void *params, gsl_vector *f)
92 const double komega = x->data[0];
93 const double kappa = x->data[1];
94 const double tth = x->data[3];
95 double omega;
97 CHECK_NAN(x->data, x->size);
99 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
101 RUBh_minus_Q(x->data, params, f->data);
102 f->data[3] = fmod(tth - 2 * fmod(omega, M_PI), 2*M_PI);
104 return GSL_SUCCESS;
107 static const HklFunction bissector_f2 = {
108 .function = _bissector_f2,
109 .size = 4,
112 static HklMode *bissector(void)
114 static const char* axes[] = {KOMEGA, KAPPA, KPHI, TTH};
115 static const HklFunction *functions[] = {&bissector_f1, &bissector_f2};
116 static const HklModeAutoInfo info = {
117 HKL_MODE_AUTO_INFO(__func__, axes, axes, functions),
120 return hkl_mode_auto_new(&info,
121 &hkl_mode_operations,
122 TRUE);
125 /* constant omega */
127 static int _constant_omega_f1(const gsl_vector *x, void *params, gsl_vector *f)
129 double const komega = x->data[0];
130 double const kappa = x->data[1];
131 double omega;
132 HklEngine *engine = params;
133 double omega0 = darray_item(engine->mode->parameters, 0)->_value;
135 CHECK_NAN(x->data, x->size);
137 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
139 RUBh_minus_Q(x->data, params, f->data);
140 f->data[3] = omega0 - omega;
142 return GSL_SUCCESS;
145 static const HklFunction constant_omega_f1 = {
146 .function = _constant_omega_f1,
147 .size = 4,
150 static int _constant_omega_f2(const gsl_vector *x, void *params, gsl_vector *f)
152 const double komega = x->data[0];
153 const double kappa = x->data[1];
154 double omega;
155 HklEngine *engine = params;
156 double omega0 = darray_item(engine->mode->parameters, 0)->_value;
158 CHECK_NAN(x->data, x->size);
160 omega = komega + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) + M_PI_2;
162 RUBh_minus_Q(x->data, params, f->data);
163 f->data[3] = omega0 - omega;
165 return GSL_SUCCESS;
168 static const HklFunction constant_omega_f2 = {
169 .function = _constant_omega_f2,
170 .size = 4,
173 static HklMode *constant_omega(void)
175 static const char* axes[] = {KOMEGA, KAPPA, KPHI, TTH};
176 static const HklFunction *functions[] = {&constant_omega_f1, &constant_omega_f2};
177 static const HklModeAutoInfo info = {
178 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
179 functions, constant_omega_parameters),
182 return hkl_mode_auto_new(&info,
183 &hkl_mode_operations,
184 TRUE);
187 /* constant chi */
189 static int _constant_chi_f1(const gsl_vector *x, void *params, gsl_vector *f)
191 const double kappa = x->data[1];
192 double chi;
193 HklEngine *engine = params;
194 double chi0 = darray_item(engine->mode->parameters, 0)->_value;
196 CHECK_NAN(x->data, x->size);
198 chi = 2 * asin(sin(kappa/2.) * sin(50 * HKL_DEGTORAD));
200 RUBh_minus_Q(x->data, params, f->data);
201 f->data[3] = chi0 - chi;
203 return GSL_SUCCESS;
206 static const HklFunction constant_chi_f1 = {
207 .function = _constant_chi_f1,
208 .size = 4,
211 static int _constant_chi_f2(const gsl_vector *x, void *params, gsl_vector *f)
213 const double kappa = x->data[1];
214 double chi;
215 HklEngine *engine = params;
216 double chi0 = darray_item(engine->mode->parameters, 0)->_value;
218 CHECK_NAN(x->data, x->size);
220 chi = -2 * asin(sin(kappa/2.) * sin(50 * HKL_DEGTORAD));
222 RUBh_minus_Q(x->data, params, f->data);
223 f->data[3] = chi0 - chi;
225 return GSL_SUCCESS;
228 static const HklFunction constant_chi_f2 = {
229 .function = _constant_chi_f2,
230 .size = 4,
233 static HklMode *constant_chi(void)
235 static const char* axes[] = {KOMEGA, KAPPA, KPHI, TTH};
236 static const HklFunction *functions[] = {&constant_chi_f1, &constant_chi_f2};
237 static const HklModeAutoInfo info = {
238 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
239 functions, constant_chi_parameters),
242 return hkl_mode_auto_new(&info,
243 &hkl_mode_operations,
244 TRUE);
247 /* constant phi */
249 static int _constant_phi_f1(const gsl_vector *x, void *params, gsl_vector *f)
251 const double kappa = x->data[1];
252 const double kphi = x->data[2];
253 double phi;
254 HklEngine *engine = params;
255 double phi0 = darray_item(engine->mode->parameters, 0)->_value;
257 CHECK_NAN(x->data, x->size);
259 phi = kphi + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) + M_PI_2;
261 RUBh_minus_Q(x->data, params, f->data);
262 f->data[3] = phi0 - phi;
264 return GSL_SUCCESS;
267 static const HklFunction constant_phi_f1 = {
268 .function = _constant_phi_f1,
269 .size = 4,
272 static int _constant_phi_f2(const gsl_vector *x, void *params, gsl_vector *f)
274 const double kappa = x->data[1];
275 const double kphi = x->data[2];
276 double phi;
277 HklEngine *engine = params;
278 double phi0 = darray_item(engine->mode->parameters, 0)->_value;
280 CHECK_NAN(x->data, x->size);
282 phi = kphi + atan(tan(kappa/2.)*cos(50 * HKL_DEGTORAD)) - M_PI_2;
284 RUBh_minus_Q(x->data, params, f->data);
285 f->data[3] = phi0 - phi;
287 return GSL_SUCCESS;
290 static const HklFunction constant_phi_f2 = {
291 .function = _constant_phi_f2,
292 .size = 4,
295 static HklMode *constant_phi(void)
297 static const char* axes[] = {KOMEGA, KAPPA, KPHI, TTH};
298 static const HklFunction *functions[] = {&constant_phi_f1, &constant_phi_f2};
299 static const HklModeAutoInfo info = {
300 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
301 functions, constant_phi_parameters),
304 return hkl_mode_auto_new(&info,
305 &hkl_mode_operations,
306 TRUE);
309 static HklMode *double_diffraction(void)
311 static const char* axes[] = {KOMEGA, KAPPA, KPHI, TTH};
312 static const HklFunction *functions[] = {&double_diffraction_func};
313 static const HklModeAutoInfo info = {
314 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
315 functions, double_diffraction_parameters),
318 return hkl_mode_auto_new(&info,
319 &hkl_mode_operations,
320 TRUE);
323 static HklMode *psi_constant(void)
325 static const char* axes[] = {KOMEGA, KAPPA, KPHI, TTH};
326 static const HklFunction *functions[] = {&psi_constant_vertical_func};
327 static const HklModeAutoInfo info = {
328 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
329 functions, psi_constant_parameters),
332 return hkl_mode_auto_new(&info,
333 &psi_constant_vertical_mode_operations,
334 TRUE);
337 static HklEngine *hkl_engine_k4cv_hkl_new(HklEngineList *engines)
339 HklEngine *self;
340 HklMode *default_mode;
342 self = hkl_engine_hkl_new(engines);
344 default_mode = bissector();
345 hkl_engine_add_mode(self, default_mode);
346 hkl_engine_mode_set(self, default_mode);
348 hkl_engine_add_mode(self, constant_omega());
349 hkl_engine_add_mode(self, constant_chi());
350 hkl_engine_add_mode(self, constant_phi());
351 hkl_engine_add_mode(self, double_diffraction());
352 hkl_engine_add_mode(self, psi_constant());
354 return self;
357 /************/
358 /* psi mode */
359 /************/
361 /* psi */
362 static HklMode *psi()
364 static const char *axes[] = {KOMEGA, KAPPA, KPHI, TTH};
365 static const HklFunction *functions[] = {&psi_func};
366 static const HklModeAutoInfo info = {
367 HKL_MODE_AUTO_INFO_WITH_PARAMS(__func__, axes, axes,
368 functions, psi_parameters),
371 return hkl_mode_psi_new(&info);
374 static HklEngine *hkl_engine_k4cv_psi_new(HklEngineList *engines)
376 HklEngine *self;
377 HklMode *default_mode;
379 self = hkl_engine_psi_new(engines);
381 default_mode = psi();
382 hkl_engine_add_mode(self, default_mode);
383 hkl_engine_mode_set(self, default_mode);
385 return self;
388 /*****************/
389 /* mode readonly */
390 /*****************/
392 REGISTER_READONLY_INCIDENCE(hkl_engine_kappa4C_vertical_incidence_new,
393 P99_PROTECT({KOMEGA, KAPPA, KPHI}),
394 surface_parameters_y);
396 REGISTER_READONLY_EMERGENCE(hkl_engine_kappa4C_vertical_emergence_new,
397 P99_PROTECT({KOMEGA, KAPPA, KPHI, TTH}),
398 surface_parameters_y);
400 /********/
401 /* K4CV */
402 /********/
404 #define HKL_GEOMETRY_KAPPA4C_VERTICAL_DESCRIPTION \
405 "For this geometry there is a special parameters called :math:`\\alpha` which is the\n" \
406 "angle between the kappa rotation axis and the :math:`\\vec{y}` direction.\n" \
407 "\n" \
408 "+ xrays source fix allong the :math:`\\vec{x}` direction (1, 0, 0)\n" \
409 "+ 3 axes for the sample\n" \
410 "\n" \
411 " + **" KOMEGA "** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
412 " + **" KAPPA "** : rotating around the :math:`\\vec{x}` direction (0, :math:`-\\cos\\alpha`, :math:`-\\sin\\alpha`)\n" \
413 " + **" KPHI "** : rotating around the :math:`-\\vec{y}` direction (0, -1, 0)\n" \
414 "\n" \
415 "+ 1 axis for the detector\n" \
416 "\n" \
417 " + **" TTH "** : rotation around the :math:`-\\\vec{y}` direction (0, -1, 0)\n"
419 static const char* hkl_geometry_kappa4C_vertical_axes[] = {KOMEGA, KAPPA, KPHI, TTH};
421 static HklGeometry *hkl_geometry_new_kappa4C_vertical(const HklFactory *factory)
423 HklGeometry *self = hkl_geometry_new(factory);
424 double alpha = 50 * HKL_DEGTORAD;
425 HklHolder *h;
427 h = hkl_geometry_add_holder(self);
428 hkl_holder_add_rotation_axis(h, KOMEGA, 0, -1, 0);
429 hkl_holder_add_rotation_axis(h, KAPPA, 0, -cos(alpha), -sin(alpha));
430 hkl_holder_add_rotation_axis(h, KPHI, 0, -1, 0);
432 h = hkl_geometry_add_holder(self);
433 hkl_holder_add_rotation_axis(h, TTH, 0, -1, 0);
435 return self;
438 static HklEngineList *hkl_engine_list_new_kappa4C_vertical(const HklFactory *factory)
440 HklEngineList *self = hkl_engine_list_new();
442 self->geometries->multiply = hkl_geometry_list_multiply_k4c_real;
443 hkl_engine_k4cv_hkl_new(self);
444 hkl_engine_eulerians_new(self);
445 hkl_engine_k4cv_psi_new(self);
446 hkl_engine_q_new(self);
447 hkl_engine_kappa4C_vertical_incidence_new(self);
448 hkl_engine_kappa4C_vertical_emergence_new(self);
450 return self;
453 REGISTER_DIFFRACTOMETER(kappa4C_vertical, "K4CV", HKL_GEOMETRY_KAPPA4C_VERTICAL_DESCRIPTION);